Bu tarih biçimi nedir? 2011-08-12T20: 17: 46.384Z


383

Aşağıdaki randevum var: 2011-08-12T20:17:46.384Z. Bu hangi biçim? Java 1.4 ile ayrıştırmaya çalışıyorum DateFormat.getDateInstance().parse(dateStr)ve alıyorum

java.text.ParseException: Ayrıştırılama tarihi: "2011-08-12T20: 17: 46.384Z"

Ben ayrıştırma için SimpleDateFormat kullanıyor olmalı , ama önce biçim dizesini bilmek zorunda düşünüyorum. Şimdiye kadar sahip olduğum tek şey yyyy-MM-dd, çünkü Tbu dizede ne anlama geldiğini bilmiyorum - zaman dilimiyle ilgili bir şey mi? Bu tarih dizesi, Dosyalar CMIS indirme geçmişi medya türündelcmis:downloadedOn gösterilen etiketten geliyor .



3
@TomaszNurkiewicz, değil. ISO8601'in sonunda Z yok.
t1gor

4
ISO8601 doe sonunda Z'ye izin verir. Yukarıdaki bağlantıya bakın, UTC arayın.
Jonathan Rosenne

2
@ t1gor Sondaki UTCZ kısadır Zuluve UTC anlamına gelir . Bu biçim , kesinlikle ISO 8601 standart tarih-saat metin biçimleri koleksiyonunun bir parçasıdır . Bu arada, bu standart biçimler varsayılan olarak java.time sınıflarında kullanılır.
Basil Bourque

3
Bilginize, gibi zahmetli eski tarih-saat sınıfları java.util.Date, java.util.Calendarve java.text.SimpleDateFormatşimdi mirası supplanted, java.time Java 8 ve Java 9. Bkz yerleşik sınıflara Oracle tarafından Öğreticisi .
Basil Bourque

Yanıtlar:


512

T, tarihi zamandan ayırmak için bir değişmezdir ve Z, "Zulu saati" (UTC) olarak da bilinen "sıfır saat ofseti" anlamına gelir. Dizelerinizde her zaman bir "Z" varsa kullanabilirsiniz:

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

Ya da Joda Time'ı kullanarak kullanabilirsiniz ISODateTimeFormat.dateTime().


7
Neden tek tırnaklara ihtiyacımız var Tve Z?
Maroun

7
@MarounMaroun: Temel olarak bu değişmez karakterleri istiyoruz . T(SimpleDateFormat'ın bilinmeyen tanımlayıcıları nasıl işlediğini hatırlayamıyorum) için gerekli olmayabilir , ancak Zbunun bir UTC ofset değeri (örn. "00") yerine 'Z' karakteri olmasını istiyoruz.
Jon Skeet

2
@nyedidikeke: Bağlandığınız Wikipedia sayfasında, UTC için "Zulu saat dilimi" gösterilir. Neyi düzelttiğinize inandığınızdan emin değilim.
Jon Skeet

9
@JonSkeet: gereksiz bir tartışma yaratabilir; yanıtınıza itiraz etmiyor, ancak mektubunu "sıfır UTC ofsetinden" alan Z harfine dikkat çekmeyi amaçlıyordu . Z harfine NATO fonetik alfabesinde "Zulu" denir . Sırayla, sıfır UTC ofsetine atıfta bulunmak için askeri yaklaşım, Zulu olarak tanımladıkları Z harfine bağlanır ve kodlanmış isimlerini kazanır: Zulu zaman dilimi. Z'nin anlamını kaybetmediğini ve Zulu saat diliminin (Z'den) basitçe miras alınan kodlanmış bir dil olduğu için sıfır UTC ofseti için bölge belirleyicisi olduğunu belirtmek önemlidir.
nyedidikeke

2
@nyedidikeke: Cevabımla başka kimsenin ayrımı umursamayacağına hala katılmıyorum, ama güncelledim. Bununla birlikte, tüm ayrıntıya girmeyeceğim, çünkü tarih cevapla büyük ölçüde alakasız.
Jon Skeet

86

tl; Dr.

Giriş dizeniz tarafından standart ISO 8601 biçimi kullanılır.

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

ISO 8601

Bu biçim, makul pratik standart ISO 8601 tarafından tanımlanır .

