Java DateTimeFormatter для часового пояса с необязательным разделителем двоеточия?

Я пытаюсь создать DateTimeFormatter, который может принимать смещение с двоеточием или смещение без двоеточия.

Есть ли способ пройти этот тест:

DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss[X]");
dateTimeFormatter.parse("2015-01-28T10:21:44+0100"); // OK
dateTimeFormatter.parse("2015-01-28T10:21:44+01:00"); // KO

person Nelson G.    schedule 06.01.2016    source источник
comment
Двоеточие, которое вы считаете необязательным, является фиксированной частью части смещения зоны. Вы можете выбирать только между шаблонными буквами X (без двоеточия) или XXX (с двоеточием). Это означает, что смещение всей зоны является необязательным, а не только двоеточие внутри.   -  person Meno Hochschild    schedule 06.01.2016
comment
Согласен, должно работать. Но когда я использую [X], он ожидает смещение без двоеточия, а когда я использую [XXX], он ожидает смещение с двоеточием. Я не могу использовать оба вместе.   -  person Nelson G.    schedule 06.01.2016
comment
Согласно Javadoc: с символом X приведены примеры тезисов: Z; -08; -0830; -08:30; -083015; -08:30:15;   -  person Nelson G.    schedule 06.01.2016
comment
Пожалуйста, прочитайте раздел javadoc Смещение X и x. Он точно описывает, какое количество букв X,x связано с представлением какого формата. Итак, у нас есть: ХХ (без двоеточия) и ХХХ (с двоеточием). X (без двоеточия) делает минутную часть необязательной.   -  person Meno Hochschild    schedule 06.01.2016


Ответы (2)


Это: yyyy-MM-dd'T'HH:mm:ss[XXX][X] кажется, работает.

DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss[XXX][X]");
dateTimeFormatter.parse("2015-01-28T10:21:44+0100");
dateTimeFormatter.parse("2015-01-28T10:21:44+01:00");
person Titus    schedule 06.01.2016
comment
Да, это работает! Я пробовал [X][XXX] (не работает), но не [XXX][X]. Спасибо! - person Nelson G.; 06.01.2016
comment
Один экзотический аспект: если вход содержит ДВА смещения, то это тоже может быть проанализировано. - person Meno Hochschild; 06.01.2016

Вот окончательное сопоставление с образцом для почти всего, что похоже на строку даты в формате ISO!

"[yyyyMMdd][yyyy-MM-dd][yyyy-DDD]['T'[HHmmss][HHmm][HH:mm:ss][HH:mm][.SSSSSSSSS][.SSSSSS][.SSS][.SS][.S]][OOOO][O][z][XXXXX][XXXX]['['VV']']"

Это работает для следующего списка тестов, кроме двух в комментариях, но я до сих пор не знаю, почему...

    ZonedDateTime dt = DateTimeUtils.parse("2016-10-27T16:36:08.993+02:00:00[Europe/Paris]");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08.993+02:00[Europe/Paris]");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08.993+020000[Europe/Paris]");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08.993+0200[Europe/Paris]");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08.993+0000[Europe/Paris]");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08.993Z[Europe/Paris]");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08.993GMT+1[Europe/Paris]");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08.993UTC[Europe/Paris]");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08.993PST[Europe/Paris]");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08.993[Europe/Paris]");

    dt = DateTimeUtils.parse("2016-10-27T16:36:08+02:00[Europe/Paris]");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08+020000[Europe/Paris]");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08+0200[Europe/Paris]");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08+0000[Europe/Paris]");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08Z[Europe/Paris]");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08GMT+1[Europe/Paris]");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08UTC[Europe/Paris]");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08PST[Europe/Paris]");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08[Europe/Paris]");

    dt = DateTimeUtils.parse("2016-10-27T16:36:08.993+02:00:00");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08.993+02:00");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08.993+020000");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08.993+0200");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08.993+0000");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08.993Z");
    //dt = DateTimeUtils.parse("2016-10-27T16:36:08.993GMT+1");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08.993UTC");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08.993PST");

    dt = DateTimeUtils.parse("2016-10-27T16:36:08.993");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08.000993");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08.000000993");

    dt = DateTimeUtils.parse("2016-10-27T16:36:08+02:00:00");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08+02:00");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08+020000");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08+0200");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08+0000");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08Z");
    //dt = DateTimeUtils.parse("2016-10-27T16:36:08GMT+1");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08UTC");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08PST");
    dt = DateTimeUtils.parse("2016-10-27T16:36:08");

    dt = DateTimeUtils.parse("2016-100T16:36:08Z");
    dt = DateTimeUtils.parse("2016-100T16:36.1Z");
    dt = DateTimeUtils.parse("2016-10-27");

    dt = DateTimeUtils.parse("20161223T163608");
    dt = DateTimeUtils.parse("20161223T1636");

И сам метод разбора:

public static ZonedDateTime parse(CharSequence text) {
    TemporalAccessor temporalAccessor = LOOSE_ISO_DATE_TIME_ZONE_PARSER.parseBest(text, ZonedDateTime::from, LocalDateTime::from, LocalDate::from);
    if (temporalAccessor instanceof ZonedDateTime) {
        return ((ZonedDateTime) temporalAccessor);
    }
    if (temporalAccessor instanceof LocalDateTime) {
        return ((LocalDateTime) temporalAccessor).atZone(ZoneId.systemDefault());
    }
    return ((LocalDate) temporalAccessor).atStartOfDay(ZoneId.systemDefault());
}
person Philippe B.    schedule 31.10.2016
comment
Я предполагаю, что это не работает для тех, кто в комментариях, потому что вы не учли +1 после GMT. Конечно, я не узнаю этих выражений, но, кажется, нигде нет знака +? - person junkfoodjunkie; 31.10.2016
comment
Предполагается, что он распознает GMT+1 в целом, как и для 2016-10-27T16:36:08.993GMT+1[Европа/Париж]. - person Philippe B.; 31.10.2016
comment
Хорошо - Европа/Париж заканчивается текстом/кареткой, а те, которые не работают, заканчиваются +1 - я мог бы что-то там :) - person junkfoodjunkie; 31.10.2016
comment
ПОЧТИ ИДЕАЛЬНО, НО, когда смещение идет без двоеточия, синтаксический анализ не заканчивается с ошибкой, но смещение не распознается, вот вывод для 2016-10-27T16:36:08.993+020000 ==› 2016-10-27T16 :36:08.993Z, Я думаю, это проблема парсера, ищу немного больше. - person tonio; 13.02.2017
comment
Вот DateTimeFormatterBuilder. Вы можете узнать, что означает XXXX или VV и так далее. - person Cnfn; 29.10.2018
comment
Спасибо @PhilippeB. - person Nelson G.; 09.11.2018
comment
2016-10-27T16:36:08.993Z , не удалось разобрать этот формат. Любые решения? @PhilippeB. @тонио - person sSD; 06.11.2019