Как преобразовать HH: mm: ss.SSS в миллисекунды?

У меня есть строка 00:01:30.500, которая эквивалентна 90500 миллисекундам. Я попытался использовать SimpleDateFormat, который дает миллисекунды, включая текущую дату. Мне просто нужно, чтобы представление String было миллисекундами. Должен ли я писать собственный метод, который будет разделять и вычислять миллисекунды? или Есть ли другой способ сделать это? Спасибо.

Я пробовал следующее:

        String startAfter = "00:01:30.555";
        SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss.SSS");
        Date date = dateFormat.parse(startAfter);
        System.out.println(date.getTime());

Ответы

Ответ 1

Вы можете использовать SimpleDateFormat для этого. Вам просто нужно знать 2 вещи.

  • Все даты представлены в UTC
  • .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());        
    }
}

Ответ 2

Если вы хотите самостоятельно проанализировать формат, вы можете легко сделать это с помощью регулярного выражения, например

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

Если вы хотите использовать 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 не является потокобезопасным, что иногда является болью. (Не зная ничего о вашем приложении, я не могу догадаться, имеет ли это значение.)

Лично я мог бы написать собственный метод.

Ответ 4

Используя 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();