Apa format tanggal ini? 2011-08-12T20: 17: 46.384Z

384

Saya memiliki tanggal sebagai berikut: 2011-08-12T20:17:46.384Z. Format apa ini? Saya mencoba untuk menguraikannya dengan Java 1.4 via DateFormat.getDateInstance().parse(dateStr)dan saya mengerti

java.text.ParseException: Tanggal tidak dapat diparsing: "2011-08-12T20: 17: 46.384Z"

Saya pikir saya harus menggunakan SimpleDateFormat untuk parsing, tetapi saya harus tahu format string terlebih dahulu. Yang saya miliki sejauh ini adalah yyyy-MM-dd, karena saya tidak tahu apa Tarti dari string ini - sesuatu yang berhubungan dengan zona waktu? String tanggal ini berasal dari lcmis:downloadedOntag yang ditampilkan pada jenis media riwayat unduhan File CMIS .

Kapal Sarah
sumber
44
Ini ISO 8601
Tomasz Nurkiewicz
3
@TomaszNurkiewicz, bukan. ISO8601 tidak memiliki Z pada akhirnya.
t1gor
5
ISO8601 doe memungkinkan Z di akhir. Lihat tautan di atas, cari UTC.
Jonathan Rosenne
2
@ t1gor The Zpada akhirnya adalah kependekan dari Zuludan artinya UTC . Format ini tentunya merupakan bagian dari koleksi format teks waktu-standar ISO 8601 . Omong-omong, format standar ini digunakan secara default di kelas java.time .
Basil Bourque
3
FYI, merepotkan tua kelas tanggal-waktu seperti java.util.Date, java.util.Calendar, dan java.text.SimpleDateFormatsekarang warisan , digantikan oleh java.time kelas dibangun ke Jawa 8 & Java 9. Lihat Tutorial oleh Oracle .
Basil Bourque

Jawaban:

513

T hanyalah literal untuk memisahkan tanggal dari waktu, dan Z berarti "offset nol jam" yang juga dikenal sebagai "waktu Zulu" (UTC). Jika string Anda selalu memiliki "Z", Anda dapat menggunakan:

