DateFormatter: klíčové pojmy, formátování data a lokalizace

Autor: IT Sectr Publikováno: 2026-07-12 Doba čtení: 7 min

DateFormatter — třída Foundation navržená pro obousměrnou konverzi mezi objekty Date a jejich řetězcovou reprezentací. Třída bere v úvahu místní nastavení, časové pásmo a kalendář uživatele, čímž zajišťuje správné zobrazení dat v jakémkoli regionu světa. Podle Apple Developer Documentation (2025) DateFormatter podporuje čtyři předdefinované styly data a času, stejně jako zcela vlastní formáty pomocí řetězce vzoru. Bez DateFormatteru není možné správně zobrazit datum uživateli v internacionalizované aplikaci.

Hlavní

  • DateFormatter — třída pro převod Date na řetězec a zpět s ohledem na místní nastavení a časové pásmo.
  • dateStyle a timeStyle — předdefinované styly (.short, .medium, .long, .full) pro rychlé formátování.
  • dateFormat — řetězec vzoru pro vlastní formát, definovaný pomocí symbolů specifikace Unicode LDML.
  • Locale a TimeZone — vlastnosti formátovače určující regionální zobrazení a časové pásmo.
  • ISO8601DateFormatter — rychlejší alternativa pro formát ISO 8601 při serializaci v API.

Co je DateFormatter?

DateFormatter — třída z frameworku Foundation, která implementuje obousměrnou konverzi mezi Date a řetězcem. Objevila se v OpenStep jako NSDateFormatter a od té doby zůstává hlavním nástrojem pro formátování dat na všech platformách Apple. Třída dědí z Formatter a poskytuje pohodlné API pro lokalizované zobrazení dat.

Princip fungování DateFormatter je založen na vzorech Unicode LDML — stejných, které se používají v ICU (International Components for Unicode). Vzor je definován vlastností dateFormat, kde symboly y, M, d, H, m, s odpovídají roku, měsíci, dni, hodinám, minutám a sekundám. Opakování symbolu určuje formát: „y“ — dvoumístný rok, „yyyy“ — čtyřmístný.

Vytvoření DateFormatter je nákladná operace, protože při inicializaci se načítají data místního nastavení a kalendáře. Apple doporučuje vytvořit formátovač jednou pro každý typ formátování a znovu jej používat. V SwiftUI a UIKit jsou formátovače často ukládány do mezipaměti ve statických vlastnostech nebo vytvářeny líně při prvním přístupu.

DateFormatter v iOS SDK

DateFormatter se používá v mnoha systémových komponentách iOS. UIDatePicker interně používá DateFormatter k zobrazení dat v režimu countDownTimer. TextField s formátovačem na vstupu může automaticky validovat datum zadané uživatelem. Core Data podporuje atributy typu Date, ale jejich řetězcové zobrazení se vždy provádí prostřednictvím DateFormatter.

Thread Safety — DateFormatter není vláknově bezpečný. Změna vlastností formátovače z různých vláken vede k nedefinovanému chování. Pro vícevláknové použití vytvářejte samostatné instance formátovače pro každé vlákno nebo použijte synchronizaci pomocí NSLock nebo serial queue.

Styly formátování DateFormatter

dateStyle a timeStyle — nejjednodušší způsoby konfigurace zobrazení data. Každý styl má čtyři varianty: .short, .medium, .long, .full. Kombinace dateStyle a timeStyle umožňuje nezávisle konfigurovat formát data a času a vlastnost .none vypne příslušnou část.

Pro americké místní nastavení formátuje .short datum jako „7/21/26“, pro české — jako „21.07.2026“. Styl .long pro české místní nastavení zobrazuje „21. července 2026“, a .full — „úterý 21. července 2026“ s uvedením dne v týdnu. Všechny čtyři styly se automaticky přizpůsobují regionálním standardům, včetně pořadí komponent a oddělovačů.

