DateIntervalFormatter — fundamentos del formato de intervalos de fecha

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

DateIntervalFormatter es una clase de Foundation en iOS y macOS diseñada para formatear rangos de fechas en cadenas localizadas: “21–25 de julio de 2024”, “del 21 al 25 de julio de 2024” o “Jul 21–25, 2024”. Según Apple Developer Documentation, 2024, DateIntervalFormatter determina automáticamente qué componentes de fecha repetir (si el rango está dentro de un mes, el mes se muestra una vez) y localiza los separadores y el orden de las palabras. A diferencia de la concatenación manual de dos fechas formateadas, esta clase tiene en cuenta las reglas gramaticales del idioma. La clase está disponible desde iOS 8 y macOS 10.10.

Puntos clave

  • DateIntervalFormatter — clase de Foundation para formatear rangos de fechas (iOS 8+)
  • Agrupación automática — los componentes repetidos (mes, año) se muestran una vez
  • Separadores localizados — reglas gramaticales: “al” (español), guion (inglés)
  • Cinco estilos de fecha — .none, .short, .medium, .long, .full para cada extremo del rango
  • Cuatro estilos de hora — mismos niveles de detalle para la parte horaria del rango

¿Qué es DateIntervalFormatter?

DateIntervalFormatter es una subclase de Formatter en Foundation que toma un objeto DateInterval (un rango entre dos fechas) y devuelve una cadena localizada que describe ese rango. Por ejemplo, para el rango del 21 al 25 de julio de 2024, el resultado sería “21–25 de julio de 2024” para es_ES. La clase agrupa inteligentemente los elementos repetidos: si ambas fechas están en el mismo mes, el nombre del mes se muestra una vez.

El valor principal de DateIntervalFormatter es el manejo automático de la gramática de rangos. Al formatear manualmente, un desarrollador tendría que comparar el mes/año de inicio y fin, elegir un separador (guion, “al”, “bis”) y gestionar la declinación. DateIntervalFormatter hace esto automáticamente basándose en los datos de CLDR (Common Locale Data Repository), reduciendo errores en aplicaciones internacionales, especialmente para idiomas con gramática compleja.

Según Unicode CLDR v44 (2024), las reglas de formato de intervalos de fecha varían significativamente entre idiomas. El alemán usa la preposición “bis” (21.–25. Juli 2024), el francés usa “au” (du 21 au 25 juillet 2024), el japonés usa un guion (2024 Jul 21–25). DateIntervalFormatter cubre todas estas variaciones sin código adicional del desarrollador.

¿Cómo funciona DateIntervalFormatter en Foundation?

El principio de funcionamiento de DateIntervalFormatter se basa en analizar dos fechas que forman un rango y seleccionar la representación textual óptima considerando la configuración regional. La clase compara los componentes de fecha (año, mes, día) y toma decisiones de agrupación: si el año es el mismo, se muestra una vez; si el mes es el mismo, se muestra una vez; si los días difieren, se muestra un rango de días.

Rangoes_ES
Un día21 de julio de 2024
Dentro del mes21–25 de julio de 2024
Meses diferentes21 de julio – 5 de agosto de 2024
Años diferentes25 de diciembre de 2024 – 5 de enero de 2025
Con hora21 de julio de 2024, 14:30–16:45

Lógica de agrupación implementada basada en plantillas CLDR. El formateador verifica la igualdad de cada componente de fecha (Calendar.Component: year, month, day) en orden de mayor a menor. Una vez que un componente difiere, todos los componentes menores se muestran para ambas fechas. Por ejemplo, para el 21–25 de julio: el año coincide, el mes coincide, el día difiere → el mes se muestra una vez, los días se muestran para cada fecha.

Nota importante: DateIntervalFormatter no permite personalizar el separador a través de la API. El separador está determinado por la configuración regional y no se puede sobrescribir. Si se requiere un separador no estándar (por ejemplo, “hasta” en lugar de “al”), tendrías que formatear las fechas manualmente con DateFormatter y concatenar las cadenas con un separador personalizado.

