2011-08-30 14 views
6

を与えられていない:私はドイツ語のウェブサイトから抽出された日時文字列を解析しようとしている解析のDateTime知られているが、私は、構文解析の日付と時刻の周りの問題とこだわっているタイムゾーン

。それは形式で指定された「24時間day.month.year:分、のような:

01.01.2011 17:00 

そして、それはドイツのタイムゾーンでは常にあります。しかし、ここで問題が来る:

  • '01 .01.2011 17:00' (ここでは、タイムゾーンが夏時間なしCET、であるUTCに'01 .01.2011午後04時00' とのDateTime構造体に解析されなければなりません
  • (ここでは、タイムゾーンが夏時間とCEST、 です)
  • '01 .06.2011 17時00' 分しばらくはUTCに'01 .01.2011 15時でのDateTime構造体に解析されるべき' )の時間を節約

私はこれを達成する手がかりがありません。ドイツのタイムゾーンにローカルクロックを設定して、DateTime.ParseExactとフラグDateTimeStyles.AssumeLocalDateTimeStyles.AdjustToUniversalを解析すると、正しく解析されます。しかし、私は、クライアントがローカル時計とタイムゾーンから独立してそれを解析することを望みます。また、日付(夏:-2 /冬:-1)によって決まるので、私は自分自身でタイムゾーンオフセットを行いたいとは考えていません。

UTCでdatetimeを取得すると、ローカルタイムゾーンに変換するのが簡単になります。

+0

