在工作中我們遇到國際化時,經常要處理時區問題。這兩個類都是處理時區的我們應該怎樣選擇呢?
TimeZone 類來檢索有關當前時區的信息,並將時間從本地時間轉換為協調世界時 (UTC),也就是說這個類是用來處理LocalTimeZone和UTC時間的。
TimeZoneInfo類可以處理系統上預定義的任何時區、創建新時區,以及輕松地將日期和時間從一個時區轉換到另一個時區。從微軟的官方提示上我們可以看出,TimeZone 類基本已經被TimeZoneInfo類取代了。
首先介紹下TimeZone類吧,TimeZone的CurrentTimeZone屬性和TimeZoneInfo的Local一屬性類似,得到的都是LocalTimeZone。
TimeZone的GetDaylightChanges方法是得到時區某一年的夏令時時間。這里提到的夏令時時間中國是不支持的,像美國和加拿大的一些國家是支持的。如果TimeZone是太平洋時區(Pacific Time Zone),這個時區的標准時間是UTC-8,夏令時時間的UTC-7。調用GetDaylightChanges返回的結果是2012-3-11 2:00 to 2012-11-4 2:00,這就是太平洋時區在這一年的夏令時開始和結束時間。
DaylightTime daylight = localZone.GetDaylightChanges(currentYear); // Display the daylight saving time range for the current year. Console.WriteLine( "Daylight saving time for year {0}:", currentYear); Console.WriteLine("{0:yyyy-MM-dd HH:mm} to " + "{1:yyyy-MM-dd HH:mm}, differ: {2}", daylight.Start, daylight.End, daylight.Delta);
TimeZone的GetUtcOffset方法得到的是Local和UTC時間的偏移量,和TimeZoneInfo的BaseUtcOffset方法類似。太平洋時區的返回結果是-7:00:00,這是因為現在是8月份太平洋時區執行的是夏令時時間,所以和UTC時間是相差7個小時。
//Pacific Standard TimeZone TimeSpan currentOffset = localZone.GetUtcOffset(currentDate); Console.WriteLine("UTC offset:{0}", currentOffset);
再說下TimeZoneInfo這個類,它的Utc和Local屬性直接得到的是UTC TimeZone和Local TImeZone對象,用起來很方便。
TimeZoneInfo的ConvertTime(DateTime, TimeZoneInfo)方法,把一個時間轉到一個時區你可能會感覺很納悶。雖然Datetime沒有時區屬性但也是有時區的,因為DateTime在創建時候可以指定DateTimeKind可以是Local或Utc,沒指定的話就是Unspecified默認按Local來處理的。
TimeZoneInfo的CreateCustomTimeZone方法可以創建帶有夏令時規則的時區。對於FloatingRule是指夏令時發生某月第幾個星期所以是浮動的,而FixedRule是指某月的多少號是固定的。
// Define transition times to/from DST TimeZoneInfo.TransitionTime startTransition, endTransition; startTransition = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(new DateTime(1, 1, 1, 4, 0, 0), 10, 2, DayOfWeek.Sunday); endTransition = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(new DateTime(1, 1, 1, 3, 0, 0), 3, 2, DayOfWeek.Sunday); // Define adjustment rule TimeSpan delta = new TimeSpan(1, 0, 0); TimeZoneInfo.AdjustmentRule adjustment; adjustment = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(new DateTime(1999, 10, 1), DateTime.MaxValue.Date, delta, startTransition, endTransition); // Create array for adjustment rules TimeZoneInfo.AdjustmentRule[] adjustments = { adjustment }; // Define other custom time zone arguments string displayName = "(GMT-04:00) Antarctica/Palmer Time"; string standardName = "Palmer Time"; string daylightName = "Palmer Daylight Time"; TimeSpan offset = new TimeSpan(-4, 0, 0); TimeZoneInfo palmer = TimeZoneInfo.CreateCustomTimeZone(standardName, offset, displayName, standardName, daylightName, adjustments); Console.WriteLine("\nThe current time is {0} {1}", TimeZoneInfo.ConvertTime(DateTime.Now, TimeZoneInfo.Local, palmer), palmer.StandardName);
TimeZoneInfo的IsAmbiguousTime(DateTime) 方法,說這我主要想說下AmbiguousTime。通過下面的代碼你會發現,在夏令時往標准時間轉的時候,1點到2點之間的時間都是AmbiguousTime。因為這段時間對應着Utc-8和Utc-7兩個時區,所以是時間是不能確定的。
DateTime baseTime = new DateTime(2007, 11, 4, 0, 59, 00, DateTimeKind.Unspecified); DateTime newTime; // Get Pacific Standard Time zone TimeZoneInfo pstZone = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time"); // List possible ambiguous times for 63-minute interval, from 12:59 AM to 2:01 AM for (int ctr = 0; ctr < 63; ctr++) { // Because of assignment, newTime.Kind is also DateTimeKind.Unspecified newTime = baseTime.AddMinutes(ctr); Console.WriteLine("{0} is ambiguous: {1} ;{2} is daylighttime: {3} ", newTime, pstZone.IsAmbiguousTime(newTime), newTime, pstZone.IsDaylightSavingTime(newTime)); }
當然TimeZoneInfo對象還可以序列化成Xml,也可以反序列化。TimeZoneInfo對象還可以被存在資源文件里面,用的時候再取出來。
關於DateTimeOffset的理解,我認為它就是DateTime加上一個UtcOffset的偏移量。
這是我寫的第一篇文章,雖然寫的一般卻是我自己一個字一個字敲出來的,希望能對大家時區的理解有幫助。