• Skip to primary navigation
  • Skip to main content
  • Skip to primary sidebar

romejs.dev

  • Javascript
  • Blog

JavaScript Date in der Praxis: Alles, was du für robuste Datums- und Zeitlogik wissen musst

13. Oktober 2025 by Mike

Das JavaScript Date-Objekt ist deine Standardbibliothek für Datum und Zeit in Browsern und Node.js. Es kann Millisekunden genau arbeiten, Datumswerte addieren und subtrahieren, zwischen lokaler Zeit und UTC unterscheiden und Strings in prüfbare Zeitwerte wandeln. Gleichzeitig ist es berüchtigt für Zero-based Monate, ISO-Parsing-Fallen und Zeitzonen-Tücken. Hier bekommst du einen umfassenden, praxisnahen Überblick mit Best Practices, Codebeispielen und sauberer Struktur, damit deine Arbeit mit Datum und Zeit stabil bleibt. Hinweis: In modernen asynchronen Szenarien lässt sich der Umgang mit Datum und Zeit auch hervorragend mit Async/Await integrieren.

Was Date intern repräsentiert

Ein Date speichert intern eine einzige Zahl: die Anzahl der Millisekunden seit dem 1. Januar 1970, 00:00:00 UTC (die Unix-Epoche). Dieser Wertebereich reicht gemäß ECMAScript-Spezifikation etwa ±100 Millionen Tage um diese Epoche herum, also grob ±273.785 Jahre. Alle Getter/Setter und Formatierungen leiten sich aus dieser Millisekunden-Zahl ab. Ein Date-Objekt läuft nicht “live” mit – es repräsentiert einen festen Zeitpunkt. Wenn du die “aktuelle Zeit” brauchst, erstelle ein neues Date oder nutze Date.now().

Merke: Date ist mutierbar. Methoden wie setDate() oder setHours() ändern das bestehende Objekt in-place.

So erzeugst du ein Date-Objekt

Du hast mehrere Wege, ein JavaScript Date zu bauen. Die folgenden Varianten sind die wichtigsten:

Signatur Beschreibung Beispiel Hinweis
new Date() Aktuelles Datum/Zeit (lokale Zeit) const d = new Date(); Schnell für “jetzt”
new Date(ms) Aus Millisekunden seit Epoche new Date(0) UTC-basierte Epoche
new Date(year, monthIndex, day?, h?, m?, s?, ms?) Numerische Komponenten (lokal) new Date(2024, 0, 31, 23, 59) Monat ist 0–11
new Date(isoString) ISO 8601-String new Date('2024-01-31T23:59:00Z') “Z” = UTC; sicherste String-Variante

Zu den String-Varianten ist wichtig:

  • ISO 8601, z. B. 2024-01-31T23:59:00Z, ist standardisiert und zuverlässig. Das “Z” kennzeichnet UTC.
  • Nur Datum im ISO-Format, z. B. '2024-01-31', wird in modernen Engines als UTC interpretiert. Das kann zu “Überraschungen” führen, wenn du lokale Mitternacht erwartest.
  • Nicht standardisierte Strings wie '12/31/2024' sind je nach Umgebung uneinheitlich – vermeide sie.
  • Arrays werden zu String konvertiert und führen meist zu Invalid Date – nicht verwenden.
// korrektes ISO: UTC
const a = new Date('2024-01-31T23:59:00Z'); // UTC Zeitpunkt

// ISO ohne Zeit -> interpretiert als UTC
const b = new Date('2024-01-31'); // Achtung: Mitternacht UTC, nicht lokal

// numerisch (lokal):
const c = new Date(2024, 0, 31, 23, 59); // Jan (0), lokale Zeitzone

// aus Millisekunden:
const d = new Date(Date.now()); // äquivalent zu new Date()

javascript date

Getter und Setter richtig nutzen

Die API unterscheidet zwischen lokalen und UTC-Methoden. Lokale Methoden beginnen mit get.../set...; UTC-Varianten mit getUTC.../setUTC....

