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

Класс Calendar

Java Syntax Pro
16 уровень , 2 лекция
Открыта

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

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


Комментарии (191)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
C0N5P1RACY Уровень 10
29 декабря 2025
В комиксе что, отсылка на Машинариум? :D
Yokei Уровень 16
18 декабря 2025

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 ":)";
        }
— это почему-то не работает :(
Алексей Уровень 36
22 декабря 2025
ну я так понимаю default лишний.
Exaltyr777 Уровень 25
27 июля 2025
Почему уже 2 раза написали что месяцы нумеруются с нуля, а что недели тоже с нуля - нигде не пишут...
Yokei Уровень 16
19 декабря 2025
Вообще нужно использовать Calendar.MONDAY, Calendar.TUESDAY и т.д. А вот почему недели нумеруются с нуля я не понял, они нумеруются с единицы, просто счет начинается с воскресенья. (я знаю, что я вовремя)
Anonymous #3585174 Уровень 33
18 июля 2025
like
Danya Уровень 17
24 мая 2025
как по мне запутано немного
Юрий Уровень 20
26 февраля 2025
А вы тоже использовали мат для вывода своих эмоций увидев что выводит на экран Calendar calendar = new GregorianCalendar(2019, 03, 12); System.out.println(calendar);?
24 апреля 2025
Нет, ведь в лекции нас предупредили, какой будет результат вывода объекта Calendar в консоль💁‍♂️
Александр Уровень 19
9 января 2025
Ну а месяцы нумеруются с нуля тоже ради читабельности. Или нет. Я бы написал "Но это не точно" 😀
Александр Уровень 19
9 января 2025
Я один заметил что после трансформации с Calendar на Date.getTime() ...месяц изначально был "03" , а в итоге стал апрелем. И дни недели тоже вперед. По Date - четверг, а Gregorian - сразу Пятницу.
Anonymous #3487873 Уровень 25
4 февраля 2025
Там все норм, ничего такого не происходит, перепроверь. 03 это и есть апрель если считать месяцы с нуля , а день недели как был пятница(5) так и остается
13 Уровень 24
22 декабря 2024
"Мы будем использовать Григорианский календарь как самый распространенный в мире. По крайней мере, пока Китай не купит компанию Oracle и не сделает свой календарь основным." .....
Antariko Уровень 1
28 декабря 2024
Китай однако тоже использует Григорианский календарь.
Antariko Уровень 1
18 декабря 2024
"с помощью класса SimpleDateFormat, но пока мы его не изучили"... А в прошлой лекции что было тогда?..
Faraway_is_close Уровень 24
27 декабря 2024
А весь прошлый уровень что было тогда? Лекции перепутаны основательно. Если искать определённые темы на JavaRush через гугл, то находит старые, ныне недоступные лекции, которые находятся совершенно не на тех уровнях, что сейчас