[tz] Java & Rearguard

Paul Eggert eggert at cs.ucla.edu
Sat Jun 1 06:09:59 UTC 2019


Stephen Colebourne wrote:
> Unfortunately I don't run on Linux, so can't check this.
I looked into this and found that on Fedora 30 x86-64, OpenJDK 12.0.1 mishandles 
  not only *negative* DST specified via a POSIX TZ string, it also mishandles 
*positive* DST specified via a POSIX TZ string. On the other hand, this Java 
works fine with TZ='Europe/Dublin' even though Europe/Dublin has negative DST on 
my platform. See attached shell transcript. I am using OpenJDK 12.0.1 linux-x64 
which I got from download.java.net.

So what I'm observing on this platform is:

* Java supports negative DST when it comes from a TZif file.

* Java does not support POSIX TZ strings that specify DST, regardless of whether 
the DST is positive or negative.

Although this is just one Java platform, it appears that I may have been 
worrying overmuch about Java and tzdb's rearguard format, in the sense that the 
problem appears to have been fixed on Fedora without modifying the Java 
libraries themselves.
-------------- next part --------------
# In this transcript, my comments are marked with leading '#'.
#
# Start with no TZ setting in the environment, which means to
# rely on /etc/localtime, which on my platform is America/Los_Angeles.
$ echo ${TZ-'TZ is unset'}
TZ is unset
$ ls -l /etc/localtime
lrwxrwxrwx. 1 root root 41 May  3 08:15 /etc/localtime -> ../usr/share/zoneinfo/America/Los_Angeles
$ jshell
|  Welcome to JShell -- Version 12.0.1
|  For an introduction type: /help intro

jshell> var wallzone = java.time.ZoneId.systemDefault()
var wallzone = java.time.ZoneId.systemDefault()
wallzone ==> America/Los_Angeles

jshell> java.time.ZonedDateTime.of(2019,5,31,0,0,0,0,wallzone)
java.time.ZonedDateTime.of(2019,5,31,0,0,0,0,wallzone)
$2 ==> 2019-05-31T00:00-07:00[America/Los_Angeles]
# correct

jshell> java.time.ZonedDateTime.of(2019,1,1,0,0,0,0,wallzone)
java.time.ZonedDateTime.of(2019,1,1,0,0,0,0,wallzone)
$3 ==> 2019-01-01T00:00-08:00[America/Los_Angeles]
# correct

jshell>
#
#
# OK, now use the POSIX TZ setting that is equivalent to America/Los_Angeles
# for timestamps from 2007 on.
$ tail -1 /usr/share/zoneinfo/America/Los_Angeles
PST8PDT,M3.2.0,M11.1.0
$ export TZ=PST8PDT,M3.2.0,M11.1.0
$ jshell
|  Welcome to JShell -- Version 12.0.1
|  For an introduction type: /help intro

jshell> var wallzone = java.time.ZoneId.systemDefault()
var wallzone = java.time.ZoneId.systemDefault()
wallzone ==> GMT-08:00

jshell> java.time.ZonedDateTime.of(2019,5,31,0,0,0,0,wallzone)
java.time.ZonedDateTime.of(2019,5,31,0,0,0,0,wallzone)
$2 ==> 2019-05-31T00:00-08:00[GMT-08:00]
# This is wrong: the UTC offset on May 31 is -07, not -08.

jshell> java.time.ZonedDateTime.of(2019,1,1,0,0,0,0,wallzone)
java.time.ZonedDateTime.of(2019,1,1,0,0,0,0,wallzone)
$3 ==> 2019-01-01T00:00-08:00[GMT-08:00]
# correct

jshell>
#
#
# OK, now try Europe/Dublin, a zone with negative DST in winter.
$ export TZ=Europe/Dublin
$ jshell
|  Welcome to JShell -- Version 12.0.1
|  For an introduction type: /help intro

jshell> var wallzone = java.time.ZoneId.systemDefault()
var wallzone = java.time.ZoneId.systemDefault()
wallzone ==> Europe/Dublin

jshell> java.time.ZonedDateTime.of(2019,5,31,0,0,0,0,wallzone)
java.time.ZonedDateTime.of(2019,5,31,0,0,0,0,wallzone)
$2 ==> 2019-05-31T00:00+01:00[Europe/Dublin]
# correct

jshell> java.time.ZonedDateTime.of(2019,1,1,0,0,0,0,wallzone)
java.time.ZonedDateTime.of(2019,1,1,0,0,0,0,wallzone)
$3 ==> 2019-01-01T00:00Z[Europe/Dublin]
# correct

jshell>
#
#
# OK
$ tail -1 /usr/share/zoneinfo/Europe/Dublin
IST-1GMT0,M10.5.0,M3.5.0/1
$ export TZ=IST-1GMT0,M10.5.0,M3.5.0/1
$ jshell
|  Welcome to JShell -- Version 12.0.1
|  For an introduction type: /help intro

jshell> var wallzone = java.time.ZoneId.systemDefault()
var wallzone = java.time.ZoneId.systemDefault()
wallzone ==> GMT+01:00

jshell> java.time.ZonedDateTime.of(2019,5,31,0,0,0,0,wallzone)
java.time.ZonedDateTime.of(2019,5,31,0,0,0,0,wallzone)
$2 ==> 2019-05-31T00:00+01:00[GMT+01:00]
# correct

jshell> java.time.ZonedDateTime.of(2019,1,1,0,0,0,0,wallzone)
java.time.ZonedDateTime.of(2019,1,1,0,0,0,0,wallzone)
$3 ==> 2019-01-01T00:00+01:00[GMT+01:00]
# This is wrong; the UTC offset on January 1 is +00, not +01.

jshell>
$


More information about the tz mailing list