Забытые Time Zone
answer by Rakesh KR близко, но не совсем верно , И вопрос, и этот ответ не задумываются о часовом поясе. Если вы не укажете часовой пояс, вы получите часовой пояс JVM по умолчанию. Пользуясь часовым поясом по умолчанию, вы можете получить неожиданные результаты.
ДСТ Эффект
Метод java.util.Calendar add
сохраняет час-в-день, с поправкой на летнее время (DST) и, возможно, других аномалий. Поэтому, если вы используете часовой пояс (например, западное побережье Соединенных Штатов), который меняет переход на летнее время на час во время вашего времени, у вас на самом деле будет один дополнительный/менее час. То есть, ваш результат в часах добавления 15 дней - ((15 * 24) ± 1)
.
Если вы ожидали, что (15 * 24)
последовательно, вы будете удивлены (в зависимости от часового пояса JVM).
Демонстрация
Поскольку plusDays
метод на класс DateTime в Joda-Time имеет такое же поведение, я продемонстрирую с помощью Joda-Time. Вы должны избегать java.util.Date & java.util.Calendar в любом случае, но в этом случае поведение такое же, как Joda-Time.
Во-первых, для вашей информации, код из другого ответа можно было бы сделать Joda-Time, как это, конвертируя между собой мир java.util.Date и мир Joda-Time. Но этот код имеет одинаковую проблему с часовым поясом (зависит от DST).
java.util.Date juDate = new java.util.Date();
java.util.Date juDateLater = new DateTime(juDate).plusDays(15).toDate() ;
Теперь, используя чистый Joda-Time, давайте посмотрим, как часовой пояс влияет на добавление дней. Мы будем запускать этот пример кода дважды, сначала как есть, а затем меняя часовые пояса, комментируя первую строку timeZone
и включаем линию после этого.
// Time zone "America/Los_Angeles" begins DST on 2014-03-09 02:00, springing ahead to 03:00.
DateTimeZone timeZone = DateTimeZone.forID("America/Los_Angeles");
//DateTimeZone timeZone = DateTimeZone.UTC;
DateTime dateTime_OneAM = new DateTime(2014, 3, 9, 1, 0, 0, timeZone);
DateTime dateTime_OneAM_Plus15 = dateTime_OneAM.plusDays(15);
DateTime dateTime_ThreeAM = new DateTime(2014, 3, 9, 3, 0, 0, timeZone);
DateTime dateTime_ThreeAM_Plus15 = dateTime_ThreeAM.plusDays(15);
long millisElapsedOneAM = (dateTime_OneAM_Plus15.getMillis() - dateTime_OneAM.getMillis());
long millisElapsedThreeAM = (dateTime_ThreeAM_Plus15.getMillis() - dateTime_ThreeAM.getMillis());
long minutes = ((millisElapsedThreeAM - millisElapsedOneAM)/1000L/60L);
самосвала утешать ...
System.out.println("timeZone " + timeZone);
System.out.println("dateTime_OneAM " + dateTime_OneAM + " (UTC/GMT: " + dateTime_OneAM.toDateTime(DateTimeZone.UTC) + ")");
System.out.println("dateTime_OneAM_Plus15 " + dateTime_OneAM_Plus15 + " (UTC/GMT: " + dateTime_OneAM_Plus15.toDateTime(DateTimeZone.UTC) + ")");
System.out.println(" "); // Blank line.
System.out.println("dateTime_ThreeAM " + dateTime_ThreeAM + " (UTC/GMT: " + dateTime_ThreeAM.toDateTime(DateTimeZone.UTC) + ")");
System.out.println("dateTime_ThreeAM_Plus15 " + dateTime_ThreeAM_Plus15 + " (UTC/GMT: " + dateTime_ThreeAM_Plus15.toDateTime(DateTimeZone.UTC) + ")");
System.out.println(" "); // Blank line.
System.out.println("millisElapsedOneAM " + millisElapsedOneAM);
System.out.println("millisElapsedThreeAM " + millisElapsedThreeAM);
System.out.println("minutes " + minutes);
При запуске с использованием первого часового пояса, на западном побережье США ...
(Обратите внимание, как час-в-день в изменении UTC или не меняется)
timeZone America/Los_Angeles
dateTime_OneAM 2014-03-09T01:00:00.000-08:00 (UTC/GMT: 2014-03-09T09:00:00.000Z)
dateTime_OneAM_Plus15 2014-03-24T01:00:00.000-07:00 (UTC/GMT: 2014-03-24T08:00:00.000Z)
dateTime_ThreeAM 2014-03-09T03:00:00.000-07:00 (UTC/GMT: 2014-03-09T10:00:00.000Z)
dateTime_ThreeAM_Plus15 2014-03-24T03:00:00.000-07:00 (UTC/GMT: 2014-03-24T10:00:00.000Z)
millisElapsedOneAM 1292400000
millisElapsedThreeAM 1296000000
minutes 60
При запуске с использованием второго часового пояса, для UTC/GMT ...
timeZone UTC
dateTime_OneAM 2014-03-09T01:00:00.000Z (UTC/GMT: 2014-03-09T01:00:00.000Z)
dateTime_OneAM_Plus15 2014-03-24T01:00:00.000Z (UTC/GMT: 2014-03-24T01:00:00.000Z)
dateTime_ThreeAM 2014-03-09T03:00:00.000Z (UTC/GMT: 2014-03-09T03:00:00.000Z)
dateTime_ThreeAM_Plus15 2014-03-24T03:00:00.000Z (UTC/GMT: 2014-03-24T03:00:00.000Z)
millisElapsedOneAM 1296000000
millisElapsedThreeAM 1296000000
minutes 0