提问人:hildegard 提问时间:5/16/2017 最后编辑:hildegard 更新时间:5/17/2017 访问量:1436
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 '2017 年 5 月 16 日星期二 13:02:16 GMT' 无法在索引 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
记录为
返回 RFC-1123 日期时间格式化程序,例如“Tue, 3 Jun 2008 格林威治标准时间 11:05:30'。
所以我认为它应该接受为时区名称。我应该说它适合您的日期字符串,并且它也适用于我的计算机。我相信这个格式化程序使用星期几和月份的英文缩写,无论在什么地方(或者你可以尝试,但我真的认为没有必要)。GMT
DateTimeFormatter.RFC_1123_DATE_TIME.withLocale(Locale.ENGLISH)
也就是说,他们说你应该避免使用三个和四个字母的时区缩写。有些是模棱两可的,有些不是完整的时区,这导致了进一步的模棱两可。虽然 GMT 不是最危险的,但解决您的问题的一个坚如磐石的解决方案是,如果您可以获取带有偏移量的日期字符串,例如 或 ,而不是三个字母的区域名称。+00:00
Z
请参阅问题和此答案中的两个示例,在 IdeOne.com 实时运行。两者都成功了。
评论
TL的;博士
在 macOS(非 Android)上使用 ThreeTen-Backport 1.3.4 项目库时:
- 我不明白你的(解析成功)
DateTimeParseException
- 但是我确实得到了一个与Java 8内置的java.time类中分配的时区不同的时区。
而不是2017-05-16T13:02:16Z[Africa/Monrovia]
2017-05-16T13:02:16Z[GMT]
Africa/Monrovia
区?
我们中的一些人已经看到您的代码工作,显然是使用 Java 8 中内置的 java.time 类。
但是你的问题是关于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构建和运行时,我得到了一个奇怪的结果。我没有得到我的期望或最后,而是得到了利比里亚的非洲/蒙罗维亚
时区。这是有效的,因为与UTC的偏移量确实为零(与UTC / GMT相同)。但这不是我们在 Java 8 类中看到的,正如我们得到的 IdeOne.com 所看到的那样。Z
Z[GMT]
2017-05-16T13:02:16Z[GMT]
parsedDate.toString(): 2017-05-16T13:02:16Z[非洲/蒙罗维亚]
我没有 Java 6 或 Java 7 的实现可供我使用。但我确实尝试在 IntelliJ 中设置我的构建字节码设置以使用 Java 6。同样的结果。
评论
java.time
2017-05-16T13:02:16Z[GMT]
DateTimeFormatter.RFC_1123_DATE_TIME