Как разобрать чч: мм: сс без часов? - PullRequest
0 голосов
/ 16 мая 2019

У меня есть строка с форматом вроде: "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)
}
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)

Ответы [ 2 ]

6 голосов
/ 16 мая 2019

tl; dr

Вы слишком усердно работаете и движетесь в неправильном направлении.

Regex излишне справляется с этой задачей.

Нет необходимости в DateTimeFormatter класс, ни шаблон форматирования.

Используйте Duration класс для анализа строки 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`.

То же самое за считанные минуты и секунды.

Duration.parse( "PT" + "33m 50s".replace( " " , "" ).toUpperCase() ) 

Duration, а не LocalTime

, если эта строка проходит через LocalTime.parse

LocalTime для времени суток.Ваш ввод не является временем суток.

Ваша входная строка представляет промежуток времени, не привязанный к временной шкале.Класс для этого Duration.

ISO 8601

Ваша строка ввода близка к стандартному формату ISO 8601 , PnYnMnDTnHnMnS.P отмечает начало.T отделяет любые годы-месяцы-дни от любых часов-минут-секунд.

Давайте настроим вашу строку ввода так, чтобы она соответствовала стандарту.

String input = "PT" + "2h 33m 50s".replace( " " , "" ).toUpperCase() ;

input:PT2H33M50S

Parse.

Duration d = Duration.parse( input ) ;  // PT2H33M50S

Чтобы сгенерировать строку в стандарте ISO 8601, вызовите toString.

String output = d.toString() ;

output: PT2H33M50S

Вы можете добавить этот Duration объект к времени суток, a LocalTime.

LocalTime lt = LocalTime.NOON.plus( d ) ;

Вы можете добавить это Duration к текущему моменту в UTC, чтобы определить будущий момент (или прошедший момент - это длительность, являющаяся отрицательной величиной).

Instant instant = Instant.now().plus( d ) ;

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

Или, возможно, вы хотите, чтобы весь промежуток времени был подсчитан как общее количество миллисекунд.

long millis = d.toMillis() ;  // All the hours-minutes-seconds and such totaled as one count of elapsed milliseconds.
0 голосов
/ 16 мая 2019

Использовать шаблон "[H'h ']m'm 's's'", который будет анализировать оба.

  • [H'h '] соответствует дополнительным часам, например, "2h "
  • m'm ' совпадений "33m "
  • s's' совпадений "50s"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...