DateTime.Now vs. DateTime.UtcNow

Me he estado preguntando cuáles son exactamente los principios de cómo funcionan las dos propiedades. Sé que el segundo es universal y, básicamente, no se ocupa de las zonas horarias, pero ¿alguien puede explicar en detalle cómo funcionan y cuál debería usarse en qué escenario?

DateTime.UtcNow te dice la fecha y la hora como en Tiempo Universal Coordinado, que también se denomina zona horaria del meridiano de Greenwich, básicamente como si estuvieras en Londres Inglaterra, pero no durante el verano. DateTime.Now le da la fecha y la hora como aparecería a alguien en su configuración regional actual.

Yo recomendaría usar DateTime.Now cuando muestre una fecha a un ser humano, de esa manera se sienten cómodos con el valor que ven, es algo que pueden comparar fácilmente con lo que ven en su reloj o reloj. Use DateTime.UtcNow cuando desee almacenar fechas o utilizarlas para cálculos posteriores de esa manera (en un modelo de cliente-servidor) sus clientes no confunden sus cálculos en los husos horarios de su servidor o entre ellos.

Es realmente bastante simple, así que creo que depende de lo que sea tu audiencia y dónde vivan.

Si no usa Utc, debe conocer la zona horaria de la persona a la que le está mostrando las fechas y horas; de lo contrario, les informará que sucedió algo a las 3 PM en el sistema o en el servidor, cuando realmente ocurrió a las 5 PM donde ellos pasan a vivir

Usamos DateTime.UtcNow porque tenemos una audiencia web global, y porque prefiero no regañar a cada usuario para que complete un formulario que indique en qué zona horaria vive.

También mostramos tiempos relativos (hace 2 horas, 1 día, etc.) hasta que la publicación envejece lo suficiente como para que el tiempo sea “el mismo” sin importar en qué parte de la Tierra viva.

Un concepto principal para entender en .NET es que ahora se encuentra en todo el mundo sin importar en qué zona horaria se encuentre. Por lo tanto, si carga una variable con DateTime.Now o DateTime.UtcNow, la asignación es idéntica. * Su DateTime El objeto sabe en qué zona horaria se encuentra y lo tiene en cuenta independientemente de la asignación.

La utilidad de DateTime.UtcNow es útil cuando se calculan fechas a lo largo de los límites del horario de verano. Es decir, en lugares que participan en el horario de verano, a veces hay 25 horas desde el mediodía hasta el mediodía del día siguiente, y a veces hay 23 horas entre el mediodía y el mediodía del día siguiente. Si quiere determinar correctamente el número de horas del tiempo A y el tiempo B, primero debe traducir cada una a sus equivalentes UTC antes de calcular el TimeSpan.

Esto está cubierto por una publicación de blog que escribí que explica más detalladamente TimeSpan, e incluye un enlace a un artículo de MS aún más extenso sobre el tema.

* Aclaración: cualquiera de las asignaciones almacenará la hora actual. Si tuviera que cargar dos variables una a través de DateTime.Now () y la otra a través de DateTime.UtcNow () la diferencia de TimeSpan entre las dos sería de milisegundos, no horas, suponiendo que se encuentre en una zona horaria a horas de GMT. Como se indica a continuación, imprimir sus valores de Cadena mostraría diferentes cadenas.

También tenga en cuenta la diferencia de rendimiento; DateTime.UtcNow es alrededor de 30 veces más rápido que DateTime.Now, porque internamente DateTime.Now está realizando muchos ajustes de zona horaria (puede verificar esto fácilmente con Reflector).

Entonces no use DateTime.Now para mediciones de tiempo relativo.

Esta es una buena pregunta. Lo estoy reviviendo para dar un poco más de detalles sobre cómo .Net se comporta con diferentes valores ‘Kind’. Como señala @Jan Zich, en realidad es una propiedad críticamente importante y está configurada de manera diferente dependiendo de si usa Now o UtcNow.

Internamente, la fecha se almacena como “Ticks” que (al contrario de la respuesta de @Carl Camera) es diferente dependiendo de si usa Now o UtcNow.

DateTime.UtcNow se comporta como otros idiomas. Establece Ticks a un valor basado en GMT. También establece ‘Kind’ en ‘Utc’.

DateTime.Now altera el valor de Ticks a lo que sería si fuera tu hora del día en la zona horaria GMT . También establece ‘Tipo’ a ‘Local’.

Si tienes 6 horas de retraso (GMT-6), obtendrás la hora GMT de hace 6 horas. .Net en realidad ignora ‘Kind’ y trata esta vez como si fuera hace 6 horas, aunque se supone que es “ahora”. Esto se rompe aún más si crea una instancia de DateTime, luego cambia su zona horaria e intenta usarla.

