Create New JavaScript Date Object With Different Timezone During Initialization [duplicate] - javascript

This question already has answers here:
How to initialize a JavaScript Date to a particular time zone
(20 answers)
Closed 9 years ago.
I have seen a lot, really a lot of post to find out a solution for my problem, but i couldn't get it, so decided to create a question.
My Question is how do we actually create a new javascript date object in different timezone, not in local timezone
i know we could create local date object and convert it to different timezone in number of ways, but i dont want to convert instead i need to create in specific timezone.
here is simple example for my problem,
Say, user has choosen a timezone "America/New_york", so all the dates in a calendar page will be shown in that timezone.
Now, if we create a event at "05:00 pm" , how do we actually create date with time 5 pm in "America/New_york" timezone,
if we use new Date() (assume browser is in different timezone say "Asia/Kolkata"), then converting it to "America/New_york" will not get "5:00pm" in that timezone , instead it will get corresponding time of "05:00 pm IST" in that timezone which will have different hour & minute value.
Any suggestion would be helpful!
Thanks

The short answer is you can't.
A Date object is just an accessor to the system time settings (so it will use the local computer timezone anyway). You can then manipulate your dates by substracting the local timezone using getTimezoneOffset(), or forcing a time with setUTCHours().
Note that moment.js is a good alternative to handle dates and timezones: http://momentjs.com/

Related

Moment.js retrieving a different date when using toDate() and format() [duplicate]

This question already has answers here:
Is the Javascript date object always one day off?
(29 answers)
Closed 2 years ago.
I need to get the current date in my TypeScript application. It is now 13:35 for me.
When using moment(Date.now()).toDate() I get the current date, but an hour too early than what I would expect:
"2020-03-26T12:35:12.938Z"
This gives me 12:35.
When using moment(Date.now()).format("DDMMYYYY_HHmm") I get the current date with the hour I am expecting: "26032020_1335"
This gives me 13:35.
What am I missing here to get the correct date and time?
To be clear, i need a Date object. Not a string.
When you call moment(Date.now()).toDate(), I presume you logged that date to the console. When a date is logged to the console, it displays as an ISO 8601 date, which uses UTC time. So, it is the correct time, just in a different timezone. If you call .toString on the date you should see the correct time for your timezone.

How to Convert datetime from one timezone to another timezone in Javascript? [duplicate]

This question already has answers here:
Convert date to another timezone in JavaScript
(34 answers)
How to initialize a JavaScript Date to a particular time zone
(20 answers)
Closed 3 years ago.
I need to convert from one timezone to another timezone in my project.
I am able to convert from my current timezone to another but not from a different timezone to another.
For example I am in India, and I am able to convert from India to US using Date d=new Date(); and assigning it to a calendar object and setting the time zone.
However, I cannot do this from different timezone to another timezone. For example, I am in India, but I am having trouble converting timezones from the US to the UK.
The easy and fast way is to use an external library. I recommend moment.js. once installed you can convert pretty easily and reliably through their ready-made functions

Is there a way to override `new Date()` in Javascript so it always returns the date considering one specific hardcoded timezone?

