JavaRush /Курси /Java Syntax Zero /Клас Date

Клас Date

Java Syntax Zero
Рівень 17 , Лекція 2
Відкрита

1. Клас Date і Unix-час

Від моменту виникнення мови Java в ній був спеціальний клас для роботи з часом і датою — Date. Із плином часу з'явилося ще кілька класів для роботи з датою, але клас Date програмісти використовують досі.

Уся річ у тім, що він дуже простий і зручний. І ви як програміст обов'язково зустрінете його в будь-якому реальному проєкті. Використовувати цей клас чи ні — вибір за вами, але знати його ви мусите. Тому приділіть йому кілька хвилин свого дорогоцінного часу.

Чим же такий хороший клас Date? Простотою.

Клас Date зберігає інформацію про дату й час у вигляді кількості мілісекунд, які минули з 1 січня 1970 року. Це дуже багато мілісекунд, тому для їх зберігання використовується тип long.

Цікаво

Чому саме з 1970 року? Це так званий Unix-time: саме так зберігає час операційна система Unix, яка є бабусею всіх сучасних операційних систем.

Натомість можна з легкістю дізнатися, скільки часу минуло між двома датами: досить відняти одну дату від іншої, і ми отримаємо різницю в часі між датами з точністю до мілісекунд.

Ось кілька корисних прикладів роботи з класом Date.


2. Отримання поточної дати

Щоб отримати поточні час і дату, досить просто створити об'єкт типу Date. Кожен новий об'єкт зберігає час (момент) його створення. Вигляд відповідної команди дуже простий:

Date current = new Date();

Після виконання цієї команди змінна current зберігатиме посилання на створений об'єкт Date, у якому зберігається час його створення — кількість мілісекунд, що минули з 1 січня 1970 року.

Виведення поточної дати на екран

Для того щоб вивести на екран поточну дату, просто: а) створіть новий об'єкт Date, б) виведіть його на екран за допомогою методу System.out.println().

Приклад:

Код Виведення на екран
Date current = new Date();
System.out.println(current);
Thu Feb 21 14:01:34 EET 2019

Виведення на екран розшифровується так:

Текст Розшифровка
Thursday Четвер
February 21 21 лютого
14:01:34 години : хвилини : секунди
EET Часовий пояс: East European Time (східноєвропейський час)
2019 Рік

3. Задання певної дати

Як отримати поточний час, ми розібралися, а як створити об'єкт Date, який би містив іншу дату або час?

Тут теж усе просто. Щоб задати певний день, слід написати такий код:

Date birthday = new Date(рік, місяць, день);

Усе просто й очевидно, але є два нюанси:

  1. Рік потрібно задавати від 1900.
  2. Місяці нумеруються з нуля.
Цікаво

Це теж спадок від операційної системи Unix: там програмісти позначали рік двома цифрами. Замість 1977 писали просто 77. Тому 77 буде правильним роком, якщо ми ведемо відлік від 1900 року.

Приміром, я народився 21 березня 1989 року. Березень — третій місяць, значить, мені потрібно написати

Код Виведення на екран
Date current = new Date(89, 2, 21);
System.out.println(current);
Tue Mar 21 00:00:00 EET 1989

Місяці нумеруються з нуля, а дні — ні. Трохи дивно, еге ж?

Вважаємо, справжні програмісти мусили пересилити себе і дні місяця теж нумерувати з нуля. Ох уже ці конформісти! 🙂

Задання певного часу

Задати певний час теж досить просто. Для цього слід написати таку команду:

Date birthday = new Date(рік, місяць, день, години, хвилини, секунди);

Години, хвилини й секунди нумеруються з нуля: ваш внутрішній програміст може видихнути.

Приклад:

Код Виведення на екран
Date current = new Date(105, 5, 4, 12, 15, 0);
System.out.println(current);
Sat Jun 04 12:15:00 EEST 2005

Ми задали час 12:15 і дату 4 червня 2005 року. Читається трохи важкувато для непрограміста, натомість працює як треба.


4. Робота із фрагментами дати

Об'єкт Date можна не просто виводити на екран. Він має методи, що дають змогу отримати окремі фрагменти його дати:

Метод Опис
int getYear()
Повертає рік дати відносно 1900 року.
int getMonth()
Повертає місяць дати, місяці нумеруються з нуля
int getDate()
Повертає день місяця
int getDay()
Повертає день тижня
int getHours()
Повертає години
int getMinutes()
Повертає хвилини
int getSeconds()
Повертає секунди

Приклад:

Код Виведення на екран Примітка
Date current = new Date(105, 5, 4, 12, 15, 0);
System.out.println(current.getYear());
System.out.println(current.getMonth());
System.out.println(current.getDate());
System.out.println(current.getDay());

