Ошибка в java.time.Duration

Мне нужно проанализировать Durations из строк. Java 8 предоставляет метод для использования стандарта ISO-8601 в качестве основы:

Duration.parse("p10d"); // parses as ten days
Duration.parse("pt1h"); // parses as one hour

Поскольку в стандарте указано, что «по взаимному согласию разрешается опускать символ 'T'», некоторые примеры Javadoc Durations.parse() опустите T. По их мнению, следующее выражение должно интерпретироваться как «-6 часов и +3 минуты»:

"P-6H3M"

Но я обнаружил, что все выражения без T дают DateTimeParseException. Это ошибка в методе parse() или я что-то упустил?


person steffen    schedule 10.03.2015    source источник
comment
Я думаю, что цитата о взаимном согласии относится только к T в комбинированном представлении даты и времени, а не к представлению Duration.   -  person RealSkeptic    schedule 10.03.2015


Ответы (2)


В JavaDoc документа parse() :

Буква ASCII "T" должна стоять перед первым появлением, если таковое имеется, часа, минуты или секунды раздел.

Это означает, что вы должны включать T всякий раз, когда используете H, M или S.


Однако примеры неверны:

"P-6H3M"    -- parses as "-6 hours and +3 minutes"
"-P6H3M"    -- parses as "-6 hours and -3 minutes"
"-P-6H+3M"  -- parses as "+6 hours and -3 minutes"
person Eng.Fouad    schedule 10.03.2015
comment
Лично мне бы хотелось, чтобы метод принимал такие строки, как p1d1h, в течение 25 часов (без T). Строки длительности в конфигурационных файлах очень легко читаются (например, 1d1h): добавить P перед строкой несложно, но добавить T где-нибудь в строку не так уж и просто. Только представьте, что метод начинает принимать недели и наносекунды в Java 9. Где бы вы поместили T в строке 1w1m1s1n. - person steffen; 10.03.2015
comment
@steffen T означает time sections, поэтому всегда должно стоять перед H и после D. - person Eng.Fouad; 10.03.2015
comment
Да, но H и D могут быть опущены. - person steffen; 10.03.2015
comment
T требуется, потому что M используется для месяцев и минут - person JodaStephen; 10.03.2015
comment
@JodaStephen Вы на 100% правы в отношении стандарта. Однако M в длительности всегда относится к минутам, поскольку это класс, основанный на времени (в отличие от Период). - person steffen; 10.03.2015
comment
@steffen Поскольку «Продолжительность» и «Период» используют один и тот же формат ввода, одна и та же строка ввода должна означать одно и то же для них обоих. - person Brilliand; 10.03.2015
comment
@Brilliand Единственный (!) ввод, который одновременно принимается как Duration, так и Period, на самом деле PnD (n = количество дней), и даже этот ввод не означает одно и то же! (Подробности см. в описании класса Period.) Тем не менее, я согласен с тем, что обе входные строки должны основываться на одном стандарте. - person steffen; 10.03.2015
comment
Я добавил ошибку JDK, чтобы попытаться исправить ошибку документа. - person JodaStephen; 11.03.2015

Регулярное выражение, используемое Duration.parse:

private static final Pattern PATTERN =
        Pattern.compile("([-+]?)P(?:([-+]?[0-9]+)D)?" +
                "(T(?:([-+]?[0-9]+)H)?(?:([-+]?[0-9]+)M)?(?:([-+]?[0-9]+)(?:[.,]([0-9]{0,9}))?S)?)?",
                Pattern.CASE_INSENSITIVE);

Ввод P-6H3M не соответствует этому регулярному выражению. Если его изменить на

"(T?(?:([-+]?[ ...

в четвертой строке (обратите внимание на ? после T) примеры совпадают (проверьте на http://regexpal.com/).

Итак, похоже, вы обнаружили несоответствие между кодом и JavaDoc.

person Community    schedule 10.03.2015
comment
Почему это ошибка? Во-первых, ссылка OP на стандарт относится к представлению даты и времени, а не к представлению продолжительности. Во-вторых, взаимное согласие означает, что JDK может принять решение не быть договаривающейся стороной. - person RealSkeptic; 10.03.2015
comment
Вы совершенно правы. Интерпретация стандарта, сделанная ОП, вероятно, неверна. - person ; 10.03.2015
comment
Регулярное выражение: hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/ - person kervin; 21.02.2016