web-dev-qa-db-ja.com

DateTimeStyles.RoundtripKind列挙はどういう意味ですか?

回答者の投稿を読んでいました here この列挙値に遭遇しましたDateTimeStyles.RoundtripKind理解しようとしています。私はMSDNを調べました ここ これは言う:

日付のDateTimeKindフィールドは、DateTimeオブジェクトが「o」または「r」の標準フォーマット指定子を使用して文字列に変換され、その後、文字列がDateTimeオブジェクトに変換されるときに保持されます。

私が参照した投稿の入力のタイムスタンプは次のとおりです:

<timestamp time='2016-09-16T13:45:30'>

私は彼女のコードを実行しましたが、それでも動作します。今、私が持っているすべての情報を接続することはすべて混乱です:

  1. 上記のタイムスタンプには、いくつかの識別子Tが含まれています
  2. MSDNのドキュメントでは、oおよびr形式指定子について説明していますが、これらは何であるかを示していません。
  3. Digに入ると、上記で引用したMSDNリンクのDateTimeKind列挙の詳細については、oおよびr形式指定子については何も述べられていません。 ここ は次のリンクです。

    Member Name   |      Description
    --------------------------------------------------------------------------------
    
    Local         |      The time represented is local time.
    
    Unspecified   |      The time represented is not specified as either local time or Coordinated Universal Time (UTC).
    
    Utc           |      The time represented is UTC.
    

P.S。上記のテーブルを作成しようとしましたが、SOはテーブル構造の作成をネイティブでサポートしていません。

誰かが私を理解するのを手伝ってもらえますかDateTimeStyles.RoundtripKind列挙とそれがどのように機能するか?

15
RBT

だから私はようやくこれを理解し、同じ情報を他の人にも役立つ場合はここで共有することができました:

最初の部分は、C#のDateTimeオブジェクトの文字列への変換です。これを行うには多くのフォーマット指定子がありますが、私たちにとっては、「r」および「o」フォーマット指定子がDateTimeStyles.RoundtripKindに関して懸念されています。すべての日時フォーマット指定子 here を確認できます。これらのフォーマット指定子を使用してコードで変換を行うとどうなるかを確認します。

//r corresponds to RFC 1123 format (GMT date time format)
var gmtDateTimeString = DateTime.Now.ToString("r"); //gives Fri, 23 Sep 2016 15:39:21 GMT 

//o corresponds to ISO 8601 (Local date time format)
var localDateTimeString = DateTime.Now.ToString("o"); //gives 2016-09-23T15:39:21.8899216+05:30

出力されている文字列の日付時刻には、以下の情報が埋め込まれていることがわかります。

  • Fri, 23 Sep 2016 15:39:21 GMTDateTimeKind.Utcのものです( "GMT"テキストが存在します)
  • 2016-09-23T15:39:21.8899216+05:30DateTimeKind.Localの日付時刻を表します(ISO 8601規格に従って「T」文字が存在します)

次は第2部です。これらの日時文字列gmtDateTimeStringおよびlocalDateTimeStringを日時オブジェクトに変換し直す必要がある場合は、それらを解析する必要があります。したがって、DateTimeStyles.RoundtripKind列挙値を使用してDateTime.Parse AP​​Iに渡すと、タイムゾーン情報が文字列に既に組み込まれており、APIがその情報を使用して日付時刻を適切に解析することを実際に示します。

通常、日時データがXML形式でネットワーク経由で転送される場合、このスレッドに質問を投稿する前に参照した投稿で見たISO 8601形式が使用されます。そのため、XMLドキュメントから取得したこのような日時文字列を解析する際、DateTimeStyles.RoundtripKindを使用して、文字列に存在するタイムゾーン情報に従って正しい日時値を取得することが適切でした。

12
RBT

他の答えを理解するのに苦労したので、自分で研究を行うことにしました。幸い、.NETライブラリのソースコードはオンラインで入手できます。

DateTimeStyles.RoundTripKindにはソースにコメントがあります

// Attempt to preserve whether the input is unspecified, local or UTC

DateTimeStyles.RoundTripKind に関するMSDNドキュメントとほぼ同じくらいあいまいです。

日付のDateTimeKindフィールドは、DateTimeオブジェクトが「o」または「r」の標準フォーマット指定子を使用して文字列に変換され、その後、文字列がDateTimeオブジェクトに変換されるときに保持されます。

Reference Source Webサイトをナビゲートすると、DateTimeStyles.RoundTripKindはほとんど使用されていないことがわかります。基本的に、フラグが設定されている場合は DateTimeの種類がDateTimeKind.Utcに変更される場合があります 。したがって、これはこのフラグを設定した効果です。解析されたKind値のDateTimeプロパティがUtcに設定される場合があります。

これが発生するタイミングは、内部フラグ ParseFlags.TimeZoneUtc によって制御されます。このフラグがいつ設定されるかを判断するのはより複雑ですが、タイムゾーンがZまたはGMTのいずれかを使用して指定されている場合、パーサーがこのフラグを設定することを私が確認できる限りでは。 ソースコードにこれに関するコメント

// NOTENOTE : for now, we only support "GMT" and "Z" (for Zulu time).

私の結論は、タイムスタンプがoまたはrのいずれかを使用してフォーマットされ、タイムスタンプの解析中にDateTimeStyles.RoundTripKindが使用される場合、文字列のタイムゾーンがUTCタイムゾーンの場合、結果のKind値のDateTimeUtcに設定されるということです。

ただし、フラグが設定されていない場合はどうなりますか?これを決定する最良の方法は、2つのフォーマット指定子の実際のテストを行うことです。

往復( "O"、 "o")形式指定子

o形式指定子を使用する場合、タイムスタンプのタイムゾーンは、UTCの場合はZか、UTCからのオフセット+/-になります(例:2017-02-26T22:55:15.4923368+01:00)。往復のタイムスタンプから解析されたKind値のDateTimeプロパティの値を示す表は次のとおりです。

タイムゾーン| RoundTripKind |種類
 --------- + --------------- + ------ 
 "Z" |指定されていません|ローカル
 "Z" |指定| Utc 
「Z」ではない|指定されていません|ローカル
「Z」ではない|指定|地元

往復形式でタイムスタンプを解析する場合、タイムスタンプのタイムゾーンがUTCであると予想される場合は、DateTimeStyles.RoundTripKindを指定して、解析されたDateTimeの値がUtc

RFC1123( "R"、 "r")形式指定子

r形式指定子を使用する場合、タイムスタンプには常にGMTが含まれます(元のDateTimeの種類がUtcでない場合でも)。したがって、r形式のテーブルにはTimezone列は必要ありません。ただし、RFC1123タイムスタンプを解析すると、DateTime.ParseDateTime.ParseExactの動作が異なることを発見しました。

方法| RoundTripKind |種類
 ----------- + --------------- + ------------ 
解析|指定されていません|ローカル
解析|指定| Utc 
 ParseExact |指定されていません|未指定
 ParseExact |指定|未指定

Parseメソッドを使用する場合、RFC1123形式のタイムスタンプは、往復形式のUTCタイムスタンプと同じように動作します。ただし、何らかの理由で、ParseExactメソッドはDateTimeStyles.RoundTripKindフラグを無視します。これは、ラウンドトリップ形式のタイムスタンプが解析される場合には当てはまりません。

RFC1123形式でタイムスタンプを解析する場合は、Parseメソッドを使用してDateTimeStyles.RoundTripKindを指定するか、ParseExactメソッドを使用する場合は解析する種類を変更する必要がありますUtcへのタイムスタンプ。そのためには、DateTime.SpecifyKindメソッドを使用して新しいタイムスタンプを作成します。

結論

ラウンドトリップとRFC1123タイムスタンプを解析するときは、DateTimeStyles.RoundTripKindを指定して、解析されたKind値のDateTimeプロパティがUtcであることを確認します。

往復のタイムスタンプにゼロ以外のオフセットがある場合、オフセットを保持するためにタイムスタンプをDateTimeOffset値に解析する必要があります(Localはオフセットが何であるかを通知しません-おそらくそれが0と異なるだけです)。

RFC1123タイムスタンプを解析するためにDateTime.ParseExactを使用しないでください(または、タイムスタンプが解析された後に種類をUtcに変更します)。

6

往復フォーマットは「マシンの消費」を目的としています。簡単に解析して同じDateTime値に戻すことができます。
他のほとんどの形式は、「人間の消費」のためのもので、日付(おそらく時間を含む)を人に示します。

3
Hans Kesting