如何不用小时来解析HH:mm:ss?

Aur*_*ora 0 java time parsing kotlin

我有一个格式如下的字符串:“ 2h 33m 50s”。如果小时数达到零,则此字符串更改为:“ 33m 50s”。因此,如果此字符串通过LocalTime.parse,则会引发异常。我该如何解析?

fun main() {
    val timeString = "2h 33m 50s"
    val timeString2 = "33m 50s"
    val formatterH = DateTimeFormatter.ofPattern("[H]'h 'm[m]'m 's[s]'s'")
    val formatterM = DateTimeFormatter.ofPattern("m[m]'m 's[s]'s'")

    val time = LocalTime.parse(timeString, formatterH)
    println(time)
    val time2 = LocalTime.parse(timeString2, formatterH) //throws exception
    println(time2)
    val time3 = LocalTime.parse(timeString2, formatterM) //throws similar exception
    println(time3)
}
Run Code Online (Sandbox Code Playgroud)
Program output:
02:33:50
Exception in thread "main" org.threeten.bp.format.DateTimeParseException: Text '33m 50s' could not be parsed: Unable to obtain LocalTime from TemporalAccessor: DateTimeBuilder[fields={SecondOfMinute=50, NanoOfSecond=0, MicroOfSecond=0, MinuteOfHour=33, MilliOfSecond=0}, ISO, null, null, null], type org.threeten.bp.format.DateTimeBuilder
    at org.threeten.bp.format.DateTimeFormatter.createError(DateTimeFormatter.java:1559)
    at org.threeten.bp.format.DateTimeFormatter.parse(DateTimeFormatter.java:1496)
    at org.threeten.bp.LocalTime.parse(LocalTime.java:437)
    at MainKt.main(main.kt:16)
    at MainKt.main(main.kt)
Caused by: org.threeten.bp.DateTimeException: Unable to obtain LocalTime from TemporalAccessor: DateTimeBuilder[fields={SecondOfMinute=50, NanoOfSecond=0, MicroOfSecond=0, MinuteOfHour=33, MilliOfSecond=0}, ISO, null, null, null], type org.threeten.bp.format.DateTimeBuilder
    at org.threeten.bp.LocalTime.from(LocalTime.java:405)
    at org.threeten.bp.LocalTime$1.queryFrom(LocalTime.java:116)
    at org.threeten.bp.LocalTime$1.queryFrom(LocalTime.java:113)
    at org.threeten.bp.format.DateTimeBuilder.build(DateTimeBuilder.java:642)
    at org.threeten.bp.format.DateTimeFormatter.parse(DateTimeFormatter.java:1492)
Run Code Online (Sandbox Code Playgroud)

Bas*_*que 6

tl; dr

您工作太辛苦,方向错误。

正则表达式对于这个问题过于矫kill过正。

不需要DateTimeFormatter类,也不需要格式化模式。

使用Durationclass解析根据您的输入制作的ISO 8601字符串。

Duration                    // Represent a span-of-time not attached to the timeline with class `Duration`, not `LocalTime`.
.parse(                     // By default, the *java.time* classes such as `Duration` use the standard ISO 8601 formats to parse/generate date-time strings.
    "PT" + "2h 33m 50s"     // Morph your input string to comply with the ISO 8601 standard. Add `P` for the beginning, and `T` to separate years-months-days from hours-minutes-seconds. 
    .replace( " " , "" )    // Delete any SPACE characters by replacing them with nothing.
    .toUpperCase()          // Force all the letters to be uppercase.
)                           // Returns a `Duration`.
Run Code Online (Sandbox Code Playgroud)

同上仅几分钟和几秒钟。

Duration.parse( "PT" + "33m 50s".replace( " " , "" ).toUpperCase() ) 
Run Code Online (Sandbox Code Playgroud)

Duration,不 LocalTime

如果此字符串通过LocalTime.parse

LocalTime是一天中的某个时间。您输入的不是一天中的时间。

您的输入字符串表示未附加到时间轴的时间跨度。该类是Duration

ISO 8601

您的输入字符串接近于标准ISO 8601格式PnYnMnDTnHnMnS。该P标志的开始。该T分离任何小时-分-秒的任何年,月,日。

让我们调整您的输入字符串以符合标准。

String input = "PT" + "2h 33m 50s".replace( " " , "" ).toUpperCase() ;
Run Code Online (Sandbox Code Playgroud)

输入:PT2H33M50S

解析。

Duration d = Duration.parse( input ) ;  // PT2H33M50S
Run Code Online (Sandbox Code Playgroud)

要在标准ISO 8601中生成字符串,请调用toString

String output = d.toString() ;
Run Code Online (Sandbox Code Playgroud)

输出:PT2H33M50S

您可以将该Duration对象添加到一天中的某个时间LocalTime

LocalTime lt = LocalTime.NOON.plus( d ) ;
Run Code Online (Sandbox Code Playgroud)

您可以将其添加Duration到UTC中的当前时刻,以确定未来时刻(或者过去时刻是持续时间为负数)。

Instant instant = Instant.now().plus( d ) ;
Run Code Online (Sandbox Code Playgroud)

lt.toString():14:33:50

查看以上所有代码,它们可在IdeOne.com上实时运行

您可以提取的每个部分Duration

long daysPart = d.toDaysPart() ;  // 24-hour chunks of time, not related to calendar days.
int hoursPart = d.toHoursPart() ;
int minutesPart = d.toMinutesPart() ;
int secondsPart = d.toSecondsPart() ;
Run Code Online (Sandbox Code Playgroud)

或者,您可能希望将整个时间跨度视为总毫秒数。

long millis = d.toMillis() ;  // All the hours-minutes-seconds and such totaled as one count of elapsed milliseconds.
Run Code Online (Sandbox Code Playgroud)