Wie man einzelne Teile eines formatierten Datums in JavaScript erhält

Verwenden Sie formatToParts(), um auf jede Komponente eines lokal formatierten Datums separat zuzugreifen

Einführung

Die format()-Methode gibt einen vollständig formatierten String wie "15. Januar 2025" oder "15.01.2025" zurück. Dies funktioniert gut für einfache Anzeigen, aber Sie können einzelne Teile nicht unterschiedlich gestalten. Sie können den Monatsnamen nicht fett formatieren, das Jahr nicht anders einfärben oder einzelnen Komponenten kein benutzerdefiniertes Markup zuweisen.

JavaScript bietet die formatToParts()-Methode, um dieses Problem zu lösen. Anstatt einen einzelnen String zurückzugeben, gibt sie ein Array von Objekten zurück, von denen jedes einen Teil des formatierten Datums repräsentiert. Jeder Teil hat einen Typ wie month, day oder year und einen Wert wie January, 15 oder 2025. Sie können diese Teile dann verarbeiten, um benutzerdefinierte Stile anzuwenden, komplexe Layouts zu erstellen oder formatierte Daten in umfangreiche Benutzeroberflächen zu integrieren.

Warum formatierte Strings schwer anzupassen sind

Wenn Sie einen formatierten String wie "15. Januar 2025" erhalten, können Sie nicht einfach erkennen, wo der Monat endet und der Tag beginnt. Verschiedene Locales ordnen Komponenten in unterschiedlichen Reihenfolgen an. Einige Locales verwenden unterschiedliche Trennzeichen. Das zuverlässige Parsen dieser Strings erfordert komplexe Logik, die die bereits in der Intl-API implementierten Formatierungsregeln dupliziert.

Betrachten Sie eine Kalenderanwendung, die Daten mit fett formatiertem Monatsnamen anzeigt. Mit format() müssten Sie:

  1. Erkennen, welche Zeichen den Monatsnamen repräsentieren
  2. Leerzeichen und Interpunktion zwischen Komponenten berücksichtigen
  3. Verschiedene Monatsformate über Locales hinweg handhaben
  4. Den String sorgfältig parsen, um das Datum nicht zu beschädigen

Dieser Ansatz ist fragil und fehleranfällig. Jede Änderung an den Locale-Formatierungsregeln bricht Ihre Parsing-Logik.

Die formatToParts()-Methode eliminiert dieses Problem, indem sie die Komponenten separat bereitstellt. Sie erhalten strukturierte Daten, die Ihnen unabhängig vom Locale genau sagen, welcher Teil welcher ist.

Verwendung von formatToParts zum Abrufen von Datumskomponenten

Die formatToParts()-Methode funktioniert identisch zu format(), mit Ausnahme ihres Rückgabewerts. Sie erstellen einen Formatter mit denselben Optionen und rufen dann formatToParts() anstelle von format() auf.

const formatter = new Intl.DateTimeFormat("en-US", {
  year: "numeric",
  month: "long",
  day: "numeric"
});

const date = new Date(2025, 0, 15);
const parts = formatter.formatToParts(date);
console.log(parts);

Dies gibt ein Array von Objekten aus:

[
  { type: "month", value: "January" },
  { type: "literal", value: " " },
  { type: "day", value: "15" },
  { type: "literal", value: ", " },
  { type: "year", value: "2025" }
]

Jedes Objekt enthält eine type-Eigenschaft, die identifiziert, was der Teil darstellt, und eine value-Eigenschaft, die die tatsächliche Zeichenkette enthält. Die Teile erscheinen in derselben Reihenfolge, wie sie in der formatierten Ausgabe vorkommen würden.

Sie können dies überprüfen, indem Sie alle Werte zusammenfügen:

const formatted = parts.map(part => part.value).join("");
console.log(formatted);
// Output: "January 15, 2025"

Die verketteten Teile erzeugen exakt dieselbe Ausgabe wie der Aufruf von format().

Verständnis der Teiltypen

