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

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

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

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

Вступ до Date Time API

Розробникам Java не дуже подобалася поточна ситуація з класами Date і Calendar. Вони були хороші свого часу, але часи змінюються. І потрібно було щось просте, потужне та надійне. І ось разом з випуском Java8 (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). Проте це додало класу простоти та надійності. Особливо якщо з об'єктом класу одночасно взаємодіє декілька потоків (threads).

Щоб створити новий об'єкт класу 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 розробника?
Ва Дим Рівень 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());
Ва Дим Рівень 28
15 травня 2024
запитав у GPT chat і потім йому ще пояснював що таке високосний рік
Beisik Рівень 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)); то працює наче правильно, але валідатор не схвалює. Чому?
Beisik Рівень 25
7 січня 2023
Я просто на калькуляторі підрахував і підставив цифри.Все працює
Avis_arctica Рівень 36
15 липня 2022
Після попереднього багатостраждального рівня ці задачки - наче відпустка)