如何:创建含调整规则的时区How to: Create time zones with adjustment rules

由于以下几个原因,应用程序所需的确切时区信息在特定系统上可能不存在:The precise time zone information that is required by an application may not be present on a particular system for several reasons:

  • 本地系统的注册表中从未定义过该时区。The time zone has never been defined in the local system's registry.

  • 已修改或删除注册表中有关时区的数据。Data about the time zone has been modified or removed from the registry.

  • 对于特定的历史时间段,时区没有有关时区调整的准确信息。The time zone does not have accurate information about time zone adjustments for a particular historic period.

在这些情况下,可以调用 CreateCustomTimeZone 方法来定义应用程序所需的时区。In these cases, you can call the CreateCustomTimeZone method to define the time zone required by your application. 您可以使用此方法的重载来创建具有或不带调整规则的时区。You can use the overloads of this method to create a time zone with or without adjustment rules. 如果时区支持夏令时,则可以用固定或浮动调整规则定义调整。If the time zone supports daylight saving time, you can define adjustments with either fixed or floating adjustment rules. (有关这些术语的定义,请参阅时区概述中的 "时区术语" 部分。)(For definitions of these terms, see the "Time Zone Terminology" section in Time zone overview.)

重要

通过调用方法创建的自定义时区 CreateCustomTimeZone 未添加到注册表中。Custom time zones created by calling the CreateCustomTimeZone method are not added to the registry. 相反,只能通过方法调用返回的对象引用来访问这些对象 CreateCustomTimeZoneInstead, they can be accessed only through the object reference returned by the CreateCustomTimeZone method call.

本主题说明如何创建具有调整规则的时区。This topic shows how to create a time zone with adjustment rules. 若要创建不支持夏令时调整规则的时区,请参阅如何:创建不带调整规则的时区To create a time zone that does not support daylight saving time adjustment rules, see How to: Create Time Zones Without Adjustment Rules.

创建具有浮动调整规则的时区To create a time zone with floating adjustment rules

  1. 对于每个调整(即,每次从一个特定时间间隔转换到标准时间时),请执行以下操作:For each adjustment (that is, for each transition away from and back to standard time over a particular time interval), do the following:

    1. 定义时区调整的开始转换时间。Define the starting transition time for the time zone adjustment.

      您必须调用 TimeZoneInfo.TransitionTime.CreateFloatingDateRule 方法并向其传递一个 DateTime 值,用于定义转换时间、定义转换月份的整数值、定义转换发生的周的整数值,以及 DayOfWeek 定义发生转换的周中某天的值。You must call the TimeZoneInfo.TransitionTime.CreateFloatingDateRule method and pass it a DateTime value that defines the time of the transition, an integer value that defines the month of the transition, an integer value that defines the week on which the transition occurs, and a DayOfWeek value that defines the day of the week on which the transition occurs. 此方法调用对对象进行实例化 TimeZoneInfo.TransitionTimeThis method call instantiates a TimeZoneInfo.TransitionTime object.

    2. 为时区调整定义结束转换时间。Define the ending transition time for the time zone adjustment. 这需要对方法的另一次调用 TimeZoneInfo.TransitionTime.CreateFloatingDateRuleThis requires another call to the TimeZoneInfo.TransitionTime.CreateFloatingDateRule method. 此方法调用将实例化第二个 TimeZoneInfo.TransitionTime 对象。This method call instantiates a second TimeZoneInfo.TransitionTime object.

    3. 调用 CreateAdjustmentRule 方法并向其传递调整的有效开始日期和结束日期、 TimeSpan 定义转换中的时间量的对象和两个 TimeZoneInfo.TransitionTime 对象,这些对象定义在夏令时发生转换的时间。Call the CreateAdjustmentRule method and pass it the effective start and end dates of the adjustment, a TimeSpan object that defines the amount of time in the transition, and the two TimeZoneInfo.TransitionTime objects that define when the transitions to and from daylight saving time occur. 此方法调用对对象进行实例化 TimeZoneInfo.AdjustmentRuleThis method call instantiates a TimeZoneInfo.AdjustmentRule object.

    4. TimeZoneInfo.AdjustmentRule 对象分配给对象的数组 TimeZoneInfo.AdjustmentRuleAssign the TimeZoneInfo.AdjustmentRule object to an array of TimeZoneInfo.AdjustmentRule objects.

  2. 定义时区的显示名称。Define the time zone's display name. 显示名称采用相当标准的格式,在此格式中,时区与协调世界时(UTC)的偏移量括在括号中,后面跟有标识时区的字符串、时区中的一个或多个城市,或者时区中的一个或多个国家或地区。The display name follows a fairly standard format in which the time zone's offset from Coordinated Universal Time (UTC) is enclosed in parentheses and is followed by a string that identifies the time zone, one or more of the cities in the time zone, or one or more of the countries or regions in the time zone.

  3. 定义时区标准时间的名称。Define the name of the time zone's standard time. 通常,此字符串还用作时区的标识符。Typically, this string is also used as the time zone's identifier.

  4. 定义时区的夏令时的名称。Define the name of the time zone's daylight time.

  5. 如果要使用不同于时区的标准名称的标识符,请定义时区标识符。If you want to use a different identifier than the time zone's standard name, define the time zone identifier.

  6. 实例化 TimeSpan 定义时区与 UTC 的偏移量的对象。Instantiate a TimeSpan object that defines the time zone's offset from UTC. 时间时区晚于 UTC 的时区具有正偏移量。Time zones with times that are later than UTC have a positive offset. 其时间早于 UTC 的时区具有负偏移量。Time zones with times that are earlier than UTC have a negative offset.

  7. 调用 TimeZoneInfo.CreateCustomTimeZone(String, TimeSpan, String, String, String, TimeZoneInfo+AdjustmentRule[]) 方法以实例化新时区。Call the TimeZoneInfo.CreateCustomTimeZone(String, TimeSpan, String, String, String, TimeZoneInfo+AdjustmentRule[]) method to instantiate the new time zone.

