When I use MomentJS or Internationalization API, I get obsolete timezones like Asia/Katmandu
or Asia/Calcutta
in Chrome! These should instead be outputted as Asia/Kathmandu
and Asia/Kolkata
.
How do I fix this?
When I use MomentJS or Internationalization API, I get obsolete timezones like Asia/Katmandu
or Asia/Calcutta
in Chrome! These should instead be outputted as Asia/Kathmandu
and Asia/Kolkata
.
How do I fix this?
Your question is a little bit misguided, as there's aren't generally such things in the tzdb as "obsoleted" time zones. In general, once the tzdb has introduced an identifier, it will continue to support it indefinitely - either as a Zone
or as a Link
.
The only exception is Canada/East-Saskatchewan
, which was removed from the tzdb in version 2017c because it was a misnomer and exceeded the 14-character limit set by the tzdb maintainers. Any usages of that zone should be updated to America/Regina
.
The examples and list you gave indicates that you would like canonical Zone
entries, rather than their aliased Link
entries. While either are valid, and all tzdb implementations should resolve links correctly, indeed should generally be preferred. So I can understand your desire to have all links resolved.
That said, the current implementation of the data file builder in moment-timezone doesn't distinguish between TZDB zones and links while it's building its data. Instead, it creates its own zone entry for the first unique data it encounters, and then creates its own link entry for any subsequent that match. This has the disadvantage of putting tzdb canonical zones front and center (which affects APIs like moment.tz.guess()
in older browsers), but also has the advantage of being able to link zones that are identical over the period covered in the data file.
For example, if you look at the current moment-timezone-with-data-2012-2022.js
file, you'll find that Europe/Paris
is the only zone entry for most places that uses CET/CEST. The rest are links back to Europe/Paris
in this file, even those that have separate canonical tzdb zones, like Europe/Amsterdam
, Europe/Berlin
, and others.
This tradeoff was a design decision by the original author of moment-timezone, and is generally not something that is going to change. It keeps the data file smaller than it would otherwise.
Also, if you are targeting modern browsers (and/or Node.js), I highly recommend using Luxon instead. This is a newer library from the Moment team, and has the advantage of supporting time zones without shipping a data file (because most modern environments have Intl API support).
It's also worth noting that the Intl API tends to be implemented via ICU, which gets some of its data from TZDB and some of it from CLDR. Those two projects have slightly different ideas of what is "canonical". Basically, the canonical zone in CLDR is the one that was introduced first and it never changes - even if TZDB decides to demote to a link and replace with a new name. For example, you may get Asia/Calcutta
as the default time zone for India from some Intl implementations, because CLDR considers it canonical. This is another reason while it's important that all implementations support both forms of identifiers equivalently.
I made a list of the obsolete timezones which you can use to compare the wrong one with the right one and output the right timezone.
P.S. In fact, if you are using PHP, this might turn out to be a huge problem while doing date_default_timezone_set()
.
So, here's the list:
(Left-Hand side is wrong one and the right-hand side is the right one)
Africa/Asmera = Africa/Asmara
Africa/Timbuktu = Africa/Abidjan
America/Argentina/ComodRivadavia = America/Argentina/Catamarca
America/Atka = America/Adak
America/Buenos_Aires = America/Argentina/Buenos_Aires
America/Catamarca = America/Argentina/Catamarca
America/Coral_Harbour = America/Atikokan
America/Cordoba = America/Argentina/Cordoba
America/Ensenada = America/Tijuana
America/Fort_Wayne = America/Indiana/Indianapolis
America/Indianapolis = America/Indiana/Indianapolis
America/Jujuy = America/Argentina/Jujuy
America/Knox_IN = America/Indiana/Knox
America/Louisville = America/Kentucky/Louisville
America/Mendoza = America/Argentina/Mendoza
America/Montreal = America/Toronto
America/Porto_Acre = America/Rio_Branco
America/Rosario = America/Argentina/Cordoba
America/Santa_Isabel = America/Tijuana
America/Shiprock = America/Denver
America/Virgin = America/Port_of_Spain
Antarctica/South_Pole = Pacific/Auckland
Asia/Ashkhabad = Asia/Ashgabat
Asia/Calcutta = Asia/Kolkata
Asia/Chongqing = Asia/Shanghai
Asia/Chungking = Asia/Shanghai
Asia/Dacca = Asia/Dhaka
Asia/Harbin = Asia/Shanghai
Asia/Istanbul = Europe/Istanbul
Asia/Kashgar = Asia/Urumqi
Asia/Katmandu = Asia/Kathmandu
Asia/Macao = Asia/Macau
Asia/Rangoon = Asia/Yangon
Asia/Saigon = Asia/Ho_Chi_Minh
Asia/Tel_Aviv = Asia/Jerusalem
Asia/Thimbu = Asia/Thimphu
Asia/Ujung_Pandang = Asia/Makassar
Asia/Ulan_Bator = Asia/Ulaanbaatar
Atlantic/Faeroe = Atlantic/Faroe
Atlantic/Jan_Mayen = Europe/Oslo
Australia/ACT = Australia/Sydney
Australia/Canberra = Australia/Sydney
Australia/LHI = Australia/Lord_Howe
Australia/North = Australia/Darwin
Australia/NSW = Australia/Sydney
Australia/Queensland = Australia/Brisbane
Australia/South = Australia/Adelaide
Australia/Tasmania = Australia/Hobart
Australia/Victoria = Australia/Melbourne
Australia/West = Australia/Perth
Australia/Yancowinna = Australia/Broken_Hill
Brazil/Acre = America/Rio_Branco
Brazil/DeNoronha = America/Noronha
Brazil/East = America/Sao_Paulo
Brazil/West = America/Manaus
Canada/Atlantic = America/Halifax
Canada/Central = America/Winnipeg
Canada/Eastern = America/Toronto
Canada/Mountain = America/Edmonton
Canada/Newfoundland = America/St_Johns
Canada/Pacific = America/Vancouver
Canada/Saskatchewan = America/Regina
Canada/Yukon = America/Whitehorse
Chile/Continental = America/Santiago
Chile/EasterIsland = Pacific/Easter
Cuba = America/Havana
Egypt = Africa/Cairo
Eire = Europe/Dublin
Europe/Belfast = Europe/London
Europe/Tiraspol = Europe/Chisinau
GB = Europe/London
GB-Eire = Europe/London
Hongkong = Asia/Hong_Kong
Iceland = Atlantic/Reykjavik
Iran = Asia/Tehran
Israel = Asia/Jerusalem
Jamaica = America/Jamaica
Japan = Asia/Tokyo
Kwajalein = Pacific/Kwajalein
Libya = Africa/Tripoli
Mexico/BajaNorte = America/Tijuana
Mexico/BajaSur = America/Mazatlan
Mexico/General = America/Mexico_City
Navajo = America/Denver
NZ = Pacific/Auckland
NZ-CHAT = Pacific/Chatham
Pacific/Johnston = Pacific/Honolulu
Pacific/Ponape = Pacific/Pohnpei
Pacific/Samoa = Pacific/Pago_Pago
Pacific/Truk = Pacific/Chuuk
Pacific/Yap = Pacific/Chuuk
Poland = Europe/Warsaw
Portugal = Europe/Lisbon
PRC = Asia/Shanghai
ROC = Asia/Taipei
ROK = Asia/Seoul
Singapore = Asia/Singapore
Turkey = Europe/Istanbul
US/Alaska = America/Anchorage
US/Aleutian = America/Adak
US/Arizona = America/Phoenix
US/Central = America/Chicago
US/Eastern = America/New_York
US/East-Indiana = America/Indiana/Indianapolis
US/Hawaii = Pacific/Honolulu
US/Indiana-Starke =America/Indiana/Knox
US/Michigan = America/Detroit
US/Mountain = America/Denver
US/Pacific = America/Los_Angeles
US/Pacific-New = America/Los_Angeles
US/Samoa = Pacific/Pago_Pago
W-SU = Europe/Moscow
Zulu = Etc/UTC
UTC = Etc/UTC
UCT = Etc/UCT
Universal = Etc/UTC
GMT = Etc/GMT
GMT+0 = Etc/GMT
GMT0 = Etc/GMT
GMT−0 = Etc/GMT
Greenwich = Etc/GMT
Etc/Greenwich = Etc/GMT
Etc/Universal = Etc/UTC
Etc/Zulu = Etc/UTC
Etc/GMT0 = Etc/GMT
Etc/GMT-0 = Etc/GMT
Etc/GMT+0 = Etc/GMT
This list might still be incomplete but should help the majority of you. If you found more of the incorrect ones, please comment it down.
Here I wrote a very small code to compare which might be helpful for you. I used unminified data file and extracted the whole data. This list will show you the comparison between new and obsolete data.
$("#div1").load("https://momentjs.com/downloads/moment-timezone-with-data.js", function(responseTxt, statusTxt, xhr) {
if (statusTxt == "success") {
//console.log("External content loaded successfully!");
keepMeUpdated();
}
if (statusTxt == "error")
console.log("Error: " + xhr.status + ": " + xhr.statusText);
});
function keepMeUpdated() {
var str = $("#div1").html();
str = str.slice(str.lastIndexOf("loadData"), str.length - 1);
str = str.slice(0, str.indexOf(')'));
str = str.replace('loadData(', '');
$("#div1").html(str);
compareNow();
}
function compareNow() {
var str = $("#div1").html();
var obj = JSON.parse(str);
var links = obj.links;
var counter = 0;
var te = "There are " + obj.zones.length + " timezones available. From these timezones " + links.length + " have recently got updated."
$("#head").html(te);
for (var i = 0; i < links.length; i++) {
var ele = links[i];
var spl = ele.split('|');
var isSame = spl[0] == spl[1];
if (!isSame) {
counter++;
var text = '<tr><td>' + counter + "</td><td>" + spl[1] + "</td><td> " + spl[0] + '</td></tr>';
$("#mm tbody").append(text);
}
}
}
@import url("https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css");
#div1 {
display: none;
}
#head {
font-size: 18px;
font-weight: bold;
margin: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<div id='head'></div>
<div>
<table id='mm' class="table table-striped">
<thead>
<th>Sr</th>
<th>Obsolete Data</th>
<th>Updated Data</th>
</thead>
<tbody>
</tbody>
</table>
</div>
<div id='div1'></div>