Статья

Как преобразовать строку в дату в Java?

В этой статье мы рассмотрим несколько способов конвертации строк в объекты типа Date. Начнем с нового Date Time API, java.time, который был представлен в Java 8, а также рассмотрим устаревший пакет java.util, который использовался ранее.
В конце статьи рассмотрим внешние библиотеки и классы из пакета Joda-Time и Apache Commons Lang DateUtils.

Преобразование строки в LocalDate или LocalDateTime

LocalDate и LocalDateTime являются неизменяемыми date-time объектами, которые представляют дату, а также дату и время соответственно. По умолчанию даты Java представлены в формате ISO-8601, поэтому, если у нас есть какая-либо строка, представляющая дату и время в этом формате, то мы можем напрямую использовать parse() API этих классов.

Использование Parse API

Date-Time API предоставляет методы parse() для синтаксического анализа строки, содержащей информацию о дате и времени. Чтобы преобразовать объекты String в объекты LocalDate и LocalDateTime, строка должна представлять корректную дату или время в соответствии с ISO_LOCAL_DATE или ISO_LOCAL_DATE_TIME.
В противном случае во время выполнения будет вызвано исключение DateTimeParseException. В нашем первом примере давайте преобразуем строку в java.time.LocalDate:
LocalDate date = LocalDate.parse("2023-06-18");
Аналогичный описанному выше подход может быть использован для преобразования строки в java.time.LocalDateTime:
LocalDateTime dateTime = LocalDateTime.parse("2023-06-18T12:52:55");
Важно отметить, что как объекты LocalDate, так и LocalDateTime не зависят от часового пояса. Однако, когда нам нужно иметь дело с датами и временем, зависящими от часового пояса, мы можем использовать метод parse() из ZonedDateTime, чтобы получить дату и время, зависящие от часового пояса:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z");
ZonedDateTime zonedDateTime = ZonedDateTime.parse("2023-06-18 14:15:30 Europe/Berlin", formatter);
Теперь давайте посмотрим, как преобразовать строки в пользовательский формат.

Использование Parse API с пользовательским форматером

Преобразование строки с использованием пользовательского форматера даты в объект Date является широко распространенной операцией в Java.
Для этой цели мы будем использовать класс DateTimeFormatter, который предоставляет множество предопределенных параметров форматирования и позволяет нам определить средство форматирования.
Давайте начнем с примера использования одного из предопределенных форматеров DateTimeFormatter:
String dateInString = "19850709";
LocalDate date = LocalDate.parse(dateInString, DateTimeFormatter.BASIC_ISO_DATE);
В следующем примере давайте создадим средство форматирования, которое применяет формат “EEE, MMM d yyyy”. Этот формат определяет три символа для полного названия дня недели, одну цифру для обозначения дня месяца, три символа для обозначения месяца и четыре цифры для обозначения года.

Этот форматер распознает такие строки, как “Fri, 18 Jan 1985“ or “Wed, 23 Feb 1998:
String dateInString = "Mon, 15 May 1985";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE, d MMM yyyy", Locale.ENGLISH);
LocalDate dateTime = LocalDate.parse(dateInString, formatter);

Общие шаблоны даты и времени

Давайте рассмотрим некоторые распространенные шаблоны даты и времени:
  • y – Год (1918; 18)
  • M – Месяц года (July; Jul; 07)
  • d – День месяца (1-31)
  • E – Имя дня недели (Friday, Sunday)
  • a AM/PM маркер
  • H – Час (0-23)
  • h – Час в формате AM/PM (1-12)
  • m – Минута (0-60)
  • s – Секунда (0-60)

Конвертация String в java.util.Date

До Java 8 механизм даты и времени предоставлялся старыми API в классах java.util.Date, java.util.Calendar и java.util.TimeZone с которыми нам иногда все еще приходится работать.
Давайте посмотрим, как преобразовать строку в объект java.util.Date:
SimpleDateFormat formatter = new SimpleDateFormat("dd-MMM-yyyy", Locale.ENGLISH);

String dateInString = "18-Jun-2015";
Date date = formatter.parse(dateInString);
В приведенном примере нам сначала нужно создать объект SimpleDateFormat, передав шаблон, описывающий формат даты и времени. Далее нам нужно вызвать метод parse(), принимающий дату в виде строки. Если переданный строковый аргумент не имеет того же формата, что и шаблон, то будет выдано исключение ParseException.

Добавление информации о часовом поясе в java.util.Date

Важно отметить, что java.util.Date не имеет понятия часового пояса и представляет только количество секунд, прошедших с момента времени эпохи Unix – 1970-01-01T00:00:00Z.
Однако, когда мы печатаем объект Date напрямую, он всегда будет печататься с системным часовым поясом Java по умолчанию.
В последнем примере мы рассмотрим, как форматировать дату c информацией о часовом поясе:
SimpleDateFormat formatter = new SimpleDateFormat("dd-M-yyyy hh:mm:ss a", Locale.ENGLISH);
formatter.setTimeZone(TimeZone.getTimeZone("America/New_York"));

String dateInString = "23-01-2018 12:15:53 AM"; 
Date date = formatter.parse(dateInString);
String formattedDateString = formatter.format(date);
Мы также можем изменить часовой пояс JVM программно, но это не рекомендуется:
TimeZone.setDefault(TimeZone.getTimeZone("GMT"));

Внешние библиотеки работы с датой

Теперь, когда у нас есть хорошее представление о том, как преобразовать объекты String в объекты Date, используя новые и старые API, предлагаемые Java Core, давайте взглянем на некоторые внешние библиотеки.

Библиотека Joda-Time

Альтернативой основной библиотеке Date and Time Java является Joda-Time. Хотя авторы теперь рекомендуют пользователям перейти на java.time (JSR-310), если это невозможно, то библиотека Joda-Time предоставляет отличную альтернативу для работы с датой и временем. Эта библиотека предоставляет практически все возможности, поддерживаемые в проекте Java 8 Date Time.
Артефакт можно найти на Maven Central:
<dependency>
    <groupId>joda-time</groupId>
    <artifactId>joda-time</artifactId>
    <version>2.12.2</version>
</dependency>
Вот небольшой пример работы со стандартным DateTime:
DateTimeFormatter formatter = DateTimeFormat.forPattern("dd/MM/yyyy HH:mm:ss");

String dateInString = "01/08/2022 14:17:59";
DateTime dateTime = DateTime.parse(dateInString, formatter);
Давайте также посмотрим пример явной установки часового пояса:
DateTimeFormatter formatter = DateTimeFormat.forPattern("dd/MM/yyyy HH:mm:ss");

String dateInString = "01/08/2022 14:17:59";
DateTime dateTime = DateTime.parse(dateInString, formatter);
DateTime dateTimeWithZone = dateTime.withZone(DateTimeZone.forID("America/Los_Angeles"));

Библиотека Apache Commons Lang – DateUtils

Класс DateUtils предоставляет множество полезных утилит, упрощающих работу с устаревшими объектами Calendar и Date.
Артефакт commons-lang3 доступен в Maven Central:
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.12.0</version>
</dependency>
Давайте преобразуем дату в виде строки в объект java.util.Date с использованием массива шаблонов дат:
String dateInString = "07/08-2017";
Date date = DateUtils.parseDate(dateInString, new String[] { "yyyy-MM-dd HH:mm:ss", "dd/MM-yyyy" });

Заключение

В этой статье мы проиллюстрировали несколько способов преобразования строк в различные типы объектов Date (со временем и без него), как в обычном Java, так и с использованием внешних библиотек.
java