Estilos de formato de intervalos

DateIntervalFormatter proporciona dos conjuntos de estilos: dateStyle y timeStyle para cada extremo del rango. Estos estilos funcionan de manera similar a DateFormatter: .none oculta el componente, .short da un formato corto (21/07/2024), .medium (21 jul 2024), .long (21 de julio de 2024), .full (domingo, 21 de julio de 2024). Combinando dateStyle y timeStyle, se pueden obtener diferentes niveles de detalle.

Ejemplos de combinaciones de estilos

  • dateStyle = .medium, timeStyle = .none — solo fecha: “21–25 de julio de 2024”
  • dateStyle = .short, timeStyle = .short — fecha y hora: “21/07/2024, 14:30 – 25/07/2024, 16:45”
  • dateStyle = .none, timeStyle = .short — solo hora: “14:30–16:45” (si las fechas son iguales)
  • dateStyle = .long, timeStyle = .none — fecha larga: “21–25 de julio de 2024”
  • dateStyle = .full, timeStyle = .short — formato completo: “domingo, 21 de julio de 2024 – jueves, 25 de julio de 2024”

Importante: dateStyle y timeStyle se aplican a ambos extremos del rango por igual. No se pueden establecer estilos diferentes para el inicio y el final (por ejemplo, .medium para el inicio y .short para el final). Si se necesitan estilos diferentes, debes formatear cada fecha con un DateFormatter independiente y concatenar los resultados.

swift
import Foundation

let formatter = DateIntervalFormatter()

// Diferentes combinaciones de estilos
let startDate = Date()
let endDate = Date().addingTimeInterval(345600) // +4 días
let interval = DateInterval(start: startDate, end: endDate)

// Solo fecha, formato medio
formatter.dateStyle = .medium
formatter.timeStyle = .none
print("Solo fecha: \(formatter.string(from: interval))")

// Formato corto con hora
formatter.dateStyle = .short
formatter.timeStyle = .short
print("Corto con hora: \(formatter.string(from: interval))")

// Formato completo
formatter.dateStyle = .full
formatter.timeStyle = .none
print("Fecha completa: \(formatter.string(from: interval))")

DateIntervalFormatter en Swift: ejemplos

Uso básico de DateIntervalFormatter incluye crear una instancia, configurar estilos y llamar a string(from:). El método acepta DateInterval, una estructura con propiedades start y end. DateInterval se puede crear a partir de dos valores Date o inicializarse con Duration (iOS 16+). Después del formateo, el resultado está listo para mostrarse en la interfaz sin procesamiento adicional.

swift
import Foundation

let calendar = Calendar.current
let now = Date()

// Ejemplos de intervalos específicos
let examples: [(title: String, start: Date, end: Date)] = [
    (
        "2-hour event",
        now,
        now.addingTimeInterval(7200)
    ),
    (
        "Week-long vacation",
        now,
        now.addingTimeInterval(604800)
    ),
    (
        "Cross-year period",
        calendar.date(from: DateComponents(
            year: 2024, month: 12, day: 25
        ))!,
        calendar.date(from: DateComponents(
            year: 2025, month: 1, day: 5
        ))!
    )
]

let intervalFormatter = DateIntervalFormatter()
intervalFormatter.dateStyle = .medium
intervalFormatter.timeStyle = .short

for (title, start, end) in examples {
    let interval = DateInterval(start: start, end: end)
    let result = intervalFormatter.string(from: interval)
    print("\(title): \(result)")
}

// Formato mediante Calendar (iOS 16+)
if let nextWeek = calendar.date(
    byAdding: .day, value: 7, to: now
) {
    let weekInterval = DateInterval(start: now, end: nextWeek)
    print("Próximos 7 días: \(intervalFormatter.string(from: weekInterval))")
}

