發現自己對.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()結果,並兩兩進行比較。
staticvoid 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) =>
{
returnstring.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
最後補充兩點:
- Unspecified很有趣(但也可能變成陷阱),ToUniversalTime()時被視為本地時間(台北時區)減去8小時,ToLocalTime()時被視為UTC時間加上8小時。
- 比較結果相等的有d1 == d2, d1 == d4, d2 == d4,原則上,ToString()的結果一致就相等,不管時區。