Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How is java.util.TimeZone daylight info updated?

Tags:

java

timezone

dst

I couldn't find a similar question around, so here it goes.

I need to create some alerts and basically identify when a daylight saving time approaches, i.e. next thursday daylight begins

Question How does Timezone knows the correct info?

I ask that because, for instance, in my country - Brazil - the day is defined one year before when it will happen by government. It could potentially not even exist on a specific year. This probably happens in other countries as well.

On Java Doc, the below info can be found:

This method returns a historically correct offset value if an underlying TimeZone implementation subclass supports historical Daylight Saving Time schedule and GMT offset changes

It says it returns a historically correct. But how trustworthy is this method for detecting timezones? Does it depends on regular java updates, does it read from somewhere in Windows, for instance ?

Thanks in advance!

like image 591
Felipe S. Avatar asked Feb 05 '18 20:02

Felipe S.


2 Answers

Timezone Updater Tool

The link below explains the official method to update timezones in Java using the Timezone Updater Tool.

https://www.oracle.com/java/technologies/javase/tzupdater-readme.html

Basically, download the tool jar and run the command

java -jar tzupdater.jar options

like image 172
LMC Avatar answered Sep 24 '22 14:09

LMC


Every Java implementation comes with its own copy of tzdata, the time zone definition set maintained by Paul Eggert and ICANN.

The definitions and rules for time zones do indeed change quite often. Politicians around the world have shown a penchant for altering the time zone(s) under their jurisdiction. You are right to be concerned about this issue.

Updates to your Java implementation will usually come with a fresh tzdata.

Unfortunately, politicians sometimes change their time zones with little or even no forewarning, oblivious to havoc this wreaks. Sometimes the notice is only a few months, or even weeks. For example Russia, Turkey, & Morocco in recent years. And in the case of North Korea, their last change had no forewarning at all.

If a time zone of interest to you is being changed with little warning, you may not have the time to wait for an update release for your Java implementation. So you may need to obtain a fresh tzdata yourself, and manually update your installed Java implementation. See the Answer by Luis Muñoz for doing so using the Timezone Updater Tool by Oracle.

Be aware that you also need to update the time zone date in other places. These include your host OS and some database systems such as Postgres.


You asked:

Does it depends on regular java updates, does it read from somewhere in Windows, for instance ?

Java keeps its own time zone for use by Java app. Your host OS keeps its own time zone data for its own use and for use by some native apps. Some other systems such as DBMS may keep their own time zone data.

You said:

basically identify when a daylight saving time approaches, i.e. next thursday daylight begins

Keep in mind that Daylight Saving Time (DST) is not the only reason a time zone changes its offset-from-UTC. Time zones change for various political, diplomatic, military, and cultural reasons.

Here is code in Java to determine the next transition.

Never use java.util.TimeZone as it is part of the troubled legacy date-time classes. Those legacy classes were supplanted years ago by the modern java.time classes defined in JSR 310.

Specify your time zone of interest as a ZoneId object.

Specify a proper time zone name in the format of Continent/Region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 2-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).

ZoneId z = ZoneId.of( "America/Sao_Paulo" ) ;

Obtain the rules for that zone. Interrogate the rules for a list of all known transitions.

ZoneRules rules = z.getRules() ;
List<ZoneOffsetTransition> transitions = rules.getTransitions() ;
transitions.stream().forEach( System.out::println ) ;

Transition[Gap at 1914-01-01T00:00-03:06:28 to -03:00]

Transition[Gap at 1931-10-03T11:00-03:00 to -02:00]

Transition[Overlap at 1932-04-01T00:00-02:00 to -03:00]

Transition[Gap at 1932-10-03T00:00-03:00 to -02:00]

Transition[Overlap at 1933-04-01T00:00-02:00 to -03:00]

Transition[Gap at 1949-12-01T00:00-03:00 to -02:00]

Transition[Overlap at 1950-04-16T01:00-02:00 to -03:00]

Transition[Gap at 1950-12-01T00:00-03:00 to -02:00]

Transition[Overlap at 1951-04-01T00:00-02:00 to -03:00]

Transition[Gap at 1951-12-01T00:00-03:00 to -02:00]

Transition[Overlap at 1952-04-01T00:00-02:00 to -03:00]

Transition[Gap at 1952-12-01T00:00-03:00 to -02:00]

Transition[Overlap at 1953-03-01T00:00-02:00 to -03:00]

Transition[Gap at 1963-10-23T00:00-03:00 to -02:00]

Transition[Overlap at 1964-03-01T00:00-02:00 to -03:00]

Transition[Gap at 1965-01-31T00:00-03:00 to -02:00]

Transition[Overlap at 1965-03-31T00:00-02:00 to -03:00]

Transition[Gap at 1965-12-01T00:00-03:00 to -02:00]

Transition[Overlap at 1966-03-01T00:00-02:00 to -03:00]

