DateTimeFormatter 解析具有区域偏移量和时区的字符串

DateTimeFormatter to parse string with both Zone offset and timezone

这个问题听起来可能与 Whosebug 上提出的大多数其他问题相似,但我无法弄清楚我的问题。 我想将字符串值解析为日期。

String dateTime = "2020 年 10 月 23 日 02:44:58 +1000"

这个问题的解决方法是:

DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder();
builder.parseCaseInsensitive();
builder.appendPattern("d MMM yyyy HH:mm[:ss] Z");
DateTimeFormatter dtf = builder.toFormatter();

ZonedDateTime zonedDateTime = ZonedDateTime.parse(dateTime, dtf);
Instant instant = zonedDateTime.toInstant();
Date finalDate = Date.from(instant);

如果我想用时区解析日期而不是 String dateTime = "23 Oct 2020 02:44:58 AEST" 那么我需要更改 builder.appendPattern("d MMM yyyy HH:mm[:ss] Z"); 如前所述从大写 Z 到小写 z here.

这里的问题是如何使我的解析器足够灵活以使其能够处理时区或偏移值?

注意。我使用 [ss] 作为秒字段是可选的。根据文档,使用 VV 类似于 z 而 'V' 对我不起作用。

您可以尝试使用 try-catch 块

DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder(); 
builder.parseCaseInsensitive(); 
builder.appendPattern("d MMM yyyy HH:mm[:ss] Z"); 
DateTimeFormatter dtf = builder.toFormatter();

DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder(); 
builder.parseCaseInsensitive(); 
builder.appendPattern("d MMM yyyy HH:mm[:ss] z"); 
DateTimeFormatter dtf = builder.toFormatter();

ZonedDateTime zonedDateTime;
try {
    zonedDateTime = ZonedDateTime.parse(dateTime, dtf1);
} catch (DateTimeParseException e) {
    zonedDateTime = ZonedDateTime.parse(dateTime, dtf2);
}
Instant instant = zonedDateTime.toInstant();
Date finalDate = Date.from(instant);

您可以将它们作为 可选部分 添加到格式化程序中,就像您对秒部分所做的那样:

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
    .parseCaseInsensitive()
    .appendPattern("d MMM yyyy HH:mm[:ss] [Z][z]")
    .toFormatter(Locale.ROOT);

Online demo

[]表示可选部分:如果可以通过括号内的模式成功解析,则相应的文本被消费,否则,不会消耗任何文本并跳过其中的模式。