ISO8601DateFormatter: conceptos clave y formato ISO 8601

Autor: IT Sectr Publicado: 2026-07-13 Tiempo de lectura: 9 min

ISO8601DateFormatter es una clase de Foundation en iOS y macOS diseñada para formatear y analizar fechas en el estándar internacional ISO 8601. Según Apple Developer Documentation, 2024, ISO8601DateFormatter maneja automáticamente formatos con milisegundos, zonas horarias y fracciones de segundo sin necesidad de establecer DateFormat manualmente. A diferencia de DateFormatter, esta clase no depende de Locale ni TimeZone — funciona estrictamente según la especificación ISO 8601, lo que la hace ideal para el intercambio de fechas entre servidor y cliente. La clase está disponible desde iOS 10 y macOS 10.12.

Puntos Clave

  • ISO8601DateFormatter — clase de Foundation para formatear fechas según el estándar ISO 8601
  • No requiere DateFormat — el formato se determina automáticamente mediante la configuración de opciones
  • Independiente de locale — funciona igual en todos los dispositivos sin configurar Locale
  • Soporte de milisegundos — maneja fracciones de segundo de cualquier precisión (tres, seis o más dígitos)
  • Opciones de formato — withFullDate, withTime, withMilliseconds, withTimeZone y otras controlan los componentes de salida

¿Qué es ISO8601DateFormatter?

ISO8601DateFormatter es una subclase especializada de Formatter en Foundation que implementa la conversión bidireccional entre Date y cadenas en formato ISO 8601. El estándar ISO 8601 (International Standard for the Representation of Dates and Times) define un formato internacional para el intercambio de fechas y horas: 2024-07-21T14:30:00+00:00. A diferencia de DateFormatter, esta clase no requiere especificar dateFormat y determina automáticamente la estructura de la cadena según las opciones proporcionadas.

Las principales ventajas de ISO8601DateFormatter sobre DateFormatter: ausencia de dependencia de locale (el análisis funciona igual en cualquier dispositivo), soporte integrado para fracciones de segundo (con cualquier número de decimales) y detección automática del formato según las opciones pasadas. La clase también maneja correctamente el sufijo Z (designación UTC), zonas horarias en formato +HH:mm y precisión reducida (solo fecha sin hora).

Según la Especificación ISO (ISO 8601-1:2019), el estándar admite cuatro niveles de precisión: año (2024), año-mes (2024-07), fecha completa (2024-07-21) y fecha-hora con zona horaria (2024-07-21T14:30:00+00:00). ISO8601DateFormatter cubre todos estos niveles mediante una combinación de opciones de formato, liberando al desarrollador de la construcción manual de cadenas dateFormat.

¿Cómo funciona ISO8601DateFormatter en Foundation?

El principio de funcionamiento de ISO8601DateFormatter se basa en una combinación de opciones de bits (formatOptions), cada una de las cuales incluye un componente específico de fecha u hora en la salida. Por ejemplo, la opción .withFullDate incluye año, mes y día; .withTime incluye horas, minutos y segundos. Combinando opciones, el desarrollador obtiene el nivel de precisión deseado sin escribir una cadena dateFormat.

Internamente, ISO8601DateFormatter utiliza la biblioteca ICU para el análisis, pero con reglas fijas de ISO 8601. Esto significa que ignora la configuración de Locale y TimeZone del dispositivo — el resultado siempre es predecible. Para establecer la zona horaria se utiliza la propiedad timeZone, cuyo valor predeterminado es UTC. Si timeZone se establece en nil, se utiliza la hora local del dispositivo.

OpciónDescripciónEjemplo de salida
.withFullDateAño, mes, día2024-07-21
.withTimeHoras, minutos, segundos14:30:00
.withMillisecondsFracciones de segundo (hasta 3 dígitos).123
.withFractionalSecondsFracciones de segundo (cualquier precisión).123456
.withTimeZoneZona horaria+03:00
.withColonSeparatorInTimeZoneSeparador de dos puntos en zona horaria+03:00 (frente a +0300)
.withInternetDateTimeFormato completo (fecha + hora + tz)2024-07-21T14:30:00+00:00

