簡體   English   中英

用閏秒解析LocalTime

[英]Parsing LocalTime with leap second

我試圖了解如何為我的應用程序構建自定義DateTimeFormatter 我基本上需要處理像“HHMMSS.FFFFFF”這樣編寫的時間。

我能夠使用以下方法獲得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 ,我只想要閏秒的額外特殊情況。

閏秒處理僅適用於appendInstant :請參閱DateTimeFormatter:parsedLeapSecond

即時解析處理'23:59:60'的特殊“閏秒”時間。 閏秒發生在UTC時區的'23:59:60',但是在不同時區的其他本地時間。 為了避免這種潛在的歧義, 閏秒處理僅限於DateTimeFormatterBuilder.appendInstant() ,因為該方法始終使用UTC區域偏移量解析瞬間。

java.time.Instant JavaDoc中的相關描述:

[...]這個Java API定義了自己的時間尺度, Java Time-Scale
...
使用JSR-310 API實現Java時標不需要提供亞秒精確或單調或平滑進展的任何時鍾。 因此,實現不需要實際執行UTC-SLS轉換或以其他方式了解閏秒
...
Java時標用於所有日期時間類。 這包括Instant,LocalDate,LocalTime,OffsetDateTime,ZonedDateTime和Duration。

簡而言之,您不應期望java.time API能夠java.time閏秒。

如果沒有顯示日歷日期和時區,顯示閏秒的本地時鍾時間也沒有多大意義。 否則你不知道要解析的字符串是否真的有效( java.time不會幫助你驗證它)或者只是以寬松的方式(即解析“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上的文章。

由於這對我的用戶使用有限(編輯無效時間),我可以使用以下簡單處理這種特殊情況:

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);

這似乎是一個普遍接受的黑客:

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM