TimeZone — qué es, clase Foundation y zonas horarias

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

TimeZone es una clase Foundation en iOS y macOS que abstrae la información de las zonas horarias para la conversión correcta del tiempo entre regiones geográficas. Según Apple Developer Documentation, 2024, TimeZone proporciona métodos para trabajar con identificadores de zonas horarias (IANA Time Zone Database), desfases con respecto a UTC y reglas de cambio al horario de verano. La clase está integrada con DateFormatter y Calendar, lo que garantiza la aplicación automática de la zona horaria correcta al formatear fechas. A diferencia del cálculo manual del desfase, TimeZone actualiza automáticamente los datos cuando cambia la zona horaria del dispositivo.

Puntos clave

  • TimeZone — una clase Foundation para trabajar con zonas horarias en iOS y macOS
  • IANA Time Zone Database — la fuente principal de identificadores de zonas horarias (America/New_York, Europe/Moscow)
  • Corrección automática — TimeZone maneja el horario de verano sin código adicional
  • Integración con DateFormatter — la zona horaria se aplica automáticamente al formatear fechas
  • Tres tipos — local (actual), fijo (especificado por identificador) y UTC

¿Qué es TimeZone en Foundation?

TimeZone es un tipo de valor en Swift que proporciona información sobre una zona horaria geográfica: desfase UTC, nombre, abreviatura y reglas de cambio al horario de verano. En Objective-C, la clase se llama NSTimeZone. Ambas clases se basan en la IANA Time Zone Database (también conocida como base de datos Olson), que contiene el historial de cambios de zonas horarias desde 1970.

Cada instancia de TimeZone almacena un identificador de zona horaria (por ejemplo, Europe/Moscow), el desfase actual en segundos desde UTC, el indicador isDaylightSavingTime y la fecha de la próxima transición. El identificador es la clave principal: al inicializar TimeZone(identifier:), el sistema carga el registro correspondiente de la base de datos de zonas horarias del dispositivo.

Según IANA (2024), la base de datos contiene más de 600 identificadores únicos de zonas horarias. Apple distribuye una instantánea de esta base de datos con cada versión de iOS y macOS, lo que garantiza cálculos consistentes en todos los dispositivos sin necesidad de solicitudes de red.

¿Cómo funciona TimeZone en iOS y macOS?

Arquitectura de TimeZone en Foundation se basa en un sistema de dos niveles: el identificador de zona horaria (nombre legible para humanos) y su representación numérica (desfase UTC). El sistema selecciona automáticamente la zona horaria actual desde la configuración del dispositivo, pero el desarrollador puede sobrescribirla para operaciones de formato específicas.

TimeZone está estrechamente vinculado a Calendar y DateFormatter. Al formatear una fecha, DateFormatter utiliza la propiedad timeZone de una instancia de TimeZone para convertir un momento absoluto en el tiempo (Date) en una representación de cadena en la zona horaria deseada. Si no se establece timeZone, se utiliza la zona horaria del sistema por defecto — TimeZone.current.

Tipos de instancias de TimeZone

TipoInicializaciónCaracterísticas
ActualTimeZone.currentSe actualiza automáticamente al cambiar la región en la configuración, rastrea el horario de verano
FijoTimeZone(identifier:)Independiente de la región del dispositivo. Aplica consistentemente el identificador seleccionado
UTCTimeZone(secondsFromGMT: 0)Zona horaria sin corrección. Identificador: GMT
Con desfase arbitrarioTimeZone(secondsFromGMT: 10800)Desfase fijo en segundos. No tiene en cuenta el horario de verano

Nota importante: TimeZone(identifier:) devuelve nil para identificadores desconocidos. Esta es una causa común de fallos en la aplicación: los desarrolladores olvidan manejar el valor opcional al pasar un identificador inválido desde la entrada del usuario. Para los identificadores IANA, las mayúsculas/minúsculas importan: Europe/Moscow es válido, europe/moscow devuelve nil.

Formatos de identificadores de zonas horarias

La IANA Time Zone Database utiliza el formato “Región/Ciudad” (Continente/Ciudad), donde la región es uno de los continentes (Africa, America, Asia, Atlantic, Australia, Europe, Indian, Pacific) o un océano, y la ciudad es la localidad más poblada dentro del área de cobertura de la zona horaria. Este formato garantiza la unicidad y legibilidad del identificador.

Además del formato principal, TimeZone admite tres métodos adicionales de identificación: abreviaturas (MSK, EST, PST), códigos de tres letras de zonas horarias (GMT, UTC) y desfases numéricos (+0300, -0500). Sin embargo, las abreviaturas son ambiguas: EST puede significar Eastern Standard Time (GMT-5) o Eastern Summer Time (GMT+10) en Australia. Apple recomienda utilizar únicamente identificadores IANA.

swift
import Foundation

// Obtener todos los identificadores de zona horaria conocidos
let allIdentifiers: [String] = TimeZone.knownTimeZoneIdentifiers
print("Total de zonas horarias: \(allIdentifiers.count)")

