[VB.NET] Date型でタイムゾーンを扱う場合の注意点

2014年12月26日

 Date型 (C# では Datetime 型) でタイムゾーンを意識する場合、注意が必要です。

 まず Date 型は 3つのタイムゾーン(モード)を持っています。

  1. ローカル時 (.Kind = DateTimeKind.Local)

     Dim d1 = Date.Now とした場合のモード。
     OS の時計の表示と同じ。

  2. 世界標準時 (.Kind = DateTimeKind.Utc)

     Dim d2 = Date.UtcNow とした場合のモード。
     世界標準時として記憶する。タイムゾーンが JST の場合、OSの表示 -9 時間になる。 

  3. 不定 (.Kind = DateTimeKind.Unspecified)

     Dim d3 = Date.Parse("2013/7/1 12:00:00") のように「タイムゾーン」を指定しなかった場合のモード。
     指定した時刻そのものを記憶する。

 これらのモードを意識せずに扱った場合、様々な問題を引き起こす可能性があります。
 たとえば以下のような問題が予想されます。

  • 問題1:上記d1 と 上記d2 を差し引くと、-9:00 が算出される

     コード

    Dim d1 = Date.Now 
    Dim d2 = Date.UtcNow
    Console.Writeline(d2 - d1)
    

     結果

    -9:00:00
    
  • 問題2:タイムゾーンが不定な時刻を、世界標準時,ローカル時に変換した場合

     コード

    Dim a = Date.Parse("2013/7/6")
    Console.WriteLine(a)
    Console.WriteLine(a.ToUniversalTime)
    Console.WriteLine(a.ToLocalTime)
    

     結果

    2013/07/06 0:00:00
    2013/07/05 15:00:00     ← 変換前時刻 -9:00 (変換前時刻が ローカル時 だとして計算)
    2013/07/06 9:00:00      ← 変換前時刻 +9:00 (変換前時刻が 世界標準時 だとして計算)
    
  • 問題3:タイムゾーンは比較の対象外

     コード

    Dim a = New Date(2013, 7, 6, 0, 0, 0, DateTimeKind.Local)
    Dim b = New Date(2013, 7, 6, 0, 0, 0, DateTimeKind.Utc)
    Dim c = New Date(2013, 7, 6, 0, 0, 0, DateTimeKind.Unspecified)
    Console.WriteLine(a = b)
    Console.WriteLine(a = c)
    

     結果

    True
    True
    
  • 問題4:タイムゾーンなし文字列だと不定モードで評価され、タイムゾーンつき文字列だとローカル時に変換される

     コード

    Dim a = Date.Parse("2013/7/6")
    Dim b = Date.Parse("2013/7/6 +1:00")
    
    Console.WriteLine("{0} {1}", a, a.Kind.ToString)
    Console.WriteLine("{0} {1}", b, b.Kind.ToString)
    

     結果

    2013/07/06 0:00:00 Unspecified   ← 不定モードで評価
    2013/07/06 8:00:00 Local         ← タイムゾーンを考慮の上、ローカル時に変換 (元のタイムゾーン情報は失われる)
    





カテゴリー: Program, VB.NET, 情報技術, 時刻

Follow comments via the RSS Feed | Leave a comment | Trackback URL

コメントを投稿する

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


«   »
 
Powered by Wordpress and MySQL. Theme by Shlomi Noach, openark.org