JavaRush/Курсы/Java Syntax Pro/Класс Calendar

Класс Calendar

Открыта

1. Переход от класса Date к классу Calendar

Переход от класса Date к классу Callendar

Программисты любили класс Date за его простоту и поддержку стандартов Unix, но, как известно, наши недостатки — это продолжение наших достоинств.

Программисты хотели иметь «умный класс Date». И такой класс появился: им стал класс Calendar. Он задумывался как инструмент не только хранения, но и сложной работы с датами.

Полное имя класса Calendar — java.util.Calendar. Не забывайте добавлять его в import, если решите использовать в своем коде.

Создать объект Calendar можно командой:

Calendar date = Calendar.getInstance();

Статический метод getInstance() класса Calendar создаст объект Calendar, инициализированный текущей датой. В зависимости от настроек компьютера, на котором выполняется программа, будет создан нужный календарь.

Более правильно было бы сказать — актуальный. Дело в том, что на Земле не один, а много календарей. И почти каждый из них связан с какой-нибудь религией или страной. Класс Calendar поддерживает 3 из них:

Календарь Описание
GregorianCalendar Христианский Григорианский календарь
BuddhistCalendar Буддистский календарь
JapaneseImperialCalendar Японский Императорский календарь

А ведь есть еще Китайский и Арабский календари. В общем, работа со временем не такая простая, как кажется.

В Китае на момент написания этой лекции официально 4716 год. А по мусульманскому календарю — 1398. Добро пожаловать в большой мир, мой друг-программист.

2. Создание объекта календарь

Мы будем использовать Григорианский календарь как самый распространенный в мире. По крайней мере, пока Китай не купит компанию Oracle и не сделает свой календарь основным.

Объект календарь с произвольной датой создается командой:

Calendar date = new GregorianCalendar(год, месяц, день);

Да, каждый раз придется писать GregorianCalendar. Можно и вместо Calendar писать GregorianCalendar: так тоже будет работать. Но просто Calendar писать короче.

Год нужно писать полностью: никаких 19 вместо 2019. Месяцы по-прежнему нумеруются с нуля. А дни месяца по-прежнему нумеруются не с нуля (слабаки!).

Чтобы задать не только дату, но и время, нужно передать их дополнительными параметрами:

... = new GregorianCalendar(год, месяц, день, часы, минуты, секунды);

Можно даже передать миллисекунды, если это необходимо: их указывают следующим параметром после секунд.

3. Вывод объекта календарь на экран

Если просто вывести объект-календарь на экран, результат вас не сильно порадует.

Код
Calendar calendar = new GregorianCalendar(2019, 03, 12);
System.out.println(calendar);
Вывод на экран
java.util.GregorianCalendar[time=?,areFieldsSet=false,areAllFieldsSet=false,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Europe/Helsinki",offset=7200000,dstSavings=3600000,useDaylight=true,transitions=118,lastRule=java.util.SimpleTimeZone[id=Europe/Helsinki,offset=7200000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=2,startMonth=2,startDay=-1,startDayOfWeek=1,startTime=3600000,startTimeMode=2,endMode=2,endMonth=9,endDay=-1,endDayOfWeek=1,endTime=3600000,endTimeMode=2]],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=?,YEAR=2019,MONTH=3,WEEK_OF_YEAR=?,WEEK_OF_MONTH=?,DAY_OF_MONTH=12,DAY_OF_YEAR=?,DAY_OF_WEEK=?,DAY_OF_WEEK_IN_MONTH=?,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=0,SECOND=0,MILLISECOND=?,ZONE_OFFSET=?,DST_OFFSET=?]

Все дело в том, что календарь — это именно календарь, а не дата: у него много всяких настроек, и они все выводятся на экран.

Правильно будет отображать объект календарь с помощью класса SimpleDateFormat, но пока мы его не изучили, можно использовать лайфхак.

Date date = calendar.getTime();

Дело в том, что объект типа Calendar можно легко преобразовать к объекту типа Date, а как выводить на экран объект типа Date, вы уже знаете. Примерно так можно преобразовать объект Calendar в Date:

Использование метода getTime():

Код Вывод на экран
Calendar calendar = new GregorianCalendar(2019, 03, 12);
System.out.println(calendar.getTime());
 Fri Apr 12 00:00:00 EEST 2019

Совсем другое дело, не так ли?

4. Работа с фрагментами даты

Чтобы получить фрагмент даты (год, месяц, ...), у класса Calendar есть специальный метод — get(). Метод один, зато с параметрами:

int month = calendar.get(Calendar.MONTH);

Где calendar — это переменная типа Calendar, а MONTH — это переменная-константа класса Calendar.

В метод get в качестве параметра вы передаете специальную константу класса Calendar, и в результате получаете нужное значение.

Примеры

Код Описание
Calendar calendar = Calendar.getInstance();

int era = calendar.get(Calendar.ERA);
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DAY_OF_MONTH);

