So formatieren Sie Datumsbereiche wie 1. Jan. - 5. Jan.
Verwenden Sie JavaScript, um Datumsbereiche mit gebietsschema-gerechter Formatierung und intelligenter Redundanzentfernung anzuzeigen
Einführung
Datumsbereiche erscheinen in Webanwendungen überall. Buchungssysteme zeigen Verfügbarkeiten vom 1. Januar bis 5. Januar, Veranstaltungskalender zeigen mehrtägige Konferenzen, Analyse-Dashboards zeigen Daten für bestimmte Zeiträume und Berichte decken Geschäftsquartale oder benutzerdefinierte Datumsspannen ab. Diese Bereiche kommunizieren, dass etwas für alle Daten zwischen zwei Endpunkten gilt.
Wenn Sie Datumsbereiche manuell formatieren, indem Sie zwei formatierte Daten mit einem Bindestrich verketten, erstellen Sie unnötig ausführliche Ausgaben. Ein Bereich vom 1. Januar 2024 bis 5. Januar 2024 muss Monat und Jahr im zweiten Datum nicht wiederholen. Die Ausgabe "1. - 5. Januar 2024" vermittelt dieselbe Information prägnanter, indem redundante Komponenten weggelassen werden.
JavaScript stellt die Methode formatRange() auf Intl.DateTimeFormat bereit, um die Formatierung von Datumsbereichen automatisch zu handhaben. Diese Methode bestimmt, welche Datumskomponenten in jedem Teil des Bereichs enthalten sein sollen, wendet gebietsschema-spezifische Konventionen für Trennzeichen und Formatierung an und entfernt unnötige Wiederholungen.
Warum Datumsbereiche intelligente Formatierung benötigen
Verschiedene Datumsbereiche erfordern unterschiedliche Detailgrade. Ein Bereich innerhalb desselben Monats benötigt weniger Informationen als ein Bereich, der mehrere Jahre umfasst. Das optimale Format hängt davon ab, welche Datumskomponenten sich zwischen Start- und Enddatum unterscheiden.
Für einen Bereich innerhalb desselben Tages müssen Sie nur die Zeitdifferenz anzeigen: "10:00 - 14:00 Uhr". Die Wiederholung des vollständigen Datums für beide Zeiten fügt keine Information hinzu.
Bei einem Zeitraum innerhalb desselben Monats wird der Monat einmal angezeigt und beide Tageszahlen aufgelistet: „1.–5. Januar 2024". Die zweimalige Angabe von „Januar" macht die Ausgabe schwerer lesbar, ohne die Klarheit zu erhöhen.
Bei einem Zeitraum über verschiedene Monate im selben Jahr werden beide Monate angezeigt, aber das Jahr kann beim ersten Datum weggelassen werden: „25. Dezember 2024 – 2. Januar 2025" benötigt die vollständigen Informationen, aber „15. Januar – 20. Februar 2024" kann in einigen Gebietsschemata das Jahr beim ersten Datum weglassen.
Bei Zeiträumen über mehrere Jahre muss das Jahr für beide Daten angegeben werden: „1. Dezember 2023 – 15. März 2024".
Die manuelle Implementierung dieser Regeln erfordert die Überprüfung, welche Datumskomponenten sich unterscheiden, und die entsprechende Konstruktion von Formatzeichenfolgen. Verschiedene Gebietsschemata wenden diese Regeln auch unterschiedlich an und verwenden verschiedene Trennzeichen und Sortierkonventionen. Die formatRange()-Methode kapselt diese Logik.
Verwenden von formatRange zum Formatieren von Datumsbereichen
Die formatRange()-Methode akzeptiert zwei Date-Objekte und gibt eine formatierte Zeichenfolge zurück. Erstellen Sie eine Intl.DateTimeFormat-Instanz mit Ihrem gewünschten Gebietsschema und Optionen und rufen Sie dann formatRange() mit Start- und Enddatum auf.
const formatter = new Intl.DateTimeFormat("en-US");
const start = new Date(2024, 0, 1);
const end = new Date(2024, 0, 5);
console.log(formatter.formatRange(start, end));
// Output: "1/1/24 – 1/5/24"
Der Formatierer wendet das standardmäßige US-englische Datumsformat auf beide Daten an und verbindet sie mit einem Halbgeviertstrich. Bei Daten innerhalb desselben Monats zeigt die Ausgabe immer noch beide vollständigen Daten an, da das Standardformat recht kurz ist.
Sie können angeben, welche Datumskomponenten einbezogen werden sollen, indem Sie dieselben Optionen verwenden, die für die reguläre Datumsformatierung verfügbar sind.
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric"
});
const start = new Date(2024, 0, 1);
const end = new Date(2024, 0, 5);
console.log(formatter.formatRange(start, end));
// Output: "January 1 – 5, 2024"
Jetzt lässt der Formatierer intelligent Monat und Jahr beim zweiten Datum weg, da sie mit dem ersten Datum übereinstimmen. Die Ausgabe zeigt nur die Tageszahl für das Enddatum an, wodurch der Zeitraum besser lesbar wird.
Wie formatRange die Ausgabe von Datumsbereichen optimiert
Die formatRange()-Methode untersucht beide Daten und bestimmt, welche Komponenten sich unterscheiden. Sie enthält nur die notwendigen Komponenten in jedem Teil des Bereichs.
Bei Daten im selben Monat und Jahr erscheint nur der Endtag im zweiten Teil.
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric"
});
console.log(formatter.formatRange(
new Date(2024, 0, 1),
new Date(2024, 0, 5)
));
// Output: "January 1 – 5, 2024"
console.log(formatter.formatRange(
new Date(2024, 0, 15),
new Date(2024, 0, 20)
));
// Output: "January 15 – 20, 2024"
Beide Bereiche zeigen Monat und Jahr einmal, wobei nur die Tageszahlen durch das Bereichstrennzeichen verbunden sind.
Bei Daten in verschiedenen Monaten desselben Jahres erscheinen beide Monate, aber das Jahr erscheint nur einmal.
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric"
});
console.log(formatter.formatRange(
new Date(2024, 0, 15),
new Date(2024, 1, 20)
));
// Output: "January 15 – February 20, 2024"
Der Formatierer enthält beide Monatsnamen, platziert das Jahr jedoch am Ende und wendet es auf den gesamten Bereich an.
Bei Daten, die sich über verschiedene Jahre erstrecken, erscheinen beide vollständigen Daten.
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric"
});
console.log(formatter.formatRange(
new Date(2023, 11, 25),
new Date(2024, 0, 5)
));
// Output: "December 25, 2023 – January 5, 2024"
Jedes Datum enthält sein vollständiges Jahr, da sich die Jahre unterscheiden. Der Formatierer kann keines der Jahre weglassen, ohne Mehrdeutigkeit zu erzeugen.
Formatierung von Datums- und Zeitbereichen
Wenn Ihr Format Zeitkomponenten enthält, wendet die formatRange()-Methode dieselbe intelligente Auslassung auf Zeitfelder an.
Bei Zeiten am selben Tag unterscheiden sich nur die Zeitkomponenten in der Ausgabe.
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric",
hour: "numeric",
minute: "numeric"
});
const start = new Date(2024, 0, 1, 10, 0);
const end = new Date(2024, 0, 1, 14, 30);
console.log(formatter.formatRange(start, end));
// Output: "January 1, 2024, 10:00 AM – 2:30 PM"
Das Datum erscheint einmal, gefolgt vom Zeitbereich. Der Formatierer erkennt, dass die Wiederholung des vollständigen Datums und der Zeit für das Ende keine nützlichen Informationen hinzufügen würde.
Bei Zeiten an verschiedenen Tagen erscheinen beide vollständigen Datums- und Zeitwerte.
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric",
hour: "numeric",
minute: "numeric"
});
const start = new Date(2024, 0, 1, 10, 0);
const end = new Date(2024, 0, 2, 14, 30);
console.log(formatter.formatRange(start, end));
// Output: "January 1, 2024, 10:00 AM – January 2, 2024, 2:30 PM"
Beide Daten und Zeiten erscheinen, da sie verschiedene Tage darstellen. Der Formatierer kann keine Komponenten sicher weglassen.
Formatierung von Datumsbereichen in verschiedenen Locales
Die Bereichsformatierung passt sich den Konventionen jedes Locales für die Reihenfolge der Datumskomponenten, Trennzeichen und welche Komponenten weggelassen werden sollen an.
const enFormatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric"
});
console.log(enFormatter.formatRange(
new Date(2024, 0, 1),
new Date(2024, 0, 5)
));
// Output: "January 1 – 5, 2024"
const deFormatter = new Intl.DateTimeFormat("de-DE", {
year: "numeric",
month: "long",
day: "numeric"
});
console.log(deFormatter.formatRange(
new Date(2024, 0, 1),
new Date(2024, 0, 5)
));
// Output: "1.–5. Januar 2024"
const jaFormatter = new Intl.DateTimeFormat("ja-JP", {
year: "numeric",
month: "long",
day: "numeric"
});
console.log(jaFormatter.formatRange(
new Date(2024, 0, 1),
new Date(2024, 0, 5)
));
// Output: "2024年1月1日~5日"
Im Englischen steht der Monat zuerst und das Jahr am Ende. Im Deutschen stehen die Tageszahlen mit Punkten zuerst, dann der Monatsname, dann das Jahr. Im Japanischen wird die Reihenfolge Jahr-Monat-Tag verwendet und der Wellenstrich (~) als Bereichstrennzeichen. Jede Locale wendet ihre eigenen Konventionen an, welche Komponenten einmal oder zweimal angezeigt werden.
Diese Unterschiede erstrecken sich auf monatsübergreifende Bereiche.
const enFormatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric"
});
console.log(enFormatter.formatRange(
new Date(2024, 0, 15),
new Date(2024, 1, 20)
));
// Output: "January 15 – February 20, 2024"
const deFormatter = new Intl.DateTimeFormat("de-DE", {
year: "numeric",
month: "long",
day: "numeric"
});
console.log(deFormatter.formatRange(
new Date(2024, 0, 15),
new Date(2024, 1, 20)
));
// Output: "15. Januar – 20. Februar 2024"
const frFormatter = new Intl.DateTimeFormat("fr-FR", {
year: "numeric",
month: "long",
day: "numeric"
});
console.log(frFormatter.formatRange(
new Date(2024, 0, 15),
new Date(2024, 1, 20)
));
// Output: "15 janvier – 20 février 2024"
Alle drei Locales zeigen beide Monatsnamen, positionieren sie jedoch unterschiedlich relativ zu den Tageszahlen. Die Formatter handhaben diese Variationen automatisch.
Formatierung von Datumsbereichen mit verschiedenen Stilen
Sie können die Option dateStyle verwenden, um die Gesamtformatlänge zu steuern, genau wie bei der Formatierung einzelner Daten.
const shortFormatter = new Intl.DateTimeFormat("en-US", {
dateStyle: "short"
});
console.log(shortFormatter.formatRange(
new Date(2024, 0, 1),
new Date(2024, 0, 5)
));
// Output: "1/1/24 – 1/5/24"
const mediumFormatter = new Intl.DateTimeFormat("en-US", {
dateStyle: "medium"
});
console.log(mediumFormatter.formatRange(
new Date(2024, 0, 1),
new Date(2024, 0, 5)
));
// Output: "Jan 1 – 5, 2024"
const longFormatter = new Intl.DateTimeFormat("en-US", {
dateStyle: "long"
});
console.log(longFormatter.formatRange(
new Date(2024, 0, 1),
new Date(2024, 0, 5)
));
// Output: "January 1 – 5, 2024"
const fullFormatter = new Intl.DateTimeFormat("en-US", {
dateStyle: "full"
});
console.log(fullFormatter.formatRange(
new Date(2024, 0, 1),
new Date(2024, 0, 5)
));
// Output: "Monday, January 1 – Friday, January 5, 2024"
Der Stil short erzeugt numerische Daten und wendet keine intelligente Auslassung an, da das Format bereits kompakt ist. Die Stile medium und long kürzen den Monat ab oder schreiben ihn aus und lassen redundante Komponenten weg. Der Stil full enthält Wochentagsnamen für beide Daten.
Verwendung von formatRangeToParts für benutzerdefiniertes Styling
Die Methode formatRangeToParts() gibt ein Array von Objekten zurück, die die Komponenten des formatierten Bereichs darstellen. Dies ermöglicht es Ihnen, einzelne Teile der Bereichsausgabe zu stylen oder zu manipulieren.
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric"
});
const parts = formatter.formatRangeToParts(
new Date(2024, 0, 1),
new Date(2024, 0, 5)
);
console.log(parts);
Die Ausgabe ist ein Array von Objekten, jedes mit den Eigenschaften type, value und source.
[
{ type: "month", value: "January", source: "startRange" },
{ type: "literal", value: " ", source: "startRange" },
{ type: "day", value: "1", source: "startRange" },
{ type: "literal", value: " – ", source: "shared" },
{ type: "day", value: "5", source: "endRange" },
{ type: "literal", value: ", ", source: "shared" },
{ type: "year", value: "2024", source: "shared" }
]
Die Eigenschaft type identifiziert die Komponente: Monat, Tag, Jahr oder Literaltext. Die Eigenschaft value enthält den formatierten Text. Die Eigenschaft source gibt an, ob die Komponente zum Startdatum, Enddatum gehört oder zwischen ihnen geteilt wird.
Sie können diese Teile verwenden, um benutzerdefiniertes HTML mit Styling für verschiedene Komponenten zu erstellen.
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric"
});
const parts = formatter.formatRangeToParts(
new Date(2024, 0, 1),
new Date(2024, 0, 5)
);
let html = "";
parts.forEach(part => {
if (part.type === "month") {
html += `<span class="month">${part.value}</span>`;
} else if (part.type === "day") {
html += `<span class="day">${part.value}</span>`;
} else if (part.type === "year") {
html += `<span class="year">${part.value}</span>`;
} else if (part.type === "literal" && part.source === "shared" && part.value.includes("–")) {
html += `<span class="separator">${part.value}</span>`;
} else {
html += part.value;
}
});
console.log(html);
// Output: <span class="month">January</span> <span class="day">1</span><span class="separator"> – </span><span class="day">5</span>, <span class="year">2024</span>
Diese Technik bewahrt die gebietsschemaspezifische Formatierung und ermöglicht gleichzeitig benutzerdefiniertes visuelles Styling.
Was passiert, wenn Daten gleich sind
Wenn Sie dasselbe Datum sowohl für den Start- als auch für den End-Parameter übergeben, gibt formatRange() ein einzelnes formatiertes Datum anstelle eines Bereichs aus.
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric"
});
const date = new Date(2024, 0, 1);
console.log(formatter.formatRange(date, date));
// Output: "January 1, 2024"
Der Formatierer erkennt, dass ein Bereich mit identischen Endpunkten kein echter Bereich ist und formatiert ihn als einzelnes Datum. Dieses Verhalten gilt auch dann, wenn die Date-Objekte unterschiedliche Instanzen mit demselben Wert sind.
const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "long",
day: "numeric"
});
const start = new Date(2024, 0, 1, 10, 0);
const end = new Date(2024, 0, 1, 10, 0);
console.log(formatter.formatRange(start, end));
// Output: "January 1, 2024"
Obwohl es sich um separate Date-Objekte handelt, repräsentieren sie dasselbe Datum und dieselbe Uhrzeit. Der Formatierer gibt ein einzelnes Datum aus, da der Bereich eine Dauer von null auf der Präzisionsebene der Formatoptionen hat. Da das Format keine Zeitkomponenten enthält, sind die Uhrzeiten irrelevant und die Daten werden als gleich betrachtet.
Wann formatRange vs. manuelle Formatierung verwendet werden sollte
Verwenden Sie formatRange(), wenn Sie Datumsbereiche für Benutzer anzeigen. Dies gilt für Buchungsdatumsbereiche, Veranstaltungsdauer, Berichtszeiträume, Verfügbarkeitsfenster oder andere Zeitspannen. Die Methode gewährleistet korrekte gebietsschemaspezifische Formatierung und optimale Komponentenauslassung.
Vermeiden Sie formatRange(), wenn Sie mehrere nicht zusammenhängende Daten anzeigen müssen. Eine Liste von Fristen wie "1. Januar, 15. Januar, 1. Februar" sollte reguläre format()-Aufrufe für jedes Datum verwenden, anstatt sie als Bereiche zu behandeln.
Vermeiden Sie auch formatRange(), wenn Sie Vergleiche oder Unterschiede zwischen Daten anzeigen. Wenn Sie anzeigen, wie viel früher oder später ein Datum im Vergleich zu einem anderen ist, stellt dies eine relative Zeitberechnung dar und keinen Bereich.