C#關於TimeZone和TimeZoneInfo類的比較


在工作中我們遇到國際化時,經常要處理時區問題。這兩個類都是處理時區的我們應該怎樣選擇呢?

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的偏移量。

這是我寫的第一篇文章,雖然寫的一般卻是我自己一個字一個字敲出來的,希望能對大家時區的理解有幫助。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM