CodeGym /Cursos /C# SELF /Trabalhando com timezones:

Trabalhando com timezones: TimeZoneInfo

C# SELF
Nível 15 , Lição 2
Disponível

1. Introdução

Se você acha que timezone é só "somar/subtrair umas horas", logo vai sentir na pele a dor de quase todo programador do planeta. Fuso horário, mudança pra horário de verão/inverno, exceptions do nada quando tenta "converter hora pra outra região" — tudo isso pode virar bug difícil de achar e mais difícil ainda de explicar pro usuário.

O pior: não existe e nunca existiu um "jeitão universal" de lidar com hora — tipo, dois países vizinhos podem tratar horário de verão de jeitos diferentes, e às vezes decidem mudar isso no meio do ano (sim, acontece de verdade!). Exemplo: em 2011, Samoa "pulou" um dia inteiro e trocou de lado na linha internacional de data.

Mas C# e .NET têm ferramentas poderosas pra pelo menos tentar domar esse caos. Hoje vamos conhecer nosso salvador — o tipo TimeZoneInfo e suas funções que vão te ajudar (e ao seu app).

Quando e por que você precisa lidar com timezones

  • Quando usuários/servidores estão em regiões diferentes do mundo
  • Quando você salva data e hora no banco em UTC, mas mostra pro usuário no horário local dele
  • Pra calcular agendas, lembretes, eventos online ("O webinar começa às 19:00 em Berlim — e aí, que horas vai ser pra você?")
  • Ao desenvolver sistemas corporativos/globais (tipo contabilidade ou CRM pra empresa internacional)

Visão geral do tipo TimeZoneInfo

TimeZoneInfo é uma classe feita especialmente no .NET pra representar info de fuso horário: o offset em relação ao UTC, nome, suporte a horário de verão e por aí vai.

Diferente da classe antiga TimeZone, que só sabe do timezone "local" e "UTC", TimeZoneInfo te dá acesso completo a todos os timezones registrados no sistema (e até uns custom, criados na mão).

2. Pegando informações de timezones

Timezone local e UTC

Pegar info do timezone local é moleza:


// Local (ou seja, onde seu programa tá rodando agora)
TimeZoneInfo local = TimeZoneInfo.Local;

// Sempre UTC
TimeZoneInfo utc = TimeZoneInfo.Utc;

Console.WriteLine(local.DisplayName); // Tipo: (UTC+01:00) Berlin, Vienna
Console.WriteLine(utc.DisplayName);   // (UTC) Coordinated Universal Time

Todos os timezones disponíveis

Às vezes você precisa mostrar pro usuário a lista de todos os timezones possíveis (tipo na hora de cadastrar no serviço):


foreach (var tz in TimeZoneInfo.GetSystemTimeZones())
{
    Console.WriteLine($"{tz.Id} | {tz.DisplayName}");
}

Isso vai printar uma lista tipo:

  • Central European Standard Time | (UTC+01:00) Berlin, Vienna
  • Pacific Standard Time | (UTC-08:00) Pacific Time (US & Canada)
  • e por aí vai.

Visualizando: principais propriedades do TimeZoneInfo

Propriedade Descrição
Id
Identificador do sistema pro timezone (usado pra buscar)
DisplayName
Descrição pro usuário (com horas e cidades)
StandardName
Nome do horário "normal"
DaylightName
Nome do horário de verão
BaseUtcOffset
Offset em relação ao UTC (tipo, +01:00 pra Berlim)
SupportsDaylightSavingTime
True se o timezone suporta horário de verão/inverno

3. Convertendo hora entre timezones

É pra isso tudo que serve! Você precisa:

  • Converter hora de uma zona pra outra (tipo, o servidor salvou em UTC, mas mostra pro usuário no timezone dele)
  • Lidar direito com horário de verão/inverno

Sintaxe geral


DateTime utcNow = DateTime.UtcNow;

// Por exemplo, vamos converter essa hora pro timezone da Europa Central
TimeZoneInfo europeZone = TimeZoneInfo.FindSystemTimeZoneById("Central European Standard Time");
DateTime europeTime = TimeZoneInfo.ConvertTimeFromUtc(utcNow, europeZone);

Console.WriteLine($"UTC now: {utcNow}");       // 2024-06-20 10:30:00
Console.WriteLine($"Europe now: {europeTime}"); // 2024-06-20 11:30:00

Importante: Sempre use UTC pra cálculos internos e armazenamento, e só converta pra timezone do usuário na hora de mostrar!

Como descobrir o identificador do timezone?

No Windows, os identificadores (Id) dos timezones são específicos (tipo "Central European Standard Time"), já no Linux/Unix — normalmente são os IANA/Olson ("Europe/Berlin", "America/New_York").

Você pode pegar a lista de identificadores do seu sistema usando TimeZoneInfo.GetSystemTimeZones().

4. Convertendo entre zonas aleatórias

Digamos que você pegou uma hora de Londres (GMT/UTC+0) e quer converter pra Tóquio (UTC+9):


DateTime londonTime = new DateTime(2024, 6, 20, 12, 0, 0, DateTimeKind.Unspecified);

TimeZoneInfo londonZone = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
TimeZoneInfo tokyoZone  = TimeZoneInfo.FindSystemTimeZoneById("Tokyo Standard Time");

// Primeiro passo: converte pra UTC (se for local)
DateTime utc = TimeZoneInfo.ConvertTimeToUtc(londonTime, londonZone);

// Segundo passo: converte UTC pra hora de Tóquio
DateTime tokyoTime = TimeZoneInfo.ConvertTimeFromUtc(utc, tokyoZone);

Console.WriteLine($"London: {londonTime} | UTC: {utc} | Tokyo: {tokyoTime}");

Lidando com horário de verão e inverno

TimeZoneInfo leva em conta horário de verão/inverno — se o timezone suportar isso.


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

DateTime dateWinter = new DateTime(2024, 1, 1, 12, 0, 0, DateTimeKind.Unspecified);
DateTime dateSummer = new DateTime(2024, 7, 1, 12, 0, 0, DateTimeKind.Unspecified);

Console.WriteLine( TimeZoneInfo.ConvertTimeToUtc(dateWinter, eastern)); // Offset UTC-5
Console.WriteLine( TimeZoneInfo.ConvertTimeToUtc(dateSummer, eastern)); // Offset UTC-4 — horário de verão!

Mesmo se os EUA (do exemplo acima) resolverem acabar com o horário de verão (e todo ano rola essa discussão!), a base de timezones do seu SO vai ser atualizada, e seu código vai continuar funcionando certo.

5. Dicas práticas e erros comuns

Exceptions e pegadinhas

  • No momento da mudança de horário (tipo, 2:30 da manhã no dia da troca pro horário de verão/inverno), alguns horários podem ser "inexistentes" ou "repetidos":
    Por exemplo, no dia de atrasar o relógio, 2:30 acontece duas vezes — e cada uma é diferente.
  • Lembra: a lista de timezones pode mudar com updates do SO! Exemplo: alguns países cancelam/implementam horário de verão.
2
Tarefa
C# SELF, nível 15, lição 2
Bloqueado
Exibindo o fuso horário local e UTC
Exibindo o fuso horário local e UTC
2
Tarefa
C# SELF, nível 15, lição 2
Bloqueado
Conversão de horário entre dois fusos horários
Conversão de horário entre dois fusos horários
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION