Why So Many IANA Time Zones Names? - javascript

Javascript allows you to see what time it is in another timezone if you specify the IANA given name of that timezone. For example:
let strTime = new Date().toLocaleString("en-US", {timeZone: "America/Chicago"});
console.log(strTime);
Below you can see that IANA provides multiple names within each general timezone:
America/New_York Eastern (most areas)
America/Detroit Eastern - MI (most areas)
America/Kentucky/Louisville Eastern - KY (Louisville area)
America/Kentucky/Monticello Eastern - KY (Wayne)
America/Indiana/Indianapolis Eastern - IN (most areas)
America/Indiana/Vincennes Eastern - IN (Da, Du, K, Mn)
America/Indiana/Winamac Eastern - IN (Pulaski)
America/Indiana/Marengo Eastern - IN (Crawford)
America/Indiana/Petersburg Eastern - IN (Pike)
America/Indiana/Vevay Eastern - IN (Switzerland)
America/Chicago Central (most areas)
America/Indiana/Tell_City Central - IN (Perry)
America/Indiana/Knox Central - IN (Starke)
America/Menominee Central - MI (Wisconsin border)
America/North_Dakota/Center Central - ND (Oliver)
America/North_Dakota/New_Salem Central - ND (Morton rural)
America/North_Dakota/Beulah Central - ND (Mercer)
America/Denver Mountain (most areas)
America/Boise Mountain - ID (south); OR (east)
America/Phoenix MST - Arizona (except Navajo)
America/Los_Angeles Pacific
America/Anchorage Alaska (most areas)
America/Juneau Alaska - Juneau area
America/Sitka Alaska - Sitka area
America/Metlakatla Alaska - Annette Island
America/Yakutat Alaska - Yakutat
America/Nome Alaska (west)
America/Adak Aleutian Islands
Pacific/Honolulu Hawaii
Why is that necessary?
For example, both America/Detroit and America/New_York are (generally) in the Eastern Time Zone. Why don't these two locations share a single IANA timezone name?
Are there occations of the year where the time in New York is different from that of Detroit?
If not, then why allow more timezone names than the exact number of variances?