示例Example

下面的示例为美国定义了一个中部标准时区,其中包括从1918到当前时间间隔内的各种时间间隔的调整规则。The following example defines a Central Standard Time zone for the United States that includes adjustment rules for a variety of time intervals from 1918 to the present.

TimeZoneInfo cst;
// Declare necessary TimeZoneInfo.AdjustmentRule objects for time zone
TimeSpan delta = new TimeSpan(1, 0, 0);
TimeZoneInfo.AdjustmentRule adjustment;
List<TimeZoneInfo.AdjustmentRule> adjustmentList = new List<TimeZoneInfo.AdjustmentRule>();
// Declare transition time variables to hold transition time information
TimeZoneInfo.TransitionTime transitionRuleStart, transitionRuleEnd;

// Define new Central Standard Time zone 6 hours earlier than UTC
// Define rule 1 (for 1918-1919)
transitionRuleStart = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(new DateTime(1, 1, 1, 2, 0, 0), 03, 05, DayOfWeek.Sunday);
transitionRuleEnd = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(new DateTime(1, 1, 1, 2, 0, 0), 10, 05, DayOfWeek.Sunday);
adjustment = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(new DateTime(1918, 1, 1), new DateTime(1919, 12, 31), delta,
                                                           transitionRuleStart, transitionRuleEnd);
adjustmentList.Add(adjustment);
// Define rule 2 (for 1942)
transitionRuleStart = TimeZoneInfo.TransitionTime.CreateFixedDateRule(new DateTime(1, 1, 1, 2, 0, 0), 02, 09);
adjustment = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(new DateTime(1942, 1, 1), new DateTime(1942, 12, 31),
                                                           delta, transitionRuleStart, transitionRuleEnd);
adjustmentList.Add(adjustment);
// Define rule 3 (for 1945)
transitionRuleStart = TimeZoneInfo.TransitionTime.CreateFixedDateRule(new DateTime(1, 1, 1, 23, 0, 0), 08, 14);
transitionRuleEnd = TimeZoneInfo.TransitionTime.CreateFixedDateRule(new DateTime(1, 1, 1, 2, 0, 0), 09, 30);
adjustment = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(new DateTime(1945, 1, 1), new DateTime(1945, 12, 31),
                                                           delta, transitionRuleStart, transitionRuleEnd);