Methode Lokale Variante UTC-Variante Rückgabe/Bereich Hinweise
Jahr getFullYear() getUTCFullYear() vierstellig getYear() ist veraltet
Monat getMonth() getUTCMonth() 0–11 Zero-based! Jan=0, Dez=11
Tag des Monats getDate() getUTCDate() 1–31 Nicht mit getDay() verwechseln
Wochentag getDay() getUTCDay() 0–6 (So=0) So=0, Mo=1, …
Stunde/Minute/Sekunde getHours() etc. getUTCHours() etc. 0–23 / 0–59 Standardwerte
Millisekunden getMilliseconds() getUTCMilliseconds() 0–999 —
Time Value getTime() — Millisekunden seit Epoche ≈ valueOf()

Beim Setzen zeigt sich eine der größten Stärken von Date: automatisches “Rollover”. Übergibst du Werte außerhalb des Bereichs, korrigiert das Objekt Monat/Jahr entsprechend.

const d = new Date(2024, 0, 31);  // 31. Jan 2024 (lokal)
d.setDate(d.getDate() + 1);       // 1. Feb 2024

// Negativer oder "zu großer" Tag funktioniert ebenfalls:
const e = new Date(2024, 1, 1);   // 1. Feb 2024
e.setDate(0);                     // 31. Jan 2024

Pro-Tipp: Nutze das Rollover-Verhalten für Monats-/Jahreswechsel. Du musst keine Monatslängen selbst berechnen.

Strings ausgeben: toLocale…, toISOString, Intl.DateTimeFormat

Für UI-Ausgaben brauchst du formatierte Strings. Zudem spielt das DOM eine zentrale Rolle bei der Einbindung von Datumswerten in Webanwendungen. Du hast drei Hauptwege:

  • Lokalisierte Ausgabe mit toLocaleDateString(), toLocaleTimeString(), toLocaleString().
  • ISO 8601 mit toISOString() für stabile, transportfähige Repräsentation.
  • Hohe Kontrolle und Performance mit Intl.DateTimeFormat.
const d = new Date('2024-01-31T23:59:00Z');

// Lokalisierte Beispiele
d.toLocaleDateString('de-DE'); // "1.2.2024" (je nach TZ, da UTC->lokal)
d.toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit' }); // "00:59"

// ISO immer UTC mit 'Z':
d.toISOString(); // "2024-01-31T23:59:00.000Z"

// Wiederverwendbares Formatter-Objekt:
const fmt = new Intl.DateTimeFormat('de-DE', {
  weekday: 'long',
  year: 'numeric',
  month: 'long',
  day: 'numeric',
  hour: '2-digit',
  minute: '2-digit',
  timeZone: 'Europe/Berlin'
});
fmt.format(d); // "Donnerstag, 1. Februar 2024 um 00:59"

Regel: Für Speicherung und API-Transport nutze ISO 8601 (toISOString()) oder Zahlenzeitstempel. Für UI nutze Intl.DateTimeFormat mit expliziter timeZone.

Zeitzonen, UTC und Sommerzeit

Standard-Date kennt genau zwei “Sichten”: lokale Zeit und UTC. Die lokale Zeitzone kommt vom System. Der Versatz zur UTC ist über getTimezoneOffset() zugänglich – in Minuten, mit Vorzeichen aus Sicht der lokalen Zeit.

const d = new Date();
const offsetMinutes = d.getTimezoneOffset();  // z. B. -60 für UTC+1

Sommerzeit (DST) macht Offsets dynamisch. Daher ist dieselbe Uhrzeit im Jahr nicht immer gleich versetzt. Für Berechnungen, die unabhängig von DST sein sollen, arbeite in UTC:

// Start des Tages in UTC:
function startOfDayUTC(d) {
  const copy = new Date(d.getTime());
  copy.setUTCHours(0, 0, 0, 0);
  return copy;
}

Wenn du gezielt in einer bestimmten IANA-Zeitzone (z. B. Europe/Berlin, America/New_York) darstellen willst, nutze Intl.DateTimeFormat mit timeZone:

const d = new Date('2024-03-31T00:30:00Z');
new Intl.DateTimeFormat('de-DE', { timeZone: 'Europe/Berlin', timeStyle: 'short', dateStyle: 'medium' })
  .format(d); // Beachtet die Zeitumstellung Ende März

Für UTC-Werte aus Komponenten existiert Date.UTC(). Es gibt die Millisekunden seit Epoche zurück, nicht ein Date-Objekt.

const utcMs = Date.UTC(2024, 0, 31, 23, 59); // Jan ist 0
const d = new Date(utcMs); // identischer Zeitpunkt in UTC

javascript date

Zeitstempel, Unix-Zeit und Messungen

JavaScript nutzt Millisekunden seit Epoche. Unix-Timestamps sind meist in Sekunden. Die Konvertierung ist trivial:

// Date -> Unix Sekunden
const unix = Math.floor(Date.now() / 1000);

// Unix Sekunden -> Date
const fromUnix = (s) => new Date(s * 1000);

Für Zeitmessungen im Code gilt:

  • Date.now() ist gut für “wall-clock time”, kann sich aber ändern (Systemuhr, NTP).
  • performance.now() ist monoton und hochauflösend – ideal für Benchmarks und Dauerberechnungen.
const t0 = performance.now();
// ... zu messender Code ...
const dt = performance.now() - t0; // Millisekunden, monotone Uhr

Datumsarithmetik: addieren, subtrahieren, differenzieren

Dank Rollover sind viele Aufgaben einfach:

// 30 Tage addieren (lokal)
function addDays(date, days) {
  const d = new Date(date.getTime());
  d.setDate(d.getDate() + days);
  return d;
}

// N Stunden abziehen (UTC-sicher)
function addHoursUTC(date, hours) {
  const d = new Date(date.getTime());
  d.setUTCHours(d.getUTCHours() + hours);
  return d;
}

Differenzen berechnest du über die Millisekunden:

// Differenz in Tagen (metrisch), Achtung: DST kann "Kalendertage" verzerren
function diffDays(a, b) {
  const ms = a.getTime() - b.getTime();
  return ms / 86400000; // 24*60*60*1000
}

// Kalender-tagesgenau (UTC-Normalisierung beugt DST-Fallen vor)
function diffCalendarDays(a, b) {
  const uA = Date.UTC(a.getUTCFullYear(), a.getUTCMonth(), a.getUTCDate());
  const uB = Date.UTC(b.getUTCFullYear(), b.getUTCMonth(), b.getUTCDate());
  return Math.round((uA - uB) / 86400000);
}

Wichtig: Willst du “Anzahl Kalendertage” zwischen zwei Daten, normalisiere auf UTC-Mitternacht. Sonst verschieben Sommerzeitübergänge dein Ergebnis.

Spezialfälle: Schaltjahre, Invalid Date, Grenzen

Schaltjahrregeln: Teilbar durch 4 ist Schaltjahr, außer zugleich durch 100; wiederum doch Schaltjahr, wenn durch 400 teilbar. Javascript macht’s dir leicht:

function isLeapYear(year) {
  const d = new Date(Date.UTC(year, 1, 29)); // 29. Februar in UTC
  return d.getUTCMonth() === 1;              // bleibt Februar?
}

Ungültige Eingaben führen zu Invalid Date. Prüfen kannst du über isNaN(d.getTime()):

const d = new Date('not-a-date');
if (isNaN(d.getTime())) {
  console.error('Ungültiges Datum');
}

Zum Bereich: Die Spezifikation verlangt etwa ±8.64e15 ms um die Epoche, was sehr weite Bereiche abdeckt. In der Praxis sind extrem große Werte selten sinnvoll.

Best Practices kompakt

  • Speichern/Transport: ISO 8601 (toISOString()) oder Millisekunden/Unix-Sekunden.
  • UI/Anzeige: Intl.DateTimeFormat mit expliziter timeZone.
  • Parsing: Nur ISO 8601 verwenden. Keine sprach- oder regionenspezifischen Formate parsen.
  • Arithmetik: Für kalendarische Berechnungen UTC-normalisieren; für “Dauern” Millisekunden verwenden.
  • Monate: Zero-based im Konstruktor und bei getMonth()/setMonth().
  • Wochentag: getDay() gibt 0–6 mit Sonntag=0; nicht mit getDate() verwechseln.
  • Messungen: performance.now() für Benchmarks nutzen.
  • Zeitzone bewusst setzen: UI-Ausgabe immer mit expliziter IANA-Zeitzone, wenn erwartbar.

Kochrezepte für den Alltag

Start/Ende des Tages

function startOfDayLocal(d) {
  const c = new Date(d.getTime());
  c.setHours(0, 0, 0, 0);
  return c;
}
function endOfDayLocal(d) {
  const c = new Date(d.getTime());
  c.setHours(23, 59, 59, 999);
  return c;
}

Nächster Montag