RelativeDateFormatter v iOS 15+ nabízí alternativní přístup prostřednictvím RelativeDateFormatter a DateIntervalFormatter. RelativeDateFormatter zobrazuje „dnes“, „včera“, „za 3 dny“ pro aktuální kontext. DateIntervalFormatter zobrazuje rozsahy dat: “21.–25. července 2026” — pro rezervace a plánování.

StylPříklad (cs_CZ)Příklad (en_US)
.short21.07.20267/21/26
.medium21. 7. 2026Jul 21, 2026
.long21. července 2026July 21, 2026
.fullúterý 21. července 2026Tuesday, July 21, 2026

Při kombinování stylů DateFormatter automaticky vybírá oddělovač: pro .short.date + .short.time může být výsledek „21.07.2026, 14:30“. Pro .full.date + .full.time — „úterý 21. července 2026, 14:30:00 MSK“. Oddělovač je řízen místním nastavením, nikoli vývojářem — to zaručuje soulad s regionálními očekáváními uživatele.

Vlastní formáty pomocí dateFormat

dateFormat umožňuje definovat libovolný vzor formátování pomocí symbolů specifikace Unicode LDML. To poskytuje úplnou kontrolu nad zobrazením: můžete zobrazit pouze rok a měsíc, den v týdnu bez čísla nebo čas bez sekund. Vlastní formát je nepostradatelný pro specifické požadavky designu.

Základní symboly — yyyy (rok: 2026), MM (měsíc: 07), dd (den: 21), HH (hodiny: 14), mm (minuty: 30), ss (sekundy: 00). Pro plný název měsíce použijte MMMM (červenec), pro zkrácený — MMM (čvc). Den v týdnu — EEEE (úterý), zkráceně — E (út).

Při použití dateFormat je důležité nastavit locale formátovače. Pokud locale není nastaveno, formátovač použije systémové místní nastavení, což může být nežádoucí pro pevný formát v API. Apple doporučuje nastavit locale = Locale(identifier: “en_US_POSIX”) pro pevný mezinárodní formát, zejména při parsování dat ze serverových odpovědí.

swift
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "ru_RU")
formatter.dateFormat = "d MMMM yyyy"
let customString = formatter.string(from: Date())
// "21 July 2026"

// Analýza vlastního řetězce
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let date = formatter.date(from: "2026-07-21 14:30:00")!

Chyba v dateFormat — jeden z častých důvodů pádu aplikace. Pokud formát neodpovídá řetězci, metoda date(from:) vrací nil. Použijte guard let nebo ?? pro bezpečné získání volitelné hodnoty. Pro validaci formátu testujte na všech podporovaných jazycích — některé symboly LDML fungují v různých místních nastaveních odlišně.

Lokalizace a TimeZone

Locale určuje, jak se zobrazují názvy měsíců, dnů v týdnu a jaké oddělovače se používají. DateFormatter ve výchozím nastavení používá Locale.current, ale v některých scénářích je třeba zadat konkrétní místní nastavení: pro pevný formát v logech použijte en_US_POSIX, pro serverová data — místní nastavení shodné se serverem.

Vlastnost TimeZone určuje časové pásmo pro zobrazení. Ve výchozím nastavení se používá systémové časové pásmo, ale pro aplikace s mezinárodním publikem je často nutné zobrazovat data v časovém pásmu uživatele nebo v UTC. Změna timeZone ovlivňuje pouze zobrazení — hodnota Date zůstává nezměněná.

Důležitá vlastnost: pokud je DateFormatter použit pro parsování řetězce a řetězec obsahuje označení časového pásma (např. “2026-07-21T14:30:00Z” s Z pro UTC), vlastnost timeZone je ignorována — formátovač použije časové pásmo z řetězce. Pokud časové pásmo v řetězci chybí, použije se timeZone formátovače.

swift
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "ru_RU")
formatter.timeZone = TimeZone(identifier: "Europe/Moscow")
formatter.dateStyle = .long
formatter.timeStyle = .short

