Java: Как преобразовать строку (ЧЧ: ММ: СС) в длительность? - PullRequest
17 голосов
/ 24 ноября 2011

Я хочу преобразовать строку с форматом ЧЧ: ММ: СС или ММ: СС или СС в тип данных Длительность.

Решение:

    private ArrayList<Duration> myCdDuration = new ArrayList<Duration>();

        private void convert(String aDuration) {

            chooseNewDuration(stringToInt(splitDuration(aDuration))); //stringToInt() returns an int[] and splitDuration() returns a String[]
        }

        private void chooseNewDuration(int[] array) {
            int elements = array.length;
            switch (elements) {
            case 1:
                myCdDuration.add(newDuration(true, 0, 0, 0, 0, 0, array[0]));
                break;
            case 2:
                myCdDuration.add(newDuration(true, 0, 0, 0, 0, array[0], array[1]));
                break;
            case 3:
                myCdDuration.add(newDuration(true, 0, 0, 0, array[0], array[1],
                        array[2]));
                break;
            }
        }

спасибо за помощь ... есть ли более простой способ сделать это? -> создать свой собственный класс продолжительности:

public class Duration {
        private int intSongDuration;
        private String printSongDuration;

        public String getPrintSongDuration() {
            return printSongDuration;
        }

        public void setPrintSongDuration(int songDuration) {
            printSongDuration = intToStringDuration(songDuration);
        }

        public int getIntSongDuration() {
            return intSongDuration;
        }

        public void setIntSongDuration(int songDuration) {
            intSongDuration = songDuration;
        }

