Monatskalender

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche

In diesem Tutorial lernst du, wie du einen (oder mehrere) Monatskalender erzeugst. Ein Script ermittelt das aktuelle Datum und den Wochentag oder reagiert auf eine Nutzereingabe. Anhand des Beispiels kannst du lernen, wie man dynamisch Tabellen erzeugt, aber ebenso den praktischen Umgang mit dem Date-Objekt von JavaScript.

Dieses Tutorial ist die umfassende Neubearbeitung eines Anwendungsbeispiels von Stefan Münz aus dem Jahre 2001.[1] 2015 wurde das Beispiel aktualisiert, indem die Tabelle mit JavaScript im DOM erzeugt und die Formatierung durch CSS festgelegt wird.

Vorüberlegungen

Mit input type="date" gibt es bereits eine Möglichkeit einzelne Daten einzugeben. Häufig möchte man dem Nutzer jedoch eine Monatsansicht bieten, in der er einen oder mehrere Tage auswählen kann. Dabei soll flexibel zwischen aktuellem und den jeweiligen vorherigen und folgenden Monaten gewechselt werden.

Es gibt dafür Widgets im Netz – hier zeigen wir, wie man so etwas von Hand programmiert.

Kalender mit Tabelle

Tabellen dynamisch erzeugen

Auch wenn es üblicher ist Elemente mit der createElement()-Methode zu erzeugen, kannst du bei Tabellen die Eigenschaften und Methoden des tableObject nutzen.[2]


Tabellenüberschrift dynamisch einfügen ansehen …
  function ueberschriftEinfuegen () {
      var tabelle = document.getElementById('tabelle');
	  // schreibe Tabellenüberschrift
	  var caption = tabelle.createCaption();
	  caption.innerHTML = 'Überschrift';
  }
  
  function zeileEinfuegen () {
      var tabelle = document.getElementById('tabelle');	  
      // schreibe Tabellenzeile
	   var Reihe = tabelle.insertRow(0);
       for (var i = 0; i <= 6; i++) {
		    var Inhalt = 'Zelle ' + (i+1);
            var Zelle = Reihe.insertCell();
            Zelle.innerHTML = Inhalt;	
	   }
  }

In diesem Beispiel erhält die schon vorhandene, aber leere Tabelle bei Klick auf den ersten Button durch createCaption eine Überschrift.

An den zweiten Button wird mit addEventListener eine Funktion zeileEinfuegen() angehängt, die bei einem Click-Event die Tabelle mit document.getElementById aufruft und mit insertRow() eine neue Zeile einfügt. [3] An diese werden in einer Zählschleife 7 Tabellenzellen dynamisch eingefügt. Sie erhalten mit innerHTML einen Text als Inhalt.

Das Kalenderscript

Das Beispiel zeigt eine vollständige HTML-Datei, in der das JavaScript für den Monatskalender eingebunden ist.

Kalenderscript ansehen …
let currentDate = new Date();
let currentMonth = currentDate.getMonth();   // 0–11
let currentYear = currentDate.getFullYear(); // e.g. 2025