105
5
4
6

2005 рік
червень
день місяця
субота

До речі, в об'єкті Date окремі фрагменти дати можна не тільки отримувати, але й змінювати:

Метод Опис
void setYear(int year) Змінює рік дати. Рік вказується відносно 1900 року
void setMonth(int month) Змінює місяць дати, місяці нумеруються з нуля
void setDate(int date) Змінює день місяця
void setHours(int hours) Змінює години
void setMinutes(int minutes) Змінює хвилини
void setSeconds(int seconds) Змінює секунди

5. Мілісекунди

Як ми вже говорили, в об'єкті Date зберігається кількість мілісекунд, які минули з 1 січня 1970 року.

Якщо вона нам потрібна, ми можемо отримати її в об'єкта Date:

long time = date.getTime();

Метод getTime() повертає кількість мілісекунд, яка зберігається в об'єкті Date.

Ви можете не просто отримати кількість мілісекунд, але й змінити це число в наявному об'єкті:

Date date = new Date();
date.setTime(1117876500000L);

До речі, цю конструкцію можна скоротити, якщо передати час в об'єкт Date безпосередньо в момент його створення:

Date date = new Date(1117876500000L);

6. Порівняння дат

Якщо ви хочете порівняти дві дати й дізнатися, яка з них раніша, можна скористатися одним з трьох способів.

Спосіб перший — просто порівняти кількість мілісекунд, яка в них зберігається:

if (date1.getTime() < date2.getTime())

Спосіб другий — скористатися методом before() об'єкта Date:

if (date1.before(date2))

Читається це так: якщо date1 перед date2, то…

Спосіб третій — скористатися методом after() об'єкта Date:

if (date2.after(date1))

Читається це так: якщо date2 після date1, то…


7. Клас DateFormat

Пам'ятаєте, коли ми виводили дату на екран, відображалося щось на кшталт Thu Feb 21 14:01:34 EET 2019? Начебто все правильно, але це, скоріше, відображення дати для програміста. А користувачам хотілося б бачити дату в зрозумілішому форматі. Приміром так: Вівторок, 21 лютого.

І без року. Або з роком за потреби. Власне, хотілося б відображати дату різними способами.

Для цього є спеціальний клас — SimpleDateFormat.

Приклад:

Код
Date current = new Date(105, 5, 4, 12, 15, 0);
SimpleDateFormat formatter = new SimpleDateFormat("MMM-dd-YYYY");
String message = formatter.format(current);
System.out.println(message);
Виведення на екран
Jun-04-2005

Подивіться, що програма вивела на екран: Jun-04-2005. Зовсім не те, що раніше.

А річ у тім, що ми відображали не сам об'єкт Date, а спеціальний рядок, отриманий шляхом виклику методу format() для об'єкта типу SimpleDateFormat. Проте головне тут навіть не це.

Коли об'єкт SimpleDateFormat створюється, ми передаємо в нього як параметр рядок "MMM-dd-YYYY". От у цьому рядку й зашифровано формат дати, яку ви в результаті побачили на екрані.

  • MMM означає, що треба вивести назву місяця, скорочену до трьох літер
  • dd — вивести день місяця
  • YYYY — вивести рік, який складається з чотирьох цифр

Якщо ми хочемо вивести місяць у вигляді цифр, потрібно замість MMM написати MM: вийде рядок "MM-dd-YYYY". На екран буде виведено 06-04-2005

Детальніше ми розглянемо цей клас трохи згодом.


8. Метод Date.parse

Клас Date уміє робити ще одну цікаву й корисну річ: отримувати дату з текстового рядка. Або, як кажуть програмісти, парсити рядок.

Для цього клас має спеціальний метод — parse(). Процес парсингу має такий вигляд:

Date date = new Date();
date.setTime( Date.parse("Jul 06 12:15:00 2019") );

До речі, цей код можна записати стисліше:

Date date = new Date("Jul 06 12:15:00 2019");

Детальніше парсинг рядків ми розглянемо в інших лекціях.


Коментарі (21)
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ
Andrew Burkut Рівень 17
4 грудня 2023
This way looks bettter :)) for me

    static void fixDate(List<Date> brokenDates) {
        Date currentDate = new Date();

        for (var dates : brokenDates) {
            if (dates.after(currentDate)){
                dates.setYear(currentDate.getYear());
                dates.setMonth(currentDate.getMonth());
            }
        }
    }
}

