Часовой пояс Java при разборе DateFormat

У меня был код, который анализирует дату следующим образом:

String ALT_DATE_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
SimpleDateFormat sdf = new SimpleDateFormat(
                    ALT_DATE_TIME_FORMAT);
Date date = sdf.parse(requiredTimeStamp);

И это работало нормально, вдруг это перестало работать. Оказывается, администратор внес некоторые изменения в конфигурацию сервера, и в настоящее время дата возвращается как «2010-12-27T10:50:44.000-08:00», что не поддается анализу по приведенному выше шаблону. У меня есть два вопроса:

Во-первых, какой шаблон будет анализировать дату, возвращаемую JVM в указанном выше формате (в частности, просто «-08:00» в качестве часового пояса)? И во-вторых, где именно можно изменить такие настройки на сервере Linux RHEL 5, чтобы мы знали о таких изменениях в будущем?


person shipmaster    schedule 27.12.2010    source источник


Ответы (8)


Другое приложение использует формат даты и времени ISO 8601. Я предполагаю, что другое приложение отправляет вам XML-ответ, соответствующий типу dateTime XML-схемы, то есть ISO 8601. Известно, что DateFormat не может анализировать этот формат. Вам либо нужно использовать другие библиотеки, такие как joda-time (joda-time — победитель), либо FastDateFormat, как указано в других ответах. Посмотрите на этот пост Преобразование строки, совместимой с ISO 8601, в java.util.Date

person Aravind Yarram    schedule 28.12.2010
comment
Библиотека Joda-Time работает, но сейчас находится в режиме обслуживания. Команда советует перейти на классы java.time. - person Basil Bourque; 06.09.2016

tl;dr

OffsetDateTime.parse( "2010-12-27T10:50:44.000-08:00" )

ИСО 8601

Формат входной строки определяется в стандарте ISO 8601, семействе форматов даты и времени.

Избегайте старых классов даты и времени

Вопрос и другие ответы используют старые устаревшие классы даты и времени, связанные с самыми ранними версиями Java. Избежать их. Теперь вытеснены классами java.time.

Использование java.time

Ваша входная строка заканчивается смещением от UTC. Поэтому мы анализируем как объект OffsetDateTime.

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

OffsetDateTime odt = OffsetDateTime.parse( "2010-12-27T10:50:44.000-08:00" );

Если вы хотите просмотреть это значение даты и времени как момент на временной шкале в формате UTC, извлеките файл Instant.

Instant instant = odt.toInstant();

Часовой пояс — это смещение плюс набор правил для обработки аномалий, таких как переход на летнее время (DST). Если вы имеете в виду часовой пояс, примените ZoneId, чтобы получить объект ZonedDateTime. Тот же момент на временной шкале, но просмотр через другое настенные часы.

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = odt.atZoneSameInstant( z );  // Same moment on the timeline, but viewed through a different wall-clock time.


О java.time

java.time framework встроен в Java 8 и более поздние версии. Эти классы заменяют проблемные старые устаревшие классы даты и времени, такие как java.util.Date, Calendar и SimpleDateFormat.

Проект Joda-Time, теперь в режим обслуживания, советует перейти на java.time.

Дополнительные сведения см. в Учебном руководстве по Oracle. . И поищите множество примеров и пояснений в Stack Overflow. Спецификация: JSR 310.

Вы можете обмениваться объектами java.time непосредственно с вашей базой данных. Используйте драйвер JDBC, совместимый с JDBC 4.2 или более поздней версии. Нет необходимости в строках, нет необходимости в java.sql.* классах.

Где получить классы java.time?

  • Java SE 8, Java SE 9, and later
    • Built-in.
    • Часть стандартного Java API со встроенной реализацией.
    • Java 9 добавляет некоторые незначительные функции и исправления.
  • Java SE 6 and Java SE 7
    • Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
  • Android

Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является испытательным полигоном для возможных дополнений к java.time в будущем. Здесь вы можете найти несколько полезных классов, таких как Interval, YearWeek, YearQuarter и подробнее.

person Basil Bourque    schedule 05.09.2016

Если вы хотите разобрать его с помощью прямого JDK, я считаю, что его можно разобрать с помощью утилит JAXB, см. DatatypeFactory.newXMLGregorianCalendar или DatatypeConverter.parseDateTime.

person jtahlborn    schedule 28.12.2010

Используйте JodaTime

