Executando Operações Aritméticas com Datas e Horas
Embora tanto as estruturas DateTime quanto as DateTimeOffset forneçam membros que executam operações aritméticas em seus valores, os resultados das operações aritméticas são muito diferentes.Este tópico examina essas diferenças, relaciona-as ao grau de consciência da zona de tempo em dados de data e hora e descreve como realizar operações de zona de tempo totalmente cientes usando dados de data e hora.
Comparações e operações aritméticas com valores de dateTime
A partir do .NET Framework versão 2.0, valores DateTime possuem um grau limitado de consciência da zona de tempo.A propriedade DateTime.Kind permite que um valor DateTimeKind a ser atribuído à data e hora para indicar se ele representa hora local, Tempo Universal Coordenado (UTC) ou a hora em um zona de tempo não especificada.No entanto, essas limitdas informações de zona de tempo serão ignoradas ao comparar ou executar aritmética de data e hora em valores DateTime.O exemplo a seguir, que compara a hora local atual com a hora UTC atual, ilustra isso.
Public Enum TimeComparison As Integer
EarlierThan = -1
TheSameAs = 0
LaterThan = 1
End Enum
Module DateManipulation
Public Sub Main()
Dim localTime As Date = Date.Now
Dim utcTime As Date = Date.UtcNow
Console.WriteLine("Difference between {0} and {1} time: {2}:{3} hours", _
localTime.Kind.ToString(), _
utcTime.Kind.ToString(), _
(localTime - utcTime).Hours, _
(localTime - utcTime).Minutes)
Console.WriteLine("The {0} time is {1} the {2} time.", _
localTime.Kind.ToString(), _
[Enum].GetName(GetType(TimeComparison), localTime.CompareTo(utcTime)), _
utcTime.Kind.ToString())
' If run in the U.S. Pacific Standard Time zone, the example displays
' the following output to the console:
' Difference between Local and Utc time: -7:0 hours
' The Local time is EarlierThan the Utc time.
End Sub
End Module
using System;
public enum TimeComparison
{
EarlierThan = -1,
TheSameAs = 0,
LaterThan = 1
}
public class DateManipulation
{
public static void Main()
{
DateTime localTime = DateTime.Now;
DateTime utcTime = DateTime.UtcNow;
Console.WriteLine("Difference between {0} and {1} time: {2}:{3} hours",
localTime.Kind.ToString(),
utcTime.Kind.ToString(),
(localTime - utcTime).Hours,
(localTime - utcTime).Minutes);
Console.WriteLine("The {0} time is {1} the {2} time.",
localTime.Kind.ToString(),
Enum.GetName(typeof(TimeComparison), localTime.CompareTo(utcTime)),
utcTime.Kind.ToString());
}
}
// If run in the U.S. Pacific Standard Time zone, the example displays
// the following output to the console:
// Difference between Local and Utc time: -7:0 hours
// The Local time is EarlierThan the Utc time.
The CompareTo(DateTime) método informa que a time local é anterior (ou menor que) indica que a time UTC e a operação de subtração a diferença entre o UTC e a time local para um sistema nos EUA Padrão do Pacífico fuso horário é de sete horas.Mas devido a esses dois valores fornecerem diferentes representações de um único ponto no tempo, é claro nesse caso, que esse intervalo de tempo é completamente relacionado ao deslocamento a partir do UTC da zona de tempo local.
Mais geralmente, a propriedade DateTime.Kind não afeta os resultados retornados por métodos DateTime de comparação e de aritmética (como indica a comparação dos dois pontos idênticos no tempo), embora ele possa afetar a interpretação desses resultados.Por exemplo:
O resultado de qualquer operação aritmética executada em dois valores de data e hora cujas ambas as propriedades DateTime.Kind sejam iguais a Utc reflete o intervalo de tempo real entre os dois valores.Da mesma forma, a comparação desses tais dois valores de data e hora precisamente refletem a relação entre horários.
O resultado de qualquer operação aritmética ou de comparação executada em dois valores de data e tempo cujas ambas as propriedades DateTime.Kind sejam iguais aos valores Local de data e hora com diferentes valores de propriedades DateTime.Kind refletem a diferença de hora do relógio entre os dois valores.
Operações aritméticas ou de comparação em valores de data e tempo local não consideram se um valor específico é ambíguo ou é inválido, nem fazem eles tomarem conta do efeito de quaisquer regras de ajuste que resultam de transição da zona de tempo local para ou a partir do horário de verão.
Qualquer operação que compara ou calcula a diferença entre o UTC e uma hora local inclui um intervalo de tempo igual ao deslocamento da zona de tempo do UTC no resultado.
Qualquer operação que compara ou calcula a diferença entre um tempo não especificado e tanto o UTC quanto a hora local reflete horário simples de relógio.Diferenças de fuso horário não são consideradas, e o resultado não reflete a aplicação das regras de ajuste de zona de tempo.
Qualquer operação que compara ou calcula a diferença entre duas horas não for especificado podem incluir um intervalo desconhecido que reflete a diferença entre a hora nos dois fusos horários diferentes.
Há muitas situações em que as diferenças de zona de tempo não afetam os cálculos de data e hora (para uma discussão sobre algumas delas, consulte Escolhendo entre DateTime, DateTimeOffset e TimeZoneInfo) ou em que o contexto dos dados de data e hora define o significado das operações de comparação ou aritmética.
Comparações e operações aritméticas com valores de DateTimeOffset
Um valor DateTimeOffset inclui não apenas uma data e tempo, mas também um deslocamento que define especificamente que data e hora em relação ao UTC.Isso faz com que seja possível definir a igualdade de uma maneira um pouco diferente do que para valores DateTime.Enquanto valores DateTime são iguais se eles tiverem o mesmo valor de data e hora, os valores DateTimeOffset são iguais se os dois se referirem ao mesmo ponto no tempo.Isso faz com que um valor DateTimeOffset seja mais preciso e necessite menos de interpretação quando usado em comparações e na maioria das operações aritméticas que determinam o intervalo entre duas datas e horas.O exemplo a seguir, que é o DateTimeOffset equivalente ao exemplo anterior que comparava valores DateTimedo tipo local e UTC, ilustra essa diferença no comportamento.
Public Enum TimeComparison As Integer
EarlierThan = -1
TheSameAs = 0
LaterThan = 1
End Enum
Module DateTimeOffsetManipulation
Public Sub Main()
Dim localTime As DateTimeOffset = DateTimeOffset.Now
Dim utcTime As DateTimeOffset = DateTimeOffset.UtcNow
Console.WriteLine("Difference between local time and UTC: {0}:{0:D2} hours.", _
(localTime - utcTime).Hours, _
(localTime - utcTime).Minutes)
Console.WriteLine("The local time is {0} UTC.", _
[Enum].GetName(GetType(TimeComparison), localTime.CompareTo(utcTime)))
End Sub
End Module
' Regardless of the local time zone, the example displays
' the following output to the console:
' Difference between local time and UTC: 0:00 hours.
' The local time is TheSameAs UTC.
' Console.WriteLine(e.GetType().Name)
using System;
public enum TimeComparison
{
EarlierThan = -1,
TheSameAs = 0,
LaterThan = 1
}
public class DateTimeOffsetManipulation
{
public static void Main()
{
DateTimeOffset localTime = DateTimeOffset.Now;
DateTimeOffset utcTime = DateTimeOffset.UtcNow;
Console.WriteLine("Difference between local time and UTC: {0}:{1:D2} hours",
(localTime - utcTime).Hours,
(localTime - utcTime).Minutes);
Console.WriteLine("The local time is {0} UTC.",
Enum.GetName(typeof(TimeComparison), localTime.CompareTo(utcTime)));
}
}
// Regardless of the local time zone, the example displays
// the following output to the console:
// Difference between local time and UTC: 0:00 hours.
// The local time is TheSameAs UTC.
Nesse exemplo, o método CompareTo indica que a hora local atual e a hora UTC atual estão iguais, e a subtração dos valores DateTimeOffset indica que a diferença entre as duas horas é TimeSpan.Zero.
A limitação principal de usar valores de data e hora DateTimeOffset é que embora valores DateTimeOffset têm alguma consciência de zona de tempo, eles são completamente cientes.Embora o deslocamento do valor DateTimeOffset reflita um deslocamento de zona de tempo do UTC na primeira vez que uma variável DateTimeOffset é atribuída um valor, ele se torna desassociado da zona de tempo daí em diante.Porque ele não é mais diretamente associado com um horário de identificação, a adição e subtração dos intervalos de data e hora não consideram as regras de ajuste de uma zona de tempo.
Para ilustrar a transição para o horário de verão nos Estados UnidosCentral padrão fuso horário ocorre às 2: 00em 9 de março de 2008.Isso significa que adicionar um intervalo de horas de duas e meia time central padrão de 1 h 30.em 9 de março de 2008, deve produzir uma data e time de 5 hem 9 de março de 2008.Entretanto, sistema autônomo mostra o exemplo a seguir, o resultado da adição é 4 hem 9 de março de 2008.Observe que esse resultado dessa operação representa o ponto correto in-time, embora não seja o tempo no fuso horário no qual estamos interessados (ou seja, ele não tem o esperado fuso horário deslocamento).
Module IntervalArithmetic
Public Sub Main()
Dim generalTime As Date = #03/09/2008 1:30AM#
Const tzName As String = "Central Standard Time"
Dim twoAndAHalfHours As New TimeSpan(2, 30, 0)
' Instantiate DateTimeOffset value to have correct CST offset
Try
Dim centralTime1 As New DateTimeOffset(generalTime, _
TimeZoneInfo.FindSystemTimeZoneById(tzName).GetUtcOffset(generalTime))
' Add two and a half hours
Dim centralTime2 As DateTimeOffset = centralTime1.Add(twoAndAHalfHours)
' Display result
Console.WriteLine("{0} + {1} hours = {2}", centralTime1, _
twoAndAHalfHours.ToString(), _
centralTime2)
Catch e As TimeZoneNotFoundException
Console.WriteLine("Unable to retrieve Central Standard Time zone information.")
End Try
End Sub
End Module
' The example displays the following output to the console:
' 3/9/2008 1:30:00 AM -06:00 + 02:30:00 hours = 3/9/2008 4:00:00 AM -06:00
using System;
public class IntervalArithmetic
{
public static void Main()
{
DateTime generalTime = new DateTime(2008, 3, 9, 1, 30, 0);
const string tzName = "Central Standard Time";
TimeSpan twoAndAHalfHours = new TimeSpan(2, 30, 0);
// Instantiate DateTimeOffset value to have correct CST offset
try
{
DateTimeOffset centralTime1 = new DateTimeOffset(generalTime,
TimeZoneInfo.FindSystemTimeZoneById(tzName).GetUtcOffset(generalTime));
// Add two and a half hours
DateTimeOffset centralTime2 = centralTime1.Add(twoAndAHalfHours);
// Display result
Console.WriteLine("{0} + {1} hours = {2}", centralTime1,
twoAndAHalfHours.ToString(),
centralTime2);
}
catch (TimeZoneNotFoundException)
{
Console.WriteLine("Unable to retrieve Central Standard Time zone information.");
}
}
}
// The example displays the following output to the console:
// 3/9/2008 1:30:00 AM -06:00 + 02:30:00 hours = 3/9/2008 4:00:00 AM -06:00
Operações aritméticas com horários nos fusos horários
A classe TimeZoneInfo inclui um número de métodos de conversão que aplicam ajustes automaticamente quando eles convertem horas de uma zona de tempo para outra.Eles incluem o seguinte:
Os métodos ConvertTime e ConvertTimeBySystemTimeZoneId, que convertem horas entre quaisquer dois fusos horários.
Os métodos ConvertTimeFromUtc e ConvertTimeToUtc, que convertem a hora em uma determinada zona de tempo em UTC, ou convertem UTC em uma determinada zona de tempo.
Para obter detalhes, consulte:Convertendo Horários entre Zonas de Tempo.
A classe TimeZoneInfo não fornece os métodos que aplicam regras de ajuste automaticamente quando você executa aritmética de data e hora.No entanto, você pode fazer isso ao converter a hora em um zona de tempo em UTC, executar a operação aritmética e, em seguida, converter a partir do UTC de volta para o tempo no zona de tempo.Para obter detalhes, consulte:Como: Use fusos horários na data e time Arithmetic.
Por exemplo, o código a seguir é semelhante ao código anterior à duas-e-a-half horas 2 hem 9 de março de 2008.No entanto, como ele converte uma time de Standard Central em UTC antes de ele executa cálculos aritméticos de data e time e, em seguida, converte o resultado de UTC para central padrão de time, o time resultante refletirá transição a região time padrão central para o horário de verão.
Module TimeZoneAwareArithmetic
Public Sub Main()
Const tzName As String = "Central Standard Time"
Dim generalTime As Date = #03/09/2008 1:30AM#
Dim cst As TimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(tzName)
Dim twoAndAHalfHours As New TimeSpan(2, 30, 0)
' Instantiate DateTimeOffset value to have correct CST offset
Try
Dim centralTime1 As New DateTimeOffset(generalTime, _
cst.GetUtcOffset(generalTime))
' Add two and a half hours
Dim utcTime As DateTimeOffset = centralTime1.ToUniversalTime()
utcTime += twoAndAHalfHours
Dim centralTime2 As DateTimeOffset = TimeZoneInfo.ConvertTime(utcTime, cst)
' Display result
Console.WriteLine("{0} + {1} hours = {2}", centralTime1, _
twoAndAHalfHours.ToString(), _
centralTime2)
Catch e As TimeZoneNotFoundException
Console.WriteLine("Unable to retrieve Central Standard Time zone information.")
End Try
End Sub
End Module
' The example displays the following output to the console:
' 3/9/2008 1:30:00 AM -06:00 + 02:30:00 hours = 3/9/2008 5:00:00 AM -05:00
using System;
public class TimeZoneAwareArithmetic
{
public static void Main()
{
const string tzName = "Central Standard Time";
DateTime generalTime = new DateTime(2008, 3, 9, 1, 30, 0);
TimeZoneInfo cst = TimeZoneInfo.FindSystemTimeZoneById(tzName);
TimeSpan twoAndAHalfHours = new TimeSpan(2, 30, 0);
// Instantiate DateTimeOffset value to have correct CST offset
try
{
DateTimeOffset centralTime1 = new DateTimeOffset(generalTime,
cst.GetUtcOffset(generalTime));
// Add two and a half hours
DateTimeOffset utcTime = centralTime1.ToUniversalTime();
utcTime += twoAndAHalfHours;
DateTimeOffset centralTime2 = TimeZoneInfo.ConvertTime(utcTime, cst);
// Display result
Console.WriteLine("{0} + {1} hours = {2}", centralTime1,
twoAndAHalfHours.ToString(),
centralTime2);
}
catch (TimeZoneNotFoundException)
{
Console.WriteLine("Unable to retrieve Central Standard Time zone information.");
}
}
}
// The example displays the following output to the console:
// 3/9/2008 1:30:00 AM -06:00 + 02:30:00 hours = 3/9/2008 5:00:00 AM -05:00
Consulte também
Tarefas
Como: Use fusos horários na data e time Arithmetic