Sava_crosava Рівень 23
26 жовтня 2023
Написав другу задачу через for(так знаю знаю довго, громіздко та не доречно і код криво написано) Але чому компілятор не прийняв мій код? Результат ж правильний(


    static void fixDate(List<Date> brokenDates) {
        Date now = new Date();
        for (int i = 0; i < brokenDates.size(); i++){
            if (brokenDates.get(i).after(now)){
                Date date = brokenDates.get(i);
                date.setYear(date.getYear()-1900);
                date.setMonth(date.getMonth()-1);
                brokenDates.set(i, date);
            }
        }
    }

Olexandr Рівень 47
28 січня 2024
теж саме було. Тільки FOR ICH валідатор прийняв. Але, я думаю - не проходе тестування тому що є якась різниця в кількості ітерацій. В for ich вона чітко по кількості елементів, а в for - i < brokenDates.size() - десь вже не "грає". Причина саме в цьому, тому що якщо написати i <= brokenDates.size() - все працює, а валідатор видає вже не 1 помилку а 3...
Viacheslav B. Рівень 1
9 квітня 2024
мабуть із за цього що - перша дата - new Date(2015, 12, 25, 20, 40) у виводу у консоль має Tue Jan 25 20:40:00 UTC 3916. тобто місяць вже (JAN) що дорівнює - 0, а у тебе у коді

"date.setMonth(date.getMonth()-1)"
тобто (0 - 1 ) = (-1)
IronMan57 Рівень 27
10 січня 2025
Мені здається, що остання команда лишня. Змінна date - це посилання на елемент в ArrayList. В цих командах:

            date.setYear(date.getYear()-1900);
            date.setMonth(date.getMonth()-1);
вже внесено потрібні зміни, і остання команда

brokenDates.set(i, date);
вже зайва, значення елементу масиву переписується ще раз тим же самим значенням. "Масло масляне".
RMykola Рівень 20
14 березня 2025
@IronMan57, саме Ваш коментар виявився вирішальним у моєму випадку. Дякую!
Ігор Рівень 41 Expert
27 липня 2023
не можу зрозуміти навіщо вивчати клас Date, якщо він застарілий і його не використовують?
Sava_crosava Рівень 23
26 жовтня 2023
Нюанс: Із плином часу з'явилося ще кілька класів для роботи з датою, але клас Date програмісти використовують досі. Тому і вчимо бо інші його використовують досі)
Наталья Рівень 69 Expert
6 квітня 2023
день тижня рахується з неділі . Неділя - 1
Sava_crosava Рівень 23
26 жовтня 2023
Так рахується з неділі але неділя 0)
FAUST_ua Рівень 29
16 вересня 2022
Першу задачу яка наче "Easy" - а вирішити її зовсім не easy з матеріалу лекції. Знову лекція про одне, задача про інше. Друга задача: логіка вирішення зрозуміла, але не вистачає синтаксичних знань. Третю наугад вирішив але хочаб сам )
Grimnir Рівень 28
10 січня 2023
В третій, як підказка, Ідея підсвічує сумнівний елемент коду)
oleh ronin Рівень 47
9 листопада 2023
На те вони і задачки, щоб подумати і пошукати дод. матеріал і інеті, а не пройти матеріал цей в лекції, перейти до задачки і одразу ж її рішити. В реальності в коді такого не буде
Niko Рівень 36
1 серпня 2022
Цікаво як це потрібно зрозуміти що дата вважаеться некоректною. dateList.add(new Date(1989, 11, 9)); Рік, добре, не вірно зазначено але місяць входить в діапазон від 0 до 11.
Anonymous #696530 Рівень 19
14 листопада 2022
Умова завдання якось поганенько сформульована...
boaster Рівень 51
14 червня 2022
Спочатку: -Дивіться, є клас SimpleDateFormat. Потім: -Ні, ні, ні! Не можна його використовувати. Треба через switch. Серйозно?
14 листопада 2022
я цього теж не зрозумів. Зробив через SimpleDateFormat в 2 рядки, а воно хоче switch
Pavlo Kezin Рівень 23
24 вересня 2023
теж здивувався. потім спробував через світч, але хто ж знав, що тижні нумеруються з неділі...
Сергій Ситюк Рівень 21
25 травня 2022
Вопрос к авторам? Накой черт подавать к изучению неактуальный материал? Неужели нельзя подать в формате - вот так делать правильно, а если хотите посмотрите как делали раньше? Сидеть ломать голову над вашей второй задачей которую для начала нужно тридцать раз прочитать что бы понять что вы вообще хотите. Зачем мне это? Просто скипнул лекцию.
Pavlo Kezin Рівень 23
24 вересня 2023
досвід (не у програмуванні) підказує, що іноді треба вивчити, щось неактуальне, щоб зрозуміти природу актуального. Сподіваюсь, що це використовується і тут. І це полегшить сприйняття майбутнього матеріалу.
Илья Кухта Рівень 28
13 березня 2022
И кто же знал, что в этом классе дни недели считаются с нуля еще и с воскресенья.