Bagaimana saya bisa membuat JavaD LocalDate dari masa Epoch yang lama dalam milidetik?

218

Saya memiliki API eksternal yang mengembalikan saya tanggal sebagai longs, diwakili sebagai milidetik sejak awal Zaman.

Dengan Java API gaya lama, saya hanya akan membangun Datedari dengannya

Date myDate = new Date(startDateLong)

Apa yang setara di Java 8 LocalDate/ LocalDateTimekelas?

Saya tertarik mengonversi titik waktu yang diwakili oleh longke LocalDatedalam zona waktu lokal saya saat ini.

Vihung
sumber
6
Anda harus mulai dengan menentukan zona waktu yang Anda pedulikan. Nilai "milidetik sejak zaman" memberi Anda waktu instan ... yang dapat merujuk ke tanggal berbeda di zona waktu berbeda. Ingatlah bahwa java.util.Dateitu tidak pernah benar-benar kencan dengan cara yang LocalDate- itu instan dalam waktu juga.
Jon Skeet
2
Periksa pertanyaan ini: stackoverflow.com/questions/21242110/… , yang mencakup konversi java.util.DatemenjadiLocalDate
hotzst
3
Catatan: Q & A ini juga berharga bagi mereka yang berusaha untuk mengkonversi File.lastModified()(zaman millis) ke LocalDate(Time).
kevinarpe

Jawaban:

403

Jika Anda memiliki milidetik sejak Zaman dan ingin mengubahnya menjadi tanggal lokal menggunakan zona waktu setempat saat ini, Anda dapat menggunakan

LocalDate date =
    Instant.ofEpochMilli(longValue).atZone(ZoneId.systemDefault()).toLocalDate();

tetapi perlu diingat bahwa bahkan zona waktu standar sistem dapat berubah, sehingga nilai yang sama longdapat menghasilkan hasil yang berbeda dalam proses selanjutnya, bahkan pada mesin yang sama.

Lebih jauh, ingatlah bahwa LocalDate, tidak seperti java.util.Date, benar-benar mewakili tanggal, bukan tanggal dan waktu.

Jika tidak, Anda dapat menggunakan LocalDateTime:

LocalDateTime date =
    LocalDateTime.ofInstant(Instant.ofEpochMilli(longValue), ZoneId.systemDefault());
Holger
sumber
2
+1 dari saya untuk penjelasan lebih rinci. Omong-omong, bahkan zona non-sistem dapat berubah (dengan tzupdater-tool atau oleh jdk-change) dan karenanya menghasilkan hasil yang berbeda sebelum dan sesudah.
Meno Hochschild
2
@Meno Hochschild: Saya tidak berfokus pada zona waktu yang dikodekan, melainkan membandingkan dengan zona waktu yang ditentukan oleh pengguna, membaca dari file konfigurasi atau variabel lingkungan, di mana programmer secara alami mengasumsikan bahwa mungkin berubah. Zona waktu hardcoded memang sangat mirip dengan standar sistem; programmer tergoda untuk berpikir bahwa mereka tidak pernah berubah ...
Holger
2
@ Demigod LocalDateTime.ofEpochSecond(…)membutuhkan aktual ZoneOffset, tetapi ZoneId.systemDefault()mengembalikan a ZoneId. Can ZoneIddapat memetakan ke offset yang berbeda, tergantung pada titik waktu yang Anda maksud. Itulah yang LocalDateTime.ofInstantAnda lakukan, mengonversi yang ditentukan ZoneIdsesuai dengan yang disediakan Instant.
Holger
2
Zaman didefinisikan sebagai UTC dan karena itu harus zona waktu independen, sehingga ZoneId harus selalu UTC.
PlexQ
2
@PlexQ Zona waktu yang ditentukan tidak relevan untuk Zaman, yang memang zona waktu independen, tetapi untuk semantik yang dihasilkan LocalDateatau LocalDateTime. Anda dapat menentukan zona waktu yang Anda inginkan, asalkan konsisten dengan penggunaan objek hasil selanjutnya. Pikirkan apa yang terjadi ketika Anda berurusan dengan banyak objek yang dibuat dengan metode yang berbeda. Kasing yang umum digunakan untuk tanggal atau datetimes lokal menggabungkan zona waktu default sistem, misalnya LocalDateTime.now()LocalDateTime.ofInstant(Instant.ofEpochMilli(System.currentTimeMillis()), ZoneId.systemDefault())
Holger
37

Anda bisa mulai dengan Instant.ofEpochMilli (panjang) :

LocalDate date =
  Instant.ofEpochMilli(startDateLong)
  .atZone(ZoneId.systemDefault())
  .toLocalDate();
Meno Hochschild
sumber
5
+1 untuk eksplisit tentang zona waktu. Jika dihilangkan, zona waktu default JVM saat ini secara implisit diterapkan dalam menentukan tanggal. Untuk setiap saat, tanggalnya bervariasi di seluruh dunia berdasarkan zona waktu ketika hari baru tiba di timur.
Basil Bourque
12

Saya pikir saya punya jawaban yang lebih baik.

