Procedura: Creare fusi orari con regole di regolazione

Le informazioni precise sul fuso orario richieste da un'applicazione potrebbero non essere presenti in un particolare sistema per diversi motivi:

  • Il fuso orario non è mai stato definito nel registro del sistema locale.

  • I dati relativi al fuso orario sono stati modificati o rimossi dal registro.

  • Il fuso orario non dispone di 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 usare gli overload di questo metodo per creare un fuso orario con o senza regole di rettifica. Se il fuso orario supporta l'ora legale, è possibile definire le regolazioni con regole di rettifica fisse o mobili. (Per le definizioni di questi termini, vedere la sezione "Terminologia dei fusi orari" in Panoramica dei fusi orari).

Importante

I fusi orari personalizzati creati chiamando il metodo CreateCustomTimeZone non vengono aggiunti al registro. È invece possibile accedervi solo tramite il riferimento all'oggetto restituito dalla chiamata al metodo CreateCustomTimeZone.

Questo argomento illustra come creare un fuso orario con regole di rettifica. Per creare un fuso orario che non supporti le regole di rettifica dell'ora legale, vedere Procedura: Creare fusi orari senza regole di rettifica.

Per creare un fuso orario con regole di rettifica float

  1. Per ogni rettifica, ovvero per ogni transizione da e verso l'ora solare in un determinato intervallo di tempo, eseguire le operazioni seguenti:

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

      È necessario chiamare il metodo TimeZoneInfo.TransitionTime.CreateFloatingDateRule e passargli un valore DateTime che definisce l'ora 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 rettifica del fuso orario. È necessaria 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 passarvi le date di inizio e fine effettive della rettifica, un oggetto TimeSpan che definisce la quantità di tempo nella transizione e i due oggetti TimeZoneInfo.TransitionTime che definiscono quando si verificano le transizioni verso e dall'ora legale. 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 abbastanza standard in cui l'offset del fuso orario dall'ora UTC (Coordinated Universal Time) è racchiuso tra parentesi ed è seguito da una stringa che identifica il fuso orario, una o più città o uno o più Paesi o aree geografiche nel fuso orario.

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

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

  5. Per usare un identificatore diverso dal nome standard del fuso orario, definire l'identificatore del fuso orario.

  6. Creare un'istanza di un oggetto TimeSpan che definisca l'offset del fuso orario dall'ora UTC. I fusi orari con orari successivi all'ora UTC hanno un offset positivo. I fusi orari con orari precedenti all'ora UTC hanno un offset negativo.

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

Esempio

Nell'esempio seguente viene definito un fuso orario standard centrale per gli Stati Uniti che include regole di rettifica per un'ampia gamma di intervalli di tempo compresi tra il 1918 e il presente.

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)

Il fuso orario creato in questo esempio include più regole di rettifica. Occorre prestare attenzione a garantire che le date di inizio e di fine effettive di qualsiasi regola di rettifica non si sovrappongano alle date di un'altra regola di rettifica. Se si verifica una sovrapposizione, viene generata un'eccezione InvalidTimeZoneException.

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

Nella creazione della matrice di oggetti TimeZoneInfo.AdjustmentRule da utilizzare nella chiamata al metodo TimeZoneInfo.CreateCustomTimeZone(String, TimeSpan, String, String, String, TimeZoneInfo+AdjustmentRule[]), il codice potrebbe inizializzare la matrice in base alle dimensioni richieste dal numero di rettifiche da creare per il fuso orario. In questo esempio di codice viene invece chiamato il metodo Add per aggiungere ogni regola di rettifica a una raccolta List<T> generica di oggetti TimeZoneInfo.AdjustmentRule. Il codice chiama quindi il metodo CopyTo per copiare i membri di questa raccolta nella matrice.

Nell'esempio viene inoltre utilizzato il metodo CreateFixedDateRule per definire le rettifiche a data fissa. Questa operazione è simile alla chiamata al metodo CreateFloatingDateRule, ad eccezione del fatto che richiede solo l'ora, il mese e il giorno dei parametri di transizione.

L'esempio può essere testato usando un codice simile al seguente:

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                            

Compilazione del codice

L'esempio presenta i requisiti seguenti:

  • Che verranno importati gli spazi dei nomi seguenti:

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

Vedi anche