¿Cómo convertir DateTime a una cadena ISO 8601 en C#? El problema que atormenta incluso a los experimentados
\n\n¿Alguna vez se ha encontrado con una situación en la que su API devuelve una fecha en el formato "2023-01-15T10:30:00" y el cliente no la entiende? ¿O, por el contrario, recibe una fecha de un servicio externo que se ve como "2023-01-15T10:30:00+03:00" y su analizador se rompe? ¿Le suena familiar? Si trabaja con C# y el objeto DateTime, el problema de obtener una cadena ISO 8601 es un clásico. En Stack Overflow, esta pregunta ha acumulado miles de visitas, y no es para menos. Hoy, de una vez por todas, entenderemos cómo convertir correctamente DateTime a una cadena en formato ISO 8601, evitando las trampas típicas.
No solo mostraremos un par de líneas de código. Analizaremos el formato DateTime de C# para ISO 8601, veremos el trabajo con zonas horarias, milisegundos y responderemos las preguntas más frecuentes. ¡Allá vamos!
\n\n¿Qué es ISO 8601 y por qué es importante?
\n\nISO 8601 es un estándar internacional para la representación de fecha y hora. Se ve así: 2023-12-25T14:30:00.0000000+03:00. Las características clave son:
- \n
- Separador T entre la fecha y la hora. \n
- Zona horaria indicada al final (Z para UTC o desplazamiento como +05:00). \n
- Parte fraccionaria de segundos (milisegundos, tics). \n
¿Para qué sirve esto? JSON, XML, API REST, bases de datos: en cualquier lugar donde se necesite una transmisión inequívoca de un momento en el tiempo, sin depender de la cultura local del servidor. Un formato incorrecto y su analizador del otro lado podría descartar las horas o confundir el día con el mes. Por lo tanto, el formato de fecha ISO 8601 en C# es una habilidad imprescindible para cualquier desarrollador backend.
\n\nLa forma más sencilla: DateTime.ToString() con el formato "o"
\n\nEn C# hay un especificador de formato incorporado para el formato de ida y vuelta (round-trip): es la letra "o" (minúscula). Proporciona una cadena ISO 8601 completa con la máxima precisión.
\n\nDateTime now = DateTime.Now;\nstring isoString = now.ToString("o");\nConsole.WriteLine(isoString);\n// Ejemplo de salida: 2023-12-25T14:30:00.1234567+03:00\n\nEsta es la forma más sencilla de obtener una cadena ISO 8601 en C#. Pero hay un matiz: si su DateTime tiene Kind = Unspecified, al final de la cadena no habrá indicación de zona horaria. Esto puede ser un problema para analizadores estrictos. La solución es usar siempre DateTimeOffset o establecer explícitamente el Kind.
¿Cómo obtener ISO 8601 sin milisegundos?
\n\nA veces los milisegundos (o incluso los tics) no son necesarios. Por ejemplo, para registros o fechas simples. Use un formato personalizado:
\n\nDateTime now = DateTime.UtcNow;\nstring isoShort = now.ToString("yyyy-MM-ddTHH:mm:ssK");\nConsole.WriteLine(isoShort);\n// Ejemplo: 2023-12-25T14:30:00Z\n\nAquí K es el especificador de zona horaria. Para UTC da Z, para hora local da el desplazamiento.
Problema con las zonas horarias: DateTime vs DateTimeOffset
\n\nEl principal dolor de cabeza de los desarrolladores es la confusión entre DateTime y DateTimeOffset. Si desea obtener una fecha ISO 8601 en C# que se interprete sin ambigüedad en cualquier parte del mundo, use DateTimeOffset. Siempre contiene el desplazamiento de UTC.
\n\nDateTimeOffset nowOffset = DateTimeOffset.Now;\nstring isoOffset = nowOffset.ToString("o");\nConsole.WriteLine(isoOffset);\n// Ejemplo: 2023-12-25T14:30:00.1234567+03:00\n\nSi trabaja con DateTime, siempre verifique su propiedad Kind:
- \n
DateTimeKind.Utc— daZal final. \n DateTimeKind.Local— da el desplazamiento local (por ejemplo, +03:00). \n DateTimeKind.Unspecified— no da nada al final. \n