Java 8 - tz database time zones

date, datetime, java, java-8, timezone

Solution

Time zones are frequently redefined by politicians. New zones appear. Old ones get renamed (ex: `Asia/Kolkata`). Some are determined to not actually be distinct, and end up pointing to another (ex: `America/Montreal`). And that is just the names – the offsets within each zone are also often modified by politicians for anomalies such as Daylight Saving Time (DST), or deciding to get off DST altogether or deciding to stay on DST all-year-round or deciding to change the offset by 15 minutes to make some political statement such as distinguishing yourself from your neighboring countries. So there is no simple permanent list.

Java comes with a copy of the tzdata time zone database. If any zones you care about experience a change, you need to update this tzdata in your Java installations. Oracle provides a tool for this chore in their implementation; I do not know about others. Similarly you should also update the tzdata in your host computer’s OS as well as other utilities such as your database like Postgres.

As for references to a `ZoneId` object in Java, you may define some as constants. The java.time classes are thread-safe. So you may keep a single instance around as a constant.

public class TimeUtils {
    static public ZoneId ZONEID_EUROPE_PARIS = ZoneId.of( "Europe/Paris" ) ;
    static public ZoneId ZONEID_ASIA_KOLKATA = ZoneId.of( "Asia/Kolkata" ) ;
}

You have a `LocalDateTime` representing potential moments, not a specific point on the timeline. A `LocalDateTime` has no time zone or offset information. So a `LocalDateTime` of noon June 1 this year could mean many different moments, with the first noon happening in Kiribati where the time zone has an offset fourteen hours ahead of UTC. Noon in Bangladesh comes later, and noon in Paris France still hours later. So a `LocalDateTime` has no real meaning until you apply a time zone for context.

LocalDateTime noon1June2017Anywhere = LocalDateTime.of( 2017 , Month.JUNE , 1 , 12 , 0);

Use those constants where you need a `ZoneId`.

ZonedDateTime noon1June2017EuropeParis = noon1June2017Anywhere.atZone( TimeUtils.ZONEID_EUROPE_PARIS ) ;
ZonedDateTime noon1June2017AsiaKolkata = noon1June2017Anywhere.atZone( TimeUtils.ZONEID_ASIA_KOLKATA ) ;

Note that `noon1June2017EuropeParis` and `noon1June2017AsiaKolkata` are two different moments, different points on the timeline. Noon happens much earlier in India than it does in France.

Let's see those two values in UTC as `Instant` objects. These two `Instant` objects are not equal, as the Kolkata one is several hours earlier than the Paris one.

Instant instantNoon1June2017EuropeParis = noon1June2017EuropeParis.toInstant() ;  // Extract the same moment but in UTC zone.
Instant instantNoon1June2017AsiaKolkata = noon1June2017AsiaKolkata.toInstant() ; // Extract the same moment but in UTC zone.

Externalize

If the intent of your Question is to externalize the decision of what zone to apply, so that you may change that choice without recompiling your source code again, simply store a string of the zone name such as `Europe/Paris` as a string in some external resource.

Pass your string to `ZoneId.of`.

ZoneId z = ZoneId.of( someStringOfZoneName ) ;

Possible storage mechanisms commonly used by folks:

- Store the text in a file.

- Store the text in a database row to retrieved by your app.

- Store the text as an entry in a JNDI facility (LDAP server, a configuration file in your Servlet container, etc.) (see Tutorial)

- Query from a Web Service. (See Tutorial)

- Ask the user for their preference and store in a variable such as a member of a class, or in a Servlet environment store string as an attribute on the context object or on the session object. You can provide the user with a choice list of all zones by calling `ZoneId.getAvailableZoneIds`.

You can ask for the JVM’s current default zone: `ZoneId.systemDefault`. But beware, this can be changed at anytime by any code in any app in that JVM.

Problem

I have to work with Java 8 dates / times in different time zones. For instance: ``` LocalDateTime dateTime = LocalDateTime.of(2017, Month.JUNE, 1, 13, 39); Instant instant = dateTime.atZone(ZoneId.of("Europe/Paris")).toInstant(); ``` and a Time Frame is an instance between to dateTimes But I don't want to hardcode the Time Zone, that is always a bad practice I couldn't find any constants in the Java API to represent the diffenent Time Zones like https://en.m.wikipedia.org/wiki/List_of_tz_database_time_zones Is there any mapping as it was in the short zone IDs ???? https://docs.oracle.com/javase/8/docs/api/java/time/ZoneId.html#of-java.lang.String-java.util.Map-

Original source