C# - DateTime, timezone e formatação de datas


 Hoje vamos tratar com datas, time zones e formatação na linguagem C#.

Ao trabalhar com datas, você tem que ter muito cuidado, caso contrário pode causar problemas que podem afetar o seu sistema, se ele for sensível à utilização de datas.

Assim você sempre deve atentar para os fusos horários e usar as melhores práticas de formatação ou poderá ter problemas no seu código.

Neste artigo eu vou tratar também de fusos horários, e como moro no Brasil, meu horário oficial é UTC -3, e, isso significa que 5:00 UTC significa 2:00 no horário brasileiro. Lembre-se  que o Brasil usa 4 fusos horários variando de UTC-2 a UTC-5.

Criando um DateTime com a time zone correta

Você usa DateTime.Now para obter a data e a hora atuais ?

Se sim, lembre-se de que você está recebendo a hora local.

Isso pode causar problemas ao trocar datas com diferentes sistemas e fusos horários.

Para evitar isso, você deve usar DateTime.UtcNow.

        static void Main(string[] args)
        {
            var d = DateTime.UtcNow;            
            Console.WriteLine(d.ToString()); 
            Console.WriteLine(d.ToUniversalTime()); 
            Console.WriteLine(d.ToLocalTime()); 
            Console.ReadLine();
        }

Além disso, preste atenção ao definir um objeto DateTime usando o construtor.

Por padrão, ele se refere a um fuso horário não especificado.

Veja o exemplo a seguir:

  static void Main(string[] args)
  {
       var d = new DateTime(2020, 7, 30, 11, 55, 16);

       Console.WriteLine(d.ToString()); 
       Console.WriteLine(d.ToUniversalTime()); 
       Console.WriteLine(d.ToLocalTime()); 
       Console.ReadLine();
  }

Percebeu que os resultados das três strings possuem valores diferentes para a hora ?

É por isso que você deve considerar o uso de um construtor diferente:

DateTime (int year, int month, int day, int hour, int minute, int second, DateTimeKind kind).

Aqui Kind do tipo DateTimeKind é uma enumeração com 3 valores:

  1. Utc - representa a hora UTC
  2. Unspecified - A hora representada não é especificada como hora local ou UTC (Tempo Universal Coordenado).
  3. Local - representa a hora local

Nesse caso, você pode adicionar o sinalizador DateTimeKind ao construtor e configurá-lo como Utc.

Veja o resultado :

static void Main(string[] args)
{
     var d = new DateTime(2020, 7, 30, 12, 05, 26, DateTimeKind.Utc);
     Console.WriteLine(d.ToString()); 
     Console.WriteLine(d.ToUniversalTime());
     Console.WriteLine(d.ToLocalTime()); 
     Console.ReadLine();
}
 

Pode também definir o valor de Kind como Local:

static void Main(string[] args)
{
     var d = new DateTime(2020, 7, 30, 12, 05, 26, DateTimeKind.Local);
     Console.WriteLine(d.ToString()); 
     Console.WriteLine(d.ToUniversalTime());
     Console.WriteLine(d.ToLocalTime()); 
     Console.ReadLine();
}

Formatar atalhos e localização

Após obter a sua data você pode desejar convertê-la como uma string para exibir aos usuários.

Podemos formatar todas as partes da data: Veja a documentação oficial

Vejamos duas opções de formatação mais usadas no exemplo a seguir:

     static void Main(string[] args)
      {
            var d = new DateTime(2020, 7, 30, 12, 15, 26, DateTimeKind.Utc);

            Console.WriteLine(d.ToString("yyyy-MM-dd HH:mm:ss")); 
            Console.WriteLine(d.ToString("yyyy-MMMM-dd hh:mm:ss")); 
            Console.ReadLine();
      }

Observe como a diferença do resultado com MMMM em vez de MM e hh em vez de HH.

Além disso, você pode usar formatos predefinidos se estiver interessado apenas na hora ou na parte da data do objeto:

static void Main(string[] args)
{
  var d = new DateTime(2020, 7, 30, 12, 38, 16, DateTimeKind.Utc);

  Console.WriteLine(d.ToLongDateString()); 
  Console.WriteLine(d.ToLongTimeString()); 
  Console.ReadLine();
}

Os dois métodos usados chamam internamente o formatador, usando, respectivamente, D e T como formato.

Isso é um atalho, e você simplesmente não precisa se lembrar da sinalização de formatação mas tem uma desvantagem: DateTime.ToLongDateString e DateTime.ToLongTimeString não permitem que você especifique a cultura.

Portanto, se você deseja obter a data em outra cultura, deverá especificar a cultura.

No exemplo vamos exibir a data usando a cultura it-IT , Itália:

static void Main(string[] args)
{
    var d = new DateTime(2020, 7, 30, 12, 15, 26, DateTimeKind.Utc);

    Console.WriteLine(d.ToString("yyyy-MM-dd HH:mm:ss")); 
     var cultureInfo = new CultureInfo("it-IT");
     Console.WriteLine(d.ToString("D", cultureInfo)); 
     Console.ReadLine();
 }
 

Na verdade, se você consultar, o segundo parâmetro de ToString não é um objeto CultureInfo, mas qualquer classe que implemente a interface IFormatProvider.

Então você pode criar seu próprio formatador adequando o formato às necessidades do seu cliente.

Vamos continuar o assunto em outro artigo.

"Porque, como o relâmpago ilumina desde uma extremidade inferior do céu até à outra extremidade, assim será também o Filho do homem no seu dia."
Lucas 17:24

Referências:


José Carlos Macoratti