Добавление дней в часовой пояс Java Eastern European Summer Time (EEST)

Я написал приложение Java, в котором я начинаю дату с 1 января 00:00 определенного года. Затем я увеличиваю день на 355 раз и по ходу дела распечатываю результаты. Я пытался понять, как часовые пояса работают с летним временем, и если добавление 1 дня сместит время с полуночи на 1:00 при переходе на летнее время. Мой код выглядит так:

TimeZone tz = TimeZone.getDefault();
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss z");
sdf.setTimeZone(tz);
Calendar cal = Calendar.getInstance(tz);
cal.set(2008, 0, 1, 0, 0, 0);
cal.set(Calendar.MILLISECOND, 0);
for ( int i = 0; i < 355; i++ ) {
    System.out.println(sdf.format(cal.getTime()));
    cal.add(Calendar.DAY_OF_MONTH, 1);
}

При работе в моем часовом поясе по умолчанию (восточная часть США) результат выглядит так, как я и ожидал:

01/01/2008 00:00:00 EST
01/02/2008 00:00:00 EST
01/03/2008 00:00:00 EST
01/04/2008 00:00:00 EST
...

и когда я перехожу на летнее время, я получаю

03/10/2008 00:00:00 EDT
03/11/2008 00:00:00 EDT
03/12/2008 00:00:00 EDT

Когда я использую часовой пояс, который соответствует восточноевропейскому летнему времени (в данном случае я выбрал часовой пояс Африки/Каира), я получаю вывод:

01/01/2008 00:00:00 EET
01/02/2008 00:00:00 EET
01/03/2008 00:00:00 EET
01/04/2008 00:00:00 EET
01/05/2008 00:00:00 EET

но когда я перехожу на восточноевропейское летнее время, я получаю:

04/25/2008 01:00:00 EEST
04/26/2008 01:00:00 EEST
04/27/2008 01:00:00 EEST

И как ни странно, когда EEST заканчивается, я все еще получаю

08/29/2008 01:00:00 EET
08/30/2008 01:00:00 EET

Я не понимаю, почему эти часовые пояса ведут себя по-разному, и если это ошибка часового пояса Африки/Каира, или я неправильно понимаю, как работают часовые пояса...

Любое понимание этого будет оценено.


person Jeff Storey    schedule 07.02.2012    source источник
comment
какую версию java вы используете? Вы обновили свою базу данных часового пояса JRE последней?   -  person kosa    schedule 08.02.2012
comment
Я использую обновление java 6 29... сейчас обновляю до 30...   -  person Jeff Storey    schedule 08.02.2012


Ответы (1)


каирский часовой пояс переходит на летнее время в полночь - так что час между полуночью 25 апреля 2008 года был пропущен... настенные часы пошли:

04/24/2008 23:59:58
04/24/2008 23:59:59
04/25/2008 01:00:00
04/25/2008 01:00:01

Попробуйте добавить один день за раз с 2 часов ночи по восточному часовому поясу США, и вы увидите то же самое — в какой-то момент он перейдет на 03:00.

Непонятно, чего именно вы пытаетесь достичь - я склонен думать, что лучше либо добавить "количество опытных миллисекунд" к дате/времени в определенном часовом поясе, либо добавить "количество логических< /em> миллисекунды" на локальную дату/время, которые не учитывают часовые пояса. При преобразовании местного времени во время в определенной зоне необходимо учитывать возможность двусмысленности (одно местное время встречается дважды) или пропуска (одно местное время вообще не встречается).

Для большего удовольствия в прошлом году Самоа полностью пропустило 30 декабря из-за изменения часового пояса с -14 до +10...

РЕДАКТИРОВАТЬ: О, и моя стандартная рекомендация применима: откажитесь от java.util.Calendar/Date и используйте Joda Time

person Jon Skeet    schedule 07.02.2012
comment
Джон, спасибо. Я считаю, что это часть проблемы. Но я ожидаю увидеть подобное поведение при выходе из EEST... несоответствие кажется неверным. Но чтобы прояснить, что я пытаюсь сделать, я в основном просто пытаюсь создать набор периодов времени, которые идут от полуночи до полуночи каждый день. Я понимаю, что в те дни, когда мы пересекаем экономию времени, период времени может составлять 23 или 25 часов (или в этот день может даже не быть полуночи) - person Jeff Storey; 08.02.2012
comment
@JeffStorey: Нет, потому что при отъезде EEST местное время 01:00 используется дважды. По сути, после того, как вы вышли из полуночи, вы больше не попадете в ситуацию, когда местное время не соответствует. - person Jon Skeet; 08.02.2012
comment
Таким образом, похоже, что добавление 1 дня имеет разный эффект для DST и EEST, поскольку EEST наступает в полночь, а DST наступает в 2 часа ночи - это правильно? - person Jeff Storey; 08.02.2012
comment
ответ на ваше редактирование во время JODA. Обычно я бы так и сделал, но я интегрируюсь с существующим API, который использует Java Calendar/Date. Я знаю, что могу конвертировать между ними двумя, так что я сделаю это, если понадобится. - person Jeff Storey; 08.02.2012
comment
@JeffStorey: я не уверен, что вы имеете в виду под DST здесь, но добавление одного дня пытается перейти к тому же (местному) времени на следующий день ... но когда это местное время не существует тогда есть проблема. Дело не в том, что добавление дня имеет другое значение, а в том, что вы избегаете проблемного времени в своей выборке для США. Как я уже сказал, попробуйте начать в 2 часа ночи в США, и вы увидите то же самое... - person Jon Skeet; 08.02.2012
comment
Теперь я понимаю. В этом есть смысл. Я только что попробовал это, и такое же поведение существует (оно идет с 02:00 до 01:00). Итак, я в основном пытаюсь распечатать равные интервалы, которые всегда начинаются с 00:00. Когда этого времени не существует, это было 01:00, но затем я хочу, чтобы оно снова начиналось с 00:00 на следующий день - не знаю, как это сделать. в общем виде. - person Jeff Storey; 08.02.2012
comment
@JeffStorey: В идеале, для начала нужно иметь дело с LocalDate значениями времени Joda :) Но если нет, просто установите час дня на 0 на каждой итерации... - person Jon Skeet; 08.02.2012
comment
Попробую. Спасибо. - person Jeff Storey; 08.02.2012