let moscowTime = formatter.string(from: Date())
// "21 July 2026, 14:30"

// Analýza bez časového pásma v řetězci
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.dateFormat = "yyyy-MM-dd HH:mm"
let utcDate = formatter.date(from: "2026-07-21 10:30")!

AutoupdatingCurrentLocale — speciální typ místního nastavení, které se automaticky aktualizuje při změně systémových nastavení uživatele. DateFormatter jej ve výchozím nastavení podporuje. Pokud aplikace běží na pozadí a uživatel změní jazyk systému, formátovač vytvořený před změnou bude nadále používat staré místní nastavení — pro aktualizaci je třeba vytvořit novou instanci.

ISO8601DateFormatter a alternativy

ISO8601DateFormatter — specializovaný formátovač pro práci s daty ve formátu ISO 8601. Tento formát je de facto standardem pro REST API, JSON a výměnu dat. ISO8601DateFormatter pracuje výrazně rychleji než DateFormatter, protože nezávisí na místním nastavení a používá pevnou gramatiku parsování.

Hlavní volby formátovače — .withInternetDateTime (2026-07-21T14:30:00Z), .withFractionalSeconds (přidává milisekundy), .withTimeZone (zahrnuje posun časového pásma). Kombinováním voleb lze získat libovolnou variantu ISO 8601: s milisekundami, s časovým pásmem, s datem bez času.

JSONEncoder.DateEncodingStrategy umožňuje globálně konfigurovat kódování dat pro všechny modely Codable. Varianty — .iso8601 (používá ISO8601DateFormatter), .formatted(DateFormatter), .millisecondsSince1970, .secondsSince1970. Výběr strategie ovlivňuje celý životní cyklus serializace a měl by být jednotný pro všechny API endpointy.

swift
// ISO8601DateFormatter
let isoFormatter = ISO8601DateFormatter()
isoFormatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
let isoString = isoFormatter.string(from: Date())
// "2026-07-21T14:30:00.000Z"

// JSONEncoder s ISO8601
let encoder = JSONEncoder()
encoder.dateEncodingStrategy = .iso8601

// Alternativa: JSONEncoder s vlastním formátovačem
let customEncoder = JSONEncoder()
customEncoder.dateEncodingStrategy = .formatted(myFormatter)

DateFormatter vs ISO8601DateFormatter — vybírejte ISO8601DateFormatter pro serializaci a parsování dat v API, protože pracuje 5-10 krát rychleji než DateFormatter a není náchylný k chybám lokalizace. DateFormatter ponechte pro uživatelské rozhraní, kde je vyžadováno lokalizované zobrazení s názvy měsíců a dnů v týdnu v rodném jazyce uživatele.

Příklady formátování dat

Podívejme se na reálné scénáře použití DateFormatter v aplikaci pro iOS: zobrazení v seznamu novinek, zadání data narození a export sestavy s daty v různých časových pásmech.

Zobrazení data novinky v seznamu

RelativeDateFormatter je optimální pro zpravodajské kanály. Zobrazuje „právě teď“, „před 5 minutami“, „včera“ pro čerstvé zprávy a přepíná na plné datum pro starší. Práh přepínání se konfiguruje pomocí calendar: pro zprávy použijte práh 24 hodin, pro messenger — týden.

swift
func formatRelativeDate(_ date: Date) -> String {
    let relative = RelativeDateFormatter()
    relative.unitsStyle = .full

    let formatter = DateFormatter()
    formatter.dateStyle = .medium
    formatter.timeStyle = .short

    let daysDiff = Calendar.current.dateComponents(
        [.day], from: date, to: Date()
    ).day ?? 0

    return daysDiff < 1
        ? relative.localizedString(for: date, relativeTo: Date())
        : formatter.string(from: date)
}