// Filtrar por región
let europeZones = allIdentifiers.filter { $0.hasPrefix("Europe/") }
print("Zonas horarias europeas: \(europeZones)")

// Abreviaturas (no recomendado para producción)
if let moscowTimeZone = TimeZone(abbreviation: "MSK") {
    print("Segundos MSK desde GMT: \(moscowTimeZone.secondsFromGMT())")
}

// Encontrar identificador por desfase
let utcPlus3 = TimeZone(secondsFromGMT: 10800)
print("Identificador: \(utcPlus3.identifier)")

Abreviaturas en TimeZone.abbreviationDictionary contienen abreviaturas para todas las zonas horarias conocidas, pero este diccionario no garantiza unicidad: la clave PST puede corresponder a America/Los_Angeles o Pacific/Pago_Pago. Para código de producción, utilice siempre identificadores IANA.

Horario de verano y TimeZone

TimeZone tiene en cuenta automáticamente los cambios al horario de verano (DST) para todas las regiones donde se aplica. El sistema utiliza datos históricos de la IANA Time Zone Database, que incluye fechas precisas de transición para cada zona horaria. La propiedad isDaylightSavingTime devuelve true si la zona horaria se encuentra actualmente en horario de verano.

El método nextDaylightSavingTimeTransition permite conocer la fecha de la próxima transición, útil para planificar eventos futuros. Esta funcionalidad es especialmente importante para regiones con cambios frecuentes en las reglas DST, como Brasil o Marruecos — hasta 2024, Brasil cambiaba las fechas de transición anualmente, y el cálculo manual provocaba errores en las aplicaciones.

Según Apple WWDC 2023, la biblioteca ICU (International Components for Unicode), que subyace a Foundation, actualiza los datos DST con cada actualización de iOS. Las aplicaciones no deben almacenar en caché los datos del horario de verano por más de un día después de una actualización del sistema — la base de datos IANA puede cambiar incluso sin una actualización de la versión del SO mediante ajustes de zonas horarias.

swift
import Foundation

// Verificar DST para Europe/Moscow
let moscow = TimeZone(identifier: "Europe/Moscow")!
let now = Date()
let isMoscowDST = moscow.isDaylightSavingTime(for: now)
print("Moscú actualmente en DST: \(isMoscowDST)")

// Obtener la fecha de la próxima transición DST
if let nextTransition = moscow.nextDaylightSavingTimeTransition(
    after: now
) {
    let dstOffset = moscow.daylightSavingTimeOffset(
        for: nextTransition
    )
    print("Próxima transición: \(nextTransition), desfase DST: \(dstOffset)s")
}

// Conversión segura con conocimiento de DST
let newYork = TimeZone(identifier: "America/New_York")!
let offsetNY = newYork.secondsFromGMT(for: now)
print("Desfase actual de NY: \(offsetNY / 3600)h")

Matiz crítico: secondsFromGMT(for:) tiene en cuenta DST para la fecha especificada, mientras que secondsFromGMT() solo se aplica a la hora actual. Al formatear fechas históricas, utilice siempre la versión con el parámetro Date: secondsFromGMT(for: someHistoricalDate). La diferencia puede ser de 1 a 2 horas, lo cual es crítico para registros o datos históricos.

TimeZone en Swift: ejemplos de código

Formateo de una fecha con una zona horaria específica es la tarea más común al trabajar con TimeZone. DateFormatter utiliza la propiedad timeZone para convertir un Date en una cadena. Si no se establece timeZone explícitamente, el formateador utiliza TimeZone.current — la zona horaria configurada en el dispositivo del usuario, lo que puede dar resultados inesperados para datos del servidor.

swift
import Foundation

// Formatear fecha en zona horaria específica
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"

let tokyo = TimeZone(identifier: "Asia/Tokyo")!
formatter.timeZone = tokyo
let tokyoTime = formatter.string(from: Date())
print("Hora de Tokio: \(tokyoTime)")

// Identificadores disponibles para selección del usuario
let displayNames: [(String, String)] = TimeZone.knownTimeZoneIdentifiers
    .prefix(20)
    .map { ($0, TimeZone(identifier: $0)!.localizedName(
        for: .generic, locale: .current
    )) }

// Comparar dos zonas horarias
let london = TimeZone(identifier: "Europe/London")!
let difference = tokyo.secondsFromGMT(for: Date())
    - london.secondsFromGMT(for: Date())
print("Diferencia Tokio-Londres: \(difference / 3600)h")

// Trabajar con diccionario de abreviaturas
let knownAbbrevs = TimeZone.abbreviationDictionary
for (abbr, ident) in knownAbbrevs.sorted(by: { $0.key < $1.key }).prefix(5) {
    print("\(abbr) -> \(ident)")
}

