Дата и время

Вы, конечно, можете хранить год, месяц и день месяца в int-ах. Однако скоро вы столкнётесь с тем, что посчитать количество дней между 20 января и 16 апреля – не такая очевидная операция. Как минимум, ввиду разного количества дней в месяцах.

В общем, гораздо удобнее использовать уже готовые классы, заточенные под хранение и вычисление даты. Аналогично со временем. Давайте посмотрим, что приготовил для нас пакет java.time.

Дата

Для оперирования датой без времени подходит класс LocalDate. Создать его объект можно через, например, LocalDate.now() для получения текущей даты. Или с помощью LocalDate.of() для задания года, месяца и дня.

Вывод даты LocalDate в консоль

Как результат, видим в консоли два представления даты, сформированных переопределённым методом toString() у LocalDate. То есть написать System.out.println(currentDate) то же самое, что System.out.println(currentDate.toString()).

Первым идёт год, затем идёт месяц, а цепочку закрывает день.

В свою очередь, получать отдельные частигод, месяц и день (но не только) – можно так:

Выведем полученные значения в консоль. Посмотрите: мы можем получить не только численные значения года, месяца и дня в месяце. Мы можем получить название месяца (enum Month), название дня недели (enum DayOfWeek) и порядковый номер дня в году. Сегодня вторник, 27 февраля 2024 года. В январе был 31 день, плюс 27 в феврале – как раз 58!

Вывод результатов работы методов LocalDate в консоль

Можно сравнивать даты при помощи методов isBefore(), isAfter() и isEqual():

Получается, currentDate (2024-02-27) находится после specificDate (2022-04-15), не находится до и не равна. Всё верно, так и есть. 27 февраля 2024 года – это после 15 апреля 2022 года.

Вывод результатов работы методов LocalDate в консоль

Помимо получений характеристик определённой даты и сохранения их в переменные, нужно уметь оперировать интервалами между датами. Например, можно производить всяческие операции и вычисления: к выбранной дате прибавлять или отнимать дни, недели, месяцы, годы:

Посмотрим на вывод в консоль:

Вывод результатов работы методов LocalDate в консоль

Я думаю, это отличная возможность для управления датами. Например, вам требуется выяснить, прошла ли неделя с некоторого момента. Это звучит очевидно до тех пор, пока ваша неделя не стоит на пересечении двух месяцев, у которых ещё и количество дней может быть разным. Нечего тратить время на то, что уже реализовано и отлично работает.

Таким образом, если нам нужно получить дату перед или после текущей, чтобы она отличалась на несколько дней, недель, месяцев или лет – это легко сделать при помощи методов вроде plusDays() и minusDays().

Также полезная функция – нахождение интервала времени между двумя заданными датами. Его можно находить разными способами.

Первый из них – при использовании класса Period. Это класс, представляющий собой промежуток в годах, месяцах и днях.

У класса Period есть всякие возможности. Однако нет одной очень важной – общее количество дней. Есть только общее количество месяцев. А также частное количество лет, месяцев и дней. А ведь общее количество дней бывает жизненно необходимым.

Вывод результатов работы методов Period в консоль

Поэтому можно воспользоваться другим способом, а именно – методом until() с указанием, что рассчитывать нужно именно дни (не месяцы и не годы). Таким образом:

Вывод результата работы метода LocalDate в консоль

Итак, подсчёты говорят, что от одной даты до другой ровно 683 дня.

Есть и третий способ – воспользоваться методом datesUntil(). Он возвращает stream дат между двумя датами. А метод count() у этого stream-а вернёт количество этих дат – то есть дней между датами.

Как видим, count() у stream-а вернул действительно ровно столько же дней (683), как и предыдущий способ подсчёта. Далее начинается пересчёт всех дат между этими двумя датами. Они идут подряд с разницей в один день каждая. Кто знает, может, и такое кому-нибудь пригодится.

Вывод результатов работы методов LocalDate в консоль

Время

Класс LocalTime предоставляет функционал по управлению временем в Java. Вот как можно создавать время:

