JavaRush /Курси /Java Syntax Zero /Сучасна робота з датою

Сучасна робота з датою

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

1. Вступ до Date Time API

Вступ до Date Time API

Створювачам Java не дуже подобалася поточна ситуація з класами Date і Calendar. Вони були хороші свого часу, але часи змінюються. Потрібно було щось просте, потужне та надійне. І ось одночасно з випуском Java 8 (через 15 років після виходу Calendar) був представлений Java Date Time API: набір класів, які мали розв'язати всі можливі проблеми щодо часу.

Класів було так багато, що їх вирішили рознести по декількох пакетах:

Пакет java.time — базовий пакет для Java Date Time API, в якому містяться такі класи, як LocalDate, LocalTime, LocalDateTime, Instant, Period, Duration. Усі об'єкти цих класів — immutable: їх не можна змінити після створення.

Пакет java.time.format містить у собі класи для форматування часу: перетворення часу (і дати) на текстовий рядок і навпаки. Наприклад, у ньому міститься такий універсальний клас, як DateTimeFormatter, що прийшов на зміну SimpleDateFormat.

Пакет java.time.zone містить класи для роботи з часовими поясами (time zones). Він охоплює такі класи, як TimeZone і ZonedDateTime. Якщо ви пишете код для сервера, клієнти якого розташовані в різних частинах світу, ці класи стануть вам у великій пригоді.


2. Клас LocalDate

Перший і найкорисніший клас із Date Time API, який ми вивчимо — це клас LocalDate. Як ви, напевно, здогадуєтеся за його назвою, цей клас створено для роботи з датою.

Об'єкти цього класу не змінюються після створення (клас LocalDate — immutable). Натомість це додало класу простоти й надійності, особливо якщо з об'єктом класу одночасно взаємодіють декілька ниток (потоків виконання).

Для створення нового об'єкта класу LocalDate слід використовувати один із статичних методів. Наведемо список основних.

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

Щоб отримати поточну дату, слід скористатися статичним методом now(). Це значно простіше, ніж здається:

LocalDate today = LocalDate.now();

де today — це змінна класу LocalDate, а LocalDate.now() — виклик статичного методу now() для класу LocalDate.

Приклад:

Код Виведення на екран
LocalDate today = LocalDate.now();
System.out.println("Сьогодні = " + today);

Сьогодні = 2019-02-22

Отримання дати в певному часовому поясі

Крім того, клас LocalDate має різновид методу now(ZoneId), який дає змогу отримати поточну дату в певному часовому поясі.

Для цього нам знадобиться ще один клас — ZoneId (java.time.ZoneId). Він має метод of(), який повертає об'єкт ZoneId за іменем часового поясу.

Щоб визначити поточну дату в Шанхаї, потрібно написати код:

Код Виведення на екран
ZoneId  timezone = ZoneId.of("Asia/Shanghai");
LocalDate today = LocalDate.now(timezone);
System.out.println("Зараз у Шанхаї = " + today);


Зараз у Шанхаї = 2019-02-22

Список імен усіх часових поясів (time zone) можна знайти в інтернеті.


3. Отримання конкретної дати

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

LocalDate date = LocalDate.of(2019, Month.FEBRUARY, 22);

де date — це змінна класу LocalDate, а LocalDate.of() — виклик статичного методу of() для класу LocalDate.

А ще ми бачимо тут використання спеціальної константи FEBRUARY класу Month (java.time.Month) для задання місяця «лютий».

Можна задати місяць і по-старому — за допомогою числа:

LocalDate date = LocalDate.of(2019, 2, 22);

Двійка? Замість місяця «лютий»? Це що ж, місяці тепер знову нумеруються з одиниці?

Так, нарешті майже через 20 років після створення Java перестали нумерувати місяці з нуля.

Приклад:

Код Виведення на екран
LocalDate today = LocalDate.of(2019, 2, 22);
System.out.println("Сьогодні = " + today);

Сьогодні = 2019-02-22

Отримання дати за номером дня

Є ще один цікавий спосіб створення дати: за допомогою методу ofYearDay можна отримати дату, якщо у вас є тільки номер року й номер дня року. Загальний вигляд такий:

LocalDate date = LocalDate.ofYearDay(рік, день);

де рік — це номер року, а день — номер дня в році.

Приклад:

Код Виведення на екран
LocalDate today = LocalDate.ofYearDay(2019, 100);
System.out.println("Сьогодні = " + today);

Сьогодні = 2019-04-10

Сотий день у 2019 році — це 10 квітня.

Отримання дати Unix

Пам'ятаєте, що об'єкти класу Date завжди зберігали час у мілісекундах з 1 січня 1970 року? Для того щоб програмісти не сумували за старими добрими часами, у клас LocalDate додали метод ofEpochDay(), який повертає дату, відлічену від 1 січня 1970 року. Загальний вигляд такий:

LocalDate date = LocalDate.ofEpochDay(день);

де день — це кількість днів, які минули з 1 січня 1970 року.

Приклад:

Код Виведення на екран
LocalDate today = LocalDate.ofEpochDay(1);
System.out.println("Сьогодні = " + today);

Сьогодні = 1970-01-02

4. Отримання фрагментів дати

Змінювати об'єкти класу LocalDate не можна, а ось отримувати окремі фрагменти дати ще й як можна. Для цього в об'єктів класу LocalDate є кілька методів:

