DateIntervalFormatter je třída Foundation v iOS a macOS určená pro formátování rozsahů dat do lokalizovaných řetězců: „21.–25. července 2024“, „od 21. do 25. července 2024“ nebo „Jul 21–25, 2024“. Podle Apple Developer Documentation, 2024, DateIntervalFormatter automaticky určuje, které komponenty data opakovat (pokud je rozsah v rámci jednoho měsíce — měsíc se zobrazí jednou) a lokalizuje oddělovače a pořadí slov. Na rozdíl od ručního lepení dvou formátovaných dat tato třída zohledňuje gramatická pravidla jazyka: pro češtinu — předložku „do“, pro angličtinu — pomlčku bez předložky. Třída je k dispozici od iOS 8 a macOS 10.10.
Hlavní body
DateIntervalFormatter je podtřída Formatter ve Foundation, která přijímá objekt DateInterval (rozsah mezi dvěma daty) a vrací lokalizovaný řetězec s popisem tohoto rozsahu. Například pro rozsah od 21. do 25. července 2024 bude výsledek „21.–25. července 2024“ pro cs_CZ a „Jul 21–25, 2024“ pro en_US. Třída inteligentně seskupuje opakující se prvky: pokud jsou obě data ve stejném měsíci, název měsíce se zobrazí jednou.
Hlavní hodnotou DateIntervalFormatter je automatické zpracování gramatiky rozsahů. Při ručním formátování by programátor musel porovnat měsíc/rok začátku a konce, vybrat oddělovač (pomlčku, „od–do“, „to“, „bis“) a sledovat skloňování. DateIntervalFormatter to dělá automaticky na základě dat CLDR (Common Locale Data Repository), což snižuje počet chyb v mezinárodních aplikacích, zejména pro jazyky se složitou gramatikou.
Podle Unicode CLDR v44 (2024) se pravidla formátování rozsahů dat výrazně liší mezi jazyky. Němčina používá předložku „bis“ (21.–25. Juli 2024), francouzština — „au“ (du 21 au 25 juillet 2024), japonština — přes pomlčku (2024 Jul 21–25). DateIntervalFormatter pokrývá všechny tyto variace bez dodatečného kódu ze strany programátora.
Princip fungování DateIntervalFormatter je založen na analýze dvou dat tvořících rozsah a výběru optimální textové reprezentace s ohledem na locale. Třída porovnává komponenty data (rok, měsíc, den) a rozhoduje o seskupení: pokud je rok stejný — zobrazí se jednou; pokud je měsíc stejný — zobrazí se jednou; pokud se dny liší — zobrazí se rozsah dnů.
| Rozsah | cs_CZ | en_US |
|---|---|---|
| Jeden den | 21. července 2024 | Jul 21, 2024 |
| V rámci měsíce | 21.–25. července 2024 | Jul 21–25, 2024 |
| Různé měsíce | 21. července – 5. srpna 2024 | Jul 21 – Aug 5, 2024 |
| Různé roky | 25. prosince 2024 – 5. ledna 2025 | Dec 25, 2024 – Jan 5, 2025 |
| S časem | 21. července 2024, 14:30–16:45 | Jul 21, 2024, 2:30–4:45 PM |
Logika seskupování je implementována na základě vzorů CLDR. Formátovač kontroluje rovnost každé komponenty data (Calendar.Component: year, month, day) v pořadí od největší k nejmenší. Jakmile se komponenta liší, všechny menší komponenty se zobrazí pro obě data. Například pro 21.–25. července: rok souhlasí, měsíc souhlasí, den se liší → měsíc jednou, dny — pro každé datum zvlášť.
Důležitý nuance: DateIntervalFormatter nepodporuje konfiguraci oddělovače přes API. Oddělovač je určen locale a nelze jej přepsat. Pokud je vyžadován vlastní oddělovač (například „do“ místo „–“), musíte formátovat data ručně přes DateFormatter a spojit řetězce s vlastním oddělovačem.
DateIntervalFormatter poskytuje dvě sady stylů: dateStyle a timeStyle — pro každý konec rozsahu. Tyto styly fungují podobně jako DateFormatter: .none skryje komponentu, .short dá krátký formát (21.07.2024), .medium — střední (21. čec 2024), .long — dlouhý (21. července 2024), .full — maximálně podrobný (neděle, 21. července 2024). Kombinováním dateStyle a timeStyle lze získat různé úrovně podrobností.
Důležité: dateStyle a timeStyle se aplikují stejně na oba konce rozsahu. Nelze nastavit různý styl pro začátek a konec (například .medium pro začátek a .short pro konec). Pokud je vyžadován různý styl, musíte formátovat každé datum samostatným DateFormatter a spojit výsledky.
import Foundation
let formatter = DateIntervalFormatter()
// Různé kombinace stylů
let startDate = Date()
let endDate = Date().addingTimeInterval(345600) // +4 dny
let interval = DateInterval(start: startDate, end: endDate)
// Pouze datum, střední formát
formatter.dateStyle = .medium
formatter.timeStyle = .none
print("Pouze datum: \(formatter.string(from: interval))")
// Krátký formát s časem
formatter.dateStyle = .short
formatter.timeStyle = .short
print("Krátký s časem: \(formatter.string(from: interval))")
// Plný formát
formatter.dateStyle = .full
formatter.timeStyle = .none
print("Plné datum: \(formatter.string(from: interval))")
Základní použití DateIntervalFormatter zahrnuje vytvoření instance, konfiguraci stylů a volání string(from:). Metoda přijímá DateInterval — strukturu s vlastnostmi start a end. DateInterval lze vytvořit ze dvou Date, nebo inicializovat s Duration (iOS 16+). Po formátování je výsledek připraven k zobrazení v UI bez dalšího zpracování.
import Foundation
let calendar = Calendar.current
let now = Date()
// Příklady konkrétních intervalů
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)")
}
// Formátování přes Calendar (iOS 16+)
if let nextWeek = calendar.date(
byAdding: .day, value: 7, to: now
) {
let weekInterval = DateInterval(start: now, end: nextWeek)
print("Následujících 7 dní: \(intervalFormatter.string(from: weekInterval))")
}
DateIntervalFormatter a Calendar Booking: v rezervačních aplikacích (hotely, vstupenky) jsou rozsahy dat klíčovým prvkem UI. DateIntervalFormatter správně zpracovává meziroční rozsahy (například od 28. prosince do 3. ledna), seskupuje měsíc a rok pro každé datum zvlášť. Pro takové scénáře se doporučuje použití dateStyle = .medium a timeStyle = .none — nejčitelnější formát pro data bez času.
import Foundation
let formatter = DateIntervalFormatter()
formatter.dateStyle = .long
formatter.timeStyle = .none
// Příklady rezervací
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("Rezervace: \(booking.formattedInterval)")
// Použití s různými locale
let enFormatter = DateIntervalFormatter()
enFormatter.dateStyle = .medium
enFormatter.timeStyle = .none
enFormatter.locale = Locale(identifier: "en_US")
print("Angličtina: \(enFormatter.string(from: interval))")
DateInterval vs DateIntervalFormatter: DateInterval — struktura představující rozsah dat (začátek a konec). DateIntervalFormatter — formátovač převádějící tuto strukturu na řetězec. DateInterval také podporuje kontroly contains(Date) a intersection(with:), což je užitečné pro logiku rezervací (kontrola překryvu dat).
DateIntervalFormatter lokalizuje výstup prostřednictvím vlastnosti locale. Ve výchozím nastavení se používá Locale.current — locale zařízení. Pro zobrazení intervalů v jiném jazyce (například anglický obsah v českém rozhraní) nastavte locale explicitně. Na rozdíl od DateFormatter, DateIntervalFormatter nevyžaduje nastavení Locale pro serverová data — vždy používá svou vlastní interní logiku seskupování založenou na CLDR.
Jazykové rozdíly ve formátování rozsahů dat jsou výrazně složitější než pro jednotlivá data. Angličtina používá jednoduchou pomlčku: Jul 21–25. Čeština — předložku „od–do“: od 21. do 25. července. Francouzština — předložku „au“: du 21 au 25 juillet. Němčina — tečku za číslem a pomlčku: 21.–25. Juli. Japonština — přes pomlčku bez předložky: Jul 21–25. DateIntervalFormatter pokrývá všechny tyto varianty.
import Foundation
let formatter = DateIntervalFormatter()
formatter.dateStyle = .medium
formatter.timeStyle = .none
let start = Date()
let end = Date().addingTimeInterval(259200) // +3 dny
let interval = DateInterval(start: start, end: end)
// Ukázka různých locale
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))")
}
// Lokalizace pro časové intervaly
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) čas: \(formatter.string(from: timeInterval))")
}
Specifika lokalizace: pro češtinu DateIntervalFormatter používá předložky „od“ a „do“ pro dlouhé formáty data. Pro krátký (short) formát — pouze pomlčku: 21.07–25.07.2024. Pro plný formát (full) — s uvedením dne v týdnu. Výběr formátu závisí na kontextu: pro seznam rezervací použijte .medium, pro detailní zobrazení — .long nebo .full.
DateIntervalFormatter zaplňuje mezeru formátování rozsahů dat, kterou ostatní třídy Foundation nepokrývají. DateFormatter formátuje jednotlivá data, RelativeDateTimeFormatter — relativní data (před/za), DateComponentsFormatter — trvání (2 hodiny 30 minut). Každá z těchto tříd řeší svůj vlastní úkol a nelze je zaměňovat.
| Třída | Účel | Příklad výstupu |
|---|---|---|
| DateIntervalFormatter | Rozsah dat | 21.–25. července 2024 |
| DateFormatter | Jednotlivé datum | 21. července 2024 |
| RelativeDateTimeFormatter | Relativní čas | Před 3 dny |
| DateComponentsFormatter | Trvání | 2 hodiny 30 minut |
| ISO8601DateFormatter | ISO 8601 formát | 2024-07-21T14:30:00Z |
Kdy použít DateIntervalFormatter: pro zobrazení rozsahů dat v UI — rezervace hotelů, události, filtrování podle data, historie operací. Pro výpočet trvání mezi daty použijte DateComponentsFormatter, ne DateIntervalFormatter — druhý není určen pro zobrazení trvání. DateFormatter používejte pouze pro jednotlivá data, ne pro lepení dvou formátovaných dat pomocí konkatenace řetězce — to vede ke ztrátě lokalizace oddělovače.
Okrajový případ: DateIntervalFormatter nepodporuje zobrazení otevřených rozsahů (bez koncového data). Pokud je konec rozsahu neznámý (například „od 21. července“), použijte DateFormatter s předložkou „od“ pro češtinu nebo „from“ pro angličtinu. DateIntervalFormatter také nepodporuje rozsahy s uvedením času pro různé dny — čas se aplikuje na každé datum zvlášť, což může vypadat nadbytečně pro krátké rozsahy.
Často kladené otázky
DateIntervalFormatter — třída Foundation pro formátování rozsahů dat do lokalizovaných řetězců. K dispozici od iOS 8, automaticky seskupuje opakující se komponenty (měsíc, rok) a vybírá správný oddělovač pro jazyk.
Porovnává komponenty od roku ke dni. Pokud rok souhlasí — zobrazí se jednou. Pokud měsíc souhlasí — zobrazí se jednou. Různé dny se zobrazí jako rozsah. To dává „21.–25. července 2024“ místo „21. července 2024 – 25. července 2024“.
Ne, oddělovač je určen locale a nelze jej konfigurovat přes API. Pro vlastní oddělovač (například „do“ místo „–“) formátujte každé datum samostatným DateFormatter a spojte řetězce ručně.
DateIntervalFormatter formátuje rozsah dat (dvě data) jako jeden celek se seskupením komponent. DateFormatter formátuje jedno datum. Pro rozsahy vždy používejte DateIntervalFormatter — to zajišťuje správnou lokalizaci oddělovače.
Automaticky — DateIntervalFormatter detekuje, že roky jsou různé, a zobrazí plná data pro oba konce: „25. prosince 2024 – 5. ledna 2025“. Žádná další nastavení nejsou potřeba, stačí nastavit dateStyle.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také