Почему при преобразовании даты из строки в другой часовой пояс Java?

У меня есть строки дат в формате ГГГГММДД, которые я пытаюсь разобрать на даты с помощью средства форматирования даты, полученного как

public static DateFormat getDateFormat() {
  SimpleDateFormat result = new SimpleDateFormat("yyyyMMdd");                  
  result.setLenient(false);
  return result;
}

Я устанавливаю часовой пояс по умолчанию, когда программа работает как

public static void doTheDateZoneInit() {
    TimeZone tzone = TimeZone.getTimeZone("Europe/London");
    TimeZone.setDefault(tzone);
}

Когда я форматирую даты и выводю их без указания часового пояса в строке печати

Date myDate= getDateFormat().parse("20110331");
System.out.println("Date after it is formatted:" + myDate);

Вывод находится в часовом поясе BST.

Date after it is formatted:Thu Mar 31 01:00:00 BST 2011

Если я запускаю одно и то же снова и снова с разными датами, я получаю разные результаты

  • 20120331 >> BST >> Дата после форматирования: Sat Mar 31 01:00:00 BST 2012
  • 20121231 >> GMT >> Дата после форматирования: Mon Dec 31 00:00:00 GMT 2012
  • 20130328 >> ​​GMT >> Дата после форматирования: Thu Mar 28 00:00:00 GMT 2013
  • 20130331 >> GMT >> Дата после форматирования: Sun 31 Mar 00:00:00 GMT 2013
  • 20140331 >> BST >> Дата после форматирования: Mon Mar 31 01:00:00 BST 2014
  • 20130401 >> BST >> Дата после форматирования: Mon Apr 01 01:00:00 BST 2013
  • 20130402 >> BST >> Дата после форматирования: Tue Apr 02 01:00:00 BST 2013
  • 20130501 >> BST >> Дата после форматирования: среда, 01 мая, 01:00:00, 2013 г.

Похоже, что есть диапазон с 2012 по 2013 год, где все рассчитываются по Гринвичу. Понятия не имею, почему это происходит.

Дело в том, что я добавляю к этим датам часы окончания рабочего дня ... например. Я вызываю следующий метод с датами, которые я преобразовал из String, и добавляю к нему 23: 59: 59: 999, чтобы получить самое позднее время для указанной даты.

public static Date addAlmostOneDay(Date startDate) {
    Calendar cal = new GregorianCalendar();
    cal.setTime(startDate);
    cal.add(Calendar.HOUR, 23);
    cal.add(Calendar.MINUTE, 59);
    cal.add(Calendar.SECOND, 59);
    cal.add(Calendar.MILLISECOND, 999);
    return cal.getTime();
}

Но в случае, когда он преобразовался в GMT, если бы я добавил 23:59:59 ... он не устанавливает дату в конец исходной даты, но учитывает разницу во времени между BST и GMT

  • Вс 31 марта 00:00:00 GMT 2013 становится Mon Apr 01 00:59:59 BST 2013 (следующий день + 1 час), в то время как
  • Пн 01 апреля 01:00:00 BST 2013 становится Mon Apr 01 23:59:59 BST 2013 (конец сегодняшнего дня - это то, что я хочу)

Может ли кто-нибудь пролить свет на то, почему это, похоже, происходит. Один и тот же код запускается с разными входами в форматах ГГГММДД?


person Chrispie    schedule 17.03.2013    source источник
comment
Я не понимаю. Вы устанавливаете часовой пояс по умолчанию на BST, затем печатаете дату и удивляетесь, что дата выводится в часовом поясе BST? Разве этого не ожидали? Или я что-то упустил? Не могли бы вы опубликовать SSCCE, рассказать нам, чего вы ожидаете от него и что он делает вместо этого?   -  person JB Nizet    schedule 17.03.2013


Ответы (2)


Хорошо, я думаю, я понял, что вы имели в виду. Вы устанавливаете часовой пояс по умолчанию в Лондон.

Летом Лондон находится в часовом поясе британского летнего времени (BST). Зимой это часовой пояс по Гринвичу. И день, когда происходит смена часового пояса, меняется из года в год.

person JB Nizet    schedule 17.03.2013
comment
Спасибо, JB ... Это имеет смысл. Я из Южной Африки, где время всегда одинаково. Имеет гораздо больше смысла. :) - person Chrispie; 17.03.2013
comment
@Chrispie Да, переход на летнее время - это настоящее групповое безумие. Чрезвычайно разрушительное и дорогостоящее мероприятие без какой-либо доказанной пользы. Как правило, при обработке информации лучше всего обрабатывать и хранить значения данных и времени в формате UTC (без смещения часового пояса). Затем преобразуйте в значения с временным поясом только для представления пользователю. - person Basil Bourque; 08.04.2014

BST - британское летнее время и действительный часовой пояс для Лондона с 31 марта 2013 г. по 27 октября 2013 г. и с 30 марта 2014 г. по 26 октября 2014 г.

Между этими датами выбор Европа / Лондон в качестве часового пояса даст вам BST, зимой правильный часовой пояс для Лондона - GMT, что согласуется с вашим выводом.

person beny23    schedule 17.03.2013