Wie formatiert man relative Zeitangaben wie vor 3 Tagen oder in 2 Stunden?

Verwenden Sie Intl.RelativeTimeFormat, um Zeitangaben wie vor 3 Tagen oder in 2 Stunden in jeder Sprache mit automatischer Pluralisierung und Lokalisierung anzuzeigen

Einführung

Social-Media-Feeds, Kommentarbereiche und Aktivitätsprotokolle zeigen Zeitstempel wie "vor 5 Minuten", "vor 2 Stunden" oder "in 3 Tagen" an. Diese relativen Zeitstempel helfen Benutzern, schnell zu verstehen, wann etwas passiert ist, ohne ein absolutes Datum interpretieren zu müssen.

Wenn Sie diese Zeichenketten in Englisch fest codieren, gehen Sie davon aus, dass alle Benutzer Englisch sprechen und den englischen Grammatikregeln folgen. Verschiedene Sprachen haben unterschiedliche Arten, relative Zeit auszudrücken. Spanisch sagt "hace 3 días" anstatt "3 days ago". Japanisch verwendet "3日前" mit einer völlig anderen Struktur. Jede Sprache hat auch einzigartige Pluralisierungsregeln, die bestimmen, wann Singular- oder Pluralformen verwendet werden.

JavaScript bietet die Intl.RelativeTimeFormat-API, um die Formatierung relativer Zeiten automatisch zu handhaben. Diese Lektion erklärt, wie man relative Zeiten für jede Sprache mit dieser integrierten API korrekt formatiert.

Warum die Formatierung relativer Zeit internationalisiert werden muss

Verschiedene Sprachen drücken relative Zeit auf unterschiedliche Weise aus. Im Englischen steht die Zeiteinheit vor "ago" für vergangene Zeiten und nach "in" für zukünftige Zeiten. Andere Sprachen verwenden unterschiedliche Wortstellungen, verschiedene Präpositionen oder völlig andere grammatikalische Strukturen.

const rtfEnglish = new Intl.RelativeTimeFormat('en');
console.log(rtfEnglish.format(-3, 'day'));
// "3 days ago"

const rtfSpanish = new Intl.RelativeTimeFormat('es');
console.log(rtfSpanish.format(-3, 'day'));
// "hace 3 días"

const rtfJapanese = new Intl.RelativeTimeFormat('ja');
console.log(rtfJapanese.format(-3, 'day'));
// "3 日前"

Jede Sprache erzeugt natürlich klingende Ausgaben, die ihren eigenen Konventionen folgen. Sie müssen diese Konventionen nicht kennen oder Übersetzungsdateien pflegen. Die API übernimmt automatisch alle Formatierungsdetails.

Auch die Pluralisierungsregeln variieren erheblich zwischen den Sprachen. Englisch unterscheidet zwischen "1 day" und "2 days". Arabisch hat sechs verschiedene Pluralformen, abhängig von der Anzahl. Japanisch verwendet unabhängig von der Menge dieselbe Form. Die Intl.RelativeTimeFormat-API wendet die korrekten Pluralisierungsregeln für jede Sprache an.

Die Intl.RelativeTimeFormat API

Der Konstruktor Intl.RelativeTimeFormat erstellt einen Formatierer, der numerische Werte und Zeiteinheiten in lokalisierte Zeichenketten umwandelt. Als erstes Argument übergeben Sie eine Gebietsschema-Kennung und rufen dann die Methode format() mit einem Wert und einer Einheit auf.

const rtf = new Intl.RelativeTimeFormat('en-US');

console.log(rtf.format(-1, 'day'));
// "1 day ago"

console.log(rtf.format(2, 'hour'));
// "in 2 hours"

Die Methode format() nimmt zwei Parameter entgegen. Der erste ist eine Zahl, die die Zeitdauer repräsentiert. Der zweite ist ein String, der die Zeiteinheit angibt.

Negative Zahlen stehen für vergangene Zeiten, während positive Zahlen zukünftige Zeiten anzeigen. Diese Konvention macht die API intuitiv nutzbar, sobald man die Zeichenkonvention verstanden hat.

Formatierung von vergangenen und zukünftigen Zeiten

Das Vorzeichen des Wertes bestimmt, ob die Zeit in der Vergangenheit oder Zukunft liegt. Negative Werte erzeugen Vergangenheitsformen, während positive Werte Zukunftsformen erzeugen.