Die type-Eigenschaft identifiziert jede Komponente. Unterschiedliche Formatierungsoptionen erzeugen unterschiedliche Teiltypen.

Für grundlegende Datumsformatierung:

const formatter = new Intl.DateTimeFormat("en-US", {
  year: "numeric",
  month: "long",
  day: "numeric"
});

const date = new Date(2025, 0, 15);
const parts = formatter.formatToParts(date);
console.log(parts);
// [
//   { type: "month", value: "January" },
//   { type: "literal", value: " " },
//   { type: "day", value: "15" },
//   { type: "literal", value: ", " },
//   { type: "year", value: "2025" }
// ]

Der month-Typ repräsentiert den Monatsnamen oder die Monatsnummer. Der day-Typ repräsentiert den Tag des Monats. Der year-Typ repräsentiert das Jahr. Der literal-Typ repräsentiert Leerzeichen, Interpunktion oder anderen Text, der vom Formatter eingefügt wird.

Für Daten mit Wochentagen:

const formatter = new Intl.DateTimeFormat("en-US", {
  weekday: "long",
  year: "numeric",
  month: "long",
  day: "numeric"
});

const date = new Date(2025, 0, 15);
const parts = formatter.formatToParts(date);
console.log(parts);
// [
//   { type: "weekday", value: "Wednesday" },
//   { type: "literal", value: ", " },
//   { type: "month", value: "January" },
//   { type: "literal", value: " " },
//   { type: "day", value: "15" },
//   { type: "literal", value: ", " },
//   { type: "year", value: "2025" }
// ]

Der weekday-Typ repräsentiert den Wochentag.

Für Daten mit Uhrzeiten:

const formatter = new Intl.DateTimeFormat("en-US", {
  year: "numeric",
  month: "long",
  day: "numeric",
  hour: "numeric",
  minute: "numeric",
  second: "numeric"
});

const date = new Date(2025, 0, 15, 14, 30, 45);
const parts = formatter.formatToParts(date);
console.log(parts);
// [
//   { type: "month", value: "January" },
//   { type: "literal", value: " " },
//   { type: "day", value: "15" },
//   { type: "literal", value: ", " },
//   { type: "year", value: "2025" },
//   { type: "literal", value: " at " },
//   { type: "hour", value: "2" },
//   { type: "literal", value: ":" },
//   { type: "minute", value: "30" },
//   { type: "literal", value: ":" },
//   { type: "second", value: "45" },
//   { type: "literal", value: " " },
//   { type: "dayPeriod", value: "PM" }
// ]

Die Typen hour, minute und second repräsentieren Zeitkomponenten. Der Typ dayPeriod repräsentiert AM oder PM im 12-Stunden-Format.

Anwenden von benutzerdefiniertem Styling auf Datumsbestandteile

Der primäre Anwendungsfall für formatToParts() ist das Anwenden unterschiedlicher Styles auf verschiedene Komponenten. Sie können das Parts-Array verarbeiten, um bestimmte Typen in HTML-Elemente einzubetten.

Den Monatsnamen fett darstellen:

const formatter = new Intl.DateTimeFormat("en-US", {
  year: "numeric",
  month: "long",
  day: "numeric"
});

const date = new Date(2025, 0, 15);
const parts = formatter.formatToParts(date);
const html = parts
  .map(part => {
    if (part.type === "month") {
      return `<strong>${part.value}</strong>`;
    }
    return part.value;
  })
  .join("");

console.log(html);
// Output: "<strong>January</strong> 15, 2025"

Dieser Ansatz funktioniert für jede Markup-Sprache. Sie können HTML, JSX oder jedes andere Format generieren, indem Sie das Parts-Array verarbeiten.

Das Jahr unterschiedlich stylen:

const formatter = new Intl.DateTimeFormat("en-US", {
  year: "numeric",
  month: "long",
  day: "numeric"
});