function nextMonday(d) {
  const c = new Date(d.getTime());
  const day = c.getDay();           // So=0, Mo=1, ...
  const delta = (8 - day) % 7 || 7; // Wenn heute Mo, dann +7 Tage
  c.setDate(c.getDate() + delta);
  return c;
}

Runden auf 5-Minuten

function roundTo5Min(d) {
  const ms = 5 * 60 * 1000;
  return new Date(Math.round(d.getTime() / ms) * ms);
}

Kalenderwoche (ISO-8601)

// ISO-Woche: Montag als Wochenbeginn, KW 1 enthält den 4. Januar
function getISOWeek(date) {
  const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
  const dayNum = d.getUTCDay() || 7; // So=7
  d.setUTCDate(d.getUTCDate() + 4 - dayNum);
  const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
  const weekNo = Math.ceil((((d - yearStart) / 86400000) + 1) / 7);
  return { year: d.getUTCFullYear(), week: weekNo };
}

Stabil in bestimmter Zeitzone formatieren

function formatInTZ(d, timeZone, locale = 'de-DE') {
  return new Intl.DateTimeFormat(locale, {
    timeZone,
    dateStyle: 'medium',
    timeStyle: 'short'
  }).format(d);
}

Alternativen und Erweiterungen: Intl, Temporal, Libraries

Intl.DateTimeFormat ist die native, performante Lösung für Formatierung und Lokalisierung, inklusive IANA-Zeitzonen. Wenn du komplexere Logik brauchst, helfen Libraries:

  • date-fns: Moderne, treeshakable Funktionen für Parsing, Formatierung, Arithmetik. Gute Wahl für modulare Nutzung.
  • Luxon: Auf Intl basierend, mit DateTime-Objekt und robuster Zeitzonen-Unterstützung.
  • Moment.js (Legacy): Stabil, aber “maintenance mode”. Für neue Projekte nicht mehr empfohlen.

Die Temporal-API ist eine in Entwicklung befindliche Spezifikation, die Datums-/Zeitlogik sicherer und expliziter machen soll (z. B. Temporal.ZonedDateTime, Temporal.PlainDate). In einigen Umgebungen ist sie bereits als Polyfill nutzbar. Für produktive Browser-/Node-Umgebungen prüfe den aktuellen Support-Status und verwende bei Bedarf das Polyfill.

Fehlerquellen und Debugging

  • “YYYY-MM-DD” als UTC: Wenn du lokale Mitternacht brauchst, setze Zeit und Zeitzone explizit oder konstruiere numerisch mit lokalen Komponenten.
  • Sommerzeit-Sprünge: Zeitspannen immer über Millisekunden und ggf. in UTC rechnen; Für “Kalendertage” normalisieren.
  • Monatsindex 0–11: Häufigster Bug bei new Date(year, monthIndex, ...).
  • Parsing inhomogener Strings: Nur ISO akzeptieren, alles andere vorher selbst validieren/konvertieren.
  • Invalid Date: Immer über isNaN(d.getTime()) prüfen.

Leistungsaspekte

  • Formatierung: Erzeuge ein Intl.DateTimeFormat-Objekt und wiederverwende es, wenn viele Datumswerte formatiert werden.
  • Aktuellen Zeitwert mit Date.now() statt new Date().getTime() ermitteln – minimal schneller und ohne Objekt-Allokation.
  • Benchmarks/Timer: performance.now() nutzen, da eine monotone Uhr benötigt wird – bedenke, dass der Event Loop dafür sorgt, dass alle zeitkritischen Aufgaben reibungslos abgearbeitet werden.

Praxisnahe Beispiele integriert

1) Fälligkeitsdatum in 30 Kalendertagen (lokal) mit Anzeige in Berlin-Zeit

function dueIn30Days() {
  const now = new Date();
  const due = new Date(now.getTime());
  due.setDate(due.getDate() + 30);
  const fmt = new Intl.DateTimeFormat('de-DE', {
    dateStyle: 'full',
    timeStyle: 'short',
    timeZone: 'Europe/Berlin'
  });
  return fmt.format(due);
}

2) API-Eingang als ISO speichern, UI lokal anzeigen

// Server sendet ISO (UTC):
const iso = '2024-01-31T23:59:00.000Z';
const d = new Date(iso);