        public Duration(int songDuration) {

            setIntSongDuration(songDuration);
        }

Преобразует значение int в строку для вывода / печати:

private String intToStringDuration(int aDuration) {
    String result = "";

    int hours = 0, minutes = 0, seconds = 0;

    hours = aDuration / 3600;
    minutes = (aDuration - hours * 3600) / 60;
    seconds = (aDuration - (hours * 3600 + minutes * 60));

    result = String.format("%02d:%02d:%02d", hours, minutes, seconds);
    return result;
}

Ответы [ 7 ]

18 голосов
/ 24 ноября 2011

Полагаю, в конечном итоге вы пытаетесь рассчитать продолжительность компакт-диска в секундах.

Есть несколько способов сделать это, но я думаю, что самым простым является просто разделить на :, чтобы получить поля часов, минут и секунд, а затем вычислить продолжительность вручную:

String timestampStr = "14:35:06";
String[] tokens = timestampStr.split(":");
int hours = Integer.parseInt(tokens[0]);
int minutes = Integer.parseInt(tokens[1]);
int seconds = Integer.parseInt(tokens[2]);
int duration = 3600 * hours + 60 * minutes + seconds;
17 голосов
/ 04 января 2017

ТЛ; др

Нет необходимости определять свой собственный класс Duration, поскольку Java предоставляет его.

Duration.between (                  // Represent a span of time of hours, minutes, seconds. 
    LocalTime.MIN ,                 // 00:00:00
    LocalTime.parse ( "08:30:00" )  // Parse text as a time-of-day. 
)                                   // Returns a `Duration` object, a span-of-time. 
.toString()                         // Generate a `String` with text in standard ISO 8601 format. 

PT8H30M

И анализировать стандартный форматированный текст ISO 8601.

Duration.parse( "PT8H30M" )   // Parse standard ISO 8601 text yo get a `Duration` object. 

Избегать HH:MM:SS формат

Если под строкой 08:30:00 вы подразумеваете промежуток времени «восемь с половиной часов», а не время суток «половина восьмого утра», тогда избегайте этого формата HH:MM:SS. Этот формат неоднозначен, кажется, время суток. Вместо этого используйте стандартный формат ISO 8601, описанный ниже.

Продолжительность и время суток - два совершенно разных понятия. Вы должны быть ясны с ними, каждый должен быть ясным в вашем уме. Использование неоднозначного формата HH: MM: SS делает это различие еще более трудным (поэтому избегайте этого формата!).

java.time

Современный способ - классы java.time.

LocalTime

Сначала проанализируйте вашу строку как LocalTime. Этот класс представляет время суток без даты и без часового пояса. Отсутствие часового пояса означает, что эти объекты основаны на общих 24-часовых часах без учета таких аномалий, как Летнее время (DST) .

Нам на самом деле не нужно LocalTime, поскольку ваша входная строка представляет промежуток времени, а не время суток. Но это только первый шаг.

LocalTime lt = LocalTime.parse ( "08:30:00" );

Duration

Для представления желаемого промежутка времени нам нужен класс Duration. Этот класс предназначен для промежутков времени, не привязанных к временной шкале. Мы можем создать его, преобразовав это LocalTime, получив количество времени от начала часов времени, 00:00:00.0 или LocalTime.MIN и lt, который мы только что создали ,

Duration d = Duration.between ( LocalTime.MIN , lt );

Редактирование строки ввода

Подход, описанный выше с использованием LocalTime, работает, только если ваши входные строки представляют продолжительность менее 24 часов. Если прошло более 24 часов, вы сами проанализируете входную строку.

Что-то вроде следующего кода. Конечно, фактический анализ зависит от разрешения неоднозначности вашей конкретной входной строки. 50:00 - это пятьдесят или пятьдесят минут? (Эта двусмысленность является веской причиной, чтобы по возможности избегать этого запутанного формата и придерживаться форматов ISO 8601.)

String input = "50:00";  // Or "50:00:00" (fifty hours, either way)

String[] parts = input.split ( ":" );
Duration d = Duration.ZERO;
if ( parts.length == 3 ) {
    int hours = Integer.parseInt ( parts[ 0 ] );
    int minutes = Integer.parseInt ( parts[ 1 ] );
    int seconds = Integer.parseInt ( parts[ 2 ] );
    d = d.plusHours ( hours ).plusMinutes ( minutes ).plusSeconds ( seconds );
} else if ( parts.length == 2 ) {
    int hours = Integer.parseInt ( parts[ 0 ] );
    int minutes = Integer.parseInt ( parts[ 1 ] );
    d = d.plusHours ( hours ).plusMinutes ( minutes );
} else {
    System.out.println ( "ERROR - Unexpected input." );
}

ISO 8601

Мы можем увидеть результат, сгенерировав строку в стандартном формате ISO 8601 для длительностей , просто вызвав Duration::toString. Классы java.time по умолчанию используют ISO 8601 при разборе / генерации строк. Для длительностей стандартным форматом является PnYnMnDTnHnMnS, где P отмечает начало, а T отделяет часть лет-месяцев-дней от части часов-минут-секунд. Итак, наши восемь с половиной часов будут выглядеть как PT8H30M.

System.out.println ("d.toString ():" + d);

d.toString (): PT8H30M

Сбор Duration объектов

Вы можете сделать List удерживающие элементы типа Duration.

List<Duration> durations = new ArrayList<>( 3 );  // Initial capacity of 3 elements.
durations.add( d ) ;
durations.add( Duration.between ( LocalTime.MIN , LocalTime.parse ( "03:00:00" ) ) ) ;
durations.add( Duration.between ( LocalTime.MIN , LocalTime.parse ( "01:15:00" ) ) ) ;

durations.toString (): [PT8H30M, PT3H, PT1H15M]

Помните, что строки, которые вы видите в этом выводе, такие как PT8H30M, - это просто вывод сгенерированных строк. Тип Duration - это не простая строка, а скорее генерирует объект String с помощью метода toString.

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

Duration d = Duration.parse( "PT8H30M" );

См. Этот пример код вживую в IdeOne.com .


О java.time

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

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

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

Где получить классы java.time?

