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

这是我写的第一篇文章,虽然写的一般却是我自己一个字一个字敲出来的,希望能对大家时区的理解有帮助。

posted @ 2012-08-30 23:39  Code_Dog  Views(12968)  Comments(1Edit  收藏  举报