Date Conversion is different between Time Zones - javascript

I am trying to convert a date, but it shows differently on a set date between time zones.
new Date(1404100800000)
Mon Jun 30 2014 00:00:00 GMT-0400 (Eastern Daylight Time)
new Date(1404100800000)
Sun Jun 29 2014 21:00:00 GMT-0700 (Pacific Daylight Time)
Why does it do that? I must be not understanding something about dates.

This is expected. The timestamp number is measuring time independent of timezone. When converted to human readable format, it will change based on the timezone of the system. This is exactly as you'd expect, so that an event that occured at 6pm in New York will not also be an event at 6pm in San Fransisco ... but they will have the same timestamp.
From ECMA standard:
Time is measured in ECMAScript in milliseconds since 01 January, 1970
UTC. In time values leap seconds are ignored. It is assumed that there
are exactly 86,400,000 milliseconds per day.
http://www.ecma-international.org/ecma-262/5.1/#sec-15.9.1.1
Conversion to string is locale dependent:
This function returns a String value. The contents of the String are
implementation-dependent, but are intended to represent the Date in
the current time zone in a convenient, human-readable form.
http://www.ecma-international.org/ecma-262/5.1/#sec-15.9.5.2

Related

How to convert date from one timezone to another timezone

I have a date which is the beginning of a given day in the user's browser timezone but I need to convert it to the beginning of the day in another timezone, using date-fns.
I have a date:
const date = new Date("2020-10-13"); // Tue Oct 13 2020 00:00:00 GMT-0400 (Eastern Daylight Time)
And I need to convert it to the beginning of the day in the "America/Chicago" timezone.
const timeZone = "America/Chicago";
// Need to convert a date object
// Tue Oct 13 2020 00:00:00 GMT-0400 (Eastern Daylight Time)
// to
// Tue Oct 13 2020 00:00:00 GMT-0500 (Central Daylight Time)
// and all I'm given is the timeZone value.
To get time zone support for date-fns, you will need the date-fns-tz add-on module.
Then you can do the following:
import { zonedTimeToUtc } from 'date-fns-tz';
const dt = zonedTimeToUtc('2020-10-13', 'America/Chicago');
The result will be a Date object that represents midnight in the given time zone.
Keep in mind that Date objects themselves are always UTC-based. Thus, you can't get a Date object that is "in" a different time zone.
Also, you should pass a string into the zonedTimeToUtc function as shown. You should not pass it to the Date object. As mentioned in comments, the ECMAScript spec says that a date-only string value should be parsed as UTC. However, there are still some implementations that don't follow the spec correctly. Thus, you should avoid parsing strings using the Date object constructor.

new Date() not working as expected when exact daylight switch happens

