Как добавить ряд строковых входов, каждый из которых представляет промежуток времени, в Android? - PullRequest
0 голосов
/ 22 марта 2020

Я получаю список раз с сервера и хочу добавить, чтобы показать общее время. Но не могу найти, как это сделать. Потому что время похоже на нормальное предложение.

15 min 24 s
1 min 56 s
18 min 3 s
2 h 48 min 46 s

Как добавить эти данные?

1 Ответ

3 голосов
/ 22 марта 2020

tl; dr

Используйте класс java.time.Duration со стандартными входными строками ISO 8601.

Duration total = 
    Duration
    .parse(
        "PT" + 
        "2 h 48 min 46 s"
        .replace( "h" , "H" ) 
        .replace( "min" , "M" )
        .replace( "s" , "S" ) 
        .replace( " " , "" )    
    )
    .plus(
        … another `Duration` object
    )

ISO 8601

Обучите издателя этих данных о ISO 8601 стандарт, который определяет множество форматов для передачи значений даты и времени в виде текста.

Стандартный формат для промежутка времени , не привязанный к временной шкале, равен PnYnMnDTnHnMnS, где P отмечает начало (думайте об этом как «p» для «периода»), а T отделяет любые годы-месяцы-дни от любых часов-минут-секунд.

Преобразование ваших входных данных

Ваши примеры входных данных могут быть преобразованы в формат ISO 8601.

Замените min на M. Заменить h на H. И заменить s на S.

Кроме того, удалите все символы пробела. Добавить с PT.

String input = "2 h 48 min 46 s" ;
String inputIso8601 = 
        "PT" + 
        input
        .replace( "h" , "H" ) 
        .replace( "min" , "M" )
        .replace( "s" , "S" ) 
        .replace( " " , "" )      
;

Duration

Современные java .time классы по Java включают Duration. Этот класс представляет промежуток времени, не привязанный к временной шкале в масштабе часов-минут-секунд.

Этот класс знает, как анализировать и генерировать строки в стандартном формате ISO 8601.

Duration d = Duration.parse( inputIso8601 ) ;

Этот класс также знает, как выполнять математику, складывая и вычитая длительности.

Duration dTotal = d1.plus( d2 ) ;

Пример

Давайте создадим метод этого кода преобразования.

public String convertInputToIso8601 ( String input )
{
    String inputIso8601 =
            "PT" +
                    input
                            .replace( "h" , "H" )
                            .replace( "min" , "M" )
                            .replace( "s" , "S" )
                            .replace( " " , "" );
    return inputIso8601;
}

Давайте используйте входные данные вашего примера.

    List < String > inputs = List.of(
            "15 min 24 s" ,
            "1 min 56 s" ,
            "18 min 3 s" ,
            "2 h 48 min 46 s"
    );

Проверка преобразования формата этих входов.

    List < String > inputsIso8601 = 
        inputs
        .stream()
        .map( this :: convertInputToIso8601 )
        .collect( Collectors.toList() )
    ;

Дамп в консоль.

    System.out.println(
            inputsIso8601
    );

[PT15M24S, PT1M56S, PT18M3S, PT2H48M46S]

Это выглядит хорошо. Теперь выполните синтаксический анализ Duration объектов.

    List < Duration > durations = 
        inputsIso8601
        .stream()
        .map( Duration :: parse )
        .collect( Collectors.toList() )
    ;

Дамп на консоль.

    System.out.println( durations );

[PT15M24S, PT1M56S, PT18M3S, PT2H48M46S]

Это также выглядит хорошо. Теперь посчитай. Классы java .time используют неизменных объектов . Это означает, что наши математические операции приводят к созданию нового объекта fre sh, а не к изменению (изменению) оригинала.

Использование обычного синтаксиса для суммирования длительностей.

    Duration total = Duration.ZERO;
    for ( Duration duration : durations )
    {
        total = total.plus( duration );
    }

Использование потоков для суммирования длительностей.

Duration total = 
    durations
    .stream()
    .reduce(
        Duration.ZERO , 
        Duration::plus
    )
;

Дамп в консоль.

    System.out.println( "total = " + total );

всего = PT3H24M9S

Это сработало. Ваши входные данные составили почти три с половиной часа.

Вот снова этот код, все вместе.

    List < String > inputs = List.of(
            "15 min 24 s" ,
            "1 min 56 s" ,
            "18 min 3 s" ,
            "2 h 48 min 46 s"
    );

    List < String > inputsIso8601 = inputs.stream().map( this :: convertInputToIso8601 ).collect( Collectors.toList() );
    System.out.println( inputsIso8601 );

    List < Duration > durations = inputsIso8601.stream().map( Duration :: parse ).collect( Collectors.toList() );
    System.out.println( durations );

    Duration total = durations.stream().reduce( Duration.ZERO , Duration::plus ) ;

    System.out.println( "total = " + total );

Я думаю, мы могли бы объединить эти три потоковых оператора в один. Но чтение и отладка были бы более сложными.


О java .time

java .time фреймворк встроен Java 8 и позже. Эти классы вытесняют проблемные старые устаревшие классы даты и времени, такие как java.util.Date, Calendar и & SimpleDateFormat.

Чтобы узнать больше, см. Учебник Oracle . И поиск переполнения стека для многих примеров и объяснений. Спецификация: JSR 310 .

Проект Joda-Time , теперь в режиме обслуживания , рекомендует перейти на java .time классы.

Вы можете обмениваться java .time объектами непосредственно с вашей базой данных. Используйте драйвер JDB C , совместимый с JDB C 4.2 или более поздней версией. Нет необходимости в строках, нет необходимости в java.sql.* классах.

Где взять классы java .time?

  • Java SE 8 , Java SE 9 , Java SE 10 , Java SE 11 и более поздних версий - часть стандартного API Java со связанной реализацией.
    • Java 9 добавляет некоторые незначительные функции и исправления.
  • Java SE 6 и Java SE 7
    • Большинство функций java .time перенесено на Java 6 & 7 в ThreeTen-Backport .
  • Android
    • Более поздние версии Android комплектных реализаций классов java .time .
    • Для более ранних Android (<26) <a href="https://github.com/JakeWharton/ThreeTenABP" rel="nofollow noreferrer"> ThreeTenABP проект адаптируется ThreeTen-Backport (упомянуто выше). См. Как использовать ThreeTenABP… .
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...