Combinación de opciones: .withInternetDateTime es equivalente a combinar .withFullDate, .withTime y .withTimeZone. Para analizar cadenas con milisegundos, añada .withFractionalSeconds. Es importante recordar que .withMilliseconds limita las fracciones de segundo a tres dígitos, mientras que .withFractionalSeconds admite cualquier precisión — de uno a nueve dígitos después del punto decimal.

Opciones de formato ISO 8601

Las opciones de formato de ISO8601DateFormatter se dividen en tres grupos: componentes de fecha (withFullDate, withYear, withMonth, withDay, withWeekOfYear), componentes de hora (withTime, withHours, withMinutes, withSeconds) y configuraciones adicionales (withMilliseconds, withFractionalSeconds, withTimeZone, withColonSeparatorInTimeZone, withDashSeparatorInDate, withFullTime). Combinándolos, se puede obtener prácticamente cualquier subformato ISO 8601.

Combinaciones principales de opciones

  • .withFullDate — solo fecha: 2024-07-21. Para analizar cadenas con formato YYYY-MM-DD
  • .withFullDate + .withTime — fecha y hora sin zona horaria: 2024-07-21T14:30:00
  • .withInternetDateTime — formato completo: 2024-07-21T14:30:00Z o 2024-07-21T14:30:00+03:00
  • .withInternetDateTime + .withFractionalSeconds — con fracciones de segundo: 2024-07-21T14:30:00.123456+00:00
  • .withFullDate + .withTime + .withTimeZone — formato completo sin dos puntos en tz: 2024-07-21T14:30:00+0300

Matiz importante: .withFractionalSeconds y .withMilliseconds son mutuamente excluyentes — si se establecen ambas, se aplica .withFractionalSeconds. Para analizar milisegundos de datos del servidor, se recomienda .withFractionalSeconds, ya que muchos servidores envían fracciones de segundo con tres, seis o nueve dígitos, y .withFractionalSeconds maneja cualquier longitud.

swift
import Foundation

// Configure ISO8601DateFormatter
let formatter = ISO8601DateFormatter()
formatter.timeZone = TimeZone(secondsFromGMT: 0)

// Different format option combinations
formatter.formatOptions = [.withFullDate]
let dateOnly = formatter.string(from: Date())
print("Date: \(dateOnly)")

formatter.formatOptions = [.withFullDate, .withTime]
let dateTime = formatter.string(from: Date())
print("DateTime: \(dateTime)")

formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
let full = formatter.string(from: Date())
print("Full: \(full)")

// Parse string with milliseconds
let serverString = "2024-07-21T14:30:00.123456+03:00"
if let parsed = formatter.date(from: serverString) {
    print("Parsed: \(parsed)")
}

ISO8601DateFormatter en Swift: ejemplos de código

Uso básico de ISO8601DateFormatter se reduce a crear una instancia, configurar timeZone (se recomienda UTC para datos del servidor) y formatOptions, después de lo cual se puede llamar a string(from:) para formatear y date(from:) para analizar. A diferencia de DateFormatter, no es necesario preocuparse por Locale — la clase ignora la configuración regional.

swift
import Foundation

let formatter = ISO8601DateFormatter()

// Parse different ISO 8601 formats
let strings: [String] = [
    "2024-07-21T14:30:00Z",
    "2024-07-21T14:30:00+03:00",
    "2024-07-21T14:30:00.123Z",
    "2024-07-21"
]

for str in strings {
    if let autoParsed = formatter.date(from: str) {
        print("Parsed '\(str)': \(autoParsed)")
    } else {
        // Use withFullDate for date-only strings
        formatter.formatOptions = [.withFullDate]
        if let fallback = formatter.date(from: str) {
            print("Fallback parsed '\(str)': \(fallback)")
        }
        formatter.formatOptions = [.withInternetDateTime]
    }
}

