Condividi tramite


Procedura: creare fusi orari con regole di regolazione

Aggiornamento: novembre 2007

Le informazioni precise del fuso orario richieste da un'applicazione possono non essere presenti in un determinato sistema per molte ragioni:

  • Il fuso orario non è mai stato definito nel Registro di sistema locale.

  • I dati sul fuso orario sono stati modificati o rimossi dal Registro di sistema.

  • Il fuso orario non ha informazioni accurate sulle regolazioni del fuso orario per un determinato periodo storico.

In questi casi, è possibile chiamare il metodo CreateCustomTimeZone per definire il fuso orario richiesto dall'applicazione. È possibile utilizzare gli overload di questo metodo per creare un fuso orario con o senza regole di regolazione. Se il fuso orario supporta l'ora legale, è possibile definire le regolazioni con regole di regolazione fisse o mobili. Per le definizioni di questi termini, vedere la sezione "Terminologia relativa al fuso orario" in Panoramica sul fuso orario.

Nota importante:

I fusi orari personalizzati creati chiamando il metodo CreateCustomTimeZone non vengono aggiunti al Registro di sistema, ma è possibile accedervi solo tramite il riferimento all'oggetto restituito dalla chiamata al metodo CreateCustomTimeZone.

In questo argomento viene illustrato come creare un fuso orario con regole di regolazione. Per creare un fuso orario che non supporta le regole di regolazione dell'ora legale, vedere Procedura: creare fusi orari senza regole di regolazione.

Per creare un fuso orario con le regole di regolazione mobili

  1. Per ogni regolazione, ovvero per ogni transizione da ora solare e viceversa in un determinato intervallo di tempo, effettuare le operazioni seguenti:

    1. Definire il tempo di transizione iniziale per la regolazione del fuso orario.

      È necessario chiamare il metodo TimeZoneInfo.TransitionTime.CreateFloatingDateRule e passare un valore DateTime che definisce il tempo della transizione, un valore intero che definisce il mese della transizione, un valore intero che definisce la settimana in cui si verifica la transizione e un valore DayOfWeek che definisce il giorno della settimana in cui si verifica la transizione. Questa chiamata al metodo crea un'istanza di un oggetto TimeZoneInfo.TransitionTime.

    2. Definire il tempo di transizione finale per la regolazione del fuso orario. Richiede un'altra chiamata al metodo TimeZoneInfo.TransitionTime.CreateFloatingDateRule. Questa chiamata al metodo crea un'istanza di un secondo oggetto TimeZoneInfo.TransitionTime.

    3. Chiamare il metodo CreateAdjustmentRule e passare le date effettive di inizio e di fine della regolazione, un oggetto TimeSpan che definisce il periodo della transizione e i due oggetti TimeZoneInfo.TransitionTime che definiscono quando si verifica la transizione da ora solare a ora legale e viceversa. Questa chiamata al metodo crea un'istanza di un oggetto TimeZoneInfo.AdjustmentRule.

    4. Assegnare l'oggetto TimeZoneInfo.AdjustmentRule a una matrice di oggetti TimeZoneInfo.AdjustmentRule.

  2. Definire il nome visualizzato del fuso orario. Il nome visualizzato segue un formato quasi standard in cui l'offset del fuso orario dall'ora UTC (Coordinated Universal Time) viene racchiuso tra parentesi e seguito da una stringa che identifica il fuso orario, una o più città del fuso orario o uno o più paesi o regioni del fuso orario.

  3. Definire il nome dell'ora solare del fuso orario. In genere questa stringa viene utilizzata anche come identificatore del fuso orario.

  4. Definire il nome dell'ora legale del fuso orario.

  5. Se si desidera utilizzare un identificatore diverso dal nome standard del fuso orario, definire l'identificatore del fuso orario.

  6. Creare un'istanza di un oggetto TimeSpan che definisce l'offset del fuso orario dall'ora UTC. I fusi orari con ore in avanti rispetto all'ora UTC hanno un offset positivo. I fusi orari con ore indietro rispetto all'ora UTC hanno un offset negativo.

  7. Chiamare il metodo TimeZoneInfo.CreateCustomTimeZone(String, TimeSpan, String, String, String, array<TimeZoneInfo.AdjustmentRule[]) per creare un'istanza del nuovo fuso orario.

Esempio

Nell'esempio seguente viene definito un fuso Ora solare fuso centrale per gli Stati Uniti che include le regole di regolazione per una varietà di intervalli di tempo dal 1918 a oggi.

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)
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);

Il fuso orario creato in questo esempio ha più regole di regolazione. È necessario pertanto assicurarsi che le date effettive di inizio e di fine di una regola di regolazione non si sovrappongono con le date di un'altra regola. In caso di sovrapposizione, viene generata un'eccezione InvalidTimeZoneException.

Per le regole di regolazione mobili, viene passato il valore 5 al parametro week del metodo CreateFloatingDateRule indicando che la transizione si verifica nell'ultima settimana di un determinato mese.

Nel creare la matrice di oggetti TimeZoneInfo.AdjustmentRule da utilizzare nella chiamata al metodo TimeZoneInfo.CreateCustomTimeZone(String, TimeSpan, String, String, String, array<TimeZoneInfo.AdjustmentRule[]), la matrice è stata inizializzata in base alla dimensione richiesta dal numero di regolazioni da creare per il fuso orario. In questo esempio di codice invece viene chiamato il metodo Add per aggiungere ogni regola di regolazione a un insieme List<T> generico di oggetti TimeZoneInfo.AdjustmentRule. Viene quindi chiamato il metodo CopyTo per copiare i membri di questo insieme nella matrice.

Nell'esempio viene anche utilizzato il metodo CreateFixedDateRule per definire regolazioni a data fissa. Equivale a chiamare il metodo CreateFloatingDateRule, con l'unica differenza che è necessario fornire solo l'ora, il mese e il giorno come parametri di transizione.

È possibile eseguire il test di questo esempio utilizzando un codice analogo al seguente:

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                            
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                            

Compilazione del codice

Per questo esempio è necessario:

  • Aggiungere un riferimento a System.Core.dll al progetto.

  • Importare gli spazi dei nomi seguenti:

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

Vedere anche

Attività

Procedura: creare fusi orari senza regole di regolazione

Concetti

Panoramica sul fuso orario

Altre risorse

Ora e fusi orari