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;
}
Ответы
Ответ 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