Як конвертувати java.sql.timestamp в LocalDate (java8) java.time?


Відповіді:


196

Ви можете зробити:

timeStamp.toLocalDateTime().toLocalDate();

Зауважте, що для перетворення timestamp.toLocalDateTime() буде використаний Clock.systemDefaultZone()часовий пояс. Це може бути або не бути тим, що ви хочете.


1
Додано в Java 8.
assylias

54
Лише зауважте, timestamp.toLocalDateTime()метод використовуватиме часовий пояс systemDefault для перетворення. Це може бути або не бути тим, що ви хочете.
Якобхіфен

1
@jacobhyphenized, будь ласка, опублікуйте відповідь, використовуючи чіткий часовий пояс. Дякую!
user482745

Коментар @ jacobhyphenized тут надзвичайно важливий, отже, кількість звернень до нього. Дивіться мою відповідь для деталей stackoverflow.com/a/57101544/2032701
Руслан

@jacobhyphenized, LocalDateTimeзавжди використовує системний часовий пояс за замовчуванням. Ось що означає «Місцеве» у своїй назві.
М. Прохоров

21

Прийнята відповідь не є ідеальною, тому я вирішив додати свої 2 копійки

timeStamp.toLocalDateTime().toLocalDate();

загалом це погане рішення , я навіть не впевнений, чому вони додали цей метод до JDK, оскільки це робить нас справді заплутаним, роблячи неявну конверсію за допомогою часового поясу системи. Зазвичай при використанні тільки класів дати Java8 програміст змушений визначати часовий пояс, що є хорошою справою.

Хороше рішення

timestamp.toInstant().atZone(zoneId).toLocalDate()

Там, де zoneId - часовий пояс, який ви хочете використовувати, який, як правило, є ZoneId.systemDefault (), якщо ви хочете використовувати часовий пояс системи або якийсь жорсткий кодовий часовий пояс, наприклад ZoneOffset.UTC

Загальний підхід повинен бути

  1. Перервіться до нових класів дати java8, використовуючи клас, який безпосередньо пов'язаний, наприклад, у нашому випадку java.time.Instant безпосередньо пов'язаний з java.sql.Timestamp , тобто між ними не потрібні перетворення часового поясу.
  2. Використовуйте добре розроблені методи в цьому класі java8, щоб зробити правильно. У нашому випадку atZone (zoneId) дав зрозуміти, що ми робимо перетворення та використовуємо для цього певний часовий пояс.

1
Я не погоджуюсь. Тимчасові позначки (а також дата) не мають жодної інформації про зони. LocalDate не має жодної інформації про зону, тому вони є рівнозначними. Перетворення між ними може бути здійснено незалежно від будь-якої конкретної зони. Перетворення в ZonedDateTime перед переходом у LocalDate додає часовий пояс, а потім знову знімає його - ви набагато більше шансів отримати неприємну помилку - помилка, яка робить це таким чином.
AutomatedMike

5
@AutomatedMike Timestamp (а також дата) представляють момент часу в UTC. LocalDate не представляє собою момент часу, а скоріше час, як це спостерігається на настінному годиннику. Прочитайте їх javadocs. "Перетворення між ними можна здійснити незалежно від будь-якої конкретної зони" - неправда , нова часова марка (0L) .toLocalDateTime () повертає "1970-01-01T03: 00" для мого московського часового поясу. Результат може бути різним для вашого часового поясу.
Руслан

1
@AutomatedMike Навіть якщо ви знімаєте час, роблячи toLocalDate (), легко довести, що день може бути неправильним, якщо у Timestamp був час близько півночі, наприклад, новий Timestamp (1000 * 60 * 60 * 23) .toLocalDateTime (). ToLocalDate () повертає "1970-01-02" для мого московського часового поясу, коли в UTC "1970-01-01".
Руслан

1
@AutomatedMike "додає у часовий пояс, а потім знімає його знову" - справа не в додаванні та видаленні часового поясу, а в перетворенні між різними поняттями за допомогою явного часового поясу. Це на відміну від прикладів моїх попередніх двох коментарів, коли часовий пояс застосовується неявно .
Руслан

7

Я трохи розгорну відповідь @assylias, щоб врахувати часовий пояс. Існує щонайменше два способи отримати LocalDateTime для конкретного часового поясу.

Ви можете використовувати часовий пояс setDefault для всього додатка. Її слід викликати перед будь-якою часовою позначкою -> java.time конвертацією:

public static void main(String... args) {
    TimeZone utcTimeZone = TimeZone.getTimeZone("UTC");
    TimeZone.setDefault(utcTimeZone);
    ...
    timestamp.toLocalDateTime().toLocalDate();
}

Або ви можете використовувати мережу toInstant.atZone:

timestamp.toInstant()
        .atZone(ZoneId.of("UTC"))
        .toLocalDate();
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.