Java SimpleDateFormat разные результаты за октябрь день смены дня для дублированного периода времени - PullRequest
2 голосов
/ 01 марта 2012

Я смотрю на SimpleDateFormat в Java.

Я хочу отформатировать строку даты и превратить ее в дату / календарь, а затем отформатировать полученную дату / календарь обратно в строку.Это для даты в течение смены часов октября, когда у вас есть два часа дня.Время смены часов в октябре должно быть:

** ОБНОВЛЕНИЕ Я изменил свое время с 01:00 до 03:00, где должно быть 2 раза в день **

  • 2012-10-28 02:00:00 CEST
  • 2012-10-28 02:30:00 CEST
  • 2012-10-28 02:00:00 CET
  • 2012-10-28 02:30:00 CET
  • 2012-10-28 03:00:00 CET

Преобразование 2012-10-28 01:00: 00 CET к дате / календарю, а затем к строке вызывает проблему.Преобразованная строка: 2012-10-28 02:00:00 CEST - которая не существует.

Следующий код будет повторять эту проблему:

public class DatesAndTimesStackOverflow {

final static SimpleDateFormat sdf;
final static TimeZone tz;
static {
    tz = TimeZone.getTimeZone( "Europe/Paris" );
    sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss zzz");
    sdf.setTimeZone(tz);
}

public static void main(String[] args) {

    // october clock change should be the following:
    outputDateInfo("2012-10-28 02:00:00 CEST");
    outputDateInfo("2012-10-28 02:30:00 CEST");
    outputDateInfo("2012-10-28 02:00:00 CET");
    outputDateInfo("2012-10-28 02:30:00 CET");
    outputDateInfo("2012-10-28 03:00:00 CET");
    outputDateInfo("2012-10-28 03:30:00 CET");
    outputDateInfo("2012-10-28 04:00:00 CET");
}


private static void outputDateInfo(String theDate) {
    try {
        output("------------------------------------------------------------------------------");
        Date d = sdf.parse(theDate);
        Calendar c = GregorianCalendar.getInstance(tz);
        c.setTimeInMillis(d.getTime());
        TimeZone tzCal = c.getTimeZone();

        output("String:                       " + theDate);
        output("");
        output("Date:                         " + d);                   // toString uses current system TimeZone
        output("Date Millis:                  " + d.getTime());
        output("Cal Millis:                   " + c.getTimeInMillis());
        output("Cal To Date Millis:           " + c.getTime().getTime());
        output("Cal TimeZone Name:            " + tzCal.getDisplayName());
        output("Cal TimeZone ID:              " + tzCal.getID());
        output("Cal TimeZone DST Name:        " + tzCal.getDisplayName(true, TimeZone.SHORT));
        output("Cal TimeZone Standard Name:   " + tzCal.getDisplayName(false, TimeZone.SHORT));
        output("In DayLight:                  " + tzCal.inDaylightTime(d));

        output("");
        output("Day Of Month:                 " + c.get(Calendar.DAY_OF_MONTH));
        output("Month Of Year:                " + c.get(Calendar.MONTH));
        output("Year:                         " + c.get(Calendar.YEAR));

        output("Hour Of Day:                  " + c.get(Calendar.HOUR_OF_DAY));
        output("Minute:                       " + c.get(Calendar.MINUTE));
        output("Second:                       " + c.get(Calendar.SECOND));

        // check to see if this converts back to correct string
        String reformat = sdf.format(c.getTime());
        if( reformat.equals(theDate) ) {
            output("ReConvert:                    " + reformat + " OK");
        } else {
            output("ReConvert:                    " + reformat + " <-------- Error.  The converted date is different");
        }

    } catch (ParseException ex) {
        output("Cannot parse this date");
    }
}

private static void output(String message) {
    System.out.println(message);
}
}

Я так не думаюэто проблема с моим примером.Надеюсь, это и не проблема в Java.Есть ли рациональное объяснение, если я не так закодировал это?

1 Ответ

6 голосов
/ 01 марта 2012

Это правильно. Существует такое время, как 2:00 (или 3) CEST. Европа / Париж содержит две часовые пояса, CET и CEST. Они всегда находятся на расстоянии одного часа и являются смежными (смещение UTC часового пояса никогда не меняется, календарь переключает часовые пояса).

Также обратите внимание, что падение назад происходит в 3 часа утра, а не в 1 час утра! Если вы измените свое время на 3, вы должны увидеть, что оно переворачивается в другую сторону, где разбирается 3:00 input дает выход 3: 00CET, но анализирует вход 3: 00CEST, как и ожидалось, вывод 2: 00CET.

В 3 часа ночи в Париже текущее время меняется с 3:00 CEST на 2:00 CET. Если вы укажете 28 октября 2012 г. 3:00 CEST в качестве входных данных, в конечном итоге будет выведено 2:00 AM CET, то есть тот же фактический момент времени, потому что так говорят часы на парижской стене!

-

Я думаю, что существует некоторая путаница в отношении "человеческого" значения CET против значения машины. Для человека «CET» для Парижа означает «Место, которое составляет +1 час UTC зимой и +2 часа UTC летом». Однако, когда вы видите вывод, напечатанный парсером, CET означает +1 час, всегда. Поэтому, когда вы печатаете парижское время, которое происходит перед «первым» 3:00 утра 10/28, парсер будет выводить его как CEST. Когда вы печатаете парижское время, которое происходит после «первого» 3 утра 28 октября, оно будет показывать CET.

Во время перехода на летнее время парижане будут испытывать как 02:59 CET (машинное значение), так и 02:59 CEST, а не «02:59 CET дважды», что может быть более понятным для человека. Они оба действительные времена, которые существуют.

...