简体   繁体   中英

What Date time format can be used to handle DST in Java

Our client sends us a start and end date-time in a text file as a String in the below format

2019-10-07 11:07 AM

All date-time is in one timezone. We calculate the difference between the start and end date-time to calculate the hours worked. The hours worked calculation goes wrong when the transition of daylight savings time happens. They are not sending enough information for us to calculate correctly.

I am about to recommend that they send us more information so that we can address this issue. What is a good solution here? What date-time format should we recommend to them that will help us address the DST change and calculate hours worked correctly.

We use Java.

Getting it right is not obvious

They are telling you their local time, and you can infer the time zone (because "all date is in one time zone").

The basic calculation looks like this:

ZoneId pacific = ZoneId.of("America/Los_Angeles");
DateTimeFormatter local = DateTimeFormatter.ofPattern("uuuu-MM-dd hh:mm a").withZone(pacific);
ZonedDateTime start = ZonedDateTime.parse("2022-11-06 01:30 AM", local);
ZonedDateTime until = ZonedDateTime.parse("2022-11-07 01:30 AM", local);
long hours = start.until(until, ChronoUnit.HOURS);
System.out.printf("%d hours elapsed%n", hours);

This prints " 25 hours elapsed." In the Pacific time zone, November 6, 2022, is 25 hours long, because when daylight saving ends in the autumn, the clock is set back one hour. If someone tells you it's 1:00 AM, you don't know if midnight was one hour ago or two.

The default offset heuristic

What you really need is the offset, and you have to rely on some heuristic for that. By default, ZonedDateTime chooses one instant from multiple ambiguous local date-times by selecting the earliest offset (the "summer" offset).

Specifying the offset

If that's not what you want, you can override the offset explicitly. For example, maybe you process these time stamps close to real-time, and you can guess what the offset should be based on the current time. Or maybe you know that these local time stamps are always processed in chronological order; by tracking the latest time you've seen, and noting if an earlier time stamp follows, you can detect the clock set back and change the offset.

The ZonedDateTime.ofLocal() and ZonedDateTime.ofStrict() functions can be used to explicitly control the offset.

OffsetDateTime

Alternatively, you might request that they include the offset in the timestamp string. Usually this would be indicated with a signed number of hours and minutes: "-07:00" or "-0800". This will provide unambiguous interpretation of times during DST transitions.


Here is an example using OffsetDateTime . First, if the offset uses a colon, as in "2019-10-07T11:07:00+01:00", it is a standard format, and can be parsed like this:

OffsetDateTime start = OffsetDateTime.parse("2019-10-07T11:07:00+01:00");

If the colon is missing, you need a formatter to handle the non-standard input:

DateTimeFormatter odt = new DateTimeFormatterBuilder()
    .append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
    .appendOffsetId()
    .toFormatter();
OffsetDateTime when = OffsetDateTime.parse("2019-10-07T11:07:00+01:00", odt);

From there, the calculation is the same as with ZonedDateTime :

OffsetDateTime start = OffsetDateTime.parse("2022-11-06T01:00:00-07:00", odt);
OffsetDateTime until = OffsetDateTime.parse("2022-11-07T01:54:00-08:00", odt);
long hours = start.until(until, ChronoUnit.HOURS);
System.out.printf("%d complete hours elapsed.%n", hours);
Duration duration = Duration.between(start, until);
System.out.println("Full duration: " + duration);

This is simple task. The DateTimeFormatter class gives you all the info you need. 2019-10-07 11:07 AM Your format would be 'yyyy-MM-dd hh:mm a' and you should use LocalDateTime class. But since you need to take into account daylight savings time then you might want to use classes ZonedDateTime or OffsetDateTime and provide your timezone. It might be an overkill, but I once worked on the project where I needed to parse Strings to Dates without knowing the format in advance. So, here is the article I wrote on how to do that: Java 8 java.time package: parsing any string to date

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM