DateTimeZoneProvider.detectTimeZone sometimes returns unexpected timezone

81 views
Skip to first unread message

Katy Jones

unread,
Dec 18, 2024, 9:08:13 AM12/18/24
to TeaVM
Hi! We've come across an odd thing when using a particular timezone.

We are using TeaVM 0.10.0 with java.util.TimeZone.autodetect set to true
My Windows timezone is set to (UTC+00:00) Dublin, Edinburgh, Lisbon, London (I am based in UK).
In our web app, the time returned by LocalTime.now() is behind by 114 minutes.
I think this is ultimately down to DateTimeZoneProvider.detectTimeZone(), which returns Atlantic/Azores.
This is the same whether or not I enable "Adjust for daylight saving time automatically" in Windows settings.
If I use any other UTC/UTC+00:00 timezones in Windows settings, TTimeZone.detectTimeZone() returns Europe/Prague, and the time returned by LocalTime.now() is as expected (don't quite understand this either as Prague is an hour ahead!).
This is repeatable in Chromium and Firefox browsers on Windows, and my colleague has replicated the same on Mac.

I am wondering if this is related to the timezone offsets, which DateTimeZoneProvider is scaling into minutes.
Most of them correspond to the UTC time differences, but some are irregular; for Atlantic/Azores, the offset is -114.
I made a copy of detectTimeZone() where I forced the Atlantic/Azores offset to -120; in this case, the default timezone returned was Europe/Prague.

Our workaround is to use another UTC/UTC+00:00 timezone but we'd like to understand whether this is an issue in TeaVM or somehow an issue with the OS - please can you shed any light on this?


*** 
While writing this I noticed you've released 0.11.0 so I've had a quick go with that.
Now, the offset for Atlantic/Azores is -60, DateTimeZoneProvider.detectTimeZone() returns Atlantic/Canary and LocalTime.now() is ahead by an hour - getting closer!
The other timezones return Europe/Prague and correct time, as before.

Alexey Andreev

unread,
Dec 18, 2024, 9:18:28 AM12/18/24
to te...@googlegroups.com

Hi! We've come across an odd thing when using a particular timezone.

We are using TeaVM 0.10.0 with java.util.TimeZone.autodetect set to true
My Windows timezone is set to (UTC+00:00) Dublin, Edinburgh, Lisbon, London (I am based in UK).
In our web app, the time returned by LocalTime.now() is behind by 114 minutes.
I think this is ultimately down to DateTimeZoneProvider.detectTimeZone(), which returns Atlantic/Azores.
This is the same whether or not I enable "Adjust for daylight saving time automatically" in Windows settings.
If I use any other UTC/UTC+00:00 timezones in Windows settings, TTimeZone.detectTimeZone() returns Europe/Prague, and the time returned by LocalTime.now() is as expected (don't quite understand this either as Prague is an hour ahead!).
This is repeatable in Chromium and Firefox browsers on Windows, and my colleague has replicated the same on Mac.

I am wondering if this is related to the timezone offsets, which DateTimeZoneProvider is scaling into minutes.
Most of them correspond to the UTC time differences, but some are irregular; for Atlantic/Azores, the offset is -114.
I made a copy of detectTimeZone() where I forced the Atlantic/Azores offset to -120; in this case, the default timezone returned was Europe/Prague.

Our workaround is to use another UTC/UTC+00:00 timezone but we'd like to understand whether this is an issue in TeaVM or somehow an issue with the OS - please can you shed any light on this?

Hi. Time zone detection is quite unreliable and was developed back 10 years ago when there was no API in JS to get system timezone. Now you can use Intl for this purpose. I'll implement proper time zone detection in TeaVM, but for now you can try to use following workaround:

  • Use following JS code (for example, via @JSBody) to get system timezone name: Intl.DateTimeFormat().resolvedOptions().timeZone
  • Use TimeZone.getTimeZone to find time zone by name
  • Set default time zone by calling TimeZone.setDefault.

Katy Jones

unread,
Dec 19, 2024, 11:14:58 AM12/19/24
to TeaVM
Thanks so much for the quick response!
I've followed your suggestion and that's now setting the default time zone to Europe/London, which makes sense.

I'm still seeing an issue with how this formats times.
I've created a ZonedDateTime myTime with a UTC time e.g. 2024-12-19T13:44:46.3433333Z
I've created a DateTimeFormatter as follows:
DateTimeFormatter dtf = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT).withZone(ZoneId.systemDefault());
The formatted time returned by myTime.format(dtf) is an hour ahead e.g. 19/12/2024, 14:44
It seems to be to do with the offset rules for Europe/London in particular.

This is behaving as I'd expect in Java server code so I've been comparing StandardZoneRules with java.time.zone.ZoneRules - the only obvious difference I can see is when savingsInstantTransitions is instantiated - StandardZoneRules uses Instant.getEpochSecond whereas ZoneRules uses ZoneOffsetTransition.toEpochSecond - could that be having an effect?
StandardZoneRules.png
ZoneRules.png

Thanks again for your advice on this.

Alexey Andreev

unread,
Dec 21, 2024, 1:57:25 PM12/21/24
to te...@googlegroups.com


Thanks so much for the quick response!
I've followed your suggestion and that's now setting the default time zone to Europe/London, which makes sense.

I'm still seeing an issue with how this formats times.
I've created a ZonedDateTime myTime with a UTC time e.g. 2024-12-19T13:44:46.3433333Z
I've created a DateTimeFormatter as follows:
DateTimeFormatter dtf = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT).withZone(ZoneId.systemDefault());
The formatted time returned by myTime.format(dtf) is an hour ahead e.g. 19/12/2024, 14:44
It seems to be to do with the offset rules for Europe/London in particular.

