How to solve problem of timezone in Node js and mongodb? - javascript

I'm trying to insert start and end time like entry and exit time logic into Mongodb from node js.
My local system's timezone is IST. +5:30 offset for both client and sever.
So now follow this example.
entryDate: 15-10-2018,
start: 15-10-2018 01:00:00,
end: 15-10-2018 05:00:00
Now since i'm on same timezone on client and server, it won't change my date value and create new object.
Then i'm storing this data into MongoDB. As you know that mongo db will convert date to UTC and then stores it. So in my DB it will look like this.
entryDate: ISODate("2018-10-15T00:00:00Z"),
start: ISODate("2018-10-14T19:30:26Z"),
end: ISODate("2018-10-14T23:30:26Z")
So now if I want to search a query that should give me records for dates and time between 15 to 16 let's say then i won't get any data.
Now consider this case. I moved app on to the server. Now servers timezone is in UTC. So every date I pass will be converted directly in UTC so it'll insert same data like before.
Now difference here is when i want to search date range in IST timezone then it will give me the exact date to search like (15-10-2018 00:00:00) to (16-10-2018 00:00:00).
Where on server it will convert this date to UTC and can give me one day less or may be higer time like (14-10-2018 18:30:00) to (15-10-2018 18:30:00). So from the start my query is wrong.
So how to solve this issue? Thank you.

After doing some research. I have a solution.
Get your date on the client side.
Convert that date to UTC date and pass date string to the server. Like 01-01-2018 10:00:00. (Note: we are just converting date, not the timezone)
On the server side create a date object from the provided date that will convert the date to UTC by default with that same time.
Store the date on the server side with MongoDB. Since the date is in UTC it won't convert the date again and store it as it is.
Now from the server, you will get the date in UTC format which will be like '2018-01-01 10:00:00'.
Now on the client side, create a date object from this date. This will convert your date to actual date that you passed.
This solved my problem.

Related

How to handle BST and GMT timezones on client side? Storing them in a DB as UTC

I've got a Go app and I store all datetimes as UTC:
dateTime, err := time.Parse("2006-01-02T15:04:05.000Z", myDateTime)
This becomes something like: 2022-09-29T19:40:36.150Z.
Now I want to show this datetime client side (on a website), but showing the user the time in their timezone.
Since it's all UTC I could have the user pick their timezone from a list, like this one https://gist.github.com/valo/c07f8db33d223f57a4cc9c670e1b6050.
Then it's just a matter of adding/subtracting some time from the UTC and showing it.
But the problem is with daylight savings time, the client side timezone would have to change when it's summer, and change again when it's winter.
How are people doing this?
Usually, this happens on the client side. Information about the client's timezone is stored on the browser and is available to you if you need it. However, there are functions that sort this out automatically like toLocaleDateString.
Step 1.
Parse the time string 2022-09-29T19:40:36.150Z to a Date object in javascript
Step 2.
Use toLocaleDateString on the date. This will display the Date in the client's timezone setting stored in the browser
MDN docs for toLocaleDateString()

How to convert a Date in specific Timezone and send to server

My scenario is a Date object created using the browser timezone (just using new Date()) and sent to the server, but I want to send this date with another specific timezone let's assume it's, Europe/Athens.
What would be the best representation of the actual date string so I can convert it back to a Date object in the backend in the actual Europe/Athens date?
I have the timezone info but not sure how to get a Fri Feb 05 2021 05:30:00 GMT-0500 (Eastern Standard Time) and convert it to Europe/Athens date.
I have tried to use date-fns but didn't get far.
You've got a few different questions and misconceptions, so I will attempt to address each of them, starting with question in the title:
How to convert a Date in specific Timezone and send to server
If you mean a date like 2021-01-18, that cannot be in a particular time zone. It is, by definition, just a date. Think about a printed calendar you might hang on your wall that has a square for each date. There are no time zones associated with such calendars. One can ask "what date is it now in a particular time zone", but the answer itself has no time zone.
If instead you meant a JavaScript Date object, the answer is again "you can't". The Date object is not actually a date, nor does it have a time zone, but rather it is a timestamp. Internally, a Date object only holds one value - the number of milliseconds that have elapsed since 1970-01-01 00:00:00.000 UTC (not considering leap seconds). It has no time zone. Instead, some functions such as .toString() will apply the system-local time zone while operating. That time zone comes from the operating system (in most cases). It is not stored inside the Date object itself.
My scenario is a Date object created using the browser timezone (just using new Date()) ...
That will use the system clock where the browser is running, but the time zone is not relevant. The Date object will be constructed from the Unix timestamp that represents "now". Such timestamps are inherently UTC based. The browser fetches the UTC time directly from the operating system, without considering time zone.
... and sent to the server
One cannot send an object to a server without going through deserialization on one side and serialization on the other.
... but I want to send this date with another specific timezone let's assume it's, Europe/Athens.
What would be the best representation of the actual date string so I can convert it back to a Date object in the backend in the actual Europe/Athens date?
Since the object only represents "now", you don't need to send it in a time zone specific format. Just send the UTC time. The ideal format is ISO 8601, which can be obtained directly using the .toISOString() function from the Date object.
Depending on your use case, you might also consider whether you might instead just take the UTC time from the server instead. At least you will have some control over the clock.
On the server side, if you need the time in a specific time zone, then convert from UTC to that time zone on the server, not on the client.
Also, from comments:
I believe even EPOCH is different between timezones. I could just get the EPOCh and then try to work with converting to specific timezones.
That is incorrect on a few levels. First, understand that epoch is just an English word meaning essentially "a representation of a starting point". It isn't a format, nor is it an acronym. In JavaScript, Date objects use Unix timestamps, which use an epoch of 1970-01-01T00:00:00.000Z. In other words, Midnight Jan 1st 1970 UTC is the 0 timestamp. Sometimes, such timestamps are referred to as "epoch time". That's a misnomer in my opinion, but even still - they are always UTC based. There is no time zone, and thus they are the same for the whole world.
Try to use toLocaleString:
let date = (new Date()).toLocaleString("en-US", {timeZone: "Europe/Athens"});