TZaman-of-day kısmından tarih kısmını ayırır. ZUcunda anlamına UTC (olduğundan, bir ofset-UTC sıfır saat-dakika-saniye). ZOlan “Zulu” telaffuz .

java.time

Java'nın en eski sürümleriyle birlikte gelen eski tarih-saat sınıflarının kötü tasarlanmış, kafa karıştırıcı ve zahmetli olduğu kanıtlanmıştır. Onlardan kaçının.

Bunun yerine, Java 8 ve sonraki sürümlerinde yerleşik olarak bulunan java.time çerçevesini kullanın . Java.time sınıfları hem eski tarih-saat sınıflarını hem de son derece başarılı Joda-Time kitaplığını destekler.

Java.time sınıfları , tarih-saat değerlerinin metinsel gösterimlerini ayrıştırırken / oluştururken varsayılan olarak ISO 8601 kullanır .

InstantSınıf içinde zaman çizelgesi üzerinde bir anını temsil UTC çözünürlüğe sahip nanosaniye . Bu sınıf, bir biçimlendirme deseni tanımlamak için rahatsız etmeden doğrudan giriş dizenizi ayrıştırabilir.

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

Java'da hem modern hem de eski tarih-saat türleri tablosu


Hakkında java.time

Java.time çerçevesi daha sonra Java 8 ve yerleşiktir. Bu sınıflar zahmetli eski yerini mirası gibi tarih-saat sınıfları java.util.Date, Calendar& SimpleDateFormat.

Artık bakım modunda olan Joda-Time projesi java.time sınıflarına geçişi tavsiye ediyor .

Daha fazla bilgi için Oracle Eğiticisine bakın . Ve birçok örnek ve açıklama için Stack Overflow'da arama yapın. Spesifikasyon JSR 310'dur .

Java.time sınıflarını nereden edinebilirsiniz?

Hangi Java veya Android sürümüyle kullanılacak java.time kütüphanesinin tablosu

ThreeTen-Ekstra proje ek sınıfları ile java.time uzanır. Bu proje, java.time'a gelecekteki olası eklemeler için bir kanıt zeminidir. Burada bazı yararlı sınıfları gibi bulabilir Interval, YearWeek, YearQuarter, ve daha .


3
@star “Zulu”, her biri belirgin bir isme sahip olan AZ alfabesinin 25 harfinin ("J" yok) saat dilimlerinin sürümlerini temsil ettiği askeri ve havacılık geleneğinden geliyor . "Zulu" bölgesi UTC'den sıfır saat uzaklığıdır. Bkz bu ve bu .
Basil Bourque

27

Java ayrıştırma konusunda emin değilim, ama bu ISO8601: http://en.wikipedia.org/wiki/ISO_8601


Bu "2016-01-27T17: 44: 55UTC", ISO8601 de mi?
user1997292

Ben inanmıyorum. Yakın, ancak son ek olarak UTC'ye izin verilmiyor. Z veya bir saat dilimi uzaklığı olmalıdır, örn. +0100. Z ve UTC böylece değişen olsa da, aynı anlama sahiptir UTC için Z geçerli ISO 8601. doğuracak
smparkes

9

İlk cevaptan ziyade ayrıştırmanın başka yolları da var. Ayrıştırmak için:

(1) Tarih ve saat hakkında bilgi almak istiyorsanız, onu ZonedDatetime( Java 8'den beri ) veya Date(eski) bir nesneye ayrıştırabilirsiniz :

// 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);

veya

// '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) Tarih ve saati umursamıyorsanız ve bilgileri nanosaniye olarak bir an olarak değerlendirmek istiyorsanız, şunları kullanabilirsiniz 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");

1

Android için bir çözüm arıyorsanız, zaman damgası dizesinden saniye saniye almak için aşağıdaki kodu kullanabilirsiniz.

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;
}

Örnek giriş: 2019-10-15T05: 51: 31.537979Z

Örnek çıktı: 1571128673


0

Aşağıdaki örneği kullanabilirsiniz.

    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);

