Elija entre DateTime, DateTimeOffset, TimeSpan y TimeZoneInfo.

Las aplicaciones .NET pueden usar información de fecha y hora de varias maneras. Los usos más comunes de la información de fecha y hora incluyen:

  • Reflejar solo la fecha (la información de hora no es importante).

  • Reflejar solo la hora (la información de fecha no es importante).

  • Reflejar una fecha y una hora abstractas que no estén asociadas a una hora ni a un lugar concretos (por ejemplo, la mayoría de tiendas de una cadena internacional abren los días laborables a las 09:00).

  • Para recuperar información de fecha y hora de orígenes fuera de .NET, normalmente donde la información de fecha y hora se almacena en un tipo de datos simple.

  • Identificar de forma exclusiva e inequívoca un solo punto en el tiempo. Algunas aplicaciones requieren que una fecha y hora sean inequívocas solo en el sistema host. Otras aplicaciones requieren que sea inequívoca en todos los sistemas (es decir, una fecha serializada en un sistema se puede deserializar y usar significativamente en otro sistema en cualquier parte del mundo).

  • Conservar varias horas relacionadas (como la hora local del solicitante y la hora de recepción del servidor con respecto a una solicitud web).

  • Realizar operaciones aritméticas de fecha y hora, posiblemente con un resultado que identifica de forma exclusiva e inequívoca un único punto en el tiempo.

.NET incluye los tipos , , y , que se pueden usar para compilar aplicaciones DateTime DateTimeOffset que funcionan con TimeSpan TimeZoneInfo fechas y horas.

Nota

En este tema no se describe porque su funcionalidad se incorpora casi por completo TimeZone en la TimeZoneInfo clase . Siempre que sea posible, use TimeZoneInfo la clase en lugar de la clase TimeZone .

DateTimeOffset (estructura)

La estructura DateTimeOffset representa un valor de fecha y hora, junto con un desplazamiento que indica la diferencia de ese valor con respecto a la hora UTC. Por lo tanto, el valor identifica siempre de forma inequívoca un único punto en el tiempo.

El tipo DateTimeOffset incluye toda la funcionalidad del tipo DateTime junto con la zona horaria. Esto hace que sea adecuado para aplicaciones que:

  • Identificar de forma exclusiva e inequívoca un solo punto en el tiempo. El tipo DateTimeOffset puede usarse para definir inequívocamente el significado de “ahora”, para registrar los tiempos de transacción, para registrar la hora de eventos del sistema o de aplicaciones, y para registrar los tiempos de creación y modificación de archivos.

  • Realizar operaciones aritméticas generales de fecha y hora.

  • Conservar varias horas relacionadas, siempre que esas horas se almacenen como dos valores independientes o como dos miembros de una estructura.

Nota

Estos usos de valores DateTimeOffset son mucho más comunes que los de valores DateTime . Como resultado, considere como el tipo de DateTimeOffset fecha y hora predeterminado para el desarrollo de aplicaciones.

Un DateTimeOffset valor no está asociado a una zona horaria determinada, pero puede originarse en una variedad de zonas horarias. En el ejemplo siguiente se enumeran las zonas horarias a las que pueden pertenecer varios valores (incluida una DateTimeOffset hora estándar del Pacífico local).

using System;
using System.Collections.ObjectModel;

public class TimeOffsets
{
   public static void Main()
   {
      DateTime thisDate = new DateTime(2007, 3, 10, 0, 0, 0);
      DateTime dstDate = new DateTime(2007, 6, 10, 0, 0, 0);
      DateTimeOffset thisTime;

      thisTime = new DateTimeOffset(dstDate, new TimeSpan(-7, 0, 0));
      ShowPossibleTimeZones(thisTime);

      thisTime = new DateTimeOffset(thisDate, new TimeSpan(-6, 0, 0));
      ShowPossibleTimeZones(thisTime);

      thisTime = new DateTimeOffset(thisDate, new TimeSpan(+1, 0, 0));
      ShowPossibleTimeZones(thisTime);
   }

