回答者の投稿を読んでいました here この列挙値に遭遇しましたDateTimeStyles.RoundtripKind
理解しようとしています。私はMSDNを調べました ここ これは言う:
日付のDateTimeKindフィールドは、DateTimeオブジェクトが「o」または「r」の標準フォーマット指定子を使用して文字列に変換され、その後、文字列がDateTimeオブジェクトに変換されるときに保持されます。
私が参照した投稿の入力のタイムスタンプは次のとおりです:
<timestamp time='2016-09-16T13:45:30'>
私は彼女のコードを実行しましたが、それでも動作します。今、私が持っているすべての情報を接続することはすべて混乱です:
T
が含まれていますo
およびr
形式指定子について説明していますが、これらは何であるかを示していません。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
列挙とそれがどのように機能するか?
だから私はようやくこれを理解し、同じ情報を他の人にも役立つ場合はここで共有することができました:
最初の部分は、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 GMT
はDateTimeKind.Utc
のものです( "GMT"テキストが存在します)2016-09-23T15:39:21.8899216+05:30
はDateTimeKind.Local
の日付時刻を表します(ISO 8601
規格に従って「T」文字が存在します)次は第2部です。これらの日時文字列gmtDateTimeString
およびlocalDateTimeString
を日時オブジェクトに変換し直す必要がある場合は、それらを解析する必要があります。したがって、DateTimeStyles.RoundtripKind
列挙値を使用してDateTime.Parse
APIに渡すと、タイムゾーン情報が文字列に既に組み込まれており、APIがその情報を使用して日付時刻を適切に解析することを実際に示します。
通常、日時データがXML形式でネットワーク経由で転送される場合、このスレッドに質問を投稿する前に参照した投稿で見たISO 8601形式が使用されます。そのため、XMLドキュメントから取得したこのような日時文字列を解析する際、DateTimeStyles.RoundtripKind
を使用して、文字列に存在するタイムゾーン情報に従って正しい日時値を取得することが適切でした。
他の答えを理解するのに苦労したので、自分で研究を行うことにしました。幸い、.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
値のDateTime
がUtc
に設定されるということです。
ただし、フラグが設定されていない場合はどうなりますか?これを決定する最良の方法は、2つのフォーマット指定子の実際のテストを行うことです。
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
。
r
形式指定子を使用する場合、タイムスタンプには常にGMT
が含まれます(元のDateTime
の種類がUtc
でない場合でも)。したがって、r
形式のテーブルにはTimezone
列は必要ありません。ただし、RFC1123タイムスタンプを解析すると、DateTime.Parse
とDateTime.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
に変更します)。
往復フォーマットは「マシンの消費」を目的としています。簡単に解析して同じDateTime値に戻すことができます。
他のほとんどの形式は、「人間の消費」のためのもので、日付(おそらく時間を含む)を人に示します。