new Timestamp(longEpochTime).toLocalDateTime();
Abhijeet
sumber
Timestamp baru (ts) .toLocalDateTime (). toLocalDate ()
Stepan Yakovenko
5
Maksud saya - jika Anda tidak keberatan mengimpor javal.sql.Timestamp, yang, mengingat sifat monolitik Jawa, saya kira baik-baik saja karena itu semua adalah bagian dari JVM ... tetapi terasa agak bau, tapi saya masih lebih suka waktu yang diakui pada dasarnya adalah dalam UTC.
PlexQ
1
The Timestampkelas buruk dirancang dan panjang usang. Kode Anda akan menggunakan pengaturan zona waktu JVM, tetapi karena pengaturan ini dapat diubah oleh bagian lain dari program Anda atau program lain yang berjalan di JVM yang sama, kami tidak dapat memastikan apa itu.
Ole VV
1
Itu selalu lebih baik untuk menjadi eksplisit tentang zona waktu yang digunakan. Menggunakan java.sql.Timestamp lama memiliki kelemahan memiliki sistem zona waktu yang diterapkan secara implisit yang biasanya menyebabkan kebingungan di antara para pengembang.
Ruslan
3

Zona waktu dan hal-hal samping, alternatif yang sangat sederhana untuk new Date(startDateLong)bisaLocalDate.ofEpochDay(startDateLong / 86400000L)

Michael Piefel
sumber
6
Saya pikir Anda setidaknya harus menjelaskan apa kepanjangan dari 86400000L.
BAERUS
3
Saya pikir itu sangat mudah dikenali bahwa itu adalah jumlah milidetik dalam sehari.
Michael Piefel
7
Untuk beberapa orang, dan saya pikir hanya itu yang masuk akal, tetapi tanpa perhitungan ulang berapa banyak ms dalam sehari, saya tidak akan yakin. Hanya berbicara sendiri, saya tidak tahu nomor ini dengan baik sehingga saya secara otomatis tahu apa artinya.
BAERUS
Perhatikan juga bahwa jawaban yang diterima benar-benar adalah jawaban terbaik, itu hanya terlihat luar biasa. Retas sederhana saya cukup dalam banyak hal. Sayang sekali yang java.timetidak termasuk DateTimeConstantsJoda.
Michael Piefel
2
java.util.concurrent.TimeUnit.MILLISECONDS.toDays(startDateLong)
Vadzim
1

ganti now.getTime () dengan nilai lama Anda.

//GET UTC time for current date
        Date now= new Date();
        //LocalDateTime utcDateTimeForCurrentDateTime = Instant.ofEpochMilli(now.getTime()).atZone(ZoneId.of("UTC")).toLocalDateTime();
        LocalDate localDate = Instant.ofEpochMilli(now.getTime()).atZone(ZoneId.of("UTC")).toLocalDate();
        DateTimeFormatter dTF2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
        System.out.println(" formats as " + dTF2.format(utcDateTimeForCurrentDateTime));
Santhosh Hirekerur
sumber
-6

Dalam kasus tertentu di mana cap waktu detik Anda berasal dari SQL atau terkait dengan SQL, Anda dapat memperolehnya seperti ini:

long startDateLong = <...>

LocalDate theDate = new java.sql.Date(startDateLong).toLocalDate();
M. Prokhorov
sumber
2
Ini tidak benar-benar berhubungan banyak dengan pertanyaan yang diajukan
Ketan R
@KetanR, saya tidak setuju. Pertanyaannya adalah "bagaimana cara mendapatkan LocalDatedari epoch-millis", dan saya menunjukkan caranya, menggunakan java.sql.Datesingkatan. Pendekatan ini masuk akal dalam kode yang sudah berurusan dengan JDBC dalam beberapa kapasitas, dan itu berfungsi dengan baik. Jika Anda masih belum yakin, jelaskan bagaimana hal itu tidak terkait dengan pertanyaan awal.
M. Prokhorov
2
Jika Anda membaca pertanyaan, dikatakan "API eksternal yang mengembalikan saya tanggal selama" dan Anda menjelaskan bagaimana konversi ini dapat dilakukan jika Anda menerima tanggal panjang dari SQL. Jawaban Anda memang menjelaskan kasus konversi tanggal yang sangat spesifik tetapi tidak benar-benar relevan dengan pertanyaan yang diajukan. Penjelasan Anda bisa menjadi jawaban yang valid untuk beberapa pertanyaan terkait lainnya.
Ketan R
@KetanR, jika seseorang menerima tanggal panjang dari SQL, saya akan menyarankan untuk mengubah rencananya sehingga dia tidak lagi menerima tanggal dalam bentuk seperti itu. Namun, jika seseorang menerima tanggal sebagai milis-cap waktu dari tempat lain (API eksternal), dan segera menggunakan tanggal ini untuk membuat pertanyaan JDBC, maka java.sql.Datependekatan adalah salah satu yang tersingkat, bijaksana kode, dan saya akan mengatakan itu tidak terlalu berguna untuk pergi meskipun Instantdengan semua objek sementara sementara ketika hasil akhirnya sama.
M. Prokhorov
2
Seperti yang telah saya katakan dan terbukti dari penjelasan terakhir Anda, jawaban Anda benar tetapi tidak untuk pertanyaan yang ada. Pertanyaan mengatakan: "Saya tertarik untuk mengubah titik waktu yang diwakili oleh panjang ke LocalDate di zona waktu lokal saya saat ini. "jawaban Anda mengatakan:" terima tanggal sebagai milis-cap waktu, dan segera gunakan tanggal ini untuk membuat pertanyaan JDBC ". Saya tidak mengerti apa yang tidak jelas di sini?
Ketan R