web-dev-qa-db-ja.com

C#datetimeオブジェクトをiso 8601文字列に変換します

DateTimeオブジェクトをISO8601文字列に変換しようとしていますが、間違った結果が出続けています。私はstackoverflowを見回しましたが、適切な解決策を見つけることができませんでした。

私は "2017-06-26T20:45:00.070Z"の日付時刻文字列で開始します。これはjsonからnewtonsoftによって逆シリアル化され、C#のDateTimeオブジェクトに変換されます。

var theTime = new DateTime(2017, 6, 26, 20, 45, 00, 70, DateTimeKind.Utc);

今、別のアルゴリズムで使用するには、その時間を元のUTC形式の文字列に戻す必要がありますが、私が試みるすべての変換は元の文字列に戻りません。何が間違っているのかわかりません。

私はもう試した:

var newTime = theTime.UtcNow.ToString("o");
// returns "2017-06-26T00:00:00.0000000Z"

var newTime2 = theTime.Date.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.sssZ");
// returns "2017-06-26T00:00:00.00Z"

私は何が間違っていますか?私はjsがtoISOString()を使用して行うことと同等のものを求めています。これはnewTime2日付時刻形式でリストしたものですが、時刻も表示していません。

ありがとう!

8
user1161137

観察する:

_// Your input
DateTime dt = new DateTime(2017, 6, 26, 20, 45, 0, 70, DateTimeKind.Utc);

// ISO8601 with 7 decimal places
string s1 = dt.ToString("o", CultureInfo.InvariantCulture);
//=> "2017-06-26T20:45:00.0700000Z"

// ISO8601 with 3 decimal places
string s2 = dt.ToString("yyyy-MM-dd'T'HH:mm:ss.fffK", CultureInfo.InvariantCulture);
//=> "2017-06-26T20:45:00.070Z"
_

いくつかのこと:

  • フォーマット文字列でZを使用しないでください。これは 有効な形式指定子 ではないため、出力する単なる文字として扱われます。入力日時の_.Kind_設定に関係なく、すべての文字列に含まれます。

  • DateTimeでは、Kを使用します。これは、Zを_.Kind_の出力に追加することで_DateTimeKind.Utc_を適切に伝達します。 _DateTimeKind.Local_、または_DateTimeKind.Unspecified_にはまったく何もありません。

  • Tは有効な書式指定子ではないため、文字として出力されますが、それらについては常に明示的にすることをお勧めします。したがって、_'T'_をお勧めします。

  • fffを使用すると、常に3桁の小数(ミリ秒)が返されます。ゼロのときに小数点を省略したい場合は、代わりにFFFを使用します。 sssの使用は無効です。

  • _CultureInfo.InvariantCulture_を渡すことは、現在のカルチャが別のカレンダーシステムを使用する可能性がある問題を回避するのに役立つため、良い習慣です。たとえば、_ar-SA_は、ISO 8601で必要とされる予測的なグレゴリオ暦ではなく、UmAlQuraCalendarを使用します。

  • 試したコードで、_theTime.UtcNow_を呼び出しました-コンパイルされません。 UtcNowは、インスタンスプロパティではなく、静的プロパティです。

  • また、コードでtheTime.Date.ToUniveralTime()を呼び出しました-どちらもしないでください。 _.Date_は時間コンポーネントをゼロに設定し、入力値にはすでに_DateTimeKind.Utc_があるため、.ToUniversalTime()は効果がありません。

32

問題は、UTCUniversalTimeなどの文化的標準を使用すると精度が低下することです。 DateTimeを単に印刷する場合:

var theTime = new DateTime(2017, 6, 26, 20, 45, 00, 70, 
    DateTimeKind.Utc);
Console.WriteLine(theTime);

6/26/2017 8:45:00 PM

この問題の詳細については、こちらをご覧ください こちら

解決策は、「文化」を使用しないことです。 (たとえば、UniversalTime、またはUtcNow)。これらの文化的基準にはミリ秒が含まれることはありません...人々が実際にミリ秒ほど頻繁に気にする文化はないからです。

解決策:

var newTime = theTime.ToString("o");
Console.WriteLine(newTime);

2017-06-26T20:45:00.0700000Z

1
Max von Hippel