Клас Calendar

Відкрита

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

Перехід від класу Date до класу Calendar

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

Програмісти хотіли мати «розумний клас Date». І такий клас з'явився — ним став клас Calendar. Його задумували як інструмент не лише для зберігання дат, а й для складної роботи з ними.

Повне ім'я класу Calendar — java.util.Calendar. Не забувайте додавати його в import, якщо вирішите використовувати у своєму коді.

Створити об'єкт Calendar можна за допомогою команди:

Calendar date = Calendar.getInstance();

Статичний метод getInstance() класу Calendar створить об'єкт Calendar, ініціалізований поточною датою. Залежно від налаштувань комп'ютера, на якому виконується програма, буде створено потрібний календар.

Правильніше було б сказати «актуальний». Річ у тім, що на Землі не один календар, а багато. І майже кожен із них пов'язаний з якоюсь релігією або країною. Клас Calendar підтримує три календарі:

Календар Опис
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

Місяць ми змінили, а рік і число залишилися без змін.


17
Задача
Java Syntax Zero,  17 рівень3 лекція
Недоступна
День тижня твого народження
День тижня твого народження
17
Задача
Java Syntax Zero,  17 рівень3 лекція
Недоступна
Кишеньковий телепорт
Кишеньковий телепорт
17
Задача
Java Syntax Zero,  17 рівень3 лекція
Недоступна
Вихід із зацикленості
Вихід із зацикленості
Коментарі (9)
  • популярні
  • нові
  • старі
Щоб залишити коментар, потрібно ввійти в систему
Natalya
Рівень 30
24 липня 2025, 12:24
Добрі люди, не вказали, що дні тижня в Calendar нумеруються з 1.
Aleksey Golovin
Рівень 55
1 жовтня 2025, 10:19
Як що використовувати константи типу Calendar.SUNDAY то над цим меньше треба думати, та легше читати код
Serhii
Рівень 30
20 липня 2023, 14:13
Обожнюю коли в лекціях використовують жартівні моменти, можеш трішки розвантажити мозок та поринути у читання з новими силами😁
Іван
Рівень 73
Expert
16 липня 2023, 12:39
Друга задача досить цікава.
8 липня 2023, 11:38
Чому у пункті 4 лекції у прикладі з get() ми щоб отримати години передаємо Calendar.HOUR, а у set() щоб змінити години у якості параметра передається Calendar HOUR_OF_DAY?
Pavlo Kezin
Рівень 23
24 вересня 2023, 11:28
HOUR_OF_DAY - 24 годинний формат HOUR - 12 годинний формат Відповідь на Ваш гет залежатиме від того, який запит виконаєте
Grimnir
Рівень 37
11 січня 2023, 19:52
В третій задачі можна ще DATE замінити на DAY_OF_YEAR, результат той же, але валідатор не приймає
RMykola
Рівень 20
15 березня 2025, 13:03
В тій задачі справа не в константах, а дещо в іншому...
hidden #3143523
Рівень 25
5 січня 2023, 12:50
Норм.