renderCalendar(currentMonth, currentYear);

 function renderCalendar(month, year) {
  const monthNames = [
    "Januar", "Februar", "März", "April", "Mai", "Juni",
    "Juli", "August", "September", "Oktober", "November", "Dezember"
  ];

  const weekdays = ["Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"];

  const today = new Date();
  const todayDay = today.getDate();
  const todayMonth = today.getMonth();
  const todayYear = today.getFullYear();

  const firstDay = new Date(year, month, 1);
  let start = firstDay.getDay();
  start = start === 0 ? 6 : start - 1;

  const daysInMonth = new Date(year, month + 1, 0).getDate();

  const table = document.getElementById("kalender");
  table.innerHTML = "";

  // Caption
  const caption = table.createCaption();
  caption.textContent = `${monthNames[month]} ${year}`;

  // Header
  const headerRow = table.insertRow();
  weekdays.forEach(day => {
    const cell = headerRow.insertCell();
    cell.textContent = day;
  });

  let dayNumber = 1;

const totalCells = start + daysInMonth;
const rowsNeeded = Math.ceil(totalCells / 7);

for (let rowIndex = 0; rowIndex < rowsNeeded; rowIndex++) {
 ...
}

Aktuelles Datum ermitteln:

Im Script-Bereich wird zunächst mit currentDay = new Date() ein neues Datumsobjekt mit dem aktuellen Zeitpunkt erzeugt. In den Variablen currentMonth und currentYear werden anschließend aus dem neuen Datumsobjekt d der Monat und das Jahr ermittelt. Mit diesen beiden Variablen wird die Funktion renderCalendar() aufgerufen.


Funktion "renderCalendar()":

Die Funktion renderCalendar(currentMonth, currentYear); ist als in sich abgeschlossenes Unterprogramm realisiert, das einen Monat und ein Jahr als Parameter erwartet, das als Monatskalender angezeigt werden soll. Auf diese Weise lässt sich die Funktion auch noch anderweitig als zur einmaligen Ausgabe des aktuellen Kalendermonats nutzen.

Zu Beginn der Funktion werden erst einmal verschiedene Variablen definiert. Dazu gehören die gewünschten Monatsnamen und die Wochentage, die jeweils als Array-Objekte angelegt werden. Wenn Sie andere, zum Beispiel landesspezifische Namen wie "Jänner" wünschen, ändern Sie den entsprechenden Namen einfach.


Ermitteln, ob aktiver Tag im anzuzeigenden Monat liegt:

Da die Funktion ja als Parameter übergeben bekommt, welchen Monat in welchem Jahr sie ausgeben soll, kann es sich durchaus um einen anderen als den aktuellen Monat handeln (nur im obigen Beispiel wird die Funktion mit dem aktuellen Monat/Jahr aufgerufen). Die Funktion ermittelt deshalb noch einmal separat die Daten des aktuellen Tages (DieserTag), des aktuellen Monats (DieserMonat) und des aktuellen Jahres (DiesesJahr). Die entsprechenden Daten werden später benötigt, um den aktuellen Tag farblich hervorzuheben, sofern er in dem auszugebenden Monat vorkommt.


Anzeige in Tabelle vorbereiten:

Der Monatskalender soll mit Hilfe der oben besprochenen Methoden in eine HTML-Tabelle geschrieben werden. Zunächst muss jedoch ermittelt werden, wie viele Tage der auszugebende Monat hat, und an welchem Wochentag er beginnt. Davon hängt ab, wie die Tage in die Tabelle geschrieben werden.

const firstDay = new Date(year, month, 1);

Damit erstellen wir ein Datum-Objekt für den ersten Tag des Monats.

year = aktuelles Jahr, month = aktueller Monat (0 = Januar), 1 = erster Tag.

Beispiel: new Date(2026, 0, 1) = 1. Januar 2026.

let start = firstDay.getDay();

.getDay() gibt den Wochentag zurück, 0 = Sonntag, 1 = Montag … 6 = Samstag.

Beispiel: 1. Januar 2026 ist ein Donnerstag → .getDay() = 4.

start = start === 0 ? 6 : start - 1;

Wir wollen, dass Montag = 0, Dienstag = 1 … Sonntag = 6 (für unsere Tabelle).

Wenn .getDay() 0 ist (Sonntag), setzen wir start = 6.

Sonst ziehen wir 1 ab, damit Montag = 0 passt.

Zusammenfassung: Diese Zeilen bestimmen, an welcher Spalte der erste Tag des Monats in der Kalender-Tabelle angezeigt wird. So weiß der Code, wie viele leere Zellen am Anfang der ersten Reihe eingefügt werden müssen.

Tabelle erzeugen:

Nachdem alle Vorbereitungen getroffen sind, kann die Tabelle mit dem Kalendermonat geschrieben werden. Dies geschieht mit Hilfe der insertRow()- und insertCell()-Methoden, die dynamisch die entsprechenden HTML-Konstrukte in die Datei schreiben. Um den Tabellenkopf mit Monats- und Jahresangabe zu schreiben, erzeugt sie mit createCaption() eine caption. Um die einzelnen Datenzellen mit den richtigen Daten zu versorgen, muss die Kalender()-Funktion die zuvor ermittelten Angaben zum Wochentag des ersten Tages im Monat sowie das aktuelle Tagesdatum berücksichtigen und die entsprechenden Parameter korrekt übergeben. Falls eine Zelle leer bleiben soll, wird ein Leerzeichen ' ' übergeben. Wenn die Zelle eine Tageszahl anzeigen soll, wird eine entsprechende Variable übergeben.

const totalCells = start + daysInMonth;

start = Anzahl der leeren Zellen am Anfang (damit der erste Tag an der richtigen Spalte steht).

daysInMonth = Anzahl der Tage im Monat (z. B. 30 oder 31).

totalCells = Gesamtanzahl der Zellen, die wir für den Monat brauchen (leere + echte Tage).

const rowsNeeded = Math.ceil(totalCells / 7);

Jede Reihe in der Tabelle hat 7 Zellen (Mo–So).

totalCells / 7 = wie viele Reihen wir theoretisch brauchen.

Math.ceil(...) rundet immer auf, damit auch unvollständige Reihen berücksichtigt werden.

Beispiel: 30 Tage + 2 leere Zellen am Anfang = 32 → 32 / 7 ≈ 4,57 → Math.ceil = 5 Reihen.

Dann kommt die Schleife, die die Tabellenzellen füllt:

Schleife zum Füllen der Tabellenzellen ansehen …
for (let rowIndex = 0; rowIndex < rowsNeeded; rowIndex++) {
  const row = table.insertRow();

  for (let colIndex = 0; colIndex < 7; colIndex++) {
    const cell = row.insertCell();

    const cellIndex = rowIndex * 7 + colIndex;
    const isBeforeStart = cellIndex < start;
    const isAfterEnd = dayNumber > daysInMonth;

    if (isBeforeStart || isAfterEnd) {
      cell.textContent = "";
      continue;
    }

    cell.textContent = dayNumber;
    cell.classList.add("kalendertag");

    if (
      dayNumber === todayDay &&
      month === todayMonth &&
      year === todayYear
    ) {
      cell.classList.add("heute");
      cell.setAttribute("aria-current", "date");
    }

    dayNumber++;
  }
}
  1. Äußere Schleife:
    • Geht jede Reihe (rowIndex) der Tabelle durch.
    • rowsNeeded = wie viele Reihen wir insgesamt brauchen.
    • table.insertRow() = neue Tabellenreihe erstellen.
  2. Innere Schleife:
    • Geht jede Spalte (colIndex) von 0 bis 6 (Mo–So) durch.
    • row.insertCell() = neue Tabellenzelle in dieser Reihe.
    • cellIndex = rowIndex * 7 + colIndex
      Berechnet die fortlaufende Zellen-Nummer im Monat.
      Damit können wir prüfen, ob wir die Zelle vor dem Monatsanfang oder nach Monatsende füllen müssen.
  3. Leere Zellen:
    • isBeforeStart = die Zellen vor dem 1. Tag.
    • isAfterEnd = die Zellen nach dem letzten Tag des Monats.
      Wenn eine der beiden Bedingungen zutrifft → Zelle leer lassen.
  4. Echte Tage:
    • cell.textContent = dayNumber → Tag in die Zelle schreiben.
    • cell.classList.add("kalendertag") → CSS-Klasse für Styling.
    • Prüfen, ob der Tag heute ist → Klasse heute + aria-current="date".
    • dayNumber++
      Nach jeder gefüllten Tageszelle wird die Nummer erhöht, damit der nächste Tag korrekt eingefügt wird.

Vor- und Folgemonate

Dieses Beispiel erweitert unser Script um die Möglichkeit je nach Wunsch des Nutzers die vorhergehenden oder folgenden Monate anzuzeigen.

Vor- und Folgemonate ansehen …
<nav>
    <button id="previous-month"><span class="visually-hidden">vorheriger Monat</span></button>
    <div id="calendar-title" aria-live="polite"></div>
    <button id="next-month"><span class="visually-hidden">nächster Monat</span></button>
</nav>
<table id="kalender">
</table>

Ein Kalender als Liste oder Grid?

Robinson Crusoe legte eine Strichliste an, um die Tage auf der Insel zu zählen. Das ist aber noch kein Kalender. Mit der festen Zuordnung von Wochen mit Daten und Wochentagen haben wir ein Raster, wofür heute ein CSS-Grid naheliegend scheint.

Allerdings gibt es bei CSS-Grid keine Zuodnung zu Spalten und Zeilen, sodass es zwar Versuche gibt, die aber eher als proof-of-concept gelten.[4]

Manchmal ist eine Tabelle eben doch eine Tabelle!

Welcher Wochentag? - Ein Quiz

Mit der oben schon erwähnten JavaScript-Methode Date.getDay() kann man den Wochentag ermitteln. Für eine solche Wochentagsberechnung – sowohl für den gregorianischen als auch für den julianischen Kalender – gibt es Formeln[5], auf die hier nicht näher eingegangen wird.

In diesem Quiz werden zufällig ausgewählte Daten angezeigt, für die der Wochentag im Kopf berechnet werden soll.

Welcher Wochentag-Quiz ansehen …
<div id="gameboard">
	<button>Start!</button>
	<p id="task">Der <time>01.01.1900</time> <span>war</span> ein  …</p>
	<p style="display:flex; gap: 0.5em;">
	<button id="1" accesskey="1">1 Montag</button>
	<button id="2" accesskey="2">2 Dienstag</button>
	<button id="3" accesskey="3">3 Mittwoch</button>
	<button id="4" accesskey="4">4 Donnerstag</button>
	<button id="5" accesskey="5">5 Freitag</button>
	<button id="6" accesskey="6">6 Samstag</button>
	<button id="7" accesskey="7">7 Sonntag</button>
	</p>
	<p id="result"></p>
</div>

Siehe auch

  • Tabellen in HTML
    • Aufbau
    • Gestaltung mit CSS
  • Einführung in Zeit & Datum
    Date-Icon.svg
  • Timer und Countdown

    Zeit hoch und runter zählen
    Ausführungszeiten messen

  • input type="date" und mehr
    HTML5 bietet eine Vielzahl von neuen Eingabe-Typen für Datums- und Zeitangaben.

Weblinks

  1. Monatskalender - Anwendungsbeispiel aus dem Jahre 2001 (SELFHTML-Doku auf web.archive.org)
  2. MSDN: Table Object
  3. MDN: insertRow
  4. How to build a calendar with CSS Grid (zellwk.com)
    Wochentage und Zahlen bestehen aus zwei verschiedenen Grid-Container - es besteht kein semantischer Zusammenhang, der mit aria-Attributen erst künstlich hergestellt werden müsste.
  5. Wochentagsberechnung (de.wikipedia.org)

Abgerufen am 31.12.2025
von "http://wiki.selfhtml.org/wiki/Monatskalender"