Java:如何将字符串(HH:MM:SS)转换为持续时间?

时间:2011-11-24 13:13:06

标签: java string duration

我想将格式为HH:MM:SS或MM:SS或SS的字符串转换为持续时间的数据类型。

溶液:

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

感谢您的帮助...任何更简单的方法吗? - &GT;创建自己的持续时间类:

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

8 个答案:

答案 0 :(得分:18)

我认为你最终想要达到的目的是以秒为单位计算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;

答案 1 :(得分:17)

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表示&#34;八个半小时&#34;时间跨度而不是“早上八点半”的时间,然后避免使用HH:MM:SS的格式。这种格式含糊不清,看起来像是一个时间。而是使用下面讨论的标准ISO 8601格式。

持续时间和时间是两个截然不同的概念。你必须清楚它们,每一个都应该在你的脑海中清晰。使用HH:MM:SS的模糊格式使得这种区别变得更加困难(因此避免使用这种格式!)。

java.time

现代的方法是使用java.time类。

LocalTime

首先将您的字符串解析为LocalTime。此类表示没有日期且没有时区的时间。没有时区意味着这些对象基于通用的24小时制,而不考虑Daylight Saving Time (DST)等异常情况。

我们并不真正想要LocalTime,因为您的输入字符串代表的是时间跨度而不是时间。但这只是第一步。

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

Duration

为了表示所需的时间跨度,我们需要Duration类。此课程适用于未附加到时间轴的时间跨度。我们可以通过将时间LocalTimeLocalTime.MIN以及00:00:00.0的{​​{1}}和lt的{​​{1}}转换为Duration d = Duration.between ( LocalTime.MIN , lt ); 来创建一个。刚刚实例化。

LocalTime

编辑输入字符串

使用50:00的上述方法仅在输入字符串表示持续时间少于24小时时才有效。如果超过24小时,您将自己解析输入字符串。

类似下面的代码。当然,实际的解析取决于解决特定输入字符串的歧义。 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格式。)

PnYnMnDTnHnMnS

ISO 8601

我们可以通过简单地调用ISO 8601 format for durations在标准Duration::toString中生成字符串来查看结果。解析/生成字符串时,java.time类在默认情况下使用ISO 8601。对于持续时间,标准格式为P,其中T标记开头,PT8H30M将年 - 月 - 日部分与小时 - 分 - 秒部分分开。因此,我们的八个半小时将显示为Duration