int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
int hour = calendar.get(Calendar.HOUR);
int minute = calendar.get(Calendar.MINUTE);
int second = calendar.get(Calendar.SECOND);


эра (до нашей эры или после)
год
месяц
день месяца

день недели
часы
минуты
секунды

Для изменения фрагмента даты используется метод set:

calendar.set(Calendar.MONTH, значение);

Где calendar — это переменная типа Calendar, а MONTH — это переменная-константа класса Calendar.

В метод set в качестве первого параметра вы передаете специальную константу класса Calendar, а в качестве второго параметра — новое значение.

Примеры

Код Описание
Calendar calendar = new GregorianCalendar();

calendar.set(Calendar.YEAR, 2019); calendar.set(Calendar.MONTH, 6);
calendar.set(Calendar.DAY_OF_MONTH, 4);
calendar.set(Calendar.HOUR_OF_DAY, 12);
calendar.set(Calendar.MINUTE, 15);
calendar.set(Calendar.SECOND, 0);

System.out.println(calendar.getTime());


год = 2019
месяц = Июль (нумерация с 0)
4 число
часы
минуты
секунды

5. Константы класса Calendar

В классе Calendar есть константы не только для названия фрагментов даты, а кажется, на все случаи жизни.

Calendar date = new GregorianCalendar(2019, Calendar.JANUARY, 31);

Например, есть константы для обозначения месяцев:

Или, например, для дней недели:

Calendar calendar = new GregorianCalendar(2019, Calendar.JANUARY, 31);
if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.FRIDAY)
{
   System.out.println("Это пятница");
}

Всего перечислять не будем. Просто хотим, чтобы вы не удивлялись, если встретите такие записи в коде.

Использование констант позволяет сделать код более читабельным, поэтому программисты их и добавили. Ну а месяцы нумеруются с нуля тоже ради читабельности. Или нет.

6. Изменение даты в объекте Calendar

У класса Calendar есть метод, который позволяет проводить с датой более умные операции. Например, добавить к дате год, месяц или несколько дней. Или отнять. Называется этот метод add(). Выглядит работа с ним примерно так:

calendar.add(Calendar.MONTH, значение);

Где calendar — это переменная типа Calendar, а MONTH — это переменная-константа класса Calendar.

В метод add в качестве первого параметра вы передаете специальную константу класса Calendar, и в качестве второго параметра — значение, которое нужно добавить.

Особенность этого метода в том, что он умный. Давайте сами посмотрим, насколько:

Код
Calendar calendar = new GregorianCalendar(2019, Calendar.FEBRUARY, 27);
calendar.add(Calendar.DAY_OF_MONTH, 2);
System.out.println(calendar.getTime());
Вывод на экран
Fri Mar 01 00:00:00 EET 2019

Этот метод понимает, что в феврале 2019 года всего 28 дней, и итоговая дата — 1 марта.

А теперь давайте отнимем 2 месяца! Что должно получиться? 27 декабря 2018 года! Сейчас проверим.

Чтобы выполнить действие, уменьшающее дату, нужно в метод add() передать значение с отрицательным знаком:

Код
Calendar calendar = new GregorianCalendar(2019, Calendar.FEBRUARY, 27);
calendar.add(Calendar.MONTH, -2);
System.out.println(calendar.getTime());
Вывод на экран
Thu Dec 27 00:00:00 EET 2018

Работает!

Этот метод учитывает длины месяцев и високосные годы. В общем, отличный метод. Именно то, что нужно большинству программистов, которые плотно работают с датами.

7. Прокручивание фрагментов даты

Но иногда бывают ситуации, когда такое умное поведение излишне: хочется что-то сделать с одной частью даты, не меняя все остальное.

Для этого у класса Calendar есть специальный метод — roll(). По своей сигнатуре он полностью аналогичен методу add(), но любые изменения с его помощью затрагивают один параметр, остальные остаются неизменными.

Пример:

