Java8 相当于 Joda 的 ISODateTimeFormat.dateTimeParser()?

标签 java java-8 jodatime

我不知道如何让 Java8 的 DateTime 解析表现得像我试图替换的 Joda 等价物。问题是 Joda 的 ISODateTimeFormat.dateTimeParser(); 允许我输入尽可能少的 YYYY 并且它仍然有效(例如,2016 年将变为 2016-01-01T00:00:00.000Z”) . 我怎样才能从 Java8 获得同样的行为?

代码很简单...

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();
      }
    }
  }
}

结果就是挑战...

$ 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)

如何摆脱“Java8 不行?”中的那些 java.time.format.DateTimeParseException案例?

最佳答案

感谢@Tunaki 建议替代语法。这将帮助您解析您提供的输入值。相应调整。

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();

测试用例:(-06:00 偏移量)

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();
        }
    }
}  

输出:(-06:00 偏移量)

    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

关于Java8 相当于 Joda 的 ISODateTimeFormat.dateTimeParser()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40727884/

相关文章:

java - 为什么在 Java 1.8 中使用 Function<V,R> 而不是 Function<R,V>?

java - 如何在 java 中获取两个日期之间的日期列表?如何包括/排除开始日期/结束日期?

java - Spring中继承@Component

java - 在特定条件下循环调用另一个 Java GUI 程序

Java 8 : Generic type inference improvements

java - Calendar.getTime() 返回不同的 Date 对象

java - 如何从 Java 中的任何字符串中提取日期时间模式?

java - 从排序流中获取拆分器会引发异常

Javafx更改组件的对齐方式

compiler-errors - 播放框架 2.2 : How to access model private field in temlate