RelativeDateTimeFormatter: Wesen, relative Daten und Swift

Autor: IT Sectr Veröffentlicht: 2026-07-13 Lesezeit: 10 Min.

RelativeDateTimeFormatter ist eine Foundation-Klasse in iOS und macOS, die absolute Daten in menschenlesbare relative Formulierungen umwandelt: „5 Minuten zuvor“, „gestern“, „in 3 Tagen“. Laut Apple Developer Documentation, 2024 wählt RelativeDateTimeFormatter automatisch die passende Einheit (Sekunden, Minuten, Stunden, Tage) aus und lokalisiert die Ausgabe in der Sprache des aktuellen Gebietsschemas des Geräts. Im Gegensatz zur manuellen Berechnung der Differenz zwischen Daten über Calendar berücksichtigt diese Klasse die sprachlichen Besonderheiten jeder Sprache: Für manche Sprachen werden Zahlwörter gebeugt, für andere wird eine spezielle Form für das Wort „gestern“ verwendet. Die Klasse ist ab iOS 13 und macOS 10.15 verfügbar.

Wichtige Punkte

  • RelativeDateTimeFormatter — eine Klasse zur Anzeige relativer Daten in iOS und macOS (iOS 13+)
  • Lokalisierte Ausgabe — wählt automatisch Formulierungen in der Sprache des aktuellen Gebietsschemas
  • Drei Kontexttypen — Vergangenheit (zuvor), Zukunft (in), Gegenwart (jetzt) mit unterschiedlichen Formulierungen
  • Automatische Einheitenauswahl — Sekunden, Minuten, Stunden, Tage, Wochen, Monate, Jahre
  • Stilanpassung — numeric (in 3 Tagen) oder abbreviated (in 3 Tg.)

Was ist RelativeDateTimeFormatter?

RelativeDateTimeFormatter ist eine Unterklasse von Formatter in Foundation, die ein Date (oder eine Differenz in Sekunden) nimmt und eine lokalisierte Zeichenfolge mit relativer Zeit zurückgibt. Für ein Datum 5 Minuten vor dem aktuellen gibt es beispielsweise „5 Minuten zuvor“ zurück. Die Klasse unterstützt drei zeitliche Kontexte: Vergangenheit, Zukunft und Gegenwart.

Die interne Logik von RelativeDateTimeFormatter verwendet Calendar und Locale, um die Differenz zwischen Daten zu berechnen und die korrekte grammatikalische Form auszuwählen. Für Deutsch wählt es zwischen „1 Minute zuvor“ und „5 Minuten zuvor“. Diese Funktionalität basiert auf ICU-Daten (International Components for Unicode) und erfordert keine zusätzliche Konfiguration durch den Entwickler.

Laut Apple WWDC 2019 wurde RelativeDateTimeFormatter Teil des Frameworks, um die Lokalisierung zu vereinfachen — vor seiner Einführung mussten Entwickler die Datumsdifferenz manuell berechnen und lokalisierte Zeichenfolgen über String.localizedStringWithFormat ersetzen. Dies führte zu Beugungsfehlern (insbesondere bei slawischen und arabischen Sprachen) und einer falschen Auswahl von Maßeinheiten.

Wie zeigt RelativeDateTimeFormatter „5 Minuten zuvor“ an?

Der Algorithmus von RelativeDateTimeFormatter besteht aus drei Schritten: Berechnen der Differenz zwischen dem übergebenen Datum und dem aktuellen Zeitpunkt, Auswählen der geeigneten Einheit (der größten, die nicht Null ergibt) und Formatieren entsprechend dem Gebietsschema. Bei einer Differenz von 3720 Sekunden (1 Stunde 2 Minuten) wird beispielsweise die Einheit „Stunde“ ausgewählt, und das Ergebnis ist „1 Stunde zuvor“, nicht „62 Minuten zuvor“.

Einheiten werden nach dem Prinzip der „größten Nicht-Null“ ausgewählt: Ist die Differenz größer als 86400 Sekunden (1 Tag), werden Tage verwendet; ist sie größer als 604800 (1 Woche) — Wochen, und so weiter. Dieser Algorithmus stellt sicher, dass das Ergebnis immer natürlich lesbar ist: Statt „518400 Sekunden zuvor“ sieht der Benutzer „6 Tage zuvor“. Die genauen Grenzen der Einheiten werden durch den Kalender des aktuellen Gebietsschemas bestimmt.

DifferenzbereichEinheitBeispiel für de_DE
0–59 SekundenSeconds30 Sekunden zuvor
1–59 MinutenMinutes5 Minuten zuvor
1–23 StundenHours3 Stunden zuvor
1–6 TageDays2 Tage zuvor
7–27 TageWeeks1 Woche zuvor
28 Tage–11 MonateMonths3 Monate zuvor
12+ MonateYears1 Jahr zuvor

