【问题标题】:Java converting string date to secondsJava将字符串日期转换为秒
【发布时间】:2014-11-25 00:31:16
【问题描述】:

我有一些意见:

1h50m22s
2h40m10s
33m03s

我必须在 java 中转换为秒。

已经使用正则表达式 '\d+|\D+' 提取数字。

【问题讨论】:

  • 如果你已经用正则表达式提取了数字,有什么问题?秒 = 小时 * 60 * 60 + 分钟 * 60 + 秒
  • 这里的问题在哪里?

标签: java regex date


【解决方案1】:

乔达时间

不要重新发明轮子。 Joda-Time 库可以为您解析这些值。不需要正则表达式。

ISO 8601

这些值接近标准ISO 8601 格式。特别是Durations 格式,PnYnMnDTnHnMnSP 标志着开始,T 将日期部分与时间位置分开。如果您只有时间值,那么只需在 PT 前面加上 PT33m03s。最后转大写得到PT33M03S

Joda-Time 默认解析和生成这样的字符串。一旦您的输入采用标准格式,您就可以将其直接传递给 Joda-Time。跳过正则表达式。

或者,您可以指定 PeriodFormatter 以适合您的确切输入字符串。然后您可以解析原始输入字符串而无需转换为标准格式。

如果您对输入字符串的来源有任何控制或影响,我强烈建议您更改该来源以使用 ISO 8601 格式。

Period

接下来,使用Period 类将该值自动解析为 Period 对象。 Period 表示一个时间跨度,如数月、数天、数小时等。 与宇宙历史时间轴上的点相关联。 (如果您在时间线上有特定点,请使用 Interval 类。)

Duration

接下来,调用toStandardDuration 以获取Duration 对象。 Joda-Time 中的持续时间表示时间跨度,就像时间的流逝一样。只是几毫秒,而不是特定的月数或小时数或类似的块。

最后,在 Duration 对象上调用 getStandardSeconds 以获得您的答案。

比处理正则表达式容易得多。并且更加可靠,因为 Joda-Time 已经构建、调试、使用良好,并且能够处理可能的输入字符串的各种排列。

示例代码

使用 Joda-Time 2.5。

简洁的版本(不推荐)。

String input = ( "PT" + "33m03s" ).toUpperCase();
long durationInSeconds = Period.parse( input ).toStandardDuration().getStandardSeconds();

详细版本。

// Convert input string to standard ISO 8601 format.
// Alternatively, you could use a formatter to parse your original string rather than convert.
String inputRaw = "33m03s";
String inputStandard = "PT" + inputRaw; // Assuming this is a time-only without date portion, prepend 'PT' to make standard ISO 8601 format.
inputStandard = inputStandard.toUpperCase();

// Parse string as Period object.
Period period = Period.parse( inputStandard );

// Convert from Period to Duration to extract total seconds.
Duration duration = period.toStandardDuration();
long durationInSeconds = duration.getStandardSeconds();  // Returns getMillis() / 1000. The result is an integer division, so 2999 millis returns 2 seconds.

转储到控制台。

System.out.println( "inputRaw : " + inputRaw );
System.out.println( "inputStandard : " + inputStandard );
System.out.println( "period : " + period );  // Notice how the leading zero on the 'seconds' number is gone. We have a Period *object*, not messing with strings.
System.out.println( "duration : " + duration );
System.out.println( "durationInSeconds : " + durationInSeconds );

运行时。

inputRaw : 33m03s
inputStandard : PT33M03S
period : PT33M3S
duration : PT1983S
durationInSeconds : 1983

【讨论】:

    【解决方案2】:

    您可以使用Joda-Time 轻松做到这一点。

    首先使用 Pattern 类来提取字段:

    Pattern pattern = Pattern.compile("(?:(\\d+)h)?(?:(\\d+)m)?(?:(\\d+)s)?");
    Matcher matcher = pattern.matcher("1h50m22s");
    matcher.matches();
    String hours = matcher.group(1);
    String minutes = matcher.group(2);
    String seconds = matcher.group(3);
    
    Period period = new Period();
    if(hours != null){
        period = period.withHours(Integer.parseInt(hours));
    }
    if(minutes != null){
        period = period.withMinutes(Integer.parseInt(minutes));
    }
    if(seconds != null){
        period = period.withSeconds(Integer.parseInt(seconds));
    }
    int totalSeconds = period.toStandardSeconds().getSeconds();
    

    使用 PeriodFormatterBuilder 类(解析模式不太灵活):

    String dateText = "1h50m22s";
    PeriodFormatterBuilder formatterBuilder = new PeriodFormatterBuilder();
    
    if(dateText.contains("h")){
        formatterBuilder.appendHours().appendLiteral("h");
    }
    if(dateText.contains("m")){
        formatterBuilder.appendMinutes().appendLiteral("m");
    }
    if(dateText.contains("s")){
        formatterBuilder.appendSeconds().appendLiteral("s");
    }
    
    Period period = formatterBuilder.toFormatter().parsePeriod(dateText);
    int totalSeconds = period.toStandardSeconds().getSeconds();
    

    【讨论】:

    • 想到 Joda-Time 很好,但你工作太努力了。 Joda-Time 可以直接解析时长字符串;不需要您使用正则表达式 Pattern 类。有关详细信息和示例代码,请参阅my answer
    • 其实你这样做的方式很脆弱,很难阅读,我的代码更灵活,更容易理解。另外,我添加了一种使用 PeriodFormatterBuilder 类的替代方法,实现起来非常简单,但效率不高,请检查代码。
    • 我不明白关于易碎的说法。我们的两个答案都假设只有时间,没有任何日期部分。我们的两个答案都容忍缺少小时、分钟或秒的组成部分。那么脆度有什么区别呢?
    • 我不认为只有时间没有日期部分,我的两个例子都可以很容易地更改为使用日期部分(或其他格式),另一方面,你的不是那么灵活。
    • 不是每个人都同意正则表达式“很容易改变”,但足够公平。 ;-) 感谢您的建设性交流;可能对其他人有用。
    【解决方案3】:

    您可能想使用 String 的 substring 方法来提取您想要的数字并将其解析为整数。例如,为了获得秒数,您可以这样做:

    String time = "32h45m93s";
    String seconds = time.substring(time.indexOf('m') + 1, time.indexOf('s'));
    int seconds = Integer.parseInt(seconds);
    

    我没有运行它,但这是一般的想法。对小时和分钟做同样的事情,然后

    int totalSeconds = hours * 3600 + minutes * 60 + seconds;
    

    【讨论】:

      猜你喜欢
      • 2012-09-12
      • 2011-07-11
      • 2016-09-07
      • 1970-01-01
      • 1970-01-01
      • 2012-08-11
      • 2012-01-15
      • 1970-01-01
      相关资源
      最近更新 更多