2

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-

La Carbonell
  • 1,976
  • 5
  • 22
  • 52
  • 1
    Could you please give an example what you want to achieve. – SubOptimal Jun 16 '17 at 07:41
  • What is `dateTime` in your example code? – Basil Bourque Jun 16 '17 at 07:45
  • 1
    You Question does not make sense as written. The best practice is to do most everything in [UTC](https://en.wikipedia.org/wiki/Coordinated_Universal_Time): your logging, your business logic, your data storage, and your data exchange/serialization. Use a time zone only where required by the business problem or for presentation to a user. The basic java.time class for a UTC value is `Instant` as in `Instant.now()`. I believe we covered this extensively in your other recent Questions. – Basil Bourque Jun 16 '17 at 07:47
  • I need to generate alarms based in Time Frames in different counties (different Time Zones) – La Carbonell Jun 16 '17 at 07:49
  • What is “Time Frames”? Also, edit your Question with additional information or clarifications rather than posting as Comments. – Basil Bourque Jun 16 '17 at 07:49
  • a period of time, especially a specified period in which something occurs or is planned to take place. – La Carbonell Jun 16 '17 at 07:50
  • You need to explain more in Question. Give examples of inputs and expected outputs/results. Also, search Stack Overflow thoroughly before posting here. Most every basic date-time issue has already been asked and answered. It would be rude to post before studying the existing Q&A on Stack Overflow. – Basil Bourque Jun 16 '17 at 07:52
  • Are you asking for alarms to go off every 3 hours? Or alarms to go off at a certain time of day? Or alarms to go off only after a certain amount of time has elapsed from now? – Basil Bourque Jun 16 '17 at 07:59
  • I repeat my question in earlier comment: What *exactly* is `dateTime` in your example code? What is the class of that object? – Basil Bourque Jun 16 '17 at 08:03
  • 3
    If you want to have the time according to the timezone of `Europe/Paris`, it doesn’t matter whether you refer to it as `"Europe/Paris"` or `"FR"` or `ConstantHoldingClass.EUROPE_PARIS` or `ConstantHoldingClass.FR`. That’s *all* “hardcoded”. If you “don’t want to hardcode the time zone”, you have to make it a parameter or configuration option of *your* program. (unless you want to use `systemDefault()`, which is already an environmental option)… – Holger Jun 16 '17 at 08:28
  • 2
    One idea is to put `Europe/Paris` in a properties file that your application reads in startup or the first time it needs a time zone. Whether it’s a good idea for you depends on things like your requirements, architecture and development cycle. Variations include putting it in a database table. – Ole V.V. Jun 16 '17 at 09:43

1 Answers1

13

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.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154