Signatur
Beschreibung
Mit until() berechnest du, wie viele Jahre und Monate zwischen zwei Temporal.PlainYearMonth-Werten liegen. Die Rechnung läuft vom aufrufenden Objekt (this) zum Argument other. Liegt other später, ist die Dauer positiv, liegt es früher, ist sie negativ.
Typische Anwendungsfälle sind Laufzeiten von Verträgen und Abonnements, Abrechnungszeiträume, Garantiefristen oder die Anzahl der Monate bis zu einem Stichtag, also überall dort, wo Tage und Uhrzeiten keine Rolle spielen. Weil PlainYearMonth keine Zeitzone und keinen Tag enthält, ist das Ergebnis immer eindeutig und hängt nicht von der Sommerzeit ab.
Über das options-Objekt legst du fest, in welcher Form das Ergebnis ausgegeben wird. Mit largestUnit: "month" bekommst du zum Beispiel alle Monate als eine Zahl (P29M statt P2Y5M). Mit smallestUnit, roundingIncrement und roundingMode rundest du das Ergebnis, etwa auf ganze Jahre.
Das Gegenstück ist since(). Es rechnet in die umgekehrte Richtung, also von other bis this.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $other Pflicht | Temporal.PlainYearMonth | string | object | Der Ziel-Jahr-Monat. Er wird wie bei Temporal.PlainYearMonth.from() umgewandelt. Erlaubt sind z. B. "2026-08" oder { year: 2026, month: 8 }. |
|
| $options | object | {} | Optionales Objekt, das die Form des Ergebnisses steuert. Mögliche Eigenschaften sind largestUnit, smallestUnit, roundingIncrement und roundingMode (siehe unten). |
| $options.largestUnit | "auto" | "year" | "month" | "auto" (entspricht "year") | Die größte Einheit im Ergebnis. Auch die Pluralformen "years" und "months" sind erlaubt. |
| $options.smallestUnit | "year" | "month" | "month" | Die kleinste Einheit im Ergebnis. Alles, was kleiner ist, wird nach roundingMode gerundet. |
| $options.roundingIncrement | number | 1 | Ganzzahliges Vielfaches von smallestUnit, auf das gerundet wird, z. B. 3 für Quartale bei smallestUnit: "month". |
| $options.roundingMode | "ceil" | "floor" | "expand" | "trunc" | "halfCeil" | "halfFloor" | "halfExpand" | "halfTrunc" | "halfEven" | "trunc" | Legt fest, wie gerundet wird. Standard ist "trunc", also Abschneiden in Richtung null. |
Rückgabewert
Temporal.Duration-Objekt, in dem nur years und/oder months belegt sind. Es ist negativ, wenn other vor this liegt.Beispiele
Einfache Differenz zwischen zwei Monaten
const start = Temporal.PlainYearMonth.from("2024-03");
const end = Temporal.PlainYearMonth.from("2026-08");
const dauer = start.until(end);
console.log(dauer.toString());
console.log(dauer.years, dauer.months);
// Umgekehrte Richtung ergibt eine negative Dauer
console.log(end.until(start).toString());
Vertragslaufzeit komplett in Monaten
const vertragsBeginn = Temporal.PlainYearMonth.from({ year: 2023, month: 11 });
const vertragsEnde = Temporal.PlainYearMonth.from("2025-10");
const laufzeit = vertragsBeginn.until(vertragsEnde, { largestUnit: "month" });
console.log(`Restlaufzeit: ${laufzeit.months} Monate`);
Auf ganze Jahre runden
const start = Temporal.PlainYearMonth.from("2024-03");
const end = Temporal.PlainYearMonth.from("2026-08"); // 2 Jahre, 5 Monate
const kaufmaennisch = start.until(end, { smallestUnit: "year", roundingMode: "halfExpand" });
const aufgerundet = start.until(end, { smallestUnit: "year", roundingMode: "ceil" });
console.log(kaufmaennisch.toString());
console.log(aufgerundet.toString());
Monate bis zu einem Stichtag ab heute
const heute = Temporal.Now.plainDateISO().toPlainYearMonth();
const stichtag = Temporal.PlainYearMonth.from("2030-01");
const rest = heute.until(stichtag, { largestUnit: "month" });
console.log(rest.sign > 0
? `Noch ${rest.months} Monate bis zum Stichtag`
: "Stichtag bereits erreicht");
// Wichtig · Fallstricke
- Browser-Unterstützung: Temporal ist noch recht neu. Es läuft in Firefox ab Version 139 und in Chromium-Browsern ab Version 144, in Safari bisher nicht vollständig. Für den Einsatz im Produktivbetrieb solltest du einen Polyfill wie
@js-temporal/polyfillverwenden oder vorher prüfen, obtypeof Temporal !== \"undefined\"gilt. - Kalender müssen übereinstimmen: Haben
thisundotherunterschiedliche Kalender (z. B.iso8601undhebrew), wirft die Methode einenRangeError. - Ungültige Einheiten: Einheiten wie
\"week\",\"day\"oder kleinere lösen einenRangeErroraus, weilPlainYearMonthkeine Tage kennt. Dasselbe passiert, wennsmallestUnitgrößer alslargestUnitist. - Standardmäßig wird abgeschnitten: Ohne Angabe gilt
roundingMode: \"trunc\". MitsmallestUnit: \"year\"werden aus 2 Jahren und 11 Monaten deshalb nurP2Y. Brauchst du kaufmännisches Runden, setzeroundingModeausdrücklich, z. B. auf\"halfExpand\". - Die Berechnung zählt nur Monate. Wie viele Tage ein Monat hat, spielt keine Rolle. Brauchst du taggenaue Differenzen, nimm
Temporal.PlainDate.prototype.until().