Como: enumerar os fusos horários presentes em um computador

Trabalhar com êxito com um fuso horário designado requer que informações sobre o fuso horário em questão estejam disponíveis no sistema. Os sistemas operacionais Windows XP e Windows Vista armazenam essas informações no registro. Embora o número total de fusos horários existentes seja grande, o Registro contém informações apenas sobre um subconjunto deles. Além disso, o Registro em si é uma estrutura dinâmica cujo conteúdo está sujeito a alterações deliberadas ou acidentais. Como resultado, um aplicativo nem sempre pode presumir que um determinado fuso horário esteja definido e disponível no sistema. A primeira etapa para muitos aplicativos que usam informações de fuso horário é determinar se os fusos horários necessários estão disponíveis no sistema local ou dar ao usuário uma lista dos fusos horários entre os quais escolher. Isso requer que o aplicativo enumere os fusos horários definidos no sistema local.

Observação

Se um aplicativo depende da presença de um fuso horário específico que pode não estar definido em um sistema local, o aplicativo poderá garantir sua presença serializando e desserializando informações sobre o fuso horário. O fuso horário então pode ser adicionado a um controle de lista para que o usuário do aplicativo possa selecioná-lo. Para detalhes, confira Como salvar fusos horários em um recurso inserido e Como restaurar fusos horários de um recurso inserido.

Para enumerar os fusos horários presentes no sistema local

  1. Chame o método TimeZoneInfo.GetSystemTimeZones . O método retorna uma coleção ReadOnlyCollection<T> genérica de objetos TimeZoneInfo. As entradas na coleção são classificadas pela propriedade DisplayName. Por exemplo:

    ReadOnlyCollection<TimeZoneInfo> tzCollection;
    tzCollection = TimeZoneInfo.GetSystemTimeZones();
    
    Dim tzCollection As ReadOnlyCollection(Of TimeZoneInfo) = TimeZoneInfo.GetSystemTimeZones
    
  2. Enumere os objetos TimeZoneInfo individuais na coleção usando um loop foreache (em C#) ou um For Each…Loop Next (no Visual Basic) e realize qualquer processamento necessário em cada objeto. Por exemplo, o código a seguir enumera a coleção ReadOnlyCollection<T>de objetos TimeZoneInfo retornados na etapa 1 e lista o nome de exibição de cada fuso horário no console.

    foreach (TimeZoneInfo timeZone in tzCollection)
        Console.WriteLine($"   {timeZone.Id}: {timeZone.DisplayName}");
    
    For Each timeZone As TimeZoneInfo In tzCollection
        Console.WriteLine("   {0}: {1}", timeZone.Id, timeZone.DisplayName)
    Next
    

Para apresentar ao usuário uma lista de fusos horários presentes no sistema local

  1. Chame o método TimeZoneInfo.GetSystemTimeZones . O método retorna uma coleção ReadOnlyCollection<T> genérica de objetos TimeZoneInfo.

  2. Atribua a coleção retornada na etapa 1 à propriedade DataSource de um controle de lista do ASP.NET ou Windows Forms.

  3. Recupere o objeto TimeZoneInfo que o usuário selecionou.

O exemplo apresenta uma ilustração para um aplicativo do Windows.

Exemplo

O exemplo inicia um aplicativo do Windows que exibe os fusos horários definidos em um sistema em uma caixa de listagem. O exemplo então exibe uma caixa de diálogo que contém o valor da propriedade DisplayName do objeto de fuso horário selecionado pelo usuário.

private void Form1_Load(object sender, EventArgs e)
{
    ReadOnlyCollection<TimeZoneInfo> tzCollection;
    tzCollection = TimeZoneInfo.GetSystemTimeZones();
    _timeZoneList.DataSource = tzCollection;
}

private void OkButton_Click(object sender, EventArgs e)
{
    TimeZoneInfo? selectedTimeZone = (TimeZoneInfo?)_timeZoneList.SelectedItem;
    MessageBox.Show($"You selected the {selectedTimeZone?.ToString()} time zone.");
}
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Dim tzCollection As ReadOnlyCollection(Of TimeZoneInfo)
    tzCollection = TimeZoneInfo.GetSystemTimeZones()
    Me.timeZoneList.DataSource = tzCollection
End Sub

Private Sub OkButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles OkButton.Click
    Dim selectedTimeZone As TimeZoneInfo = DirectCast(Me.timeZoneList.SelectedItem(), TimeZoneInfo)
    MsgBox("You selected the " & selectedTimeZone.ToString() & " time zone.")
End Sub

A maioria dos controles de lista (como o controle System.Windows.Forms.ListBox ou System.Web.UI.WebControls.BulletedList) permite que você atribua uma coleção de variáveis de objeto à propriedade DataSource, desde que essa coleção implemente a interface IEnumerable. (A classe genérica ReadOnlyCollection<T> faz isso.) Para exibir um objeto individual na coleção, o controle chama o método desse objeto ToString para extrair a cadeia de caracteres usada para representar o objeto. No caso de objetos TimeZoneInfo, o método ToString retorna o nome de exibição do objeto TimeZoneInfo (o valor de sua propriedade DisplayName).

Observação

Como os controles de lista chamam o método de um objeto ToString, você pode atribuir uma coleção de objetos TimeZoneInfo ao controle, fazer com que o controle exiba um nome significativo para cada objeto e recuperar o objeto TimeZoneInfo selecionado pelo usuário. Isso elimina a necessidade de extrair uma cadeia de caracteres para cada objeto na coleção, atribuir a cadeia de caracteres a uma coleção que, por sua vez, é atribuída à propriedade do controle DataSource, recuperar a cadeia de caracteres selecionada pelo usuário e então usar essa cadeia de caracteres para extrair o objeto que ela descreve.

Compilando o código

Este exemplo requer:

Confira também