adjustmentList.Add(adjustment);
// Define end rule (for 1967-2006)
transitionRuleEnd = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(new DateTime(1, 1, 1, 2, 0, 0), 10, 5, DayOfWeek.Sunday);
// Define rule 4 (for 1967-73)
transitionRuleStart = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(new DateTime(1, 1, 1, 2, 0, 0), 04, 05, DayOfWeek.Sunday);
adjustment = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(new DateTime(1967, 1, 1), new DateTime(1973, 12, 31),
                                                           delta, transitionRuleStart, transitionRuleEnd);
adjustmentList.Add(adjustment);
// Define rule 5 (for 1974 only)
transitionRuleStart = TimeZoneInfo.TransitionTime.CreateFixedDateRule(new DateTime(1, 1, 1, 2, 0, 0), 01, 06);
adjustment = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(new DateTime(1974, 1, 1), new DateTime(1974, 12, 31),
                                                           delta, transitionRuleStart, transitionRuleEnd);
adjustmentList.Add(adjustment);
// Define rule 6 (for 1975 only)
transitionRuleStart = TimeZoneInfo.TransitionTime.CreateFixedDateRule(new DateTime(1, 1, 1, 2, 0, 0), 02, 23);
adjustment = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(new DateTime(1975, 1, 1), new DateTime(1975, 12, 31),
                                                           delta, transitionRuleStart, transitionRuleEnd);
adjustmentList.Add(adjustment);
// Define rule 7 (1976-1986)
transitionRuleStart = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(new DateTime(1, 1, 1, 2, 0, 0), 04, 05, DayOfWeek.Sunday);
adjustment = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(new DateTime(1976, 1, 1), new DateTime(1986, 12, 31),
                                                           delta, transitionRuleStart, transitionRuleEnd);
adjustmentList.Add(adjustment);
// Define rule 8 (1987-2006)
transitionRuleStart = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(new DateTime(1, 1, 1, 2, 0, 0), 04, 01, DayOfWeek.Sunday);
adjustment = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(new DateTime(1987, 1, 1), new DateTime(2006, 12, 31),
                                                           delta, transitionRuleStart, transitionRuleEnd);
adjustmentList.Add(adjustment);
// Define rule 9 (2007- )
transitionRuleStart = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(new DateTime(1, 1, 1, 2, 0, 0), 03, 02, DayOfWeek.Sunday);
transitionRuleEnd = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(new DateTime(1, 1, 1, 2, 0, 0), 11, 01, DayOfWeek.Sunday);
adjustment = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(new DateTime(2007, 1, 1), DateTime.MaxValue.Date,
                                                           delta, transitionRuleStart, transitionRuleEnd);
adjustmentList.Add(adjustment);

// Convert list of adjustment rules to an array
TimeZoneInfo.AdjustmentRule[] adjustments = new TimeZoneInfo.AdjustmentRule[adjustmentList.Count];
adjustmentList.CopyTo(adjustments);

cst = TimeZoneInfo.CreateCustomTimeZone("Central Standard Time", new TimeSpan(-6, 0, 0),
      "(GMT-06:00) Central Time (US Only)", "Central Standard Time",
      "Central Daylight Time", adjustments);
Dim cst As TimeZoneInfo
' Declare necessary TimeZoneInfo.AdjustmentRule objects for time zone
Dim delta As New TimeSpan(1, 0, 0)
Dim adjustment As TimeZoneInfo.AdjustmentRule
Dim adjustmentList As New List(Of TimeZoneInfo.AdjustmentRule)
' Declare transition time variables to hold transition time information
Dim transitionRuleStart, transitionRuleEnd As TimeZoneInfo.TransitionTime

