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?
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.