const rtf = new Intl.RelativeTimeFormat('en-US');

console.log(rtf.format(-5, 'minute'));
// "5 minutes ago"

console.log(rtf.format(5, 'minute'));
// "in 5 minutes"

console.log(rtf.format(-2, 'week'));
// "2 weeks ago"

console.log(rtf.format(2, 'week'));
// "in 2 weeks"

Dieses Muster funktioniert konsistent über alle Zeiteinheiten und alle Sprachen hinweg. Die API wählt automatisch die korrekte grammatikalische Struktur basierend darauf aus, ob der Wert positiv oder negativ ist.

Verfügbare Zeiteinheiten

Die API unterstützt acht Zeiteinheiten, die die meisten Anforderungen an die relative Zeitformatierung abdecken. Sie können entweder Singular- oder Pluralformen verwenden, beide funktionieren identisch.

const rtf = new Intl.RelativeTimeFormat('en-US');

console.log(rtf.format(-30, 'second'));
// "30 seconds ago"

console.log(rtf.format(-15, 'minute'));
// "15 minutes ago"

console.log(rtf.format(-6, 'hour'));
// "6 hours ago"

console.log(rtf.format(-3, 'day'));
// "3 days ago"

console.log(rtf.format(-2, 'week'));
// "2 weeks ago"

console.log(rtf.format(-4, 'month'));
// "4 months ago"

console.log(rtf.format(-1, 'quarter'));
// "1 quarter ago"

console.log(rtf.format(-2, 'year'));
// "2 years ago"

Die API akzeptiert sowohl Singularformen wie day als auch Pluralformen wie days. Beide erzeugen identische Ausgaben. Die Einheit quarter ist nützlich für Geschäftsanwendungen, die mit Geschäftsperioden arbeiten.

Verwendung natürlicher Sprache mit numeric auto

Die Option numeric steuert, ob der Formatierer Zahlen oder natürliche Sprachalternativen verwendet. Der Standardwert ist always, der immer Zahlen anzeigt.

const rtfAlways = new Intl.RelativeTimeFormat('en-US', {
  numeric: 'always'
});

console.log(rtfAlways.format(-1, 'day'));
// "1 day ago"

console.log(rtfAlways.format(0, 'day'));
// "in 0 days"

console.log(rtfAlways.format(1, 'day'));
// "in 1 day"

Die Einstellung von numeric auf auto erzeugt natürlichere Formulierungen für bestimmte Werte.

const rtfAuto = new Intl.RelativeTimeFormat('en-US', {
  numeric: 'auto'
});

console.log(rtfAuto.format(-1, 'day'));
// "yesterday"

console.log(rtfAuto.format(0, 'day'));
// "today"

console.log(rtfAuto.format(1, 'day'));
// "tomorrow"

Diese Option lässt Benutzeroberflächen gesprächiger wirken. Benutzer sehen "gestern" anstatt "vor 1 Tag", was natürlicher klingt. Die Option auto funktioniert für alle Zeiteinheiten und alle Sprachen, wobei jede Sprache ihre eigenen idiomatischen Alternativen bietet.

Auswahl eines Formatierungsstils

Die Option style steuert die Ausführlichkeit der Ausgabe. Die drei verfügbaren Stile sind long, short und narrow.

const rtfLong = new Intl.RelativeTimeFormat('en-US', {
  style: 'long'
});
console.log(rtfLong.format(-2, 'hour'));
// "2 hours ago"

const rtfShort = new Intl.RelativeTimeFormat('en-US', {
  style: 'short'
});
console.log(rtfShort.format(-2, 'hour'));
// "2 hr. ago"

const rtfNarrow = new Intl.RelativeTimeFormat('en-US', {
  style: 'narrow'
});
console.log(rtfNarrow.format(-2, 'hour'));
// "2h ago"

Der Stil long ist der Standard und eignet sich gut für die meisten Benutzeroberflächen. Der Stil short spart Platz in mobilen Layouts oder Tabellen. Der Stil narrow erzeugt die kompakteste Ausgabe für Designs mit extremen Platzbeschränkungen.

Berechnung von Zeitunterschieden

Die API Intl.RelativeTimeFormat formatiert Werte, berechnet sie aber nicht. Sie müssen den Zeitunterschied selbst berechnen und dann das Ergebnis an den Formatierer übergeben.

Um einen Zeitunterschied zu berechnen, subtrahieren Sie das Zieldatum vom aktuellen Datum und konvertieren dann das Ergebnis von Millisekunden in die gewünschte Einheit.

const rtf = new Intl.RelativeTimeFormat('en-US', { numeric: 'auto' });

function formatDaysAgo(date) {
  const now = new Date();
  const diffInMs = date - now;
  const diffInDays = Math.round(diffInMs / (1000 * 60 * 60 * 24));

  return rtf.format(diffInDays, 'day');
}

const yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);

console.log(formatDaysAgo(yesterday));
// "yesterday"

const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);

console.log(formatDaysAgo(tomorrow));
// "tomorrow"

Diese Funktion berechnet den Unterschied in Tagen zwischen dem Zieldatum und dem aktuellen Datum. Die Berechnung teilt Millisekunden durch die Anzahl der Millisekunden in einem Tag und rundet dann auf die nächste ganze Zahl.

Die Subtraktion date - now erzeugt einen negativen Wert für vergangene Daten und einen positiven Wert für zukünftige Daten. Dies entspricht der Zeichenkonvention, die von der Methode format() erwartet wird.

Eine vollständige Hilfsfunktion erstellen

Für einen allgemeinen Formatierer für relative Zeitangaben müssen Sie die am besten geeignete Zeiteinheit basierend auf der Größenordnung der Zeitdifferenz auswählen.

const rtf = new Intl.RelativeTimeFormat('en-US', { numeric: 'auto' });

const units = {
  year: 24 * 60 * 60 * 1000 * 365,
  month: 24 * 60 * 60 * 1000 * 365 / 12,
  week: 24 * 60 * 60 * 1000 * 7,
  day: 24 * 60 * 60 * 1000,
  hour: 60 * 60 * 1000,
  minute: 60 * 1000,
  second: 1000
};

function formatRelativeTime(date) {
  const now = new Date();
  const diffInMs = date - now;
  const absDiff = Math.abs(diffInMs);

  for (const [unit, msValue] of Object.entries(units)) {
    if (absDiff >= msValue || unit === 'second') {
      const value = Math.round(diffInMs / msValue);
      return rtf.format(value, unit);
    }
  }
}

const fiveMinutesAgo = new Date(Date.now() - 5 * 60 * 1000);
console.log(formatRelativeTime(fiveMinutesAgo));
// "5 minutes ago"

const threeDaysAgo = new Date(Date.now() - 3 * 24 * 60 * 60 * 1000);
console.log(formatRelativeTime(threeDaysAgo));
// "3 days ago"

const tomorrow = new Date(Date.now() + 24 * 60 * 60 * 1000);
console.log(formatRelativeTime(tomorrow));
// "tomorrow"

Diese Funktion iteriert durch Zeiteinheiten von der größten bis zur kleinsten und wählt die erste Einheit aus, bei der die absolute Differenz den Millisekunden-Wert der Einheit überschreitet. Der Fallback auf Sekunden stellt sicher, dass die Funktion immer ein Ergebnis zurückgibt.

Die Einheitendefinitionen verwenden Näherungswerte. Monate werden als 1/12 eines Jahres berechnet, anstatt die unterschiedlichen Monatslängen zu berücksichtigen. Diese Annäherung funktioniert gut für relative Zeitanzeigen, bei denen ungefähre Werte nützlicher sind als exakte Präzision.

Formatierung für die Locale des Benutzers

Anstatt eine bestimmte Locale fest zu codieren, können Sie die bevorzugte Sprache des Benutzers aus dem Browser verwenden.

const userLocale = navigator.language;
const rtf = new Intl.RelativeTimeFormat(userLocale, { numeric: 'auto' });

const yesterday = new Date(Date.now() - 24 * 60 * 60 * 1000);
console.log(rtf.format(-1, 'day'));
// Ausgabe variiert je nach Locale des Benutzers
// Für en-US: "yesterday"
// Für es-ES: "ayer"
// Für fr-FR: "hier"
// Für de-DE: "gestern"

