Confusion with Java UTC Time Analysis

I got confused in time during java. I have worked for so long under the assumption that if the timestamp is specified as zulu time, java will take care of the offset relative to local time.

To illustrate. I am currently in BST, which has a UTC +1 offset. With that in mind, I would expect this Zulu time:

2016-09-12T13:15:17.309Z 

be

 2016-09-12T14:15:17.309 

LocalDateTime after parsing it. This is because my system time is set to BST by default, and the above timestamp (zulu time) indicates that this is UTC time.

Instead, consider this sample:

  String ts = "2016-09-12T13:15:17.309Z"; LocalDateTime parse = LocalDateTime.parse(ts, DateTimeFormatter.ISO_DATE_TIME); System.out.println(parse); 

This will print:

 2016-09-12T13:15:17.309 

Thus, the timestamp parsed as LocalDateTime is not recognized as UTC and instead is treated as local time directly. So I thought, maybe I need to parse it as ZonedDateTime and convert it to LocalDateTime specifically in order to get the correct local time. With this test:

  String ts = "2016-09-12T13:15:17.309Z"; ZonedDateTime parse = ZonedDateTime.parse(ts, DateTimeFormatter.ISO_DATE_TIME); System.out.println(parse); System.out.println(parse.toLocalDateTime()); 

I get the outputs:

 2016-09-12T13:15:17.309Z 2016-09-12T13:15:17.309 

The same conclusion for both dates.

The only way to correctly parse this that I could find is:

  String ts = "2016-09-12T13:15:17.309Z"; Instant instant = Instant.parse(ts); // parses UTC LocalDateTime ofInstant = LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); System.out.println(instant); System.out.println(ofInstant); 

Fingerprints:

 2016-09-12T13:15:17.309Z 2016-09-12T14:15:17.309 

It is right.

So the question (s):

  • Should Java time not recognize the UTC timestamp and analyze it for the correct system default setting?
  • How can I use the LocalDateTime#parse approach to get the correct result?
  • Should I use Instant for everyone now and give up parsing?

The problem is that jersey/jackson java time modules parse timestamps using the ISO format and the usual LocalDateTime#parse methods. I realized that my times do not pass, since they are considered as LocalTime , while in reality they are in Zulu time.

+5
source share
2 answers

You misunderstand the purpose of LocalDateTime .

To quote class documentation:

Date-time without a time zone in the ISO-8601 calendar system, for example {@code 2007-12-03T10: 15:30}.

...

This class does not store or represent a time zone. Instead, it is a description of the date used for birthdays, combined with local time, as shown on the wall clock. It cannot represent a point in time on a line without additional information, such as an offset or time zone.

Thus, the explicit goal is to simply represent the date and time without a time zone. It is not intended to represent the date and time in the local time zone.

Therefore, each conversion simply breaks the time zone.

So, for your purposes, you need ZonedDateTime with ZoneId.systemDefault() , as you already used in your third example.

For your second example, this could be:

 String ts = "2016-09-12T13:15:17.309Z"; ZonedDateTime parse = ZonedDateTime.parse(ts, DateTimeFormatter.ISO_DATE_TIME) .withZoneSameInstant(ZoneId.systemDefault()); System.out.println(parse); System.out.println(parse.toLocalDateTime()); 
+5
source

TL; DR

Example:

 Instant.parse( "2016-09-12T13:15:17.309Z" ) .atZone( ZoneId.of( "Europe/London" ) ) .toString(); 

2016-09-12T14: 15: 17,309 + 01: 00 [Europe / London]

Launch at IdeOne.com .

More details

The answer to this question is Krüske . You misunderstand the value of the LocalDateTime class. It does not represent the date-time of a specific location. Quite the contrary, this does not represent the actual moment at all.

I suggest thinking of Instant as your main building block class in java.time. The Instant class represents a moment on the UTC timeline with a nanosecond resolution (up to nine (9) decimal digits).

Your input string complies with the ISO 8601 standard used by default in the Instant class for parsing and generating string representations. Z at the end is short for Zulu and means UTC. There is no need to specify a formatting template.

 Instant instant = Instant.parse( "2016-09-12T13:15:17.309Z" ); 

As a programmer, you must learn to think and work in UTC first. Forget about your time zone. Think of UTC as the only true time. The use of time zone as an option and only as necessary.

Specify the time zone name in continent/region format, such as America/Montreal , Africa/Casablanca or Pacific/Auckland . Never use the abbreviation 3-4 letters, for example BST or EST or IST , as they are not real time zones, and are not standardized and not even unique (!). If you meant British Daylight Saving Time on BST , then the actual time zone name would be Europe/London . The java.time classes will determine how to configure any anomalies, including daylight saving time (DST).

 ZoneId z = ZoneId.of( "Europe/London" ); ZonedDateTime zdt = instant.atZone( z ); 

About java.time

The java.time framework is built into Java 8 and later. These classes supersede the nasty old legacy time classes such as java.util.Date , Calendar and SimpleDateFormat .

The Joda-Time project, now in maintenance mode , advises switching to java.time.

To learn more, see the Oracle Tutorial . And search for qaru for many examples and explanations. JSR 310 specification .

Where to get java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is proof of possible future additions to java.time. Here you can find useful classes such as Interval , YearWeek , YearQuarter and more .

+3
source

All Articles