Java8 equivalent of Joda ISODateTimeFormat.dateTimeParser ()?

I can't figure out how to make Java8 DateTime parsing behave like the equivalent of Joda, which I'm trying to replace. The problem is that Joda ISODateTimeFormat.dateTimeParser(); allowed me to enter only YYYY, and it will still work (for example, 2016 2016-01-01T00: 00: 00.000Z). How can I get the same behavior from Java8

The code is quite simple ...

 import java.time.OffsetDateTime; import java.time.temporal.ChronoField; import org.joda.time.DateTime; import org.joda.time.format.DateTimeFormatter; import org.joda.time.format.ISODateTimeFormat; public class Java8OffsetDateTime { public static void main(String[] args) { String[] candidates = { "2016-11-21T17:54:51.841Z", "2016-11-21T09:54:51.841-08:00", "2016", // Java8 no can do? "2016-11", // Java8 no can do? "2016-11-21", // Java8 no can do? "2016-11-21T01", // Java8 no can do? "2016-11-21T01:02", // Java8 no can do? "2016-11-21T01:02:03" // Java8 no can do? }; DateTimeFormatter JodaDateTimeFormatter = ISODateTimeFormat.dateTimeParser(); for (String candidate : candidates) { System.out.println("\ncandidate:\t\"" + candidate + "\""); DateTime jodaDateTime = JodaDateTimeFormatter.parseDateTime(candidate); System.out.println("Joda:\t" + jodaDateTime); try { OffsetDateTime java8OffsetDateTime = OffsetDateTime.parse(candidate); System.out.println("Java8:\t" + java8OffsetDateTime); long jodaMillis = jodaDateTime.getMillis(); long javaMillis = java8OffsetDateTime.toInstant().toEpochMilli(); System.out.printf("jodaMillis:%d %s javaMillis:%d\n", jodaMillis, (jodaMillis==javaMillis) ? "==" : "!=", javaMillis); } catch (Exception e) { e.printStackTrace(); } } } } 

Results are a challenge ...

 $ java -cp ~/work/joda-time-2.9.6/joda-time-2.9.6.jar:. Java8OffsetDateTime candidate: "2016-11-21T17:54:51.841Z" Joda: 2016-11-21T09:54:51.841-08:00 Java8: 2016-11-21T17:54:51.841Z jodaMillis:1479750891841 == javaMillis:1479750891841 candidate: "2016-11-21T09:54:51.841-08:00" Joda: 2016-11-21T09:54:51.841-08:00 Java8: 2016-11-21T09:54:51.841-08:00 jodaMillis:1479750891841 == javaMillis:1479750891841 candidate: "2016" Joda: 2016-01-01T00:00:00.000-08:00 java.time.format.DateTimeParseException: Text '2016' could not be parsed at index 4 at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1947) at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1849) at java.time.OffsetDateTime.parse(OffsetDateTime.java:402) at java.time.OffsetDateTime.parse(OffsetDateTime.java:387) at Java8OffsetDateTime.main(Java8OffsetDateTime.java:26) candidate: "2016-11" Joda: 2016-11-01T00:00:00.000-07:00 java.time.format.DateTimeParseException: Text '2016-11' could not be parsed at index 7 at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1947) at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1849) at java.time.OffsetDateTime.parse(OffsetDateTime.java:402) at java.time.OffsetDateTime.parse(OffsetDateTime.java:387) at Java8OffsetDateTime.main(Java8OffsetDateTime.java:26) candidate: "2016-11-21" Joda: 2016-11-21T00:00:00.000-08:00 java.time.format.DateTimeParseException: Text '2016-11-21' could not be parsed at index 10 at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1947) at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1849) at java.time.OffsetDateTime.parse(OffsetDateTime.java:402) at java.time.OffsetDateTime.parse(OffsetDateTime.java:387) at Java8OffsetDateTime.main(Java8OffsetDateTime.java:26) candidate: "2016-11-21T01" Joda: 2016-11-21T01:00:00.000-08:00 java.time.format.DateTimeParseException: Text '2016-11-21T01' could not be parsed at index 13 at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1947) at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1849) at java.time.OffsetDateTime.parse(OffsetDateTime.java:402) at java.time.OffsetDateTime.parse(OffsetDateTime.java:387) at Java8OffsetDateTime.main(Java8OffsetDateTime.java:26) candidate: "2016-11-21T01:02" Joda: 2016-11-21T01:02:00.000-08:00 java.time.format.DateTimeParseException: Text '2016-11-21T01:02' could not be parsed at index 16 at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1947) at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1849) at java.time.OffsetDateTime.parse(OffsetDateTime.java:402) at java.time.OffsetDateTime.parse(OffsetDateTime.java:387) at Java8OffsetDateTime.main(Java8OffsetDateTime.java:26) candidate: "2016-11-21T01:02:03" Joda: 2016-11-21T01:02:03.000-08:00 java.time.format.DateTimeParseException: Text '2016-11-21T01:02:03' could not be parsed at index 19 at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1947) at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1849) at java.time.OffsetDateTime.parse(OffsetDateTime.java:402) at java.time.OffsetDateTime.parse(OffsetDateTime.java:387) at Java8OffsetDateTime.main(Java8OffsetDateTime.java:26) 

How do I get rid of these java.time.format.DateTimeParseException from "Java8 no can can?" cases?

+7
java java-8 jodatime
source share
3 answers

