由于Java 8的行为不像预期的那样好,所以我建议一个解决方案是先尝试没有区域的解析。如果从字符串中分析区域或偏移量,则将使用此值。如果没有区域的解析失败,请尝试使用区域。以下方法可以做到这一点:
private static void parseAndPrint(String formatPattern, String dateTimeString) {
// Try parsing without zone first
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(formatPattern);
Instant parsedInstant;
try {
parsedInstant = formatter.parse(dateTimeString, Instant::from);
} catch (DateTimeParseException dtpe) {
// Try parsing with zone
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
是一种危险且不受鼓励的做法,因为缩写词通常是模棱两可的。我只把这个例子作为演示。
有没有办法使用一个类?
我已经用过
瞬间
对于所有情况,有一种方法可以只使用一个类。限制是,你不知道是否有任何时区或偏移在字符串中,也不知道它是什么。你不知道你什么时候用的
SimpleDateFormat
和
Date
我也觉得还好吧?
Java 8中的bug?