Подтвердить что ты не робот

Java: Как преобразовать строку (HH: MM: SS) в продолжительность?

Я хочу преобразовать строку с форматом HH: MM: SS или MM: SS или SS в тип данных Duration.

решение:

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

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

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;
}
4b9b3361

Ответ 1

  • Ваш myCdDuration запутан. Вы хотите, чтобы один объект Duration эквивалентен тому, что было указано в строке, или список объектов Duration, где первый содержит часы, секунды и т.д.?

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

Ответ 2

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

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

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;

Ответ 3

ТЛ; др

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

Duration.between ( 
    LocalTime.MIN , 
    LocalTime.parse ( "08:30:00" ) 
).toString()

PT8H30M

Избегайте HH:MM:SS формат 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

Мы можем увидеть результат, создав String в стандартном формате ISO 8601 для продолжительности, просто называя Duration::toString. Классы java.time используют ISO 8601 по умолчанию при разборе/генерации строк. Для продолжительности стандартный формат - PnYnMnDTnHnMnS где P обозначает начало, а T отделяет часть years-months-days от части часов-минут-секунд. Итак, наши восемь с половиной часов появятся как 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 преобразования rigamarole мы провели на вершине этого ответа.

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

См. Этот пример кода в реальном времени на IdeOne.com.


О java.time

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

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

Чтобы узнать больше, ознакомьтесь с учебным пособием Oracle. И поиск Qaru для многих примеров и объяснений. Спецификация - 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 и другие.

Ответ 4

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

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

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

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

Ответ 5

Я написал этот метод в своем классе 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)

Ответ 6

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

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

Ответ 7

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

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

Вывод -

P48Y5M13DT19H59M24.658S