DateIntervalFormatter y reservas de calendario: en aplicaciones de reservas (hoteles, billetes), los intervalos de fecha son un elemento clave de la interfaz. DateIntervalFormatter maneja correctamente los intervalos entre años (por ejemplo, del 28 de diciembre al 3 de enero), agrupando mes y año para cada fecha por separado. Para estos escenarios, se recomienda usar dateStyle = .medium y timeStyle = .none, el formato más legible para fechas sin hora.

swift
import Foundation

let formatter = DateIntervalFormatter()
formatter.dateStyle = .long
formatter.timeStyle = .none

// Ejemplos de reservas
struct Booking {
    let checkIn: Date
    let checkOut: Date

    var formattedInterval: String {
        let interval = DateInterval(start: checkIn, end: checkOut)
        return formatter.string(from: interval)
    }
}

let booking = Booking(
    checkIn: calendar.date(from: DateComponents(
        year: 2024, month: 7, day: 21
    ))!,
    checkOut: calendar.date(from: DateComponents(
        year: 2024, month: 7, day: 25
    ))!
)
print("Reserva: \(booking.formattedInterval)")

// Usar con diferentes configuraciones regionales
let enFormatter = DateIntervalFormatter()
enFormatter.dateStyle = .medium
enFormatter.timeStyle = .none
enFormatter.locale = Locale(identifier: "en_US")
print("Inglés: \(enFormatter.string(from: interval))")

DateInterval vs DateIntervalFormatter: DateInterval es una estructura que representa un rango de fechas (inicio y fin). DateIntervalFormatter es un formateador que convierte esta estructura en una cadena. DateInterval también admite comprobaciones contains(Date) e intersection(with:), útil para la lógica de reservas (verificar superposición de fechas).

Localización de intervalos de fecha

DateIntervalFormatter localiza la salida a través de la propiedad locale. Por defecto, se usa Locale.current, la configuración regional del dispositivo. Para mostrar intervalos en otro idioma (por ejemplo, contenido en inglés con interfaz en ruso), establece la locale explícitamente. A diferencia de DateFormatter, DateIntervalFormatter no requiere configurar la locale para datos del servidor. Siempre usa su lógica de agrupación interna basada en CLDR.

Las diferencias de idioma en el formato de intervalos de fecha son significativamente más complejas que para fechas individuales. El español usa la preposición “al”: del 21 al 25 de julio. El inglés usa un guion simple: Jul 21–25. El francés usa la preposición “au”: du 21 au 25 juillet. El alemán usa un punto después del número y un guion: 21.–25. Juli. DateIntervalFormatter cubre todas estas variantes.

swift
import Foundation

let formatter = DateIntervalFormatter()
formatter.dateStyle = .medium
formatter.timeStyle = .none

let start = Date()
let end = Date().addingTimeInterval(259200) // +3 días
let interval = DateInterval(start: start, end: end)

// Demostrar diferentes configuraciones regionales
let localeIds = ["ru_RU", "en_US", "de_DE", "fr_FR", "ja_JP", "zh_CN"]
for localeId in localeIds {
    formatter.locale = Locale(identifier: localeId)
    print("\(localeId): \(formatter.string(from: interval))")
}

// Localización para intervalos de tiempo
formatter.dateStyle = .none
formatter.timeStyle = .short

let todayStart = Date()
let todayEnd = Date().addingTimeInterval(3600)
let timeInterval = DateInterval(start: todayStart, end: todayEnd)

for localeId in ["ru_RU", "en_US", "de_DE"] {
    formatter.locale = Locale(identifier: localeId)
    print("\(localeId) hora: \(formatter.string(from: timeInterval))")
}

Particularidades de localización: para español, DateIntervalFormatter usa la preposición “al” para formatos largos. Para formatos cortos, usa el guion. La elección del formato depende del contexto: para una lista de reservas usa .medium, para vista detallada usa .long o .full.

