Diberikan kode berikut

public static void main(String[] args) {
     org.joda.time.format.DateTimeFormatter _timestampFomatNYCJoda = org.joda.time.format.DateTimeFormat.forPattern("yyyyMMdd HHmmss.SSS").withZone(DateTimeZone.forID("America/New_York"));
     DateTimeFormatter _timestampFomatNYC = DateTimeFormatter.ofPattern("yyyyMMdd HHmmss.SSS").withZone(ZoneId.of("America/New_York"));
     LocalDateTime localDateTime = LocalDateTime.now();
     org.joda.time.LocalDateTime jodaLocalDateTime = new org.joda.time.LocalDateTime();
     System.out.println("System Time " + new Date());
     System.out.println("Java Version " +  localDateTime.format(_timestampFomatNYC));
     System.out.println("Joda Version " +  _timestampFomatNYCJoda.print(jodaLocalDateTime.toDateTime(DateTimeZone.UTC)));
} 

Mengapa Versi Java dan Versi Joda tidak cocok? Saya menjalankan ini pada jam IST.

Di bawah ini adalah outputnya

System Time Fri Mar 27 17:01:33 IST 2020
Java Version 20200327 170133.933
Joda Version 20200327 130133.938
1
Abhishek Singh 27 Maret 2020, 14:33

1 menjawab

Jawaban Terbaik

Saya dapat mereproduksi hasil Anda. Saya juga bisa menjelaskannya. Joda-Time dan Java.time telah dirancang untuk berperilaku berbeda dalam kasus ini. Mari kita lihat mereka secara bergantian.

Waktu Joda

Di Joda-Time DateTimeFormatter.withZone() memberi Anda pemformat dengan zona penggantian, yaitu, zona yang selalu akan digunakan untuk memformat tanggal dan waktu. Dengan kata lain, setiap tanggal dan waktu akan dikonversi ke zona ini untuk dicetak. Dokumentasi mengatakan:

Saat mencetak, zona ini akan digunakan dalam preferensi ke zona dari tanggal waktu yang seharusnya digunakan.

Saat Anda melakukan new org.joda.time.LocalDateTime(), Anda mendapatkan LocalDateTime yang mewakili tanggal dan waktu saat ini di zona waktu default Anda. Local dalam beberapa nama kelas berarti tanpa zona waktu atau offset dari UTC. Saya pikir Anda harus mendapatkan nilai yang sama dengan 2020-03-27T17:01:33.938.

Rupanya apa yang terjadi ketika Anda memformat LocalDateTime dengan pemformat dengan zona override, adalah bahwa pemformat mengasumsikan bahwa LocalDateTime Anda ada di UTC (yang bukan milik Anda) dan mengonversinya dari sana, di kasus ke zona waktu Amerika/New_York. Karena waktu musim panas (DST) berlaku di New York, offsetnya adalah -04:00, jadi 17:01 menjadi 13:01.

Ini adalah hasil yang salah. Ketika waktunya 17:01 di zona waktu Anda, itu bukan 17:01 UTC, jadi konversi didasarkan pada premis yang salah. Ini juga bukan pukul 13:01 di New York, jadi hasil konversi adalah bohong.

java.time

Dengan pengaturan Java.time, zona override pada formatter berfungsi sama untuk pemformatan, tetapi dengan perbedaan yang penting di sini: zona override hanya digunakan saat mencetak objek tanggal-waktu yang mengidentifikasi instan (titik waktu). Dari dokumen:

Saat memformat, jika objek temporal berisi instan, maka itu akan dikonversi ke tanggal-waktu yang dikategorikan menggunakan zona override. Apakah temporal adalah instan ditentukan dengan menanyakan INSTANT_SECONDS bidang. Jika input memiliki kronologi maka itu akan menjadi dipertahankan kecuali diganti. Jika input tidak memiliki kronologi, seperti Instan, maka kronologi ISO akan digunakan.

… Dalam semua kasus lain, zona override ditambahkan ke temporal, menggantikan zona sebelumnya, tetapi tanpa mengubah tanggal/waktu.

Sekali lagi LocalDateTime.now() memberi Anda tanggal dan waktu saat ini (beberapa milidetik lebih awal dari kueri melalui Joda-Time), 2020-03-27T17:01:33.933. Local masih berarti tanpa offset atau zona waktu.

Karena LocalDateTIme Anda tidak memiliki offset atau zona waktu, ia tidak dapat mengidentifikasi titik waktu yang jelas, seketika. Oleh karena itu saat memformatnya, baik tanggal maupun waktu tidak berubah. Dan karena pola format Anda tidak mengandung zona waktu atau offset, tidak ada yang dicetak. Jadi Anda hanya mendapatkan tanggal dan waktu di zona waktu Anda (bukan di New York), 20200327 170133.933.

Untuk mendapatkan tanggal dan waktu di zona waktu New York

    DateTimeFormatter timestampFormat
            = DateTimeFormatter.ofPattern("yyyyMMdd HHmmss.SSS");
    ZonedDateTime timeInNy = ZonedDateTime.now(ZoneId.of("America/New_York"));
    System.out.println(timeInNy.format(timestampFormat));

Ketika saya menjalankan kode ini sekarang, hasilnya adalah:

20200327 122359.683

Tautan dokumentasi

2
Ole V.V. 27 Maret 2020, 16:31