1. Введение в 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). Зато это добавило классу простоты и надежности. Особенно если с объектом класса одновременно взаимодействуют несколько нитей (потоков исполнения).
Чтобы создать новый объект класса LocalDate, нужно использовать один из статических методов. Вот список основных.
Получение текущей даты
Чтобы получить текущую дату, нужно воспользоваться статическим методом now(). Это гораздо проще, чем кажется:
LocalDate today = LocalDate.now();
Где today — это переменная класса LocalDate, а LocalDate.now() — вызов статического метода now() у класса LocalDate.
Пример:
| Код | Вывод на экран |
|---|---|
|
|
Получение даты в определенном часовом поясе
Также у класса LocalDate есть разновидность метода now(ZoneId), который позволяет получить текущую дату в определенном часовом поясе.
Для этого нам понадобится еще один класс — ZoneId (java.time.ZoneId). У него есть метод of(), который возвращает объект ZoneId по имени часового пояса.
Чтобы определить текущую дату в Шанхае, нужно написать код:
| Код | Вывод на экран |
|---|---|
|
|
Список имен всех часовых поясов (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 месяцы перестали нумеровать с нуля.
Пример:
| Код | Вывод на экран |
|---|---|
|
|
Получение даты по номеру дня
Есть еще один любопытный метод создания даты: с помощью метода ofYearDay можно получить дату, имея только номер года и номер дня года. Общий вид такой:
LocalDate date = LocalDate.ofYearDay(год, день);
Где год — это номер года, а день — номер дня в году.
Пример:
| Код | Вывод на экран |
|---|---|
|
|
Сотый день в 2019 году — это 10 апреля.
Получение даты Unix
Помните, что объекты класса Date всегда хранили время в миллисекундах с 1 января 1970 года? Чтобы программисты не скучали по старым добрым временам, в класс LocalDate добавили метод ofEpochDay(), который возвращает дату, отсчитанную от 1 января 1970 года. Общий вид такой:
LocalDate date = LocalDate.ofEpochDay(день);
Где день — это количество дней, прошедшее с 1 января 1970 года.
Пример:
| Код | Вывод на экран |
|---|---|
|
|
4. Получение фрагментов даты
Изменять объекты класса LocalDate нельзя, а вот получать отдельные фрагменты даты еще как можно. Для этого у объектов класса LocalDate есть несколько методов:
| Метод | Описание |
|---|---|
|
Возвращает год из конкретной даты |
|
Возвращает месяц даты — одну из специальных константJANUARY, FEBRUARY, ...; |
|
Возвращает номер месяца из даты. Январь == 1. |
|
Возвращает номер дня в месяце |
|
Возвращает номер дня с начала года |
|
Возвращает день недели: одну из специальных константMONDAY, TUESDAY, ...; |
|
Возвращает эру: константа BC (Before Current Era) и CE(Current Era) |
Пример:
| Код | Вывод на экран |
|---|---|
|
|
5. Изменение даты в объекте LocalDate
Класс LocalDate содержит несколько методов, которые позволяют работать с датой. Эти методы реализованы по аналогии с методами класса String: каждый из этих методов не меняет существующий объект LocalDate, а возвращает новый с нужными данными.
Вот какие методы есть у класса LocalDate:
| Метод | Описание |
|---|---|
|
Добавляет определенное количество дней к дате |
|
Добавляет недели к дате |
|
Добавляет месяцы к дате |
|
Добавляет годы к дате |
|
Отнимает дни от даты |
|
Отнимает недели от даты |
|
Отнимает месяцы от даты |
|
Отнимает годы от даты |
Пример:
| Код | Вывод на экран |
|---|---|
|
|
Объект birthday, чьи методы мы вызываем, не меняется. Вместо этого его методы возвращают новые объекты, которые и содержат нужные данные.