I'll use your example:
For example, both America/Detroit and America/New_York are in the Eastern Time Zone. Why don't these two locations share a single timezone name?
In the TZDB, the Zone entry for America/New_York looks like this:
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone America/New_York -4:56:02 - LMT 1883 Nov 18 12:03:58
-5:00 US E%sT 1920
-5:00 NYC E%sT 1942
-5:00 US E%sT 1946
-5:00 NYC E%sT 1967
-5:00 US E%sT
While the Zone entry for America/Detroit looks like this:
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone America/Detroit -5:32:11 - LMT 1905
-6:00 - CST 1915 May 15 2:00
-5:00 - EST 1942
-5:00 US E%sT 1946
-5:00 Detroit E%sT 1973
-5:00 US E%sT 1975
-5:00 - EST 1975 Apr 27 2:00
-5:00 US E%sT
To fully decipher this, one also needs the Rule entries for US, NYC, and Detroit (which I won't copy/paste here, but you can follow the links).
As you can see, Detroit has had variations from New York, the last of which was in 1975 when Detroit started daylight saving time slightly later than most of the Eastern time zone (Apr 27 shown here vs Feb 23rd given by Rule US).
Since then however, they have been the same. The TZDB rules require a unique zone for areas that have agreed since 1970, and these areas have deviations in 1973 and 1975, thus they require unique zone identifiers.
One can see this difference in JavaScript like so:
var d = new Date("1975-03-01T00:00:00.000Z"); // Midnight UTC on March 1st
d.toLocaleString("en-US", {timeZone: "America/New_York"}) //=> "2/28/1975, 8:00:00 PM"
d.toLocaleString("en-US", {timeZone: "America/Detroit"}) //=> "2/28/1975, 7:00:00 PM"
Of course, if in your application, you never deal with dates going back that far, then you can just use America/New_York to represent the US Eastern time zone, and omit America/Detroit (and a few others) - but this is entirely your decision to make.
You may also be interested in reading the Theory file with in the tzdb itself, which explains the concepts and principles of the time zone database in a lot more detail.

Related

Store date as if they were entered in a specific timezone

I am using Moment. I need users to enter a date, and make sure that that's always the time for Australia/Perth, regardless of what the browser is set as.
For example, assume the computer is set as Sydney time (which right now is +3 but in winter it's +2). I want the user to enter a date/time, and make sure that that date/time is stored as Perth's time.
Note that visualising the correct date isn't an issue (with moment.tz). What I am worried about, is the date object creation which would need to happen providing a time, and forcing the browser to pretend that they are in that timezone.
I need this to work regardless of daylight savings etc.
UPDATE: this is what I want to achieve:
// MY CURRENT TIMEZONE IS SYDNEY, CURRENTLY PERTH + 3 BUT +2 IN SUMMER
// IN PERTH IT's 10:11AM, and *THAT* is the time I am interested in
// storing, not 13:11:58
var d = new Date()
// => Wed Nov 28 2018 13:11:58 GMT+1100 (Australian Eastern Daylight Time)
// NOTE: the date 13:11:58 SYDNEY time. I don't want this.
// I MUST pretend that users entered the date with their timezone
// is in Perth
// So...
// Create a date string that exclude original timezone and includes new timezone
perthDateString = moment(new Date()).format('YYYY-MM-DDTHH:MM:ss') + '+0800'
// => "2018-11-28T13:11:58+0800"
// Make a new date object using the tinkered date string
var newD = new Date(perthDateString)
// Display the date. Note: the time is "wrong" (since it displays
// a time that is 3 hours ahead), but it's actually the correct
// answer since 'd' is meant to be Perth time in the first place
newD
// => Wed Nov 28 2018 16:11:58 GMT+1100 (Australian Eastern Daylight Time)
// Display the date as the Perth time
moment.tz(newD, 'Australia/Perth').toString()
// => "Wed Nov 28 2018 13:11:58 GMT+0800"
However:
in perthDateString = moment(new Date()).format('YYYY-MM-DDTHH:MM:ss') + '+0800', I would like to specify Australia/Perth, rather than '+0800'
I feel uneasy with dealing with dates by chopping/concatenating strings
I wonder if EVERY browser will be able to parse the date returned by .format('YYYY-MM-DDTHH:MM:ss') + '+0800' or if I am going to have surprises -- especially when/if I have a solution so that I use Australia/Perth instead
If you are anywhere in the world (say, Sydney or Tokyo), and the local time is "12:30", but you want to store the same time-of-day ("12:30") as if you were in Perth -- you can use the moment-timezone package together with moment.
For example, this snippet will give you a moment for "12:30" in Perth:
let x = moment.tz('2019-01-01T12:30:00', 'Australia/Perth')
console.log(x.format()); // Show that it is 12:30 in Perth time
console.log(new Date(x)); // Generate Date for that time
<script src="https://momentjs.com/downloads/moment.js"></script>
<script src="http://momentjs.com/downloads/moment-timezone-with-data.js"></script>

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.

momentjs toDate - different output on different clients/browsers

I use momentjs to parse a Date String and convert it to a native JavaScript Date:
let dateString = '1980-04-06';
console.log(moment().utcOffset());
console.log(moment(dateString, 'YYYY-MM-DD').toDate());
<script src="https://cdn.jsdelivr.net/npm/moment#2.22.2/moment.min.js"></script>
The output on client 1(Firefox 62) is
120
Date 1980 - 04 - 05 T23: 00: 00.000 Z
and the output on client 2(Firefox 52 ESR) is
120
Date 1980 - 04 - 05 T22: 00: 00.000 Z
Can somebody explain me, why the utcOffset is the same (new Date().getTimezoneOffset() prints also -120 on both clients), but the Date (hour) is different?
You're checking the current UTC offset, not the offset of your 1980 moment instance. My guess is that if you took moment(dateString, 'YYYY-MM-DD') and called utcOffset on that, you'd get different offsets on the different browsers.
I bet what's happening is that the rules for your zone have changed since 1980 (for example, perhaps the timing of the DST has changed, or DST has been added or eliminated, or perhaps the standard offset has even changed). Browsers vary in the degree to which they get historical zone data right, which leads to errors interpreting date strings. I suspect that Firefox fixed their historical zone database for your zone, leading to different behavior in newer versions of the browser.
The offsets you're showing are for the current date and time, not for the date provided. If you change the middle line to log moment(dateString, 'YYYY-MM-DD').utcOffset(), you should see that the result in the older Firefox 52 is 60 instead of 120.
Contributing factors explaining this difference are:
The daylight saving time rules for your time zone are not the same in 1980 as they are today. Assuming Vienna (from your user profile), in 1980 the start of DST was at 00:00 on April 6th (reference here) which is the first Sunday in April. The current (2018) rule for Vienna is the last Sunday in March, which would be March 25th 2018 (reference here).
ECMAScript 5.1 (section 15.9.1.8) and earlier required browsers to always assume the current DST rule was in effect for all time - even if this was not actually what happened. This was corrected in ECMAScript 6 / 2015 (section 20.3.1.8) .
ECMAScript 2015 was implemented in Firefox starting with version 54. Since you are testing version 52, you are seeing the old behavior.
Since this particular DST change is right at the stroke of midnight, and it's a spring-forward transition, then, 1980-04-06T00:00 is not valid. The first moment of that day in that time zone is 1980-04-06T01:00. Moment takes care of this for you when you pass a date-only value. In the current browser (62, not 52), If you call .format() on the moment, you should see 1980-04-06T01:00:00+02:00. Note that this is time is already in DST, with a UTC+02:00 offset. Converted to UTC is 1980-04-05T23:00:00Z, thus aligning with the correct data as seen in your examples.
Long story short, there are many reasons to use up-to-date browsers. This is one of them.

Office 365 REST API: Correct for daylight savings time

The Office 365 REST API returns local dates and times with time zones. As the documentation explains, time zones are specified by strings from this standard Windows list of zones. Here's an example of a date/time value returned by the API, in JSON:
{ DateTime: '2016-04-13T08:00:00.0000000',
TimeZone: 'Pacific Standard Time' }
Let's say you want to use this date---for example, to parse it to a JavaScript Date object. You might think that, to parse this date, you'd just need to look up that time zone name in a table to get its offset.
But that's not quite right! Because that date is in April, it's actually specified in daylight time: the appointment it reflects is at 8 AM PDT, not PST, despite all appearances. The date contains no indication of daylight savings time, and "Pacific Daylight Time" isn't even a valid time zone according to that list.
Does the API provide any facilities for getting the real, daylight-sensitive time zone offset for one of these values? Or am I on my own to compensate for DST in my JavaScript client?
Pacific Daylight Time / Pacific Daylight Saving Time are not Time zone (time zone is geography based). The TimeZone property in Office 365 REST API can be set to any of the time zones supported by Windows, as well as the following time zones names.
Etc/GMT+12
Etc/GMT+11
Pacific/Honolulu
America/Anchorage
America/Santa_Isabel
America/Los_Angeles
America/Phoenix
America/Chihuahua
America/Denver
America/Guatemala
America/Chicago
America/Mexico_City
America/Regina
America/Bogota
America/New_York
America/Indiana/Indianapolis
America/Caracas
America/Asuncion
America/Halifax
America/Cuiaba
America/La_Paz
America/Santiago
America/St_Johns
America/Sao_Paulo
America/Argentina/Buenos_Aires
America/Cayenne
America/Godthab
America/Montevideo
America/Bahia
Etc/GMT+2
Atlantic/Azores
Atlantic/Cape_Verde
Africa/Casablanca
Etc/GMT
Europe/London
Atlantic/Reykjavik
Europe/Berlin
Europe/Budapest
Europe/Paris
Europe/Warsaw
Africa/Lagos
Africa/Windhoek
Europe/Bucharest
Asia/Beirut
Africa/Cairo
Asia/Damascus
Africa/Johannesburg
Europe/Kiev
Europe/Istanbul
Asia/Jerusalem
Asia/Amman
Asia/Baghdad
Europe/Kaliningrad
Asia/Riyadh
Africa/Nairobi
Asia/Tehran
Asia/Dubai
Asia/Baku
Europe/Moscow
Indian/Mauritius
Asia/Tbilisi
Asia/Yerevan
Asia/Kabul
Asia/Karachi
Asia/Tashkent
Asia/Kolkata
Asia/Colombo
Asia/Kathmandu
Asia/Almaty
Asia/Dhaka
Asia/Yekaterinburg
Asia/Rangoon
Asia/Bangkok
Asia/Novosibirsk
Asia/Shanghai
Asia/Krasnoyarsk
Asia/Singapore
Australia/Perth
Asia/Taipei
Asia/Ulaanbaatar
Asia/Irkutsk
Asia/Tokyo
Asia/Seoul
Australia/Adelaide
Australia/Darwin
Australia/Brisbane
Australia/Sydney
Pacific/Port_Moresby
Australia/Hobart
Asia/Yakutsk
Pacific/Guadalcanal
Asia/Vladivostok
Pacific/Auckland
Etc/GMT-12
Pacific/Fiji
Asia/Magadan
Pacific/Tongatapu
Pacific/Apia
Pacific/Kiritimati
In this case, the app need to handle it itself which means that you need to compensate for DST in his JavaScript client.

jQuery.datepicker.formatDate and timezone offset

To handle dates, i'm using a jQuery UI public method in my application: jQuery.datepicker.formatDate
See params & source here : https://github.com/jquery/jquery-ui/blob/master/ui/jquery.ui.datepicker.js
However the wrong date is displayed sometimes, according to the computer timezone.
Demo here : http://jsfiddle.net/7ACdB/
With a UTC+1 (paris) timezone in windows, i got :
03/30/20
03/30/20
With a UTC-6 (us&canada) timezone in windows, i got :
03/29/20 <- meh!
03/30/20
You need to restart your browser (well for google chrome at least) when you change the OS timezone.
My problem is the "03/29/20" date as you can imagine.
Can somebody explains to me if this is normal or a jquery ui issue ?
I'm beginning to think that it is normal to see a "Mon Mar 30 2020 00:00:00 GMT+0200 (Romance Daylight Time)" as 03/29/20 in a US timezone but i'm not so sure. :-/
What you're getting is correct. Your example sets the time at midnight for Paris. Midnight in Paris is 6PM the day before in the US for the Eastern Time Zone which I am in.
Your first time: GMT+0200 is Paris
Your second time: GMT-0500 is Chicago (note it is currently Daylight Savings Time)
So, when you change the time zone to US (using one of our 6 time zones), the output is the time in the US when is that time in Paris.
Here is an updated fiddle with a the time set to 6 AM Paris: http://jsfiddle.net/jensbits/7ACdB/1/

Categories

Resources