Подтвердить что ты не робот

Joda Time анализирует дату с часовым поясом и сохраняет этот часовой пояс

Я хочу проанализировать дату, созданную с определенным часовым поясом, преобразовать ее в формат и вернуть ее. Преобразование работает, но смещение часового пояса всегда установлено на +0000, когда разница во времени добавляется/вычитается по мере необходимости. Как я могу получить его для форматирования и правильной коррекции?

Я ожидаю этого: 2012-11-30T12: 08: 56.23 + 07: 00

Но получите это: 2012-11-30T05: 08: 56.23 + 00: 00

Реализация:

public static final String ISO_8601_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSZZ";

public static String formatDateToISO8601Standard(Date date) {
    DateTime dateTime = new DateTime(date);
    DateTimeFormatter df = DateTimeFormat.forPattern(ISO_8601_DATE_FORMAT);
    return dateTime.toString(df);
}

Класс тестирования:

private static final String DATE_WITH_TIMEZONE = "30 11 2012 12:08:56.235 +0700";
private static final String EXPECTED_DATE_WITH_TIMEZONE = "2012-11-30T12:08:56.23+07:00";

@Test public void testFormattingDateWithSpecificTimezone() throws Exception {
    String result = JodaDateUtil.formatDateToISO8601Standard(createDate(DATE_WITH_TIMEZONE));
    assertEquals("The date was not converted correctly", EXPECTED_DATE_WITH_TIMEZONE, result); }

private Date createDate(String dateToParse) throws ParseException {
    DateTimeFormatter df = DateTimeFormat.forPattern("dd MM yyyy HH:mm:ss.SSS Z");
    DateTime temp = df.parseDateTime(dateToParse);
    Date date = temp.toDate();
    return date; }
4b9b3361

Ответ 1

В принципе, как только вы проанализируете строку даты [в методе createDate()], вы потеряли исходную зону. Joda-Time позволит вам форматировать дату в любой зоне, но вам нужно сохранить исходную зону.

В вашем методе createDate() DateTimeFormatter "df" может вернуть зону, которая была в строке. Вам нужно будет использовать метод withOffsetParsed(). Затем, когда у вас есть DateTime, вызовите getZone(). Если вы сохраните эту зону где-нибудь или каким-то образом передадите ее в свою процедуру форматирования, вы можете использовать ее там, создав DateTimeFormatter "withZone" и указав, что зона как таковая вы хотите в формате.

Как демонстрационный пример, здесь приведен пример кода в одном методе. Надеюсь, это поможет изменить код так, как вы хотите его запустить.

  public static void testDate() 
  {
    DateTimeFormatter df = DateTimeFormat.forPattern("dd MM yyyy HH:mm:ss.SSS Z");
    DateTime temp = df.withOffsetParsed().parseDateTime("30 11 2012 12:08:56.235 +0700");
    DateTimeZone theZone = temp.getZone();

    Date date = temp.toDate();

    DateTime dateTime = new DateTime(date);
    DateTimeFormatter df2 = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSZZ");
    DateTimeFormatter df3 = df2.withZone(theZone);

    System.out.println(dateTime.toString(df2));
    System.out.println(dateTime.toString(df3));

  }

Ответ 2

Попробуйте это.

ISODateTimeFormat.dateTimeParser().parseDateTime(dateString), 

затем преобразуйте его в желаемый формат.

Ответ 3

Принятый ответ правильный. Как только вы конвертируете в объект java.util.Date, вы теряете информацию о часовом поясе. Это осложняется тем фактом, что java.util.Date::toString смешивает текущий часовой пояс по умолчанию при создании строки.

Не используйте эти старые классы времени, например java.util.Date. Они плохо разработаны, запутываются и хлопотны. Теперь наследие, вытесненное проектом java.time. Так же проект Joda-Time теперь вытесняется классами java.time.

java.time

Разберите эту входную строку как объект OffsetDateTime, поскольку она включает в себя смещение-от-UTC, но не имеет часового пояса. Вызовите DateTimeFormatter.ofPattern, чтобы указать собственный формат, соответствующий вашей входной строке. Передайте этот объект форматирования OffsetDateTime.parse.

String input = "30 11 2012 12:08:56.235 +0700";
DateTimeFormatter f = DateTimeFormatter.ofPattern ( "dd MM uuuu HH:mm:ss.SSS X" , Locale.US );
OffsetDateTime odt = OffsetDateTime.parse ( input , f );

odt: toString(): 2012-11-30T12: 08: 56.235 + 07: 00

Чтобы увидеть тот же самый момент в UTC, извлеките Instant. Класс Instant представляет момент на временной шкале в UTC с разрешением наносекунды (до девяти (9) цифр десятичной дроби).

Instant instant = odt.toInstant();

instant.toString(): 2012-11-30T05: 08: 56.235Z

Вы можете применить любой часовой пояс, через который вы хотите просмотреть тот же момент, ту же точку на временной шкале.

ZonedDateTime zdtKolkata = odt.toInstant ().atZone ( ZoneId.of ( "Asia/Kolkata" ) );

zdtKolkata.toString(): 2012-11-30T10: 38: 56.235 + 05: 30 [Азия/Калькутта]

Не нужно смешивать старые классы времени. Придерживайтесь java.time. Если вы должны использовать какой-то старый код, еще не обновленный до типов java.time, посмотрите на новые методы, добавленные к старым классам для преобразования в/из java.time.

Эквивалент java.util.Date равен Instant, оба являются точкой отсчета с 1970-01-01T00:00:00Z в UTC. Но остерегайтесь потери данных, поскольку классы java.time поддерживают наносекундное разрешение, но старые классы ограничены миллисекундами.

java.util.Date utilDate = java.util.Date.from( instant );

Живой код

Смотрите живой рабочий код в IdeOne.com.


О java.time

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

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

Чтобы узнать больше, см. Учебник Oracle. И поиск Qaru для многих примеров и объяснений. Спецификация JSR 310.

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

  • Java SE 8 и SE 9 и позже
    • Встроенный.
    • Часть стандартного Java API с объединенной реализацией.
    • Java 9 добавляет некоторые незначительные функции и исправления.
  • Java SE 6 и SE 7
    • Большая часть функциональных возможностей java.time портирована на Java 6 и 7 в ThreeTen-Backport.
  • Android

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