Вывод создания объектов LocalTime в консоль

В значение времени можно задавать часы и минуты. А можно дополнительно указать секунды. Более того, можно указать и наносекунды. В currentTime, то есть LocalTime.now() после 34 и точки как раз идут доли этой секунды.

Теперь получим данные из объекта времени firstTime – часы, минуты, секунды, наносекунды:

Итак, время 12:30:14 нам удалось разбить на отдельные составляющие – часы, минуты, секунды и наносекунды, коих 0. Кроме того, мы сумели получить порядковую секунду дня – и на момент времени 12:30:14 это 45014-ая секунда. Вполне неплохо: всего в дне 86400, а мы установили чуть позже полудня. Вроде сходится.

Вывод результатов работы методов LocalTime в консоль

Как и даты, время можно сравнивать. Делается это такими же методами isAfter() и isBefore(). Правда, isEqual() нету, можно использовать вместо него equals().

Вывод результатов работы методов LocalTime в консоль

Да, 12:30 действительно раньше, чем 16:17. В свою очередь, 16:17 не раньше, чем 12:30. И уж точно они не равны.

Ещё аналогичным образом, как и с датой, можно прибавлять и отнимать время:

Удобно, не правда ли? Это очень упрощает жизнь. Также есть методы для наносекунд, кстати – plusNanos() и minusNanos().

Вывод результатов работы методов LocalTime в консоль

Для нахождения продолжительности времени между двумя LocalTime, используется класс Duration.

Вывод результатов работы методов Duration в консоль

Видно, что между 12:30:14 и 16:17:05 разница во времени – 3 часа 46 минут 51 секунда. Всего это 13611000 миллисекунд, 13611 секунд, 226 минут или 3 часа. Причём при получении общего количества минут отбрасываются секунды, а при получении общего количества часов отбрасываются минуты.

И дата, и время

Если вам нужно управлять и датой, и временем, вам подойдёт класс LocalDateTime. По сути, это просто комбинация данных из LocalDate и LocalTime. Вот так можно создать объект LocalDateTime:

Для создания объекта с произвольной датой и временем нужно внести 6 значений: год, месяц, день, час, минута, секунда. Также можно опустить секунды или добавить наносекунды.

Вывод создания объектов LocalDateTime в консоль

В целом, все остальные методы схожи с LocalDate и LocalTime. Ведь LocalDateTime может точно так же возвращать значения своих характеристик. Может он и прибавлять/отнимать дни, недели, месяцы, годы (а также часы, минуты, секунды). Он может и находить разницу между датами и временем. И, конечно, определять, какие дата и время были до, а какие после. Даже называются методы точно так же.

Часовые пояса

В настоящих проектах локальной датой и временем обычно дело не обходится. Ведь пользователи могут быть из разных часовых поясов, а время согласовать каким-то образом надо. Поэтому применяется класс ZonedDateTime, который хранит не только время и дату, но и часовой пояс. Таким образом, можно будет сравнивать хронологию временных меток пользователей даже из разных стран.

Чтобы создать ZonedDateTime, можно вводить много int-ов характеристик даты и времени. А можно создать объект из готового LocalDateTime, просто указав часовой пояс:

Вывод создания объектов LocalDateTime в консоль

Выводится много цифр и букв. Как видно в консоли, на моём компьютере стоит часовой пояс UTC+3. В Нью-Йорке он UTC+4. А в Париже – UTC+1.

В общем-то и всё. Ведь ZonedDateTime, как и LocalDateTime, реализует те же методы, что есть в LocalDate и LocalTime.

В итоге, в этой статье мы рассмотрели 4 класса по работе с датой и временем. Шучу, на самом деле 6: ещё Period и Duration. И 3 enum-а (Month, DayOfWeek, ChronoUnit). Что ж, они позволяют создавать, форматировать, преобразовывать и выполнять операции с датой и временем в Java с учетом временной зоны или без неё. И это удобно.

Добавить комментарий