Etrafına kesme işaretleri koymamalısınız Z. Bu mektubu beklemek ama görmezden gelmek demektir. Ancak bu mektup göz ardı edilmemelidir. Bu harf değerli bir bilgi sağlar, dizenin sıfır ofseti UTC için tasarlanmış olması. Biçiminiz bu önemli gerçeği atmaktadır. Ayrıca, bu biçimlendirme desenini tanımlamaya bile gerek yoktur. Bu model için bir formatlayıcı yerleşiktir.
Basil Bourque

-1

Bu teknik java.util.Date dosyasını UTC biçimine (veya başka bir biçime) çevirir ve tekrar geri getirir.

Şunun gibi bir sınıf tanımlayın:

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;
}

}

Sonra şu şekilde kullanın:

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

veya

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

İsterseniz diğer tarih biçimlerini de tanımlayabilirsiniz (yalnızca UTC değil)


Hem java.util.Dateve Joda-Time projesi, modern tarafından yıllar önce supplanted edildi java.time JSR 310 Burada uzun modası geçmiş danışma tanımlanan sınıflar.
Basil Bourque

java.time Java 8'de tanıtıldı. Bu soru özellikle Java 1.4'e başvuruyor ve bu nedenle yeni sınıfların kullanımından kasten kaçındım. Bu çözüm daha eski kod tabanlarına yöneliktir. Yazarın kod tabanını Java 8'e taşıyabileceğini düşünüyorum, ancak bu her zaman basit, verimli veya gerekli değildir.
Gapmeister66

-1

@ John-Skeet bu konuyla ilgili kendi sorunumu çözmem için ipucu verdi. Daha genç bir programcı olarak bu küçük konunun kaçırılması ve teşhis edilmesi zordur. Bu yüzden birisine yardım edeceği umuduyla paylaşıyorum.

Benim sorunum ben bir JSON bir zaman damgası karşısında aşağıdaki dizeyi ayrıştırmak istedim üzerinde hiçbir etkisi var ve daha yararlı değişkenler koymak oldu. Ama hata almaya devam ettim.

Bu nedenle aşağıdakiler göz önüne alındığında (Pasat () içindeki string parametresine dikkat edin;

String str = "20190927T182730.000Z"

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

Hata:

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

Sorun? Desenin sonundaki Z'nin, tıpkı 'T' gibi 'Z' ile sarılması gerekir. Değişim "yyyyMMdd'T'HHmmss.SSSZ"için "yyyyMMdd'T'HHmmss.SSS'Z'"ve çalışıyor.

Z'nin kalıptan tamamen çıkarılması da hatalara yol açtı.

Açıkçası, bir Java sınıfının bunu beklemesini beklerdim.


1
Bu, burada ve burada zaten sorulmuş ve cevaplanmıştır . Ve çözümün yanlış. Süre Tbir değişmezdir ve alıntılanması gerekir Z, bir ofsettir (sıfır) ve bu şekilde ayrıştırılması gerekir, aksi takdirde yanlış sonuçlar alırsınız. Beklenmediğini kastettiğinizi bilmiyorum, inanıyorum.
Ole VV

1
Hayır, hayır, hayır, görmezden gelme Z. Değerli bilgileri atıyorsunuz. Saat dilimini veya UTC'den sapmayı yok sayarken bir tarih-saat değerinin işlenmesi, para birimini yok sayarken bir miktar parayı işlemeye benzer!
Basil Bourque

1
TSadece zaman günün-kısmından tarih kısmını ayırır ve hiçbir anlamı katar. ZÖte yandan kesinlikle anlam katan.
Basil Bourque

Ole, linkler için teţekkürler. Kesinlikle bunları okuyacağım. Ve kesinlikle bir genç olarak yanlış olabileceğimi kabul ediyorum. Söylediğim tek şey, Z'yi kalıptaki bir karakter gibi tek tırnak içine almak hatayı çözdü. Benim eleştirim, sınıfın "desen" bölümünü tasarlayan her kim 'Z' (ya da farklı bir zaman dilimi?) Ve 'T' nin '' içine girip girmediği ya da yokluğu etrafında kodlanmış olabileceğidir. Çünkü benzersiz değildi. Karşılaştığım biçim JSON'dan bir dizeye ayrıştırılmış ticari bir API'den geliyor. Ama bunları daha kullanışlı hale getirmek için bunları tarih saat takvimine vb.
spencemw
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.