primer - Análisis de intervalo de tiempo ISO 8601 en Java
iso 8601 pt (4)
Supongo que ya has probado Joda-Time. Al alimentar las cadenas de ejemplo de su pregunta a través de Interval.parse(Object)
revela que puede manejar "inicio y fin", "inicio y duración" y "duración y finalización", pero no campos implícitos ni repetición.
2007-03-01T13:00:00Z/2008-05-11T15:30:00Z => from 2007-03-01T13:00:00.000Z to 2008-05-11T15:30:00.000Z
2007-03-01T13:00:00Z/P1Y2M10DT2H30M => from 2007-03-01T13:00:00.000Z to 2008-05-11T15:30:00.000Z
P1Y2M10DT2H30M/2008-05-11T15:30:00Z => from 2007-03-01T13:00:00.000Z to 2008-05-11T15:30:00.000Z
2007-12-14T13:30/15:30 => java.lang.IllegalArgumentException: Invalid format: "15:30" is malformed at ":30"
R5/2008-03-01T13:00:00Z/P1Y2M10DT2H30M => java.lang.IllegalArgumentException: Invalid format: "R5"
La única otra completa biblioteca de fecha / hora que conozco es JSR-310 , que no parece manejar intervalos como estos.
En este punto, construir tus propias mejoras además de Joda-Time es probablemente tu mejor opción, lo siento. ¿Hay algún formato de intervalo ISO específico que deba manejar más allá de los que ya admite Joda-Time?
ISO 8601 define una sintaxis para representar un intervalo de tiempo.
Hay cuatro formas de expresar un intervalo de tiempo:
- Principio y fin, como "2007-03-01T13: 00: 00Z / 2008-05-11T15: 30: 00Z"
- Inicio y duración, como "2007-03-01T13: 00: 00Z / P1Y2M10DT2H30M"
- Duración y finalización, como "P1Y2M10DT2H30M / 2008-05-11T15: 30: 00Z"
- Duración solamente, como "P1Y2M10DT2H30M", con información de contexto adicional
Si falta algún elemento del valor final, se supone que es el mismo que para el valor inicial, incluida la zona horaria. Esta característica del estándar permite representaciones concisas de intervalos de tiempo. Por ejemplo, la fecha de una reunión de dos horas que incluye las horas de inicio y finalización podría simplemente mostrarse como "2007-12-14T13: 30/15: 30", donde "/ 15: 30" implica "/ 2007-12- 14T15: 30 "(la misma fecha que el inicio), o las fechas de inicio y finalización de un período de facturación mensual como" 2008-02-15 / 03-14 ", donde" / 03-14 "implica" / 2008-03 -14 "(el mismo año que el comienzo).
Además, los intervalos de repetición se forman al agregar "R [n] /" al comienzo de una expresión de intervalo, donde R se usa como la letra misma y [n] se reemplaza por el número de repeticiones. Dejar el valor de [n] significa un número ilimitado de repeticiones. Por lo tanto, para repetir el intervalo de "P1Y2M10DT2H30M" cinco veces a partir de "2008-03-01T13: 00: 00Z", utilice "R5 / 2008-03-01T13: 00: 00Z / P1Y2M10DT2H30M".
Estoy buscando un buen analizador de Java (si es posible compatible con la biblioteca Joda-Time) para analizar esta sintaxis. ¿Alguna sugerencia para una buena biblioteca?
java.time
El marco java.time integrado en Java 8 y posterior tiene un método Duration.parse
para analizar una duración formateada ISO 8601 :
java.time.Duration d = java.time.Duration.parse("PT1H2M34S");
System.out.println("Duration in seconds: " + d.get(java.time.temporal.ChronoUnit.SECONDS));
Imprime la Duration in seconds: 3754
Para cualquier persona en un proyecto que podría estar restringido al uso de bibliotecas de terceros (razones de licencia, o lo que sea), Java proporciona al menos una parte de esta capacidad, desde Java 1.6 (¿o anterior?), Utilizando javax.xml.datatype. Método DatatypeFactory.newDuration (String) y clase de duración . El método DatatypeFactory.newDuration (String) analizará una cadena en formato "PnYnMnDTnHnMnS". Estas clases están destinadas a la manipulación de XML, pero dado que XML utiliza la notación de tiempo ISO 8601, también sirven como convenientes utilidades de análisis de duración.
Ejemplo:
import javax.xml.datatype.*;
Duration dur = DatatypeFactory.newInstance().newDuration("PT5H12M36S");
int hours = dur.getHours(); // Should return 5
Personalmente, no he utilizado ningún formato de duración, excepto el 4º que me aparece, por lo que no puedo garantizar si los analiza correctamente o no.
La única biblioteca que es capaz de modelar todas las características del análisis de intervalo que desea es en realidad mi biblioteca Time4J (range-module). Ejemplos:
// case 1 (start/end)
System.out.println(MomentInterval.parseISO("2012-01-01T14:15Z/2014-06-20T16:00Z"));
// output: [2012-01-01T14:15:00Z/2014-06-20T16:00:00Z)
// case 1 (with some elements missing at end component and different offset)
System.out.println(MomentInterval.parseISO("2012-01-01T14:15Z/08-11T16:00+00:01"));
// output: [2012-01-01T14:15:00Z/2012-08-11T15:59:00Z)
// case 1 (with missing date and offset at end component)
System.out.println(MomentInterval.parseISO("2012-01-01T14:15Z/16:00"));
// output: [2012-01-01T14:15:00Z/2012-01-01T16:00:00Z)
// case 2 (start/duration)
System.out.println(MomentInterval.parseISO("2012-01-01T14:15Z/P2DT1H45M"));
// output: [2012-01-01T14:15:00Z/2012-01-03T16:00:00Z)
// case 3 (duration/end)
System.out.println(MomentInterval.parseISO("P2DT1H45M/2012-01-01T14:15Z"));
// output: [2011-12-30T12:30:00Z/2012-01-01T14:15:00Z)
// case 4 (duration only, in standard ISO-format)
Duration<IsoUnit> isoDuration = Duration.parsePeriod("P2DT1H45M");
// case 4 (duration only, in alternative representation)
Duration<IsoUnit> isoDuration = Duration.parsePeriod("P0000-01-01T15:00");
System.out.println(isoDuration); // output: P1M1DT15H
Algunas observaciones:
Existen otras clases de intervalo con capacidades de análisis similares, por ejemplo,
DateInterval
oTimestampInterval
en el paquete net.time4j.range .Para manejar duraciones solamente (que también pueden abarcar tanto unidades de calendario como de reloj), consulte también el javadoc . También hay características de formateo, vea la clase anidada
Duration.Formatter
o la versión localizadanet.time4j.PrettyTime
(actualmente en 86 idiomas).La interoperabilidad se ofrece con Java-8 (
java.time
) pero no con Joda-Time. Por ejemplo:getStartAsInstant()
ogetEndAsInstant()
pueden consultar fácilmente el componente inicial o final deMomentInterval
.
La clase IsoRecurrence admite intervalos de repetición. Ejemplo:
IsoRecurrence<MomentInterval> ir =
IsoRecurrence.parseMomentIntervals("R5/2008-03-01T13:00:00Z/P1Y2M10DT2H30M");
ir.intervalStream().forEach(System.out::println);
Salida:
[2008-03-01T13:00:00Z/2009-05-11T15:30:00Z)
[2009-05-11T15:30:00Z/2010-07-21T18:00:00Z)
[2010-07-21T18:00:00Z/2011-10-01T20:30:00Z)
[2011-10-01T20:30:00Z/2012-12-11T23:00:00Z)
[2012-12-11T23:00:00Z/2014-02-22T01:30:00Z)