Метод Опис
int getYear()
Повертає рік із конкретної дати
Month getMonth()
Повертає місяць дати — одну зі спеціальних констант
JANUARY, FEBRUARY, …;
int getMonthValue()
Повертає номер місяця з дати. Січень == 1.
int getDayOfMonth()
Повертає номер дня в місяці
int getDayOfYear()
Повертає номер дня з початку року
DayOfWeek getDayOfWeek()
Повертає день тижня: одну зі спеціальних констант
MONDAY, TUESDAY, …;
IsoEra getEra()
Повертає еру: константу BC (Before Current Era) або CE(Current Era)

Приклад:

Код Виведення на екран
LocalDate today = LocalDate.now();
System.out.println(today.getYear());
System.out.println(today.getMonth());
System.out.println(today.getMonthValue());
System.out.println(today.getDayOfMonth());
System.out.println(today.getDayOfWeek());

2019
FEBRUARY
2
22
FRIDAY

5. Змінення дати в об'єкті LocalDate

Клас LocalDate містить кілька методів, які дають змогу працювати з датою. Ці методи реалізовано за аналогією до методів класу String: кожен із цих методів не змінює наявний об'єкт LocalDate, а повертає новий із потрібними даними.

Отакі методи має клас LocalDate:

Метод Опис
plusDays(int days)
Додає певну кількість днів до дати
plusWeeks(int weeks)
Додає тижні до дати
plusMonths(int months)
Додає місяці до дати
plusYears(int years)
Додає роки до дати
minusDays(int days)
Віднімає дні від дати
minusWeeks(int weeks)
Віднімає тижні від дати
minusMonths(int months)
Віднімає місяці від дати
minusYears(int years)
Віднімає роки від дати

Приклад:

Код Виведення на екран
LocalDate birthday = LocalDate.of(2019, 2, 28);
LocalDate nextBirthday = birthday.plusYears(1);
LocalDate firstBirthday = birthday.minusYears(30);

System.out.println(birthday);
System.out.println(nextBirthday);
System.out.println(firstBirthday);




2019-02-28
2020-02-28
1989-02-28

Об'єкт birthday, чиї методи ми викликаємо, не змінюється. Натомість його методи повертають об'єкти, які й містять потрібні дані.


Коментарі (24)
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ
Андрій Рівень 18
2 травня 2024
Останню задачу взято зі співбесіди в goolge на посаду senior розробника?
hidden #3421731 Рівень 28
15 травня 2024
полюбом.Я аж спотів
Vlad Рівень 21
7 жовтня 2024
Згоден
oleh ronin Рівень 47
13 листопада 2023
Всім привіт, я створив групу для української спільноти JavaRush в телеграмі (👈клік https://t.me/javaHelpUkraine) . Якщо тобі, при виконанні завдань щось було незрозумілим, виникли питання - долучайся та будемо допомогати. Також якщо ти вже експерт в Java, також долучайся, дискусувати ж з кимось потрібно🙂.
Михайло Рівень 1 Expert
2 травня 2023
Додайте на третю задачу позначку HARD!
Artem Рівень 1
18 травня 2023
Чому? одразу ж в око падає)
Sava_crosava Рівень 23
27 жовтня 2023
Сарказм) Інколи люди так глузують з різних речей та ситуацій)
theylovevalera Рівень 51
1 березня 2023
Сиджу на цьому рівні вже третій місяць,все-через останню задачу.
nepanikyu Рівень 34
11 лютого 2023
Третья задача это прикол ?
Бородатий Рівень 17
15 січня 2023
до другої задачі. тре почати писати return date. і далі все по інструкції
Бородатий Рівень 17
15 січня 2023
256- днів 12 вересня 18517 - час від 1970 )) можна використати в Гуглі калькулятор дат
24 лютого 2023
я просто глянув правильну відповідь🤡
AntonSaikevich Рівень 25
25 лютого 2023
Можна заморочитись і так) int day = 0; for(int i = 1970; i<2020; i++){ LocalDate date = LocalDate.of(i, 12, 31); day = day + date.getDayOfYear(); } LocalDate notToday = LocalDate.of(2020, 9, 11); day = day+notToday.getDayOfYear(); LocalDate today = LocalDate.ofEpochDay(day);
Pavlo Kezin Рівень 23
24 вересня 2023
методом наукового тику знайшов метод toEpochDay() (як розумію він повертає кількість днів від 1970) але це спрацює тільки, коли відома відповідь😁

return LocalDate.ofEpochDay(LocalDate.of(2020, Month.SEPTEMBER, 12).toEpochDay());
hidden #3421731 Рівень 28
15 травня 2024
запитав у GPT chat і потім йому ще пояснював що таке високосний рік
hidden #3143523 Рівень 25
7 січня 2023
Останню задача сильна💪
Бородатий Рівень 17
15 січня 2023
хахаха))
15 липня 2022
У першій задачі у методі ofEpochDayExample() якщо вираховувати кількість днів через date.getTime() таким чином: Date date = new Date (120, 8, 13); return LocalDate.ofEpochDay((date.getTime())/(1000 * 3600 * 24)); то працює наче правильно, але валідатор не схвалює. Чому?
hidden #3143523 Рівень 25
7 січня 2023
Я просто на калькуляторі підрахував і підставив цифри.Все працює
Avis_arctica Рівень 36
15 липня 2022
Після попереднього багатостраждального рівня ці задачки - наче відпустка)