FYI: Kedua kelas mengerikan ini digantikan bertahun-tahun yang lalu oleh kelas java.time yang didefinisikan dalam JSR 310. Lihat ZonedDateTimekelas, dan metode konversi baru ditambahkan ke kelas lawas. Detail dalam Jawaban ini oleh Ole VV
Basil Bourque
Jawaban:
36
Saya ingin mengambil langkah mundur dan melihat modern pada pertanyaan berumur 10 tahun ini. Kelas-kelas yang disebutkan, Datedan XMLGregorianCalendar, sudah tua sekarang. Saya menantang penggunaan mereka dan menawarkan alternatif.
Dateselalu dirancang dengan buruk dan berusia lebih dari 20 tahun. Ini sederhana: jangan gunakan itu.
XMLGregorianCalendarsudah tua juga dan memiliki desain kuno. Seperti yang saya pahami, ini digunakan untuk menghasilkan tanggal dan waktu dalam format XML untuk dokumen XML. Suka 2009-05-07T19:05:45.678+02:00atau 2009-05-07T17:05:45.678Z. Format ini cukup sesuai dengan ISO 8601 sehingga kelas java.time, API tanggal dan waktu Jawa modern, dapat memproduksinya, yang kami inginkan.
Tidak perlu konversi
Untuk banyak tujuan (sebagian besar?) Pengganti modern untuk Dateakan menjadi Instant. An Instantadalah titik waktu (sama seperti apa adanya Date).
Itu sama dengan yang terakhir dari contoh XMLGregorianCalendarstring saya di atas. Seperti sebagian besar dari Anda tahu, itu berasal dari Instant.toStringdipanggil secara implisit System.out.println. Dengan java.time, dalam banyak kasus kita tidak perlu konversi yang di hari tua kita dibuat antara Date, Calendar, XMLGregorianCalendardan kelas-kelas lain (dalam beberapa kasus kita lakukan konversi kebutuhan, meskipun, saya menunjukkan kepada Anda beberapa di bagian berikutnya) .
Mengontrol offset
Baik a Datemaupun in tidak Instantmemiliki zona waktu atau offset UTC. Jawaban yang diterima sebelumnya dan masih dinilai tertinggi oleh Ben Noland menggunakan zona waktu default JVM saat ini untuk memilih offset dari XMLGregorianCalendar. Untuk memasukkan offset dalam objek modern, kami menggunakan OffsetDateTime. Sebagai contoh:
ZoneId zone =ZoneId.of("America/Asuncion");OffsetDateTime dateTime = yourInstant.atZone(zone).toOffsetDateTime();System.out.println(dateTime);
2009-05-07T13: 05: 45.678-04: 00
Sekali lagi ini sesuai dengan format XML. Jika Anda ingin menggunakan pengaturan zona waktu JVM saat ini lagi, atur zoneke ZoneId.systemDefault().
Bagaimana jika saya benar-benar membutuhkan XMLGregorianCalendar?
Ada banyak cara untuk mengkonversi Instantke XMLGregorianCalendar. Saya akan menyajikan pasangan, masing-masing dengan pro dan kontra. Pertama, seperti halnya XMLGregorianCalendarmenghasilkan string 2009-05-07T17:05:45.678Z, itu juga dapat dibangun dari string seperti itu:
Apakah menyimpan untuk menjaga getInstance () sebagai variabel statis di beberapa kelas konverter? Saya mencoba mencarinya di JavaDoc tetapi tidak menemukan apa pun. Agak sulit untuk mengetahui apakah akan ada masalah dalam penggunaan bersamaan?
Martin
36
Jika Anda bersedia untuk menggunakan JodaTime Anda dapat melakukan ini dalam satu baris: DatatypeFactory.newInstance () newXMLGregorianCalendar. (DateTime baru () toGregorianCalendar ().)
Nicolas Mommaerts
3
XMLGregorianCalendar date2 = DatatypeFactory.newInstance (). NewXMLGregorianCalendar (GregorianCalendar baru (YYYY, MM, DD));
Berikut adalah metode untuk mengkonversi dari GregorianCalendar ke XMLGregorianCalendar; Saya akan meninggalkan bagian konversi dari java.util.Date ke GregorianCalendar sebagai latihan untuk Anda:
Saya pikir saya akan menambahkan solusi saya di bawah ini, karena jawaban di atas tidak memenuhi kebutuhan saya yang sebenarnya. Skema Xml saya membutuhkan elemen Tanggal dan Waktu yang terpisah, bukan bidang DateTime yang baru. Konstruktor XMLGregorianCalendar standar yang digunakan di atas akan menghasilkan bidang DateTime
Perhatikan ada beberapa gothca, seperti harus menambahkan satu ke bulan (karena java menghitung bulan dari 0).
Saya harap penyandian saya di sini benar; D Untuk membuatnya lebih cepat cukup gunakan panggilan getInstance () jelek dari GregorianCalendar alih-alih panggilan konstruktor:
import java.util.GregorianCalendar;import javax.xml.datatype.DatatypeFactory;import javax.xml.datatype.XMLGregorianCalendar;publicclassDateTest{publicstaticvoid main(finalString[] args)throwsException{// do not forget the type cast :/GregorianCalendar gcal =(GregorianCalendar)GregorianCalendar.getInstance();XMLGregorianCalendar xgcal =DatatypeFactory.newInstance().newXMLGregorianCalendar(gcal);System.out.println(xgcal);}}
-1 untuk menggunakan .getInstance (). GregorianCalendar.getInstance()adalah setara dengan Calendar.getInstance(). Tidak Calendar.getInstance()dapat membuatnya lebih cepat, karena menggunakan yang sama new GregorianCalendar(), tetapi sebelum itu juga memeriksa lokal default dan dapat membuat kalender Jepang atau Buddish, jadi bagi beberapa pengguna yang beruntung itu akan menjadi ClassCastException!
kan
6
Dengan anggapan Anda sedang mendekode atau menyandikan xml dan menggunakan JAXB, maka dimungkinkan untuk mengganti penjilidan dateTime sepenuhnya dan menggunakan sesuatu yang lain selain `XMLGregorianCalendar 'untuk setiap tanggal dalam skema.
Dengan cara itu Anda dapat JAXBmelakukan hal-hal yang berulang sementara Anda dapat menghabiskan waktu untuk menulis kode yang luar biasa yang memberikan nilai.
Contoh untuk jodatime DateTime: (Melakukan ini dengan java.util.Date juga akan berfungsi - tetapi dengan batasan tertentu. Saya lebih suka jodatime dan disalin dari kode saya jadi saya tahu itu berfungsi ...)
Jika Anda senang hanya memetakan ke instan berdasarkan zona waktu + timestamp, dan zona waktu asli tidak benar-benar relevan, maka java.util.Datemungkin juga baik-baik saja.
Saya tidak berpikir bahwa jawaban ini tidak memberikan sesuatu yang baru .. Mungkin Anda dapat mengedit jawaban sebelumnya alih-alih memposting yang lain hampir sama.
musim dingin
1
Bagaimana cara melakukan dateFormat untuk XMLGregorianCalendar?
ZonedDateTime
kelas, dan metode konversi baru ditambahkan ke kelas lawas. Detail dalam Jawaban ini oleh Ole VVJawaban:
Saya ingin mengambil langkah mundur dan melihat modern pada pertanyaan berumur 10 tahun ini. Kelas-kelas yang disebutkan,
Date
danXMLGregorianCalendar
, sudah tua sekarang. Saya menantang penggunaan mereka dan menawarkan alternatif.Date
selalu dirancang dengan buruk dan berusia lebih dari 20 tahun. Ini sederhana: jangan gunakan itu.XMLGregorianCalendar
sudah tua juga dan memiliki desain kuno. Seperti yang saya pahami, ini digunakan untuk menghasilkan tanggal dan waktu dalam format XML untuk dokumen XML. Suka2009-05-07T19:05:45.678+02:00
atau2009-05-07T17:05:45.678Z
. Format ini cukup sesuai dengan ISO 8601 sehingga kelas java.time, API tanggal dan waktu Jawa modern, dapat memproduksinya, yang kami inginkan.Tidak perlu konversi
Untuk banyak tujuan (sebagian besar?) Pengganti modern untuk
Date
akan menjadiInstant
. AnInstant
adalah titik waktu (sama seperti apa adanyaDate
).Contoh output dari cuplikan ini:
Itu sama dengan yang terakhir dari contoh
XMLGregorianCalendar
string saya di atas. Seperti sebagian besar dari Anda tahu, itu berasal dariInstant.toString
dipanggil secara implisitSystem.out.println
. Dengan java.time, dalam banyak kasus kita tidak perlu konversi yang di hari tua kita dibuat antaraDate
,Calendar
,XMLGregorianCalendar
dan kelas-kelas lain (dalam beberapa kasus kita lakukan konversi kebutuhan, meskipun, saya menunjukkan kepada Anda beberapa di bagian berikutnya) .Mengontrol offset
Baik a
Date
maupun in tidakInstant
memiliki zona waktu atau offset UTC. Jawaban yang diterima sebelumnya dan masih dinilai tertinggi oleh Ben Noland menggunakan zona waktu default JVM saat ini untuk memilih offset dariXMLGregorianCalendar
. Untuk memasukkan offset dalam objek modern, kami menggunakanOffsetDateTime
. Sebagai contoh:Sekali lagi ini sesuai dengan format XML. Jika Anda ingin menggunakan pengaturan zona waktu JVM saat ini lagi, atur
zone
keZoneId.systemDefault()
.Bagaimana jika saya benar-benar membutuhkan XMLGregorianCalendar?
Ada banyak cara untuk mengkonversi
Instant
keXMLGregorianCalendar
. Saya akan menyajikan pasangan, masing-masing dengan pro dan kontra. Pertama, seperti halnyaXMLGregorianCalendar
menghasilkan string2009-05-07T17:05:45.678Z
, itu juga dapat dibangun dari string seperti itu:Pro: pendek dan saya pikir itu tidak memberikan kejutan. Con: Bagi saya rasanya seperti memformat instan menjadi string dan mem-parsingnya kembali.
Pro: Ini adalah konversi resmi. Mengontrol offset datang secara alami. Con: Ini melewati lebih banyak langkah dan karena itu lebih lama.
Bagaimana jika kita mendapat kencan?
Jika Anda mendapatkan
Date
objek kuno dari API lawas yang tidak mampu Anda ubah sekarang, konversikan keInstant
:Outputnya sama seperti sebelumnya:
Jika Anda ingin mengontrol offset, konversikan lebih jauh ke
OffsetDateTime
dalam dengan cara yang sama seperti di atas.Jika Anda memiliki model lama
Date
dan benar-benar membutuhkan model lamaXMLGregorianCalendar
, gunakan saja jawaban oleh Ben Noland.Tautan
sumber
sumber
Bagi yang mungkin berakhir di sini mencari konversi yang berlawanan (dari
XMLGregorianCalendar
keDate
):sumber
Berikut adalah metode untuk mengkonversi dari GregorianCalendar ke XMLGregorianCalendar; Saya akan meninggalkan bagian konversi dari java.util.Date ke GregorianCalendar sebagai latihan untuk Anda:
EDIT: Slooow :-)
sumber
Contoh satu baris menggunakan perpustakaan Joda-Time :
Penghargaan untuk Nicolas Mommaerts dari komentarnya dalam jawaban yang diterima .
sumber
Saya pikir saya akan menambahkan solusi saya di bawah ini, karena jawaban di atas tidak memenuhi kebutuhan saya yang sebenarnya. Skema Xml saya membutuhkan elemen Tanggal dan Waktu yang terpisah, bukan bidang DateTime yang baru. Konstruktor XMLGregorianCalendar standar yang digunakan di atas akan menghasilkan bidang DateTime
Perhatikan ada beberapa gothca, seperti harus menambahkan satu ke bulan (karena java menghitung bulan dari 0).
sumber
Saya harap penyandian saya di sini benar; D Untuk membuatnya lebih cepat cukup gunakan panggilan getInstance () jelek dari GregorianCalendar alih-alih panggilan konstruktor:
sumber
GregorianCalendar.getInstance()
adalah setara denganCalendar.getInstance()
. TidakCalendar.getInstance()
dapat membuatnya lebih cepat, karena menggunakan yang samanew GregorianCalendar()
, tetapi sebelum itu juga memeriksa lokal default dan dapat membuat kalender Jepang atau Buddish, jadi bagi beberapa pengguna yang beruntung itu akan menjadiClassCastException
!Dengan anggapan Anda sedang mendekode atau menyandikan xml dan menggunakan
JAXB
, maka dimungkinkan untuk mengganti penjilidan dateTime sepenuhnya dan menggunakan sesuatu yang lain selain `XMLGregorianCalendar 'untuk setiap tanggal dalam skema.Dengan cara itu Anda dapat
JAXB
melakukan hal-hal yang berulang sementara Anda dapat menghabiskan waktu untuk menulis kode yang luar biasa yang memberikan nilai.Contoh untuk jodatime
DateTime
: (Melakukan ini dengan java.util.Date juga akan berfungsi - tetapi dengan batasan tertentu. Saya lebih suka jodatime dan disalin dari kode saya jadi saya tahu itu berfungsi ...)Dan konverter:
Lihat di sini: bagaimana cara mengganti XmlGregorianCalendar berdasarkan Tanggal?
Jika Anda senang hanya memetakan ke instan berdasarkan zona waktu + timestamp, dan zona waktu asli tidak benar-benar relevan, maka
java.util.Date
mungkin juga baik-baik saja.sumber
Lihat kode ini: -
Anda dapat melihat contoh lengkapnya di sini
sumber