Zadání data narození — další častý scénář. DateFormatter se konfiguruje s konkrétním dateFormat „dd.MM.yyyy“ a místním nastavením „cs_CZ“. Při parsování zadaného řetězce je důležité ošetřit možné chyby: formátovač vrací nil pro neplatný řetězec. Po úspěšném parsování se datum zkontroluje, zda spadá do povoleného rozsahu — ne dříve než 1900, ne později než dnes.

Export sestavy s daty vyžaduje pevný formát nezávislý na místním nastavení uživatele. Použijte dateFormat „yyyy-MM-dd HH:mm:ss“ s místním nastavením en_US_POSIX a časovým pásmem UTC. Tento přístup zaručuje, že se soubor správně otevře v jakékoli zemi bez ohledu na regionální nastavení systému.

ScénářFormátovačKlíčové nastavení
Zpravodajský kanálRelativeDateFormatterunitsStyle = .full
Zadání dataDateFormatterdateFormat + fallback
API serializaceISO8601DateFormatterwithInternetDateTime
Export sestavyDateFormatteren_US_POSIX + UTC

Často kladené dotazy

Proč DateFormatter vrací nil pro správný řetězec?

Nejčastější příčina — nesoulad dateFormat s formátem řetězce. Například formát „dd.MM.yyyy“ neparsuje řetězec „2026-07-21“. Druhý důvod — nesoulad místního nastavení: řetězec „July 21, 2026“ se neparsuje s místním nastavením cs_CZ. Třetí — překlepy v symbolech LDML: používejte yyyy, nikoli YYYY (odlišný význam).

Je třeba vytvářet nový DateFormatter pro každé volání?

Ne. DateFormatter je těžký objekt, jeho inicializace zahrnuje načítání dat místního nastavení. Vytvořte jednu instanci na typ formátování a znovu ji používejte. V multithreadovém prostředí použijte Thread-local storage nebo fond formátovačů s serial queue pro synchronizaci.

Čím se DateFormatter liší od RelativeDateFormatter?

DateFormatter zobrazuje absolutní datum (21. července 2026), zatímco RelativeDateFormatter — relativní datum (dnes, včera, za 3 dny). RelativeDateFormatter se objevil v iOS 15+ a používá stejný vzor LDML, ale automaticky volí relativní zobrazení.

Jak zpracovat data bez časového pásma z API?

Nastavte timeZone formátovače na UTC před parsováním. Pokud server vrací datum v místním čase bez označení pásma, zkontrolujte specifikaci API — pravděpodobně se předpokládá UTC. Pro ISO 8601 s Z na konci timeZone není potřeba — formátovač parsuje posun z řetězce.

Jak udělat DateFormatter vláknově bezpečným?

Nepoužívejte jednu instanci z různých vláken bez synchronizace. Vytvářejte novou instanci v každém vlákně nebo použijte Thread.current.threadDictionary pro uložení. Alternativa — NSLock s uzamčením po dobu string(from:) a date(from:).

Shrnutí

  • DateFormatter — třída Foundation pro převod Date na řetězec a zpět s ohledem na místní nastavení, časové pásmo a kalendář uživatele.
  • Předdefinované styly dateStyle a timeStyle s variantami .short, .medium, .long, .full pokrývají většinu UI scénářů.
  • Vlastní dateFormat pomocí symbolů LDML poskytuje úplnou kontrolu nad formátem, ale vyžaduje opatrnost při lokalizaci.
  • Locale a TimeZone — povinné vlastnosti pro správné zobrazení: pro UI — systémové místní nastavení, pro API — en_US_POSIX a UTC.
  • ISO8601DateFormatter — preferovaná volba pro serializaci dat v API díky rychlosti a stabilitě.
  • DateFormatter není vláknově bezpečný — používejte samostatné instance pro každé vlákno nebo synchronizujte přístup.
  • RelativeDateFormatter (iOS 15+) — optimální řešení pro zobrazení relativních dat ve zpravodajských kanálech a messengerech.

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í.

Prodiskutovat projekt

Přečtěte si také