Der Formatierungskontext bestimmt die Endung des Satzes. Für die Vergangenheit: „zuvor“ (Deutsch). Für die Zukunft: „in 3 Tagen“ (Deutsch). Für die Gegenwart: „jetzt“ (Deutsch). Der Kontext wird über die Methode localizeString(fromTimeInterval:) oder direkt über string(from: Date) festgelegt.

Einheiten- und Stileinstellungen

RelativeDateTimeFormatter bietet mehrere Einstellungen zur Steuerung der Ausgabe: Die Eigenschaft unitsStyle bestimmt den Formatierungsstil (numeric, abbreviated, full, spellOut), und maximumUnitCount begrenzt die Anzahl der angezeigten Einheiten. Mit maximumUnitCount = 1 wird eine Differenz von 1 Stunde 30 Minuten beispielsweise als „1 Stunde zuvor“ statt „1 Stunde 30 Minuten zuvor“ angezeigt.

Formatierungsstile

  • .numeric — voller numerischer Wert: „3 Tage zuvor“, „in 2 Wochen“. Für UI standardmäßig empfohlen
  • .abbreviated — Kurzform: „3 Tg. zuvor“, „in 2 Wo.“. Für kompakte Anzeige in Tabellen und Listen
  • .full — verbale Form ohne Ziffern: „drei Tage zuvor“. Für Barrierefreiheit und Sprachschnittstellen
  • .spellOut — Buchstabenform mit alternativer Schreibweise: „three days ago“. Selten verwendet, hauptsächlich für spezielle Zwecke

Einheitenbegrenzung: Standardmäßig zeigt RelativeDateTimeFormatter nur eine (die größte) Einheit an. Das Setzen von maximumUnitCount = 2 schließt die nächste Einheit für eine genauere Beschreibung ein: „1 Stunde 30 Minuten zuvor“. Dies kann jedoch die Zeichenfolge für kurze Nachrichten (Push-Benachrichtigungen, Alarme) übermäßig lang machen. Für die UI wird empfohlen, maximumUnitCount = 1 beizubehalten.

swift
import Foundation

let formatter = RelativeDateTimeFormatter()

// Configure styles
formatter.unitsStyle = .numeric
formatter.maximumUnitCount = 1

// Examples with different dates
let fiveMinAgo = Date().addingTimeInterval(-300)
print("5 min ago: \(formatter.localizedString(for: fiveMinAgo, relativeTo: Date()))")

let twoDaysLater = Date().addingTimeInterval(172800)
print("2 days later: \(formatter.localizedString(for: twoDaysLater, relativeTo: Date()))")

// Abbreviated style
formatter.unitsStyle = .abbreviated
let oneWeekAgo = Date().addingTimeInterval(-604800)
print("Abbreviated: \(formatter.localizedString(for: oneWeekAgo, relativeTo: Date()))")

// Full style (spelled out)
formatter.unitsStyle = .full
let threeHours = Date().addingTimeInterval(10800)
print("Full: \(formatter.localizedString(for: threeHours, relativeTo: Date()))")

Stilauswahl für verschiedene Kontexte: Für einen Nachrichtenfeed verwenden Sie .numeric mit maximumUnitCount = 1 — dies ist der Standard für Twitter, Instagram und Facebook. Für Barrierefreiheit (VoiceOver) verwenden Sie .full — ausgeschriebene Zahlen werden natürlicher vorgelesen. Für kompakte Elemente (Benachrichtigungsabzeichen, Statusleiste) verwenden Sie .abbreviated, um Platz zu sparen.

RelativeDateTimeFormatter in Swift: Beispiele

Grundlegende Verwendung von RelativeDateTimeFormatter beschränkt sich auf das Erstellen einer Instanz, das Konfigurieren von Eigenschaften und das Aufrufen einer der Formatierungsmethoden. Die wichtigsten Methoden sind: localizedString(for:relativeTo:) — für ein Paar von Daten, localizedString(fromTimeInterval:) — für eine Differenz in Sekunden, und string(for:) — für Date mit automatischem Kontext (Vergangenheit/Zukunft).

swift
import Foundation

let formatter = RelativeDateTimeFormatter()
formatter.unitsStyle = .numeric
formatter.maximumUnitCount = 1

// Social network UI examples
let postDates: [(title: String, date: Date)] = [
    ("Just now", Date().addingTimeInterval(-30)),
    ("5 min ago", Date().addingTimeInterval(-300)),
    ("Yesterday", Date().addingTimeInterval(-90000)),
    ("Last week", Date().addingTimeInterval(-700000)),
    ("Last year", Date().addingTimeInterval(-32000000))
]

for (title, postDate) in postDates {
    let relative = formatter.localizedString(
        for: postDate,
        relativeTo: Date()
    )
    print("\(title): \(relative)")
}