I have a scenario where I have to pass "year,month,date,time" to Date() function and get the datetime type.
Using chrome.
Windows has been configured with EST timezone(-05:00).
DST starts On March 8th 2020 2AM(EDT -04:00)
If i pass date time as Date(2020,02,08,01) it returns as "Sun Mar 08 2020 01:00:00 GMT-0500 (Eastern Standard Time)".
But when I pass date time for 2AM(exactly where dst switches) it returns as "Sun Mar 08 2020 03:00:00 GMT-0400 (Eastern Daylight Time)".
It returning Time as "03" istead of "02".
Can anyone let me know why the Date function not working as I expect for the particular time and how to fix this issue?
We have DST on the 29th of March - works as expected in GMT-1/GMT-2
console.log(new Date(2020,2,29,0,0,0,0)); // in CEST I get "2020-03-28T23:00:00.000Z"
console.log(new Date(2020,2,29,1,0,0,0)) // in CEST I get "2020-03-29T00:00:00.000Z"
console.log(new Date(2020,2,29,2,0,0,0)) // in CEST I get "2020-03-29T01:00:00.000Z"
console.log(new Date(2020,2,29,3,0,0,0)) // in CEDT I get "2020-03-29T01:00:00.000Z" !!!
console.log(new Date(2020,2,29,4,0,0,0)) // in CEDT I get "2020-03-29T02:00:00.000Z"
Perhaps you want UTC
console.log(new Date(Date.UTC(2020,2,29,0,0,0,0))); // in CET I get "2020-03-29T00:00:00.000Z"
console.log(new Date(Date.UTC(2020,2,29,1,0,0,0))); // in CET I get "2020-03-29T01:00:00.000Z"
console.log(new Date(Date.UTC(2020,2,29,2,0,0,0))); // in CET I get "2020-03-29T02:00:00.000Z"
console.log(new Date(Date.UTC(2020,2,29,3,0,0,0))); // in CET I get "2020-03-29T03:00:00.000Z"
console.log(new Date(Date.UTC(2020,2,29,4,0,0,0))); // in CET I get "2020-03-29T04:00:00.000Z"
Or in your case - UTC on the 8th:
console.log(new Date(Date.UTC(2020,2,8,0,0,0,0))); // in CET I get "2020-03-08T00:00:00.000Z"
console.log(new Date(Date.UTC(2020,2,8,1,0,0,0))); // in CET I get "2020-03-08T01:00:00.000Z"
console.log(new Date(Date.UTC(2020,2,8,2,0,0,0))); // in CET I get "2020-03-08T02:00:00.000Z"
console.log(new Date(Date.UTC(2020,2,8,3,0,0,0))); // in CET I get "2020-03-08T03:00:00.000Z"
console.log(new Date(Date.UTC(2020,2,8,4,0,0,0))); // in CET I get "2020-03-08T04:00:00.000Z"
The result is correct.
Date(2020,02,08,01,59,00) returns Sun Mar 08 2020 01:59:00 GMT-0500
Date(2020,02,08,02,00,00) returns Sun Mar 08 2020 03:00:00 GMT-0400
In Spring, clocks skip forward by an hour. Notice how the offset to GMT is decreased by one hour? That's daylight savings time on the East Coast.
There IS no 2AM (GMT-05) on March 8, at least not in the Eastern timezone. One second after 01:59:59 GMT-05:00 the clock jumps to 03:00:00 GMT -04:00. The jump is reflected in the GMT, which really is an offset to GMT.
What is going under the hood is the following: When you create a new Date, Javascript parses it and internally stores the exact time in ticks after 1/1/1970 GMT00:00 (the epoch, in Greenwich mean time). When you now try to get information like year, month, day, hour from this internal value, Javascript applies your local timezone to determine what local time it should return. So when you create your date object from Date(2020,02,08,02,00,00), JS assumes that this is still Standard (winter) time because there is no 2am in Daylight Savings time. The value in ticks is the same as 03:00:00 GMT-00:40, and when you then print or otherwise access the hour value of this date, Javascript localizes it to your timezone. But again, the two times 02:00:00 GMT-05:00 and 03:00:00 GMT-04:00 are identical, only expressed in different timezones/daylight savings periods.
Please note that your date/time parsing logic will run into problems in Fall as the hour between 1 and 2 is "executed" twice. Per TimeAndDate, on 11/1 at 2am the clock will be set back to 1am. So
Date(2020, 10, 01, 01, 30, 00)
cannot determine whether it is still EDT or already EST. You need to pass in the current time zone/offset to UTC.

Why does passing an argument to new Date() result in a different timezone than not passing any argument?

When using new Date(0) (or any other argument) I get a date in GMT+1
When using new Date() I get a date in GMT+2
Why?
It is likely because your locale settings use a time zone that observes daylight savings (or some similar annual time adjustment).
For example, in the Central Time Zone, today is October 19, 2018 and new Date() returns (at the moment):
Fri Oct 19 2018 15:16:16 GMT-0500 (Central Daylight Time)
But new Date(0), in the Central Time Zone, returns:
Wed Dec 31 1969 18:00:00 GMT-0600 (Central Standard Time)
Note that both the offset and time zones are different because December 31, 1969 was during the part of the year that the Central Time Zone observes Central Standard Time while October 19, 2018 is during the part of the year when the Central Time Zone observes Central Daylight Time.
IMPORTANT NOTE:
As pointed out in the comment from #Bergi, Date objects do not contain any timezone information. From the JavaScript Date docs:
Date objects are based on a time value that is the number of
milliseconds since 1 January 1970 UTC.
When a date is represented as a string, i.e. console.log(new Date()), the toString() method is automatically called and applies an implementation dependent string format to the date that includes a timezone offset and sometimes a timezone name.

Why does js subtract a day from a Date object with a certain format?

