Trabajo con fechas y horas en Swift: técnicas avanzadas

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

Trabajo avanzado con fechas y horas en Swift: de lo básico a la optimización

\n

Trabajar con fechas y horas es una de las tareas más comunes y, al mismo tiempo, más engañosas en el desarrollo de iOS/macOS. La aparente simplicidad de la API de Foundation (Date, DateFormatter, Calendar) a menudo conduce a errores relacionados con zonas horarias, localización o rendimiento. En este artículo, analizaremos técnicas avanzadas para trabajar con fechas en Swift: desde un análisis correcto hasta cálculos de alto rendimiento que serán útiles en proyectos de producción.

\n\n

1. DateFormatter: ajuste fino y almacenamiento en caché

\n

El error más común de los principiantes es crear un nuevo objeto DateFormatter dentro de un bucle o un método llamado con frecuencia. Crear un DateFormatter es una operación costosa (hasta 1000 veces más lenta que reutilizarlo).

\n\n
// ❌ Mal: creamos un formatter cada vez\nfunc parseDate(from string: String) -> Date? {\n    let formatter = DateFormatter()\n    formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"\n    formatter.locale = Locale(identifier: "ru_RU")\n    formatter.timeZone = TimeZone(secondsFromGMT: 0)\n    return formatter.date(from: string)\n}\n\n// ✅ Bien: almacenamos en caché el formatter\nprivate let isoDateFormatter: DateFormatter = {\n    let f = DateFormatter()\n    f.dateFormat = "yyyy-MM-dd HH:mm:ss"\n    f.locale = Locale(identifier: "ru_RU")\n    f.timeZone = TimeZone(secondsFromGMT: 0)\n    return f\n}()\n\nfunc parseDateFast(from string: String) -> Date? {\n    return isoDateFormatter.date(from: string)\n}
\n\n

Consejo avanzado: Para trabajar con formatos fijos (por ejemplo, ISO 8601), usa ISO8601DateFormatter — es más rápido que el DateFormatter estándar. Para formatos personalizados que requieren alto rendimiento, considera DateFormatter con almacenamiento local de hilo:

\n\n
extension DateFormatter {\n    static let threadLocal: ThreadLocal<DateFormatter> = ThreadLocal {\n        let f = DateFormatter()\n        f.dateFormat = "dd.MM.yyyy"\n        f.locale = Locale(identifier: "ru_RU")\n        return f\n    }\n}
\n\n

2. Calendar y DateComponents: cálculos sin errores

\n

Para la aritmética de fechas (agregar un día, encontrar el inicio del mes), usa Calendar, no la suma manual de segundos. Agregar manualmente 86400 segundos (24*60*60) falla durante el cambio al horario de verano.

\n\n
let calendar = Calendar.current\nlet now = Date()\n\n// ✅ Agregamos 1 día de forma segura\nif let tomorrow = calendar.date(byAdding: .day, value: 1, to: now) {\n    print("Mañana: \\(tomorrow)")\n}\n\n// ✅ Encontramos el inicio del mes actual\nlet startOfMonth = calendar.date(from: calendar.dateComponents([.year, .month], from: now))!\n\n// ✅ Obtenemos componentes teniendo en cuenta la configuración regional\nlet components = calendar.dateComponents([.weekday, .weekOfYear], from: now)\nprint("Día de la semana: \\(components.weekday ?? 0)") // 1 = domingo en EE. UU., 2 = lunes en RF
\n\n

Consejo avanzado: Para cálculos de alta carga (por ejemplo, generación de una cuadrícula de calendario), almacena en caché Calendar y TimeZone. Evita usar Calendar.current en bucles: cada vez accede a la configuración del sistema.

\n\n

3. Localización y formato para el usuario

\n

Nunca muestres al usuario una fecha en bruto. Usa DateFormatter con estilos predefinidos (.short, .medium, .long, .full) y RelativeDateTimeFormatter para fechas relativas legibles por humanos ("ayer", "hace 3 días").

\n\n
// Fecha absoluta teniendo en cuenta la configuración regional del usuario\nlet userFormatter = DateFormatter()\nuserFormatter.dateStyle = .long\nuserFormatter.timeStyle = .short\nprint(userFormatter.string(from: Date())) // "15 de junio de 2025, 14:30" (para es_ES)\n\n// Fecha relativa (iOS 13+)\nlet relativeFormatter = RelativeDateTimeFormatter()\nrelat                

Blogs

Book Recommendations