Compartilhar via


Como: Use fusos horários na data e time Arithmetic

Normalmente, ao executar aritmética de data e hora usando valoresDateTime ou DateTimeOffset, o resultado não reflete quaisquer regras de ajuste da zona de tempo.Isso é verdade mesmo quando a zona de tempo do valor de data e tempo é claramente identificável (por exemplo, quando a propriedade Kind é definida como Local).Este tópico mostra como executar operações aritméticas em valores de data e hora que pertencem a uma determinada zona de tempo.Os resultados das operações aritméticas refletirá as regras de ajuste da zona de tempo.

Para aplicar as regras de ajuste para aritmética de data e hora

  1. Implemente algum método ao acoplar estritamente um valor de data e tempo com a zona de tempo ao qual ele pertence.Por exemplo, declare uma estrutura que inclui ambos o valor de data e tempo e a sua zona de tempo.O exemplo a seguir usa essa abordagem para vincular um valor DateTime com sua zona de tempo.

    ' Define a structure for DateTime values for internal use only
    Friend Structure TimeWithTimeZone
       Dim TimeZone As TimeZoneInfo
       Dim Time As Date
    End Structure
    
    // Define a structure for DateTime values for internal use only
    internal struct TimeWithTimeZone
    {
       TimeZoneInfo TimeZone;
       DateTime Time;
    }
    
  2. Converta um horário Tempo Universal Coordenado (UTC), chamando o método ConvertTimeToUtc ou o método ConvertTime.

  3. Execute a operação aritmética na hora UTC.

  4. Converta a hora de UTC para a zona de tempo associada a hora original chamando o método TimeZoneInfo.ConvertTime(DateTime, TimeZoneInfo).

Exemplo

O exemplo seguinte adiciona duas horas e trinta minutos 9 de março de 2008, no 1 h 30.time padrão de central.Trinta minutos mais tarde, de ocorre a transição de fuso horário's para horário de verão, às 2: 00.em 9 de março de 2008.sistema autônomo o exemplo a segue sistema autônomo quatro etapas listadas na seção anterior, ele reporta corretamente o resultante time sistema autônomo 5 hem 9 de março de 2008.

Public Structure TimeZoneTime
   Public TimeZone As TimeZoneInfo
   Public Time As Date

   Public Sub New(tz As TimeZoneInfo, time As Date)
      If tz Is Nothing Then _
         Throw New ArgumentNullException("The time zone cannot be a null reference.")

      Me.TimeZone = tz
      Me.Time = time
   End Sub

   Public Function AddTime(interval As TimeSpan) As TimeZoneTime
      ' Convert time to UTC
      Dim utcTime As DateTime = TimeZoneInfo.ConvertTimeToUtc(Me.Time, _
                                                              Me.TimeZone)      
      ' Add time interval to time
      utcTime = utcTime.Add(interval)
      ' Convert time back to time in time zone
      Return New TimeZoneTime(Me.TimeZone, TimeZoneInfo.ConvertTime(utcTime, _
                              TimeZoneInfo.Utc, Me.TimeZone))
   End Function
End Structure

Module TimeArithmetic
   Public Const tzName As String = "Central Standard Time"

   Public Sub Main()
      Try
         Dim cstTime1, cstTime2 As TimeZoneTime

         Dim cst As TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(tzName)
         Dim time1 As Date = #03/09/2008 1:30AM#
         Dim twoAndAHalfHours As New TimeSpan(2, 30, 0)

         cstTime1 = New TimeZoneTime(cst, time1)
         cstTime2 = cstTime1.AddTime(twoAndAHalfHours)

         Console.WriteLine("{0} + {1} hours = {2}", cstTime1.Time, _
                                                    twoAndAHalfHours.ToString(), _ 
                                                    cstTime2.Time)  
      Catch
         Console.WriteLine("Unable to find {0}.", tzName)
      End Try   
   End Sub   
End Module
using System;

public struct TimeZoneTime
{
   public TimeZoneInfo TimeZone;
   public DateTime Time;

   public TimeZoneTime(TimeZoneInfo tz, DateTime time)
   {
      if (tz == null) 
         throw new ArgumentNullException("The time zone cannot be a null reference.");

      this.TimeZone = tz;
      this.Time = time;   
   }

   public TimeZoneTime AddTime(TimeSpan interval)
   {
      // Convert time to UTC
      DateTime utcTime = TimeZoneInfo.ConvertTimeToUtc(this.Time, this.TimeZone);
      // Add time interval to time
      utcTime = utcTime.Add(interval);
      // Convert time back to time in time zone
      return new TimeZoneTime(this.TimeZone, TimeZoneInfo.ConvertTime(utcTime, 
                              TimeZoneInfo.Utc, this.TimeZone));
   }
}

public class TimeArithmetic
{
   public const string tzName = "Central Standard Time";

   public static void Main()
   {
      try
      {
         TimeZoneTime cstTime1, cstTime2;

         TimeZoneInfo cst = TimeZoneInfo.FindSystemTimeZoneById(tzName);
         DateTime time1 = new DateTime(2008, 3, 9, 1, 30, 0);          
         TimeSpan twoAndAHalfHours = new TimeSpan(2, 30, 0);

         cstTime1 = new TimeZoneTime(cst, time1);
         cstTime2 = cstTime1.AddTime(twoAndAHalfHours);
         Console.WriteLine("{0} + {1} hours = {2}", cstTime1.Time, 
                                                    twoAndAHalfHours.ToString(),  
                                                    cstTime2.Time);
      }
      catch
      {
         Console.WriteLine("Unable to find {0}.", tzName);
      }
   }
}

