Análisis de los valores de duración ISO-8601 del tipo de ranura AMAZON.DURATION

¿La java.timebiblioteca proporciona una forma consolidada de analizar toda la Especificación de duración ISO-8601 ?

La referencia de Alexa Slot Type para la duración enumera algunas cadenas de ejemplo que se pueden esperar al usar el tipo de ranura AMAZON.DURATION. Todas las cadenas están en duración ISO-8601, pero P2YT3H10no pueden ser analizadas por java.time.Periodo java.time.Duration.

Seq(
 "PT10M",
 "PT5H",
 "P3D",
 "PT45S",
 "P8W",
 "P7Y",
 "PT5H10M",
 "P2YT3H10"
).map { s =>
 s -> Try {
   try {
     Period.parse(s)
   } catch {
     case ex: Throwable => Duration.parse(s)
   }
 }.map(x => x.toString -> x.getClass.getSimpleName)
}
.foreach(println)

Resultados:

(PT10M,Success((PT10M,Duration)))
(PT5H,Success((PT5H,Duration)))
(P3D,Success((P3D,Period)))
(PT45S,Success((PT45S,Duration)))
(P8W,Success((P56D,Period)))
(P7Y,Success((P7Y,Period)))
(PT5H10M,Success((PT5H10M,Duration)))
(P2YT3H10,Failure(java.time.format.DateTimeParseException: Text cannot be parsed to a Duration))
Respuesta 1

La respuesta de Hugos solo se relaciona con un aspecto detallado del estándar ISO-8601, es decir, la combinación de la parte de fecha y hora con un separador "T". De hecho, este detalle no está java.timerespaldado por la biblioteca externa Threeten-Extra, pero sí lo está (usando la clase PeriodDurationen la versión v1.2). Sin embargo:

El estándar ISO-8601 describe aún más variaciones.

Una variación es el uso de semanas en la forma "P8W". Ambos java.timey Threeten-Extra lo cambian automáticamente a "P56D" pero no lo dejan en forma relacionada con la semana al analizar y formatear. Se puede obtener una vista similar al mirar los componentes de tiempo. java.time.Durationno puede almacenar horas o minutos directamente, sino convertirlo automáticamente a segundos. Al formatear también se realiza una normalización automática. Ejemplo:

System.out.println(Duration.parse("PT4200S")); // PT1H10M

Entonces, en ambos casos: lo que pones dentro durante la construcción no siempre es lo que obtienes al formatear .

Otros puntos:

  • Las representaciones de duración en ISO-8601 (como se especifica en la sección 4.4.4.2) siempre se denominan "Duración" (incluso si están relacionadas con la fecha) mientras java.timeusan dos términos diferentes, a saber, Periody Duration(ya sea relacionado con la fecha o con la hora).
  • Las duraciones relacionadas con la semana se manejan por separado ya que se describen dos formas estándar en la notación ISO-8601: "PnnYnnMnnDTnnHnnMnnS" o "PnnW".
  • Los signos no existen en la especificación ISO-8601 (ver sección 3.4.2: símbolo "n" definido como entero positivo o cero) mientras que java.timepermite signos incluso dentro de las representaciones e interpreta signos como relacionados con componentes. Tenga en cuenta que el esquema XML solo maneja los signos que preceden a la expresión de duración completa (antes de "P"), que no está relacionada con los componentes sino con la duración.
  • También se especifican representaciones alternativas de duraciones , ya sea en formato básico o extendido: "PYYYYMMDDThhmmss" resp. "PYYYY-MM-DDThh: mm: ss".
  • Manejo de segundos fraccionarios : ISO-8601 habla sobre el uso de coma o punto (e incluso prefiere explícitamente la coma) mientras java.time.Durationsolo admite el punto.

Finalmente podemos decir:

El estándar ISO-8601 solo es parcialmente compatible con java.time(y Threeten-Extra, que solo admite la combinación de las clases Periody java.time.Durationcomo detalle adicional).

Solución alternativa para el verdadero soporte ISO-8601:

Si desea o incluso necesita superar las limitaciones integradas,java.time puede usar mi biblioteca Time4J que admite todos los detalles adicionales de ISO-8601. Consulte la API de la clase net.time4j.Duration . Los siguientes ejemplos también muestran la compatibilidad con java.time:

Duration<CalendarUnit> d1 = Duration.parseCalendarPeriod("P8W");
System.out.println(d1); // P8W
System.out.println(d1.getPartialAmount(CalendarUnit.WEEKS)); // 8
System.out.println(Duration.Formatter.ofPattern(CalendarUnit.class, "W' weeks'").format(d1)); // 8 weeks
System.out.println(PrettyTime.of(Locale.GERMAN).print(d1)); // 8 Wochen
LocalDate ld = LocalDate.of(2017, 9, 17);
System.out.println(PlainDate.from(ld).plus(d1)); // 2017-11-12
System.out.println(PlainDate.of(2017, 9, 17).plus(d1)); // 2017-11-12

Duration<IsoUnit> d2 = Duration.parsePeriod("P2DT5H10M");
LocalDateTime ldt = LocalDateTime.of(2017, 9, 17, 19, 15);
System.out.println(PlainTimestamp.from(ldt).plus(d2)); // 2017-09-20T00:25
System.out.println(PlainTimestamp.of(2017, 9, 17, 19, 15).plus(d2)); // 2017-09-20T00:25
System.out.println(PrettyTime.of(Locale.GERMAN).print(d2)); // 2 Tage, 5 Stunden und 10 Minuten

Duration<IsoUnit> d3 = Duration.parsePeriod("P0001-01-02T05:10:04");
System.out.println(d3); // P1Y1M2DT5H10M4S
LocalDateTime ldt = LocalDateTime.of(2017, 9, 17, 19, 15);
System.out.println(PlainTimestamp.from(ldt).plus(d3)); // 2018-10-20T00:25:04

Nota al margen: es posible formatear duraciones en 86 idiomas.

Respuesta: 2

PD : a su entrada le falta el designador para el último campo ( P2YT3H10- 2 años, 3 horas y 10 ¿qué?). Entonces, en el código a continuación, supuse que era M(minutos), no funcionará sin un designador después 10.


La java.timeAPI ha separado la duración de ISO8601 en 2 clases :

Desafortunadamente, esas clases no pueden manejar una duración ISO8601 con campos basados ​​en fecha y hora.

Una alternativa es utilizar el proyecto ThreeTen Extra , que contiene algunas extensiones para java.timeAPI. Con esta lib, puede usar la org.threeten.extra.PeriodDurationclase , que puede analizar duraciones ISO8601 completas:

PeriodDuration pd = PeriodDuration.parse("P2YT3H10M");

Entonces puede obtener el respectivo Periody Durationde él:

System.out.println(pd.getPeriod()); // P2Y
System.out.println(pd.getDuration()); // PT3H10M

Otra alternativa es dividir Stringy analizar ambos Periody por Durationseparado:

// split in 2 parts
String input = "P2YT3H10M";
String[] v = input.split("T");
Period p;
Duration d;
if (v.length == 1) { // has only date-based fields
    p = Period.parse(input);
    d = Duration.ZERO;
} else {
    if ("P".equals(v[0])) { // has only time-based fields
        p = Period.ZERO;
    } else {
        p = Period.parse(v[0]);
    }
    d = Duration.parse("PT" + v[1]);
}

* A Durationtambién acepta días , y siempre se considera que tienen 24 horas (en Periodun día , no necesariamente tiene 24 horas debido a los efectos del horario de verano).

Respuesta: 3

Soy principiante y me mantengo en manos. Necesito probar este método: escribir / leer en / desde el archivo. ¿Puedes obtener consejos? ¿Qué mejor puedo hacer esto, usar solo prueba junit o mejor EasyMock? Que puedes ...

Estoy creando una extensión Keycloak con dependencias. Agregué la entrada en el pom.xml así: <dependency> <groupId> org.json </groupId> <artifactId> json </ ...

Hola, necesito convertir Mongo Document a DBObject (BasicDBObject). Estoy cargando un archivo a mongo usando GridFS y quiero establecer metadatos, que obtengo en el documento. Sé que Document es más o menos el ...

Tengo una ArrayList <Metadata> y quiero saber si hay una API Java para trabajar con archivos CSV que tenga un método de escritura que acepte una ArrayList <> como parámetro similar a LinqToCsv en ...