// Serialize to RFC 3339 (GitHub API)
formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
let rfc3339 = formatter.string(from: Date())
print("RFC 3339: \(rfc3339)")

Analizar fechas con fracciones de segundo de longitud variable es una característica de muchas API modernas. Un servidor puede enviar 2024-07-21T14:30:00.123Z (3 dígitos) o 2024-07-21T14:30:00.123456Z (6 dígitos). ISO8601DateFormatter con la opción .withFractionalSeconds manejará correctamente ambos casos, mientras que DateFormatter con dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ" solo manejará milisegundos de tres dígitos.

swift
import Foundation

let variantFormatter = ISO8601DateFormatter()
variantFormatter.formatOptions = [
    .withInternetDateTime,
    .withFractionalSeconds
]

// Different fractional second precision
let variants: [String] = [
    "2024-07-21T14:30:00.1Z",
    "2024-07-21T14:30:00.12Z",
    "2024-07-21T14:30:00.123Z",
    "2024-07-21T14:30:00.123456Z",
    "2024-07-21T14:30:00.123456789Z"
]

for variant in variants {
    if let parsed = variantFormatter.date(from: variant) {
        print("OK: \(variant) -> \(parsed)")
    } else {
        print("FAIL: \(variant)")
    }
}

// Use withMilliseconds (3 digits only)
variantFormatter.formatOptions = [
    .withInternetDateTime,
    .withMilliseconds
]
let milliParsed = variantFormatter.string(from: Date())
print("With milliseconds: \(milliParsed)")

Prueba de análisis de todas las variantes: el código mostrado demuestra que ISO8601DateFormatter con .withFractionalSeconds maneja con éxito fracciones de segundo de cualquier longitud, de 1 a 9 dígitos. Esto es importante para la compatibilidad con diferentes plataformas de servidor: .NET a menudo genera 7 dígitos (ticks de 100 nanosegundos), Python — 6, Java — 3 o 9 según la versión.

Comparación con DateFormatter para ISO 8601

DateFormatter también puede analizar ISO 8601, pero requiere configuración manual de dateFormat, locale y timeZone. El problema principal es que DateFormatter depende de Locale, y si no se establece en_US_POSIX, el análisis puede fallar para usuarios de regiones con formatos de fecha no estándar. ISO8601DateFormatter resuelve este problema a nivel de arquitectura: no utiliza Locale.

ParámetroISO8601DateFormatterDateFormatter
Configuración de LocaleNo requerida (lo ignora)en_US_POSIX obligatorio
DateFormatAutomático (mediante opciones)Cadena de formato manual
Fracciones de segundoCualquier precisión (.withFractionalSeconds)SSS fijo
Sufijo ZManeja correctamenteMediante dateFormat
RendimientoMayor (especializado)Menor (general)
EstándarSolo ISO 8601Cualquier formato
Versión de iOSiOS 10+iOS 2+

Cuándo usar DateFormatter: si necesita formatear una fecha en un formato que no sea ISO 8601 (por ejemplo, "21 de julio de 2024" para la UI) o si necesita soporte para iOS 9 y versiones anteriores. Para todas las tareas de intercambio de fechas entre servidor y cliente, use ISO8601DateFormatter — es más seguro, más eficiente y requiere menos código. DateFormatter para ISO 8601 es una fuente de posibles errores relacionados con la configuración regional.

Migración de DateFormatter a ISO8601DateFormatter: reemplace la creación de DateFormatter + configuración de dateFormat + locale + timeZone por la creación de ISO8601DateFormatter + configuración de formatOptions + timeZone. El análisis de la cadena permanece sin cambios mediante date(from:). Para compatibilidad hacia atrás, puede usar #available(iOS 10, *) con un fallback a DateFormatter.

Errores comunes al analizar ISO 8601

Configuración olvidada de formatOptions hace que el formateador use el valor predeterminado — .withInternetDateTime. Si el servidor envía una fecha sin hora (2024-07-21), el análisis devolverá nil. Siempre verifique que formatOptions cubra todos los formatos posibles que puedan llegar del servidor. Para API con formatos variables, use intentos de fallback con diferentes combinaciones de opciones.