// Future dates
let reminderFormatter = RelativeDateTimeFormatter()
reminderFormatter.unitsStyle = .abbreviated
let inOneHour = Date().addingTimeInterval(3600)
let reminderText = reminderFormatter.localizedString(
    for: inOneHour,
    relativeTo: Date()
)
print("Reminder: \(reminderText)")

Behandlung des „gerade eben“-Szenarios — RelativeDateTimeFormatter hat keine integrierte Unterstützung für den Ausdruck „gerade eben“ für sehr kleine Intervalle. Bei einer Differenz von weniger als 5 Sekunden gibt es „0 Sekunden zuvor“ zurück, was in der UI unschön aussieht. Es wird empfohlen, den Formatiereraufruf in eine bedingte Logik zu verpacken: Wenn die Differenz kleiner als ein festgelegter Schwellenwert (z.B. 5 Sekunden) ist — zeigen Sie manuell „gerade eben“ an, andernfalls übergeben Sie das Datum an den Formatierer.

swift
import Foundation

func relativeTimeString(from date: Date) -> String {
    let interval = Date().timeIntervalSince(date)

    // "Just now" threshold
    if interval < 5 {
        return "just now"
    }

    // "Today" threshold
    if interval < 60 {
        return "just now"
    }

    let formatter = RelativeDateTimeFormatter()
    formatter.unitsStyle = .numeric
    formatter.maximumUnitCount = 1

    // Display without "ago" suffix
    return formatter.localizedString(
        for: date,
        relativeTo: Date()
    )
}

print(relativeTimeString(from: Date().addingTimeInterval(-3)))
print(relativeTimeString(from: Date().addingTimeInterval(-120)))
print(relativeTimeString(from: Date().addingTimeInterval(-3600)))

Die Methode string(fromTimeInterval:) akzeptiert eine Differenz in Sekunden und bestimmt automatisch den Kontext (positiver Wert — Zukunft, negativer — Vergangenheit). Dies ist praktisch, wenn die Differenz bereits bekannt ist (z.B. vom Server als Unix-Zeitstempel empfangen). In diesem Fall muss kein Date erstellt werden — die Differenz wird direkt übergeben.

Lokalisierung relativer Daten

RelativeDateTimeFormatter lokalisiert die Ausgabe automatisch basierend auf Locale.current. Um die Formatierungssprache zu ändern, setzen Sie die Eigenschaft locale — im Gegensatz zu DateFormatter ist bei RelativeDateTimeFormatter das Gebietsschema nicht festgelegt und kann für jeden Aufruf geändert werden. Dies ermöglicht die Anzeige relativer Daten in einer anderen Sprache als der Oberflächensprache (z.B. Inhalte in der Originalsprache).

Die Komplexität der Lokalisierung relativer Daten liegt in den grammatikalischen Besonderheiten verschiedener Sprachen. Deutsch erfordert unterschiedliche Formen von Zahlwörtern: „1 Minute“, „2 Minuten“. Arabisch verwendet die Pluralform für Zahlen von 3 bis 10 und spezielle Formen für 11+. Chinesisch hat überhaupt keine Beugung, was die Aufgabe vereinfacht. RelativeDateTimeFormatter deckt all diese Fälle durch ICU-Regeln ab, ohne dass zusätzlicher Code erforderlich ist.

swift
import Foundation

let formatter = RelativeDateTimeFormatter()
formatter.unitsStyle = .numeric
formatter.maximumUnitCount = 1

let targetDate = Date().addingTimeInterval(-7200) // 2 hours ago

// Different locales
let locales: [String] = ["ru_RU", "en_US", "de_DE", "fr_FR", "ja_JP", "ar_SA"]

for identifier in locales {
    formatter.locale = Locale(identifier: identifier)
    let result = formatter.localizedString(
        for: targetDate,
        relativeTo: Date()
    )
    print("\(identifier): \(result)")
}

// Check German pluralization
formatter.locale = Locale(identifier: "ru_RU")
let intervals: [TimeInterval] = [-60, -120, -180, -300]
for interval in intervals {
    let date = Date().addingTimeInterval(interval)
    print("\(-Int(interval / 60)) min: \(formatter.localizedString(for: date, relativeTo: Date()))")
}

Eine wichtige Nuance: RelativeDateTimeFormatter ignoriert TimeZone bei der Berechnung der Differenz für .numeric-Einstellungen — es verwendet die absolute Differenz in Sekunden. Für den .full-Stil (mit ausgeschriebenen Zahlen) und Sonderfälle (gestern, heute) wird TimeZone jedoch berücksichtigt. Setzen Sie TimeZone aus Gründen der Konsistenz immer explizit, insbesondere wenn die Anwendung mit Serverdaten in UTC arbeitet.