Dieser Ansatz zeigt relative Zeitangaben entsprechend den Spracheinstellungen jedes Benutzers an, ohne dass eine manuelle Locale-Auswahl erforderlich ist. Der Browser stellt die Spracheinstellung bereit, und die API wendet die entsprechenden Formatierungskonventionen an.

Dieselbe Zeit in verschiedenen Sprachen sehen

Derselbe relative Zeitwert erzeugt unterschiedliche Ausgaben für verschiedene Locales. Jede Sprache folgt ihren eigenen Konventionen für Wortstellung, Grammatik und Pluralisierung.

const threeDaysAgo = -3;

const rtfEnglish = new Intl.RelativeTimeFormat('en-US');
console.log(rtfEnglish.format(threeDaysAgo, 'day'));
// "3 days ago"

const rtfSpanish = new Intl.RelativeTimeFormat('es-ES');
console.log(rtfSpanish.format(threeDaysAgo, 'day'));
// "hace 3 días"

const rtfFrench = new Intl.RelativeTimeFormat('fr-FR');
console.log(rtfFrench.format(threeDaysAgo, 'day'));
// "il y a 3 jours"

const rtfGerman = new Intl.RelativeTimeFormat('de-DE');
console.log(rtfGerman.format(threeDaysAgo, 'day'));
// "vor 3 Tagen"

const rtfJapanese = new Intl.RelativeTimeFormat('ja-JP');
console.log(rtfJapanese.format(threeDaysAgo, 'day'));
// "3 日前"

const rtfArabic = new Intl.RelativeTimeFormat('ar-SA');
console.log(rtfArabic.format(threeDaysAgo, 'day'));
// "قبل 3 أيام"

Jede Sprache erzeugt natürlich klingende Ausgaben, die Muttersprachler im Gespräch verwenden würden. Die API bewältigt die gesamte Komplexität verschiedener grammatikalischer Strukturen, unterschiedlicher Schriftsysteme und verschiedener Textrichtungen.

Wiederverwendung von Formatierern für bessere Performance

Das Erstellen einer Intl.RelativeTimeFormat-Instanz beinhaltet das Laden von Locale-Daten und die Verarbeitung von Optionen. Beim Formatieren mehrerer Zeitstempel sollte der Formatierer einmal erstellt und wiederverwendet werden.

const rtf = new Intl.RelativeTimeFormat('en-US', { numeric: 'auto' });

const timestamps = [
  new Date(Date.now() - 5 * 60 * 1000),      // vor 5 Minuten
  new Date(Date.now() - 2 * 60 * 60 * 1000), // vor 2 Stunden
  new Date(Date.now() - 24 * 60 * 60 * 1000) // vor 1 Tag
];

timestamps.forEach(date => {
  const diffInMs = date - new Date();
  const diffInMinutes = Math.round(diffInMs / (60 * 1000));
  console.log(rtf.format(diffInMinutes, 'minute'));
});

Dieser Ansatz ist effizienter als das Erstellen eines neuen Formatierers für jeden Zeitstempel. Der Leistungsunterschied wird signifikant, wenn Hunderte oder Tausende von Zeitstempeln in Aktivitätsfeeds oder Kommentar-Threads formatiert werden.

Verwendung relativer Zeitangaben in Benutzeroberflächen

Sie können relative Zeitformatierung überall dort verwenden, wo Sie Zeitstempel für Benutzer anzeigen. Dies umfasst Social-Media-Feeds, Kommentarbereiche, Aktivitätsprotokolle, Benachrichtigungssysteme und jede Schnittstelle, bei der die Anzeige, wie lange etwas her ist, den Benutzern hilft, den Kontext zu verstehen.

const rtf = new Intl.RelativeTimeFormat(navigator.language, {
  numeric: 'auto'
});

function updateTimestamp(element, date) {
  const now = new Date();
  const diffInMs = date - now;
  const diffInMinutes = Math.round(diffInMs / (60 * 1000));

  element.textContent = rtf.format(diffInMinutes, 'minute');
}

const commentDate = new Date('2025-10-15T14:30:00');
const timestampElement = document.getElementById('comment-timestamp');

updateTimestamp(timestampElement, commentDate);

Die formatierten Zeichenketten funktionieren wie jeder andere Zeichenkettenwert. Sie können sie in Textinhalte, Attribute oder jeden anderen Kontext einfügen, in dem Sie Informationen für Benutzer anzeigen.