System.out.println(&#34; d.toString():&#34; + d);

  

d.toString():PT8H30M

收集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" ) ) ) ; 的{​​{1}}元素。

PT8H30M
  

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

请记住,您在该输出中看到的字符串如Duration就是:生成的字符串的输出。 LocalTime类型是一个简单的字符串,而是通过其toString方法生成一个String对象。

如果您坚持使用ISO 8601格式,您可以轻松解析以及生成此类字符串。无需完成我们在本答案顶部执行的Duration d = Duration.parse( "PT8H30M" ); 转换操作。

{{1}}

请参阅此示例code live in IdeOne.com

关于java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendar和&amp; SimpleDateFormat

现在位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310

从哪里获取java.time类?

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

答案 2 :(得分:2)

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

  2. 您不能只将String转换为其他对象。您应该将值解析为数值类型,并使用DataTypeFactory构造Duration对象。

答案 3 :(得分:2)

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

答案 4 :(得分:2)

java.time.Duration

其他几个答案已经提到 java.time 中的 Duration 类,现代 Java 日期和时间 API,是在一段时间内使用的类。有一些方法可以将您的字符串解析为 Duration,但老实说,目前尚不清楚哪种方法最好。我想展示我的方式。

基本

我从简单的一种可能的格式开始,hh:mm:ss,例如 01:30:41 为 1 小时 30 分 41 秒。

    String durationString = "01:30:41";
    
    String iso = durationString.replaceFirst(
            "^(\\d{2}):(\\d{2}):(\\d{2})$", "PT$1H$2M$3S");
    Duration dur = Duration.parse(iso);
    
    System.out.format("%-10s  Total %2d minutes or %4d seconds%n",
            dur, dur.toMinutes(), dur.toSeconds());

到目前为止的输出是:

<块引用>
PT1H30M41S  Total 90 minutes or 5441 seconds

Duration.parse 方法需要 ISO 8601 格式。它类似于 PT1H30M41S 1 小时 30 分 41 秒。所以我所做的是通过正则表达式将您的字符串转换为这种格式。我的替换字符串中的 $1 等将被正则表达式中圆括号中 groups 匹配的内容替换。因此,durationString.replaceFirst() 会将您的字符串转换为 PT01H30M41SDuration 可以解析该字符串。

三种格式

您要求转换 HH:MM:SS 或 MM:SS 或 SS。对上面的修改其实很简单:我们只需要三个调用 replaceFirst() 而不是一个。正是其中之一将成功取代任何​​东西。其他两个将只返回字符串不变。

    String[] durationStrings = { "01:32:43", "26:31", "14" };
    
    for (String durationString : durationStrings) {
        String iso = durationString.replaceFirst("^(\\d{2}):(\\d{2}):(\\d{2})$", "PT$1H$2M$3S")
                .replaceFirst("^(\\d{2}):(\\d{2})$", "PT$1M$2S")
                .replaceFirst("^(\\d{2})$", "PT$1S");
        Duration dur = Duration.parse(iso);
        
        System.out.format("%-10s  Total %2d minutes or %4d seconds%n",
                dur, dur.toMinutes(), dur.toSeconds());
    }
<块引用>
PT1H32M43S  Total 92 minutes or 5563 seconds
PT26M31S    Total 26 minutes or 1591 seconds
PT14S       Total  0 minutes or   14 seconds

Time4J 和 net.time4j.Duration

如果您对外部依赖没有问题,Time4J 库提供了一种将字符串解析为持续时间对象的更优雅的方法。我们首先声明一个格式化程序:

private static final Duration.Formatter<ClockUnit> FORMATTER 
        = Duration.formatter(ClockUnit.class, "[[hh:]mm:]ss");

格式模式字符串中的方括号将可选部分括起来,因此此格式器接受所有 hh:mm:ss、mm:ss 和仅 ss。

    for (String durationString : durationStrings) {
        Duration<ClockUnit> dur = FORMATTER.parse(durationString);

        long minutes = dur.with(ClockUnit.MINUTES.only())
                .getPartialAmount(ClockUnit.MINUTES);
        long seconds = dur.with(ClockUnit.SECONDS.only())
                .getPartialAmount(ClockUnit.SECONDS);
        
        System.out.format("%-10s  Total %2d minutes or %4d seconds%n",
                dur, minutes, seconds);
    }

输出和之前一样:

<块引用>
PT1H32M43S  Total 92 minutes or 5563 seconds
PT26M31S    Total 26 minutes or 1591 seconds
PT14S       Total  0 minutes or   14 seconds

链接

答案 5 :(得分:1)

我建议 not 使用javax.xml.datatype.Duration,因为它与XML Java API有关,如果你不处理XML,它会让你感到困惑。此外,它是一个抽象类,并且在Java SE中没有非抽象的文档实现,因此您必须创建自己的非抽象实现或以某种方式获取实例(可能使用XML API)

您可以使用DateCalendar类在Java中管理时间和日期。要将String转换为Date / Calendar,请使用DateFormatSimpleDateFormat。这将让你执行你的持续时间算术,虽然这不是100%漂亮。

Mansoor提供了一种使用字符串操作手动处理内容并将持续时间作为数值处理的方法 - 如果你只做简单的事情,那么这样做可能会更直接。

如果您必须执行更复杂的内容,可能需要查看http://joda-time.sourceforge.net/

答案 6 :(得分:0)

使用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 :(得分:0)

示例,将当前日期时间转换为Java 7中的持续时间。

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

输出 -

P48Y5M13DT19H59M24.658S