Bagaimana cara mengonversi java.sql.timestamp ke LocalDate (java8) java.time?

Jawaban:

196

Anda dapat melakukan:

timeStamp.toLocalDateTime().toLocalDate();

Perhatikan bahwa zona waktu timestamp.toLocalDateTime() akan digunakan Clock.systemDefaultZone()untuk melakukan konversi. Ini mungkin atau mungkin tidak yang Anda inginkan.

assylias
sumber
1
Ini telah ditambahkan di Jawa 8.
assylias
54
Sekadar catatan, timestamp.toLocalDateTime()metode ini akan menggunakan zona waktu systemDefault untuk melakukan konversi. Ini mungkin atau mungkin tidak yang Anda inginkan.
jacobhyphenated
1
@jacobhyphenated tolong posting jawaban menggunakan zona waktu eksplisit. Terima kasih!
pengguna482745
Komentar @ jacobhyphenated sangat penting di sini, oleh karena itu jumlah suara positif untuk itu. Lihat jawaban saya untuk detailnya stackoverflow.com/a/57101544/2032701
Ruslan
@jacobhyphenated, LocalDateTimeselalu menggunakan zona waktu default sistem. Itulah yang dimaksud dengan "Lokal" dalam namanya.
M. Prokhorov
21

Jawaban yang diterima tidak ideal, jadi saya memutuskan untuk menambahkan 2 sen saya

timeStamp.toLocalDateTime().toLocalDate();

adalah solusi yang buruk secara umum , saya bahkan tidak yakin mengapa mereka menambahkan metode ini ke JDK karena membuat hal-hal sangat membingungkan dengan melakukan konversi implisit menggunakan zona waktu sistem. Biasanya ketika hanya menggunakan kelas tanggal java8 programmer dipaksa untuk menentukan zona waktu yang merupakan hal yang baik.

Solusi yang bagus adalah

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

Di mana zoneId adalah zona waktu yang ingin Anda gunakan yang biasanya adalah ZoneId.systemDefault () jika Anda ingin menggunakan zona waktu sistem atau zona waktu hardcode seperti ZoneOffset.UTC

Pendekatan umum seharusnya

  1. Bebaskan diri ke kelas tanggal java8 baru menggunakan kelas yang terkait langsung, misalnya dalam kasus kita java.time.Instant secara langsung terkait dengan java.sql.Timestamp , yaitu tidak ada konversi zona waktu yang diperlukan di antara mereka.
  2. Gunakan metode yang dirancang dengan baik di kelas java8 ini untuk melakukan hal yang benar. Dalam kasus kami, atZone (zoneId) menjelaskan bahwa kami sedang melakukan konversi dan menggunakan zona waktu tertentu untuk itu.
Ruslan
sumber
1
Saya tidak setuju. Timestamp (dan juga Date) tidak memiliki informasi zona apa pun. LocalDate tidak memiliki informasi zona apa pun sehingga keduanya setara. Konversi di antara mereka dapat dilakukan secara independen dari zona tertentu mana pun. Mengonversi ke ZonedDateTime sebelum mengonversi ke LocalDate menambahkan zona waktu dan kemudian melepasnya lagi - Anda lebih mungkin mendapatkan kesalahan-sulit ditemukan- melakukannya dengan cara itu.
AutomatedMike
5
@AutomatedMike Timestamp (dan juga Date) menunjukkan titik waktu dalam UTC. LocalDate tidak mewakili suatu titik waktu, melainkan waktu seperti yang terlihat pada jam dinding. Silakan baca javadocs mereka. "Konversi di antara mereka dapat dilakukan secara independen dari zona tertentu" - tidak benar , Stempel Waktu (0L) baru .toLocalDateTime () mengembalikan "1970-01-01T03: 00" untuk zona waktu Moskow saya. Hasilnya mungkin berbeda untuk zona waktu Anda.
Ruslan
1
@AutomatedMike Meskipun Anda menghapus waktu dengan melakukan toLocalDate (), mudah untuk membuktikan bahwa hari itu bisa salah jika Stempel Waktu memiliki waktu sekitar tengah malam, misalnya Stempel Waktu baru (1000 * 60 * 60 * 23) .toLocalDateTime (). ToLocalDate () mengembalikan "1970-01-02" untuk zona waktu Moskow saya saat "1970-01-01" di UTC.
Ruslan
1
@AutomatedMike "menambahkan zona waktu lalu melepasnya lagi" - intinya bukan menambah dan menghapus zona waktu, melainkan mengubah di antara pengertian yang berbeda dengan menggunakan zona waktu eksplisit . Ini berbeda dengan contoh dari dua komentar saya sebelumnya di mana zona waktu diterapkan secara implisit .
Ruslan
7

Saya akan sedikit memperluas jawaban @assylias untuk memperhitungkan zona waktu. Setidaknya ada dua cara untuk mendapatkan LocalDateTime untuk zona waktu tertentu.

Anda dapat menggunakan zona waktu setDefault untuk seluruh aplikasi. Ini harus dipanggil sebelum stempel waktu -> konversi java.time:

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

Atau Anda dapat menggunakan rantai toInstant.atZone:

timestamp.toInstant()
        .atZone(ZoneId.of("UTC"))
        .toLocalDate();
Pavel
sumber