API для работы с датой и временем – одна из крупнейших особенностей выпуска Java 8. У Java с самого начала не было последовательного подхода к работе с датой и временем, и API для работы с датой и временем в Java 8 – долгожданное дополнение к основным API Java.
Зачем нам нужен новый API для работы с датой и временем в Java?
Прежде чем мы начнем рассматривать API для работы с датой и временем в Java 8, давайте посмотрим, зачем нам нужно новое API. У существующих классов для работы с датой и временем в Java есть несколько проблем, некоторые из них следующие:
- Классы для работы с датой и временем в Java не определены последовательно: у нас есть класс Date как в пакете java.util, так и в пакете java.sql. Кроме того, классы для форматирования и разбора определены в пакете java.text.
- java.util.Date содержит как дату, так и время, в то время как java.sql.Date содержит только значение даты. Наличие этого в пакете java.sql не имеет смысла. Кроме того, оба класса имеют одно и то же имя, что само по себе является очень плохим дизайном.
- Не существует четко определенных классов для работы с временем, метками времени, форматированием и разбором. У нас есть абстрактный класс java.text.DateFormat для разбора и форматирования. Обычно используется класс SimpleDateFormat для разбора и форматирования.
- Все классы Date изменяемы, поэтому они не являются потокобезопасными. Это одна из крупнейших проблем с классами Date и Calendar в Java.
- Класс Date не предоставляет интернационализацию, нет поддержки часового пояса. Поэтому были введены классы java.util.Calendar и java.util.TimeZone, но у них также есть все перечисленные выше проблемы.
Есть и другие проблемы с методами, определенными в классах Date и Calendar, но вышеуказанные проблемы ясно показывают, что в Java нужен надежный API для работы с датой и временем. Вот почему Joda Time сыграл ключевую роль как качественная замена для требований Java Date Time.
Принципы проектирования даты и времени в Java 8
API даты и времени в Java 8 – это реализация JSR-310. Он разработан для преодоления всех недостатков устаревших реализаций даты и времени. Некоторые из принципов проектирования нового API даты и времени:
-
Неизменяемость: Все классы в новом API даты и времени являются неизменяемыми и подходят для многопоточных сред.
-
Разделение забот: Новое API четко разделяет человекочитаемую дату и время и машинное время (Unix-метка времени). Оно определяет отдельные классы для Даты, Времени, ДатаВремени, Метки времени, Часового пояса и т.д.
-
Ясность: Методы четко определены и выполняют одно и то же действие во всех классах. Например, для получения текущего экземпляра у нас есть метод now(). Во всех этих классах определены методы format() и parse() вместо того, чтобы иметь отдельный класс для них.
Все классы используют Шаблон Фабрика и Шаблон Стратегия для лучшей обработки. После использования методов в одном из классов работа с другими классами не будет сложной.
-
Операции утилиты: Все новые классы API даты и времени поставляются с методами для выполнения общих задач, таких как плюс, минус, форматирование, разбор, получение отдельной части в дате/времени и т. д.
-
Расширяемость: Новый API даты и времени работает на календарной системе ISO-8601, но мы также можем использовать его с другими не ISO-календарями.
Пакеты API даты и времени
API даты и времени Java 8 состоит из следующих пакетов.
- java.time: Это базовый пакет нового API даты и времени Java. Все основные базовые классы являются частью этого пакета, такие как LocalDate, LocalTime, LocalDateTime, Instant, Period, Duration и т. д. Все эти классы являются неизменяемыми и потокобезопасными. В большинстве случаев эти классы будут достаточны для обработки общих требований.
- java.time.chrono: Этот пакет определяет общие API для календарных систем, не соответствующих ISO. Мы можем расширить класс AbstractChronology для создания собственной календарной системы.
- java.time.format: Этот пакет содержит классы, используемые для форматирования и разбора объектов даты и времени. В большинстве случаев мы не будем использовать их напрямую, потому что основные классы в пакете java.time предоставляют методы форматирования и разбора.
- java.time.temporal: Этот пакет содержит временные объекты, и мы можем использовать его для определения конкретных дат или временных точек, связанных с объектами даты/времени. Например, мы можем использовать их, чтобы определить первый или последний день месяца. Вы можете легко определить эти методы, потому что они всегда имеют формат “withXXX”.
- Пакет java.time.zone: Этот пакет содержит классы для поддержки различных часовых поясов и их правил.
Примеры классов Java 8 Date Time API
Мы рассмотрели большую часть важных частей Java Date Time API. Пора теперь рассмотреть наиболее важные классы Date Time API с примерами.
1. LocalDate
LocalDate – это неизменяемый класс, представляющий дату с форматом по умолчанию yyyy-MM-dd. Мы можем использовать метод now() для получения текущей даты. Мы также можем предоставить аргументы для года, месяца и дня для создания экземпляра LocalDate.
Этот класс предоставляет перегруженный метод для now(), в котором мы можем передать ZoneId для получения дат в определенном часовом поясе. Этот класс предоставляет ту же функциональность, что и java.sql.Date.
Пояснения к методам LocalDate предоставлены в комментариях. При запуске этой программы мы получаем следующий вывод.
2. LocalTime
LocalTime – это неизменяемый класс, экземпляр которого представляет собой время в удобочитаемом формате. Его формат по умолчанию – чч:мм:сс.мсс. Подобно LocalDate, этот класс поддерживает часовой пояс и создание экземпляра путем передачи часа, минуты и секунды в качестве входных аргументов.
Вывод:
3. LocalDateTime
LocalDateTime – это неизменяемый объект даты и времени, который представляет собой дату и время в формате по умолчанию yyyy-MM-dd-HH-mm-ss.zzz. Он предоставляет фабричный метод, который принимает в качестве аргументов ввода LocalDate и LocalTime для создания экземпляра LocalDateTime.
Во всех трех примерах мы видели, что если мы предоставляем недопустимые аргументы для создания Даты/Времени, то возникает исключение java.time.DateTimeException, которое является RuntimeException, поэтому нам не нужно явно его перехватывать.
Мы также видели, что можем получить данные о дате/времени, передавая ZoneId; вы можете получить список поддерживаемых значений ZoneId из его JavaDoc. Когда мы запускаем вышеуказанный класс, мы получаем следующий вывод.
4. Мгновенность
Класс Instant используется для работы с форматом времени, читаемым машиной. Instant хранит дату и время в формате Unix-времени.
Вывод:
Утилиты Java 8 Date API
Большинство основных классов для работы с датой и временем предоставляют различные утилиты, такие как плюс/минус дни, недели, месяцы и т. д. Существуют также другие утилиты для настройки даты с использованием TemporalAdjuster
и для расчета периода между двумя датами.
Вывод:
Java 8 Разбор и Форматирование Даты
Очень распространено форматировать дату в различные форматы, а затем разбирать строку, чтобы получить объекты Date Time.
Вывод:
Поддержка устаревших классов дат и времени в Java Date API
Устаревшие классы дат и времени используются практически во всех приложениях, поэтому обеспечение обратной совместимости является обязательным. Именно поэтому существует несколько утилитарных методов, с помощью которых мы можем преобразовывать устаревшие классы в новые и наоборот.
Результат:
Как видно, методы toString() устаревших классов TimeZone и GregorianCalendar слишком многословны и неудобны для пользователя.
Заключение
I like this new Date Time API a lot. Some of the most used classes will be LocalDate and LocalDateTime. It’s very easy to work with the new classes. And, having similar methods that does a particular job makes it easy to find. It will take some time from moving legacy classes to new Date Time classes, but I believe it will be worth the time and effort.
Source:
https://www.digitalocean.com/community/tutorials/java-8-date-localdate-localdatetime-instant