简体   繁体   中英

Timezone problems with MongoDB and NodeJs

So the problem I'm currently having is :

I've a list of gym classes, which every class has an OpeningTime. I want to fetch all the classes from the current day, but. I'm not getting the same result locally and in production, cause for some reason, when Im deploying my backend to Heroku, the timezone is being setted by default to UTC (when I've a GMT-3 timezone).

Here is my query :

 var now = moment();

 var startOfDay = now.startOf('day').format();

 var endOfDay = now.endOf('day').format();

 var clasesDB = await Clase.find({ $and: [{ openingTime: { $gte: startOfDay } }, { openingTime: { $lte: endOfDay } }] })

So, like I said before, the problem is ocurring when, for example:

When I fetch the classes at my local time (Ex: 02-26-19 21:00hs ( GMT-3) ), the queries are actually showing the classes from 02-27 , because, at MINE 21:00hs, on the server side is already 00:00, so, the date is not 02-26 anymore. And I dont want this kind of output.

How can I get a workaround to solve this?

Thanks in advance! :)

By default in MongoDB a date field is stored in UTC , You can create a date with offset while writing to store it in your timeZone. But you've not done it while writing documents then you need to convert date field to your required timeZone while reading data from database. Check this below example.

JavaScript Code :

const today = new Date().toLocaleDateString(undefined, {
    day: '2-digit',
    month: '2-digit',
    year: 'numeric'
})  // 02/26/2020. If your Heroic server is in different location then specify your locale in place of undefined - whereas undefined picks local time by default. Ex:- 'en-Us' for USA

Query :

db.collection.aggregate([
    { $addFields: { timewithOffsetNY: { $dateToString: { format: "%m/%d/%Y", date: "$openingTime", timezone: "America/New_York" } } } },
    { $match: { timewithOffsetNY: today } }, { $project: { timewithOffsetNY: 0 } }
])

Above query is written for New York timeZone, you can convert it according to your timeZone, In test url you can see 1st doc is not returned though it is on 2020-02-26 cause offset to New York as of today is 5hrs, So after converting date becomes as 2020-02-25 .

Test : MongoDB-Playground

Ref : $dateToString

Don't use .format() , this makes a string . Compare directly Date values, ie use

var now = moment();

var startOfDay = now.startOf('day').toDate();    
var endOfDay = now.endOf('day').toDate();

By default moment uses local times, so moment().startOf('day') returns midnight of local time. If you want to get midnight of UTC then use moment.utc().startOf('day') .

If you don't rely on "local" time zone, then you can specify it like moment.tz("America/New_York").startOf('day')

No matter which time you need, never compare Date values by string, use always actual Date value.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM