65

DateTime を UTC 形式で表す文字列を解析したいと考えています。

私の文字列表現には、文字列が UTC 時間を表すことを示す必要があるズールー時間仕様が含まれています。

var myDate = DateTime.Parse("2012-09-30T23:00:00.0000000Z");    

上記から、myDate.Kind は DateTimeKind.Utc であると予想されますが、代わりに DatetimeKind.Local です。

UTC 時刻を表す文字列を解析するにはどうすればよいですか?

どうもありがとう!

4

5 に答える 5

90

私は自分のNoda Timeプロジェクトを個人的に使用します。(確かに私は作者として偏見がありますが、それはよりきれいになるでしょう...)しかし、あなたがそれを行うことができない場合...

DateTime.ParseExact期待する正確な形式を指定して使用し、解析コードにDateTimeStyles.AssumeUniversalとを含めます。DateTimeStyles.AdjustToUniversal

using System;
using System.Globalization;

class Test
{
    static void Main()        
    {
        var date = DateTime.ParseExact("2012-09-30T23:00:00.0000000Z",
                                       "yyyy-MM-dd'T'HH:mm:ss.fffffff'Z'",
                                       CultureInfo.InvariantCulture,
                                       DateTimeStyles.AssumeUniversal |
                                       DateTimeStyles.AdjustToUniversal);
        Console.WriteLine(date);
        Console.WriteLine(date.Kind);
    }
}

(なぜデフォルトでローカルに調整されるのかAdjustToUniversalは私にはわかりませんが、気にしないでください...)

編集: mattytommo の提案に対する私の異議を拡張するために、情報が失われることを証明することを目指しました。私はこれまで失敗してきましたが、非常に奇妙な方法で。これを見てください - ヨーロッパ/ロンドンのタイム ゾーンで実行され、時計は 2012 年 10 月 28 日の現地時間午前 2 時 (UTC 午前 1 時) に戻ります。

DateTime local1 = DateTime.Parse("2012-10-28T00:30:00.0000000Z");
DateTime local2 = DateTime.Parse("2012-10-28T01:30:00.0000000Z");
Console.WriteLine(local1 == local2); // True

DateTime utc1 = TimeZoneInfo.ConvertTimeToUtc(local1);
DateTime utc2 = TimeZoneInfo.ConvertTimeToUtc(local2);
Console.WriteLine(utc1 == utc2); // False. Hmm.

「DSTの有無にかかわらず」フラグがどこかに保存されているようですが、どこに解決できれば私は吹き飛ばされます. TimeZoneInfo.ConvertTimeToUtc状態のドキュメント

dateTimeがあいまいな時間に対応する場合、このメソッドはそれがソース タイム ゾーンの標準時間であると想定します。

変換するとき、ここではそうではないようlocal2です...

編集:わかりました、さらに奇妙になります-使用しているフレームワークのバージョンによって異なります。このプログラムを考えてみましょう:

using System;
using System.Globalization;

class Test
{
    static void Main()        
    {
        DateTime local1 = DateTime.Parse("2012-10-28T00:30:00.0000000Z");
        DateTime local2 = DateTime.Parse("2012-10-28T01:30:00.0000000Z");

        DateTime utc1 = TimeZoneInfo.ConvertTimeToUtc(local1);
        DateTime utc2 = TimeZoneInfo.ConvertTimeToUtc(local2);
        Console.WriteLine(utc1);
        Console.WriteLine(utc2);

        DateTime utc3 = local1.ToUniversalTime();
        DateTime utc4 = local2.ToUniversalTime();
        Console.WriteLine(utc3);
        Console.WriteLine(utc4);
    }
}

したがって、これは 2 つの異なるUTC 値を取得し、それらを で解析してDateTime.Parseから、2 つの異なる方法でそれらを UTC に変換します。

.NET 3.5 での結果:

28/10/2012 01:30:00 // Look - we've lost information
28/10/2012 01:30:00
28/10/2012 00:30:00 // But ToUniversalTime() seems okay...
28/10/2012 01:30:00

.NET 4.5 ベータ版での結果:

28/10/2012 00:30:00 // It's okay!
28/10/2012 01:30:00
28/10/2012 00:30:00
28/10/2012 01:30:00
于 2012-04-05T13:05:50.940 に答える
28

いつものように、ジョンの答えは非常に包括的です。とはいえ、誰もまだ言及していませんDateTimeStyles.RoundtripKind。DateTime を文字列に変換し、同じ DateTime に戻す (DateTime.Kind設定の保持を含む) 場合は、DateTimeStyles.RoundtripKindフラグを使用します。

Jon が言ったように、正しいことは、DateTime オブジェクトを文字列に変換するときに "O" フォーマッタを使用することです。これにより、精度とタイムゾーン情報の両方が保持されます。繰り返しますが、ジョンが言ったようDateTime.ParseExactに、元に戻すときに使用します。しかし、DateTimeStyles.RoundtripKind を使用すると、入力したものが常に返されます。

var now = DateTime.UtcNow;
var strNow = now.ToString("O");
var newNow = DateTime.ParseExact(strNow, "O", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind);

上記のコードでは、は UTC であることを含め、newNowとまったく同じ時刻です。の代用をnow除いて同じコードを実行すると、 の正確なコピーが として返されますが、今回は現地時間として取得されます。DateTime.NowDateTime.UtcNownownewNow

私の目的にとって、これは正しいことでした。なぜなら、渡されて変換されたものはすべて、まったく同じものに変換されることを確認したかったからです。

于 2012-08-21T22:49:36.477 に答える
5

以下を使用してTimeZoneInfoクラスを使用します。

var myDate = TimeZoneInfo.ConvertTimeToUtc(DateTime.Parse("2012-09-30T23:00:00.0000000Z"));
于 2012-04-05T13:02:54.070 に答える
3

パーサー メソッドには次の形式を使用できます。yyyy-MM-ddTHH:mm:ss.ffffffK

これにより、最後にタイム ゾーン情報が適切に処理されます ( .NET 2.0 以降)。

RE: ISO 8601

于 2013-03-22T18:05:05.380 に答える