Procedimiento para crear zonas horarias con reglas de ajuste

Es posible que la información precisa de zona horaria que necesita una aplicación no esté presente en un sistema determinado por varias razones:

  • La zona horaria nunca se ha definido en el registro del sistema local.

  • Los datos sobre la zona horaria se han modificado o quitado del registro.

  • La zona horaria no tiene información precisa sobre los ajustes de zona horaria de un período histórico determinado.

En estos casos, puede llamar al método CreateCustomTimeZone para definir la zona horaria que necesita la aplicación. Puede usar las sobrecargas de este método para crear una zona horaria con o sin reglas de ajuste. Si la zona horaria admite el horario de verano, puede definir ajustes con reglas de ajuste fijas o flotantes. (Para consultar las definiciones de estos términos, vea la sección "Terminología de zona horaria" de Información general sobre zonas horarias).

Importante

Las zonas horarias personalizadas creadas mediante una llamada al método CreateCustomTimeZone no se agregan al registro. sino que solo se puede acceder a ellas por medio de la referencia de objeto devuelta por la llamada de método CreateCustomTimeZone.

En este tema se muestra cómo crear una zona horaria con reglas de ajuste. Para crear una zona horaria que no admita reglas de ajuste de horario de verano, vea Procedimiento para crear zonas horarias sin reglas de ajuste.

Para crear una zona horaria con reglas de ajuste flotantes

  1. En cada ajuste (es decir, en cada transición de y hacia el tiempo estándar a lo largo de un intervalo de tiempo determinado), haga lo siguiente:

    1. Defina la hora de transición inicial del ajuste de zona horaria.

      Debe llamar al método TimeZoneInfo.TransitionTime.CreateFloatingDateRule y pasarle un valor DateTime que defina la hora de la transición, un valor entero que defina el mes de la transición, un valor entero que defina la semana en la que se produce la transición y un valor DayOfWeek que defina el día de la semana en que se produce la transición. Esta llamada de método crea una instancia de un objeto TimeZoneInfo.TransitionTime.

    2. Defina la hora de transición final del ajuste de zona horaria. Esto requiere otra llamada al método TimeZoneInfo.TransitionTime.CreateFloatingDateRule. Esta llamada de método crea una instancia de un segundo objeto TimeZoneInfo.TransitionTime.

    3. Llame al método CreateAdjustmentRule y pásele las fechas de inicio y finalización efectivas del ajuste, un objeto TimeSpan que defina la cantidad de tiempo de la transición y los dos objetos TimeZoneInfo.TransitionTime que definen cuándo se producen las transiciones a y desde el horario de verano. Esta llamada de método crea una instancia de un objeto TimeZoneInfo.AdjustmentRule.

    4. Asigne el objeto TimeZoneInfo.AdjustmentRule a una matriz de objetos TimeZoneInfo.AdjustmentRule.

  2. Defina el nombre para mostrar de la zona horaria. El nombre para mostrar sigue un formato bastante estándar en el que el desajuste de la zona horaria con respecto a la hora universal coordinada (UTC) se incluye entre paréntesis y va seguido de una cadena que identifica la zona horaria, una o varias de las ciudades de la zona horaria, o uno o varios de los países o regiones de la zona horaria.

  3. Defina el nombre de la hora estándar de la zona horaria. Normalmente, esta cadena también se usa como identificador de la zona horaria.

  4. Defina el nombre de la hora de verano de la zona horaria.

  5. Si quiere usar un identificador diferente al nombre estándar de la zona horaria, defina el identificador de zona horaria.

  6. Cree una instancia de un objeto TimeSpan que defina el desajuste de la zona horaria con respecto a UTC. Las zonas horarias con horas posteriores a UTC tienen un desajuste positivo. Las zonas horarias con horas anteriores a UTC tienen un desajuste negativo.

  7. Llame al método TimeZoneInfo.CreateCustomTimeZone(String, TimeSpan, String, String, String, TimeZoneInfo+AdjustmentRule[]) para crear una instancia de la nueva zona horaria.

Ejemplo

En el ejemplo siguiente se define una zona de Hora estándar central para los Estados Unidos que incluye reglas de ajuste para diversos intervalos de tiempo desde 1918 hasta la actualidad.

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)

La zona horaria creada en este ejemplo tiene varias reglas de ajuste. Se debe tener cuidado para garantizar que las fechas de inicio y finalización efectivas de cualquier regla de ajuste no se superpongan con las fechas de otra regla de ajuste. Si hay una superposición, se inicia una excepción InvalidTimeZoneException.

En el caso de las reglas de ajuste flotantes, se pasa el valor 5 al parámetro week del método CreateFloatingDateRule para indicar que la transición se produce durante la última semana de un mes determinado.

Al crear la matriz de objetos TimeZoneInfo.AdjustmentRule que se van a usar en la llamada de método TimeZoneInfo.CreateCustomTimeZone(String, TimeSpan, String, String, String, TimeZoneInfo+AdjustmentRule[]), el código podría inicializar la matriz en el tamaño requerido por el número de ajustes que se van a crear para la zona horaria. En su lugar, este ejemplo de código llama al método Add para agregar cada regla de ajuste a una colección genérica List<T> de objetos TimeZoneInfo.AdjustmentRule. Luego el código llama al método CopyTo para copiar los miembros de esta colección en la matriz.

En el ejemplo también se usa el método CreateFixedDateRule para definir ajustes de fecha fija. Esto es similar a llamar al método CreateFloatingDateRule, salvo que solo requiere la hora, el mes y el día de los parámetros de la transición.

El ejemplo se puede probar mediante código como el siguiente:

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                            

Compilación del código

Para este ejemplo se necesita:

  • Que se importen los siguientes espacios de nombres:

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

Consulte también