SimpleDateFormat format = new SimpleDateFormat(
    "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
format.setTimeZone(TimeZone.getTimeZone("UTC"));

Atau menggunakan Joda Time , Anda bisa menggunakan ISODateTimeFormat.dateTime().

Jon Skeet
sumber
7
Mengapa kita perlu tanda kutip tunggal sekitar Tdan Z?
Maroun
7
@MarounMaroun: Pada dasarnya kami menginginkan karakter literal itu . Mungkin tidak perlu untuk T(saya tidak ingat bagaimana SimpleDateFormat menangani specifier yang tidak diketahui) tetapi karena Zkami ingin itu menjadi karakter 'Z' daripada "nilai offset UTC" (misalnya "00").
Jon Skeet
2
@nyedidikeke: Di halaman Wikipedia yang Anda tautkan, ini menunjukkan "zona waktu Zulu" untuk UTC. Saya tidak yakin apa yang Anda yakini sedang Anda koreksi.
Jon Skeet
9
@ JonSkeet: ini dapat menghasilkan perdebatan yang tidak perlu; tidak memperdebatkan jawaban Anda tetapi dimaksudkan untuk menarik perhatian Z yang mendapatkan hurufnya dari "offset UTC nol". Huruf Z disebut sebagai "Zulu" dalam alfabet fonetik NATO . Pada gilirannya, pendekatan militer untuk merujuk pada offset nol UTC berlabuh pada huruf Z yang mereka identifikasi sebagai Zulu, yang memberinya nama kode mereka: zona waktu Zulu. Penting untuk dicatat bahwa Z belum kehilangan maknanya dan masih merupakan penentu zona untuk offset UTC nol karena zona waktu Zulu (dari Z) hanyalah bahasa kode yang diturunkan untuk merujuknya.
nyedidikeke
2
@nyedidikeke: Saya masih tidak setuju tentang apakah ada orang lain yang akan peduli tentang perbedaan dengan mengacu pada jawaban saya, tapi saya sudah memperbaruinya. Saya tidak akan membahas semua detail, karena sejarah secara luas tidak relevan dengan jawabannya.
Jon Skeet
86

tl; dr

Format standar ISO 8601 digunakan oleh string input Anda.

Instant.parse ( "2011-08-12T20:17:46.384Z" ) 

ISO 8601

Format ini ditentukan oleh standar praktis yang masuk akal, ISO 8601 .

The Tmemisahkan bagian tanggal dari porsi waktu-of-hari. Pada Zakhirnya berarti UTC (yaitu, offset-dari-UTC nol jam-menit-detik). The Zadalah diucapkan “Zulu” .

waktu java

Kelas tanggal-waktu lama yang dibundel dengan versi Jawa yang paling awal telah terbukti dirancang dengan buruk, membingungkan, dan menyusahkan. Hindari mereka.

Sebagai gantinya, gunakan kerangka kerja java.time yang ada di dalam Java 8 dan yang lebih baru. Kelas java.time menggantikan kedua kelas tanggal-waktu lama dan perpustakaan Joda-Time yang sangat sukses.

Kelas java.time menggunakan ISO 8601 secara default ketika parsing / menghasilkan representasi tekstual dari nilai-nilai tanggal-waktu.

The Instantkelas merupakan saat di timeline di UTC dengan resolusi nanodetik . Kelas itu dapat secara langsung mem-parsing string input Anda tanpa perlu repot menentukan pola pemformatan.

Instant instant = Instant.parse ( "2011-08-12T20:17:46.384Z" ) ;

Tabel tipe waktu-tanggal di Jawa, baik yang modern maupun yang lama


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 .

Di mana mendapatkan kelas java.time?

Tabel mana perpustakaan java.time untuk digunakan dengan versi Java atau Android

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 .

Basil Bourque
sumber
3
@star The "Zulu" berasal dari tradisi militer dan penerbangan di mana 25 huruf abjad AZ (no "J"), setiap huruf memiliki nama yang dapat diucapkan, mewakili versi zona waktu mereka . Zona "Zulu" adalah offset nol jam dari UTC. Lihat ini dan ini .
Basil Bourque
27

Tidak yakin tentang Java parsing, tapi itu ISO8601: http://en.wikipedia.org/wiki/ISO_8601

smparkes
sumber
Apakah ini "2016-01-27T17: 44: 55UTC", ISO8601 juga?
user1997292
Saya tidak percaya begitu. Sangat dekat tetapi UTC sebagai akhiran tidak diizinkan. Itu harus Z atau offset zona waktu, misalnya, +0100. Z dan UTC memiliki arti yang sama, jadi mengubah UTC ke Z akan menghasilkan ISO 8601. valid
smparkes
9

Ada cara lain untuk menguraikannya daripada jawaban pertama. Untuk menguraikannya:

(1) Jika Anda ingin mengambil informasi tentang tanggal dan waktu, Anda dapat menguraikannya ke objek ZonedDatetime(karena Java 8 ) atau Date(lama):

// ZonedDateTime's default format requires a zone ID(like [Australia/Sydney]) in the end.
// Here, we provide a format which can parse the string correctly.
DateTimeFormatter dtf = DateTimeFormatter.ISO_DATE_TIME;
ZonedDateTime zdt = ZonedDateTime.parse("2011-08-12T20:17:46.384Z", dtf);

atau

// 'T' is a literal.
// 'X' is ISO Zone Offset[like +01, -08]; For UTC, it is interpreted as 'Z'(Zero) literal.
String pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSX";

// since no built-in format, we provides pattern directly.
DateFormat df = new SimpleDateFormat(pattern);

Date myDate = df.parse("2011-08-12T20:17:46.384Z");

(2) Jika Anda tidak peduli tanggal dan waktu dan hanya ingin memperlakukan informasi sebagai momen dalam nanodetik, maka Anda dapat menggunakan Instant:

// The ISO format without zone ID is Instant's default.
// There is no need to pass any format.
Instant ins = Instant.parse("2011-08-12T20:17:46.384Z");
VeryLazyBoy
sumber
1

Jika Anda mencari solusi untuk Android, Anda dapat menggunakan kode berikut untuk mendapatkan detik dari jaman timestamp.

public static long timestampToEpochSeconds(String srcTimestamp) {
    long epoch = 0;

    try {
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            Instant instant = Instant.parse(srcTimestamp);
            epoch = instant.getEpochSecond();
        } else {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSSSSS'Z'", Locale.getDefault());
            sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
            Date date = sdf.parse(srcTimestamp);
            if (date != null) {
                epoch = date.getTime() / 1000;
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

    return epoch;
}

Input sampel: 2019-10-15T05: 51: 31.537979Z

Contoh output: 1571128673

Rahul Raveendran
sumber
0

Anda dapat menggunakan contoh berikut ini.

    String date = "2011-08-12T20:17:46.384Z";

    String inputPattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";

    String outputPattern = "yyyy-MM-dd HH:mm:ss";

    LocalDateTime inputDate = null;
    String outputDate = null;


    DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern(inputPattern, Locale.ENGLISH);
    DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern(outputPattern, Locale.ENGLISH);

    inputDate = LocalDateTime.parse(date, inputFormatter);
    outputDate = outputFormatter.format(inputDate);

    System.out.println("inputDate: " + inputDate);
    System.out.println("outputDate: " + outputDate);
Salih Kesepara
sumber
Anda tidak harus meletakkan tanda kutip di sekitar Z. Itu berarti mengharapkan tetapi mengabaikan surat itu. Tapi surat itu jangan diabaikan. Surat itu memberikan informasi berharga, fakta bahwa string itu ditujukan untuk UTC, offset dari nol. Format Anda membuang fakta penting ini. Lebih jauh lagi, tidak perlu repot mendefinisikan pola format ini. Formatter untuk pola ini sudah terpasang.
Basil Bourque
-1

Teknik ini menerjemahkan java.util.Date ke format UTC (atau yang lain) dan kembali lagi.

Tentukan kelas seperti ini:

import java.util.Date;

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

public class UtcUtility {

public static DateTimeFormatter UTC = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").withZoneUTC();


public static Date parse(DateTimeFormatter dateTimeFormatter, String date) {
    return dateTimeFormatter.parseDateTime(date).toDate();
}

public static String format(DateTimeFormatter dateTimeFormatter, Date date) {
    return format(dateTimeFormatter, date.getTime());
}

private static String format(DateTimeFormatter dateTimeFormatter, long timeInMillis) {
    DateTime dateTime = new DateTime(timeInMillis);
    String formattedString = dateTimeFormatter.print(dateTime);
    return formattedString;
}

}

Kemudian gunakan seperti ini:

Date date = format(UTC, "2020-04-19T00:30:07.000Z")

atau

String date = parse(UTC, new Date())

Anda juga dapat menentukan format tanggal lainnya jika diperlukan (bukan hanya UTC)

Gapmeister66
sumber
Baik java.util.Datedan proyek Joda-Time digantikan tahun yang lalu oleh kelas java.time modern yang didefinisikan dalam JSR 310. Saran di sini sudah lama usang.
Basil Bourque
java.time diperkenalkan di Java 8. Pertanyaan ini secara khusus merujuk Java 1.4 dan karena itu saya sengaja menghindari penggunaan kelas yang lebih baru. Solusi ini melayani basis kode yang lebih lama. Saya kira penulis bisa memindahkan basis kode ke Java 8 tapi itu tidak selalu mudah, efisien atau perlu.
Gapmeister66
-1

@ John-Skeet memberi saya petunjuk untuk memperbaiki masalah saya sendiri tentang ini. Sebagai programmer yang lebih muda, masalah kecil ini mudah untuk dilewatkan dan sulit didiagnosis. Jadi saya membagikannya dengan harapan ini akan membantu seseorang.

Masalah saya adalah bahwa saya ingin mengurai string berikut yang berisi cap waktu dari JSON yang tidak saya pengaruhi dan memasukkannya ke dalam variabel yang lebih berguna. Tapi saya terus mendapatkan kesalahan.

Jadi diberi yang berikut (perhatikan parameter string di dalam ofPattern ();

String str = "20190927T182730.000Z"

LocalDateTime fin;
fin = LocalDateTime.parse( str, DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss.SSSZ") );

Kesalahan:

Exception in thread "main" java.time.format.DateTimeParseException: Text 
'20190927T182730.000Z' could not be parsed at index 19

Masalah? Z di akhir Pola harus dibungkus 'Z' seperti 'T'. Ubah "yyyyMMdd'T'HHmmss.SSSZ"ke "yyyyMMdd'T'HHmmss.SSS'Z'"dan berfungsi.

Menghapus Z dari pola semuanya juga menyebabkan kesalahan.

Terus terang, saya berharap kelas Java mengantisipasi ini.

spencemw
sumber
1
Ini sudah ditanyakan dan dijawab di sini dan di sini . Dan solusi Anda salah. Meskipun Tliteral dan perlu dikutip, Zmerupakan offset (nol) dan perlu diurai seperti itu, atau Anda akan mendapatkan hasil yang salah. Saya tidak tahu apa maksud Anda bahwa hal itu belum diantisipasi, saya percaya hal itu telah terjadi.
Ole VV
1
Tidak, tidak, tidak, jangan abaikan Z. Anda membuang informasi berharga. Memproses nilai tanggal-waktu sambil mengabaikan zona waktu atau mengimbangi-dari-UTC sama seperti memproses sejumlah uang sambil mengabaikan mata uang!
Basil Bourque
1
The Thanya memisahkan bagian tanggal dari porsi waktu-of-hari, dan menambahkan tidak ada artinya. Di Zsisi lain pasti menambah makna.
Basil Bourque
Ole, terima kasih atas tautannya. Saya pasti akan membaca itu. Dan saya menerima bahwa saya pasti bisa salah ketika masih muda. Semua yang saya katakan adalah bahwa membungkus Z dalam tanda kutip tunggal seperti arang dalam pola menyelesaikan kesalahan. Kritik saya adalah bahwa siapa pun yang merancang "pola" bagian dari kelas dapat membuat kode di sekitar ada atau tidaknya 'Z' (atau zona waktu berbeda?) Dan 'T' dibungkus '' atau tidak. Karena mereka tidak unik. Format yang saya tangani berasal dari JSON dari API komersial yang diuraikan menjadi string. Tetapi saya perlu menguraikan semua itu ke dalam kalender waktu tanggal dll untuk membuatnya lebih berguna.
spencemw