Как рассчитать время на стене из UTC time + TimeZone ID? - PullRequest
4 голосов
/ 27 ноября 2011

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

Если у меня есть время UTC и идентификатор часового пояса, как рассчитать время на стене (= время UTC + смещение часового пояса)+ летнее время) в Java, зная, что летнее время меняется в течение года?

Я ищу проверенный пример кода.Спасибо.

Ответы [ 2 ]

3 голосов
/ 27 ноября 2011

Когда вы говорите, что у вас есть время в UTC, я предполагаю, что вы держите его в Calendar (Date не имеет понятия о часовом поясе, несмотря на вводящее в заблуждение toString()).Если у вас есть время, например, в String, вы можете легко проанализировать его или экземпляр календаря, как здесь:

Calendar summer = new GregorianCalendar(DateUtils.UTC_TIME_ZONE);
summer.set(2011, Calendar.JUNE, 27, 9, 0, 0);

summer представляет 9:00 AM UTC 27 июня 2011 года. Теперь все, что вам нужно сделатьизменить часовой пояс с UTC на Мельбунр, Австралия:

summer.setTimeZone(TimeZone.getTimeZone("Australia/Melbourne"));

Я буду использовать FastDateFormat для правильной печати даты:

final FastDateFormat formatter = FastDateFormat.getDateTimeInstance(FastDateFormat.SHORT, FastDateFormat.SHORT);

System.out.println(formatter.format(summer));

Время в Мельбурне 19: 00 (+10 часов).Но измените дату на зиму:

Calendar winter = new GregorianCalendar(DateUtils.UTC_TIME_ZONE);
winter.set(2011, Calendar.DECEMBER, 27, 9, 0, 0);
System.out.println(formatter.format(winter));

И вдруг время в Мельбурне будет 20: 00 (+11 часов).

Разница доказывает, что изменениечасовой пояс на Calendar принимает во внимание летнее время.В течение июня в часовом поясе UTC в Австралии зима, поэтому они не наблюдают летнее время.

Но зимой в UTC в Австралии лето - и они переходят на летнее время, переводя часы на один час.По этой причине зимой разница составляет +11 часов, а в летнее время UTC +10.


Но подождите!Это становится еще более интересным, если учитывать несколько часовых поясов, наблюдающих летнее время.Сначала я создаю ту же дату в часовом поясе Европы / Осло:

Calendar winter = new GregorianCalendar(TimeZone.getTimeZone("Europe/Oslo"));
winter.set(2011, Calendar.DECEMBER, 27, 9, 0, 0);

9: 00. В Осло зимой - 8:00 UTC, а в Мельбурне - 19:00 ( + 10 часов ).).

Но в то же время летом:

Calendar summer = new GregorianCalendar(TimeZone.getTimeZone("Europe/Oslo"));
summer.set(2011, Calendar.JUNE, 27, 9, 0, 0);

На самом деле 7:00 UTC и 17:00 в Мельбурне! + 8 часов !

Почему-то люди считают, что разница между двумя часовыми поясами всегда постоянна ( "разница между Осло и Мельбурном составляет всегда 10 часов) - что не верно, особенно когда учитываются разные полушария.

В действительности зимой в Осло (без летнего времени, UTC + 1) ТЛЧ наблюдается в Мельбурне (UTC + 11). С другой стороны, хотя в Осло лето и наблюдается летнее время (UTC + 2), его нет в Мельбурне (UTC + 10).Теперь становится очевидным, почему разница варьируется от 8 до 10 часов в зависимости от дня года.

Также помните, что первый и последний день летнего времени не являются глобальными, а выбираются произвольно для каждого часового пояса. Это означает, чтотакже возможна разница в 9 часов (!) Например, проверьте 1 апреля этого года.

3 голосов
/ 27 ноября 2011

Когда вы используете Date в java, он всегда внутри UTC.И часовой пояс включает настройки DST, так что на самом деле это довольно просто.

public static void main(String[] args) throws ParseException {
    String stringAugust = "2011-08-01 12:00:00";
    String stringNovember = "2011-11-01 12:00:00";

    // Outputting the time in Stockholm and Santiago
    // Stockholm has DST in August and not in November
    // Santiago has DST in November and not in August

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    // Parsing the Strings
    sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
    Date dateAugust = sdf.parse(stringAugust);
    Date dateNovember = sdf.parse(stringNovember);

    // outputting the dates for Stockholm
    sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
    sdf.setTimeZone(TimeZone.getTimeZone("Europe/Stockholm"));
    System.out.println(sdf.format(dateAugust));
    System.out.println(sdf.format(dateNovember));

    // outputting the dates for Santiago
    sdf.setTimeZone(TimeZone.getTimeZone("America/Santiago"));
    System.out.println(sdf.format(dateAugust));
    System.out.println(sdf.format(dateNovember));

}

выходы

2011-08-01 14:00:00 +0200
2011-11-01 13:00:00 +0100
2011-08-01 08:00:00 -0400
2011-11-01 09:00:00 -0300
...