Nombre localizado de una zona horaria mediante localizedName(for:locale:) devuelve un nombre legible para humanos en el idioma especificado. Por ejemplo, para Europe/Moscow con configuración regional rusa, el método devuelve el nombre ruso “Moskva”, y con configuración regional inglesa — “Moscow Time”. Estilos disponibles: .standard (nombre estándar), .daylightSaving (horario de verano) y .shortGeneric (corto).

swift
import Foundation

let paris = TimeZone(identifier: "Europe/Paris")!
let nameRU = paris.localizedName(
    for: .standard,
    locale: Locale(identifier: "ru_RU")
)
print("Nombre en ruso: \(nameRU)")

// Verificar si la región está en el mismo día
let isSameDay = Calendar.current.isDate(
    Date(),
    equalTo: Date(),
    toGranularity: .day
)
print("Mismo día en distintas zonas horarias: \(isSameDay)")

Serialización del identificador de zona horaria es la mejor práctica para almacenar TimeZone en bases de datos o UserDefaults. Guarde el identificador (una cadena como Europe/Moscow), no el desfase en segundos ni una abreviatura. El desfase puede cambiar con los cambios DST, y las abreviaturas son ambiguas. Restauración: TimeZone(identifier: savedString).

Errores típicos al trabajar con TimeZone

Usar un desfase fijo en lugar de un identificador de zona horaria es el error más común. TimeZone(secondsFromGMT: 10800) no tiene en cuenta DST, por lo que para Europe/Moscow en verano, esta construcción da un desfase incorrecto de 1 hora. Utilice siempre el identificador IANA para regiones con horario de verano.

Manejo olvidado de nil al inicializar TimeZone(identifier:) es el segundo error más frecuente. Si un usuario introduce un identificador incorrecto (por ejemplo, “moscow” en lugar de “Europe/Moscow”), el constructor devuelve nil. Sin manejar el valor opcional, la aplicación falla con un error de ejecución. Use guard let o TimeZone(identifier:) con un fallback conocido.

Ignorar DST al trabajar con fechas futuras. TimeZone.secondsFromGMT(for:) es la única forma correcta de obtener el desfase para una fecha específica. Usar secondsFromGMT() sin parámetro para fechas históricas o futuras da el desfase para el momento actual, que puede no coincidir con el desfase real en la fecha especificada, especialmente para regiones que han abolido o introducido DST.

Según Stack Overflow (2024), aproximadamente el 15% de las preguntas sobre DateFormatter están relacionadas con una configuración incorrecta de timeZone. Un escenario típico: el servidor envía una fecha en UTC, el desarrollador la formatea sin establecer el timeZone del formateador, y la fecha se muestra en la zona horaria del dispositivo, creando confusión entre usuarios de diferentes regiones. Regla: establezca siempre explícitamente el timeZone del formateador para datos del servidor.

Preguntas frecuentes

¿Qué es TimeZone en Foundation?

TimeZone es una clase Foundation para trabajar con zonas horarias en iOS y macOS. Proporciona información sobre el desfase UTC, las reglas de horario de verano y los identificadores de zonas horarias basados en la IANA Time Zone Database.

¿Qué formatos de identificadores admite TimeZone?

Tres formatos: identificadores IANA (Europe/Moscow), abreviaturas (MSK, EST) y desfases numéricos (+0300). Apple recomienda usar identificadores IANA como el único formato inequívoco para código de producción.

¿Cómo maneja TimeZone el horario de verano?

Automáticamente a través de los métodos secondsFromGMT(for:) y isDaylightSavingTime(for:). TimeZone utiliza datos históricos de IANA, actualizados con cada versión de iOS, lo que garantiza transiciones DST correctas para cualquier fecha.

¿Cuál es la diferencia entre TimeZone.current y TimeZone.system?

TimeZone.current devuelve la zona horaria seleccionada por el usuario en la configuración (puede diferir de la geográfica). TimeZone.system devuelve la zona horaria del dispositivo, que se determina automáticamente por geolocalización y no puede ser sobrescrita por el usuario.

¿Cómo obtener la zona horaria actual en Swift?

TimeZone.current devuelve la zona horaria actual del dispositivo. Para obtener el identificador, use la propiedad identifier: TimeZone.current.identifier. Para un nombre localizado, llame a localizedName(for:locale:).

Resumen

  • TimeZone — una clase fundamental de Foundation para trabajar con zonas horarias en iOS y macOS
  • Identificadores IANA — la única forma fiable de especificar una zona horaria (Europe/Moscow, America/New_York)
  • Manejo automático de DST — TimeZone maneja correctamente el horario de verano mediante secondsFromGMT(for:)
  • Integración con DateFormatter — la configuración obligatoria de timeZone evita la visualización incorrecta de fechas
  • Nombres localizados — el método localizedName(for:locale:) devuelve el nombre de la zona horaria en el idioma deseado
  • Manejo de errores — la inicialización TimeZone(identifier:) devuelve nil para identificadores no válidos
  • Almacenamiento de identificadores — guarde la cadena IANA para serialización, no el desfase ni la abreviatura

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