使用闰秒解析本地时间



我正在尝试了解如何为我的应用程序构建自定义DateTimeFormatter。我基本上需要处理像这样写的时间"HHMMSS。FFFFFFF"。

我能够通过以下方式获得 99%的它:

import static java.time.temporal.ChronoField.HOUR_OF_DAY;
import static java.time.temporal.ChronoField.MICRO_OF_SECOND;
import static java.time.temporal.ChronoField.MINUTE_OF_HOUR;
import static java.time.temporal.ChronoField.SECOND_OF_MINUTE;
public static final DateTimeFormatter MY_TIME;
static {
MY_TIME = new DateTimeFormatterBuilder()
.appendValue(HOUR_OF_DAY, 2)
.appendValue(MINUTE_OF_HOUR, 2)
.optionalStart()
.appendValue(SECOND_OF_MINUTE, 2)
.optionalStart()
.appendFraction(MICRO_OF_SECOND, 0, 6, true)
.toFormatter().withResolverStyle(ResolverStyle.STRICT);
}

我可以很好地处理输入:

String text = "101530";
LocalTime lt = LocalTime.parse(text, MY_TIME);

甚至

String text = "070907.0705";
LocalTime lt = LocalTime.parse(text, MY_TIME);

String text = "0000";
LocalTime lt = LocalTime.parse(text, MY_TIME);

但是由于某种原因,我无法理解用于处理闰秒的 API,因此以下内容对我来说总是失败:

String text = "235960";
LocalTime lt = LocalTime.parse(text, MY_TIME);

我应该如何构建我的DateTimeFormatterBuilder以便处理闰秒?


更新:我真的很喜欢ResolverStyle.STRICT,因为它拒绝无效输入,例如:

  • "251213"或,
  • "126100">

所以我不能在这种情况下使用ResolverStyle.LENIENT,我只是想要闰秒的额外特殊情况。

显示闰秒的本地时钟时间如果不同时显示日历日期和时区,就没有多大意义。否则,您不知道要解析的字符串是否真的有效(java.time-package 不会帮助您验证它)或只是以宽松的方式(即解析"60"作为下一秒)。

关于java.time的闰秒能力:

java.time确实可以容忍任何虚拟日期与闰秒相结合,尽管这在大多数情况下是错误的。DateTimeFormatter只接受 UTC 偏移量零,不接受"2012-07-01T08:59:60+0900"之类的表达式。

此外:java.time.Instant不能存储闰秒信息,而是将其丢弃。您只能查询解析器以获取可能的闰秒标志。然后由您想如何处理这些信息。

结论:如果您想忽略闰秒信息,但在输入中容忍它,这种方法对您来说很好。

选择:

如果你真的对解析、验证和评估可能的闰秒感兴趣,那么我建议使用我的库 Time4J。但它确实需要一个有效的日历日期(闰秒只在极少数日期上插入)。

ChronoFormatter<Moment> formatter = 
ChronoFormatter.ofMomentPattern( 
"uuuu-MM-dd'T'HH:mm:ss XXX", 
PatternType.CLDR, 
Locale.ROOT, 
ZonalOffset.UTC 
)
Moment m = formatter.parse("2012-07-01T08:59:60+09:00");
// this conversion throws away the leap second
Instant i = m.toTemporalAccessor();

有关更多信息,另请参阅我关于DZone的文章。

来自java.time.Instant JavaDoc的相关描述:

这个Java API定义了它自己的时间尺度,即Java时间尺度
...
使用 JSR-310 API 实现 Java 时间刻度 不需要提供任何亚秒级精度的时钟, 或单调或顺利地进行。因此,实际执行不需要实现 UTC-SLS 摆动或以其他方式注意闰秒

Java 时间刻度用于所有日期时间类。这包括即时、本地日期、本地时间、偏移日期时间、分区日期时间和持续时间。

简而言之,您不应该期望java.timeAPI 能够识别闰秒。

闰秒处理仅适用于appendInstant:请参阅日期时间格式化程序:parsedLeapSecond

即时解析处理特殊的"闰秒"时间"23:59:60"。 闰秒出现在 UTC 时区的"23:59:60",但在其他时区 不同时区的当地时间。为了避免这种潜力 歧义,闰秒的处理仅限于 DateTimeFormatterBuilder.appendInstant(),因为该方法总是解析 具有 UTC 区域偏移的时刻。

由于这对我的用户用途有限(编辑无效时间),我可以简单地处理这种特殊情况:

if (text.length() >= 6 && "60".equals(text.substring(4, 6))) {
String newText = text.substring(0, 4) + "59" + text.substring(6);
return LocalTime.parse(newText, MY_TIME);
}
return LocalTime.parse(text, MY_TIME);

这似乎是一个普遍接受的黑客:

  • https://gist.github.com/dehora/9b2ce8bac22d1b37393d8b4f7c9eb7aa

相关内容

  • 没有找到相关文章

最新更新