Confusión entre withMilliseconds y withFractionalSeconds es un error común al analizar fechas con fracciones de segundo. withMilliseconds espera exactamente 3 dígitos después del punto decimal. Si el servidor envía 6 dígitos (microsegundos), el análisis con withMilliseconds fallará. Use .withFractionalSeconds para compatibilidad con cualquier cantidad de dígitos. .withFractionalSeconds está disponible desde iOS 13; para versiones anteriores, use DateFormatter con dateFormat.

Ignorar la zona horaria es otro problema frecuente. Si el servidor envía una fecha con zona horaria (+03:00) y el formateador está configurado en UTC, el análisis no fallará, pero el resultado estará en UTC. Los desarrolladores a menudo esperan que Date conserve la zona horaria, pero Date es un momento absoluto en el tiempo — no almacena información de zona horaria. Para una visualización correcta, guarde la zona horaria por separado o use ISO8601DateFormatter con el timeZone adecuado.

Según Apple Forum (2024), alrededor del 20% de las preguntas sobre ISO8601DateFormatter están relacionadas con el formato donde los segundos son opcionales. El estándar ISO 8601 permite un formato sin segundos: 2024-07-21T14:30+03:00. ISO8601DateFormatter con .withInternetDateTime no admite este formato — para analizarlo se necesitará DateFormatter con dateFormat = "yyyy-MM-dd'T'HH:mmZ". Esta limitación es importante al trabajar con API que utilizan el formato de hora abreviado.

Preguntas Frecuentes

¿Qué es ISO8601DateFormatter?

ISO8601DateFormatter es una clase especializada de Foundation para formatear y analizar fechas en formato ISO 8601, disponible desde iOS 10. Maneja automáticamente formatos estándar sin necesidad de establecer dateFormat manualmente.

¿En qué se diferencia ISO8601DateFormatter de DateFormatter?

ISO8601DateFormatter no depende de Locale, usa opciones en lugar de dateFormat y maneja correctamente fracciones de segundo de cualquier longitud. DateFormatter es universal, pero requiere configuración manual y es propenso a errores relacionados con la configuración regional.

¿Cómo manejar fracciones de segundo de longitud variable?

Use la opción .withFractionalSeconds — admite de 1 a 9 dígitos después del punto decimal. No use .withMilliseconds si la precisión puede variar. .withFractionalSeconds está disponible desde iOS 13.

¿Qué zona horaria usa ISO8601DateFormatter?

UTC por defecto. Para cambiarla, configure la propiedad timeZone. Si timeZone = nil, se usa la hora local del dispositivo. Al analizar una cadena con zona horaria explícita en formato +HH:MM, el formateador la tiene en cuenta automáticamente.

¿Por qué analizar una fecha sin hora devuelve nil?

Porque formatOptions por defecto es .withInternetDateTime, que espera fecha + hora + zona horaria. Para analizar solo la fecha, establezca formatOptions = [.withFullDate]. Para admitir ambos formatos, use fallback con diferentes opciones.

Resumen

  • ISO8601DateFormatter — clase especializada para ISO 8601, más segura y simple que DateFormatter
  • Opciones de formato reemplazan el dateFormat manual — combine .withFullDate, .withTime, .withTimeZone
  • Independiente de Locale — el análisis funciona igual en todos los dispositivos sin configurar locale
  • .withFractionalSeconds maneja fracciones de segundo de cualquier precisión (1–9 dígitos)
  • DateFormatter es inferior en rendimiento, seguridad y simplicidad para tareas ISO 8601
  • Confusión de opciones — withMilliseconds y withFractionalSeconds no son intercambiables
  • Formato sin segundos (2024-07-21T14:30+03:00) no es compatible — se necesita DateFormatter

Desarrollaremos una aplicación móvil llave en mano

IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.

Discutir el proyecto

Lea también