Transition[Gap at 1966-11-01T00:00-03:00 to -02:00]

Transition[Overlap at 1967-03-01T00:00-02:00 to -03:00]

Transition[Gap at 1967-11-01T00:00-03:00 to -02:00]

Transition[Overlap at 1968-03-01T00:00-02:00 to -03:00]

Transition[Gap at 1985-11-02T00:00-03:00 to -02:00]

Transition[Overlap at 1986-03-15T00:00-02:00 to -03:00]

Transition[Gap at 1986-10-25T00:00-03:00 to -02:00]

Transition[Overlap at 1987-02-14T00:00-02:00 to -03:00]

Transition[Gap at 1987-10-25T00:00-03:00 to -02:00]

Transition[Overlap at 1988-02-07T00:00-02:00 to -03:00]

Transition[Gap at 1988-10-16T00:00-03:00 to -02:00]

Transition[Overlap at 1989-01-29T00:00-02:00 to -03:00]

Transition[Gap at 1989-10-15T00:00-03:00 to -02:00]

Transition[Overlap at 1990-02-11T00:00-02:00 to -03:00]

Transition[Gap at 1990-10-21T00:00-03:00 to -02:00]

Transition[Overlap at 1991-02-17T00:00-02:00 to -03:00]

Transition[Gap at 1991-10-20T00:00-03:00 to -02:00]

Transition[Overlap at 1992-02-09T00:00-02:00 to -03:00]

Transition[Gap at 1992-10-25T00:00-03:00 to -02:00]

Transition[Overlap at 1993-01-31T00:00-02:00 to -03:00]

Transition[Gap at 1993-10-17T00:00-03:00 to -02:00]

Transition[Overlap at 1994-02-20T00:00-02:00 to -03:00]

Transition[Gap at 1994-10-16T00:00-03:00 to -02:00]

Transition[Overlap at 1995-02-19T00:00-02:00 to -03:00]

Transition[Gap at 1995-10-15T00:00-03:00 to -02:00]

Transition[Overlap at 1996-02-11T00:00-02:00 to -03:00]

Transition[Gap at 1996-10-06T00:00-03:00 to -02:00]

Transition[Overlap at 1997-02-16T00:00-02:00 to -03:00]

Transition[Gap at 1997-10-06T00:00-03:00 to -02:00]

Transition[Overlap at 1998-03-01T00:00-02:00 to -03:00]

Transition[Gap at 1998-10-11T00:00-03:00 to -02:00]

Transition[Overlap at 1999-02-21T00:00-02:00 to -03:00]

Transition[Gap at 1999-10-03T00:00-03:00 to -02:00]

Transition[Overlap at 2000-02-27T00:00-02:00 to -03:00]

Transition[Gap at 2000-10-08T00:00-03:00 to -02:00]

Transition[Overlap at 2001-02-18T00:00-02:00 to -03:00]

Transition[Gap at 2001-10-14T00:00-03:00 to -02:00]

Transition[Overlap at 2002-02-17T00:00-02:00 to -03:00]

Transition[Gap at 2002-11-03T00:00-03:00 to -02:00]

Transition[Overlap at 2003-02-16T00:00-02:00 to -03:00]

Transition[Gap at 2003-10-19T00:00-03:00 to -02:00]

Transition[Overlap at 2004-02-15T00:00-02:00 to -03:00]

Transition[Gap at 2004-11-02T00:00-03:00 to -02:00]

Transition[Overlap at 2005-02-20T00:00-02:00 to -03:00]

Transition[Gap at 2005-10-16T00:00-03:00 to -02:00]

Transition[Overlap at 2006-02-19T00:00-02:00 to -03:00]

Transition[Gap at 2006-11-05T00:00-03:00 to -02:00]

Transition[Overlap at 2007-02-25T00:00-02:00 to -03:00]

Transition[Gap at 2007-10-14T00:00-03:00 to -02:00]

Transition[Overlap at 2008-02-17T00:00-02:00 to -03:00]

Transition[Gap at 2008-10-19T00:00-03:00 to -02:00]

Transition[Overlap at 2009-02-15T00:00-02:00 to -03:00]

Transition[Gap at 2009-10-18T00:00-03:00 to -02:00]

Transition[Overlap at 2010-02-21T00:00-02:00 to -03:00]

Transition[Gap at 2010-10-17T00:00-03:00 to -02:00]

Transition[Overlap at 2011-02-20T00:00-02:00 to -03:00]

Transition[Gap at 2011-10-16T00:00-03:00 to -02:00]

Transition[Overlap at 2012-02-26T00:00-02:00 to -03:00]

Transition[Gap at 2012-10-21T00:00-03:00 to -02:00]

Transition[Overlap at 2013-02-17T00:00-02:00 to -03:00]

Transition[Gap at 2013-10-20T00:00-03:00 to -02:00]

