由于您的Java 8不像合理预期的那样运行,我建议尝试首先解析没有时区的字符串。如果从字符串中解析出时区或偏移量,则将使用它。如果没有时区的解析失败,请尝试使用时区。以下方法可以实现这一点:
private static void parseAndPrint(String formatPattern, String dateTimeString) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(formatPattern);
Instant parsedInstant;
try {
parsedInstant = formatter.parse(dateTimeString, Instant::from);
} catch (DateTimeParseException dtpe) {
ZoneId defaultZone = ZoneId.of("Asia/Calcutta");
formatter = formatter.withZone(defaultZone);
parsedInstant = formatter.parse(dateTimeString, Instant::from);
}
System.out.println("Parsed instant: " + parsedInstant);
}
让我们试试:
parseAndPrint("yyyy-MM-dd'T'HH:mm:ss.SSSSSSXXX", "2018-10-22T02:17:58.717853Z");
parseAndPrint("yyyy-MM-dd'T'HH:mm:ss.SSSSSS", "2018-10-22T02:17:58.717853");
parseAndPrint("EEE MMM d HH:mm:ss zzz yyyy", "Mon Oct 22 02:17:58 CEST 2018");
Java 8 的输出为:
Parsed instant: 2018-10-22T02:17:58.717853Z
Parsed instant: 2018-10-21T20:47:58.717853Z
Parsed instant: 2018-10-22T00:17:58Z
第一个例子在字符串中有一个偏移量,最后一个例子在字符串中有一个时区缩写,并且在这两种情况下都会被尊重:打印的瞬间已经调整了时间到UTC(因为Instant始终以UTC打印,它的toString方法会确保)。中间的例子在字符串中既没有偏移量也没有时区,因此使用了方法中指定的Asia/Calcutta的默认时区。
话虽如此,解析三个或四个字母的时区缩写(如CEST)是一种危险和不鼓励的做法,因为这些缩写通常是模糊的。我只是为了演示而包含了这个例子。
“是否有一种方式可以使用单个类...?”
我对所有情况都使用了Instant,所以是的,有一种方法只使用一个类。局限性在于您事后不知道字符串中是否有任何时区或偏移量,也不知道它是什么。您使用SimpleDateFormat和Date时也不知道,所以我觉得这没问题?
Java 8中的一个错误?
你在 REX 测试器上的演示结果令人失望且错误,并且与我在 Java 11 上得到的结果不一致。我觉得你可能遇到了 Java 8 中的一个 bug,可能是这个:DateTimeFormatter.withZone 解析并没有按照 javadocs 中的描述行事。