Java SimpleDateFormat («гггг-ММ-дд'ТХЧ: мм: сс'З») дает часовой пояс как IST

148

У меня есть конструктор SimpleDateFormat как

SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")

и я разбираю строку "2013-09-29T18:46:19Z".

Я читал, что здесь Z представляет GMT/UTCчасовой пояс. но когда я печатаю эту дату на консоли, она печатает IST timezne для возвращенной даты.

Теперь мой вопрос, является ли мой вывод правильным или неправильным?

Прадип Борде
источник
3
да, это то, что представляет собой «Z». Z- Часовой пояс
Вуди
5
Z = время Зулу => GMT + 0, вы явно не обслуживали свою страну;)
MushyPeas

Ответы:

251

Вы не установили часовой пояс, добавленный только Zк концу даты / времени, поэтому он будет выглядеть как дата / время по Гринвичу, но это не изменит значения.

Установите часовой пояс на GMT, и он будет правильным.

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
Питер Лори
источник
3
Если у вас есть дата, скажем 2012-12-06T06: 00: 00 без Z, означает ли это GMT?
бинарный гигант
3
@binarygiant Вы должны спросить тех, кто его отправил. Это может быть местное время отправителя.
Питер Лори
2
Часовой пояс может быть установлен на «UTC»
Prashanth
2
Вместо того, чтобы устанавливать часовой пояс во многих местах для разных библиотек и избегать конфликтов с часовым поясом вашего компьютера / ноутбука, вы всегда должны устанавливать часовой пояс JVM по умолчанию, задав системное свойство user.timezone: java -Duser.timezone = GMT ...
Кисна
100

'T'и 'Z'рассматриваются здесь как константы. Вам нужно пройти Zбез кавычек. Кроме того, вам необходимо указать часовой пояс во входной строке.

Пример: 2013-09-29T18:46:19-0700 и формат как"yyyy-MM-dd'T'HH:mm:ssZ"

Субир Кумар Сан
источник
Subir, спасибо за ваш ответ, но что такое "0700" добавляется во входную строку ??
Прадип Борде
-0700это часовой пояс, т.е. -7: 00 часов
Субир Кумар Сан
12
для -07: 00 часов, а не -0700, это будет следующим: гггг-ММ-дд'ТХЧ: мм: сс.SSSXXX
Tastybrownies
48

От строки ISO 8601 до объекта даты Java

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
sdf.parse("2013-09-29T18:46:19Z"); //prints-> Mon Sep 30 02:46:19 CST 2013

если вы не установите, TimeZone.getTimeZone("GMT")то он выведетSun Sep 29 18:46:19 CST 2013

От объекта даты Java к строке ISO 8601

И для преобразования Dateобъекта в ISO 8601 Standard ( yyyy-MM-dd'T'HH:mm:ss'Z') используйте следующий код

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));           
System.out.println(sdf.format(new Date())); //-prints-> 2015-01-22T03:23:26Z

Также обратите внимание, что без ' 'Zyyyy-MM-dd'T'HH:mm:ssZ печатает2015-01-22T03:41:02+0000

AZ_
источник
2
Это дает мне java.text.ParseException: Неразборчивая дата: "2018-05-01T18: 30: 00.000Z" @AZ_
Mansuu ....
41

Если вы хотите обработать « стандартный » JSON представление Дата , то лучше использовать этот шаблон: "yyyy-MM-dd'T'HH:mm:ssX".

Обратите внимание Xна конец. Он будет обрабатывать часовые пояса в стандарте ISO 8601 , и именно ISO 8601 создает именно это утверждение в Javascriptnew Date().toJSON()

По сравнению с другими ответами у него есть некоторые преимущества:

  1. Вам не нужно требовать от ваших клиентов отправлять дату в GMT
  2. Вам не нужно явно конвертировать ваш объект Date в GMT, используя это: sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
MyTitle
источник
1
Я использую playавтоматическое связывание форм и использую @Format.DateTimeаннотации. Использовать шаблон по умолчанию Zв конце кажется неправильным. После того, как изменился на X, это работает. Большое спасибо
трансанг
Если ваша дата указывает часовой пояс в соответствии с RFC822, например, «-0500», это работает нормально. Но для даты, такой как «2013-07-15T10: 22: 17-05: 00» (также действительный ISO8601 TZ), это перерыв. В этом случае вам нужно использовать «гггг-ММ-дд'ТХЧ: мм: ссХХХ».
Ламбарт
23

ТЛ; др

Другие ответы устарели с Java 8.

Instant                           // Represent a moment in UTC. 
.parse( "2013-09-29T18:46:19Z" )  // Parse text in standard ISO 8601 format where the `Z` means UTC, pronounces “Zulu”.
.atZone(                          // Adjust from UTC to a time zone. 
    ZoneId.of( "Asia/Kolkata" )
)                                 // Returns a `ZonedDateTime` object. 

ISO 8601

Ваш формат строки соответствует ISO 8601 . Этот стандарт определяет разумные форматы для представления различных значений даты и времени в виде текста.

java.time

Старые java.util.Date/ .Calendarи java.text.SimpleDateFormatклассы были вытеснены фреймворком java.time, встроенным в Java 8 и более поздние версии. Смотрите учебник . Избегайте старых классов, поскольку они оказались плохо продуманными, запутанными и хлопотными.

Часть плохого дизайна в старых классах укусила вас, когда toStringметод применяет текущий часовой пояс JVM по умолчанию при генерации текстового представления значения даты и времени, которое фактически находится в UTC (GMT); из лучших побуждений, но сбивает с толку.

Классы java.time по умолчанию используют форматы ISO 8601 при разборе / создании текстовых представлений значений даты и времени. Поэтому не нужно указывать шаблон разбора.

Это Instantмомент времени на UTC .

Instant instant = Instant.parse( "2013-09-29T18:46:19Z" );

Вы можете применить часовой пояс по мере необходимости для создания ZonedDateTimeобъекта.

ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( zoneId );

Таблица типов даты и времени в Java, как современных, так и устаревших

Базилик Бурк
источник
22

и если у вас нет возможности перейти на java8, лучше используйте 'yyyy-MM-dd'T'HH: mm: ssX XX ', так как это снова будет правильно проанализировано (хотя с одним X это может быть не так). .. в зависимости от вашей функции синтаксического анализа)

X генерирует: +01

XXX генерирует: +01: 00

Thirdman
источник
0

Для Java 8: вы можете использовать встроенный, java.time.format.DateTimeFormatterчтобы уменьшить вероятность опечаток, таких как

DateTimeFormatter formatter = DateTimeFormatter.ISO_ZONED_DATE_TIME;

ISO_ZONED_DATE_TIME представляет 2011-12-03T10:15:30+01:00[Europe/Paris]собой один из стандартных форматов DateTime, предоставляемых по ссылке Oracle

Niraj
источник