const date = new Date(2025, 0, 15);
const parts = formatter.formatToParts(date);
const html = parts
  .map(part => {
    if (part.type === "year") {
      return `<span class="text-gray-500">${part.value}</span>`;
    }
    return part.value;
  })
  .join("");

console.log(html);
// Output: "January 15, <span class="text-gray-500">2025</span>"

Dieses Muster ist in Kalenderanzeigen üblich, bei denen verschiedene Komponenten unterschiedliche visuelle Betonung benötigen.

Erstellen benutzerdefinierter Datumsanzeigen mit mehreren Styles

Komplexe Interfaces kombinieren oft mehrere Styling-Regeln. Sie können verschiedene Klassen oder Elemente gleichzeitig auf unterschiedliche Part-Typen anwenden.

const formatter = new Intl.DateTimeFormat("en-US", {
  weekday: "long",
  year: "numeric",
  month: "long",
  day: "numeric"
});

const date = new Date(2025, 0, 15);
const parts = formatter.formatToParts(date);

const html = parts
  .map(part => {
    switch (part.type) {
      case "weekday":
        return `<span class="weekday">${part.value}</span>`;
      case "month":
        return `<span class="month">${part.value}</span>`;
      case "day":
        return `<span class="day">${part.value}</span>`;
      case "year":
        return `<span class="year">${part.value}</span>`;
      case "literal":
        return `<span class="literal">${part.value}</span>`;
      default:
        return part.value;
    }
  })
  .join("");

console.log(html);
// Output: "<span class="weekday">Wednesday</span><span class="literal">, </span><span class="month">January</span><span class="literal"> </span><span class="day">15</span><span class="literal">, </span><span class="year">2025</span>"

Diese granulare Kontrolle ermöglicht präzises Styling für jede Komponente. Sie können dann CSS verwenden, um jede Klasse unterschiedlich zu stylen.

Erstellen benutzerdefinierter Datumslayouts

Sie können Datumskomponenten in benutzerdefinierte Layouts umordnen, die vom Standard-Locale-Format abweichen. Extrahieren Sie spezifische Parts und komponieren Sie diese in beliebiger Reihenfolge.

const formatter = new Intl.DateTimeFormat("en-US", {
  year: "numeric",
  month: "long",
  day: "numeric"
});

const date = new Date(2025, 0, 15);
const parts = formatter.formatToParts(date);

const day = parts.find(p => p.type === "day").value;
const month = parts.find(p => p.type === "month").value;
const year = parts.find(p => p.type === "year").value;

const customLayout = `
  <div class="date-card">
    <div class="day-large">${day}</div>
    <div class="month-small">${month}</div>
    <div class="year-small">${year}</div>
  </div>
`;

console.log(customLayout);

Dies erstellt ein vertikales Karten-Layout mit prominent angezeigtem Tag, gefolgt von Monat und Jahr. Die Komponenten bleiben korrekt lokalisiert, auch wenn das Layout vom Standard-Formatting abweicht.

Alle verfügbaren Part-Typen

Die Property type kann abhängig von den verwendeten Formatierungsoptionen folgende Werte haben:

  • weekday: Wochentag wie Montag oder Mo
  • era: Ära-Indikator wie v. Chr., n. Chr. oder BCE
  • year: Jahr wie 2025
  • month: Monatsname oder -nummer wie Januar oder 01
  • day: Tag des Monats wie 15
  • dayPeriod: AM oder PM oder andere locale-spezifische Tagesperioden
  • hour: Stunde wie 14 oder 2
  • minute: Minute wie 30
  • second: Sekunde wie 45
  • fractionalSecond: Millisekunden oder andere Sekundenbruchteile
  • timeZoneName: Zeitzonenname wie MEZ oder Mitteleuropäische Zeit
  • literal: Leerzeichen, Interpunktion oder anderer durch Formatierung hinzugefügter Text
  • relatedYear: Gregorianisches Jahr in alternativen Kalendersystemen
  • yearName: Benanntes Jahr in einigen Kalendersystemen
  • unknown: Nicht erkannte Tokens

Nicht jede Formatierungsoption erzeugt jeden Teiltyp. Die Teile, die Sie erhalten, hängen vom Datumswert und der Formatter-Konfiguration ab.

Daten mit Epochenindikatoren:

const formatter = new Intl.DateTimeFormat("en-US", {
  year: "numeric",
  era: "short"
});

const date = new Date(-100, 0, 1);
const parts = formatter.formatToParts(date);
console.log(parts);
// [
//   { type: "year", value: "101" },
//   { type: "literal", value: " " },
//   { type: "era", value: "BC" }
// ]

Daten mit Zeitzonen:

const formatter = new Intl.DateTimeFormat("en-US", {
  year: "numeric",
  month: "long",
  day: "numeric",
  hour: "numeric",
  minute: "numeric",
  timeZoneName: "short"
});

const date = new Date(2025, 0, 15, 14, 30);
const parts = formatter.formatToParts(date);
console.log(parts);
// Parts will include { type: "timeZoneName", value: "PST" } or similar

Daten mit Sekundenbruchteilen:

const formatter = new Intl.DateTimeFormat("en-US", {
  hour: "numeric",
  minute: "numeric",
  second: "numeric",
  fractionalSecondDigits: 3
});

const date = new Date(2025, 0, 15, 14, 30, 45, 123);
const parts = formatter.formatToParts(date);
// Parts will include { type: "fractionalSecond", value: "123" }

Bedingte Hervorhebung von Datumskomponenten

Einige Anwendungen heben bestimmte Datumskomponenten basierend auf Geschäftslogik hervor. Mit formatToParts() können Sie Styling basierend auf dem Datumswert anwenden und dabei die korrekte Formatierung beibehalten.

const formatter = new Intl.DateTimeFormat("en-US", {
  year: "numeric",
  month: "long",
  day: "numeric"
});

function formatDateWithHighlight(date) {
  const parts = formatter.formatToParts(date);
  const isWeekend = date.getDay() === 0 || date.getDay() === 6;

  const html = parts
    .map(part => {
      if (part.type === "day" && isWeekend) {
        return `<span class="text-blue-600 font-bold">${part.value}</span>`;
      }
      return part.value;
    })
    .join("");

  return html;
}

const saturday = new Date(2025, 0, 18);
console.log(formatDateWithHighlight(saturday));
// Output: "January <span class="text-blue-600 font-bold">18</span>, 2025"

const monday = new Date(2025, 0, 13);
console.log(formatDateWithHighlight(monday));
// Output: "January 13, 2025"

Das Datum erhält die korrekte Formatierung für das Gebietsschema, während bedingtes Styling basierend auf Geschäftslogik angewendet wird.

Erstellung barrierefreier Datumsanzeigen

Sie können formatToParts() verwenden, um Barrierefreiheitsattribute zu formatierten Daten hinzuzufügen. Dies hilft Screenreadern, Werte korrekt anzukündigen.

const formatter = new Intl.DateTimeFormat("en-US", {
  year: "numeric",
  month: "long",
  day: "numeric"
});

function formatAccessibleDate(date) {
  const parts = formatter.formatToParts(date);
  const formatted = parts.map(part => part.value).join("");
  const isoDate = date.toISOString().split('T')[0];

  return `<time datetime="${isoDate}">${formatted}</time>`;
}

const date = new Date(2025, 0, 15);
console.log(formatAccessibleDate(date));
// Output: "<time datetime="2025-01-15">January 15, 2025</time>"

Dies stellt sicher, dass Screenreader das Datum korrekt ankündigen können, während die Anzeige die gebietsschemaformatierte Version zeigt.

Wie Teile gebietsschemaspezifische Formatierung bewahren

Das Parts-Array behält gebietsschemaspezifische Formatierungsregeln automatisch bei. Verschiedene Gebietsschemata platzieren Komponenten in unterschiedlicher Reihenfolge und verwenden unterschiedliche Formate, aber formatToParts() behandelt diese Unterschiede.

const usFormatter = new Intl.DateTimeFormat("en-US", {
  year: "numeric",
  month: "long",
  day: "numeric"
});

const date = new Date(2025, 0, 15);
console.log(usFormatter.formatToParts(date));
// [
//   { type: "month", value: "January" },
//   { type: "literal", value: " " },
//   { type: "day", value: "15" },
//   { type: "literal", value: ", " },
//   { type: "year", value: "2025" }
// ]

const ukFormatter = new Intl.DateTimeFormat("en-GB", {
  year: "numeric",
  month: "long",
  day: "numeric"
});

console.log(ukFormatter.formatToParts(date));
// [
//   { type: "day", value: "15" },
//   { type: "literal", value: " " },
//   { type: "month", value: "January" },
//   { type: "literal", value: " " },
//   { type: "year", value: "2025" }
// ]

Die britische Formatierung platziert den Tag vor dem Monat. Ihr Styling-Code verarbeitet das Parts-Array unabhängig vom Gebietsschema auf die gleiche Weise, und die Formatierung passt sich automatisch an.

const jpFormatter = new Intl.DateTimeFormat("ja-JP", {
  year: "numeric",
  month: "long",
  day: "numeric"
});

console.log(jpFormatter.formatToParts(date));
// [
//   { type: "year", value: "2025" },
//   { type: "literal", value: "年" },
//   { type: "month", value: "1月" },
//   { type: "day", value: "15" },
//   { type: "literal", value: "日" }
// ]

Die japanische Formatierung verwendet eine andere Reihenfolge und enthält Zeichenliterale wie 年 (Jahr) und 日 (Tag). Das Parts-Array spiegelt diese gebietsschemaspezifischen Konventionen automatisch wider.

Kombination von formatToParts mit Framework-Komponenten

Moderne Frameworks wie React können formatToParts() verwenden, um Komponenten effizient zu erstellen.

function DateDisplay({ date, locale, options }) {
  const formatter = new Intl.DateTimeFormat(locale, options);
  const parts = formatter.formatToParts(date);

  return (
    <span className="date-display">
      {parts.map((part, index) => {
        if (part.type === "month") {
          return <strong key={index}>{part.value}</strong>;
        }
        if (part.type === "year") {
          return <span key={index} className="text-sm text-gray-500">{part.value}</span>;
        }
        return <span key={index}>{part.value}</span>;
      })}
    </span>
  );
}

Diese Komponente wendet unterschiedliches Styling auf verschiedene Teile an und behält dabei die korrekte Formatierung für jedes Gebietsschema bei.

Wann formatToParts anstelle von format verwenden

Verwenden Sie format(), wenn Sie eine einfache formatierte Zeichenkette ohne Anpassungen benötigen. Dies ist der häufigste Fall für die meisten Datumsanzeigen.

Verwenden Sie formatToParts(), wenn Sie:

  • Verschiedene Stile auf verschiedene Teile des Datums anwenden möchten
  • HTML oder JSX mit formatierten Daten erstellen möchten
  • Attribute oder Metadaten zu bestimmten Komponenten hinzufügen möchten
  • Datumskomponenten in benutzerdefinierte Layouts umordnen möchten
  • Formatierte Daten in komplexe Layouts integrieren möchten
  • Formatierte Ausgaben programmatisch verarbeiten möchten

Die Methode formatToParts() hat etwas mehr Overhead als format(), da sie ein Array von Objekten anstelle einer einzelnen Zeichenkette erstellt. Dieser Unterschied ist für typische Anwendungen vernachlässigbar, aber wenn Sie Tausende von Daten pro Sekunde formatieren, bietet format() eine bessere Performance.

Für die meisten Anwendungen sollten Sie basierend auf Ihren Styling-Anforderungen und nicht auf Performance-Überlegungen wählen. Wenn Sie die Ausgabe nicht anpassen müssen, verwenden Sie format(). Wenn Sie benutzerdefiniertes Styling oder Markup benötigen, verwenden Sie formatToParts().