Las instancias DateTime con diferentes valores ‘Kind’ NO son compatibles.

Veamos un poco de código …

  DateTime utc = DateTime.UtcNow; DateTime now = DateTime.Now; Debug.Log (utc + " " + utc.Kind); // 05/20/2015 17:19:27 Utc Debug.Log (now + " " + now.Kind); // 05/20/2015 10:19:27 Local Debug.Log (utc.Ticks); // 635677391678617830 Debug.Log (now.Ticks); // 635677139678617840 now = now.AddHours(1); TimeSpan diff = utc - now; Debug.Log (diff); // 05:59:59.9999990 Debug.Log (utc < now); // false Debug.Log (utc == now); // false Debug.Log (utc > now); // true Debug.Log (utc.ToUniversalTime() < now.ToUniversalTime()); // true Debug.Log (utc.ToUniversalTime() == now.ToUniversalTime()); // false Debug.Log (utc.ToUniversalTime() > now.ToUniversalTime()); // false Debug.Log (utc.ToUniversalTime() - now.ToUniversalTime()); // -01:00:00.0000010 

Como puede ver aquí, las comparaciones y las funciones matemáticas no se convierten automáticamente a tiempos compatibles. El Timespan debería haber sido de casi una hora, pero en su lugar era casi 6. “utc

También puede ver el ‘trabajo alrededor’, que es simplemente convertir a la hora universal en cualquier lugar donde ‘Kind’ no sea el mismo.

Mi respuesta directa a la pregunta concuerda con la recomendación de la respuesta aceptada sobre cuándo usar cada una. Siempre debe intentar trabajar con objetos DateTime que tienen Kind = Utc, excepto durante i / o (visualización y análisis). Esto significa que casi siempre debe utilizar DateTime.UtcNow, excepto en los casos en los que crea el objeto solo para mostrarlo, y descartarlo de inmediato.

DateTime no tiene idea de qué son las zonas horarias. Siempre asume que estás a tu hora local. UtcNow solo significa “Restar mi zona horaria de la hora”.

Si desea usar fechas que tengan en cuenta la zona horaria, use DateTimeOffset , que representa una fecha / hora con una zona horaria. Tuve que aprenderlo de la manera difícil.

Solo una pequeña adición a los puntos mencionados anteriormente: la estructura DateTime también contiene un campo poco conocido llamado Kind (al menos, no lo conocía desde hace mucho tiempo). Básicamente es solo una bandera que indica si la hora es local o UTC; no especifica la compensación real de UTC para las horas locales. Además del hecho de que indica con qué intenciones se construyó el stuct, también influye en la forma en que funcionan los métodos ToUniversalTime () y ToLocalTime () .

La respuesta “simple” a la pregunta es:

DateTime.Now devuelve un valor de DateTime que representa la hora actual del sistema (en cualquier zona horaria en que se ejecute el sistema). La propiedad DateTime.Kind será DateTimeKind.Local

DateTime.UtcNow devuelve un valor de fecha y hora que representa la hora universal coordinada actual (también conocida como UTC), que será la misma independientemente de la zona horaria del sistema. La propiedad DateTime.Kind será DateTimeKind.Utc

Un poco tarde para la fiesta, pero encontré que estos dos enlaces (4guysfromrolla) son muy útiles:

Usar el tiempo universal coordinado (UTC) para almacenar valores de fecha / hora

Consejos para almacenar y mostrar fechas y horas en diferentes zonas horarias

DateTime.UtcNow es una escala de tiempo continua de un solo valor, mientras que DateTime.Now no es continua o de un solo valor. La razón principal es el horario de verano, que no se aplica a UTC. Así que UTC nunca salta hacia delante o hacia atrás una hora, mientras que la hora local (DateTime.Now) sí lo hace. Y cuando salta hacia atrás, el mismo valor de tiempo ocurre dos veces.

Cuando necesite una hora local para la máquina en la que se ejecuta su aplicación (como CEST for Europe), use Now. Si quieres un tiempo universal, UtcNow. Es solo cuestión de tus preferencias, probablemente crear un sitio web local o una aplicación independiente que quieras utilizar en función del tiempo que el usuario tenga, tan afectado por su configuración de zona horaria, DateTime.Now.

Solo recuerde, para un sitio web es la configuración de la zona horaria del servidor. Por lo tanto, si muestra la hora para el usuario, obtenga su zona horaria preferida y cambie la hora (simplemente guarde la hora Utc en la base de datos y modifíquela) o especifique que es UTC. Si se le olvida hacerlo, el usuario puede ver algo así como: publicado hace 3 minutos y luego un momento en el futuro cerca de él 🙂