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

Nutze Intl.RelativeTimeFormat, um Zeiten 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 Zeitangaben helfen Nutzer:innen, schnell zu erfassen, wann etwas passiert ist, ohne ein absolutes Datum interpretieren zu müssen.

Wenn du diese Zeichenketten auf Englisch fest codierst, gehst du davon aus, dass alle Nutzer:innen Englisch sprechen und den englischen Grammatikregeln folgen. Verschiedene Sprachen drücken relative Zeit unterschiedlich aus. Spanisch sagt zum Beispiel „hace 3 días“ statt „3 days ago“. Japanisch verwendet „3日前“ mit einer ganz anderen Struktur. Jede Sprache hat zudem eigene Pluralisierungsregeln, die bestimmen, wann Singular- oder Pluralformen verwendet werden.

JavaScript stellt die Intl.RelativeTimeFormat-API bereit, um relative Zeitangaben automatisch zu formatieren. In dieser Lektion erfährst du, wie du mit dieser integrierten API relative Zeiten in jeder Sprache korrekt formatierst.

Warum die Formatierung relativer Zeiten 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 andere Wortstellungen, Präpositionen oder ganz andere grammatische 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 eine natürlich klingende Ausgabe, die ihren eigenen Konventionen folgt. Du musst diese Konventionen nicht kennen oder Übersetzungsdateien pflegen. Die API übernimmt alle Formatierungsdetails automatisch.

Auch die Pluralisierungsregeln unterscheiden sich stark zwischen den Sprachen. Im Englischen wird zwischen „1 day“ und „2 days“ unterschieden. Arabisch hat je nach Anzahl sechs verschiedene Pluralformen. Japanisch verwendet unabhängig von der Menge immer die gleiche Form. Die Intl.RelativeTimeFormat-API wendet für jede Sprache die korrekten Pluralisierungsregeln an.

Die Intl.RelativeTimeFormat-API

Der Intl.RelativeTimeFormat-Konstruktor erstellt einen Formatter, der numerische Werte und Zeiteinheiten in lokalisierte Strings umwandelt. Sie übergeben eine Locale-Kennung als erstes Argument und rufen dann die format()-Methode 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 format()-Methode nimmt zwei Parameter entgegen. Der erste ist eine Zahl, die die Zeitspanne repräsentiert. Der zweite ist ein String, der die Zeiteinheit angibt.

Negative Zahlen kennzeichnen vergangene Zeiten, während positive Zahlen zukünftige Zeiten kennzeichnen. Diese Konvention macht die API intuitiv nutzbar, sobald Sie die Vorzeichenkonvention verstanden haben.

Formatierung vergangener und zukünftiger Zeiten

Das Vorzeichen des Werts 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 Formatierung relativer Zeiten 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 Quartal-Einheit ist nützlich für Business-Anwendungen, die mit Geschäftsperioden arbeiten.

Verwendung natürlicher Sprache mit numeric auto

Die numeric-Option steuert, ob der Formatter Zahlen oder natürlichsprachliche Alternativen verwendet. Der Standardwert ist always, wodurch immer Zahlen angezeigt werden.

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"

Das Setzen von numeric auf auto sorgt für eine natürlichere Formulierung bei bestimmten Werten.

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"

Mit dieser Option wirken Benutzeroberflächen gesprächiger. Nutzer sehen "gestern" statt "vor 1 Tag", was natürlicher klingt. Die Option auto funktioniert für alle Zeiteinheiten und in allen Sprachen, wobei jede Sprache eigene idiomatische Alternativen bereitstellt.

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 für die meisten Oberflächen. Der Stil short spart Platz in mobilen Layouts oder Tabellen. Der Stil narrow erzeugt die kompakteste Ausgabe für extrem platzbeschränkte Designs.

Zeitdifferenzen berechnen

Die API Intl.RelativeTimeFormat formatiert Werte, berechnet sie jedoch nicht. Sie müssen die Zeitdifferenz selbst berechnen und das Ergebnis an den Formatter übergeben.

Um eine Zeitdifferenz zu berechnen, subtrahieren Sie das Zieldatum vom aktuellen Datum und konvertieren 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 die Differenz in Tagen zwischen dem Zieldatum und jetzt. Die Berechnung teilt die Millisekunden durch die Anzahl der Millisekunden pro Tag und rundet auf die nächste ganze Zahl.

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

Eine vollständige Hilfsfunktion erstellen

Für einen universellen 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 zur kleinsten und wählt die erste Einheit aus, bei der die absolute Differenz den Millisekundenwert 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 unterschiedliche Monatslängen zu berücksichtigen. Diese Näherung funktioniert gut für relative Zeitanzeigen, bei denen ungefähre Werte nützlicher sind als exakte Präzision.

Formatierung für das Gebietsschema des Benutzers

Anstatt ein bestimmtes Gebietsschema 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'));
// Output varies by user's locale
// For en-US: "yesterday"
// For es-ES: "ayer"
// For fr-FR: "hier"
// For de-DE: "gestern"

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

Dieselbe Zeit in verschiedenen Sprachen sehen

Derselbe relative Zeitwert erzeugt unterschiedliche Ausgaben für verschiedene Gebietsschemata. Jede Sprache folgt ihren eigenen Konventionen für Wortreihenfolge, 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 in Gesprächen verwenden würden. Die API übernimmt die gesamte Komplexität unterschiedlicher grammatikalischer Strukturen, unterschiedlicher Schriftsysteme und unterschiedlicher Textrichtungen.

Formatierer für bessere Performance wiederverwenden

Das Erstellen einer Intl.RelativeTimeFormat-Instanz umfasst das Laden von Gebietsschemadaten und die Verarbeitung von Optionen. Wenn Sie mehrere Zeitstempel formatieren, erstellen Sie den Formatierer einmal und verwenden Sie ihn wieder.

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

const timestamps = [
  new Date(Date.now() - 5 * 60 * 1000),      // 5 minutes ago
  new Date(Date.now() - 2 * 60 * 60 * 1000), // 2 hours ago
  new Date(Date.now() - 24 * 60 * 60 * 1000) // 1 day ago
];

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 die Erstellung eines neuen Formatters für jeden Zeitstempel. Der Leistungsunterschied wird signifikant, wenn Hunderte oder Tausende von Zeitstempeln in Aktivitäts-Feeds oder Kommentar-Threads formatiert werden.

Verwendung relativer Zeiten in Benutzeroberflächen

Sie können die relative Zeitformatierung überall dort verwenden, wo Sie Benutzern Zeitstempel anzeigen. Dies umfasst Social-Media-Feeds, Kommentarbereiche, Aktivitätsprotokolle, Benachrichtigungssysteme und jede Benutzeroberfläche, bei der die Anzeige, wie lange etwas her ist, 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 Strings funktionieren wie jeder andere String-Wert. Sie können sie in Textinhalte, Attribute oder jeden anderen Kontext einfügen, in dem Sie Benutzern Informationen anzeigen.