Comparación con otros formateadores de fecha

DateIntervalFormatter ocupa el nicho de formateo de rangos de fechas, que no cubren otras clases de Foundation. DateFormatter formatea fechas individuales, RelativeDateTimeFormatter formatea fechas relativas (hace/dentro de), DateComponentsFormatter formatea duración (2 horas 30 minutos). Cada una de estas clases resuelve una tarea específica y no se pueden usar indistintamente.

ClasePropósitoEjemplo de salida
DateIntervalFormatterRango de fechas21–25 de julio de 2024
DateFormatterFecha individual21 de julio de 2024
RelativeDateTimeFormatterTiempo relativohace 3 días
DateComponentsFormatterDuración2 horas 30 minutos
ISO8601DateFormatterFormato ISO 86012024-07-21T14:30:00Z

Cuándo usar DateIntervalFormatter: para mostrar rangos de fechas en la interfaz — reservas de hoteles, eventos, filtrado por fechas, historial de operaciones. Para calcular la duración entre fechas, usa DateComponentsFormatter, no DateIntervalFormatter, ya que este último no está diseñado para mostrar duración. DateFormatter debe usarse solo para fechas individuales, no para concatenar dos fechas formateadas mediante concatenación de cadenas, ya que esto provoca pérdida de localización del separador.

Caso extremo: DateIntervalFormatter no admite la visualización de intervalos abiertos (sin fecha de fin). Si se desconoce el final del rango (por ejemplo, “desde el 21 de julio”), usa DateFormatter con la preposición “desde”. Además, DateIntervalFormatter no admite intervalos con hora especificada para días diferentes. La hora se aplica a cada fecha por separado, lo que puede resultar redundante para intervalos cortos.

Preguntas frecuentes

¿Qué es DateIntervalFormatter?

DateIntervalFormatter es una clase de Foundation para formatear rangos de fechas en cadenas localizadas. Disponible desde iOS 8, agrupa automáticamente los componentes repetidos (mes, año) y selecciona el separador correcto para el idioma.

¿Cómo agrupa fechas DateIntervalFormatter?

Compara componentes desde el año hasta el día. Si el año coincide, se muestra una vez. Si el mes coincide, se muestra una vez. Los días diferentes se muestran como un rango. Esto da “21–25 de julio de 2024” en lugar de “21 de julio de 2024 – 25 de julio de 2024”.

¿Se puede cambiar el separador del rango?

No, el separador está determinado por la configuración regional y no se puede personalizar mediante la API. Para un separador personalizado (por ejemplo, “hasta” en lugar de “al”), formatea cada fecha con un DateFormatter independiente y concatena las cadenas manualmente.

¿En qué se diferencia DateIntervalFormatter de DateFormatter?

DateIntervalFormatter formatea un rango de fechas (dos fechas) como una unidad única con agrupación de componentes. DateFormatter formatea una fecha individual. Para rangos, usa siempre DateIntervalFormatter, ya que proporciona la localización correcta del separador.

¿Cómo formatear un intervalo con años diferentes?

Automáticamente — DateIntervalFormatter detecta que los años difieren y muestra las fechas completas para ambos extremos: “25 de diciembre de 2024 – 5 de enero de 2025”. No se requiere configuración adicional, solo establecer dateStyle.

Resumen

  • DateIntervalFormatter — clase especializada para formatear rangos de fechas (iOS 8+)
  • Agrupación automática — los componentes repetidos (año, mes) se muestran una vez para todo el rango
  • Separadores localizados — “al” (español), “bis” (alemán) automáticamente
  • Estilos de fecha y hora — combinaciones de .none, .short, .medium, .long, .full para cada extremo del rango
  • No para duración — para calcular duración usa DateComponentsFormatter
  • Sin separadores personalizados — para casos no estándar se requiere formateo manual
  • Integración con DateInterval — la estructura DateInterval proporciona comprobaciones contains e intersection

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