發現自己對.NET DateTime時區及比對的概念有點模糊,特實測並整理筆記備忘。

首先,.NET的DateTime型別包含時區觀念,DateTime.Kind記錄了時區類別,共分為Unspecified(不指定)、Utc(世界標準時間)以及Local(本地時間)三種。但兩個DateTime在比較時不會自動轉換時區,所以本地時間台北早上8點的DateTime,與UTC當日凌晨0點的DateTime物件直接比較不相等(雖然它們實質上相等),但只需透過ToUniversalTime()ToLocalTime()轉換成統一基準就相等了。

以下的例子利用JSON轉換產生四組時間,00:00 UTC、00:00 Unspecified、08:00 台北時區、00:00 台北時區,分別檢視其Kind、ToUniversalTime()及ToLocalTime()結果,並兩兩進行比較。

排版顯示純文字
        static void Main(string[] args)
        {
            string j1 = "\"2012-12-21T00:00:00Z\""; //00:00 UTC
            string j2 = "\"2012-12-21T00:00:00\"";  //00:00 不指定時區
    string j3 = "\"2012-12-21T08:00:00+0800\""; //08:00 TPE
            string j4 = "\"2012-12-21T00:00:00+0800\""; //00:00 TPE
            DateTime d1 = JsonConvert.DeserializeObject<DateTime>(j1);
            DateTime d2 = JsonConvert.DeserializeObject<DateTime>(j2);
            DateTime d3 = JsonConvert.DeserializeObject<DateTime>(j3);
            DateTime d4 = JsonConvert.DeserializeObject<DateTime>(j4);
            Func<DateTime, string> inspect = (d) =>
            {
                return string.Format(
"{0} toString=[{1:MM-dd HH:mm}] toUTC=[{2:MM-dd HH:mm}] toLocal=[{3:MM-dd HH:mm}]",
                    d.Kind.ToString().PadRight(11), 
                    d, d.ToUniversalTime(), d.ToLocalTime());
            };
            Console.WriteLine("d1:{0}", inspect(d1));
            Console.WriteLine("d2:{0}", inspect(d2));
            Console.WriteLine("d3:{0}", inspect(d3));
            Console.WriteLine("d4:{0}", inspect(d4));
            Console.WriteLine("d1 == d2 ? {0}", d1.CompareTo(d2) == 0);
            Console.WriteLine("d1 == d3 ? {0}", d1.CompareTo(d3) == 0);
            Console.WriteLine("d1 == d4 ? {0}", d1.CompareTo(d4) == 0);
            Console.WriteLine("d2 == d3 ? {0}", d2.CompareTo(d3) == 0);
            Console.WriteLine("d2 == d4 ? {0}", d2.CompareTo(d4) == 0);
            Console.WriteLine("d3 == d4 ? {0}", d3.CompareTo(d4) == 0);
            Console.Read();
        }

結果如下:

d1:Utc         toString=[12-21 00:00] toUTC=[12-21 00:00] toLocal=[12-21 08:00]
d2:Unspecified toString=[12-21 00:00] toUTC=[12-20 16:00] toLocal=[12-21 08:00]
d3:Local       toString=[12-21 08:00] toUTC=[12-21 00:00] toLocal=[12-21 08:00]
d4:Local       toString=[12-21 00:00] toUTC=[12-20 16:00] toLocal=[12-21 00:00]
d1 == d2 ? True
d1 == d3 ? False
d1 == d4 ? True
d2 == d3 ? False
d2 == d4 ? True
d3 == d4 ? False

最後補充兩點:

  1. Unspecified很有趣(但也可能變成陷阱),ToUniversalTime()時被視為本地時間(台北時區)減去8小時,ToLocalTime()時被視為UTC時間加上8小時。
  2. 比較結果相等的有d1 == d2, d1 == d4, d2 == d4,原則上,ToString()的結果一致就相等,不管時區。

Comments

Be the first to post a comment

Post a comment