I'm working on a React.js project that handles lots of comparisons related to DateTime (comparing the hour, the month, the year and so forth to dates retrieved from an API). For this specific React.js application, I would like to always consider DateTimes (from new Date()) as if the user was in the server timezone. Assuming that the server is in "Europe/Berlin" timezone, I would like that at any point in the application, calling new Date('2019-01-01') would retrieve me a DateTime that refers to this time in the "Europe/Berlin" timezone, that would be Tue Jan 01 2019 01:00:00 GMT+0100 (Central European Standard Time). If I set my computer Date and Time as if I was in Brazil, for instance, I get Mon Dec 31 2018 22:00:00 GMT-0200 (Brasilia Summer Time), but would like to get the same as before. The main reason why this is a problem is that we extract data from these DateTimes such as .getHours(), .getDate(), etc.
This would fit this specific application because it's really important for this project that we only support the server Timezone, no matter where the user is. So to keep consistent with the server time, the call new Date('2019-01-01').getDate() should return 1, since it will be 1st January in Berlin. However, if the user is in Brazil, this same call will return 31, as Brazil is some hours before GMT, when it's midnight in GMT time, it will be still the previous day in Brazil.
I tried first to use the date-fns along with date-fns-timezone to set the DateTime to display the dates and times to the client considering the server timezone. That worked fine to display the right data but didn't solve some issues that are caused due to these attributes extraction from the date and that will vary depending on where the user is.
So that's why what I'm trying to do now is override the new Date() method in a way that it will always retrieve the date as if the user was in the server time. I haven't managed to get how it can be done. Whenever I change the Date and Time from my computer, the output for the new Date() already takes into account this new date and time settings.
So how can I force the new Date() to always give back the DateTime with a hardcoded timezone? Also, it would be really good if I could do it without using external libs (like moment.js, for instance), and do it only with plain Javascript.
I was taking a look into the window.navigator variable to see if I could set this one to force the Date to the server timezone, but it doesn't look like that will be the way to solve my issue.
I looked a lot for this answer and didn't find any question that was really close to this one. I'll just list here some of the questions I looked before and why my case differs from them.
1- new Date() for a specific timezone in JavaScript: In this case, the moment is used, and there was no way to accomplish this overriding for the new Date() itself.
2- Convert string to date without considering timezone: In this one, the answer gives back a string with the date formatted to the desired timezone, but not a Date object itself.
3- javascript date considering Request.UserLanguages[0]: also in this one, the question/answer is about formatting the date output rather than retrieving the Date object itself with the new timezone.
4- How do I combine moment.js timezone with toDate to build a new date object?: in this one the answer also is about using moment.js, what I would like to avoid since what I really want to achieve is overriding the new Date() method.
A few things:
Generally speaking, one should try to design their applications such that the server's time zone is not relevant at all. This means only relying on the server's UTC functionality, and working with specific named time zones. Asking for the local time of a server tends to become problematic, especially when dealing with environments where you may not have full control of the server.
Keep in mind that the Date object in JavaScript is misnamed. It is really a timestamp. Essentially it is just an object wrapper around the value you get with .valueOf() or .getTime() or when you coerce it to a number. Everything function on the Date object simply reads this value, applies some logic (which may or may not use the local time zone depending on the function), and emits some result. Similarly, the constructors of the Date object interpret your input and then assign this number in the resulting object. In other words, the Date object does not keep track of a time zone at all. It simply applies it when it is called for. Thus, one cannot change it.
When you pass a string in yyyy-MM-dd format to the Date constructor, per the ECMAScript specification it is interpreted as midnight UTC, not as midnight local time. This is a deviation from ISO 8601, and such often confuses people.
The strings you showed as output like Tue Jan 01 2019 01:00:00 GMT+0100 (Central European Standard Time) are emitted in local time, and are the result of either calling the .toString() function, or by passing a Date object to console.log in some environments. Other environments show the result of .toISOString(), which is emitted in UTC.
There's no global in window.navigator or elsewhere that can change the local time zone. In Node.js apps, if you really need to set the server's time zone globally, you can set the TZ environment variable before launching Node. However, this doesn't work in Windows environments, and doesn't help for browsers.
You're on track with using a library such as date-fns with date-fns-timezone. There are other libraries as well, which are listed in this answer. Alternatively, you could call .toLocaleString with the timeZone option, such as:
new Date().toLocaleString("en-US", {timeZone: "America/New_York"})
This API provides functionality for emitting a string in a particular time zone, but it does not do anything for applying a time zone to an input string.
So ultimately, to answer your question:
So how can I force the new Date() to always give back the DateTime with a hardcoded timezone?
Sorry, you can't. You can either use a different object to track the time zone statefully, or you can use functions that take the time zone as a parameter. Both are things offered by existing library, but only the one function I showed above is currently built in to JavaScript.
In case someone else has this same problem, here is the approach that I followed to solve the issue:
As in this specific case I really need to compare and group some entities based on date, among other operations (always considering the server timezone), I ended up choosing moment.js along with moment-timezone. The native Date class would not solve it since it has no way to handle different timezones. Then, I tried to use first date-fns and date-fsn-timezone, but as these libs always use the standard Date class, it gets back to the problem that a Date in javascript is only a timestamp and has no clue about other timezones other than the one in the client (the application is a React.js one).
Just to show one example about the issue, consider that the server is placed in Europe/Berlin timezone, and one stamp is retrieved as 2019-04-30T02:00:00+02:00. On the React.js application, I want to group this stamp to all the stamps that are also from 2019-04-30. However, if the browser is in Brazil/Brasilia time, the call new Date('2019-04-30T02:00:00+02:00').getDate() will give me 29 as return, since in the client timezone, this same timestamp will represent 2019-04-29T09:00:00-03:00.
Using moment and moment-timezone it could be fixed by defining in which timezone I want to retrieve the values, such as:
moment('2019-04-30T02:00:00+02:00').tz('Europe/Berlin').date()
// retrieves 30 independent on the client timezone.
Thank you very much to all who contributed with answers and suggestions. You all helped me to find the path to solve this issue.

