[tz] OpenJDK/CLDR/ICU/Joda issues with Ireland change

Stephen Colebourne scolebourne at joda.org
Mon Jan 22 17:19:20 UTC 2018

Let me try to summarize why the negative SAVE (Ireland change) matters
to Java-based projects. there are two basic streams of code - old and

The older OpenJDK time-zone code and ICU Java code both derive from
the same original 20 year old source.
The newer OpenJDK time-zone code derives indirectly from Joda-Time,
which is still based on many principles from the older OpenJDK code.
The ThreeTen-Backport project is an early version of the newer OpenJDK
time-zone code.
Thus, the vast majority of Java time-zone code is linked and follows a
similar approach.

The basic data stored is:
- a "raw" offset that changes over time, also known as "standard"
- a "daylight" offset that changes over time (either relative to the
"raw" or absolute)
- time-zone changes available from 1970 or earlier
- only the *current* names of time-zones are available

Some problems:

1) The older code has limits on the difference between the "raw" and
"daylight" offset in `GregorianCalendar`. Specifically, the
"DST_OFFSET" can only be from 0 to 2 hours. Negative SAVE values are
not expected or supported. Note that the limits of 0 to 2 hours are
publicly visible via the API `GregorianCalendar.getLeastMinimum()` and

2) The current names of the time-zones is accessed via an array of a
fixed order, roughly [long-std, short-std, long-daylight,
short-daylight]. Whether the std or daylight text form should be
returned is determined by a parameter - a boolean, named "daylight".
The basic way this is determined is whether the offset and the"raw"
offset are the same or not. This is also expressed in
`TimeZone.inDaylightTime()` and `ZoneRules.isDaylightSavings()`,
making any switch in the boolean user-visible.

The problem here is that the Ireland change flips when the boolean is
true from summer to winter. Whereas the content of the array has been
stable for 20 years. In the problematic case I looked at, this means
that the wrong textual description is returned. ie. in winter, the
code has always accessed array elements 0 and 1, whereas if the
boolean flag is swapped it will access elements 2 and 3.

Remember that only the *current* names of the time-zones are available
- so if the Ireland change happens, the time-zone name will
necessarily be wrong either before the change occurs or after it. It
is a similar problem as Yoshito Umaoka from CLDR expressed a clash
between data and code. Here the data on names would clash with the
boolean "daylight" flag. Fixing the code doesn't help in this scenario
- there is no viable approach to fixing it that can work, as Java has
a long history of backwards compatibility over decades, not a year (as
is being talked about). Specifically, some of these libraries
(Joda-Time, ThreeTen-Backport) run with new tzdb data on older JDK
versions. It is the incompatibility in the boolean, where false no
longer means winter that cannot be accepted.

So, to summarize, even if those in the CLDR/ICU/Java world thought
this change was meaningful and positive, backwards compatibility rules
out making it. But, in fact the majority of the feedback on the topic
from software library maintainers has been negative.

I'm pretty sure that negative SAVE is going to be rejected by CLDR,
ICU, OpenJDK, Joda-Time and ThreeTen-Backport permanently, and
probably Android and Apple too based on their responses so far. As
I've outlined, there is no way to meet the backwards compatibility
requirements with it. A one year stay of execution won't make a
difference in the practicality of the change.

FWIW, I understand why some are attached to trying to express data in
a "pure" form, but that was never the original intent of the project
IMO. The project needs to get back to serving its downstream consumers
who just want to know the time without continuous instability in the
data format.


PS, Microsoft .NET APIs also have an IsDaylightSavingTime() method:

More information about the tz mailing list