Как преобразовать java.sql.timestamp в LocalDate (java8) java.time?

Как в Java 8 преобразовать Timestampjava.sql) в LocalDatejava.time)?


person simonides    schedule 24.04.2014    source источник
comment
У меня была похожая проблема здесь: stackoverflow.com/a/23197731/1856960. Короткий ответ, не совсем так. Но это не обязательно плохо.   -  person jacobhyphenated    schedule 24.04.2014


Ответы (3)


Ты можешь сделать:

timeStamp.toLocalDateTime().toLocalDate();

Обратите внимание, что timestamp.toLocalDateTime() для преобразования будет использоваться часовой пояс Clock.systemDefaultZone(). Это может быть или не быть тем, что вам нужно.

person assylias    schedule 24.04.2014
comment
Он был добавлен в Java 8. - person assylias; 24.04.2014
comment
Просто примечание: метод timestamp.toLocalDateTime() будет использовать часовой пояс systemDefault для преобразования. Это может быть или не быть тем, что вы хотите. - person jacobhyphenated; 24.04.2014
comment
@jacobhyphenated, пожалуйста, опубликуйте ответ, указав часовой пояс. Спасибо! - person user482745; 19.06.2018
comment
Комментарий @jacobhyphenated здесь чрезвычайно важен, отсюда и количество голосов за него. Подробнее см. в моем ответе stackoverflow.com/a/57101544/2032701 - person Ruslan; 18.07.2019
comment
@jacobhyphenated, LocalDateTime всегда использует системный часовой пояс по умолчанию. Вот что означает Local в своем названии. - person M. Prokhorov; 26.08.2019
comment
@ М.Прохоров Это не совсем так. LocalDateTime не имеет часового пояса, что отличается от использования системного часового пояса по умолчанию. Иногда это не имеет значения, иногда это может быть очень важным отличием. - person jacobhyphenated; 28.08.2019
comment
@jacobhyphenated, отсутствие информации о часовом поясе проявляется как невозможность преобразования его экземпляров в момент времени, если часовой пояс не указан явно. Однако now() теперь находится в зоне по умолчанию, следовательно, в локальной части. Честно говоря, было бы лучше просто назвать его DateTime, а не now(). - person M. Prokhorov; 28.08.2019

Принятый ответ не идеален, поэтому я решил добавить свои 2 цента.

timeStamp.toLocalDateTime().toLocalDate();

в целом это плохое решение, я даже не знаю, почему они добавили этот метод в JDK, поскольку он делает вещи действительно запутанными, выполняя неявное преобразование с использованием системного часового пояса. Обычно при использовании только классов даты java8 программист вынужден указывать часовой пояс, что хорошо.

Хорошее решение

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

Где zoneId – это часовой пояс, который вы хотите использовать. Обычно это либо ZoneId.systemDefault(), если вы хотите использовать системный часовой пояс, либо какой-либо жестко заданный часовой пояс, например ZoneOffset. Всемирное координированное время

Общий подход должен быть

  1. Освободитесь от новых классов даты java8, используя класс, который напрямую связан, например. в нашем случае java.time.Instant напрямую связан с java.sql.Timestamp, т. е. между ними не требуется никаких преобразований часовых поясов.
  2. Используйте хорошо разработанные методы в этом классе java8, чтобы поступать правильно. В нашем случае atZone(zoneId) явно указал, что мы выполняем преобразование и используем для этого определенный часовой пояс.
person Ruslan    schedule 18.07.2019
comment
Я не согласен. Отметка времени (а также дата) не содержат никакой информации о зоне. LocalDate не имеет никакой информации о зоне, поэтому они эквивалентны. Преобразование между ними может осуществляться независимо от какой-либо конкретной зоны. Преобразование в ZonedDateTime перед преобразованием в LocalDate добавляет часовой пояс, а затем снова снимает его - у вас гораздо больше шансов получить неприятную - трудно найти - ошибку, делая это таким образом. - person AutomatedMike; 13.08.2019
comment
Отметка времени @AutomatedMike (а также дата) представляют момент времени в формате UTC. LocalDate представляет не момент времени, а время, отображаемое на настенных часах. Пожалуйста, прочитайте их javadocs. Преобразование между ними может быть выполнено независимо от какой-либо конкретной зоны - неверно, new Timestamp(0L).toLocalDateTime() возвращает 1970-01-01T03:00 для моего московского часового пояса. Результат может отличаться для вашего часового пояса. - person Ruslan; 14.08.2019
comment
@AutomatedMike Даже если вы удалите время, выполнив toLocalDate(), легко доказать, что день может быть неправильным, если время Timestamp было около полуночи, например, new Timestamp(1000 * 60 * 60 * 23).toLocalDateTime().toLocalDate () возвращает 1970-01-02 для моего московского часового пояса, когда это 1970-01-01 в UTC. - person Ruslan; 14.08.2019
comment
@AutomatedMike добавляет часовой пояс, а затем снова снимает его - дело не в добавлении и удалении часового пояса, а в преобразовании между различными понятиями с использованием явного часового пояса. Это отличается от примеров из двух моих предыдущих комментариев, где часовой пояс применяется неявно. - person Ruslan; 14.08.2019

Я немного расширю ответ @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();
person Pavel    schedule 26.06.2018