Конвертировать LocalDate в LocalDateTime или java.sql.Timestamp - PullRequest
106 голосов
/ 24 января 2012

Я использую JodaTime 1.6.2.

У меня есть LocalDate, который мне нужно преобразовать в (Joda) LocalDateTime или java.sqlTimestamp для ormapping.

Причина этого в том, что я выяснил, как конвертировать между LocalDateTime и java.sql.Timestamp:

LocalDateTime ldt = new LocalDateTime();
DateTimeFormatter dtf = DateTimeFormatter.forPattern("yyyy-MM-dd HH:mm:ss");
Timestamp ts = Timestamp.valueOf(ldt.toString(dtf));

Итак, если я могу просто конвертировать между LocalDate и LocalDateTime,тогда я смогу продолжить преобразование в java.sql.Timestamp.Спасибо за любые толчки в правильном направлении!

Ответы [ 7 ]

238 голосов
/ 24 января 2012

JodaTime

Чтобы преобразовать JodaTime org.joda.time.LocalDate в java.sql.Timestamp, просто сделайте

Timestamp timestamp = new Timestamp(localDate.toDateTimeAtStartOfDay().getMillis());

Чтобы преобразовать JodaTime org.joda.time.LocalDateTime в java.sql.Timestamp, просто сделайте

Timestamp timestamp = new Timestamp(localDateTime.toDateTime().getMillis());

JavaTime

Чтобы преобразовать Java8 java.time.LocalDate в java.sql.Timestamp, просто выполните

Timestamp timestamp = Timestamp.valueOf(localDate.atStartOfDay());

Чтобы преобразовать Java8 java.time.LocalDateTime в java.sql.Timestamp, просто выполните

Timestamp timestamp = Timestamp.valueOf(localDateTime);
52 голосов
/ 08 января 2015

Лучший способ использовать Java 8 time API:

  LocalDateTime ldt = timeStamp.toLocalDateTime();
  Timestamp ts = Timestamp.valueOf(ldt);