В качестве более конкретного примера предложения @Pangea использовать JodaTime это то, что вы могли бы использовать:

String timestamp = "2012-09-17T04:11:46Z";

DateTime date = ISODateTimeFormat.dateTimeParser().parseDateTime(timestamp);

Это правильно распознает часовой пояс UTC. Я не пробовал использовать миллисекунды в отметке времени строки, но я уверен, что это сработает так же хорошо.

Надеюсь, это поможет другим.

JP

person Joshua Pinter    schedule 10.12.2013
comment
К вашему сведению: проект Joda-Time теперь находится в режим обслуживания, рекомендуется переход на java.time. - person Basil Bourque; 29.12.2016
comment
@BasilBourque Спасибо, что указали на это! При использовании Java SE 8+ рекомендуется перейти на java.time. Рад видеть, что эти улучшения внедряются в ядро. - person Joshua Pinter; 02.01.2017
comment
Большая часть функций java.time обратно перенесена на Java 6 и 7 в ThreeTen-Backport. Дальнейшая адаптация для Android в проекте ThreeTenABP. - person Basil Bourque; 02.01.2017
comment
К вашему сведению, все эти проекты (Joda-Time, JSR 310, java.time классы, ThreeTen-Backport и ThreeTen-Extra) возглавляет один и тот же человек, Стивен Колебурн. - person Basil Bourque; 05.07.2018

Вопрос должен заключаться в том, откуда берется requiredTimeStamp и в каком формате. Введен ли он пользователем или прочитан из другой программы? Какой компонент создает дату в представлении String?

Формат "2010-12-27T10:50:44.000-08:00" выглядит как стандартный формат ISO-8601 Это должно быть разборчиво с шаблоном yyyy-MM-dd'T'HH:mm:ss.SSSZ

Не уверен, какие настройки влияют на это, но есть Часто задаваемые вопросы Oracle о Java. Часовые пояса. Это может быть системное свойство user.timezone или символическая ссылка /etc/localtime в RHEL.

person mhaller    schedule 28.12.2010
comment
Извините, я не был ясен. requiredTimeStamp генерируется java-приложением на сервере (не на нашем) и отправляется как часть ответа службы. Кажется, он использует некоторые настройки сервера по умолчанию, поскольку они меняются при реконфигурации сервера. Отметка времени «-08:00» не может быть проанализирована Z в шаблоне даже в изолированном модульном тесте на моей машине, Z может анализировать «-0800» или «GMT-08:00», но не «-08:00». '. - person shipmaster; 28.12.2010

SimpleDateFormat принимает только -0800 или GMT-08:00 в качестве часового пояса.

Кажется, формат ISO 8601 не может быть проанализирован с помощью SimpleDateFormat. Возможно, вам следует взглянуть на Apache Commons Lang на FastDateFormat. Он совместим с SimpleDateFormat, но принимает шаблон ZZ для часового пояса, который должен анализировать нужный вам формат часового пояса. DateFormatUtils содержит несколько примеров констант которые выглядят как шаблон, который вам нужен, только без миллисекунд (например, ISO_DATETIME_TIME_ZONE_FORMAT).

person Reboot    schedule 28.12.2010
comment
Насколько я мог судить, FastDateFormat не поддерживает синтаксический анализ. - person shipmaster; 28.12.2010
comment
Кажется, ты прав. Поскольку он реализует стандартный интерфейс Format, я предположил, что он также будет анализировать формат, например SimpleDateFormat. Я не проверял комментарии для методов синтаксического анализа. - person Reboot; 29.12.2010

Попробуйте изменить его на нижний регистр z.

z обрабатывает большую часть общего синтаксиса общего часового пояса, в то время как Z использует более строгий часовой пояс RFC 822 с 4 цифрами.

Хотя задокументировано, что оба должны анализировать «Общие настройки часового пояса», это может иметь значение в вашем случае.

person jbx    schedule 28.12.2010

если все еще ищете ответ, это сработало для меня

Мой ввод: 2020-12-08T10:36:53.939+05:30
Мой вывод: Вт, 08 декабря, 10:36:53 IST 2020

Вы можете преобразовать эту дату в любой формат, который вам нужен!

private static Date convertDate(String input) {
    Date newDate = null;
    try {
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
        newDate=dateFormat.parse(input);  
    } catch (Exception e) {
        e.printStackTrace();
    }
    return newDate;
}
person Srikanth Josyula    schedule 08.12.2020