Joda DateTimeFormatter.parseDateTime 因一般时区 ('z') 而失败

Joda DateTimeFormatter.parseDateTime is failing for General time zone('z')

混淆了一般时区的使用('z')。 Joda 在以下示例代码中失败。有人可以帮助我理解为什么这种行为是这样的吗?我如何在 Joda 中使用这种格式解析不同时区的日期?

    public static void main(String[] args) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd G 'at' HH:mm:ss z");
        System.out.println(sdf.parse("2019.09.17 AD at 15:29:00 IST"));

        DateTimeFormatter pattern = DateTimeFormat.forPattern("yyyy.MM.dd G 'at' HH:mm:ss z");
        DateTime dateCtxParamDateTimeObj = pattern.parseDateTime("2019.09.17 AD at 15:29:00 IST");
        System.out.println(dateCtxParamDateTimeObj.toDate());
    }

输出

Tue Sep 17 15:29:00 IST 2019
Exception in thread "main" java.lang.IllegalArgumentException: Invalid format: "2019.09.17 AD at 15:29:00 IST" is malformed at "IST"
    at org.joda.time.format.DateTimeFormatter.parseDateTime(DateTimeFormatter.java:945)

编辑:您需要告诉 Joda-Time 您所说的 IST 是什么意思

感谢转至 HarryQ, who pointed me here 记录此内容的位置。

    DateTimeUtils.setDefaultTimeZoneNames(Collections.singletonMap(
            "IST", DateTimeZone.forID("Europe/Dublin")));

    DateTimeFormatter pattern = DateTimeFormat.forPattern("yyyy.MM.dd G 'at' HH:mm:ss z");
    DateTime dateCtxParamDateTimeObj = pattern.parseDateTime("2019.09.17 AD at 15:29:00 IST");

    System.out.println(dateCtxParamDateTimeObj);

此片段的输出是:

2019-09-17T15:29:00.000+01:00

格式模式字符串中的小写 z 在格式化和在 Joda-Time 中解析时的工作方式不同。 Joda-Time 可以格式化所有可用时区的时区名称,但在默认设置下它只能解析几个回来。它可以解析的内容由 DateTimeUtils class 的 默认时区名称 控制。它带有 10 个时区缩写的地图,如 DateTimeUtils.getDefaultTimeZoneNames 方法(底部的 link)所述:CST、MDT、GMT、PST、PDT、UTC、EDT,CDT 、美国东部标准时间和最低标准时间。我们可以用不同的地图代替。我在上面所做的是用一张只有一个缩写的地图代替插图。这有破坏其他代码的风险,因此对于大多数目的来说,更好的方法是构建一个包含之前存在的缩写和我们希望能够解析的缩写的映射。

我在上面提供的地图假定 IST 适用于爱尔兰夏令时(2019 年 9 月 17 日,爱尔兰使用夏令时 (DST))。您几乎不是指以色列标准时间,因为以色列也使用夏令时 IDT。第三种可能的理解是印度标准时间:

    DateTimeUtils.setDefaultTimeZoneNames(Collections.singletonMap(
            "IST", DateTimeZone.forID("Asia/Kolkata")));

2019-09-17T15:29:00.000+05:30

您注意到我们现在得到偏移量 +05:30 而不是 +01:00,所以时间点不同。歧义也可能是 Joda-Time 拒绝对您的意图做出自己的假设并因此需要我们在它可以解析字符串之前告诉它的原因。

原回答

这是 Joda-Time 中记录的限制。来自 DateTimeFormat 的文档:

Zone names: Time zone names ('z') cannot be parsed.

另请注意,IST 和许多其他时区缩写是不明确的,因此如果有任何方法可以避免解析,请务必避免使用。 IST 可能适用于爱尔兰夏令时、以色列标准时间或印度标准时间,但无法保证您会得到其中的哪一个,或者您是否会得到冰岛标准时间。

如果您坚持,一种可能的解决方案是遵循 Joda-Time 主页上的建议:

Note that Joda-Time is considered to be a largely “finished” project. No major enhancements are planned. If using Java SE 8, please migrate to java.time (JSR-310).

java.time(现代 Java 日期和时间 API)的 DateTimeFormatter class 将尝试解析时区缩写。祝你好运。

链接

乔达时间

其他

  • My answer here 显示了在使用 java.time.
  • 时如何在解析时控制 IST 的解释