Для использования с JPA, установленным вместе с вашей моделью (https://weblogs.java.net/blog/montanajava/archive/2014/06/17/using-java-8-datetime-classes-jpa):

@Converter(autoApply = true)
public class LocalDateTimeConverter implements AttributeConverter<LocalDateTime, Timestamp> {
    @Override
    public Timestamp convertToDatabaseColumn(LocalDateTime ldt) {
        return Timestamp.valueOf(ldt);
    }

    @Override
    public LocalDateTime convertToEntityAttribute(Timestamp ts) {
        return ts.toLocalDateTime();
    }
}

Так что теперь это относительное время, независимое от часового пояса. Дополнительно это легко сделать:

  LocalDate ld = ldt.toLocalDate();
  LocalTime lt = ldt.toLocalTime();

Форматирование:

 DateTimeFormatter DATE_TME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")
 String str = ldt.format(DATE_TME_FORMATTER);
 ldt = LocalDateTime.parse(str, DATE_TME_FORMATTER);

ОБНОВЛЕНИЕ: postgres 9.4.1208, HSQLDB 2.4.0 и т. Д. Понимают Java 8 Time API без каких-либо разговоров!

10 голосов
/ 13 марта 2018

tl; dr

Проект Joda-Time находится в режиме обслуживания, теперь его заменяют java.time классы.

  • Просто используйте java.time.Instant класс.
  • Нет необходимости:
    • LocalDateTime
    • java.sql.Timestamp
    • Strings

Захват текущего момента в UTC.

Instant.now()  

Для сохранения этого момента в базе данных:

myPreparedStatement.setObject( … , Instant.now() )  // Writes an `Instant` to database.

Чтобы извлечь этот момент из базы данных:

myResultSet.getObject( … , Instant.class )  // Instantiates a `Instant`

Чтобы настроить время настенных часов на время определенного часового пояса.

instant.atZone( z )  // Instantiates a `ZonedDateTime`

LocalDateTime неправильный класс

Другие ответы верны, но они не указывают, что LocalDateTime неправильный класс для вашей цели.

В обоих java.time и Joda-Time , LocalDateTime преднамеренно лишены какой-либо концепции часового пояса или смещения от UTC.Таким образом, не представляет момент, а не является точкой на временной шкале.LocalDateTime представляет приблизительное представление о потенциальных моментах в диапазоне около 26-27 часов.

Используйте LocalDateTime для случаев, когда зона / смещение неизвестна (плохая ситуация) или когда смещение зоны неопределенное.Например, «Рождество начинается в первый момент 25 декабря 2018 года» будет представлено как LocalDateTime.

. Используйте ZonedDateTime для представления момента в определенном часовом поясе.Например, Рождество, начинающееся в любой конкретной зоне, такой как Pacific/Auckland или America/Montreal, будет представлено объектом ZonedDateTime.

Для момента всегда в UTC используйте Instant.

Instant instant = Instant.now() ;  // Capture the current moment in UTC.

Применение часового пояса.Тот же самый момент, та же точка на временной шкале, но просматриваемая с другим временем настенных часов.

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;  // Same moment, different wall-clock time.

Итак, если я могу просто конвертировать между LocalDate и LocalDateTime,

Нет, неправильная стратегия.Если у вас есть значение только для даты, и вы хотите значение даты и времени, вы должны указать время суток.Это время суток может быть недопустимым в эту дату для конкретной зоны - в этом случае класс ZonedDateTime автоматически корректирует время суток по мере необходимости.

LocalDate ld = LocalDate.of( 2018 , Month.JANUARY , 23 ) ;
LocalTime lt = LocalTime.of( 14 , 0 ) ;  // 14:00 = 2 PM.
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;

Если вы хотите первыйМомент дня, как ваше время, позвольте java.time определить этот момент.Не думайте, что день начинается в 00:00:00.Аномалии, такие как переход на летнее время (DST), означают, что день может начаться в другое время, например 01: 00: 00.

ZonedDateTime zdt = ld.atStartOfDay( z ) ;

java.sql.Timestamp - неправильный класс

java.sql.Timestamp является частью проблемных старых классов даты и времени, которые теперь унаследованы и полностью вытеснены классами java.time .Этот класс использовался для представления момента в UTC с разрешением наносекунд .Эта цель теперь выполняется с java.time.Instant.

JDBC 4.2 с getObject / setObject

Начиная с JDBC 4.2 и вышеВаш драйвер JDBC может напрямую обмениваться объектами java.time с базой данных, вызывая:

Например:

myPreparedStatement.setObject( … , instant ) ;

… и…

Instant instant = myResultSet.getObject( … , Instant.class ) ;

Преобразовать наследие ⬌ современный

Есливы должны взаимодействовать со старым кодом, который еще не обновлен до java.time , конвертировать туда и обратно, используя новые методы, добавленные к старым классам.

Instant instant = myJavaSqlTimestamp.toInstant() ;  // Going from legacy class to modern class.

… и…

java.sql.Timestamp myJavaSqlTimestamp = java.sql.Timestamp.from( instant ) ;  // Going from modern class to legacy class.

О java.time

Фреймворк java.time встроен в Java 8 и более поздние версии.Эти классы вытесняют проблемные старые устаревшие классы даты и времени, такие как java.util.Date, Calendar, & SimpleDateFormat.

Проект Joda-Time , теперь в режиме обслуживания , рекомендует перейти на классы java.time .

Чтобы узнать больше, см. Oracle Tutorial .И поиск переполнения стека для многих примеров и объяснений.Спецификация JSR 310 .

Вы можете эксизмените java.time объекты непосредственно с вашей базой данных.Используйте драйвер JDBC , совместимый с JDBC 4.2 или более поздней версией.Нет необходимости в строках, нет необходимости в java.sql.* классах.

Где получить классы java.time?

  • Java SE 8 , Java SE 9 , а позднее
    • Встроенный-в.
    • Часть стандартного API Java с встроенной реализацией.
    • Java 9 добавляет некоторые незначительные функции и исправления.
  • Java SE 6 и Java SE 7
    • Большая часть функций java.time перенесена на Java 6 & 7 в ThreeTen-Backport .
  • Android
    • Более поздние версии реализации комплекта Android классов java.time.
    • Для более ранних версий Android (<26) адаптируется проект <a href="https://github.com/JakeWharton/ThreeTenABP" rel="noreferrer"> ThreeTenABP ThreeTen-Backport (упомянуто выше).См. Как использовать ThreeTenABP… .

ThreeTen-Extra Проект расширяет java.time дополнительными классами.Этот проект является полигоном для возможных будущих дополнений к java.time.Здесь вы можете найти несколько полезных классов, таких как Interval, YearWeek, YearQuarter и more .

5 голосов
/ 11 апреля 2012

В зависимости от вашего часового пояса вы можете потерять несколько минут (1650-01-01 00:00:00 становится 1649-12-31 23:52:58)

Используйте следующий код, чтобы избежать

new Timestamp(localDateTime.getYear() - 1900, localDateTime.getMonthOfYear() - 1, localDateTime.getDayOfMonth(), localDateTime.getHourOfDay(), localDateTime.getMinuteOfHour(), localDateTime.getSecondOfMinute(), fractional);
2 голосов
/ 12 марта 2018

Поскольку Joda становится блеклой, кто-то может захотеть преобразовать LocaltDate в LocalDateTime в Java 8. В Java 8 LocalDateTime это даст способ создать экземпляр LocalDateTime с использованием LocalDate и LocalTime.Проверьте здесь.

public static LocalDateTime of (LocalDate date, LocalTime time)

Пример будет,

    // just to create a sample LocalDate
    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd");
    LocalDate ld = LocalDate.parse("20180306", dtf);

    // convert ld into a LocalDateTime
    // We need to specify the LocalTime component here as well, it can be any accepted value
    LocalDateTime ldt = LocalDateTime.of(ld, LocalTime.of(0,0)); // 2018-03-06T00:00

Только для справки. Для получения значений эпох, указанных ниже,

    ZoneId zoneId = ZoneId.systemDefault();
    long epoch = ldt.atZone(zoneId).toEpochSecond(); 

    // If you only care about UTC
    long epochUTC = ldt.toEpochSecond(ZoneOffset.UTC);
0 голосов
/ 15 марта 2019

вызов функции asStartOfDay() on java.time.LocalDate объект возвращает java.time.LocalDateTime объект

0 голосов
/ 05 декабря 2018

Java8 +

import java.time.Instant;
Instant.now().getEpochSecond(); //timestamp in seconds format (int)
Instant.now().toEpochMilli(); // timestamp in milliseconds format (long)
...