Saya memiliki nilai Stempel waktu yang berasal dari aplikasi saya. Pengguna dapat berada di TimeZone lokal mana pun.
Karena tanggal ini digunakan untuk WebService yang mengasumsikan waktu yang diberikan selalu dalam GMT, saya perlu mengonversi parameter pengguna dari say (EST) menjadi (GMT). Inilah kickernya: Pengguna tidak menyadari TZ-nya. Dia memasukkan tanggal pembuatan yang ingin dia kirim ke WS, jadi yang saya butuhkan adalah:
Masukkan pengguna: 5/1/2008 6:12 PM (EST)
Parameter ke WS harus : 5/1/2008 6:12 PM (GMT)
Saya tahu Stempel Waktu seharusnya selalu dalam GMT secara default, tetapi ketika mengirim parameter, meskipun saya membuat Kalender saya dari TS (yang seharusnya dalam GMT), jam selalu tidak aktif kecuali pengguna dalam GMT. Apa yang saya lewatkan?
Timestamp issuedDate = (Timestamp) getACPValue(inputs_, "issuedDate");
Calendar issueDate = convertTimestampToJavaCalendar(issuedDate);
...
private static java.util.Calendar convertTimestampToJavaCalendar(Timestamp ts_) {
java.util.Calendar cal = java.util.Calendar.getInstance(
GMT_TIMEZONE, EN_US_LOCALE);
cal.setTimeInMillis(ts_.getTime());
return cal;
}
Dengan Kode sebelumnya, inilah yang saya dapatkan sebagai hasilnya (Format Singkat agar mudah dibaca):
[1 Mei 2008 11:12]
Jawaban:
Berikut outputnya jika saya melewatkan waktu saat ini ("12:09:05 EDT" dari
Calendar.getInstance()
) di:12:09:05 GMT adalah 8:09:05 EDT.
Bagian yang membingungkan di sini adalah yang
Calendar.getTime()
mengembalikan AndaDate
pada zona waktu Anda saat ini, dan juga tidak ada metode untuk mengubah zona waktu kalender dan juga tanggal yang mendasarinya. Bergantung pada jenis parameter apa yang diambil layanan web Anda, Anda mungkin hanya ingin memiliki kesepakatan WS dalam milidetik dari epoch.sumber
offsetFromUTC
daripada menambahkannya? Menggunakan contoh Anda, jika 12:09 GMT adalah 8:09 EDT (yang benar), dan pengguna memasukkan "12:09 EDT", algoritme harus menghasilkan "16:09 GMT", menurut pendapat saya.Terima kasih atas tanggapannya. Setelah penyelidikan lebih lanjut, saya mendapat jawaban yang benar. Seperti yang disebutkan oleh Skip Head, TimeStamped yang saya dapatkan dari aplikasi saya sedang disesuaikan dengan TimeZone pengguna. Jadi jika Pengguna memasukkan 6:12 PM (EST) saya akan mendapatkan 2:12 PM (GMT). Apa yang saya butuhkan adalah cara untuk membatalkan konversi sehingga waktu yang dimasukkan oleh pengguna adalah waktu yang saya kirimkan ke permintaan WebServer. Inilah cara saya mencapai ini:
Output kode adalah: (Pengguna memasukkan 5/1/2008 6:12 PM (EST)
Zona Waktu Pengguna Saat Ini: EST
Offset Saat Ini dari GMT (dalam jam): - 4 (Biasanya -5, kecuali disesuaikan DST)
TS dari ACP: 2008-05-01 14: 12: 00.0
Tanggal Kalender dikonversi dari TS menggunakan GMT dan US_EN Lokal : 1/5/08 18:12 (GMT)
sumber
Anda mengatakan bahwa tanggal digunakan sehubungan dengan layanan web, jadi saya berasumsi bahwa itu diserialkan menjadi string di beberapa titik.
Jika demikian, Anda harus melihat metode setTimeZone dari kelas DateFormat. Ini menentukan zona waktu mana yang akan digunakan saat mencetak cap waktu.
Contoh sederhana:
sumber
Anda bisa mengatasinya dengan Joda Time :
Jawa 8:
sumber
Sepertinya Stempel Waktu Anda disetel ke zona waktu dari sistem asal.
Ini sudah usang, tetapi seharusnya berfungsi:
Cara yang tidak digunakan lagi adalah dengan menggunakan
tetapi itu perlu dilakukan di sisi klien, karena sistem tersebut mengetahui zona waktunya.
sumber
Metode untuk mengonversi dari satu zona waktu ke zona waktu lainnya (mungkin berhasil :)).
sumber
Objek Tanggal dan Stempel Waktu tidak menyadari zona waktu: objek tersebut mewakili jumlah detik tertentu sejak zaman, tanpa melakukan interpretasi tertentu saat itu sebagai jam dan hari. Zona waktu memasukkan gambar hanya di GregorianCalendar (tidak diperlukan secara langsung untuk tugas ini) dan SimpleDateFormat , yang memerlukan offset zona waktu untuk mengonversi antara bidang terpisah dan nilai Tanggal (atau panjang ).
Masalah OP ada tepat di awal pemrosesannya: jam input pengguna, yang ambigu, dan ditafsirkan dalam zona waktu lokal non-GMT; pada titik ini nilainya adalah "6:12 EST" , yang dapat dengan mudah dicetak sebagai "11.12 GMT" atau zona waktu lainnya tetapi tidak akan pernah berubah menjadi "6.12 GMT" .
Tidak ada cara untuk membuat SimpleDateFormat yang mengurai "06:12" sebagai "HH: MM" (default ke zona waktu lokal) sebagai default ke UTC; SimpleDateFormat agak terlalu pintar untuk kebaikannya sendiri.
Namun, Anda dapat meyakinkan setiap instance SimpleDateFormat untuk menggunakan zona waktu yang benar jika Anda meletakkannya secara eksplisit di input: cukup tambahkan string tetap ke "06:12" yang diterima (dan divalidasi secara memadai) untuk mengurai "06:12 GMT" sebagai "HH: MM z" .
Tidak perlu pengaturan eksplisit bidang Kalender Gregorian atau mengambil dan menggunakan offset zona waktu dan waktu musim panas.
Masalah sebenarnya adalah memisahkan input yang default ke zona waktu lokal, input yang default ke UTC, dan input yang benar-benar membutuhkan indikasi zona waktu yang eksplisit.
sumber
Sesuatu yang berhasil bagi saya di masa lalu adalah menentukan offset (dalam milidetik) antara zona waktu pengguna dan GMT. Setelah Anda memiliki offset, Anda dapat menambahkan / mengurangi (tergantung ke arah mana konversi akan) untuk mendapatkan waktu yang sesuai di kedua zona waktu. Saya biasanya akan melakukannya dengan menyetel bidang milidetik dari objek Kalender, tetapi saya yakin Anda dapat dengan mudah menerapkannya ke objek stempel waktu. Berikut kode yang saya gunakan untuk mendapatkan offset
timezoneId adalah id zona waktu pengguna (seperti EST).
sumber
java.time
Pendekatan modern menggunakan kelas java.time yang menggantikan kelas tanggal-waktu lama yang merepotkan yang digabungkan dengan versi Java yang paling awal.
The
java.sql.Timestamp
kelas adalah salah satu kelas warisan. Tidak lagi dibutuhkan. Sebagai gantinya gunakanInstant
atau kelas java.time lainnya secara langsung dengan database Anda menggunakan JDBC 4.2 dan yang lebih baru.The
Instant
kelas merupakan saat di timeline di UTC dengan resolusi nanodetik (hingga sembilan (9) angka dari pecahan desimal).Jika Anda harus beroperasi dengan yang sudah ada
Timestamp
, segera ubah menjadi java.time melalui metode konversi baru yang ditambahkan ke kelas lama.Untuk menyesuaikan dengan zona waktu lain, tentukan zona waktu sebagai
ZoneId
objek. Tentukan nama zona waktu yang tepat dalam formatcontinent/region
, sepertiAmerica/Montreal
,Africa/Casablanca
, atauPacific/Auckland
. Jangan pernah menggunakan 3-4 huruf pseudo-zone sepertiEST
atauIST
karena itu bukan zona waktu yang sebenarnya, tidak terstandarisasi, dan bahkan tidak unik (!).Terapkan ke
Instant
untuk menghasilkanZonedDateTime
objek.Untuk menghasilkan string untuk ditampilkan kepada pengguna, telusuri Stack Overflow untuk
DateTimeFormatter
menemukan banyak diskusi dan contoh.Pertanyaan Anda benar-benar tentang pergi ke arah lain, dari entri data pengguna ke objek tanggal-waktu. Umumnya paling baik untuk memecah entri data Anda menjadi dua bagian, tanggal dan waktu.
Pertanyaanmu tidak jelas. Apakah Anda ingin mengartikan tanggal dan waktu yang dimasukkan oleh pengguna sebagai UTC? Atau di zona waktu lain?
Jika yang Anda maksud adalah UTC, buat file
OffsetDateTime
dengan offset menggunakan konstanta untuk UTCZoneOffset.UTC
,.Jika yang Anda maksud zona waktu lain, gabungkan dengan objek zona waktu, a
ZoneId
. Tapi zona waktu yang mana? Anda mungkin mendeteksi zona waktu default. Atau, jika penting, Anda harus mengonfirmasi dengan pengguna untuk memastikan niat mereka.Untuk mendapatkan objek yang lebih sederhana yang selalu dalam UTC menurut definisi, ekstrak file
Instant
.…atau…
Kirim ke database Anda.
Tentang java.time
The java.time kerangka dibangun ke Jawa 8 dan kemudian. Kelas-kelas ini menggantikan tua merepotkan warisan kelas tanggal-waktu seperti
java.util.Date
,Calendar
, &SimpleDateFormat
.Proyek Joda-Time , sekarang dalam mode pemeliharaan , menyarankan migrasi ke java.time kelas .
Untuk mempelajari lebih lanjut, lihat Tutorial Oracle . Dan cari Stack Overflow untuk banyak contoh dan penjelasan. Spesifikasinya adalah JSR 310 .
Dimana mendapatkan kelas java.time?
Proyek ThreeTen-Extra memperluas java.time dengan kelas tambahan. Proyek ini adalah tempat pembuktian untuk kemungkinan penambahan java.time di masa mendatang. Anda mungkin menemukan beberapa kelas berguna di sini seperti
Interval
,YearWeek
,YearQuarter
, dan lebih .sumber