Poking about in Java TimeZones
Yup, yet another post about some of the i18n and l10n facilities in Java, on the back of code I’ve scribbled to demonstrate and clarify various “interesting” cases of the world being complicated.
Here I’m basically looking at the TimeZone utility and the available info it gives in Java 8, 9 and 10. That data largely comes from the team which attempts to track timezone changes around the world - The IANA Timezone database.
As with the Locale facilities, most of the differences between versions mentioned here are between Java 8 and Java 9, although Java 10 did make a few more changes, presumably because the world changed, people never agree how to handle time.
The code used as the source of this article is here but basically it’s:
get a unicode capable output stream get a sorted list of all the available TimeZones print a bunch of info about each TimeZone * its "code" (doesn't seem to follow an ISO standard though) * a DisplayName (can be localized, but I've only checked English) * it's current offset from UTC/GMT/Z (I'll be talking about that below) * whether it does Daylight Saving Time and whether it's currently active print the count of known TimeZones
The raw results are here:
I compiled that with OpenJDK’s Java 8 version, then ran it in OpenJDK’s JVMs for
Java 8, 9 and 10. I took the outputs from each and diff
ed them to see what has
changed between Java versions.
Usual Caveat: These results are from the OpenJDK JVM, on a Debian PC. Different JVMs for different OSs on different hardware may have different information. Do your own tests if you need to know for sure!
A quick glossary note …
- DST = Daylight Saving Time, aka “messing with the clocks in summer”
- UTC = GMT = the baseline time. Historically based on a North-South line through Greenwich.
- 1H5M30S = 1 hour, 5 minutes and 30 seconds, it’s a standard notation for time durations.
And now on with the waffle about those results…
1. There are a lot of specified timezones
- Java 8 TimeZone count: 627
- Java 9 TimeZone count: 628
- Java 10 TimeZone count: 627
Two things here - firstly, nearly 630 different timezones - on this single planet which only has one sun - and a fairly steady rotation rate. WTAF?!
Actually, a lot of these are just different names for the same timezone. For example our friendly, simple to understand, zero line through Greenwich from pole to pole has 37 different names. Some of them are:
TZ code: Africa/Abidjan, TZ name: Greenwich Mean Time, current UTC offset is 0S, DST is: 0S TZ code: Africa/Accra, TZ name: Ghana Mean Time, current UTC offset is 0S, DST is: 0S TZ code: GMT, TZ name: Greenwich Mean Time, current UTC offset is 0S, DST is: 0S TZ code: GMT0, TZ name: Greenwich Mean Time, current UTC offset is 0S, DST is: 0S TZ code: Greenwich, TZ name: Greenwich Mean Time, current UTC offset is 0S, DST is: 0S TZ code: UCT, TZ name: Coordinated Universal Time, current UTC offset is 0S, DST is: 0S TZ code: UTC, TZ name: Coordinated Universal Time, current UTC offset is 0S, DST is: 0S TZ code: Zulu, TZ name: Coordinated Universal Time, current UTC offset is 0S, DST is: 0S
It looks like Java has taken the approach of recording all the names each specific timezone is known as, rather than picking one name to use for each zone. That makes sense as they’re trying to handle all the timezones names currently being used around the world.
The second thing to notice with those counts is that Java 9 has one more timezone than java 8 and 10. It turns out Java 9 added a zone and Java 10 removed it again.
TZ code: Canada/East-Saskatchewan, TZ name: Central Standard Time, current UTC offset is -6H, DST is: 0S
According to the 2017 release notes from the IANA team, the name was
too long for some of the standard TZ database tools and the timezone was a misnamed
variant of Canada/Saskatchewan
, so they dropped it.
2. The Antarctic is a mess
TZ code: Antarctica/Casey, TZ name: Australian Western Standard Time, current UTC offset is 11H, DST is: 0S TZ code: Antarctica/Davis, TZ name: Davis Time, current UTC offset is 7H, DST is: 0S TZ code: Antarctica/DumontDUrville, TZ name: Dumont-d’Urville Time, current UTC offset is 10H, DST is: 0S TZ code: Antarctica/Macquarie, TZ name: Macquarie Island Time, current UTC offset is 11H, DST is: 0S TZ code: Antarctica/Mawson, TZ name: Mawson Time, current UTC offset is 5H, DST is: 0S TZ code: Antarctica/McMurdo, TZ name: New Zealand Standard Time, current UTC offset is 12H, DST is: 1H TZ code: Antarctica/Palmer, TZ name: Chile Standard Time, current UTC offset is -3H, DST is: 0S TZ code: Antarctica/Rothera, TZ name: Rothera Time, current UTC offset is -3H, DST is: 0S TZ code: Antarctica/South_Pole, TZ name: New Zealand Standard Time, current UTC offset is 12H, DST is: 1H TZ code: Antarctica/Syowa, TZ name: Syowa Time, current UTC offset is 3H, DST is: 0S TZ code: Antarctica/Troll, TZ name: Greenwich Mean Time, current UTC offset is 2H, DST is: 2H, ACTIVE TZ code: Antarctica/Vostok, TZ name: Vostok Time, current UTC offset is 6H, DST is: 0S and TZ code: Indian/Kerguelen, TZ name: French Southern & Antarctic Time, current UTC offset is 5H, DST is: 0S
So there’s 14 different timezones, ranging from -3 hours behind UTC to +12 hours ahead of UTC. Some of them have DST, some don’t. Some are currently in DST, some aren’t.
Luckily no one lives there permanently and it appears that those who do either use UTC or the timezone of whoever they talk to on the radio most often.
I’ll be mentioning Antarctica/Troll
again later, watch out for them.
Strangely the arctic appears to have largely avoided this. There’s only one named arctic timezone:
TZ code: Arctic/Longyearbyen, TZ name: Central European Standard Time, current UTC offset is 2H, DST is: 1H, ACTIVE
3. Different TimeZones have the same name
Just to mess with us a bit more, not only do some timezones have multiple names (section 1)
but some names are used for multiple timezones. Greenwich Mean Time
is the obvious
example - most of the time it’s actually the same rules, but occasionally, well:
TZ code: Antarctica/Troll, TZ name: Greenwich Mean Time, current UTC offset is 2H, DST is: 2H, ACTIVE TZ code: Eire, TZ name: Greenwich Mean Time, current UTC offset is 1H, DST is: 1H, ACTIVE TZ code: GMT, TZ name: Greenwich Mean Time, current UTC offset is 0S, DST is: 0S
Yup, that’s Greenwich Mean Time
- it unambiguously refers to a slice of the
planet which is either 0, 1 or 2 hours ahead of UTC, has a DST of 1 or 2 hours,
or maybe doesn’t do DST, and if it does do DST, it may or may not be active at the moment.
And there’s Antarctica/Troll
again, hello.
4. DST isn’t always 1 hour
Some timezones don’t do DST; that’s fine, it’s a bit of a controversial hack and clearly up to countries to decide whether it’s a good idea. Some even change their minds - that’s partly why the IANA timezone team do their thing.
Almost all countries that decide to do DST stick with a 1 hour forward jump. However there are a few outliers:
TZ code: Australia/Lord_Howe, TZ name: Lord Howe Standard Time, current UTC offset is 10H30M, DST is: 30M TZ code: Antarctica/Troll, TZ name: Greenwich Mean Time, current UTC offset is 2H, DST is: 2H, ACTIVE
Oh hello Antarctica/Troll
fancy seeing you again! And Lord Howe
, I don’t know
where in Australia you’re used, but seriously, is 30 minutes really worth it?
5. UTC offsets aren’t always full hours
Speaking of that Lord Howe
timezone - notice its offset from UTC is 10H30M
at the moment. It has 30M of DST and 10H of normal UTC offset. They’re not alone
in having a fraction of an hour offset from UTC:
TZ code: Asia/Kathmandu, TZ name: Nepal Time, current UTC offset is 5H45M, DST is: 0S TZ code: Asia/Kolkata, TZ name: India Standard Time, current UTC offset is 5H30M, DST is: 0S TZ code: Asia/Pyongyang, TZ name: Pyongyang Time, current UTC offset is 8H30M, DST is: 0S TZ code: Australia/Adelaide, TZ name: Australian Central Standard Time, current UTC offset is 9H30M, DST is: 1H TZ code: CNT, TZ name: Newfoundland Standard Time, current UTC offset is -2H-30M, DST is: 1H, ACTIVE
There’s about 30 fractional offsets altogether in the Java 10 result set. It looks
like Kathmandu
is the only one that has gone for a 45M fraction and none of
them have gone for a 15M fraction or smaller slices.
Surprisingly Antarctica/Troll
doesn’t appear in this section, I’m sure they’ll
be in contact with IANA sometime soon to say they plan to use an offset of Pi minutes.
6. Java 8 vs Java 9
There were a lot of differences in the timezone data between 8 and 9. Partly because the Java i18n team did a lot of leg work getting names correctly sorted out and partly because there was a long time between them, so more changes piled up in the IANA database.
Overall my diff shows 111 timezones were altered between the two versions, so I’ll just summarise the changes with the following bullets:
- A lot of DisplayName tweaks like “Eastern African” -> “East Africa”, “Argentine” -> “Argentina” and the like.
- Some obvious typos being fixed
- Sprinkling “Standard” into a bunch of the DisplayNames. I guess it’s a security blanket of a kind :-)
- Timezones changing their UTC offset
- Timezones changing their UTC offset and compensating with a DST change too
- Changing whether or not they’re doing DST at all
And finally, just to hark back to the Locale work in Java 9, the first use of a non-ASCII char in the DisplayName of a timezone in English…
TZ code: Antarctica/DumontDUrville, TZ name: Dumont-d’Urville Time, current UTC offset is 10H, DST is: 0S
That was a single quote mark in Java 8. Tiny steps, but that’s a unicode char in an English DisplayName!
7. Java 9 vs Java 10
Far fewer changes between 9 and 10. I expect that’s partly that Java 9 had a massive chunk of improvements over 8, and there wasn’t such a long gap to 10. Only 6 changes in total:
TZ code: Africa/Khartoum, TZ name: East Africa Time, current UTC offset is 2H, DST is: 0S (was 3H offset) TZ code: Africa/Windhoek, TZ name: West Africa Standard Time, current UTC offset is 2H, DST is: 0S TZ code: Pacific/Tongatapu, TZ name: Tonga Standard Time, current UTC offset is 13H, DST is: 0S (both not doing DST any more) TZ code: America/Grand_Turk, TZ name: Atlantic Standard Time, current UTC offset is -4H, DST is: 1H, ACTIVE TZ code: Asia/Famagusta, TZ name: GMT+02:00, current UTC offset is 3H, DST is: 1H, ACTIVE (both started doing DST) -- TZ code: Canada/East-Saskatchewan, TZ name: Central Standard Time, current UTC offset is -6H, DST is: 0S (disappeared)