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

  1. 你的myCdDuration令人困惑。 您是否希望一个 Duration对象等同于字符串中指定的内容,或者一个Duration对象列表,其中第一个包含小时,第二个分钟等?

  2. 您不能只将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.0LocalTime.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.DateCalendarSimpleDateFormat

现在处于维护模式的Joda-Time项目建议迁移到java.time类。

要了解更多信息,请参阅Oracle教程 。 并搜索Stack Overflow以获取许多示例和解释。 规范是JSR 310 。

从哪里获取java.time类?

  • Java SE 8SE 9及更高版本
    • 内置。
    • 带有捆绑实现的标准Java API的一部分。
    • Java 9增加了一些小function和修复。
  • Java SE 6SE 7
    • 许多java.timefunction都被反向移植到ThreeTen-Backport中的 Java 6和7。
  • Android的
    • ThreeTenABP项目特别适用于Android的ThreeTen-Backport (如上所述)。
    • 请参见如何使用ThreeTenABP ….

ThreeTen-Extra项目使用其他类扩展了java.time。 该项目是未来可能添加到java.time的试验场。 您可以在这里找到一些有用的课程,如IntervalYearWeekYearQuarter等。

我在我的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) 。

您可以使用DateCalendar类在Java中管理时间和日期。 要将String转换为Date / Calendar可以使用DateFormatSimpleDateFormat 。 这将让你执行你的持续时间算术,虽然这不是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