Os dois valores DateTime e DateTimeOffset serão desassociadas de qualquer zona de tempo às quais eles podem pertencer.Para executar aritmética de data e hora de forma que automaticamente se aplique as regras de ajuste de uma zona de tempo, a zona de tempo a qual um valor qualquer de data e tempo pertence deve ser imediatamente identificável.Isso significa que uma data e hora e sua zona de tempo associada devem ser fortemente agrupados.Há várias maneiras para fazer isso, que incluem o seguinte:

  • Suponha que todos os horários usados em um aplicativo pertencem a uma determinada zona de tempo.Embora adequado em alguns casos, essa abordagem oferece flexibilidade limitada e possivelmente portabilidade limitada.

  • Definir um tipo que agrupa rigidamente uma data e hora com sua zona de tempo associada, incluindo os dois como campos do tipo.Essa abordagem é usada no exemplo de código, que define uma estrutura para armazenar a data e hora e a zona de tempo em dois campos membro.

O exemplo ilustra como executar operações aritméticas em valores DateTime para que as regras de ajuste da zona de tempo sejam aplicadas ao resultado.No entanto, valores DateTimeOffset também podem ser usados da mesma forma facilmente.O exemplo a seguir ilustra como o código de exemplo original pode ser adaptado para usar valores DateTimeOffset em vez de valores DateTime.

Public Structure TimeZoneTime
   Public TimeZone As TimeZoneInfo
   Public Time As DateTimeOffset

   Public Sub New(tz As TimeZoneInfo, time As DateTimeOffset)
      If tz Is Nothing Then _
         Throw New ArgumentNullException("The time zone cannot be a null reference.")

      Me.TimeZone = tz
      Me.Time = time
   End Sub

   Public Function AddTime(interval As TimeSpan) As TimeZoneTime
      ' Convert time to UTC
      Dim utcTime As DateTimeOffset = TimeZoneInfo.ConvertTime(Me.Time, TimeZoneInfo.Utc)      
      ' Add time interval to time
      utcTime = utcTime.Add(interval)
      ' Convert time back to time in time zone
      Return New TimeZoneTime(Me.TimeZone, TimeZoneInfo.ConvertTime(utcTime, Me.TimeZone))
   End Function
End Structure

Module TimeArithmetic
   Public Const tzName As String = "Central Standard Time"

   Public Sub Main()
      Try
         Dim cstTime1, cstTime2 As TimeZoneTime

         Dim cst As TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(tzName)
         Dim time1 As Date = #03/09/2008 1:30AM#
         Dim twoAndAHalfHours As New TimeSpan(2, 30, 0)

         cstTime1 = New TimeZoneTime(cst, _
                        New DateTimeOffset(time1, cst.GetUtcOffset(time1)))
         cstTime2 = cstTime1.AddTime(twoAndAHalfHours)

         Console.WriteLine("{0} + {1} hours = {2}", cstTime1.Time, _
                                                    twoAndAHalfHours.ToString(), _ 
                                                    cstTime2.Time)  
      Catch
         Console.WriteLine("Unable to find {0}.", tzName)
      End Try   
   End Sub   
End Module
using System;

public struct TimeZoneTime
{
   public TimeZoneInfo TimeZone;
   public DateTimeOffset Time;

   public TimeZoneTime(TimeZoneInfo tz, DateTimeOffset time)
   {
      if (tz == null) 
         throw new ArgumentNullException("The time zone cannot be a null reference.");

      this.TimeZone = tz;
      this.Time = time;   
   }

   public TimeZoneTime AddTime(TimeSpan interval)
   {
      // Convert time to UTC
      DateTimeOffset utcTime = TimeZoneInfo.ConvertTime(this.Time, TimeZoneInfo.Utc);      
      // Add time interval to time
      utcTime = utcTime.Add(interval);
      // Convert time back to time in time zone
      return new TimeZoneTime(this.TimeZone, TimeZoneInfo.ConvertTime(utcTime, this.TimeZone));
   }
}

public class TimeArithmetic
{
   public const string tzName = "Central Standard Time";

   public static void Main()
   {
      try
      {
         TimeZoneTime cstTime1, cstTime2;

         TimeZoneInfo cst = TimeZoneInfo.FindSystemTimeZoneById(tzName);
         DateTime time1 = new DateTime(2008, 3, 9, 1, 30, 0);          
         TimeSpan twoAndAHalfHours = new TimeSpan(2, 30, 0);

         cstTime1 = new TimeZoneTime(cst, 
                        new DateTimeOffset(time1, cst.GetUtcOffset(time1)));
         cstTime2 = cstTime1.AddTime(twoAndAHalfHours);
         Console.WriteLine("{0} + {1} hours = {2}", cstTime1.Time, 
                                                    twoAndAHalfHours.ToString(),  
                                                    cstTime2.Time);
      }
      catch
      {
         Console.WriteLine("Unable to find {0}.", tzName);
      }
   }
}

Observe que se esta adição simplesmente é realizada no valor DateTimeOffset sem antes convertê-lo ao UTC, o resultado reflete o ponto correto no tempo, mas seu deslocamento não reflete o mesmo que a zona de tempo designada para esse horário deveria apresentar.

Compilando o código

Este exemplo requer:

  • Que uma referência a System.Core.dll seja adicionada ao projeto.

  • Que o namespace System seja importado com a instrução using (necessária em código C#).

Consulte também

Conceitos

Executando Operações Aritméticas com Datas e Horas

Outros recursos

Horários e Zonas de Tempo