Java joda time ISODateTimeFormat.dateTime()行为不正常

Java joda time ISODateTimeFormat.dateTime()行为不正常,java,datetime,parsing,jodatime,datetime-format,Java,Datetime,Parsing,Jodatime,Datetime Format,应该是宽容和灵活的。例如,毫秒是可选的,日期是可选的,时区是可选的,时区可以是Z或+/-HH[:MM] 但事实并非如此。我错过了什么 使用版本joda时间:2.9.9(也尝试了2.10.8,结果相同) 输出: 2020-11-22T01:59:59.001+00:00 -- 2020-11-22T01:59:59.001Z 2020-11-22T01:59:59.001Z -- 2020-11-22T01:59:59.001Z 2020-11-22T01:59:59+00:00

应该是宽容和灵活的。例如,毫秒是可选的,日期是可选的,时区是可选的,时区可以是
Z
+/-HH[:MM]

但事实并非如此。我错过了什么

使用版本
joda时间:2.9.9
(也尝试了
2.10.8
,结果相同)

输出:

2020-11-22T01:59:59.001+00:00  -- 2020-11-22T01:59:59.001Z
2020-11-22T01:59:59.001Z       -- 2020-11-22T01:59:59.001Z
2020-11-22T01:59:59+00:00      -- Invalid format: "2020-11-22T01:59:59+00:00" is malformed at "+00:00"
2020-11-22T01:59:59Z           -- Invalid format: "2020-11-22T01:59:59Z" is malformed at "Z"
01:59:59.000                   -- Invalid format: "01:59:59.000" is malformed at ":59:59.000"
:

java.time 正如Abra在一篇评论中所建议的,您可能希望遵循官方的Joda时间建议,转而使用java.Time,即现代的java日期和时间API

下面的内容不会给您提供Joda时间解析器的全部灵活性,但它会解析您的五个示例字符串。你可以进一步调整它,以适应你可能有的任何进一步的需求

    ZoneOffset defaultOffset = ZoneOffset.UTC; // Configurable
    LocalDate defaultDate = LocalDate.now(ZoneId.systemDefault());
    
    DateTimeFormatter flexibleFormatter = new DateTimeFormatterBuilder()
            .optionalStart()
            .append(DateTimeFormatter.ISO_LOCAL_DATE)
            .appendLiteral('T')
            .optionalEnd()
            .parseDefaulting(ChronoField.YEAR, defaultDate.getYear())
            .parseDefaulting(ChronoField.MONTH_OF_YEAR, defaultDate.getMonthValue())
            .parseDefaulting(ChronoField.DAY_OF_MONTH, defaultDate.getDayOfMonth())
            .append(DateTimeFormatter.ISO_LOCAL_TIME)
            .optionalStart()
            .appendOffsetId()
            .optionalEnd()
            .parseDefaulting(ChronoField.OFFSET_SECONDS, defaultOffset.getTotalSeconds())
            .toFormatter();

    Arrays.asList("2020-11-22T01:59:59.001+00:00", "2020-11-22T01:59:59.001Z", "2020-11-22T01:59:59+00:00",
            "2020-11-22T01:59:59Z", "01:59:59").forEach(s -> {
            try {
                System.out.println(String.format("%-30s -- %s", s, OffsetDateTime.parse(s, flexibleFormatter)));
            } catch (DateTimeParseException dtpe) {
                System.out.println(String.format("%-30s -- %s", s, dtpe.getMessage()));
            }
        });     
我刚才在欧洲/哥本哈根时区跑步时的输出:

从Joda Time主页:

请注意,Joda Time被认为是一个基本上已“完成”的项目。 没有计划进行重大改进。如果使用JavaSE8,请迁移 到
java.time
(JSR-310)

你的代码出了什么问题? jensgram在评论中说:


您正在为
dateTimeParser
链接文档,但调用
dateTime()

链接
  • 解释如何使用java.time
java.time 正如Abra在一篇评论中所建议的,您可能希望遵循官方的Joda时间建议,转而使用java.Time,即现代的java日期和时间API

下面的内容不会给您提供Joda时间解析器的全部灵活性,但它会解析您的五个示例字符串。你可以进一步调整它,以适应你可能有的任何进一步的需求

    ZoneOffset defaultOffset = ZoneOffset.UTC; // Configurable
    LocalDate defaultDate = LocalDate.now(ZoneId.systemDefault());
    
    DateTimeFormatter flexibleFormatter = new DateTimeFormatterBuilder()
            .optionalStart()
            .append(DateTimeFormatter.ISO_LOCAL_DATE)
            .appendLiteral('T')
            .optionalEnd()
            .parseDefaulting(ChronoField.YEAR, defaultDate.getYear())
            .parseDefaulting(ChronoField.MONTH_OF_YEAR, defaultDate.getMonthValue())
            .parseDefaulting(ChronoField.DAY_OF_MONTH, defaultDate.getDayOfMonth())
            .append(DateTimeFormatter.ISO_LOCAL_TIME)
            .optionalStart()
            .appendOffsetId()
            .optionalEnd()
            .parseDefaulting(ChronoField.OFFSET_SECONDS, defaultOffset.getTotalSeconds())
            .toFormatter();

    Arrays.asList("2020-11-22T01:59:59.001+00:00", "2020-11-22T01:59:59.001Z", "2020-11-22T01:59:59+00:00",
            "2020-11-22T01:59:59Z", "01:59:59").forEach(s -> {
            try {
                System.out.println(String.format("%-30s -- %s", s, OffsetDateTime.parse(s, flexibleFormatter)));
            } catch (DateTimeParseException dtpe) {
                System.out.println(String.format("%-30s -- %s", s, dtpe.getMessage()));
            }
        });     
我刚才在欧洲/哥本哈根时区跑步时的输出:

从Joda Time主页:

请注意,Joda Time被认为是一个基本上已“完成”的项目。 没有计划进行重大改进。如果使用JavaSE8,请迁移 到
java.time
(JSR-310)

你的代码出了什么问题? jensgram在评论中说:


您正在为
dateTimeParser
链接文档,但调用
dateTime()

链接
  • 解释如何使用java.time

您正在链接到
dateTimeParser
的文档,但调用了
dateTime()
。您使用的是什么java版本?如果是8或更高,则指示您迁移到java.time(JSR-310)——JDK的一个核心部分,它取代了这个project@jensgram是的,这就是问题所在<代码>(--)ლ)@Abra,所有预定义的语法似乎都是
严格的
。是否有一些简单的方法可以获得像
ISODateTimeFormat.dateTimeParser()
这样的智能解析器?
DateTimeFormatter.ISO\u OFFSET\u DATE\u TIME.withResolverStyle(ResolverStyle.SMART)
?它并不完全等同于Joda Time,但它应该是智能的。您正在链接到
dateTimeParser
的文档,但调用
dateTime()
。您使用的java版本是什么?如果是8或更高版本,则会指示您迁移到java.Time(JSR-310)-JDK的核心部分,它取代了此project@jensgram,是的,这就是问题所在ლ)@Abra,所有预定义的语法似乎都是
严格的
。是否有一些简单的方法可以获得像
ISODateTimeFormat.dateTimeParser()
这样的智能解析器?
DateTimeFormatter.ISO\u OFFSET\u DATE\u TIME.withResolverStyle(ResolverStyle.SMART)
?这与Joda Time(乔达时间)并不完全等同,但它应该是聪明的。谢谢!我现在要坚持Joda。但希望这能帮助其他人。谢谢!我现在要坚持Joda。但希望这能帮助其他人。
    ZoneOffset defaultOffset = ZoneOffset.UTC; // Configurable
    LocalDate defaultDate = LocalDate.now(ZoneId.systemDefault());
    
    DateTimeFormatter flexibleFormatter = new DateTimeFormatterBuilder()
            .optionalStart()
            .append(DateTimeFormatter.ISO_LOCAL_DATE)
            .appendLiteral('T')
            .optionalEnd()
            .parseDefaulting(ChronoField.YEAR, defaultDate.getYear())
            .parseDefaulting(ChronoField.MONTH_OF_YEAR, defaultDate.getMonthValue())
            .parseDefaulting(ChronoField.DAY_OF_MONTH, defaultDate.getDayOfMonth())
            .append(DateTimeFormatter.ISO_LOCAL_TIME)
            .optionalStart()
            .appendOffsetId()
            .optionalEnd()
            .parseDefaulting(ChronoField.OFFSET_SECONDS, defaultOffset.getTotalSeconds())
            .toFormatter();

    Arrays.asList("2020-11-22T01:59:59.001+00:00", "2020-11-22T01:59:59.001Z", "2020-11-22T01:59:59+00:00",
            "2020-11-22T01:59:59Z", "01:59:59").forEach(s -> {
            try {
                System.out.println(String.format("%-30s -- %s", s, OffsetDateTime.parse(s, flexibleFormatter)));
            } catch (DateTimeParseException dtpe) {
                System.out.println(String.format("%-30s -- %s", s, dtpe.getMessage()));
            }
        });     
2020-11-22T01:59:59.001+00:00  -- 2020-11-22T01:59:59.001Z
2020-11-22T01:59:59.001Z       -- 2020-11-22T01:59:59.001Z
2020-11-22T01:59:59+00:00      -- 2020-11-22T01:59:59Z
2020-11-22T01:59:59Z           -- 2020-11-22T01:59:59Z
01:59:59                       -- 2020-11-19T01:59:59Z