Перейти к основному содержимому

Преобразование даты в LocalDate или LocalDateTime и обратно

· 4 мин. чтения

1. Обзор

Начиная с Java 8, у нас есть новый API Date: java.time .

Однако иногда нам по-прежнему необходимо выполнять преобразования между новым и старым API и работать с представлениями даты из обоих.

2. Преобразование java.util.Date в java.time.LocalDate

Начнем с преобразования старого представления даты в новое.

Здесь мы можем воспользоваться новым методом toInstant() , который был добавлен в java.util.Date в Java 8.

Когда мы преобразовываем объект Instant , необходимо использовать ZoneId , потому что объекты Instant не зависят от часового пояса — просто точки на временной шкале.

API atZone(ZoneId zone) из объекта Instant возвращает ZonedDateTime , поэтому нам просто нужно извлечь из него LocalDate с помощью метода toLocalDate() .

Во-первых, мы используем системный ZoneId по умолчанию :

public LocalDate convertToLocalDateViaInstant(Date dateToConvert) {
return dateToConvert.toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDate();
}

И похожее решение, но с другим способом создания объекта Instant — с использованием метода ofEpochMilli() :

public LocalDate convertToLocalDateViaMilisecond(Date dateToConvert) {
return Instant.ofEpochMilli(dateToConvert.getTime())
.atZone(ZoneId.systemDefault())
.toLocalDate();
}

Прежде чем двигаться дальше, давайте также кратко рассмотрим старый класс java.sql.Date и то, как его можно также преобразовать в LocalDate .

Начиная с Java 8, мы можем найти дополнительный метод toLocalDate () для java.sql.Date , который также дает нам простой способ преобразования его в java.time.LocalDate .

В этом случае нам не нужно беспокоиться о часовом поясе:

public LocalDate convertToLocalDateViaSqlDate(Date dateToConvert) {
return new java.sql.Date(dateToConvert.getTime()).toLocalDate();
}

Точно так же мы можем преобразовать старый объект Date в объект LocalDateTime . Давайте посмотрим на это дальше.

3. Преобразование java.util.Date в java.time.LocalDateTime

Чтобы получить экземпляр LocalDateTime , мы можем аналогичным образом использовать посредник ZonedDateTime, а затем использовать API toLocalDateTime() .

Как и раньше, мы можем использовать два возможных решения для получения объекта Instant из java.util.Date :

public LocalDateTime convertToLocalDateTimeViaInstant(Date dateToConvert) {
return dateToConvert.toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDateTime();
}

public LocalDateTime convertToLocalDateTimeViaMilisecond(Date dateToConvert) {
return Instant.ofEpochMilli(dateToConvert.getTime())
.atZone(ZoneId.systemDefault())
.toLocalDateTime();
}

Обратите внимание, что для дат до 10 октября 1582 года необходимо настроить Calendar как григорианский календарь и вызвать метод setGregorianChange ():

GregorianCalendar calendar = new GregorianCalendar();
calendar.setGregorianChange(new Date(Long.MIN_VALUE));
Date dateToConvert = calendar.getTime();

И, начиная с Java 8, мы также можем использовать java.sql.Timestamp для получения LocalDateTime :

ocalDateTime convertToLocalDateTimeViaSqlTimestamp(Date dateToConvert) {
return new java.sql.Timestamp(
dateToConvert.getTime()).toLocalDateTime();
}

4. Преобразование java.time.LocalDate в java.util.Date

Теперь, когда мы хорошо понимаем, как преобразовать старое представление данных в новое, давайте посмотрим на преобразование в другом направлении.

Мы обсудим два возможных способа преобразования LocalDate в Date .

В первом мы используем новый метод valueOf(LocalDate date) , предоставленный в объекте java.sql.Date , который принимает LocalDate в качестве параметра:

public Date convertToDateViaSqlDate(LocalDate dateToConvert) {
return java.sql.Date.valueOf(dateToConvert);
}

Как мы видим, это легко и интуитивно понятно. Он использует местный часовой пояс для преобразования (все делается скрыто, так что не о чем беспокоиться).

В другом примере Java 8 мы используем объект Instant , который мы передаем в метод from (Instant Instant) объекта java.util.Date : **** ``

public Date convertToDateViaInstant(LocalDate dateToConvert) {
return java.util.Date.from(dateToConvert.atStartOfDay()
.atZone(ZoneId.systemDefault())
.toInstant());
}

Обратите внимание, что здесь мы используем объект Instant и что нам также нужно позаботиться о часовых поясах при выполнении этого преобразования.

Далее воспользуемся очень похожим решением для преобразования LocalDateTime в объект Date .

5. Преобразование java.time.LocalDateTime в java.util.Date

Самый простой способ получить java.util.Date из LocalDateTime использовать расширение для java.sql.Timestamp, доступное в Java 8:

public Date convertToDateViaSqlTimestamp(LocalDateTime dateToConvert) {
return java.sql.Timestamp.valueOf(dateToConvert);
}

Но, конечно, альтернативным решением является использование объекта Instant , который мы получаем из ZonedDateTime :

Date convertToDateViaInstant(LocalDateTime dateToConvert) {
return java.util.Date
.from(dateToConvert.atZone(ZoneId.systemDefault())
.toInstant());
}

6. Дополнения для Java 9

В Java 9 доступны новые методы, упрощающие преобразование между java.util.Date и java.time.LocalDate или java.time.LocalDateTime .

LocalDate.ofInstant(Instant Instant, ZoneId zone) и LocalDateTime.ofInstant(Instant Instant, ZoneId zone) предоставляют удобные ярлыки:

public LocalDate convertToLocalDate(Date dateToConvert) {
return LocalDate.ofInstant(
dateToConvert.toInstant(), ZoneId.systemDefault());
}

public LocalDateTime convertToLocalDateTime(Date dateToConvert) {
return LocalDateTime.ofInstant(
dateToConvert.toInstant(), ZoneId.systemDefault());
}

7. Заключение

В этой статье мы рассмотрели возможные способы преобразования старого java.util.Date в новые java.time.LocalDate и java.time.LocalDateTime , а также наоборот.

Полная реализация этой статьи доступна на GitHub .