   private static void ShowPossibleTimeZones(DateTimeOffset offsetTime)
   {
      TimeSpan offset = offsetTime.Offset;
      ReadOnlyCollection<TimeZoneInfo> timeZones;

      Console.WriteLine("{0} could belong to the following time zones:",
                        offsetTime.ToString());
      // Get all time zones defined on local system
      timeZones = TimeZoneInfo.GetSystemTimeZones();
      // Iterate time zones
      foreach (TimeZoneInfo timeZone in timeZones)
      {
         // Compare offset with offset for that date in that time zone
         if (timeZone.GetUtcOffset(offsetTime.DateTime).Equals(offset))
            Console.WriteLine("   {0}", timeZone.DisplayName);
      }
      Console.WriteLine();
   }
}
// This example displays the following output to the console:
//       6/10/2007 12:00:00 AM -07:00 could belong to the following time zones:
//          (GMT-07:00) Arizona
//          (GMT-08:00) Pacific Time (US & Canada)
//          (GMT-08:00) Tijuana, Baja California
//
//       3/10/2007 12:00:00 AM -06:00 could belong to the following time zones:
//          (GMT-06:00) Central America
//          (GMT-06:00) Central Time (US & Canada)
//          (GMT-06:00) Guadalajara, Mexico City, Monterrey - New
//          (GMT-06:00) Guadalajara, Mexico City, Monterrey - Old
//          (GMT-06:00) Saskatchewan
//
//       3/10/2007 12:00:00 AM +01:00 could belong to the following time zones:
//          (GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna
//          (GMT+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague
//          (GMT+01:00) Brussels, Copenhagen, Madrid, Paris
//          (GMT+01:00) Sarajevo, Skopje, Warsaw, Zagreb
//          (GMT+01:00) West Central Africa
Imports System.Collections.ObjectModel

