Diferencia entre System.DateTime.Now y System.DateTime.Today

127

¿Alguien puede explicar la diferencia entre System.DateTime.Nowy System.DateTime.Todayen C # .NET? Pros y contras de cada uno si es posible.

Samuel Liew
fuente

Respuestas:

179

DateTime.Nowdevuelve un DateTimevalor que consiste en la fecha y hora local de la computadora donde se ejecuta el código. Se ha DateTimeKind.Localasignado a su Kindpropiedad. Es equivalente a llamar a cualquiera de los siguientes:

  • DateTime.UtcNow.ToLocalTime()
  • DateTimeOffset.UtcNow.LocalDateTime
  • DateTimeOffset.Now.LocalDateTime
  • TimeZoneInfo.ConvertTime(DateTime.UtcNow, TimeZoneInfo.Local)
  • TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, TimeZoneInfo.Local)

DateTime.Todaydevuelve un DateTimevalor que tiene los mismos componentes de año, mes y día que cualquiera de las expresiones anteriores, pero con los componentes de tiempo establecidos en cero. También tiene DateTimeKind.Localen su Kindpropiedad. Es equivalente a cualquiera de los siguientes:

  • DateTime.Now.Date
  • DateTime.UtcNow.ToLocalTime().Date
  • DateTimeOffset.UtcNow.LocalDateTime.Date
  • DateTimeOffset.Now.LocalDateTime.Date
  • TimeZoneInfo.ConvertTime(DateTime.UtcNow, TimeZoneInfo.Local).Date
  • TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, TimeZoneInfo.Local).Date

Tenga en cuenta que internamente, el reloj del sistema está en términos de UTC, por lo que cuando lo llama DateTime.Nowprimero obtiene la hora UTC (a través de la GetSystemTimeAsFileTimefunción en la API Win32) y luego convierte el valor a la zona horaria local. (Por DateTime.Now.ToUniversalTime()lo tanto, es más caro que DateTime.UtcNow).

También tenga en cuenta que DateTimeOffset.Now.DateTimetendrá valores similares a DateTime.Now, pero tendrá DateTimeKind.Unspecifiedmás que DateTimeKind.Local- lo que podría conducir a otros errores dependiendo de lo que haga con él.

Entonces, la respuesta simple es que DateTime.Todayes equivalente a DateTime.Now.Date.
Pero en mi humilde opinión: no debe usar ninguno de estos ni ninguno de los equivalentes anteriores.

Cuando solicita DateTime.Now, solicita el valor del reloj de calendario local de la computadora en la que se ejecuta el código. ¡Pero lo que obtienes no tiene información sobre ese reloj! Lo mejor que obtienes es eso DateTime.Now.Kind == DateTimeKind.Local. ¿Pero de quién es el local? Esa información se pierde tan pronto como hace algo con el valor, como almacenarlo en una base de datos, mostrarlo en la pantalla o transmitirlo mediante un servicio web.

Si su zona horaria local sigue alguna regla de horario de verano, no obtiene esa información DateTime.Now. En tiempos ambiguos, como durante una transición "alternativa", no sabrá cuál de los dos posibles momentos corresponde al valor con el que recuperó DateTime.Now. Por ejemplo, supongamos que la zona horaria de su sistema está configurada Mountain Time (US & Canada)y lo solicita DateTime.Nowen las primeras horas del 3 de noviembre de 2013. ¿Qué significa el resultado 2013-11-03 01:00:00? Hay dos momentos de tiempo instantáneo representados por este mismo calendario fecha y hora. Si tuviera que enviar este valor a otra persona, no tendrían idea de a qué me refería. Especialmente si están en una zona horaria donde las reglas son diferentes.

Lo mejor que podría hacer sería usar DateTimeOffseten su lugar:

// This will always be unambiguous.
DateTimeOffset now = DateTimeOffset.Now;

Ahora, para el mismo escenario que describí anteriormente, obtengo el valor 2013-11-03 01:00:00 -0600antes de la transición o 2013-11-03 01:00:00 -0700después de la transición. Cualquiera que mire estos valores puede decir lo que quise decir.

