2011-06-19 14 views
31

Alguien sabe de una biblioteca Java que puede analizar cadenas de tiempo como "30min" o "2h 15min" o "2d 15h 30min" como milisegundos (o algún tipo de objeto Duration). ¿Puede Joda-Time hacer algo como esto?cadenas de tiempo de análisis como "1h 30min"

(no tengo un método a largo fea para mantener que hace tal análisis y le gustaría deshacerse de él/reemplazarlo con algo que hace un mejor trabajo.)

+0

He visto este "Xd Yh Zm" o "Xd Yh Zmin" referido como "notación JIRA", pero no sé si ese término está muy extendido. – Jonik

Respuesta

29

Es probable que tenga que ajustar esto un poco para su propio formato, pero intenta algo en este sentido:

PeriodFormatter formatter = new PeriodFormatterBuilder() 
    .appendDays().appendSuffix("d ") 
    .appendHours().appendSuffix("h ") 
    .appendMinutes().appendSuffix("min") 
    .toFormatter(); 

Period p = formatter.parsePeriod("2d 5h 30min"); 

en cuenta que hay un appendSuffix que toma un parámetro variants si es necesario hacerlo mas flexible.

actualización: desde Joda Time ha añadido Period.toStandardDuration(), y desde allí se puede utilizar getStandardSeconds() para obtener el tiempo transcurrido en segundos como un long.

Si está utilizando una versión anterior sin estos métodos, aún puede calcular una marca de tiempo usted mismo asumiendo el estándar 24/hr en un día, 60min/hora, etc. (En este caso, aproveche las constantes en la clase DateTimeConstants para evitar la necesidad de números mágicos.)

+0

+1: pásamelo. –

+1

¡Gracias! Con pequeños ajustes hago que haga lo que quiero, y es bastante mejor que el monstruo de regex/máquina de estado de 150 líneas al que me enfrenté. (Por cierto, para la conversión 'Period' -> millis,' DateTimeConstants' de Joda contiene constantes útiles como 'MILLIS_PER_DAY'.) – Jonik

-1

No hay, por defecto Joda a tomar sólo duraciones, Intervalos instantáneos y objetos. Para este último, acepta cosas como el formato ISO Fechas o SOAP. Puede agregar su propio convertidor aquí para la clase de Duración, y es cierto que ocultaría todo su código feo.

12

Quería que el día, la hora y los minutos fueran opcionales y esto parece funcionar para hacer eso. Tenga en cuenta que las llamadas appendSuffix() no tienen un espacio después del carácter.

Usando Joda 2.3.

PeriodParser parser = new PeriodFormatterBuilder() 
     .appendDays().appendSuffix("d").appendSeparatorIfFieldsAfter(" ") 
     .appendHours().appendSuffix("h").appendSeparatorIfFieldsAfter(" ") 
     .appendMinutes().appendSuffix("min") 
     .toParser(); 

El código anterior supera estas pruebas.

@Test 
public void testConvert() { 
    DurationConverter c = new DurationConverter(); 

    Duration d; 
    Duration expected; 

    d = c.convert("1d"); 
    expected = Duration.ZERO 
      .withDurationAdded(Duration.standardDays(1),1); 
    assertEquals(d, expected); 

    d = c.convert("1d 1h 1min"); 
    expected = Duration.ZERO 
      .withDurationAdded(Duration.standardDays(1),1) 
      .withDurationAdded(Duration.standardHours(1),1) 
      .withDurationAdded(Duration.standardMinutes(1),1); 
    assertEquals(d, expected); 


    d = c.convert("1h 1min"); 
    expected = Duration.ZERO 
      .withDurationAdded(Duration.standardHours(1),1) 
      .withDurationAdded(Duration.standardMinutes(1),1); 
    assertEquals(d, expected); 

    d = c.convert("1h"); 
    expected = Duration.ZERO 
      .withDurationAdded(Duration.standardHours(1),1); 
    assertEquals(d, expected); 

    d = c.convert("1min"); 
    expected = Duration.ZERO 
      .withDurationAdded(Duration.standardMinutes(1),1); 
    assertEquals(d, expected); 

} 
+0

' PeriodParser' se entiende principalmente como una interfaz interna. 'PeriodFormatter' es la API orientada al usuario. –

+0

donde se define 'DurationConverter'? –

+0

Aunque originalmente pensé que esto era útil, no maneja correctamente la entrada no válida. O al menos puede, pero eso sería en la implementación de DurationConverter que no podemos ver. –

23

El análisis de duración se incluye ahora en Java 8. Use el formato estándar ISO 8601 con Duration.parse.

Duration d = Duration.parse("PT1H30M") 

Puede convert this duration a la longitud total en milisegundos. Tenga en cuenta que Duration tiene una resolución de nanosegundos, por lo que puede perder datos desde nanoseconds hasta milliseconds.

long milliseconds = d.toMillis(); 

El formato es ligeramente diferente de lo que describes, pero se puede traducir fácilmente de uno a otro.

+2

Esto también agrega la ventaja de admitir el estándar ISO8601 para la duración. La cadena ISO debe coincidir con la forma P [yY] [mM] [dD] [T [hH] [mM] [s [.s] S]]. Utiliza clases estándar de Java en Java 8 y también hay backports para Java 6 y 7, vea: http://www.threeten.org/threetenbp/ – theINtoy

+0

No estoy seguro si es compatible con el estándar ISO8601 completo, específicamente una cadena con semanas : P2W, por ejemplo, no es analizable, pero creo que es válido según el estándar. Los documentos de 'Duración' dicen:" Obtiene una Duración de una cadena de texto como PnDTnHnMn.nS ". –

Cuestiones relacionadas