String to ZonedDateTime меняет формат

String ip = "2011-05-01T06:47:35.422-05:00";
ZonedDateTime mzt = ZonedDateTime.parse(ip).toInstant().atZone(ZoneOffset.UTC);
System.out.println(mzt);

System.out.println("-----");

String ip2 = "2011-05-01T00:00:00.000-05:00";
ZonedDateTime mzt2 = ZonedDateTime.parse(ip2).toInstant().atZone(ZoneOffset.UTC);
System.out.println(mzt2);

Выход:

2011-05-01T11:47:35.422Z
-----
2011-05-01T05:00Z

Почему в случае 2 меняется формат даты? Из-за этого я получаю ошибку базы данных SQLServer.

Кстати, вы используете неправильный класс для своих входных данных и своих манипуляций. OffsetDateTime здесь подходит, тогда как ZonedDateTime подходит, когда у вас есть часовой пояс, Continent/Region, такой как America/Montreal или Africa/Tunis. А когда вам нужен UTC, просто используйте Instant.

Basil Bourque 02.05.2018 03:19

Пожалуйста, прочтите документация класса, прежде чем размещать вопрос о таком простом вызове метода.

Basil Bourque 02.05.2018 03:25
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
2
2 900
2

Ответы 2

Это то, что toString из документации сказал

The format used will be the shortest that outputs the full value of the time where the omitted parts are implied to be zero.

Для решения этой проблемы вам понадобится другой форматтер:

String result = mzt2.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss:SSS'Z'"));

Выход

2011-05-01T11:47:35.422Z
2011-05-01T05:00:00:000Z

Ваш ответ дает правильный результат. Но мне нужен объект ZonedDateTime

Sujan Davangere Sunil 01.05.2018 20:19

@SujanDavangereSunil У вас уже есть ZonedDateTime Object, но вы не можете получить ожидаемый результат, потому что, когда вы попытаетесь распечатать этот объект, он вызовет метод toString, поэтому этот метод вернет тот результат, которым вы поделились. поделитесь, пожалуйста, дополнительной информацией о вашей проблеме, чтобы мы могли помочь вам ее решить?

YCF_L 01.05.2018 20:23

Я напечатал здесь System.out, чтобы увидеть результат. Все, что мне нужно, - это объект ZonedDateTimeObject в этом формате, а это случай 1.

Sujan Davangere Sunil 01.05.2018 20:27

ZonedDateTime не может иметь формат. У него есть только метод toString, и вы не можете изменить его работу. Если вам нужен конкретный формат, вам необходимо иметь этот формат в String (а не в ZonedDateTime). Это также существенное различие: используйте ZonedDateTime для вашей модели и String для вашей презентации. Кроме того, зачем вам этот конкретный формат, если ISO 8601 дает свободу, которую берет toString?

Ole V.V. 01.05.2018 20:34

@SujanDavangereSunil прочитал комментарий Оле В.В. пожалуйста, ответьте на ваш предыдущий вопрос

YCF_L 01.05.2018 20:49

Я хочу, чтобы значение mzt2 было 2011-05-01T05: 00: 00: 000Z. Использование System.out.print будет использовать средство форматирования для печати этого. В моем случае я делаю запись в базе данных, для которой требуется, чтобы значение объекта ZonedDateTime было 2011-05-01T05: 00: 00: 000Z

Sujan Davangere Sunil 14.05.2018 00:40

@SujanDavangereSunil У вас есть XY проблема. Вы думаете, что ваша проблема в том, что toString() генерирует неправильную строку для вставки в базу данных, тогда как ваша настоящая проблема заключается в том, что вы вообще вызываете toString(). Не конвертируйте значение даты в строку для вставки в базу данных, вставляйте само значение даты. Если ваш драйвер JDBC не может обрабатывать новые объекты Java Time, вместо этого преобразуйте их в Timestamp.

Andreas 30.01.2020 05:50

Просто чтобы дополнить ответ YCF_L:

Использование буквы в кавычках в шаблоне, как это было сделано с Z (внутри кавычек: 'Z'), неправильно. Это будет рассматривать Z как литерал и игнорировать смещение объекта.

В данном конкретном случае, это работает, но буква «Z» в конце означает, что дата указана в формате UTC, и вы не можете жестко запрограммировать ее как литерал. Помещение его в кавычки всегда будет печатать «Z» независимо от смещения, что приведет к неверным результатам.

Пример:

// wrong: it uses Z inside quotes
DateTimeFormatter wrong = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss:SSS'Z'");

// correct: it uses the offset pattern (X)
DateTimeFormatter correct = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss:SSSXXX");

// print a date/time not in UTC
String ip2 = "2011-05-01T00:00:00.000-05:00";
ZonedDateTime mzt = ZonedDateTime.parse(ip2);

System.out.println(mzt.format(wrong)); // 2011-05-01T00:00:00:000Z
System.out.println(mzt.format(correct)); // 2011-05-01T00:00:00:000-05:00

Обратите внимание, что неправильный форматтер печатает Z, что неверно, потому что смещение mzt равно -05:00.

Неправильный форматтер работает для вашего случая, потому что вы используете UTC:

// convert to UTC
ZonedDateTime mzt2 = mzt.withZoneSameInstant(ZoneOffset.UTC);
System.out.println(mzt2.format(wrong)); // 2011-05-01T05:00:00:000Z
System.out.println(mzt2.format(correct)); // 2011-05-01T05:00:00:000Z

В этом случае оба средства форматирования выводят правильный результат, но это совпадение, потому что mzt2 находится в формате UTC (поэтому смещение равно "Z"). Но для любого смещения, отличного от UTC, будет работать только правильный форматер.

Также обратите внимание, что я использовал withZoneSameInstant, который дает тот же результат, что и использование .toInstant().atZone(ZoneOffset.UTC).

Другие вопросы по теме