Saya mencoba untuk mengubah String berformat ISO 8601 ke ajava.util.Date
.
Saya menemukan polanya yyyy-MM-dd'T'HH:mm:ssZ
untuk menjadi ISO8601-compliant jika digunakan dengan Lokal (bandingkan sampel).
Namun, dengan menggunakan java.text.SimpleDateFormat
, saya tidak dapat mengonversi String yang diformat dengan benar 2010-01-01T12:00:00+01:00
. Saya harus mengubahnya terlebih dahulu2010-01-01T12:00:00+0100
, tanpa titik dua.
Jadi, solusi saat ini adalah
SimpleDateFormat ISO8601DATEFORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.GERMANY);
String date = "2010-01-01T12:00:00+01:00".replaceAll("\\+0([0-9]){1}\\:00", "+0$100");
System.out.println(ISO8601DATEFORMAT.parse(date));
yang jelas tidak menyenangkan. Apakah saya kehilangan sesuatu atau ada solusi yang lebih baik?
Menjawab
Berkat komentar JuanZe, saya menemukan sihir Joda-Time , juga dijelaskan di sini .
Jadi solusinya adalah
DateTimeFormatter parser2 = ISODateTimeFormat.dateTimeNoMillis();
String jtdate = "2010-01-01T12:00:00+01:00";
System.out.println(parser2.parseDateTime(jtdate));
Atau lebih sederhana, gunakan parser default melalui konstruktor:
DateTime dt = new DateTime( "2010-01-01T12:00:00+01:00" ) ;
Bagi saya, ini bagus.
Jawaban:
Sayangnya, format zona waktu yang tersedia untuk SimpleDateFormat (Java 6 dan yang lebih lama) tidak sesuai dengan ISO 8601 . SimpleDateFormat memahami string zona waktu seperti "GMT + 01: 00" atau "+0100", yang terakhir menurut RFC # 822 .
Bahkan jika Java 7 menambahkan dukungan untuk deskriptor zona waktu sesuai dengan ISO 8601, SimpleDateFormat masih tidak dapat menguraikan string tanggal yang lengkap, karena tidak memiliki dukungan untuk bagian opsional.
Memformat ulang string input Anda menggunakan regexp tentu merupakan satu kemungkinan, tetapi aturan penggantian tidak sesederhana dalam pertanyaan Anda:
Solusi yang lebih mudah adalah dengan menggunakan konverter tipe data di JAXB, karena JAXB harus dapat mengurai string tanggal ISO8601 sesuai dengan spesifikasi XML Schema.
javax.xml.bind.DatatypeConverter.parseDateTime("2010-01-01T12:00:00Z")
akan memberi AndaCalendar
objek dan Anda bisa menggunakan getTime () di atasnya, jika Anda memerlukanDate
objek.Anda mungkin bisa menggunakan Joda-Time juga, tapi saya tidak tahu mengapa Anda harus repot-repot dengan itu.
sumber
Cara yang diberkati oleh dokumentasi Java 7 :
Anda dapat menemukan lebih banyak contoh di bagian Contoh di javadoc SimpleDateFormat .
UPD 02/13/2020: Ada cara yang sama sekali baru untuk melakukan ini di Java 8
sumber
java.time
kerangka kerja baru di Java 8, terinspirasi oleh Joda-Time , menggantikan kelas java.util.Date, .Calendar, dan SimpleDateFormat yang merepotkan.string1
danstring2
tetapi tidak tahu mana yang akan Anda dapatkan.Oke, pertanyaan ini sudah dijawab, tetapi saya tetap akan memberikan jawaban. Mungkin membantu seseorang.
Saya sudah mencari solusi untuk Android (API 7).
javax.xml
tidak akan berfungsi di Android API 7.Akhirnya menerapkan kelas sederhana ini. Ini hanya mencakup bentuk paling umum dari string ISO 8601, tetapi ini harus cukup dalam beberapa kasus (ketika Anda cukup yakin bahwa input akan berada dalam format ini ).
Catatan kinerja: Saya instantiate SimpleDateFormat baru setiap saat sebagai cara untuk menghindari bug di Android 2.1. Jika Anda sama takjubnya dengan saya, lihatlah teka-teki ini . Untuk mesin Java lainnya, Anda dapat menyimpan instance di bidang statis pribadi (menggunakan ThreadLocal, agar aman thread).
sumber
s = s.substring(0, 22) + s.substring(23);
- saya tidak mengerti maksudnyawaktu java
The java.time API (dibangun ke Jawa 8 dan kemudian), membuat ini sedikit lebih mudah.
Jika Anda tahu input dalam UTC , seperti
Z
(untuk Zulu) di akhir,Instant
kelas dapat diuraikan.Jika input Anda mungkin merupakan nilai offset-dari-UTC lain daripada UTC yang ditunjukkan oleh
Z
(Zulu) di bagian akhir, gunakanOffsetDateTime
kelas untuk menguraikan.Kemudian ekstrak
Instant
, dan konversikan kejava.util.Date
dengan meneleponfrom
.sumber
LocalDateTime
danZoneId
danatZone
. Satu kalimat sederhana ini akan membantu:java.util.Date date = Date.from( ZonedDateTime.parse( "2014-12-12T10:39:40Z" ).toInstant() );
Date.from(Instant.parse("2014-12-12T10:39:40Z" ));
sudah cukup.OffsetDateTime
akan cukup untuk mem-parsing ISO8601 (yang tidak mengandung informasi zona waktu tetapi hanya offset).Instant
melakukan parsing. Meskipun tidak cukup untuk Pertanyaan khusus ini, ini adalah perbedaan penting yang perlu ditunjukkan. Jadi saya menambahkan contoh kode kedua. Ups, perhatikan saja ini bukan jawaban saya semula; Saya harap Adam menyetujuinya.The perpustakaan Jackson-databind juga memiliki kelas ISO8601DateFormat yang melakukan itu (yang sebenarnya implementasi di ISO8601Utils .
sumber
2015-08-11T13:10:00
. Saya mengertiString index out of range: 19
. Melihat kode itu tampaknya membutuhkan milidetik untuk ditentukan, dan zona waktu. Itu harus opsional.[yyyy-MM-dd|yyyyMMdd][T(hh:mm[:ss[.sss]]|hhmm[ss[.sss]])]?[Z|[+-]hh:mm]]
. Dengan kata lain, milidetik bersifat opsional tetapi zona waktu wajib.new DateTime("2015-08-11T13:10:00").toDate()
tl; dr
Menggunakan java.time
Paket java.time baru di Java 8 dan yang lebih baru terinspirasi oleh Joda-Time.
The
OffsetDateTime
kelas merupakan saat di timeline dengan offset-dari-UTC zona waktu tapi tidak.Memanggil
toString
menghasilkan string dalam format standar ISO 8601:Untuk melihat nilai yang sama melalui lensa UTC, ekstrak a
Instant
atau sesuaikan offset dari+01:00
ke00:00
.…atau…
Sesuaikan menjadi zona waktu jika diinginkan. Sebuah zona waktu adalah sejarah offset-dari-UTC nilai untuk suatu daerah, dengan seperangkat aturan untuk penanganan anomali seperti Daylight Saving Time (DST). Jadi, terapkan zona waktu alih-alih hanya offset jika memungkinkan.
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 kelas java.time .
Untuk mempelajari lebih lanjut, lihat Tutorial Oracle . Dan cari Stack Overflow untuk banyak contoh dan penjelasan. Spesifikasi adalah JSR 310 .
Anda dapat bertukar objek java.time secara langsung dengan database Anda. Gunakan driver JDBC yang sesuai dengan JDBC 4.2 atau yang lebih baru. Tidak perlu untuk string, tidak perlu untuk
java.sql.*
kelas.Di mana mendapatkan kelas java.time?
Proyek ThreeTen-Extra memperpanjang java.time dengan kelas tambahan. Proyek ini adalah ajang pembuktian untuk kemungkinan penambahan masa depan ke java.time. Anda mungkin menemukan beberapa kelas berguna di sini seperti
Interval
,YearWeek
,YearQuarter
, dan lebih .sumber
Untuk Java versi 7
Anda dapat mengikuti dokumentasi Oracle: http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
X - digunakan untuk zona waktu ISO 8601
sumber
Solusi DatatypeConverter tidak berfungsi di semua VM. Berikut ini berfungsi untuk saya:
Saya telah menemukan bahwa joda tidak berfungsi di luar kotak (khusus untuk contoh yang saya berikan di atas dengan zona waktu pada tanggal, yang seharusnya valid)
sumber
Saya pikir kita harus menggunakan
untuk Date
2010-01-01T12:00:00Z
sumber
Mulai dari Java 8, ada cara baru yang didukung secara resmi untuk melakukan ini:
sumber
Z
sebagai offset, kita tidak perlu menentukan ini secara eksplisit. AdilInstant i = Instant.parse(s);
. String dalam pertanyaan itu+01:00
, dalam halDateTimeFormatter.ISO_INSTANT
ini tidak berfungsi (setidaknya tidak pada Java 11 saya).ISO_OFFSET_DATE_TIME
untuk memformat tanggal dengan offset, seperti+01:00
( docs.oracle.com/javase/8/docs/api/java/time/format/… )Cara lain yang sangat sederhana untuk mengurai cap waktu ISO8601 adalah dengan menggunakan
org.apache.commons.lang.time.DateUtils
:sumber
waktu java
Perhatikan bahwa di Java 8, Anda bisa menggunakan kelas java.time.ZonedDateTime dan
parse(CharSequence text)
metode statisnya .sumber
Instant
danZonedDateTime
pantas di sini, tidakZonedDateTime
.Solusi untuk Java 7+ menggunakan SimpleDateFormat:
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX", Locale.US);
Kode ini dapat mem-parsing format ISO8601 seperti:
2017-05-17T06:01:43.785Z
2017-05-13T02:58:21.391+01:00
Tetapi pada Java6,
SimpleDateFormat
tidak mengertiX
karakter dan akan melempar.IllegalArgumentException: Unknown pattern character 'X'
Kita perlu menormalkan tanggal ISO8601 ke format yang dapat dibaca di Java 6 dengan
SimpleDateFormat
.Metode di atas untuk mengganti [
Z
dengan+0000
] atau [+01:00
dengan+0100
] ketika kesalahan terjadi pada Java 6 (Anda dapat mendeteksi versi Java dan mengganti pernyataan try / catch with if).sumber
Date
danSimpleDateFormat
tidak dirancang dengan baik, membingungkan, dan cacat. Mereka sekarang warisan, digantikan oleh kelas java.time dibangun ke dalam Java 8 dan yang lebih baru. Untuk Java 6 dan Java 7, sebagian besar fungsi java.time di-porting dalam proyek ThreeTen-Backport . Jauh lebih baik untuk menambahkan perpustakaan itu ke aplikasi Anda daripada menggunakan kelas-kelas sebelumnya. Solusi satu baris di java.time:OffsetDateTime.parse( "2010-01-01T12:00:00+01:00" )
Saya menghadapi masalah yang sama dan menyelesaikannya dengan kode berikut.
Sebelumnya saya menggunakan
SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.getDefault());
Tetapi kemudian saya menemukan penyebab utama pengecualian adalah
yyyy-MM-dd'T'HH:mm:ss.SSSZ
,Jadi saya menggunakan
SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault());
Ini bekerja dengan baik untukku .
sumber
Anda juga dapat menggunakan kelas berikut -
Tautan ke Java Doc - Hierarchy For Package org.springframework.extensions.surf.maven.plugin.util
sumber
Java memiliki selusin cara berbeda untuk mem-parse waktu-waktu, seperti yang ditunjukkan oleh jawaban-jawaban yang bagus di sini. Tetapi agak luar biasa, tidak ada kelas waktu Java sepenuhnya menerapkan ISO 8601!
Dengan Java 8, saya akan merekomendasikan:
Itu akan menangani contoh dalam UTC dan dengan offset, seperti "2017-09-13T10: 36: 40Z" atau "2017-09-13T10: 36: 40 + 01: 00". Ini akan dilakukan untuk sebagian besar kasus penggunaan.
Tapi itu tidak akan menangani contoh seperti "2017-09-13T10: 36: 40 + 01", yang merupakan tanggal waktu ISO 8601 yang valid.
Itu juga tidak akan menangani tanggal saja, misalnya "2017-09-13".
Jika Anda harus mengatasinya, saya sarankan menggunakan regex terlebih dahulu untuk mengendus sintaks.
Ada daftar contoh bagus ISO 8601 di sini dengan banyak kotak sudut: https://www.myintervals.com/blog/2009/05/20/iso-8601-date-validation-that-doesnt-suck/ Saya tidak mengetahui adanya kelas Java yang dapat mengatasi semuanya.
sumber
OffsetDateTime
akan melakukan dan secara konseptual cocok dengan tanggal-waktu dengan offset yang lebih baik.OffsetDateTime
menangani contoh yang Anda tanganiZonedDateTime
. Saya percaya bahwa itu tidak menangani salah satu contoh yangZonedDateTime
tidak. Dalam hal itu tidak ada perbaikan (tetapi juga tidak lebih buruk). Maaf, saya tidak begitu jelas.Apache Jackrabbit menggunakan format ISO 8601 untuk tanggal yang tetap, dan ada kelas pembantu untuk menguraikannya:
org.apache.jackrabbit.util.ISO8601
Dilengkapi dengan jackrabbit-jcr-commons .
sumber
Seperti yang disebutkan orang lain, Android tidak memiliki cara yang baik untuk mendukung parsing / memformat tanggal ISO 8601 menggunakan kelas yang termasuk dalam SDK. Saya telah menulis kode ini beberapa kali sehingga saya akhirnya membuat Gist yang menyertakan kelas DateUtils yang mendukung pemformatan dan penguraian tanggal ISO 8601 dan RFC 1123. Gist juga mencakup test case yang menunjukkan apa yang didukungnya.
https://gist.github.com/mraccola/702330625fad8eebe7d3
sumber
SimpleDateFormat untuk JAVA 1.7 memiliki pola keren untuk format ISO 8601.
Kelas SimpleDateFormat
Inilah yang saya lakukan:
sumber
Z
dalam format string bukan zona waktu ISO 8601, Anda harus menggunakanX
(atauXX
atauXXX
) jika Anda menginginkan zona waktu ISO 8601Lakukan seperti ini:
Berikut hasilnya:
Rabu 19 Oktober 15:15:36 CST 2016
sumber
Gunakan string seperti
LocalDate.parse(((String) data.get("d_iso8601")),DateTimeFormatter.ISO_DATE)
sumber
Saya terkejut bahwa tidak satu pun perpustakaan java mendukung semua format tanggal ISO 8601 sesuai https://en.wikipedia.org/wiki/ISO_8601 . Joda DateTime mendukung sebagian besar dari mereka, tetapi tidak semua dan karenanya saya menambahkan logika khusus untuk menangani semuanya. Ini implementasi saya.
sumber
Sebuah tes kecil yang menunjukkan cara mem-parsing tanggal di ISO8601 dan bahwa LocalDateTime tidak menangani DST.
sumber
java.util.Date
,java.util.Calendar
, danjava.text.SimpleDateFormat
sekarang warisan , digantikan oleh java.time kelas dibangun ke Jawa 8 dan kemudian. Lihat Tutorial oleh Oracle .LocalDateTime
tidak menangani waktu musim panas (DST) karena tidak menangani zona waktu sama sekali. Untuk itu kita perluZonedDateTime
. MengusulkanDate
danSimpleDateFormat
- IMHO buruk.Saya memiliki kebutuhan yang sama: Saya harus dapat menguraikan tanggal yang sesuai ISO8601 tanpa mengetahui format yang tepat di muka, dan saya ingin solusi ringan yang juga akan bekerja di Android.
Ketika saya mencari di Google kebutuhan saya, saya menemukan pertanyaan ini, dan memperhatikan bahwa AFAIU, tidak ada jawaban yang sepenuhnya sesuai dengan kebutuhan saya. Jadi saya mengembangkan jISO8601 dan mendorongnya ke pusat maven.
Cukup tambahkan Anda
pom.xml
:dan kemudian Anda baik untuk pergi:
Semoga bisa membantu.
sumber
Untuk hanya memformat tanggal seperti ini, berikut ini berfungsi untuk saya dalam aplikasi berbasis Java 6. Ada
DateFormat
kelasJacksonThymeleafISO8601DateFormat
dalam proyek thymeleaf yang menyisipkan titik dua yang hilang:https://github.com/thymeleaf/thymeleaf/blob/40d27f44df7b52eda47d1bc6f1b3012add6098b3/src/main/java/org/thymeleaf/standard/serializer/StandardJavaScriptSerializer.java
Saya menggunakannya untuk kompatibilitas format tanggal ECMAScript.
sumber
Kesopanan Fungsi Dasar: @wrygiel.
Fungsi ini dapat mengkonversi format ISO8601 ke Tanggal Java yang dapat menangani nilai offset. Sesuai definisi ISO 8601 , offset dapat disebutkan dalam format yang berbeda.
Kelas ini memiliki metode statis untuk dikonversi
Contoh String ISO8601
}
sumber
Ini sepertinya bekerja paling baik untuk saya:
Saya perlu mengonversi string tanggal ke / dari JavaScript ke Java. Saya menemukan karya-karya di atas dengan rekomendasi. Ada beberapa contoh menggunakan SimpleDateFormat yang dekat tetapi mereka tampaknya bukan himpunan bagian seperti yang direkomendasikan oleh:
http://www.w3.org/TR/NOTE-datetime
dan didukung oleh PLIST dan JavaScript Strings dan semacam itulah yang saya butuhkan.
Ini tampaknya merupakan bentuk paling umum dari string ISO8601 di luar sana, dan bagian yang baik.
Contoh yang mereka berikan adalah:
Saya juga memiliki versi cepat:
...
Saya belum membandingkannya, tapi saya kira ini akan cukup cepat. Sepertinya berhasil. :)
sumber
Saya pikir apa yang banyak orang ingin lakukan adalah mengurai string tanggal JSON. Ada kemungkinan besar jika Anda mengunjungi halaman ini bahwa Anda mungkin ingin mengonversi tanggal JSON JavaScript ke tanggal Java.
Untuk menampilkan seperti apa string tanggal JSON:
String tanggal JSON adalah 2013-12-14T01: 55: 33.412Z.
Tanggal tidak dicakup oleh spesifikasi JSON per katakan, tetapi di atas adalah format ISO 8601 yang sangat spesifik, sedangkan ISO_8601 jauh lebih besar dan itu hanyalah sebagian kecil meskipun sangat penting.
Lihat http://www.json.org Lihat http://en.wikipedia.org/wiki/ISO_8601 Lihat http://www.w3.org/TR/NOTE-datetime
Seperti yang terjadi saya menulis parser JSON dan parser PLIST yang keduanya menggunakan ISO-8601 tetapi tidak bit yang sama.
Saya menulis dua cara untuk melakukan ini untuk proyek saya. Satu standar, satu cepat.
Sekali lagi, string tanggal JSON adalah implementasi ISO 8601 yang sangat spesifik ....
(Saya memposting yang lain di jawaban lain yang harus bekerja untuk tanggal PLIST, yang merupakan format ISO 8601 yang berbeda).
Tanggal JSON adalah sebagai berikut:
File PLIST (ASCII non GNUNext) juga menggunakan ISO 8601 tetapi tidak ada milidetik jadi ... tidak semua tanggal ISO-8601 adalah sama. (Setidaknya saya belum menemukan yang menggunakan milis dan parser yang saya lihat melewati zona waktu sama sekali OMG).
Sekarang untuk versi cepat (Anda dapat menemukannya di Boon).
Perhatikan bahwa Reflection.toCharArray menggunakan tidak aman jika tersedia tetapi default ke string.toCharArray jika tidak.
(Anda bisa mengeluarkannya dengan mengganti Reflection.toCharArray (string) dengan string.toCharArray ()).
IsJsonDate diimplementasikan sebagai berikut:
Ngomong-ngomong ... tebakan saya adalah bahwa beberapa orang yang datang ke sini .. mungkin mencari JSON Date String dan meskipun ini adalah tanggal ISO-8601, itu adalah yang sangat spesifik yang membutuhkan penguraian yang sangat spesifik.
Lihat https://github.com/RichardHightower/boon Boon memiliki pengurai PLIST (ASCII) dan pengurai JSON.
Pengurai JSON adalah pengurai Java JSON tercepat yang saya tahu.
Diverifikasi secara independen oleh dudes Kinerja Gatling.
https://github.com/gatling/json-parsers-benchmark
Ini memiliki parser JSON tercepat untuk stream, pembaca, byte [], char [], CharSequence (StringBuilder, CharacterBuffer), dan String.
Lihat lebih banyak tolok ukur di:
https://github.com/RichardHightower/json-parsers-benchmark
sumber
Instant.parse( "2013-12-14T01:55:33.412Z" )