  • Java SE 8 и SE 9 и более поздних
    • Встроенный,
    • Часть стандартного Java API с встроенной реализацией.
    • Java 9 добавляет некоторые незначительные функции и исправления.
  • Java SE 6 и SE 7
    • Большая часть функций java.time перенесена на Java 6 & 7 в ThreeTen-Backport .
  • Android

Проект ThreeTen-Extra расширяет java.time дополнительными классами.Этот проект является полигоном для возможных будущих дополнений к java.time.Здесь вы можете найти некоторые полезные классы, такие как Interval, YearWeek, YearQuarter и more .

2 голосов
/ 29 мая 2016

Я написал этот метод в своем классе utils для разбора различных типов строк продолжительности.Это довольно гибко:

public static int getSecondsFromFormattedDuration(String duration){
        if(duration==null)
            return 0;
        try{

            Pattern patternDuration = Pattern.compile("\\d+(?::\\d+){0,2}");

            int hours = 0;
            int minutes = 0;
            int seconds = 0;
            if(patternDuration.matcher(duration).matches()){
                String[] tokens = duration.split(":");
                if(tokens.length==1){
                    seconds = Integer.parseInt(tokens[0]);
                }else if(tokens.length == 2){
                    minutes = Integer.parseInt(tokens[0]);
                    seconds = Integer.parseInt(tokens[1]);
                }else{
                    hours = Integer.parseInt(tokens[0]);
                    minutes = Integer.parseInt(tokens[1]);
                    seconds = Integer.parseInt(tokens[2]);
                }

                return 3600 * hours + 60 * minutes + seconds;
            }else
                return 0;

        }catch (NumberFormatException ignored){
            return 0;
        }

}

Вот как он проанализировал эти длительности:

"1"   -->  1
"10"  -->  10
"10:"   -->  0  (not a valid duration)
"10:07"   -->  607
"06:08"   -->  368
"7:22"   -->  442
":22"   -->  0  (not a valid duration)
"10:32:33"   -->  37953
"2:33:22"   -->  9202
"2:2:02"   -->  7322
"2:33:43:32"   -->  0  (not a valid duration)
"33ff"   -->  0  (not a valid duration)
"2d:33"   -->  0  (not a valid duration)
2 голосов
/ 24 ноября 2011
  1. Ваш myCdDuration сбивает с толку.Вам нужен один Duration объект, эквивалентный тому, что было указано в строке, или список Duration объектов, где первый содержит часы, вторые минуты и т. Д.?

  2. Вы не можете просто наложить String на какой-то другой объект.Вы должны разобрать значение в числовой тип и использовать DataTypeFactory для создания объекта Duration.

1 голос
/ 24 ноября 2011

Я бы предложил , а не , используя javax.xml.datatype.Duration, так как он связан с XML Java API, и использование его сбивает с толку, если вы не имеете дело с XML. Более того, это абстрактный класс, и в Java SE нет неабстрактной документированной реализации, поэтому вам придется либо создать собственную неабстрактную реализацию, либо каким-либо образом получить экземпляр (возможно, играя с XML API) .

Вы управляете временем и датами в Java, используя классы Date и Calendar. Для преобразования String с в Date / Calendar вы используете DateFormat или SimpleDateFormat. Это позволит вам выполнить арифметику длительности, хотя это не на 100% красиво.

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

Если вам нужно выполнить более сложные вещи, вы можете заглянуть в http://joda -time.sourceforge.net /

0 голосов
/ 14 июня 2018

Пример, преобразование текущего DateTime в длительность в Java 7.

DatatypeFactory.newInstance().newDuration(Calendar.getInstance().getTimeInMillis())

Выход -

P48Y5M13DT19H59M24.658S

0 голосов
/ 09 ноября 2016

С Java 8 и Java.time.Duration вы можете сделать это, учитывая, что строка имеет формат ЧЧ: ММ: СС или ММ: СС или СС

Duration.ofSeconds(Arrays.stream(runtime.split(":"))
                  .mapToInt(n -> Integer.parseInt(n))
                  .reduce(0, (n, m) -> n * 60 + m));
...