The date 2019-04-01T00:00:00.000Z gives me previous month (March, not April)

So, I have the 1st day of month as 2019-04-01T00:00:00.000Z
When I use moment(date).month(), it returns me 2, not 3.
So, I receive March, not April.
What is the problem with it, and why I receive the previous month from the date? Maybe the problem in the TimeZone? Because my TimeZone is GMT-4, so, maybe this is problem?
Should I use UTC or ISO string instead to work with the date?
Like you mentioned, your timezone is GMT-4. The date that you are providing is in UTC. The 'Z' at the end stands for Zulu time, which is the same as UTC.
momentjs will convert this to local time.
How to handle this all depends on what you need the date for.
If this is a date that you saved somewhere before on a server, it might be important to add the correct timezone to it when you are saving it.
Be careful if you let a server create these dates, because the server might be running in a different timezone than your client.
If you create a new Date() in JS it will return a date object with the current time of your local time. If this happens on a server that's running in a different timezone, or in UTC (for example Docker containers), it will create a date in that timezone.
The best way to solve this is to think about your exact use case.
There are tons of articles written about handling dates and it's not easy.
If you have some time, this podcast helps to explain how dates work and will help you to get a better understanding of dates in general:
Coding Blocks - Why Date-ing Is Hard

How to convert date time saved in New York timezone to local time zone in javascript?

I am getting date time stored as string in New York timezone (GMT -4) format from third-party website. I want to convert it to local time zone using javascript. Date time is saved in following format
"2019-04-15 19:09:16"
I know i can achieve this through MomentJS but I want to know if there is any simple solution beside loading all library to convert date time to local timezone.
On Chrome expected output could be achieved by appending GMT-4 at the end of date and
new Date("2019-04-15 19:09:16 GMT-4")
But this solution doesn't work on Firefox because of invalid format.
If you actually know that the offset is UTC-4, then you simply need to reformat your string to be compliant with the ECMAScript Date Time String Format, which is a simplification of the ISO 8601 Extended Format.
new Date("2019-04-15T19:09:16-04:00")
However, note that New York is on US Eastern Time, which is actually in daylight saving time for the date and time you provided. In other words, it isn't UTC-4 (EST), but rather UTC-5 (EDT). So for that example, it should be:
new Date("2019-04-15T19:09:16-05:00")
But what if you don't know which offset it is for a given time zone on a particular date and time? After all, time zones, daylight saving time transitions, and associated offset are different all over the world, and have changed throughout history. So one cannot just assume a time zone has a single number that is its offset. (Read more under "Time Zone != Offset" in the timezone tag wiki.)
Presently, JavaScript cannot help you with that on its own. Instead, you'll need to use a library, such as the ones referenced here.
For example, using Luxon, you can do the following:
luxon.DateTime.fromISO("2019-04-15T19:09:16", { zone: "America/New_York" }).toJSDate()
In the future, we hope to solve this in the JavaScript language via Temporal objects - which are still in the ECMAScript proposal stage.

Categories

Resources