Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java.time DateTimeFormatter pattern for timezone offset

Tags:

I am trying to parse: 2014-05-02-10.45.05.993280-5:00 where the -5:00 is the offset from UTC. Using a java.time DateTimeFormatter in Java 8.

For the first bit I have the following: yyyy-MM-dd-HH.mm.ss.SSSSSS however, I can't figure out what the pattern should be to parse the offset also.

If I had the offset with 4 digits (-05:00) I could use: yyyy-MM-dd-HH.mm.ss.SSSSSSxxx, but this doesn't work for 3 digits.

Any ideas?

like image 338
Cheetah Avatar asked Jun 08 '15 13:06

Cheetah


People also ask

How do I change the TimeZone on DateTimeFormatter?

The LocalDateTime API gives the possibility to add the TimeZone Name by using the key "z" in the formatter.

What is the Java time format DateTimeFormatter?

DateTimeFormatter is used as a Formatter for printing and parsing date-time objects. DateTimeFormatterBuilder allows a DateTimeFormatter to be created. It is used for constructing formatters which are then used to print or parse.

What is offset in TimeZone in Java?

The OffsetTime class, in effect, combines the LocalTime class with the ZoneOffset class. It is used to represent time (hour, minute, second, nanosecond) with an offset from Greenwich/UTC time (+/-hours:minutes, such as +06:00 or -08:00).

Is Java time DateTimeFormatter thread-safe?

A formatter created from a pattern can be used as many times as necessary, it is immutable and is thread-safe. The count of pattern letters determines the format.


1 Answers

Use capital letter X instead of x, hence XXX. The difference is that big X can recognize the input letter "Z" as UTC-Offset +00:00 while small pattern letter X cannot.

Suggested pattern:

yyyy-MM-dd-HH.mm.ss.SSSSSSXXX 

Please be also aware of following JDK-bug:

java.time.format.DateTimeFormatter cannot parse an offset with single digit hour

UPDATE:

I have now tested the described workaround in the bug-log.

String input = "2014-05-02-10.45.05.993280-5:00"; DateTimeFormatter f = new DateTimeFormatterBuilder()         .appendPattern("yyyy-MM-dd-HH.mm.ss.SSSSSS")         .parseLenient()         .appendOffset("+HH:MM", "Z")         .toFormatter(); System.out.println(f.parse(input, ZonedDateTime::from)); 

But it throws an exception:

Exception in thread "main" java.time.format.DateTimeParseException: Text '2014-05-02-10.45.05.993280-5:00' could not be parsed at index 26 at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1947) at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1849) at HelloWorld.main(HelloWorld.java:16)

So lenient parsing does not help either. So there are now only three options left for you:

  • Use workaround suggested by bug reporter: [...] workaround is to parse the date/time separately, use a hand coded parser for the offset and combine the LocalDateTime with the hand parsed offset. Not an easy work around.

  • Try your own specialized string preprocessing. If you have a fixed format then you can try to insert the zero-digit at position 26 (if the total input length is one digit too small).

  • Or you use an external library which can do this. My library Time4J (v4.0) can do that if you are willing to add an extra dependency. See this code:

String input = "2014-05-02-10.45.05.993280-5:00"; ZonalDateTime zdt =     ZonalDateTime.parse(         input,         Moment.localFormatter("yyyy-MM-dd-HH.mm.ss.SSSSSSXXX", PatternType.CLDR)); System.out.println(zdt); // 2014-05-02T10:45:05,993280UTC-05:00 ZonedDateTime result = zdt.toTemporalAccessor(); 

Update: According to JDK-bug-status, the bug has been fixed for Java-9, but a backport for Java-8 does not seem to be available though.

like image 92
Meno Hochschild Avatar answered Sep 22 '22 11:09

Meno Hochschild