2012-01-11 42 views
15

Tengo una cadena 00:01:30.500 que es equivalente a 90500 milisegundos. Intenté usar SimpleDateFormat que dan milisegundos incluyendo la fecha actual. Solo necesito esa representación de cadena a milisegundos. ¿Tengo que escribir un método personalizado, que se dividirá y calculará milisegundos? o ¿Hay alguna otra forma de hacer esto? Gracias.Cómo convertir HH: mm: ss.SSS a milisegundos?

He tratado de la siguiente manera:

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

¿Qué patrón usó para crear SimpleDateFormat? ¿Puedes publicar el código? –

Respuesta

31

Puede utilizar SimpleDateFormat para hacerlo. Solo debes saber 2 cosas.

  1. Todas las fechas se representan internamente en UTC
  2. .getTime() devuelve el número de milisegundos desde 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());   
    } 
} 
+1

No es necesario preceder yyyy-MM-dd y 1970-01-01. El análisis como el OP funcionó si la zona horaria está configurada en GMT. –

+0

@JBNizet verdadero y un buen punto. Incluí deliberadamente la información de la fecha extra porque creo que muestra mejor lo que está sucediendo realmente. –

+0

@AndreasWederbrand: El "truco" que lo hace funcionar aquí es establecer el día para el 1 de enero de 1970. Pero supongamos que si no doy este día, ¿funcionará? –

2

Si desea utilizar SimpleDateFormat, se podría escribir:

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

Pero un método personalizado sería mucho más eficiente. SimpleDateFormat, debido a todo su soporte de calendario, soporte de zona horaria, soporte de horario de verano, etc., es bastante lento. La lentitud vale la pena si realmente necesita algunas de esas características, pero como no es así, podría no serlo. (Depende de la frecuencia con la que llame a este método, y si la eficiencia es una preocupación para su aplicación).

Además, SimpleDateFormat no es seguro para subprocesos, lo que en ocasiones es un problema. (Sin saber nada sobre su aplicación, no puedo adivinar si eso importa.)

Personalmente, probablemente escribiría un método personalizado.

+0

No es necesario preceder yyyy-MM-dd y 1970-01-01. El análisis como el OP funcionó si la zona horaria está configurada en GMT. –

+0

@JBNizet: en mi sistema es cierto, pero el OP escribió que su enfoque dio "milisegundos incluyendo la fecha actual", por lo que asumí que la implementación de su JDK de 'SimpleDateFormat' no debe estar llamando' calendar.clear () '. No veo nada en el Javadoc que indique que 'SimpleDateFormat' debe estar predeterminado a 1970-01-01. ¿Sabes si eso está garantizado? – ruakh

1

Usando 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(); 
3

Si desea analizar el formato de sí mismo que podía hacerlo fácilmente con una expresión regular como

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

Sin embargo, este análisis es bastante indulgentes y aceptarían 99 : 99: 99.999 y simplemente deje que los valores se desborden. Esto podría ser un inconveniente o una característica.

+0

Hola, he usado su enfoque, pero da el resultado con un carácter añadido entre, es esto debido a L que ha usado con 3600000 – Prateek

+0

Probablemente no, la L es para hacerlo más largo. ¿Qué parte da el resultado con a -? La fechaParseRegExp devuelve un largo que no tiene un - (a menos que sea negativo). ¿Es uno de los grupos coincidentes que tiene el -? –

+0

OOPS no por L mi mal. – Prateek

Cuestiones relacionadas