Escribí una publicación de blog sobre este mismo tema. Por favor lea - El caso contra DateTime . Ahora .

Además, hay algunos lugares en este mundo (como Brasil) donde la transición "hacia adelante" ocurre exactamente a la medianoche. Los relojes van desde las 23:59 hasta la 01:00. ¡Esto significa que el valor que obtienes DateTime.Todayen esa fecha no existe! Incluso si lo usa DateTimeOffset.Now.Date, está obteniendo el mismo resultado y todavía tiene este problema. Es porque tradicionalmente, no ha habido un Dateobjeto en .Net. Entonces, independientemente de cómo obtenga el valor, una vez que se quita el tiempo, debe recordar que realmente no representa la "medianoche", aunque ese es el valor con el que está trabajando.

Si realmente desea una solución completamente correcta para este problema, el mejor enfoque es usar NodaTime . La LocalDateclase representa correctamente una fecha sin hora. Puede obtener la fecha actual para cualquier zona horaria, incluida la zona horaria del sistema local:

using NodaTime;
...

Instant now = SystemClock.Instance.Now;

DateTimeZone zone1 = DateTimeZoneProviders.Tzdb.GetSystemDefault();
LocalDate todayInTheSystemZone = now.InZone(zone1).Date;

DateTimeZone zone2 = DateTimeZoneProviders.Tzdb["America/New_York"];
LocalDate todayInTheOtherZone = now.InZone(zone2).Date;

Si no desea utilizar Noda Time, ahora hay otra opción. He contribuido con una implementación de un objeto de solo fecha al proyecto .Net CoreFX Lab . Puede encontrar el System.Timeobjeto del paquete en su feed MyGet. Una vez agregado a su proyecto, encontrará que puede hacer lo siguiente:

using System;
...

Date localDate = Date.Today;

Date utcDate = Date.UtcToday;

Date tzSpecificDate = Date.TodayInTimeZone(anyTimeZoneInfoObject);
Matt Johnson-Pint
fuente
9
¿Qué pasa con el uso de en DateTime.UtcNowlugar de DateTimeOffset.Now?
Samuel Liew
55
DateTime.UtcNowes aceptable si puede transmitir en su solicitud o especificación que el valor está en UTC. (Me gusta llamar al campo o la propiedad algo así como en MyDateUtclugar de simplemente MyDate, pero eso es solo la guinda del pastel). Si no puede transmitirlo en la especificación o el nombre del campo, DateTimeOffset.UtcNowpuede usarse para garantizar que se transmita el desplazamiento cero. con los valores de fecha y hora.
Matt Johnson-Pint
No son iguales Hoy tiene el tiempo como 00:00:00.
James Wilkins
@JamesWilkins: no estoy seguro de a qué te refieres. También lo hace DateTime.Now.Date.
Matt Johnson-Pint
@MattJohnson La pregunta es preguntar la diferencia entre DateTime.Today y DateTime.Now, no DateTime.Today y DateTime.Now.Date.
David Anderson
85

Hora. .Nowincluye el 09:23:12 o lo que sea; .Todayes la parte de fecha solamente (a las 00:00:00 de ese día).

¡Úselo .Nowsi desea incluir la hora y .Todaysi solo desea la fecha!

.Today es esencialmente lo mismo que .Now.Date

Marc Gravell
fuente
27
... y utilícelo a UtcNowmenos que realmente desee la zona horaria local del sistema. (En particular, en una aplicación web que casi siempre es la elección incorrecta.)
Jon Skeet
22

La DateTime.Nowpropiedad devuelve la fecha y hora actuales, por ejemplo 2011-07-01 10:09.45310.

La DateTime.Todaypropiedad devuelve la fecha actual con los componentes de tiempo establecidos en cero, por ejemplo 2011-07-01 00:00.00000.

La DateTime.Todaypropiedad en realidad se implementa para devolver DateTime.Now.Date:

public static DateTime Today {
  get {
    DateTime now = DateTime.Now;
    return now.Date;
  }
}
Guffa
fuente
9

DateTime.Today representa la fecha actual del sistema con la parte de tiempo establecida en 00:00:00

y

DateTime.Now representa la fecha y hora actuales del sistema

daniel.herken
fuente
2
solo una observación ... la documentación 1.1 es mucho menos detallada que la documentación 4.0; quizás sea mejor vincular a vLatest?
Marc Gravell
3
@megaperlz: ahora está vinculando a 4.0 en lugar de vLatest. Los enlaces VLatest se pueden hacer eliminando el (v=VS.100).
Brian
6

Pensé en agregar estos enlaces:

Volviendo a la pregunta original, usando Reflector he explicado la diferencia en el código

 public static DateTime Today
    {
      get
      {
        return DateTime.Now.Date;   // It returns the date part of Now

        //Date Property
       // returns same date as this instance, and the time value set to 12:00:00 midnight (00:00:00) 
      }
    }


    private const long TicksPerMillisecond = 10000L;
    private const long TicksPerDay = 864000000000L;
    private const int MillisPerDay = 86400000;

    public DateTime Date
    {
       get
      {
        long internalTicks = this.InternalTicks; // Date this instance is converted to Ticks 
        return new DateTime((ulong) (internalTicks - internalTicks % 864000000000L) | this.InternalKind);  
// Modulo of TicksPerDay is subtracted - which brings the time to Midnight time 
      }
    }


     public static DateTime Now
        {
          get
          {
           /* this is why I guess Jon Skeet is recommending to use  UtcNow as you can see in one of the above comment*/
            DateTime utcNow = DateTime.UtcNow;


            /* After this i guess it is Timezone conversion */
            bool isAmbiguousLocalDst = false;
            long ticks1 = TimeZoneInfo.GetDateTimeNowUtcOffsetFromUtc(utcNow, out isAmbiguousLocalDst).Ticks;
            long ticks2 = utcNow.Ticks + ticks1;
            if (ticks2 > 3155378975999999999L)
              return new DateTime(3155378975999999999L, DateTimeKind.Local);
            if (ticks2 < 0L)
              return new DateTime(0L, DateTimeKind.Local);
            else
              return new DateTime(ticks2, DateTimeKind.Local, isAmbiguousLocalDst);
          }
        }
dekdev
fuente
5
DateTime dt = new DateTime();// gives 01/01/0001 12:00:00 AM
DateTime dt = DateTime.Now;// gives today date with current time
DateTime dt = DateTime.Today;// gives today date and 12:00:00 AM time
deepi
fuente
1

DateTime.Todayes DateTime.Nowcon el tiempo establecido en cero.

Es importante tener en cuenta que hay una diferencia entre un valor DateTime, que representa el número de tics que han transcurrido desde la medianoche del 1 de enero de 0000, y la representación de cadena de ese valor DateTime, que expresa un valor de fecha y hora en un formato específico de cultura específica: https://msdn.microsoft.com/en-us/library/system.datetime.now%28v=vs.110%29.aspx

DateTime.Now.Tickses el tiempo real almacenado por .net (esencialmente hora UTC), el resto son solo representaciones (que son importantes para fines de visualización).

Si la Kindpropiedad es DateTimeKind.Local, implícitamente incluye la información de zona horaria de la computadora local. Al enviar a través de un servicio web .net, los valores de DateTime se serializan de manera predeterminada con información de zona horaria incluida, por ejemplo, 2008-10-31T15: 07: 38.6875000-05: 00, y una computadora en otra zona horaria aún puede saber exactamente qué hora es siendo referido

Entonces, usar DateTime.Now y DateTime.Today está perfectamente bien.

Por lo general, comienza a tener problemas cuando comienza a confundir la representación de cadena con el valor real e intenta "arreglar" el DateTime, cuando no está roto.

Kobus
fuente
-1

DateTime.Now.ToShortDateString() mostrará solo la parte de la fecha

sunnyca99
fuente