SimpleDateFormat - неверный часовой пояс - PullRequest
0 голосов
/ 11 мая 2018

У меня проблема с анализом меток времени в Java.

Я ожидаю, что обе временные метки будут в одном часовом поясе (CET).

    SimpleDateFormat sdaf = new SimpleDateFormat ("dd.MM.yyyy HH:mm:ss");

    String str = "30.03.2013 06:00:00";
    sdaf.setTimeZone (TimeZone.getTimeZone ("CET"));
    java.util.Date dat = sdaf.parse (str);
    System.out.println (str + " = " + dat);

    str = "31.03.2013 05:00:00";
    sdaf.setTimeZone (TimeZone.getTimeZone ("CET"));
    dat = sdaf.parse (str);
    System.out.println (str + " = " + dat);

Но это не тот случай - см. Вывод.

30.03.2013 06:00:00 = Sat Mar 30 06:00:00 CET 2013
31.03.2013 05:00:00 = Sun Mar 31 05:00:00 CEST 2013

EDIT:

Если я меняю CET с GMT + 1, я получаю это.

 03.2013 06:00:00 = Sat Mar 30 06:00:00 CET 2013
 31.03.2013 05:00:00 = Sun Mar 31 06:00:00 CEST 2013

Кажется, правильно. Но почему CET не работает?

UTC + 1 производит

30.03.2013 06:00:00 = Sat Mar 30 07:00:00 CET 2013
31.03.2013 05:00:00 = Sun Mar 31 07:00:00 CEST 2013

что отличается от GMT + 1 - ????

Ответы [ 3 ]

0 голосов
/ 11 мая 2018

Вы можете использовать Java 8, и она более понятна и проста, чем эта.

DateTimeFormatter parse = DateTimeFormatter.ofPattern("dd.MM.yyyy hh:mm:ss.XXX");
LocalDate localDate = LocalDate.of(2013,3,30);
LocalTime localTime = LocalTime.of(6,0);

LocalDateTime dateTime = LocalDateTime.of(localDate, localTime);
ZonedDateTime zonedDateTime = dateTime.atZone(ZoneId.of("CET"));

System.out.println(zonedDateTime.format(parse));

Выход: 30.03.2013 06: 00: 00. + 01: 00

0 голосов
/ 11 мая 2018

Ответ AxelH правильный. Поэтому я не думаю, что вам действительно нужно центральноевропейское (стандартное) время для даты 31 марта.

Я хотел бы сделать еще три замечания:

  • Вы никогда не должны полагаться на любое трех или четырехбуквенное сокращение часового пояса, например CET.
  • Если вам действительно нужно центральноевропейское время, возможно , так как две африканские страны используют CET круглый год, Алжир и Тунис.
  • Избегайте устаревших SimpleDateFormat, TimeZone и Date и используйте вместо этого java.time, современный Java-интерфейс даты и времени.

Итак, мой код:

    ZoneId cetAllYear = ZoneId.of("Africa/Algiers");
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.uuuu HH:mm:ss");
    DateTimeFormatter demoFormatter 
            = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss z yyyy", Locale.ROOT);

    String str = "31.03.2013 05:00:00";
    ZonedDateTime dateTime = LocalDateTime.parse(str, formatter).atZone(cetAllYear);
    System.out.println (str + " = " + dateTime 
                            + " = " + dateTime.format(demoFormatter));

Выход:

31.03.2013 05:00:00 = 2013-03-31T05: 00 + 01: 00 [Африка / Алжир] = вс 31 марта 05:00:00 CET 2013

То же самое возможно с часовым поясом Африка / Тунис.

Избегайте трехбуквенных сокращений часовых поясов. Центральноевропейское время - это общее название для стандартного времени со смещением +01: 00, которое используется 5 месяцев в году в большом количестве европейских часовых поясов. Так что, с одной стороны, это только половина часового пояса, с другой - их много, и вы не знаете, какой из них вы получите. И тем более, когда вы указываете дату-время, которое выпадает на летнее время (DST-время года). Очень много трех и четырехбуквенных сокращений неоднозначно. Вместо этого укажите часовой пояс, например, Европа / Рим или Африка / Тунис, как регион / город .

Избегайте SimpleDateFormat и его устаревших друзей. Этот класс, как известно, проблематичен. java.time намного приятнее работать.

Ссылки

0 голосов
/ 11 мая 2018

Вы не можете получить CET часовой пояс для 31.03.2013 05: 00: 00 , поскольку он больше не был в этом часовом поясе.Чтобы понять, просто проверьте название часового пояса

  • CET: Центрально-европейское время (UTC+1 или GMT+1)
  • CEST: Центральноевропейское летнее время (UTC+2 или GMT+2)

Это летнее время, которое произошло 31 марта 2013 года в 02:00:00.Таким образом, вы не можете получить CET часовой пояс для второго свидания, поскольку он находится в летнем "часовом поясе".

Если вы проанализируете 31.03.2013 02:00:00, вы получите

31.03.2013 02:00:00 = Вс 31 марта 03:00:00 CEST 2013

Потому что в этот день в 02:00:00 наступило спасительное летнее время, которое стало 03:00:00.

Вы можете проверить это с помощью TimeZone.inDaylightTime(Date)

String str = "30.03.2013 06:00:00";
java.util.Date dat = sdaf.parse (str);
System.out.println (str + " = " + dat);
System.out.println("SDT : " + TimeZone.getTimeZone("CET").inDaylightTime(dat));

30.03.2013 06:00:00 = сб. 30 марта 06:00:00 CET 2013
SDT:false

str = "31.03.2013 02:00:00";
dat = sdaf.parse (str);
System.out.println (str + " = " + dat);
System.out.println("SDT : " + TimeZone.getTimeZone("CET").inDaylightTime(dat));

31.03.2013 02:00:00 = вс 31 марта 03:00:00 CEST 2013
SDT: true

Поскольку CET совпадает с UTC+1 или GMT+1 и CEST становятся UTC+2 или GMT+2, когда вы заставляете дату быть на GMT+1, вы получаете эквивалент CET, нобез учета параметра SDT.

Примечание. Это одна из причин, по которой LocalDateTime не беспокоится о TimeZone для большей части обработки.

...