Search code examples
javadatetimetimezonedatetime-conversionjava-time

Throw exception in case of ambiguous date-time for a timezone?


Using the java.time package:

I am converting a user-input of freely inserted date-time (year, month, day, hour, minute) to a LocalDateTime and then, according to the timezone of the user, to a ZonedDateTime.

Example for Estonia:

LocalDateTime local = LocalDateTime.of(2018, 10, 28, 3, 30); // October 28th 03:30
ZonedDateTime zoned = local.atZone(ZoneId.of("Europe/Tallinn"));

The above time 03:30 can mean two instances on a time-line, because on 28 Oct 2018 the Daylight Saving Time in Estonia ended. At 04:00 GMT+3 the clocks were changed to 03:00 GMT+2, which means the time 03:30 was reached twice that day. According to the documentation of atZone(), the resulting time of the conversion is the summer-time 03:30 GMT+3 (emphasis mine):

In most cases, there is only one valid offset for a local date-time. In the case of an overlap, where clocks are set back, there are two valid offsets. This method uses the earlier offset typically corresponding to "summer".

What I would like is for this conversion not to be carried out implicitly. Instead, I would like to catch an exception and inform the user about the ambiguous input. There seems to be a method for doing this, but what I do not understand is why the method is static and accepts three arguments. How to use it correctly for my case? From the same documentation:

To throw an exception when there is a gap or overlap, use ZonedDateTime.ofStrict(LocalDateTime, ZoneOffset, ZoneId).

Why does it ask for a ZoneOffset argument? It seems to me all I would need is a LocalDateTime and ZoneId. Otherwise, each time I convert to ZonedDateTime, how do I know whether to use the offset of GMT+2 or GMT+3? This is something I want Java to tell me or throw an exception if both are applicable.


Solution

  • I have found the answer and flagged my own question as a duplicate.

    ZoneId zoneId = ZoneId.of("America/Chicago");
    LocalDateTime ldt = LocalDateTime.of(2017, 3, 12, 2, 39, 0, 0);
    ZoneOffset zoneOffset = zoneId.getRules().getOffset(ldt);
    ZonedDateTime zdt = ZonedDateTime.ofStrict(ldt, zoneOffset, zoneId);
    

    would throw

    Exception in thread "main" java.time.DateTimeException: LocalDateTime '2017-03-12T02:39' does not exist in zone 'America/Chicago' due to a gap in the local time-line, typically caused by daylight savings
        at java.time.ZonedDateTime.ofStrict(ZonedDateTime.java:484)