// UI (lokal):
const ui = new Intl.DateTimeFormat('de-DE', { dateStyle: 'medium', timeStyle: 'short' }).format(d);

// Persistenz:
const persist = d.toISOString();

3) Dauer in Stunden/Minuten robust zeigen

function formatDuration(ms) {
  const totalMin = Math.floor(ms / 60000);
  const h = Math.floor(totalMin / 60);
  const m = totalMin % 60;
  return `${h}h ${String(m).padStart(2, '0')}m`;
}

const started = Date.now();
// ... Arbeit ...
const elapsed = Date.now() - started;
console.log(formatDuration(elapsed));

Fazit

JavaScript Date ist ein leistungsfähiges Fundament für Datums- und Zeitlogik – wenn du seine Eigenheiten bewusst einsetzt. Arbeite für Transport und Speicherung mit ISO-Strings oder numerischen Timestamps, formatiere für die UI mit Intl.DateTimeFormat und setze Zeitzonen explizit, wenn du eine bestimmte Region erwartest. Nutze das Rollover-Verhalten für Arithmetik, normalisiere für kalendarische Differenzen auf UTC-Mitternacht und meide uneinheitliche String-Formate. Für komplexere Anforderungen stehen dir moderne Libraries und die aufkommende Temporal-API zur Verfügung. Mit diesen Prinzipien baust du robuste und vorhersagbare Datumsfunktionen – von der API-Schicht bis zur sauberen Anzeige.

FAQ

Wie konvertiere ich zwischen Date und Unix-Timestamp?

Date liefert Millisekunden. Unix-Timestamps sind Sekunden.

  • Date → Unix: Math.floor(Date.now() / 1000)
  • Unix → Date: new Date(unixSeconds * 1000)

Warum ist “2024-01-01” nicht lokale Mitternacht?

Das ISO-Datum ohne Zeit/Offset wird in modernen Engines als UTC interpretiert. Wenn du lokale Mitternacht willst, verwende numerische Konstruktion new Date(year, monthIndex, day) oder setze explizit Stunde/Zeitzone in der Formatierung.

Wieso beginnt getMonth() bei 0?

Das ist Designhistorie der Spezifikation. Januar=0, Dezember=11. Achte beim numerischen Konstruktor und bei getMonth()/setMonth() stets auf Zero-based Monate.

Worin liegt der Unterschied zwischen getDate() und getDay()?

getDate() liefert den Tag im Monat (1–31). getDay() liefert den Wochentag (0–6, Sonntag=0). Diese Verwechslung ist ein häufiger Bug.

Wie formatiere ich zuverlässig in einer bestimmten Zeitzone?

Mit Intl.DateTimeFormat und timeZone:

new Intl.DateTimeFormat('de-DE', {
  dateStyle: 'medium',
  timeStyle: 'short',
  timeZone: 'Europe/Berlin'
}).format(date);

Wie prüfe ich auf Invalid Date?

Über die Zeitwert-Prüfung:

const d = new Date(input);
if (isNaN(d.getTime())) {
  // ungültig
}

Wie berechne ich kalendarische Tagesdifferenzen ohne DST-Fehler?

Normalisiere beide Daten auf UTC-Mitternacht und teile die Differenz durch 86400000. Beispiel siehe diffCalendarDays oben.

Ist Date.now() oder new Date() besser?

Date.now() ist minimal schneller und erzeugt kein Objekt. Wenn du nur den Zeitstempel brauchst, nimm Date.now().

Wann sollte ich Libraries nutzen?

Wenn du viele Operationen auf Kalenderbasis, wiederkehrende Formatierungen in vielen Locales, komplexe Zeitzonenlogik oder saubere, deklarative APIs brauchst. date-fns und Luxon sind gute moderne Optionen.

Filed Under: Javascript

Primary Sidebar

Neue Beiträge

  • Die besten ChatGPT-Alternativen 2025: Welche Lösung passt wirklich zu deinem Workflow?
  • OK Google, mein Gerät einrichten Android TV: Dein kompletter Praxis‑Leitfaden
  • KI programmieren für Anfänger: Dein pragmatischer Start in Python, ML und Deep Learning
  • Node.js in der Praxis: Architektur, Tools, Best Practices und Fallstricke
  • javascript settimeout richtig einsetzen: Praxis, Fallstricke, Event Loop und Best Practices

Copyright © 2025 · romejs.dev