ISO 8601 Анализ интервала времени в Java

17

ISO 8601 определяет синтаксис представления временного интервала.

Существует четыре способа выражения временного интервала:

  • Начало и конец, например «2007-03-01T13: 00: 00Z / 2008-05-11T15: 30: 00Z»
  • Начало и продолжительность, такие как «2007-03-01T13: 00: 00Z / P1Y2M10DT2H30M»
  • Продолжительность и конец, например «P1Y2M10DT2H30M / 2008-05-11T15: 30: 00Z»
  • Только продолжительность, например «P1Y2M10DT2H30M», с дополнительной информацией о контексте

Если какие-либо элементы отсутствуют в конечном значении, они считаются такими же, как для начального значения, включая часовой пояс. Эта особенность стандарта позволяет получить краткие представления временных интервалов. Например, дата двухчасового собрания, включая время начала и окончания, может быть просто показана как «2007-12-14T13: 30/15: 30», где «/ 15: 30» означает «/ 2007-12- 14T15: 30 "(на ту же дату, что и начало), или даты начала и окончания месячного расчетного периода как« 2008-02-15 / 03-14 », где« / 03-14 »подразумевает« / 2008-03 -14 "(в том же году, что и начало).

Кроме того, повторяющиеся интервалы формируются путем добавления «R [n] /» в начало интерпольного выражения, где R используется как сама буква, а [n] заменяется числом повторений. Оставляя значение для [n], означает неограниченное количество повторений. Итак, чтобы повторить интервал «P1Y2M10DT2H30M» пять раз, начиная с «2008-03-01T13: 00: 00Z», используйте «R5 / 2008-03-01T13: 00: 00Z / P1Y2M10DT2H30M».

Я ищу хороший Java-анализатор (если возможно, совместимый с библиотекой Joda-Time), чтобы проанализировать этот синтаксис. Любые указатели на хорошую библиотеку?

    
задан fellahst 12.04.2013 в 19:42
источник

4 ответа

15

java.time

Структура java.time , встроенная в Java 8 и позже имеет Duration.parse для анализа длительности отформатированного ISO 8601 :

java.time.Duration d = java.time.Duration.parse("PT1H2M34S");
System.out.println("Duration in seconds: " + d.get(java.time.temporal.ChronoUnit.SECONDS));

Отпечатки Duration in seconds: 3754

    
ответ дан Shaun Parker 24.11.2015 в 05:30
источник
10

Для тех, кто в проекте, который может быть ограничен использованием сторонних библиотек (причины лицензирования или что-то еще), сама Java предоставляет хотя бы часть этой возможности, поскольку Java 1.6 (или ранее?), используя javax.xml.datatype.DatatypeFactory.newDuration (String) и Продолжительность класса. Метод DatatypeFactory.newDuration (String) будет анализировать строку в формате «PnYnMnDTnHnMnS». Эти классы предназначены для манипуляций с XML, но поскольку XML использует временные обозначения ISO 8601, они также служат удобными утилитами для синтаксического разбора.

Пример:

import javax.xml.datatype.*;

Duration dur = DatatypeFactory.newInstance().newDuration("PT5H12M36S");
int hours = dur.getHours(); // Should return 5

Я лично не использовал формат продолжительности, кроме 4-го, который вы перечисляете, поэтому я не могу ручаться за то, успешно ли он разбирает их или нет.

    
ответ дан Ogre Psalm33 28.02.2014 в 18:05
источник
8

Я так понимаю, вы уже пробовали Joda-Time? Подача строк примера из вашего вопроса через Interval.parse(Object) показывает, что он может обрабатывать «начало и конец», «начало и продолжительность» и «продолжительность и конец», но не подразумеваемые поля и повторение.

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"

Единственная другая исчерпывающая библиотека времени / времени, о которой я знаю, - JSR-310 , который, как представляется, не обрабатывает такие интервалы.

На данный момент, создание ваших собственных улучшений поверх Joda-Time - это, вероятно, ваш лучший выбор, извините. Существуют ли какие-либо конкретные форматы интервала ISO, которые вам нужно обрабатывать, помимо тех, которые уже поддерживаются Joda-Time?

    
ответ дан Barend 13.04.2013 в 00:26
источник
6

Единственная библиотека, которая способна моделировать все функции анализа интервала, которые вы хотите , на самом деле является моей библиотекой Time4J (диапазон-модуль). Примеры:

// 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

Некоторые замечания:

  • Другие классы интервалов существуют с аналогичными возможностями синтаксического анализа, например DateInterval или TimestampInterval в пакете net.time4j.range .

  • Только для обработки продолжительности (которая может охватывать как календарные, так и часы), см. также Javadoc . Существуют также функции форматирования, см. Вложенный класс Duration.Formatter или локализованная версия net.time4j.PrettyTime (на самом деле на 86 языках).

  • Взаимодействие предлагается с Java-8 ( java.time -package), но не с Joda-Time. Например: начальный или конечный компонент MomentInterval можно легко запросить getStartAsInstant() или getEndAsInstant() .

Повторяющиеся интервалы поддерживаются классом IsoRecurrence . Пример:

IsoRecurrence<MomentInterval> ir =
    IsoRecurrence.parseMomentIntervals("R5/2008-03-01T13:00:00Z/P1Y2M10DT2H30M");
ir.intervalStream().forEach(System.out::println);

Вывод:

[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)
    
ответ дан Meno Hochschild 19.06.2017 в 07:21
источник