确定Java 8 DateTimeFormatter是否包含足够的时区信息

问题描述 投票:3回答:1

我有一些代码接收解析的DateTimeFormatter实例。现在在某些情况下,我已经看到那里没有时区/偏移信息,因此我遇到了解析错误(例外)。

为了避免这些错误,我想在没有指定任何内容时强制使用ZoneOffset.UTC中的默认时区/偏移量。

到目前为止,我还没有找到一种“干净且有记录”的方法来做到这一点。

在这个例子中,getZone()方法返回null

ParseCaseSensitive(false)Value(DayOfMonth,2)'/'Text(MonthOfYear,SHORT)'/'Value(Year,4)' 'Value(HourOfDay,2)':'Value(MinuteOfHour,2)':'Value(SecondOfMinute,2)'.'Value(MilliOfSecond,3)' 'Offset(+HHMM,'+0000')

到目前为止,我提出的最好的方法是执行'toString()',然后检查所需的子字符串是否在这里:

String formatterExpression = formatter.toString();
if (formatterExpression.lastIndexOf("Offset(") == -1 &&
    formatterExpression.lastIndexOf("ZoneText(") == -1
    ) {
    formatter = formatter.withZone(defaultZone);
    LOG.error("The timestamp format \"{}\" does NOT contain a timezone so we assume \"{}\".",
        formatter.toString(), defaultZone.getDisplayName(TextStyle.SHORT, Locale.ENGLISH));
}

这样做的正确方法是什么?

其他背景信息此代码是系统的一部分,该系统允许解析使用strftime格式指定格式的日期/时间文本。

看到:

java datetime java-8 timezone timezone-offset
1个回答
1
投票

我明白你的意思了,我也没有找到完美的解决方案,但我想我会分享几个选择。

如果格式化程序无法解析区域或偏移量,您可以设置像UTC这样的偏移量,我建议:

formatter = new DateTimeFormatterBuilder().append(formatter)
        .parseDefaulting(ChronoField.OFFSET_SECONDS, ZoneOffset.UTC.getTotalSeconds())
        .toFormatter();

我还没有发现这会造成任何伤害的情况。如果格式化程序已经解析了区域或偏移量信息(或包含默认偏移量),则这将不起作用。如果没有,将使用指定的默认偏移量。

以上内容不适用于强制执行具有可变偏移的时区(如夏令时(DST)的时区)。为了强制执行一个,我相信你应该解析,获取并捕获异常,然后以你已经找到的方式强制执行时区:

ZonedDateTime dateTime;
try {
    dateTime = ZonedDateTime.parse(dateTimeString, formatter);
} catch (DateTimeParseException dtpe) {
    dateTime = ZonedDateTime.parse(dateTimeString, 
                    formatter.withZone(ZoneId.of("Europe/Amsterdam")));
}

缺点是catch子句还将捕获与缺失偏移或区域无关的错误。您可能会尝试解析异常消息,但我相信这会让您遇到类似于您开始的问题。我不打扰。

恕我直言,我们真正缺少的是获取格式化器知道如何格式化和解析的字段的getter。对于复杂的格式化程序,这种方法的设计和使用将具有挑战性,因此我倾向于理解为什么他们没有提供。

© www.soinside.com 2019 - 2024. All rights reserved.