ISO 8601 biçiminden .NET DateTime nasıl oluşturulur


130

Bir DateTime'ı bir ISO 8601 formatına nasıl dönüştüreceğimi buldum , ancak C # 'da tersinin nasıl yapılacağına dair hiçbir şey yok.

Yaptım 2010-08-20T15:00:00Zve onu bir DateTimenesneye dönüştürmek istiyorum .

İpin parçalarını kendim ayırabilirim, ancak bu zaten uluslararası bir standart olan bir şey için çok çalışma gibi görünüyor.



1
@Aidin: 24 Ağu '10 12:02
abatishchev

@Aidin: ve evet, bu bir kopya. Biçimdeki tek fark. Gerisi aynı.
abatishchev

6
@abatishchev ve bu yüzden bir kopya değil. "Yinelenen" yanıt
8601'i kapsamıyor.

3
Evet bu bir kopya değil. Bu soru, ISO 8601 formatının ayrıştırılmasına özeldir.
Jose

Yanıtlar:


142

Bu çözüm, DateTimeStyles numaralandırmasını kullanır ve ayrıca Z ile de çalışır.

DateTime d2 = DateTime.Parse("2010-08-20T15:00:00Z", null, System.Globalization.DateTimeStyles.RoundtripKind);

Bu, çözümü mükemmel şekilde yazdırır.


3
Düzenlenmiş çözümü DateTime d2= DateTime.Parse("2010-08-20T15:00:00Z", null, DateTimeStyles.RoundtripKind);güzel çalışıyor gibi görünüyor.
j3ko

4
Bu DateTimeStyles.RoundtripKind? MSDN açıklamasını detaylandırmak isteyenler boştur.
Steve Parish

8
Görünüşe göre bu soru daha iyi bir cevabı yansıtmak için düzenlenmiş ama @MamtaD orijinal cevabın üzerine yazdığı için yorumlar çok yanıltıcı oluyor. Başlangıçta üstteki yorumlar nedeniyle cevabın doğru olduğundan emin değildim ama sonra yanlış cevabın doğru cevapla değiştirildiğini fark ettim
Aidin

5
Kesirli rakamlarla benim için çalışmıyor. 2018-06-19T14:56:14.123ZUTC olarak değil, yerel saat olarak ayrıştırılır. CultureInfo.InvariantCultureNull yerine kullanıyorum .
Erik Hart

1
Hakkında daha fazla bilgi için DateTimeStyles.RoundTripKind, bkz stackoverflow.com/q/39572395/2014893
Robert K. Bell

33

MSDN, "s" ve "o" biçimlerinin standardı yansıttığını söylese de, bunların yalnızca sınırlı bir alt kümesini ayrıştırabildikleri görülmektedir. Özellikle dizenin saat dilimi belirtimi içermesi bir sorundur. (Temel ISO8601 formatları ya da azaltılmış hassasiyet formatları için de geçerli değildir - ancak bu tam olarak sizin durumunuz değildir.) Bu yüzden, ISO8601 ayrıştırması söz konusu olduğunda özel format dizgelerinden yararlanıyorum. Şu anda tercih ettiğim pasaj:

static readonly string[] formats = { 
    // Basic formats
    "yyyyMMddTHHmmsszzz",
    "yyyyMMddTHHmmsszz",
    "yyyyMMddTHHmmssZ",
    // Extended formats
    "yyyy-MM-ddTHH:mm:sszzz",
    "yyyy-MM-ddTHH:mm:sszz",
    "yyyy-MM-ddTHH:mm:ssZ",
    // All of the above with reduced accuracy
    "yyyyMMddTHHmmzzz",
    "yyyyMMddTHHmmzz",
    "yyyyMMddTHHmmZ",
    "yyyy-MM-ddTHH:mmzzz",
    "yyyy-MM-ddTHH:mmzz",
    "yyyy-MM-ddTHH:mmZ",
    // Accuracy reduced to hours
    "yyyyMMddTHHzzz",
    "yyyyMMddTHHzz",
    "yyyyMMddTHHZ",
    "yyyy-MM-ddTHHzzz",
    "yyyy-MM-ddTHHzz",
    "yyyy-MM-ddTHHZ"
    };

public static DateTime ParseISO8601String ( string str )
{
    return DateTime.ParseExact ( str, formats, 
        CultureInfo.InvariantCulture, DateTimeStyles.None );
}

TZ'siz dizeleri ayrıştırmaktan çekinmiyorsanız (ben yaparım), kapsanan biçim değişikliklerinin sayısını büyük ölçüde artırmak için bir "s" satırı ekleyebilirsiniz.


3
Eklemek olacaktır "yyyyMMdd"de formatsbu bazen RFC 5545 RRULE süresi sağlamak için bir DTStart dayanacak olduğu gibi, gün düşük doğruluğu dizi.
Kyle Falconer

1
Kullanımı K, farklı saat dilimi işlemlerinizi bir araya getirmenize olanak tanır. Stackoverflow.com/a/31246449/400547 adresinde daha kapsamlı bir varyantım var, ancak çok kapsamlı bir şeyse (ISO 8601 geçerli ancak daha yaygın profillerde kullanılmayan şeyleri kabul ediyor) ancak Kboyutu nasıl küçültebileceğini gösteriyor. üçüncü.
Jon Hanna

20
using System.Globalization;

DateTime d;
DateTime.TryParseExact(
    "2010-08-20T15:00:00",
    "s",
    CultureInfo.InvariantCulture,
    DateTimeStyles.AssumeUniversal, out d);

1
LinqPad'de False ve d ~~> "1/1/0001 12:00:00 AM" üretir :(
Reb.Cabin

@Reb: "2010-08-20T15: 00: 00" ve "s", sonunda "Z" yoksa
abatishchev

düzeltildi :) Z tüm örneklerimde görünüyor (çeşitli GPS birimlerinden ve GPX dosyalarından geliyor)
Reb.Cabin

başka bir ISO 8601 referansında "Z" nin Saat Diliminde olduğu gibi Bölge anlamına geldiği bulunmuştur.
Reb.Cabin

30
Z aslında Zulu zamanını veya UTC'yi ifade eder. en.wikipedia.org/wiki/ISO_8601#UTC
Peter Stephens

19

İşte benim için daha iyi çalışan biri ( LINQPad sürümü):

DateTime d;
DateTime.TryParseExact(
    "2010-08-20T15:00:00Z",
    @"yyyy-MM-dd\THH:mm:ss\Z",
    CultureInfo.InvariantCulture,
    DateTimeStyles.AssumeUniversal, 
    out d);
d.ToString()

üretir

true
8/20/2010 8:00:00 AM

Şu anda bunu birim testlerimde tarih olmasını beklediğim tüm dizelerin Iso8601 biçiminde olduğunu doğrulamak için kullanıyorum. Teşekkürler!
anthv123

1
Bu neden UTC'de olmayan bir zaman damgası döndürüyor ?! "AssumeUniversal" ile "Değişmez kültür", bunu yapmamalı çünkü DST dünya çapında çılgınca farklılık gösteriyor, bu nedenle yerel zaman diliminize geri dönmeniz, kodu çalıştırmaya başlarsanız hatalara neden olabilir. farklı ayarlara sahip bir sunucuda!
Elaskanator

7

TryParseExactÇalışması için ISO dizesinin formatıyla tam olarak eşleşmesi önemli görünüyor . Sanırım Exact is Exact ve bu cevap çoğu kişi için açık ama neyse ...

Benim durumumda, Reb.Cabin'in cevabı, aşağıdaki "değerime" göre biraz farklı bir girdiye sahip olduğum için çalışmıyor.

Değeri: 2012-08-10T14:00:00.000Z

Orada milisaniyeler için fazladan 000 var ve daha fazlası da olabilir.

Ancak .fff, aşağıdaki biçime bazılarını eklersem, her şey yolunda.

Biçim Dizesi: @"yyyy-MM-dd\THH:mm:ss.fff\Z"

VS2010 Hemen Penceresinde:

DateTime.TryParseExact(value,@"yyyy-MM-dd\THH:mm:ss.fff\Z", CultureInfo.InvariantCulture,DateTimeStyles.AssumeUniversal, out d);

doğru

DateTimeStyles.AssumeLocalSaatinizin hangi bölge için olduğuna bağlı olarak da kullanmanız gerekebilir ...


1
Bu benim için çalıştı, ama aynı zamanda değiştirmem AssumeUniversalgerekiyordu AdjustToUniversal.
Augusto Barreto

4

Bu, LINQPad4'te iyi çalışıyor:

Console.WriteLine(DateTime.Parse("2010-08-20T15:00:00Z"));
Console.WriteLine(DateTime.Parse("2010-08-20T15:00:00"));
Console.WriteLine(DateTime.Parse("2010-08-20 15:00:00"));

-1

DateTime.ParseExact(...) ayrıştırıcıya her karakterin neyi temsil ettiğini söylemenizi sağlar.

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.