Код
Calendar calendar = new GregorianCalendar(2019, Calendar.FEBRUARY, 27);
calendar.roll(Calendar.MONTH, -2);
System.out.println(calendar.getTime());
Вывод на экран
Fri Dec 27 00:00:00 EET 2019

Месяц мы поменяли, а год и число остались неизменными.


Комментарии (189)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Euraks Backend Developer
4 октября, 04:39
Calendar изменяемый, и это главная практическая ловушка. Calendar и Date в новом коде заменены пакетом java.time (Java 8+). В нём объекты неизменяемы, месяцы и дни недели нумеруются нормально (январь = 1, понедельник = 1), недопустимые даты вызывают исключение, а типы разделены по смыслу: LocalDate, LocalDateTime, ZonedDateTime, Instant
Grigoryvvv
Уровень 28
Expert
3 июля, 09:27
03.07.2026 / 17 уровень В старом API Java для работы с временем одним из базовых классов был класс Date (java.util.Date), который хранил момент времени, но не мог хранить часовой пояс. Позже в старом API появился класс Calendar (java.util.Calendar), который хранит момент времени, часовой пояс и умеет выполнять умные операции над датой. Класс Calendar хранит часовой пояс с помощью объекта класса TimeZone ( java.util.TimeZone). Объект TimeZone содержит информацию о часовом поясе и правилах его применения. TimeZone — это не просто +08:00 или -04:00. Он может учитывать переходы на летнее/зимнее время и исторические изменения правил часового пояса. Из объекта Calendar можно получить объект Date с помощью команды
Date date = calendar.getTime();
Из объекта Calendar можно получить объект TimeZone с помощью команды
TimeZone timeZone = calendar.getTimeZone();
При создании объекта класса Calendar автоматически создается объект класса TimeZone. Создание объекта класса Date при создании Calendar не требуется, поскольку Calendar самостоятельно хранит конкретный момент времени. Так и сформировался полноценный старый API для работы с временем. Старый API Java для работы с датой и временем (java.util.Date, Calendar, TimeZone) │ ├── Date │ └── конкретный момент времени │ ├── Calendar │ ├── календарные поля │ ├── операции над датой │ └── использует TimeZone │ └── TimeZone └── часовой пояс + его правила
26 марта, 19:45
В Date дни недели нумеруются с 0 а в Calendar c 1 и как я понял ни в 1 ни во 2 лекции про это ни слова а задание про это) Очередной байт на ресерч защитан
Underdante
Уровень 74
15 марта, 14:27
а как надо правильно смотрите в следующей серии
Yokei
Уровень 18
18 декабря 2025, 19:13
switch (calendar.get(Calendar.DAY_OF_WEEK)) {
            case Calendar.MONDAY:
                return "понедельник";
            case Calendar.TUESDAY:
                return "вторник";
            case Calendar.WEDNESDAY:
                return "среда";
            case Calendar.THURSDAY:
                return "четверг";
            case Calendar.FRIDAY:
                return "пятница";
            case Calendar.SATURDAY:
                return "суббота";
            case Calendar.SUNDAY:
                return "воскресенье";
            default:
                return ":)";
        }
— это почему-то не работает :(
Алексей
Уровень 52
22 декабря 2025, 18:27
ну я так понимаю default лишний.
ectavgen
Уровень 24
11 сентября, 09:54
get возвращает int
Exaltyr777
Уровень 25
27 июля 2025, 09:09
Почему уже 2 раза написали что месяцы нумеруются с нуля, а что недели тоже с нуля - нигде не пишут...
Yokei
Уровень 18
19 декабря 2025, 13:23
Вообще нужно использовать Calendar.MONDAY, Calendar.TUESDAY и т.д. А вот почему недели нумеруются с нуля я не понял, они нумеруются с единицы, просто счет начинается с воскресенья. (я знаю, что я вовремя)
Anonymous #3585174
Уровень 33
18 июля 2025, 14:19
like
Danya Java Developer
24 мая 2025, 08:48
как по мне запутано немного
Юрий Frontend Developer
26 февраля 2025, 12:19
А вы тоже использовали мат для вывода своих эмоций увидев что выводит на экран Calendar calendar = new GregorianCalendar(2019, 03, 12); System.out.println(calendar);?
24 апреля 2025, 14:35
Нет, ведь в лекции нас предупредили, какой будет результат вывода объекта Calendar в консоль💁‍♂️
Александр
Уровень 19
9 января 2025, 20:53
Ну а месяцы нумеруются с нуля тоже ради читабельности. Или нет. Я бы написал "Но это не точно" 😀