如何将 HH:mm:ss.SSS 转换为毫秒?

问题描述 投票:0回答:6

我有一个字符串

00:01:30.500
,相当于
90500
毫秒。我尝试使用
SimpleDateFormat
给出包括当前日期在内的毫秒数。我只需要毫秒级的字符串表示形式。我是否必须编写自定义方法来分割并计算毫秒?或者还有其他方法可以做到这一点吗?谢谢。

我尝试过如下:

        String startAfter = "00:01:30.555";
        SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss.SSS");
        Date date = dateFormat.parse(startAfter);
        System.out.println(date.getTime());
java time timestamp simpledateformat
6个回答
41
投票

您可以使用

SimpleDateFormat
来完成此操作。你只需要知道两件事。

  1. 所有日期均以 UTC 内部表示
  2. .getTime()
    返回自 1970-01-01 00:00:00 UTC 以来的毫秒数。
package se.wederbrand.milliseconds;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

public class Main {        
    public static void main(String[] args) throws Exception {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        sdf.setTimeZone(TimeZone.getTimeZone("UTC"));

        String inputString = "00:01:30.500";

        Date date = sdf.parse("1970-01-01 " + inputString);
        System.out.println("in milliseconds: " + date.getTime());        
    }
}

6
投票

如果您想自己解析格式,您可以使用正则表达式轻松完成,例如

private static Pattern pattern = Pattern.compile("(\\d{2}):(\\d{2}):(\\d{2}).(\\d{3})");

public static long dateParseRegExp(String period) {
    Matcher matcher = pattern.matcher(period);
    if (matcher.matches()) {
        return Long.parseLong(matcher.group(1)) * 3600000L 
            + Long.parseLong(matcher.group(2)) * 60000 
            + Long.parseLong(matcher.group(3)) * 1000 
            + Long.parseLong(matcher.group(4)); 
    } else {
        throw new IllegalArgumentException("Invalid format " + period);
    }
}

但是,这种解析相当宽松,会接受 99:99:99.999 并让值溢出。这可能是一个缺点,也可能是一个特点。


3
投票

使用JODA

PeriodFormatter periodFormat = new PeriodFormatterBuilder()
  .minimumParsedDigits(2)
  .appendHour() // 2 digits minimum
  .appendSeparator(":")
  .minimumParsedDigits(2)
  .appendMinute() // 2 digits minimum
  .appendSeparator(":")
  .minimumParsedDigits(2)
  .appendSecond()
  .appendSeparator(".")
  .appendMillis3Digit()
  .toFormatter();
Period result = Period.parse(string, periodFormat);
return result.toStandardDuration().getMillis();

2
投票

如果你想使用

SimpleDateFormat
,你可以写:

private final SimpleDateFormat sdf =
    new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
    { sdf.setTimeZone(TimeZone.getTimeZone("GMT")); }

private long parseTimeToMillis(final String time) throws ParseException
    { return sdf.parse("1970-01-01 " + time).getTime(); }

但是自定义方法会更有效。

SimpleDateFormat
,由于其所有日历支持、时区支持、夏令时支持等,速度相当慢。如果您确实需要其中一些功能,那么缓慢是值得的,但既然您不需要,则可能不需要。 (这取决于您调用此方法的频率,以及效率是否是您的应用程序关注的问题。)

此外,

SimpleDateFormat
是非线程安全的,这有时很痛苦。 (在不了解您的申请的情况下,我无法猜测这是否重要。)

就我个人而言,我可能会编写一个自定义方法。


1
投票

我提出两种选择:

  1. Time4J,高级外部日期、时间和时间间隔库。
  2. java.time,内置的现代 Java 日期和时间 API。

SimpleDateFormat
Date
是错误的类,因为 1 分 30.5 秒的持续时间不是日期,而且这些类早已不再合理使用。

时间4J

这是优雅的解决方案。我们首先声明一个格式化程序:

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

然后像这样解析并转换为毫秒:

    String startAfter = "00:01:30.555";
    
    Duration<ClockUnit> dur = DURATION_FORMAT.parse(startAfter);
    long milliseconds = dur.with(ClockUnit.MILLIS.only())
            .getPartialAmount(ClockUnit.MILLIS);
    
    System.out.format("%d milliseconds%n", milliseconds);

输出是:

90555 毫秒

java.time

java.time.Duration
类只能解析ISO 8601格式。所以我首先将您的字符串转换为该格式。它就像
PT00H01M30.555S
(前导零不是必需的,但我为什么要费心删除它们?)

    String startAfter = "00:01:30.555";
    
    String iso = startAfter.replaceFirst(
            "^(\\d{2}):(\\d{2}):(\\d{2}\\.\\d{3})$", "PT$1H$2M$3S");
    Duration dur = Duration.parse(iso);
    long milliseconds = dur.toMillis();
    
    System.out.format("%d milliseconds%n", milliseconds);

输出与之前相同:

90555 毫秒

与 Time4J 的另一个区别是 Java

Duration
可以直接转换为毫秒,而不需要先转换为只有毫秒的
Duration

链接


0
投票

对于 .NET / C# 如果 timeString = "00:00:00:014"

public static int GetTimeSpanInMs(string timeString)
{
    int returnValue = 0;
    try
    {
        var parts = timeString.Split(":");
        returnValue = GetNumeric(parts[0]) * 1000 * 60 * 60 + GetNumeric(parts[1]) * 1000 * 60 + GetNumeric(parts[2]) * 1000 + GetNumeric(parts[3]);
    }
    catch 
    {
        //handle
    }

    return returnValue;
}
© www.soinside.com 2019 - 2024. All rights reserved.