Неожиданный результат вычитания 24 часов из даты 25.03.2018

Я вычитаю 24 часа из григорианского календаря 25.03.2018 09:41.

Результат 03/24/2018 08:41.

public class Utiles{
    public static void main(String args[]) {

        SimpleDateFormat sdt = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
        GregorianCalendar gcFinAux = new GregorianCalendar(2018, 2, 25, 9, 41, 0);

        System.out.println("1. " + sdt.format(gcFinAux.getTime()));
        gcFinAux.add(Calendar.HOUR_OF_DAY, -24);
        System.out.println("2. " + sdt.format(gcFinAux.getTime()));
    }
}

Вывод:

1. 25/03/2018 09:41:00
2. 24/03/2018 08:41:00

Если я попробую с другой датой, результат будет правильным.

Пробую в Linux и Windows с JDK1.6.0_45 и Java 1.8.

Может ли кто-нибудь подтвердить, если вы получите те же результаты?

Спасибо.


person Mastroca    schedule 23.03.2018    source источник
comment
Да, летнее время реально. Если вам это не нравится, подпишите эту петицию: change.org/p/   -  person baao    schedule 23.03.2018
comment
летнее время   -  person Federico klez Culloca    schedule 23.03.2018
comment
Рассмотрите возможность перехода на java.time. Делает вещи намного проще.   -  person lexicore    schedule 23.03.2018
comment
Используемый вами API дат является устаревшим. Вместо этого используйте классы пакета java.time.   -  person Zabuzard    schedule 23.03.2018
comment
Оооо!!!! Большая ошибка. Извиняюсь. Спасибо всем.   -  person Mastroca    schedule 23.03.2018
comment
Я получаю тот же результат (я нахожусь в часовом поясе Европы/Копенгагена, так что это то, что я ожидал).   -  person Ole V.V.    schedule 23.03.2018
comment
Связано: преобразование Java ZonedDateTime в Instant   -  person Ole V.V.    schedule 23.03.2018


Ответы (2)


Я знаю, что в некоторых частях мира время изменяется в течение этого конкретного 24-часового периода. Похоже, основная логика принимает это во внимание.

person Chris Gerken    schedule 23.03.2018

Как было сказано в комментариях, то, что вы наблюдали, является ожидаемым и правильным поведением в часовых поясах, которые переходят на летнее время (DST) в ночь с 24 на 25 марта этого года. Это включает в себя большую часть Европы, включая Испанию, а не (европейские части) Турцию и Россию, а также, например, Гренландию и Ливан (в то время как Парагвай возвращается с летнего времени той же ночью).

java.time: Как сказали в комментариях lexicore и Zabuza, на самом деле нет причин, по которым вы должны использовать SimpleDateFormat и GregorianCalendar. Эти классы давно устарели, а первые особенно неприятны. Вместо этого используйте java.time, современный API даты и времени Java:

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss");
    ZonedDateTime zdtFinAux 
            = ZonedDateTime.of(2018, 3, 25, 9, 41, 0, 0, ZoneId.of("Europe/Madrid"));

    System.out.println("1. " + zdtFinAux.format(formatter));
    zdtFinAux = zdtFinAux.minusHours(24);
    System.out.println("2. " + zdtFinAux.format(formatter));

Выход такой же, как у вас, конечно:

1. 25/03/2018 09:41:00
2. 24/03/2018 08:41:00

Если вы хотите, чтобы то же время суток было в предыдущий день, один из вариантов — использовать minusDays(1) вместо minusHours(24).

Ссылки

person Ole V.V.    schedule 24.03.2018