[c#fx 3.5の特定のタイムゾーンでのDateTimeの作成](http://stackoverflow.com/questions/246498/creating-a-datetime-in-a-specific-time-zone-in) -c-fx-3-5) –

+0

@Michael Haren:いいえ、それは重複していません。私はこの質問をする前に私はこれを見て、それは私の特定の問題に役立たなかった。 –

+0

おそらく重複はありませんが、助けてくれると思いました –

答えて

1

タスクはWP7/Silverlightのフレームワークの助けを借りてarchievedすることができないことを見た後、私はその小さなヘルパーを書きました

public static class DateTimeHelper 
{ 
    /// <summary> 
    /// Tries to parse the given datetime string that is not annotated with a timezone 
    /// information but known to be in the CET/CEST zone and returns a DateTime struct 
    /// in UTC (so it can be converted to the devices local time). If it could not be 
    /// parsed, result contains the current date/time in UTC. 
    /// </summary> 
    public static bool TryParseCetCest(string s, string format, IFormatProvider provider, DateTimeStyles style, out DateTime result) 
    { 
     // Parse datetime, knowing it is in CET/CEST timezone. Parse as universal as we fix it afterwards 
     if (!DateTime.TryParseExact(s, format, provider, style, out result)) 
     { 
      result = DateTime.UtcNow; 
      return false; 
     } 
     result = DateTime.SpecifyKind(result, DateTimeKind.Utc); 

     // The boundaries of the daylight saving time period in CET and CEST (_not_ in UTC!) 
     // Both DateTime structs are of kind 'Utc', to be able to compare them with the parsing result 
     DateTime DstStart = LastSundayOf(result.Year, 3).AddHours(2); 
     DateTime DstEnd = LastSundayOf(result.Year, 10).AddHours(3); 

     // Are we inside the daylight saving time period? 
     if (DstStart.CompareTo(result) <= 0 && result.CompareTo(DstEnd) < 0) 
      result = result.AddHours(-2); // CEST = UTC+2h 
     else 
      result = result.AddHours(-1); // CET = UTC+1h 

     return true; 
    } 

    /// <summary> 
    /// Returns the last sunday of the given month and year in UTC 
    /// </summary> 
    private static DateTime LastSundayOf(int year, int month) 
    { 
     DateTime firstOfNextMonth = new DateTime(year, month + 1, 1, 0, 0, 0, DateTimeKind.Utc); 
     return firstOfNextMonth.AddDays(firstOfNextMonth.DayOfWeek == DayOfWeek.Sunday ? -7 : 
                (-1 * (int)firstOfNextMonth.DayOfWeek)); 
    } 
} 

トリックは、(これはTryParseExact日付がUTCであると仮定し、日付変換/ローカルに調整を戻すことができる)なしDateTimeStyles.AssumeUniversalフラグをそれを解析することでUTCとしてrespecifyingとジョブを行いそれを手動でアクチュエータに調整するUTC相当です。

hereというDST規則に従います。私は夏時間の開始/終了の直前/直後に4つの境界ケースすべてでそれをテストしました。これは再びテストの重要性を示しました。DstStart.CompareTo(result) < 0<演算子を<=に変更して正しい結果を出さなければなりませんでした。

私はここでホイールを再発明している気がしましたが、私はこの単純な仕事のために専用の図書館を使いたくありませんでした。素晴らしいプロジェクトであるノーダタイムを見ましたが、これは必要ではないと思います。

私はこの小さなヘルパーで少し時間を節約することができれば幸いです。これは意図的にすべてのタイムゾーン(Noda Timeのようなlibを使用する必要がある場合)ではなく、私の場合のように1つの固定された単一のタイムゾーンを持つこれらのケースに対してです。

+0

私はあなたがAssumeUniversalを使用していないことに驚いています。すでにUTCのDateTimeで返すことが期待されています。それが当てはまらない場合には、あなたを誤解する謝罪をしてください。 DateTimeは私を悩ます:( –

+0

@Jon:正直言って、まったく同じだと思って、それがなぜこのような奇妙な結果を作り出したのか疑問に思っていました。 :00 'それは期待どおりの午後5時を想定していますが、私の場合は7pm(Kind = local)のDateTime構造体を返します(ローカルタイムゾーン=ドイツ語)。午後7時のUtc構造体... –

+0

はい:DateTimeは本当に迷惑です:) –

4

どのようなタイムゾーンを解析する必要があるかはわかるようです。論理的に.NET 3.5(ひいてはTimeZoneInfoを)あなたがすべきであると仮定:

  • は "ローカル" の時間としてそれを解析し(特定のない時間帯)
  • を変換することをUTC時間

に現地時間残念ながらDateTime makes that slightly tricky。編集:私と考えてあなたはDateTimeStyles.AssumeUniversalを使用してそれを解析して変換したいと思うが、ローカルDateTime、annoyinglyを返すようになります。基本的に、あなたが使用できるように、適切なタイミングでDateTimeで終わるしたい:

parsed = DateTime.SpecifyKind(parsed, DateTimeKind.Unspecified); 

あなたは、その後でUTC値を取得できます。

DateTime utc = TimeZoneInfo.ConvertTimeToUtc(parsed, germanTimeZone); 

あなたが本当にしたいノート「指定されていない」日付時刻が最初に表示されるため、任意の時間帯にUTCに変換できます。 DSTの変更により、現地時間が不明確(2回発生)または不可能(まったく発生しない)という可能性も覚えておく必要があります。

そして、それが終了していますとき、はい、これはNoda Timeで非常に簡単になります:)

+0

+1「ConvertTimeToUtc」は何とか見つからなかったものです。しかし、最後の質問があります。「germanTimeZone」はどこから取得できますか? –

+0

@Philip:適切なタイムゾーンIDを設定し、 'TimeZoneInfo.FindSystemTimeZoneById'を使用します。私はあなたが「W.ヨーロッパの標準時」を望んでいると思う(それは標準時と呼ばれる事実を無視する、それはちょうどIDである - それはまだ夏時間を扱うだろう)。 –

+0

私はおそらく、 '' TimeZoneInfo''が '' ConvertTime''メソッドとタイムゾーン '' Utc''と '' Local''を持つWindows phone 7アプリケーションをビルドしていると言いました。 –

関連する問題