DateTime o DateTimeOffset en C#: Guía completa para desarrolladores

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Introducción: ¿Por qué te duele la cabeza con las fechas?

Si alguna vez has escrito código en C# y te has enfrentado a la tarea de transferir una fecha y hora entre un servidor en Moscú y un cliente en Nueva York, seguramente habrás notado errores extraños: «¿Por qué tengo mañana?», «¿De dónde salieron las 3 horas?». ¿Te suena familiar?

En .NET hay dos herramientas principales para trabajar con fechas: DateTime y DateTimeOffset. A primera vista son similares: ambas almacenan fecha y hora. Pero la diferencia entre ellas es clave, y una elección incorrecta puede provocar errores catastróficos en la lógica de negocio.

En este tutorial analizaremos DateTime vs DateTimeOffset con ejemplos reales, entenderemos cuándo usar cada una y olvidaremos para siempre la confusión con las zonas horarias. ¡Allá vamos!



¿Qué es DateTime? (Y por qué es una trampa)

DateTime es una estructura que almacena fecha y hora. Existe en .NET desde la primera versión. Pero tiene una particularidad: no almacena información sobre la zona horaria. O mejor dicho, la almacena, pero solo como una bandera Kind:

  • DateTimeKind.Unspecified — zona no especificada (por defecto).
  • DateTimeKind.Utc — hora UTC.
  • DateTimeKind.Local — hora local del sistema.

El problema es que esta bandera es solo información. No convierte la hora automáticamente. Imagina que guardas en la base de datos un DateTime con Kind = Local en un servidor en Moscú. Luego lees esa fecha en un servidor en Vladivostok. ¿Qué ocurre? Correcto: el programa verá que Kind = Local y pensará que es la hora local de Vladivostok. Pero en realidad es la de Moscú. Una catástrofe absoluta.



// Ejemplo del problema con DateTimeDateTime moscowTime = new DateTime(2025, 3, 15, 14, 0, 0, DateTimeKind.Local);Console.WriteLine(moscowTime); // 15.03.2025 14:00:00 (se asume que es MSK)

// Si este código se ejecuta en un servidor con zona horaria UTC+10 (Vladivostok)// ¡DateTime se interpretará como la hora local de Vladivostok!// Lo que provocará un error de 7 horas.


¿Qué es DateTimeOffset? (El salvador de los desarrolladores)

DateTimeOffset es una estructura más inteligente que apareció en .NET Framework 3.5. Almacena fecha, hora y el desplazamiento respecto a UTC (Offset). El desplazamiento es el número de horas y minutos en que tu hora local difiere de UTC.

Por ejemplo: 2025-03-15 14:00:00 +03:00 — es la hora en Moscú (UTC+3). Si pasas este valor a un servidor en Vladivostok (UTC+10), .NET entenderá: «Vale, esto es +03, por lo tanto UTC = 11:00. Ahora puedo recalcular fácilmente a la hora local: 21:00». Sin magia, matemática pura.



// Ejemplo con DateTimeOffsetDateTimeOffset moscowOffset = new DateTimeOffset(2025, 3, 15, 14, 0, 0, TimeSpan.FromHours(3));Console.WriteLine(moscowOffset); // 15.03.2025 14:00:00 +03:00

// Ahora, incluso en un servidor en Vladivostok, sabemos el desplazamiento exacto// y podemos mostrar la hora correctamente al usuario


Diferencias clave: DateTime vs DateTimeOffset

Resumamos todo en una tabla clara. Esto te ayudará a decidir rápidamente qué elegir en cada situación.



1. Almacenamiento de información de zona horaria

  • DateTime: Almacena solo la bandera Kind (Unspecified, Utc, Local). No almacena el desplazamiento en sí.
  • DateTimeOffset: Almacena el desplazamiento exacto respecto a UTC (por ejemplo, +03:00, -05:00).


2. Comparación de valores

  • DateTime: Compara por el valor «crudo». Si tienes 10:00 UTC y 10:00 MSK (UTC+3), entonces DateTime.Equals() dirá que son iguales. Aunque en realidad son momentos diferentes en el tiempo.
  • DateTimeOffset: Compara por el momento en el tiempo (UTC). 10:00 UTC y 13:00 MSK serán

Blogs

Book Recommendations