threetenbp:解析带时区名称的日期时解析异常

threetenbp: Parse exception when parsing date with time-zone name

我正在尝试以 EEE, dd MMM yyyy HH:mm:ss zzz 格式解析日期,例如使用 threeten 的 DateTimeFormatter 的 "Tue, 16 May 2017 07:44:48 GMT" 这样的字符串。但是,似乎由于某种原因无法解析时区名称(我尝试在没有时区名称部分的情况下解析相同的字符串并且有效)。

下面是代码的解析部分:

DateTimeFormatter parseFormatter = DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH);
ZonedDateTime parsedDate = ZonedDateTime.parse(date, parseFormatter);

我收到以下错误:

org.threeten.bp.format.DateTimeParseException: Text 'Tue, 16 May 2017 13:02:16 GMT' could not be parsed at index 26

我为时区名称部分尝试了各种不同的格式(例如 z、zzz、Z、ZZZ),但没有任何效果。同样,如果我解析一个没有时区名称部分的子字符串日期(到 LocalDateTime),那么它就可以工作,所以我确信问题出在时区名称上。有人知道问题出在哪里吗?

我不知道为什么你的代码不起作用。当我在我的 Java 8 中使用 java.time 类 时会发生这种情况。所以这只是对可能修复的猜测:

    DateTimeFormatter parseFormatter = DateTimeFormatter.RFC_1123_DATE_TIME;
    ZonedDateTime parsedDate = ZonedDateTime.parse(date, parseFormatter);

您会注意到它在同一时间略有简化。

DateTimeFormatter.RFC_1123_DATE_TIME 记录为

Returns the RFC-1123 date-time formatter, such as 'Tue, 3 Jun 2008 11:05:30 GMT'.

所以我认为它应该接受 GMT 作为时区名称。我应该说它适合你的日期字符串,它也适用于我的电脑。我相信无论语言环境如何,此格式化程序都使用英文缩写来表示星期几和月份(或者您可以尝试 DateTimeFormatter.RFC_1123_DATE_TIME.withLocale(Locale.ENGLISH),但我真的认为没有必要)。

也就是说,他们说您应该避免使用三字母和四字母时区缩写。有些是模棱两可的,有些不是完整的时区,这会导致进一步的模棱两可。虽然 GMT 不是最危险的,但解决您的问题的可靠方法是,如果您可以获得带有偏移量的日期字符串,例如 +00:00 或只是 Z,而不是三个字母区域名字.

请参阅问题和此答案中的两个示例,running live at IdeOne.com。都成功了。

tl;博士

在 macOS 上使用 ThreeTen-Backport 1.3.4 项目库时(不是 Android):

  • 没有得到你的DateTimeParseException(解析成功)
  • 但我得到的 时区 与 java.time 类 中指定的时区不同 Java 8.
    2017-05-16T13:02:16Z[Africa/Monrovia] 而不是 2017-05-16T13:02:16Z[GMT]

Africa/Monrovia 区域?

我们中的一些人已经看到您的代码有效,显然使用 java.time 类 内置于 Java 8.

但是您的问题具体是关于 Java 6 和 Java 7 的那些 类 的后向端口。所以我使用 ThreeTen-Backport 尝试了以下示例项目库。

package com.example.threetenbp.example;

import org.threeten.bp.*;
import org.threeten.bp.format.*;

import java.util.Locale;

/**
 * By Basil Bourque.
 */
public class App {
    public static void main ( String[] args ) {
        App app = new App ( );
        app.doIt ( );
    }

    private void doIt ( ) {
        String input = "Tue, 16 May 2017 13:02:16 GMT";
        DateTimeFormatter parseFormatter = DateTimeFormatter.ofPattern ( "EEE, dd MMM yyyy HH:mm:ss z" , Locale.ENGLISH );
        ZonedDateTime parsedDate = ZonedDateTime.parse ( input , parseFormatter );

        System.out.println ("parsedDate.toString(): " + parsedDate );
    }

}

在 macOS Sierra 10.12.4 上使用 IntellJ 2017.1.x 为 Java 8 构建 & 运行 时,我得到了一个奇怪的结果。最后我没有得到预期的 ZZ[GMT],而是得到了 2017-05-16T13:02:16Z[GMT].

的时区 Africa/Monrovia in Liberia. This is valid, as the offset-from-UTC there is indeed zero (the same as UTC/GMT). But this is not what we see with the Java 8 classes as seen live at IdeOne.com

parsedDate.toString(): 2017-05-16T13:02:16Z[Africa/Monrovia]

我没有 Java 6 或 Java 7 的实现供我使用。但我确实尝试在 IntelliJ 中设置我的构建字节码设置以使用 Java 6。结果相同。