Thanks @Tunaki for suggesting alternative syntax. This will help you parse the values ​​you entered. Set accordingly.

 OffsetDateTime java8OffsetDateTime = OffsetDateTime.parse(candidate, offsetDateTimeFormatter ); DateTimeFormatter customOffsetDateTimeFormatter = new DateTimeFormatterBuilder().appendPattern("yyyy[-MM][-dd['T'HH[:mm[:ss]]]][.SSSXXX]") .parseDefaulting(ChronoField.MONTH_OF_YEAR, 1) .parseDefaulting(ChronoField.DAY_OF_MONTH, 1) .parseDefaulting(ChronoField.HOUR_OF_DAY, 0) .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0) .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0) .parseDefaulting(ChronoField.NANO_OF_SECOND, 0) .parseDefaulting(ChronoField.OFFSET_SECONDS, ZoneOffset.of("-08:00").getTotalSeconds()) .toFormatter(); 

Test case: (- 06:00 Offset)

 import java.time.OffsetDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; import java.time.temporal.ChronoField; public class App { public static void main(String[] args) { String[] candidates = {"2016-11-21T15:54:51.841Z", "2016-11-21T09:54:51.841-06:00", "2016", // Java8 no can do? "2016-11", // Java8 no can do? "2016-11-21", // Java8 no can do? "2016-11-21T01", // Java8 no can do? "2016-11-21T01:02", // Java8 no can do? "2016-11-21T01:02:03" // Java8 no can do?*/ }; DateTimeFormatter customOffsetDateTimeFormatter = new DateTimeFormatterBuilder().appendPattern("yyyy[-MM][-dd['T'HH[:mm[:ss]]]][.SSSXXX]") .parseDefaulting(ChronoField.MONTH_OF_YEAR, 1) .parseDefaulting(ChronoField.DAY_OF_MONTH, 1) .parseDefaulting(ChronoField.HOUR_OF_DAY, 0) .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0) .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0) .parseDefaulting(ChronoField.NANO_OF_SECOND, 0) .parseDefaulting(ChronoField.OFFSET_SECONDS, ZoneOffset.of("-06:00").getTotalSeconds()) .toFormatter(); org.joda.time.format.DateTimeFormatter jodaDateTimeFormatter = ISODateTimeFormat.dateTimeParser(); for (String candidate : candidates) { System.out.println("\ncandidate:\t\"" + candidate + "\""); DateTime jodaDateTime = jodaDateTimeFormatter.parseDateTime(candidate); System.out.println("Joda:\t" + jodaDateTime); try { OffsetDateTime java8OffsetDateTime = OffsetDateTime.parse(candidate,customOffsetDateTimeFormatter); System.out.println("Java8:\t" + java8OffsetDateTime); long jodaMillis = jodaDateTime.getMillis(); long javaMillis = java8OffsetDateTime.toInstant().toEpochMilli(); System.out.printf("jodaMillis:%d %s javaMillis:%d\n", jodaMillis, (jodaMillis == javaMillis) ? "==" : "!=", javaMillis); } catch (Exception e) { e.printStackTrace(); } } } 

Exit: (- 06:00 Offset)

  candidate: "2016-11-21T15:54:51.841Z" Joda: 2016-11-21T09:54:51.841-06:00 Java8: 2016-11-21T15:54:51.841Z jodaMillis:1479743691841 == javaMillis:1479743691841 candidate: "2016-11-21T09:54:51.841-06:00" Joda: 2016-11-21T09:54:51.841-06:00 Java8: 2016-11-21T09:54:51.841-06:00 jodaMillis:1479743691841 == javaMillis:1479743691841 candidate: "2016" Joda: 2016-01-01T00:00:00.000-06:00 Java8: 2016-01-01T00:00-06:00 jodaMillis:1451628000000 == javaMillis:1451628000000 candidate: "2016-11" Joda: 2016-11-01T00:00:00.000-05:00 Java8: 2016-11-01T00:00-06:00 jodaMillis:1477976400000 != javaMillis:1477980000000 candidate: "2016-11-21" Joda: 2016-11-21T00:00:00.000-06:00 Java8: 2016-11-21T00:00-06:00 jodaMillis:1479708000000 == javaMillis:1479708000000 candidate: "2016-11-21T01" Joda: 2016-11-21T01:00:00.000-06:00 Java8: 2016-11-21T01:00-06:00 jodaMillis:1479711600000 == javaMillis:1479711600000 candidate: "2016-11-21T01:02" Joda: 2016-11-21T01:02:00.000-06:00 Java8: 2016-11-21T01:02-06:00 jodaMillis:1479711720000 == javaMillis:1479711720000 candidate: "2016-11-21T01:02:03" Joda: 2016-11-21T01:02:03.000-06:00 Java8: 2016-11-21T01:02:03-06:00 jodaMillis:1479711723000 == javaMillis:1479711723000 
+3
source share

This will analyze all your dates, with the exception of a few funky 2016-11-21T01 . If you really need to, see how DateTimeFormatterBuilder creates the ISO_TIME format. It uses an optional seconds field. Copy it and make the minutes field extra.

 DateTimeFormatter isoDateParser = new DateTimeFormatterBuilder() .parseCaseInsensitive() .append(DateTimeFormatter.ISO_LOCAL_DATE) .optionalStart() .appendLiteral('T') .append(DateTimeFormatter.ISO_TIME) .toFormatter(); 
+2
source share

DateTimeFormatter is your class. However, this new java.time package takes some time. I worked with him, and after a while I found him very flexible and powerful. I wrote a short article in which I described the general idea of ​​how to try to parse an unknown format string for a date. Here is the link: Java 8 java.time package: parsing any string to date

+2
source share

All Articles