Module TimeOffsets
    Public Sub Main()
        Dim thisTime As DateTimeOffset

        thisTime = New DateTimeOffset(#06/10/2007#, New TimeSpan(-7, 0, 0))
        ShowPossibleTimeZones(thisTime)

        thisTime = New DateTimeOffset(#03/10/2007#, New TimeSpan(-6, 0, 0))
        ShowPossibleTimeZones(thisTime)

        thisTime = New DateTimeOffset(#03/10/2007#, New TimeSpan(+1, 0, 0))
        ShowPossibleTimeZones(thisTime)
    End Sub

    Private Sub ShowPossibleTimeZones(offsetTime As DateTimeOffset)
        Dim offset As TimeSpan = offsetTime.Offset
        Dim timeZones As ReadOnlyCollection(Of TimeZoneInfo)

        Console.WriteLine("{0} could belong to the following time zones:", _
                          offsetTime.ToString())
        ' Get all time zones defined on local system
        timeZones = TimeZoneInfo.GetSystemTimeZones()
        ' Iterate time zones
        For Each timeZone As TimeZoneInfo In timeZones
            ' Compare offset with offset for that date in that time zone
            If timeZone.GetUtcOffset(offsetTime.DateTime).Equals(offset) Then
                Console.WriteLine("   {0}", timeZone.DisplayName)
            End If
        Next
        Console.WriteLine()
    End Sub
End Module
' This example displays the following output to the console:
'       6/10/2007 12:00:00 AM -07:00 could belong to the following time zones:
'          (GMT-07:00) Arizona
'          (GMT-08:00) Pacific Time (US & Canada)
'          (GMT-08:00) Tijuana, Baja California
'       
'       3/10/2007 12:00:00 AM -06:00 could belong to the following time zones:
'          (GMT-06:00) Central America
'          (GMT-06:00) Central Time (US & Canada)
'          (GMT-06:00) Guadalajara, Mexico City, Monterrey - New
'          (GMT-06:00) Guadalajara, Mexico City, Monterrey - Old
'          (GMT-06:00) Saskatchewan
'       
'       3/10/2007 12:00:00 AM +01:00 could belong to the following time zones:
'          (GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna
'          (GMT+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague
'          (GMT+01:00) Brussels, Copenhagen, Madrid, Paris
'          (GMT+01:00) Sarajevo, Skopje, Warsaw, Zagreb
'          (GMT+01:00) West Central Africa

La salida muestra que cada valor de fecha y hora de este ejemplo puede pertenecer al menos a tres zonas horarias diferentes. El valor de 10/6/2007 muestra que si un valor de fecha y hora representa un horario de verano, su desplazamiento respecto a utc ni siquiera se corresponde necesariamente con el desplazamiento UTC base de la zona horaria de origen ni con el desplazamiento de UTC encontrado en su nombre para DateTimeOffset mostrar. Dado que un valor único no está estrechamente unido a su zona horaria, no puede reflejar la transición de una zona horaria hacia y desde el horario de DateTimeOffset verano. Esto puede ser problemático cuando se usa la aritmética de fecha y hora para manipular un DateTimeOffset valor. Para obtener una explicación de cómo realizar operaciones aritméticas de fecha y hora de forma que se tienen en cuenta las reglas de ajuste de una zona horaria, vea Realizar operaciones aritméticas con fechas y horas.

DateTime (estructura)

Un valor DateTime define una fecha y hora concretas. Incluye una propiedad que proporciona información limitada sobre la zona horaria a la que Kind pertenece esa fecha y hora. El valor DateTimeKind devuelto por la propiedad Kind indica si el valor DateTime representa la hora local (DateTimeKind.Local), la hora universal coordinada (UTC) (DateTimeKind.Utc) o una hora no especificada (DateTimeKind.Unspecified).

La DateTime estructura es adecuada para aplicaciones con una o varias de las siguientes características:

  • Trabajar solo con fechas.

  • Trabajar solo con horas.

  • Trabajar con fechas y horas abstractas.

  • Trabajar con fechas y horas cuya información de zona horaria no esté disponible.

  • Trabajar solo con fechas y horas UTC.

  • Recupere información de fecha y hora de orígenes fuera de .NET, como bases de SQL datos. Normalmente, estos orígenes almacenan la información de fecha y hora en un formato sencillo que es compatible con la estructura DateTime .

  • Realizar operaciones aritméticas de fecha y hora, pero con interés por los resultados generales. Por ejemplo, en una operación que suma seis meses a una determinada fecha y hora, a menudo no resulta importante si el resultado se ajusta al horario de verano.

A menos que un determinado valor DateTime represente la hora UTC, ese valor de fecha y hora suele ser ambiguo o limitado en su movilidad. Por ejemplo, si un valor DateTime representa la hora local, entonces se puede mover en la zona horaria local (es decir, si el valor se deserializa en otro sistema de la misma zona horaria, dicho valor sigue identificando inequívocamente un único punto en el tiempo). Fuera de la zona horaria local, ese valor DateTime puede tener varias interpretaciones. Si la propiedad Kind del valor es DateTimeKind.Unspecified, es aún menos móvil: ahora es ambiguo dentro de la misma zona horaria y posiblemente incluso en el mismo sistema en el que se serializó por primera vez. Solo si un valor DateTime representa la hora UTC, ese valor identificará inequívocamente un único punto con independencia del sistema o la zona horaria en los que se usa el valor.

Importante

Al guardar o compartir datos de DateTime , debe usarse la hora UTC, y la propiedad DateTime del valor Kind debe establecerse en DateTimeKind.Utc.

TimeSpan (estructura)

La estructura TimeSpan representa un intervalo de tiempo. Sus dos usos típicos son:

  • Reflejar el intervalo de tiempo entre dos valores de fecha y hora. Por ejemplo, restar un valor DateTime de otro devuelve un valor TimeSpan .

  • Medir el tiempo transcurrido. Por ejemplo, la propiedad devuelve un valor que refleja el intervalo de tiempo transcurrido desde la llamada a uno de los métodos que comienzan a medir Stopwatch.Elapsed TimeSpan el tiempo Stopwatch transcurrido.

Un valor también se puede usar como reemplazo de un valor cuando ese valor refleja una hora TimeSpan sin referencia a un día DateTime determinado. Este uso es similar a las DateTime.TimeOfDay propiedades y , que DateTimeOffset.TimeOfDay devuelven un valor que representa la TimeSpan hora sin referencia a una fecha. Por ejemplo, la estructura TimeSpan puede usarse para reflejar la hora diaria de apertura o cierre de una tienda, o puede usarse para representar la hora en que se produce cualquier evento habitual.

En el ejemplo siguiente se define una estructura StoreInfo que incluye objetos TimeSpan para las horas de apertura y cierre de la tienda, así como un objeto TimeZoneInfo que representa la zona horaria de la tienda. La estructura también incluye dos métodos, IsOpenNow e IsOpenAt, que indican si la tienda está abierta en el momento especificado por el usuario, quien se supone que está en la zona horaria local.

using System;

public struct StoreInfo
{
   public String store;
   public TimeZoneInfo tz;
   public TimeSpan open;
   public TimeSpan close;

   public bool IsOpenNow()
   {
      return IsOpenAt(DateTime.Now.TimeOfDay);
   }

   public bool IsOpenAt(TimeSpan time)
   {
      TimeZoneInfo local = TimeZoneInfo.Local;
      TimeSpan offset = TimeZoneInfo.Local.BaseUtcOffset;

      // Is the store in the same time zone?
      if (tz.Equals(local)) {
         return time >= open & time <= close;
      }
      else {
         TimeSpan delta = TimeSpan.Zero;
         TimeSpan storeDelta = TimeSpan.Zero;

         // Is it daylight saving time in either time zone?
         if (local.IsDaylightSavingTime(DateTime.Now.Date + time))
            delta = local.GetAdjustmentRules()[local.GetAdjustmentRules().Length - 1].DaylightDelta;

         if (tz.IsDaylightSavingTime(TimeZoneInfo.ConvertTime(DateTime.Now.Date + time, local, tz)))
            storeDelta = tz.GetAdjustmentRules()[tz.GetAdjustmentRules().Length - 1].DaylightDelta;

         TimeSpan comparisonTime = time + (offset - tz.BaseUtcOffset).Negate() + (delta - storeDelta).Negate();
         return comparisonTime >= open & comparisonTime <= close;
      }
   }
}
Public Structure StoreInfo
    Dim store As String
    Dim tz As TimeZoneInfo
    Dim open As TimeSpan
    Dim close As TimeSpan

    Public Function IsOpenNow() As Boolean
        Return IsOpenAt(Date.Now.TimeOfDay)
    End Function

    Public Function IsOpenAt(time As TimeSpan) As Boolean
        Dim local As TimeZoneInfo = TimeZoneInfo.Local
        Dim offset As TimeSpan = TimeZoneInfo.Local.BaseUtcOffset

        ' Is the store in the same time zone?
        If tz.Equals(local) Then
            Return time >= open AndAlso time <= close
        Else
            Dim delta As TimeSpan = TimeSpan.Zero
            Dim storeDelta As TimeSpan = TimeSpan.Zero

            ' Is it daylight saving time in either time zone?
            If local.IsDaylightSavingTime(Date.Now.Date + time) Then
                delta = local.GetAdjustmentRules(local.GetAdjustmentRules().Length - 1).DaylightDelta
            End If
            If tz.IsDaylightSavingTime(TimeZoneInfo.ConvertTime(Date.Now.Date + time, local, tz))
                storeDelta = tz.GetAdjustmentRules(tz.GetAdjustmentRules().Length - 1).DaylightDelta
            End If
            Dim comparisonTime As TimeSpan = time + (offset - tz.BaseUtcOffset).Negate() + (delta - storeDelta).Negate
            Return (comparisonTime >= open AndAlso comparisonTime <= close)
        End If
    End Function
End Structure

La estructura StoreInfo puede usarla un código de cliente como este.

public class Example
{
   public static void Main()
   {
      // Instantiate a StoreInfo object.
      var store103 = new StoreInfo();
      store103.store = "Store #103";
      store103.tz = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
      // Store opens at 8:00.
      store103.open = new TimeSpan(8, 0, 0);
      // Store closes at 9:30.
      store103.close = new TimeSpan(21, 30, 0);

      Console.WriteLine("Store is open now at {0}: {1}",
                        DateTime.Now.TimeOfDay, store103.IsOpenNow());
      TimeSpan[] times = { new TimeSpan(8, 0, 0), new TimeSpan(21, 0, 0),
                           new TimeSpan(4, 59, 0), new TimeSpan(18, 31, 0) };
      foreach (var time in times)
         Console.WriteLine("Store is open at {0}: {1}",
                           time, store103.IsOpenAt(time));
   }
}
// The example displays the following output:
//       Store is open now at 15:29:01.6129911: True
//       Store is open at 08:00:00: True
//       Store is open at 21:00:00: False
//       Store is open at 04:59:00: False
//       Store is open at 18:31:00: False
Module Example
    Public Sub Main()
        ' Instantiate a StoreInfo object.
        Dim store103 As New StoreInfo()
        store103.store = "Store #103"
        store103.tz = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time")
        ' Store opens at 8:00.
        store103.open = new TimeSpan(8, 0, 0)
        ' Store closes at 9:30.
        store103.close = new TimeSpan(21, 30, 0)

        Console.WriteLine("Store is open now at {0}: {1}",
                          Date.Now.TimeOfDay, store103.IsOpenNow())
        Dim times() As TimeSpan = {New TimeSpan(8, 0, 0),
                                    New TimeSpan(21, 0, 0),
                                    New TimeSpan(4, 59, 0),
                                    New TimeSpan(18, 31, 0)}
        For Each time In times
            Console.WriteLine("Store is open at {0}: {1}",
                              time, store103.IsOpenAt(time))
        Next
    End Sub
End Module
' The example displays the following output:
'       Store is open now at 15:29:01.6129911: True
'       Store is open at 08:00:00: True
'       Store is open at 21:00:00: False
'       Store is open at 04:59:00: False
'       Store is open at 18:31:00: False

TimeZoneInfo (clase)

La clase TimeZoneInfo class represents any of the Earth's time zones, and enables the conversion of any date and time in one time zone to its equivalent in another time zone. La clase TimeZoneInfo permite trabajar con valores de fecha y hora de forma que cada uno de esos valores identifique de forma inequívoca un único punto en el tiempo. La clase TimeZoneInfo también es extensible. Aunque depende de la información de zona horaria proporcionada para los sistemas Windows y definida en el Registro, admite la creación de zonas horarias personalizadas. También admite la serialización y deserialización de la información de zona horaria.

En algunos casos, si desea aprovechar al máximo la clase TimeZoneInfo puede que tenga que desarrollar aún más. Si los valores de fecha y hora no están estrechamente unidos a las zonas horarias a las que pertenecen, se requiere más trabajo. A menos que la aplicación proporciona algún mecanismo para vincular una fecha y hora con su zona horaria asociada, es fácil que un valor de fecha y hora determinado se desasocia de su zona horaria. Un método para vincular esta información es definir una clase o estructura que contenga el valor de fecha y hora, y su objeto de zona horaria asociada.

Para aprovechar la compatibilidad con la zona horaria en .NET, debe conocer la zona horaria a la que pertenece un valor de fecha y hora cuando se crea una instancia de ese objeto de fecha y hora. La zona horaria a menudo no se conoce, especialmente en aplicaciones web o de red.

Consulta también