Transition[Overlap at 2014-02-16T00:00-02:00 to -03:00]

Transition[Gap at 2014-10-19T00:00-03:00 to -02:00]

Transition[Overlap at 2015-02-22T00:00-02:00 to -03:00]

Transition[Gap at 2015-10-18T00:00-03:00 to -02:00]

Transition[Overlap at 2016-02-21T00:00-02:00 to -03:00]

Transition[Gap at 2016-10-16T00:00-03:00 to -02:00]

Transition[Overlap at 2017-02-19T00:00-02:00 to -03:00]

Transition[Gap at 2017-10-15T00:00-03:00 to -02:00]

Transition[Overlap at 2018-02-18T00:00-02:00 to -03:00]

Transition[Gap at 2018-11-04T00:00-03:00 to -02:00]

Transition[Overlap at 2019-02-17T00:00-02:00 to -03:00]

Transition[Gap at 2019-11-03T00:00-03:00 to -02:00]

Transition[Overlap at 2020-02-16T00:00-02:00 to -03:00]

Transition[Gap at 2020-11-01T00:00-03:00 to -02:00]

Transition[Overlap at 2021-02-21T00:00-02:00 to -03:00]

Transition[Gap at 2021-11-07T00:00-03:00 to -02:00]

Transition[Overlap at 2022-02-20T00:00-02:00 to -03:00]

Transition[Gap at 2022-11-06T00:00-03:00 to -02:00]

Transition[Overlap at 2023-02-26T00:00-02:00 to -03:00]

Transition[Gap at 2023-11-05T00:00-03:00 to -02:00]

Transition[Overlap at 2024-02-18T00:00-02:00 to -03:00]

Transition[Gap at 2024-11-03T00:00-03:00 to -02:00]

Transition[Overlap at 2025-02-16T00:00-02:00 to -03:00]

Transition[Gap at 2025-11-02T00:00-03:00 to -02:00]

Transition[Overlap at 2026-02-22T00:00-02:00 to -03:00]

Transition[Gap at 2026-11-01T00:00-03:00 to -02:00]

Transition[Overlap at 2027-02-21T00:00-02:00 to -03:00]

Transition[Gap at 2027-11-07T00:00-03:00 to -02:00]

Transition[Overlap at 2028-02-20T00:00-02:00 to -03:00]

Transition[Gap at 2028-11-05T00:00-03:00 to -02:00]

Transition[Overlap at 2029-02-18T00:00-02:00 to -03:00]

Transition[Gap at 2029-11-04T00:00-03:00 to -02:00]

Transition[Overlap at 2030-02-17T00:00-02:00 to -03:00]

Transition[Gap at 2030-11-03T00:00-03:00 to -02:00]

Transition[Overlap at 2031-02-16T00:00-02:00 to -03:00]

Transition[Gap at 2031-11-02T00:00-03:00 to -02:00]

Transition[Overlap at 2032-02-15T00:00-02:00 to -03:00]

Transition[Gap at 2032-11-07T00:00-03:00 to -02:00]

Transition[Overlap at 2033-02-20T00:00-02:00 to -03:00]

Transition[Gap at 2033-11-06T00:00-03:00 to -02:00]

Transition[Overlap at 2034-02-26T00:00-02:00 to -03:00]

Transition[Gap at 2034-11-05T00:00-03:00 to -02:00]

Transition[Overlap at 2035-02-18T00:00-02:00 to -03:00]

Transition[Gap at 2035-11-04T00:00-03:00 to -02:00]

Transition[Overlap at 2036-02-17T00:00-02:00 to -03:00]

Transition[Gap at 2036-11-02T00:00-03:00 to -02:00]

Transition[Overlap at 2037-02-22T00:00-02:00 to -03:00]

Transition[Gap at 2037-11-01T00:00-03:00 to -02:00]

Transition[Overlap at 2038-02-21T00:00-02:00 to -03:00]

Transition[Gap at 2038-11-07T00:00-03:00 to -02:00]

Transition[Overlap at 2039-02-20T00:00-02:00 to -03:00]

Transition[Gap at 2039-11-06T00:00-03:00 to -02:00]

Let's narrow that down to the next expected transition as defined in our tzdata file.

Capture the current moment as seen in UTC, a Instant.

Instant instant = Instant.now() ;

Then ask the rules for the next transition scheduled after that moment. You get a ZoneOffsetTransition object.

ZoneOffsetTransition t = rules.nextTransition( instant );

t.toString(): Transition[Gap at 2020-11-01T00:00-03:00 to -02:00]

Calculate time remaining until the next transition:

Duration d = Duration.between( instant , t.getInstant() ) ;

PT2695H54M20.431322S

See this code run live at IdeOne.com.

like image 45
Basil Bourque Avatar answered Sep 25 '22 14:09

Basil Bourque