ISO 8601形式から.NET DateTimeを作成する方法


130

DateTimeをISO 8601形式に変換する方法はわかりましたが、C#でその逆を行う方法はありません。

私は持っていて2010-08-20T15:00:00Z、それをDateTimeオブジェクトにしたいのです。

文字列の部分を自分で分離することもできましたが、それはすでに国際標準となっているものに対しては多くの作業のように思えます。



1
@アイディン:2010 年8月24日 12:02
abatishchev 2015年

@Aidin:そして、はい、これは複製です。フォーマットの唯一の違い。残りは同じです。
abatishchev 2015年

6
@abatishchev、それが複製ではない理由です。8601に対応していない「複製」の答え
spiralisの

3
はい、これは重複ではありません。この質問は、ISO 8601形式の解析に固有です。
ホセ

回答:


142

このソリューションは、DateTimeStyles列挙を利用し、Zでも機能します。

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

これにより、ソリューションが完全に印刷されます。


3
の編集済みソリューションはDateTime d2= DateTime.Parse("2010-08-20T15:00:00Z", null, DateTimeStyles.RoundtripKind);うまく機能しているようです。
j3ko

4
このDateTimeStyles.RoundtripKind? MSDNの説明について詳しく説明したい人は誰もいません。
スティーブパリッシュ

8
この質問はより良い回答を反映するように編集されたようですが、@ MamtaDが元の回答を上書きしたため、コメントは非常に誤解を招くようになっています。最初はコメントが上にあるため、答えが正しいかどうかわかりませんでしたが、間違った答えは
後で

5
小数桁では機能しません。2018-06-19T14:56:14.123ZUTCではなく現地時間として解析されます。CultureInfo.InvariantCulturenullの代わりに使用します。
Erik Hart

1
の詳細についてはDateTimeStyles.RoundTripKindstackoverflow.com / q / 39572395/2014893
Robert K. Bell

33

MSDNでは、「s」および「o」のフォーマットは標準を反映していると述べていますが、それらはその限られたサブセットしか解析できないようです。特に文字列にタイムゾーンの指定が含まれている場合は問題です。(基本的なISO8601形式でも精度の低い形式でもありませんが、これは厳密にはそうではありません。)そのため、ISO8601の解析に関してカスタム形式の文字列を利用します。現在のところ私が好むスニペットは:

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なしの文字列の解析を気にしない場合(私はそうします)、「s」行を追加して、対象となるフォーマット変更の数を大幅に拡張できます。


3
これは、RFC 5545 RRULEがDTSTARTを使用して時間を提供する場合があるため、精度を数日に減らすために配列を追加"yyyyMMdd"formatsます。
カイルファルコナー2014

1
を使用Kすると、さまざまなタイムゾーンの処理をまとめて行うことができます。私はstackoverflow.com/a/31246449/400547でより広範なバリアントを持っていますが、それはあまりにも広範囲である場合(有効なISO 8601であるが、より一般的なプロファイルでは使用されないものを受け入れます)ですがK、第三。
ジョンハンナ

20
using System.Globalization;

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

1
LinqPadでFalseおよびd ~~> "1/1/0001 12:00:00 AM"を生成します:(
Reb.Cabin

@Reb:「2010-08-20T15:00:00」と「s」、末尾に「Z」がない場合
abatishchev

修正済み:)すべてのサンプルにZが表示されます(これはたまたま、さまざまなGPSユニットとGPXファイルから
取得され

別のISO 8601参照で、 "Z"はタイムゾーンのようにゾーンを表すことがわかりました。
Reb.Cabin

30
Zは実際にはズールー時間またはUTCを表します。en.wikipedia.org/wiki/ISO_8601#UTC
Peter Stephens、

19

これは私にとってよりうまくいくものです(LINQPadバージョン):

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

作り出す

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

現在、これを使用して、ユニットテストで日付であると予想されるすべての文字列がIso8601形式であることを確認しています。ありがとう!
anthv123 2015年

1
なぜこれはUTCではなくタイムスタンプを返すのですか?DSTは世界中で非常に大きく異なるため、「不変の文化」と「AssumeUniversal」の違いはそれほど大きくないため、コードの実行を開始するとバグが発生する可能性があります。異なる設定のサーバーで!
Elaskanator

7

が機能するには、ISO文字列の形式を正確に一致させることが重要と思わTryParseExactれます。ExactはExactであり、この答えはほとんどの人にとって明白ですが、とにかく...

私の場合、Reb.Cabinの回答は機能しません。これは、以下の「値」に従って入力がわずかに異なるためです。

値: 2012-08-10T14:00:00.000Z

ミリ秒の間、そこに余分な000がいくつかありますが、それ以上の場合もあります。

しかし、.fff以下に示すようにフォーマットにいくつかを追加すると、すべて問題ありません。

フォーマット文字列: @"yyyy-MM-dd\THH:mm:ss.fff\Z"

VS2010イミディエイトウィンドウ:

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

本当

あなたのDateTimeStyles.AssumeLocal時間はどのゾーンであるかに応じて使用する必要があるかもしれません...


1
これは私にとってはうまくいきましたが、私もに変更AssumeUniversalする必要がありましたAdjustToUniversal
Augusto Barreto

4

これはLINQPad4で正常に機能します。

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.