DateTimeFormatter.ISO_OFFSET_DATE_TIME не работает должным образом - PullRequest
0 голосов
/ 27 июня 2018

На основе этого Java Date Time - OffsetDateTime.format () Примеры статьи и этой официальной документации для DateTimeFormatter Я ожидаю, что мой OffsetDateTime будет сериализован как 2011-12-03T10:15:30+00:00, где смещение смещение составляет +00:00 с момента его UTC.

Мне не удается получить OffsetDateTime для рендеринга со смещением, он всегда рендерится с Z-Zulu. Что я делаю не так?

enter image description here

Это Spring Boot 2.0.0.RELEASE , и, как вы можете видеть на скриншоте, у меня есть следующие модули на пути к классам и они зарегистрированы в objectMapper, хотя я не думаю, что это относительно, потому что эта проблема, кажется, напрямую связана с DateTimeFormatter, мой объектный преобразователь просто использует форматер, который я даю.

Это оказывает влияние, потому что, как вы можете видеть на втором скриншоте, когда я указываю BASIC_ISO_FORMAT, оно дает другой результат.

У меня есть это свойство, установленное spring.jackson.date-format= com.fasterxml.jackson.databind.util.ISO8601DateFormat в моем application.properties, но, насколько я понимаю, это не влияет на OffsetDateTime, оно поддерживает только устаревшие объекты Date из предыдущей версии java. Случайно изменение этого, кажется, не имеет никакого эффекта, как ожидалось.

Любая помощь будет оценена.

Использование формата ISO_ZONED_DATE_TIME ... Using ISO_ZONED_DATE_TIME format

Использование BASIC_ISO_FORMAT ... это действительно влияет, так что я знаю, что форматировщик что-то делает, я просто не понимаю, почему ISO_ZONED_DATE_TIME не отображается должным образом. Using BASIC_ISO_FORMAT

 this.objectMapper = objectMapperBuilder.build()      
      .setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE)
      .disable(SerializationFeature.INDENT_OUTPUT)
      .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
      .disable(SerializationFeature.WRITE_DATES_WITH_ZONE_ID);

 SimpleModule simpleModule = new SimpleModule();
 simpleModule.addSerializer(OffsetDateTime.class, new JsonSerializer<OffsetDateTime>() {
        @Override
        public void serialize(OffsetDateTime offsetDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
            String formattedDate = DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(offsetDateTime);
            jsonGenerator.writeString(formattedDate);
        }
    });
this.objectMapper.registerModule(simpleModule);

OffsetDateTime now = OffsetDateTime.now();
TimeZone defaultTimeZone = TimeZone.getDefault();
ZoneId defautlZoneOffset = ZoneOffset.systemDefault();
String serializedOffsetDateTime = this.objectMapper.writeValueAsString(now);
//returns -> "2018-06-27T11:45:56.035Z"

Ответы [ 2 ]

0 голосов
/ 29 июня 2018

Как вы знаете, форматирование смещения нуля (или Zulu) как Z должно работать. Это часть стандартного формата, который вы используете, ISO 8601. Однако, если он не:

    static DateTimeFormatter formatter
            = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssxxx");

    @Override
    public void serialize(OffsetDateTime offsetDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        String formattedDate = formatter.format(offsetDateTime);
        jsonGenerator.writeString(formattedDate);
    }

Это будет сериализовать OffsetDateTime как, например, 2011-12-03T10:14:30+00:00 (что также допустимо в рамках стандарта). Нижний регистр x в строке шаблона формата форматирует смещение, не прибегая к Z для смещения ноль.

Выше приведено краткое и простое объявление форматера. Поскольку я предпочитаю полагаться на стандартные элементы более высокого уровня, я могу рассмотреть более длинный вариант:

    static DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .append(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
            .appendPattern("xxx")
            .toFormatter();

Это повторно использует ISO_LOCAL_DATE_TIME из стандартной библиотеки. Если у вашего времени нет доли секунды, результат будет таким же. Если он есть, он будет включен в сериализацию в последнем случае, так же, как это было бы с ISO_OFFSET_DATE_TIME, например 2011-12-03T10:14:30.1234+00:00.

Ссылка: Статья в Википедии: ISO 8601

0 голосов
/ 28 июня 2018

Функция, а не ошибка

В документации для DateTimeFormatter. ISO_OFFSET_DATE_TIME указано, что при использовании смещения нуля (* UTC) ожидается Z, а не +00:00.

Этот документ говорит:

Формат состоит из:

• ISO_LOCAL_DATE_TIME

• Идентификатор смещения.

Перейдите по ссылке для второго элемента, ID смещения . На этой странице написано:

Существует три формата:

• Z - для UTC (ISO-8601)

• + чч: мм или -чч: мм - если секунды равны нулю (ISO-8601)

• + чч: мм: сс или -чч: мм: сс - если секунды отличны от нуля (не ISO-8601)

Z является частью стандарта ISO 8601 . Любая приличная библиотека времени и даты должна иметь возможность анализировать строку с Z.

Если вы настаиваете на +00:00, а не на более распространенном Z, вам нужно будет указать пользовательский шаблон форматирования, как обсуждалось в Вопросе , связанном с Оле В.В.

Нет такой вещи, как -00:00

Смещение

составляет -00: 00 с момента его UTC.

Вы используете -00:00 в Вопросе неправильно. Стандарт ISO 8601 специально запрещает такое значение. Смещение для самого UTC - это положительный ноль, а не отрицательный ноль: +00:00.

Существует RFC 3339 , который провозглашает себя «профилем» ISO 8601. RFC нарушает ISO 8601, допуская использование -00:00 и присваивая ему значение неизвестного смещения. Очень плохой и неразумный выбор, имхо, запутанный и ненужный. ISO 8601 уже учитывает неизвестное смещение: просто полностью опустите обозначение смещения.

Я рекомендую избегать как этой практики отрицательного нуля, так и RFC 3339.

...