' Define new Central Standard Time zone 6 hours earlier than UTC
' Define rule 1 (for 1918-1919)
transitionRuleStart = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(#02:00:00AM#, 03, 05, DayOfWeek.Sunday)
transitionRuleEnd = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(#02:00:00AM#, 10, 05, DayOfWeek.Sunday)
adjustment = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(#01/01/1918#, #12/31/1919#, delta, transitionRuleStart, transitionRuleEnd)
adjustmentList.Add(adjustment)
' Define rule 2 (for 1942)
transitionRuleStart = TimeZoneInfo.TransitionTime.CreateFixedDateRule(#2:00:00AM#, 02, 09)
adjustment = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(#01/01/1942#, #12/31/1942#, delta, transitionRuleStart, transitionRuleEnd)
adjustmentList.Add(adjustment)
' Define rule 3 (for 1945)
transitionRuleStart = TimeZoneInfo.TransitionTime.CreateFixedDateRule(#11:00:00PM#, 08, 14)
transitionRuleEnd = TimeZoneInfo.TransitionTime.CreateFixedDateRule(#2:00:00AM#, 09, 30)
adjustment = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(#01/01/1945#, #12/31/1945#, delta, transitionRuleStart, transitionRuleEnd)
adjustmentList.Add(adjustment)
' Define end rule (for 1967-2006)
transitionRuleEnd = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(#02:00:00AM#, 10, 5, DayOfWeek.Sunday)
' Define rule 4 (for 1967-73)
transitionRuleStart = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(#2:00:00AM#, 04, 05, DayOfWeek.Sunday)
adjustment = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(#01/01/1967#, #12/31/1973#, delta, transitionRuleStart, transitionRuleEnd)
adjustmentList.Add(adjustment)
' Define rule 5 (for 1974 only)
transitionRuleStart = TimeZoneInfo.TransitionTime.CreateFixedDateRule(#2:00:00AM#, 01, 06)
adjustment = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(#01/01/1974#, #12/31/1974#, delta, transitionRuleStart, transitionRuleEnd)
adjustmentList.Add(adjustment)
' Define rule 6 (for 1975 only)
transitionRuleStart = TimeZoneInfo.TransitionTime.CreateFixedDateRule(#2:00:00AM#, 02, 23)
adjustment = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(#01/01/1975#, #12/31/1975#, delta, transitionRuleStart, transitionRuleEnd)
adjustmentList.Add(adjustment)
' Define rule 7 (1976-1986)
transitionRuleStart = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(#2:00:00AM#, 04, 05, DayOfWeek.Sunday)
adjustment = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(#01/01/1976#, #12/31/1986#, delta, transitionRuleStart, transitionRuleEnd)
adjustmentList.Add(adjustment)
' Define rule 8 (1987-2006)  
transitionRuleStart = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(#2:00:00AM#, 04, 01, DayOfWeek.Sunday)
adjustment = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(#01/01/1987#, #12/31/2006#, delta, transitionRuleStart, transitionRuleEnd)
adjustmentList.Add(adjustment)
' Define rule 9 (2007- )  
transitionRuleStart = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(#2:00:00AM#, 03, 02, DayOfWeek.Sunday)
transitionRuleEnd = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(#2:00:00AM#, 11, 01, DayOfWeek.Sunday)
adjustment = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(#01/01/2007#, Date.MaxValue.Date, delta, transitionRuleStart, transitionRuleEnd)
adjustmentList.Add(adjustment)

' Convert list of adjustment rules to an array
Dim adjustments(adjustmentList.Count - 1) As TimeZoneInfo.AdjustmentRule
adjustmentList.CopyTo(adjustments)

cst = TimeZoneInfo.CreateCustomTimeZone("Central Standard Time", New TimeSpan(-6, 0, 0), _
      "(GMT-06:00) Central Time (US Only)", "Central Standard Time", _
      "Central Daylight Time", adjustments)

在此示例中创建的时区具有多个调整规则。The time zone created in this example has multiple adjustment rules. 必须小心,以确保任何调整规则的有效开始日期和结束日期不会与另一个调整规则的日期重叠。Care must be taken to ensure that the effective start and end dates of any adjustment rule do not overlap with the dates of another adjustment rule. 如果有重叠, InvalidTimeZoneException 则会引发。If there is an overlap, an InvalidTimeZoneException is thrown.

对于浮点调整规则,将值5传递给方法的 week 参数, CreateFloatingDateRule 以指示在特定月份的最后一周发生转换。For floating adjustment rules, the value 5 is passed to the week parameter of the CreateFloatingDateRule method to indicate that the transition occurs on the last week of a particular month.

在创建 TimeZoneInfo.AdjustmentRule 要在方法调用中使用的对象数组 TimeZoneInfo.CreateCustomTimeZone(String, TimeSpan, String, String, String, TimeZoneInfo+AdjustmentRule[]) 时,代码可以将数组初始化为要为时区创建的调整数所需的大小。In creating the array of TimeZoneInfo.AdjustmentRule objects to use in the TimeZoneInfo.CreateCustomTimeZone(String, TimeSpan, String, String, String, TimeZoneInfo+AdjustmentRule[]) method call, the code could initialize the array to the size required by the number of adjustments to be created for the time zone. 相反,此代码示例调用 Add 方法将每个调整规则添加到对象的泛型 List<T> 集合 TimeZoneInfo.AdjustmentRuleInstead, this code example calls the Add method to add each adjustment rule to a generic List<T> collection of TimeZoneInfo.AdjustmentRule objects. 然后,该代码调用 CopyTo 方法将此集合的成员复制到数组。The code then calls the CopyTo method to copy the members of this collection to the array.

该示例还使用 CreateFixedDateRule 方法定义固定日期调整。The example also uses the CreateFixedDateRule method to define fixed-date adjustments. 这类似于调用 CreateFloatingDateRule 方法,只需要转换参数的时间、月份和日期。This is similar to calling the CreateFloatingDateRule method, except that it requires only the time, month, and day of the transition parameters.

可以使用如下所示的代码测试该示例:The example can be tested using code such as the following:

TimeZoneInfo est = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");

DateTime pastDate1 = new DateTime(1942, 2, 11);
Console.WriteLine("Is {0} daylight saving time: {1}", pastDate1,
                  cst.IsDaylightSavingTime(pastDate1));

DateTime pastDate2 = new DateTime(1967, 10, 29, 1, 30, 00);
Console.WriteLine("Is {0} ambiguous: {1}", pastDate2,
                  cst.IsAmbiguousTime(pastDate2));

DateTime pastDate3 = new DateTime(1974, 1, 7, 2, 59, 00);
Console.WriteLine("{0} {1} is {2} {3}", pastDate3,
                  est.IsDaylightSavingTime(pastDate3) ?
                      est.DaylightName : est.StandardName,
                  TimeZoneInfo.ConvertTime(pastDate3, est, cst),
                  cst.IsDaylightSavingTime(TimeZoneInfo.ConvertTime(pastDate3, est, cst)) ?
                      cst.DaylightName : cst.StandardName);
//
// This code produces the following output to the console:
//
//    Is 2/11/1942 12:00:00 AM daylight saving time: True
//    Is 10/29/1967 1:30:00 AM ambiguous: True
//    1/7/1974 2:59:00 AM Eastern Standard Time is 1/7/1974 2:59:00 AM Central Daylight Time
Dim est As TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time")

Dim pastDate1 As Date = #2/11/1942#
Console.WriteLine("Is {0} daylight saving time: {1}", pastDate1, _
                  cst.IsDaylightSavingTime(pastDate1))

Dim pastDate2 As Date = #10/29/1967 1:30AM#
Console.WriteLine("Is {0} ambiguous: {1}", pastDate2, _
                  cst.IsAmbiguousTime(pastDate2))

Dim pastDate3 As Date = #1/7/1974 2:59AM#
Console.WriteLine("{0} {1} is {2} {3}", pastDate3, _
                  IIf(est.IsDaylightSavingTime(pastDate3), _
                      est.DaylightName, est.StandardName), _
                  TimeZoneInfo.ConvertTime(pastDate3, est, cst), _
                  IIf(cst.IsDaylightSavingTime(TimeZoneInfo.ConvertTime(pastDate3, est, cst)), _
                      cst.DaylightName, cst.StandardName))
'
' This code produces the following output to the console:
' 
'    Is 2/11/1942 12:00:00 AM daylight saving time: True
'    Is 10/29/1967 1:30:00 AM ambiguous: True
'    1/7/1974 2:59:00 AM Eastern Standard Time is 1/7/1974 2:59:00 AM Central Daylight Time                            

编译代码Compiling the code

此示例需要:This example requires:

  • 导入以下命名空间:That the following namespaces be imported:

    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    
    Imports System.Collections.Generic
    Imports System.Collections.ObjectModel
    
    

另请参阅See also