Häufige Formatierungsfehler

Ignorieren von TimeZone bei der Berechnung relativer Daten — ein häufiger Fehler bei der Arbeit mit Serverdaten. Wenn der Server ein Date in UTC sendet und RelativeDateTimeFormatter TimeZone.current verwendet, kann die Differenz für Daten nahe dem aktuellen Zeitpunkt falsch berechnet werden. Es wird empfohlen, für Serverdaten immer formatter.timeZone = TimeZone(secondsFromGMT: 0) zu setzen.

Falsche Einheitenauswahl für kurze Intervalle — RelativeDateTimeFormatter rundet die Differenz auf die größte Einheit. Bei 25 Stunden ist das Ergebnis „1 Tag zuvor“, was den Benutzer in die Irre führen kann. Wenn eine hohe Genauigkeit erforderlich ist (z.B. für Countdown-Timer), verwenden Sie DateComponentsFormatter anstelle von RelativeDateTimeFormatter — dieser ermöglicht die gleichzeitige Anzeige mehrerer Einheiten.

Fehlende Prüfung auf negatives TimeInterval — Wenn ein zukünftiges Datum als vergangen übergeben wird (negativer Wert in string(fromTimeInterval:)), kann der Formatierer eine falsche Zeichenfolge zurückgeben. Überprüfen Sie immer das Vorzeichen des Intervalls, bevor Sie es an den Formatierer übergeben, insbesondere bei der Arbeit mit Serverdaten, bei denen die Zeitzone die Berechnung verzerren kann.

Laut Hacker News (2024) ist eines der am meisten diskutierten Probleme von RelativeDateTimeFormatter das Fehlen einer integrierten Unterstützung für „gestern“ und „heute“ für die englische Sprache. Statt „gestern“ gibt der Formatierer bei einer Differenz von 90000 Sekunden „1 Tag zuvor“ zurück. Für Deutsch gibt es dieses Problem nicht — „1 Tag zuvor“ klingt natürlich, aber für die englische UI ist „yesterday“ vorzuziehen. Diese Funktionalität wird nicht unterstützt und erfordert eine manuelle Überprüfung über Calendar.isDateInToday/Yesterday.

Häufig gestellte Fragen

Was ist RelativeDateTimeFormatter?

RelativeDateTimeFormatter ist eine Foundation-Klasse zur Anzeige von Daten in relativem Format: „5 Minuten zuvor“, „in 2 Tagen“. Verfügbar ab iOS 13 und macOS 10.15.

Wie wählt RelativeDateTimeFormatter Einheiten aus?

Nach dem Prinzip der größten Nicht-Null-Einheit — Sekunden, Minuten, Stunden, Tage, Wochen, Monate oder Jahre. Bei einer Differenz von 3720 Sekunden (1 Stunde 2 Minuten) wird beispielsweise die Einheit „Stunde“ ausgewählt, nicht „Minuten“.

Wie ändere ich die Ausgabesprache?

Setzen Sie die Eigenschaft locale auf die gewünschte Locale-Instanz. Standardmäßig wird Locale.current verwendet. Beispiel: formatter.locale = Locale(identifier: "de_DE") für Deutsch.

Was ist der Unterschied zwischen .numeric und .abbreviated?

.numeric — vollständige Form („3 Tage zuvor“), .abbreviated — Kurzform („3 Tg. zuvor“). Die Wahl hängt vom Kontext ab: numeric für die Haupt-UI, abbreviated für kompakte Elemente.

Wie zeige ich „gerade eben“ anstatt „0 Sekunden zuvor“?

Fügen Sie eine manuelle Prüfung für ein Intervall von weniger als 5–10 Sekunden hinzu. RelativeDateTimeFormatter unterstützt „gerade eben“ nicht — bei kleinen Intervallen gibt es „0 Sekunden zuvor“ zurück. Verwenden Sie bedingte Logik mit einem Schwellenwert.

Zusammenfassung

  • RelativeDateTimeFormatter — eine praktische Klasse zur Anzeige relativer Daten in iOS 13+
  • Automatische Lokalisierung — korrekte Beugung für alle unterstützten Sprachen via ICU
  • Drei Stile — .numeric (Standard), .abbreviated (kompakt), .full (ausgeschrieben)
  • Einheitenauswahl — automatisch basierend auf dem größten Nicht-Null-Wert
  • TimeZone-Konfiguration — für Konsistenz bei der Arbeit mit Serverdaten obligatorisch
  • „Gerade eben“-Schwellenwert — nicht integriert unterstützt; erfordert manuelle Intervallprüfung
  • Keine Unterstützung für „gestern“ — der Formatierer verwendet für Englisch nicht die Form yesterday

Wir entwickeln eine mobile Applikation schlüsselfertig

IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.

Projekt besprechen

Lesen Sie auch