Java:如何将字符串(HH:MM:SS)转换为持续时间?
我想将格式为HH:MM:SS或MM:SS或SS的字符串转换为持续时间的数据类型。
解:
private ArrayList myCdDuration = new ArrayList(); 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值转换为String以进行输出/打印:
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; }
-
你的
myCdDuration
令人困惑。 您是否希望一个Duration
对象等同于字符串中指定的内容,或者一个Duration
对象列表,其中第一个包含小时,第二个分钟等? -
您不能只将
String
转换为其他对象。 您应该将值解析为数值类型,并使用DataTypeFactory
构造Duration
对象。
我假设你最终想要实现的是以秒为单位计算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;
TL;博士
无需定义自己的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)等exception。
我们并不真正想要LocalTime
因为您的输入字符串代表一段时间而不是一个时间。 但这只是第一步。
LocalTime lt = LocalTime.parse ( "08:30:00" );
Duration
为了表示所需的时间跨度,我们需要Duration
类。 此课程适用于未附加到时间轴的时间跨度。 我们可以通过从时钟时间00:00:00.0
或LocalTime.MIN
开始获取时间量来转换该LocalTime.MIN
,并且我们刚刚实例化了它。
Duration d = Duration.between ( LocalTime.MIN , lt );
编辑输入字符串
使用LocalTime
上述方法仅适用于输入字符串表示持续时间少于24小时的情况。 如果超过24小时,您将自己解析输入字符串。
类似下面的代码。 当然,实际的解析取决于解决特定输入字符串的歧义。 50:00
是50小时还是50分钟? (这种模糊性是尽可能避免这种混淆格式的强烈理由,并坚持使用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
我们可以通过简单地调用Duration::toString
通过标准ISO 8601格式生成持续时间的String来查看结果。 解析/生成字符串时,java.time类在默认情况下使用ISO 8601。 对于持续时间,标准格式为PnYnMnDTnHnMnS
,其中P
标记开头, T
将年 – 月 – 日部分与小时 – 分 – 秒部分分开。 因此,我们的八个半小时将显示为PT8H30M
。
System.out.println(“d.toString():”+ d);
d.toString():PT8H30M
收集Duration
对象
您可以创建一个List
持有Duration
类型的元素。
List 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
类型不是简单的字符串,而是通过其toString
方法生成 String对象。
如果您坚持使用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教程 。 并搜索Stack Overflow以获取许多示例和解释。 规范是JSR 310 。
从哪里获取java.time类?
- Java SE 8和SE 9及更高版本
- 内置。
- 带有捆绑实现的标准Java API的一部分。
- Java 9增加了一些小function和修复。
- Java SE 6和SE 7
- 许多java.timefunction都被反向移植到ThreeTen-Backport中的 Java 6和7。
- Android的
- ThreeTenABP项目特别适用于Android的ThreeTen-Backport (如上所述)。
- 请参见如何使用ThreeTenABP ….
ThreeTen-Extra项目使用其他类扩展了java.time。 该项目是未来可能添加到java.time的试验场。 您可以在这里找到一些有用的课程,如Interval
, YearWeek
, YearQuarter
等。
我在我的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)
我建议不要使用javax.xml.datatype.Duration
,因为它与XML Java API有关,如果你不处理XML,它会让你感到困惑。 此外,它是一个抽象类,并且在Java SE中没有非抽象的文档实现,因此您必须创建自己的非抽象实现或以某种方式获取实例(可能使用XML API) 。
您可以使用Date
和Calendar
类在Java中管理时间和日期。 要将String
转换为Date
/ Calendar
可以使用DateFormat
或SimpleDateFormat
。 这将让你执行你的持续时间算术,虽然这不是100%漂亮。
Mansoor提供了一种使用String操作手动完成任务的方法,并将持续时间作为数值处理 – 如果您只做简单的事情,那么这样做可能会更直接。
如果你必须执行更复杂的东西,你可能想要查看http://joda-time.sourceforge.net/
使用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));
示例,将当前日期时间转换为Java 7中的持续时间。
DatatypeFactory.newInstance().newDuration(Calendar.getInstance().getTimeInMillis())
输出 –
P48Y5M13DT19H59M24.658S