Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Aunque tanto la DateTime como la DateTimeOffset estructuras proporcionan miembros que realizan operaciones aritméticas en sus valores, los resultados de las operaciones aritméticas son muy diferentes. En este artículo se examinan esas diferencias, se relacionan con grados de reconocimiento de zona horaria en los datos de fecha y hora, y se describe cómo realizar operaciones con reconocimiento de zona horaria completa mediante datos de fecha y hora.
Comparaciones y operaciones aritméticas con valores DateTime
La DateTime.Kind propiedad permite asignar un DateTimeKind valor a la fecha y hora para indicar si representa la hora local, la hora universal coordinada (UTC) o la hora en una zona horaria no especificada. Sin embargo, esta información de zona horaria limitada se omite al comparar o realizar aritmética de fecha y hora en los valores DateTimeKind. En el ejemplo siguiente, que compara la hora local actual con la hora UTC actual, se muestra cómo se omite la información de zona horaria.
using System;
public enum TimeComparison2
{
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,
utcTime.Kind,
(localTime - utcTime).Hours,
(localTime - utcTime).Minutes);
Console.WriteLine("The {0} time is {1} the {2} time.",
localTime.Kind,
Enum.GetName(typeof(TimeComparison2), localTime.CompareTo(utcTime)),
utcTime.Kind);
}
}
// 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.
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
El método CompareTo(DateTime) indica que la hora local es anterior a (o menor que) la hora UTC, y la operación de resta indica que la diferencia entre UTC y la hora local de un sistema en la zona horaria Pacific Standard Time de EE. UU. es de siete horas. Pero dado que estos dos valores proporcionan representaciones diferentes de un único punto en el tiempo, está claro en este caso que el intervalo de tiempo es completamente imputable al desplazamiento de la zona horaria local de UTC.
Por lo general, la DateTime.Kind propiedad no afecta a los resultados devueltos por Kind comparación y métodos aritméticos (como indica la comparación de dos puntos idénticos en el tiempo), aunque puede afectar a la interpretación de esos resultados. Por ejemplo:
Resultado de cualquier operación aritmética realizada en dos valores de fecha y hora cuyas propiedades DateTime.Kind son iguales a DateTimeKind refleja el intervalo de tiempo real entre los dos valores. De forma similar, la comparación de dos valores de fecha y hora de este tipo refleja con precisión la relación entre las horas.
El resultado de cualquier operación aritmética o de comparación realizada en dos valores de fecha y hora cuyas DateTime.Kind propiedades sean iguales DateTimeKind o en dos valores de fecha y hora con valores de propiedad diferentes DateTime.Kind refleja la diferencia en la hora del reloj entre los dos valores.
Las operaciones aritméticas o de comparación en los valores de fecha y hora locales no tienen en cuenta si un valor determinado es ambiguo o no válido, ni tienen en cuenta el efecto de las reglas de ajuste resultantes de la transición de la zona horaria local a o desde el horario de verano.
Cualquier operación que compare o calcule la diferencia entre utc y una hora local incluye un intervalo de tiempo igual al desplazamiento de la zona horaria local de UTC en el resultado.
Cualquier operación que compare o calcule la diferencia entre una hora no especificada y la hora UTC o la hora local refleja la hora del reloj simple. No se tienen en cuenta las diferencias de zona horaria y el resultado no refleja la aplicación de reglas de ajuste de zona horaria.
Cualquier operación que compare o calcule la diferencia entre dos horas no especificadas puede incluir un intervalo desconocido que refleje la diferencia entre la hora en dos zonas horarias diferentes.
Hay muchos escenarios en los que las diferencias de zona horaria no afectan a los cálculos de fecha y hora (para obtener una explicación de algunos de estos escenarios, vea Elegir entre DateTime, DateTimeOffset, TimeSpan y TimeZoneInfo) o en el que el contexto de los datos de fecha y hora define el significado de las operaciones de comparación o aritmética.
Comparaciones y operaciones aritméticas con valores DateTimeOffset
Un valor de DateTimeOffset incluye no solo una fecha y hora, sino también un desplazamiento que define inequívocamente esa fecha y hora en relación con UTC. Este desplazamiento permite definir la igualdad de manera diferente a la de los valores DateTime. Mientras que los DateTime valores son iguales si tienen el mismo valor de fecha y hora, DateTimeOffset los valores son iguales si ambos hacen referencia al mismo punto en el tiempo. Cuando se usa en comparaciones y en la mayoría de las operaciones aritméticas que determinan el intervalo entre dos fechas y horas, un DateTimeOffset valor es más preciso y menos necesario de interpretación. En el ejemplo siguiente, que es el DateTimeOffset equivalente al ejemplo anterior que comparó los valores locales y UTC DateTimeOffset , se muestra esta diferencia en el comportamiento.
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: {(localTime - utcTime).Hours}:{(localTime - utcTime).Minutes:D2} hours");
Console.WriteLine($"The local time is {Enum.GetName(typeof(TimeComparison), localTime.CompareTo(utcTime))} UTC.");
}
}
// 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.
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}:{1: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)
En este ejemplo, el CompareTo método indica que la hora local actual y la hora UTC actual son iguales y la resta de CompareTo(DateTimeOffset) valores indica que la diferencia entre las dos veces es TimeSpan.Zero.
La limitación principal del uso DateTimeOffset de valores en la aritmética de fecha y hora es que, aunque DateTimeOffset los valores tienen algún reconocimiento de zona horaria, no son totalmente conscientes de la zona horaria. Aunque el desplazamiento de un valor refleja el desplazamiento de una zona horaria respecto a UTC cuando se asigna por primera vez a una variable, luego se desasocia de la zona horaria. Dado que ya no está asociado directamente a una hora identificable, la suma y resta de intervalos de fecha y hora no tiene en cuenta las reglas de ajuste de una zona horaria.
Para ilustrarlo, la transición al horario de verano en la zona horaria estándar central de EE. UU. se produce a las 2:00 A.M. el 9 de marzo de 2008. Teniendo esto en cuenta, agregar un intervalo de dos y media hora a una hora estándar central de 1:30 A.M. el 9 de marzo de 2008, debe producir una fecha y hora de 5:00 A.M. el 9 de marzo de 2008. Sin embargo, como se muestra en el ejemplo siguiente, el resultado de la adición es 4:00 A.M. el 9 de marzo de 2008. El resultado de esta operación representa el momento dado correcto, aunque no es la hora en la zona horaria en la que estamos interesados (es decir, no tiene el desplazamiento de zona horaria esperado).
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($"{centralTime1} + {twoAndAHalfHours.ToString()} hours = {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
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
Operaciones aritméticas con tiempos en zonas horarias
La TimeZoneInfo clase incluye métodos de conversión que aplican automáticamente ajustes cuando convierten horas de una zona horaria a otra. Estos métodos de conversión incluyen:
Los métodos ConvertTime y ConvertTimeBySystemTimeZoneId, que convierten horas entre dos zonas horarias.
Los métodos ConvertTimeFromUtc y ConvertTimeToUtc convierten la hora en una zona horaria determinada a UTC, o convierten UTC a la hora en una zona horaria determinada.
Para obtener más información, consulte Conversión de horas entre zonas horarias.
La TimeZoneInfo clase no proporciona ningún método que aplique automáticamente reglas de ajuste al realizar la aritmética de fecha y hora. Sin embargo, puede aplicar reglas de ajuste convirtiendo la hora en una zona horaria a UTC, realizando la operación aritmética y, a continuación, convirtiendo de UTC a la hora en la zona horaria. Para obtener más información, consulte Cómo: Usar zonas horarias en la aritmética de fecha y hora.
Por ejemplo, el código siguiente es similar al código anterior que agregó dos horas y media a las 2:00 a.m. el 9 de marzo de 2008. Sin embargo, dado que convierte una hora estándar central a UTC antes de realizar la aritmética de fecha y hora, y luego convierte el resultado de UTC a hora estándar central, la hora resultante refleja la transición de la zona horaria estándar central al horario de verano.
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($"{centralTime1} + {twoAndAHalfHours.ToString()} hours = {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
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