How to convert UTC date of specific timezone to UTC +0 (default Greenwich)?

I want to insert an item to the DB in a specific date based on the client's timezone. So if client desired in today on 20:00, and his timezone is +3, I want that node and mongodb will set the date to be on today on 17:00. I hope that is clear enough.
Generally it is recommended to save all timestamps in database in UTC only, along with it you can save extra field timezone/offset value in each document. Check -
https://docs.mongodb.com/manual/tutorial/model-time-data/
But if you want to save in local timezone, you need to do conversion at application level before inserting in database.

Dealing with js localized date in C#

My app (back-end in C# & front-end in Angular Materials) has a search screen allowing user to specify the date period using datepickers. The problem is that some of the users are not in UK while all the data they view has been created with GMT date. So if someone in Germany selects date 01/01/2017 in datepicker, my back-end reads it as 31/12/2016 23:00:00 resulting in incorrect search results.
Can someone advise me how to deal with this? I'd like to still use the Angular Material datepicker but be sure that I'm passing the date selected by the user. I know I can transform the date before posting it like this:
moment(myDate).format('MM/DD/YYYY'))
but I have a lot of cases like this and would prefer some generic solution.
For transmission and storage, I advise using UTC for everything. Only at the point of display should the time be converted to whatever locale the user has selected. Despite this being an old problem, running into time conversion issues is still quite common. Most places I've worked at will store everything as UTC timestamps or Unix epoch time with respect to UTC, that way there is no question what the meaning is anywhere in the system. If/when it needs to be rendered to something local, we do it on the client side.
For example, to get the local time converted to UTC as a string:
var noTimeZone = new Date().toUTCString();
-or-
var noTimeZone = new Date().toISOString();
Or, if you want a numeric value so you don't have to deal with funky format parsing between client/server, you can get the Unix epoch:
var unixEpochMS = new Date().getTime();
Mind you, Date.getTime() will return milliseconds rather than seconds. Also note that the Unix epoch is defined in terms of UTC. That is, any numeric value that is a timestamp is expected to be UTC. If you want a different timezone, you need to parse the value and then set the timezone to what you want.
Solution 1:
I think the solution is to get your user's timezone. You can use Javascript to get timezone from user's computer and send it to server with the request.
var d = new Date();
var tz = d.getTimezoneOffset()/-60;
tz will be 2 if user's timezone is GM+2
Soution 2:
You send and receive Unix timestamp. But then you need to convert the timestamp to readable date/time based on user's timezone.

Javascript handle daylight savings time for different time zones

Here I got an input box on my web page for users to input a date. For some reason I can't use a datetime picker and I have to pass it to an .NET based service as a String via ajax.
Users may from different time zones. And the date is stored as UTC in database.
It seems I have 2 options to handle the timezone:
Convert the date string to UTC date string at frontend and pass to service.
Pass the UTC offset to service and convert the date string to UTC at backend.
However, neither option can handle the daylight savings time.
Could anyone give me some suggestions on this?
Javascript's toUTCString() and functions like getUTCDate() instead of getDate() will ignore the timezone offset, including I presume the DST offsets.

Categories