I get dates from the database in this format:
yyyy-mm-dd
When I create a javascript Date object using this string, it builds a day before the date.
You can test this in your console:
var d = new Date("2015-02-01");
d
You will get January 31st! I've tested many theories, but none answer the question.
The day is not zero-based, otherwise it would give Feb 00, not Jan 31
It's not performing a math equation, subtracting the day from the month and/or year
Date(2015-02-01) = Wed Dec 31 1969
Date("2015-01") = Wed Dec 31 2014
It is not confusing the day for the month
Date("2015-08-02") = Sat Aug 01 2015
If this were true the date would be Feb 08 2015
If you create a Date using a different format, it works fine
Date("02/01/2015") = Feb 1st, 2015
My conclusion is that js does this purposefully. I have tried researching 'why' but can't find an explanation. Why does js build dates this way, but only with this format? Is there a way around it, or do I have to build the Date, then set it to the next day?
PS: "How to change the format of the date from the db" is not what I'm asking, and that is why I'm not putting any db info here.
Some browsers parse a partial date string as UTC and some as a local time,
so when you read it the localized time may differ from one browser to another
by the time zone offset.
You can force the Date to be UTC and add the local offset if you
want the time to be guaranteed local:
1. set UTC time:
var D= new Date("2015-02-01"+'T00:00:00Z');
2. adjust for local:
D.setMinutes(D.getMinutes()+D.getTimezoneOffset());
value of D: (local Date)
Sun Feb 01 2015 00:00:00 GMT-0500 (Eastern Standard Time)
Offset will be whatever is local time.
Some differences between browsers when time zone is not specified in a parsed string:
(tested on Eastern Standard Time location)
(new Date("2015-02-01T00:00:00")).toUTCString();
Firefox 35: Sun, 01 Feb 2015 05:00:00 GMT
Chrome 40: Sun, 01 Feb 2015 00:00:00 GMT
Opera 27: Sun, 01 Feb 2015 00:00:00 GMT
IE 11: Sun, 01 Feb 2015 05:00:00 GMT
IE and Firefox set the Date as if it was local, Chrome and Opera as if it was UTC.
In javascript, Date objects are internally represented as the number of milliseconds since Jan 1st 1970 00:00:00 UTC. So instead of thinking of it as a "date" in the normal sense, try thinking of a Date object as a "point in time" represented by an integer number (without timezone).
When constructing your Date object using a string, you are actually just calling the parse function. Most date time formats (including ISO 8601) allow you to reduce the precision of a date string.
For reduced precision, any number of values may be dropped from any
of the date and time representations, but in the order from the least
to the most significant.
e.g. 2015-02-01 would represent the day February 1st 2015.
This causes a dilemma for javascript because a Date object is always accurate to the millisecond. Javascript cannot store a reduced accuracy date since it is just an integer of milliseconds since 1st Jan 1970. So it does the next best thing which is to assume a time of midnight (00:00:00) if not specified, and a timezone of UTC if not specified.
All valid javascript implementations should give the same result for this:
var d = new Date("2015-02-01");
alert(d.getTime());
1422748800000
The out-by-1-day issue comes when outputting the date either to some (often unclear) debugger or using the getter methods because the local timezone is used. In a browser, that will be your operating systems timezone. Anyone "west" of Greenwich Mean Time may see this problem because they have a negative UTC offset. Please note there are UTC equivalent functions too which use the UTC timezone, if you are really just interested in representing a date rather than a point in time.

Javascript date formatting - one hour out due to daylight saving

So now, its 9:23am. I have a UTC date string that represents the current date, that looks like this "2012-07-17T09:23:27.75"
I want that in a date object, so I can display a nicely formatted date, so I:
var myDate = new Date("2012-07-17T09:23:27.75")
// Gives --> Tue Jul 17 2012 10:23:27 GMT+0100 (GMT Daylight Time)
So because of daylight saving time I'm getting an hour-out issue. I can see that myDate.getTimezoneOffset() gives me -60, what's the standard / best practice way to get my date to actually reflect the current correct time? Have I just entered javascript date hell?
Try momentjs.com. I really found it handy for such things.
var myDate = moment("2012-07-17T09:23:27.75");
Gives you a date instance in your timezone (that basically configured on your computer). Moreover momentjs has nice human friendly formattings like "a couple of seconds ago", "a month ago",...
Dates are really a hell in JS (but not only in JS). The best thing you can do is to always only transport in UTC between browser <-> server. Then on the server convert it to what time format you like, you obviously only have to be consistent. That way I managed to handle date-times properly.
Try removing the 'T'
I was debugging some date time format issue in chrome when I found out that in console
new Date('2016-04-16T15:15:00') returns Sat Apr 16 2016 16:15:00 GMT+0100 (GMT Daylight Time)
while
new Date('2016-04-16 15:15:00') returns Sat Apr 16 2016 15:15:00 GMT+0100 (GMT Daylight Time)

Categories

Resources