Странное несоответствие календаря Java - PullRequest
0 голосов
/ 31 мая 2018

Почему такое несоответствие?

public static void main(String[] args) {
    final Calendar calendar = Calendar.getInstance();

    calendar.set(Calendar.MONTH, 1);
    System.out.println("KO current month: " + calendar.get(Calendar.MONTH));

    calendar.set(Calendar.MONTH, 1);
    System.out.println("OK current month: " + calendar.get(Calendar.MONTH));
}

Вывод:

KO current month: 2
OK current month: 1

Ответы [ 2 ]

0 голосов
/ 31 мая 2018

Ответ Кароля Доубеки является правильным и хорошо объясненным (и я должен сказать, хорошо определенным).Я хотел бы предоставить хорошее и современное исправление.

    LocalDate date = LocalDate.of(2018, Month.MAY, 31);
    date = date.with(Month.FEBRUARY);
    System.out.println(date.getMonth());
    System.out.println(date);

Вывод:

FEBRUARY
2018-02-28

Класс Calendar сбивает с толку и плохо спроектирован, поэтому вместо этого я использую LocalDateот java.time, современного Java API даты и времени.С этим API гораздо приятнее работать.LocalDate не даст вам 31 февраля, к счастью, так как эта дата не существует.Он дает вам последний день февраля и, следовательно, месяц, который вы ожидали.

PS Следующая инициализация будет имитировать ваш код:

    LocalDate date = LocalDate.now(ZoneId.of("Europe/Paris"))`

Однако я предпочел бы дать код, который будет такжепродемонстрируйте момент, когда кто-то попытается запустить его когда-нибудь в будущем.

Ссылка: Учебное пособие по Oracle: Дата и время , объясняющее, как использовать java.time.

0 голосов
/ 31 мая 2018

Сегодня 31 мая.Объект Calendar по умолчанию снисходительный , поэтому после первого set() дата переключается на 31 февраля, которого не существует.Calendar мягко исправляет это, переходя на 3 марта.Месяц 2 означает март.

Вторая операция set() применяется к 3 марта, поэтому она переключается на 3 февраля, как и следовало ожидать.Месяц 1 означает февраль.

Это можно увидеть, отформатировав полную дату:

SimpleDateFormat sdf = new SimpleDateFormat();
Calendar calendar = Calendar.getInstance();

calendar.set(Calendar.MONTH, 1);
System.out.println(sdf.format(calendar.getTime()));

calendar.set(Calendar.MONTH, 1);
System.out.println(sdf.format(calendar.getTime()));

, которая возвращает

03/03/18 10:40
03/02/18 10:40

Если вы хотите предотвратить поведениевам нужно вызвать setLenient() метод

Calendar calendar = Calendar.getInstance();
calendar.setLenient(false);
calendar.set(Calendar.MONTH, 1);

, что приведет к следующему IllegalArgumentException исключению:

Исключение в потоке "main" javaИсключение

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...