Can you please provide the code, with default time zone set to some particular constant, so that it's easily reproducible? I did try following:

        TimeZone.setDefault(TimeZone.getTimeZone("Europe/London"));
        System.out.println(ZoneId.systemDefault());
        var dtf = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT).withZone(ZoneId.of("UTC"));
        var time = ZonedDateTime.of(2024, 12, 19, 13, 44, 46, 0, ZoneId.systemDefault());
        System.out.println(time.format(dtf));

And got following result on JVM in JS respectively:

Europe/London
19.12.2024, 13:44

Europe/London
12/19/24, 1:44 PM


This is behaving as I'd expect in Java server code so I've been comparing StandardZoneRules with java.time.zone.ZoneRules - the only obvious difference I can see is when savingsInstantTransitions is instantiated - StandardZoneRules uses Instant.getEpochSecond whereas ZoneRules uses ZoneOffsetTransition.toEpochSecond - could that be having an effect?

Sorry, have no idea. I don't know well this thing with time zones and don't know java.time API. I just ported threeten code to TeaVM - without understanding how it works internally.

You can also use native JS code to format dates. In order you want to share some code between client and server, hide date-formatting routine behind some interface and provide either JS-specific or JVM-specific implementation. Also, you can try to update to 0.11.0

Alexey Andreev

unread,
Dec 21, 2024, 1:57:56 PM12/21/24
to te...@googlegroups.com


Thanks so much for the quick response!
I've followed your suggestion and that's now setting the default time zone to Europe/London, which makes sense.

I'm still seeing an issue with how this formats times.
I've created a ZonedDateTime myTime with a UTC time e.g. 2024-12-19T13:44:46.3433333Z
I've created a DateTimeFormatter as follows:
DateTimeFormatter dtf = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT).withZone(ZoneId.systemDefault());
The formatted time returned by myTime.format(dtf) is an hour ahead e.g. 19/12/2024, 14:44
It seems to be to do with the offset rules for Europe/London in particular.

Can you please provide the code, with default time zone set to some particular constant, so that it's easily reproducible? I did try following:

        TimeZone.setDefault(TimeZone.getTimeZone("Europe/London"));
        System.out.println(ZoneId.systemDefault());
        var dtf = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT).withZone(ZoneId.of("UTC"));
        var time = ZonedDateTime.of(2024, 12, 19, 13, 44, 46, 0, ZoneId.systemDefault());
        System.out.println(time.format(dtf));

And got following result on JVM in JS respectively:

Europe/London
19.12.2024, 13:44

Europe/London
12/19/24, 1:44 PM


This is behaving as I'd expect in Java server code so I've been comparing StandardZoneRules with java.time.zone.ZoneRules - the only obvious difference I can see is when savingsInstantTransitions is instantiated - StandardZoneRules uses Instant.getEpochSecond whereas ZoneRules uses ZoneOffsetTransition.toEpochSecond - could that be having an effect?

Sorry, have no idea. I don't know well this thing with time zones and don't know java.time API. I just ported threeten code to TeaVM - without understanding how it works internally.

Katy Jones

unread,
Jan 7, 2025, 6:24:34 AMJan 7
to TeaVM
The code you've used reproduces the problem for me - I'm using TeaVM 0.11.0, I see the same in Chrome and Firefox.

Java code:
        TimeZone.setDefault(TimeZone.getTimeZone("Europe/London"));
        System.out.println(ZoneId.systemDefault());
        var dtf = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT).withZone(ZoneId.of("UTC"));
        var time = ZonedDateTime.of(2024, 12, 19, 13, 44, 46, 0, ZoneId.systemDefault());
        System.out.println(time.format(dtf));

TeaVM compiles into JS (this looks fine to me):
    let $dtf, $time;
    ju_TimeZone_setDefault(ju_TimeZone_getTimeZone($rt_s(1643)));
    (jl_System_out()).$println0(jt_ZoneId_systemDefault());
    jtf_FormatStyle_$callClinit();
    $dtf = jtf_DateTimeFormatter_withZone(jtf_DateTimeFormatter_ofLocalizedDateTime(jtf_FormatStyle_SHORT), jt_ZoneId_of($rt_s(669)));
    $time = jt_ZonedDateTime_of0(2024, 12, 19, 13, 44, 46, 0, jt_ZoneId_systemDefault());
    (jl_System_out()).$println1(jt_ZonedDateTime_format($time, $dtf));

Gives me this result in the web app - London is an hour ahead of UTC (it should be the same):
Europe/London
19/12/2024, 12:44

The difference is the same for all months of the year; possibly applying Daylight Savings Time all year round?
Europe/Lisbon is also an hour ahead, but Europe/Dublin is fine (on Windows, these are all listed as part of the same time zone).
Another odd one is Africa/Tunis, which comes out as 9 minutes ahead. 
Seems to be something to do with how the time zones/offsets are created (e.g. DateTimeZone.getOffset(time)) but I don't understand it either!

For now, we've found a workaround using pure JS - just sharing these details in case you wanted to pursue further in future - thanks again.

Alexey Andreev

unread,
Jan 17, 2025, 1:02:33 PMJan 17
to TeaVM
Strange. I just tried your sample and got following result:

12/19/24, 1:44 PM

Did you try to upgrade to the latest version? Also, is this possible that during latest few month British government changed rules of transferring to daylight saving time?
вторник, 7 января 2025 г. в 12:24:34 UTC+1, Katy Jones:
Reply all
Reply to author
Forward
0 new messages