DateIntervalFormatter é uma classe Foundation no iOS e macOS projetada para formatar intervalos de datas em strings localizadas: “21–25 de julho de 2024”, “de 21 a 25 de julho de 2024” ou “Jul 21–25, 2024”. De acordo com Apple Developer Documentation, 2024, o DateIntervalFormatter determina automaticamente quais componentes de data repetir (se o intervalo estiver dentro de um mês, o mês é exibido uma vez) e localiza os separadores e a ordem das palavras. Ao contrário da concatenação manual de duas datas formatadas, esta classe leva em conta as regras gramaticais do idioma. A classe está disponível desde o iOS 8 e macOS 10.10.
Pontos principais
DateIntervalFormatter é uma subclasse de Formatter no Foundation que recebe um objeto DateInterval (um intervalo entre duas datas) e retorna uma string localizada descrevendo esse intervalo. Por exemplo, para o intervalo de 21 a 25 de julho de 2024, o resultado seria “21–25 de julho de 2024” para pt_BR. A classe agrupa inteligentemente elementos repetidos: se ambas as datas estiverem no mesmo mês, o nome do mês é exibido uma vez.
O principal valor do DateIntervalFormatter é o tratamento automático da gramática de intervalos. Ao formatar manualmente, um desenvolvedor teria que comparar mês/ano de início e fim, escolher um separador (travessão, “a”, “bis”) e lidar com a declinação. O DateIntervalFormatter faz isso automaticamente com base nos dados do CLDR (Common Locale Data Repository), reduzindo erros em aplicações internacionais, especialmente para idiomas com gramática complexa.
De acordo com Unicode CLDR v44 (2024), as regras de formatação de intervalos de data variam significativamente entre os idiomas. O alemão usa a preposição “bis” (21.–25. Juli 2024), o francês usa “au” (du 21 au 25 juillet 2024), o japonês usa um hífen (2024 Jul 21–25). O DateIntervalFormatter cobre todas essas variações sem código adicional do desenvolvedor.
O princípio de funcionamento do DateIntervalFormatter é baseado na análise de duas datas formando um intervalo e na seleção da representação textual ideal considerando a localidade. A classe compara os componentes de data (ano, mês, dia) e toma decisões de agrupamento: se o ano é o mesmo, é exibido uma vez; se o mês é o mesmo, é exibido uma vez; se os dias diferem, um intervalo de dias é exibido.
| Intervalo | pt_BR |
|---|---|
| Um dia | 21 de julho de 2024 |
| Dentro do mês | 21–25 de julho de 2024 |
| Meses diferentes | 21 de julho – 5 de agosto de 2024 |
| Anos diferentes | 25 de dezembro de 2024 – 5 de janeiro de 2025 |
| Com hora | 21 de julho de 2024, 14:30–16:45 |
Lógica de agrupamento implementada com base em templates CLDR. O formatador verifica a igualdade de cada componente de data (Calendar.Component: year, month, day) na ordem do maior para o menor. Uma vez que um componente difere, todos os componentes menores são exibidos para ambas as datas. Por exemplo, para 21–25 de julho: ano corresponde, mês corresponde, dia difere → mês é exibido uma vez, dias são exibidos para cada data.
Nota importante: DateIntervalFormatter não suporta personalização do separador via API. O separador é determinado pela localidade e não pode ser sobrescrito. Se for necessário um separador não padrão (por exemplo, “até” em vez de “a”), você precisará formatar as datas manualmente usando DateFormatter e concatenar as strings com um separador personalizado.
DateIntervalFormatter fornece dois conjuntos de estilos: dateStyle e timeStyle para cada extremidade do intervalo. Esses estilos funcionam de forma semelhante ao DateFormatter: .none oculta o componente, .short dá um formato curto (21/07/2024), .medium (21 jul 2024), .long (21 de julho de 2024), .full (domingo, 21 de julho de 2024). Combinando dateStyle e timeStyle, diferentes níveis de detalhe podem ser alcançados.
Importante: dateStyle e timeStyle se aplicam a ambas as extremidades do intervalo igualmente. Não é possível definir estilos diferentes para o início e o fim (por exemplo, .medium para o início e .short para o fim). Se forem necessários estilos diferentes, você deve formatar cada data com um DateFormatter separado e concatenar os resultados.
import Foundation
let formatter = DateIntervalFormatter()
// Combinações de estilos diferentes
let startDate = Date()
let endDate = Date().addingTimeInterval(345600) // +4 dias
let interval = DateInterval(start: startDate, end: endDate)
// Apenas data, formato médio
formatter.dateStyle = .medium
formatter.timeStyle = .none
print("Apenas data: \(formatter.string(from: interval))")
// Formato curto com hora
formatter.dateStyle = .short
formatter.timeStyle = .short
print("Curto com hora: \(formatter.string(from: interval))")
// Formato completo
formatter.dateStyle = .full
formatter.timeStyle = .none
print("Data completa: \(formatter.string(from: interval))")
Uso básico do DateIntervalFormatter inclui criar uma instância, definir estilos e chamar string(from:). O método aceita DateInterval, uma estrutura com propriedades start e end. DateInterval pode ser criado a partir de dois valores Date ou inicializado com Duration (iOS 16+). Após a formatação, o resultado está pronto para exibição na interface sem processamento adicional.
import Foundation
let calendar = Calendar.current
let now = Date()
// Exemplos 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)")
}
// Formatar via 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 dias: \(intervalFormatter.string(from: weekInterval))")
}
DateIntervalFormatter e reservas de calendário: em aplicações de reserva (hotéis, bilhetes), os intervalos de data são um elemento chave da interface. DateIntervalFormatter lida corretamente com intervalos entre anos (por exemplo, 28 de dezembro a 3 de janeiro), agrupando mês e ano para cada data separadamente. Para tais cenários, recomenda-se usar dateStyle = .medium e timeStyle = .none, o formato mais legível para datas sem hora.
import Foundation
let formatter = DateIntervalFormatter()
formatter.dateStyle = .long
formatter.timeStyle = .none
// Exemplos 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 com diferentes localidades
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 é uma estrutura que representa um intervalo de datas (início e fim). DateIntervalFormatter é um formatador que converte esta estrutura em uma string. DateInterval também suporta verificação contains(Date) e intersection(with:), útil para lógica de reservas (verificar sobreposição de datas).
DateIntervalFormatter localiza a saída através da propriedade locale. Por padrão, Locale.current é usado, a localidade do dispositivo. Para exibir intervalos em outro idioma (por exemplo, conteúdo em inglês com interface em português), defina a locale explicitamente. Ao contrário do DateFormatter, DateIntervalFormatter não requer definição de locale para dados do servidor. Ele sempre usa sua lógica de agrupamento interna baseada em CLDR.
As diferenças idiomáticas na formatação de intervalos de data são significativamente mais complexas do que para datas individuais. O português usa a preposição “a”: de 21 a 25 de julho. O inglês usa um travessão simples: Jul 21–25. O francês usa a preposição “au”: du 21 au 25 juillet. O alemão usa um ponto após o número e um travessão: 21.–25. Juli. DateIntervalFormatter cobre todas essas variantes.
import Foundation
let formatter = DateIntervalFormatter()
formatter.dateStyle = .medium
formatter.timeStyle = .none
let start = Date()
let end = Date().addingTimeInterval(259200) // +3 dias
let interval = DateInterval(start: start, end: end)
// Demonstrar diferentes localidades
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))")
}
// Localização para intervalos de tempo
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 localização: para português, DateIntervalFormatter usa a preposição “a” para formatos longos. Para formatos curtos, usa o travessão. A escolha do formato depende do contexto: para uma lista de reservas use .medium, para visualização detalhada use .long ou .full.
DateIntervalFormatter preenche o nicho de formatação de intervalos de datas, que não é coberto por outras classes Foundation. DateFormatter formata datas individuais, RelativeDateTimeFormatter formata datas relativas (atrás/em), DateComponentsFormatter formata duração (2 horas 30 minutos). Cada uma dessas classes resolve uma tarefa específica e não podem ser usadas indistintamente.
| Classe | Propósito | Exemplo de saída |
|---|---|---|
| DateIntervalFormatter | Intervalo de datas | 21–25 de julho de 2024 |
| DateFormatter | Data individual | 21 de julho de 2024 |
| RelativeDateTimeFormatter | Tempo relativo | há 3 dias |
| DateComponentsFormatter | Duração | 2 horas 30 minutos |
| ISO8601DateFormatter | Formato ISO 8601 | 2024-07-21T14:30:00Z |
Quando usar DateIntervalFormatter: para exibir intervalos de datas na interface — reservas de hotéis, eventos, filtragem por datas, histórico de operações. Para calcular a duração entre datas, use DateComponentsFormatter, não DateIntervalFormatter, pois este último não foi projetado para exibir duração. DateFormatter deve ser usado apenas para datas individuais, não para concatenar duas datas formatadas via concatenação de strings, pois isso leva à perda de localização do separador.
Caso extremo: DateIntervalFormatter não suporta exibição de intervalos abertos (sem data de término). Se o fim do intervalo for desconhecido (por exemplo, “desde 21 de julho”), use DateFormatter com a preposição “desde”. Além disso, DateIntervalFormatter não suporta intervalos com hora especificada para dias diferentes. A hora é aplicada a cada data separadamente, o que pode parecer redundante para intervalos curtos.
Perguntas frequentes
DateIntervalFormatter é uma classe Foundation para formatar intervalos de datas em strings localizadas. Disponível desde iOS 8, agrupa automaticamente componentes repetidos (mês, ano) e seleciona o separador correto para o idioma.
Ele compara componentes do ano ao dia. Se o ano corresponder, é exibido uma vez. Se o mês corresponder, é exibido uma vez. Dias diferentes são exibidos como um intervalo. Isso dá “21–25 de julho de 2024” em vez de “21 de julho de 2024 – 25 de julho de 2024”.
Não, o separador é determinado pela localidade e não pode ser personalizado via API. Para um separador personalizado (por exemplo, “até” em vez de “a”), formate cada data com um DateFormatter separado e concatene as strings manualmente.
DateIntervalFormatter formata um intervalo de datas (duas datas) como uma unidade única com agrupamento de componentes. DateFormatter formata uma data individual. Para intervalos, use sempre DateIntervalFormatter, pois ele fornece a localização correta do separador.
Automaticamente — DateIntervalFormatter detecta que os anos diferem e exibe as datas completas para ambas as extremidades: “25 de dezembro de 2024 – 5 de janeiro de 2025”. Nenhuma configuração adicional é necessária, basta definir o dateStyle.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também