Auch Konsoleros müssen nicht auf Terminkalender und Erinnerungen verzichten. Zudem bietet die Shell viele Werkzeuge zum benutzerfreundlichen Umgang mit Datumsangaben in Skripten.
Das Arbeiten mit Datumsangaben in der Shell verursacht oftmals Probleme. Neben den üblichen Tippfehlern liegt das meist an nicht übereinstimmenden Sprach- und Ländereinstellungen. In der Praxis werden Sie vor allem bei Arbeiten an Datenbanken damit konfrontiert.
Eine manuelle Eingabe lässt sich relativ unaufwendig auf ihre formelle Richtigkeit hin überprüfen. Der dabei wohl einfachste Aspekt besteht darin, die Trennzeichen beziehungsweise die Reihenfolge von Tag, Monat und Jahr zu verändern. Ein Beispiel dafür zeigt Listing 1, die entsprechende Ausgabe sehen Sie in Abbildung 1. Das kurze Skript ermöglicht sowohl die korrekte Eingabe mit dem Punkt als Trennzeichen als auch jene mit dem Komma am Ziffernblock zur schnellen Datenerfassung.
Listing 1
Datum formatieren
#!/bin/bash
# Komma dient als Feldtrenner
# Ausgabe in der Form JJJJ-MM-TT
# Eingabe
read -p "Datum eingeben: " eingabe
# Komma durch Punkt ersetzen zwecks Einheitlichkeit
eingabe=$(echo $eingabe | tr \, \. )
# Ausgabe in Variable mit Awk, Minuszeichen als Trenner
ausgabe=$(echo $eingabe | awk -F \. '{ print $3 "-" $2 "-" $1 } ')
echo "Umgestelltes Datum: $ausgabe"
TIPP
Wie Datumsangaben zu gestalten sind, geben die beiden Normen DIN 5008 (Deutschland [5]) und ISO 8601 (international [6]) vor.
Dialog und Yad
Legen Sie mehr Wert auf Benutzerfreundlichkeit, aber auch auf korrekte Datumswerte, nutzen Sie die ansprechenden (semi-)grafischen Eingabemöglichkeiten von Dialog oder Yad.
Bei Dialog [1] funktioniert eine einfache Datumseingabe in der Grundform mit dialog --calendar 0 0. Die beiden Nullen stehen für das automatische Einstellen der Größe in Abhängigkeit vom Terminal. Im aufrufenden Shell-Skript lassen sich die verschiedenen Exit-Codes von Dialog zur Steuerung nutzen, wie in Listing 2. In der resultierenden Maske (Abbildung 2) navigieren Sie mit dem Tabulator und den Pfeiltasten. Mit der Eingabetaste schließen Sie die Eingabe ab.
Listing 2
Abfrage per Dialog
#!/bin/bash datum=$(dialog --stdout \ --title "Kalender" \ --calendar "Datum wählen" 0 0) if [ $? -eq 0 ]; then datum=$(echo $datum | tr \/ \.) echo "Eingabedatum: $datum" elif [ $? -eq 1 ]; then echo "Eingabeabbruch" fi
Mit Yad [2] zaubern Sie den Benutzerdialog eines Shell-Skripts auf die GUI. Wegen der sehr umfangreichen Optionen sollten Sie die Dokumentation des Tools zumindest einmal auszugsweise gelesen haben. Die Eingabe erfolgt bequem per Maus. Im Beispiel aus Listing 3 haben wir die Standardschaltflächen durch eigene ersetzt, woraus auch andere Exit-Codes resultieren (hier: 2 für die Eingabe). Die Ausgabe des Skripts sehen Sie in Abbildung 3.
Listing 3
Abfrage per Yad
#!/bin/bash datum=$(yad --title=Kalender \ --text="Datum auswählen" \ --calendar --show-weeks \ --button="Abbruch":1 \ --button="Eingabe":2) if [ $? -eq 2 ]; then datum=$(echo $datum | tr \/ \.) echo "Eingabedatum: $datum" elif [ $? -eq 1 ]; then echo "Eingabeabbruch" fi

Abbildung 3: Die Datumseingabe mit Yad in der GUI.
Smenu
Nicht überall funktioniert eine Display-Umleitung per SSH. Zudem kann die Darstellung der Dialog-Masken bei manchen Terminaleinstellungen Probleme bereiten. Es gibt jedoch noch eine weitere Methode, die Sie nutzen können, wenn es darauf ankommt, fehlerhafte Eingaben (etwa den 31. April) zu vermeiden: Sie geben mit Smenu [3] die möglichen Werte vor.
Für das Kalenderjahr darf der Benutzer in Listing 4 das aktuelle, das vorige und das nachfolgende Jahr wählen (Zeile 7). Beim Tag funktioniert die Auswahl analog (Zeile 17). Um bei der Darstellung im Terminal Platz zu sparen, kommt die Option -n1 von Smenu zum Einsatz, die die Auswahl auf eine Zeile beschränkt. Mit den Pfeiltasten wählen Sie den Tag. Welche Angaben dafür zulässig sind, ermittelt zuvor ein cal-Befehl (Zeile 16), aus dessen Ausgabe das Skript Zusatzangaben wie Monat, Jahr und Wochentag herausschneidet. Damit das Datum für die weitere Verarbeitung passt, erhalten einstellige Tagesangaben noch eine führende Null (Zeilen 19 bis 21).
Listing 4
Abfrage per Smenu
#!/bin/bash # Jahre: aktuell, davor, danach ajahr=$(date +%Y) vjahr=$(echo $ajahr -1 | bc) fjahr=$(echo $ajahr + 1 | bc) # Monate via Smenu auswählen jahr=$(echo $vjahr $ajahr $fjahr | smenu -m "Kalenderjahr auswählen") echo "" echo "------------------------" echo "" monat=$(echo 01 02 03 04 05 06 07 08 09 10 11 12 | smenu -m "Monat auswählen" ) echo "------------------------" # Kopf für Auswahl erstellen menukopf=$(cal $monat $jahr | head -1) # Kalenderfeld kalender=$(cal $monat $jahr | tail -6 | tr -d [:alpha:]) tag=$(echo $kalender | smenu -m "Tag mit den Pfeiltasten auswählen" -t1 -n1 ) # einstellige Tagesangabe mit führender Null versehen if [ $(echo $tag | wc -L) -eq 1 ]; then tag=$(echo "0$tag") fi datum=$(echo $tag.$monat.$jahr) echo $datum

Abbildung 4: Der Ablauf des Skripts aus Listing 4.
Die Shell-Kalender
Für das Anzeigen eines Kalenders verwenden Sie Cal oder dessen etwas aufgehübschte neuere Variante Ncal, die gängige Distributionen bereits vorinstallieren. Die Optionen beider Programme finden Sie in der Tabelle “Cal und Ncal: Optionen”. Mit dem Parameter -C aufgerufen, verhält sich Ncal exakt wie Cal. Abbildung 5 zeigt die beiden resultierenden Kalender, die drei Monate mitsamt den Wochennummern darstellen.
|
Option |
Ncal |
Cal |
|---|---|---|
|
aktuellen Tag nicht hervorheben |
|
– |
|
Monat (aktuelles Jahr) |
|
– |
|
Monat (beliebiges Jahr) |
|
|
|
Jahreskalender für Jahr |
|
|
|
Kalender aktuelles Jahr |
|
|
|
Dreimonatskalender |
|
|
|
Monate vor aktuellem |
|
– |
|
Monate nach aktuellem |
|
– |
|
Wochen nummerieren |
|
|
|
Wochen horizontal darstellen |
|
– |
|
Wochen vertikal darstellen |
– |
|
|
(1) M = numerische Monatsangabe, (2) JJJJ = vierstellige Jahresangabe |
||
Calendar
Mit Calendar, das die meisten Distributionen mit dem Paket bsdmainutils bereits vorinstallieren, zaubern Sie Ereignisse zum Tagesdatum auf das Terminal. Setzen Sie den Befehl ohne weitere Optionen ab, bekommen Sie eine lange Liste von hierzulande größtenteils irrelevanten Informationen. Sie können deshalb die Abfrage zum Beispiel auf Deutschland eingrenzen, indem Sie wie in Abbildung 6 Calendar über den Parameter -f mit einer entsprechenden Ereignisdatei aufrufen. Solche Dateien finden Sie bei den meisten Distributionen unter /usr/share/calendar/de_DE/.

Abbildung 6: Abfrage der für Deutschland relevanten Ereignisse für die drei Wochen nach Erscheinen dieser Ausgabe.
Eigene, zusätzliche Kalenderdaten tragen Sie in Ihre eigene .calendar-Datei ein. Dazu kopieren Sie beispielsweise unter Debian und Ubuntu die Datei /usr/share/calendar/de_DE/calender.all nach $HOME/.calendar. Unterhalb der #include-Anweisungen tragen Sie Ihre eigenen Jubiläen und Ereignisse ein (Listing 5, Einträge für den 6. und 7. Januar). Jeder Datensatz beginnt mit der Monatsnummer, den folgenden Tag trennen Sie mit einem Schrägstrich ab. Als Feldtrenner zwischen dem Datum und dem Eintragstext kommt der Tabulator zum Einsatz.
Listing 5
Eigene Kalendereinträge
/* * deutscher Kalender */ #ifndef _de_DE_all_ #define _de_DE_all_ #include <de_DE/calendar.feiertag> #include <de_DE/calendar.geschichte> #include <de_DE/calendar.kirche> #include <de_DE/calendar.literatur> #include <de_DE/calendar.musik> #include <de_DE/calendar.wissenschaft> 01/06 Jahrestag Erstbesteigung Blåbjerg-Nordwand 01/07 Geburtstag Schwiegermutter #endif /* !_de_DE_all_ */
Ein Seitenblick auf die Datei calendar.kirche lohnt sich: Hier sehen Sie, wie Calendar vom Ostersonntag ausgehend die davon abhängigen Feiertage berechnet. Diese Funktion lässt sich für die Erstellung eigener Kalender nutzen.
In der Tabelle “Calendar-Optionen” finden Sie einige wichtige Optionen für den Gebrauch des Programms. Sie können den Aufruf samt für Sie passender Optionen als Alias in der persönlichen oder systemweiten Konfigurationsdatei der Shell ablegen.
|
Aktion |
Option |
|---|---|
|
Angabe der Konfigurationsdatei |
|
|
Ausgabe des Wochentags |
|
|
Anzahl der anzuzeigenden Tage (Zukunft) |
|
|
Zurückliegende Tage anzeigen |
|
|
Bestimmten Tag anzeigen |
|
|
(1) |
|
Einige Beispiele zeigt die Abbildung 7, in der alle Befehle auf die eigene Kalenderdatei Bezug nehmen. Geben Sie keine eigene Datei an, greift Calender auf die systemweite Variante zurück.
Kalender mit Pcal
Das Programm Pcal, das sich in den Repositories aller gängigen Distributionen findet, erstellt einen Kalender im Postscript- oder HTML-Format. Durch die umfangreichen Optionen und die feine Steuerbarkeit bezüglich der Kalenderdaten erscheint die Arbeit damit anfangs kompliziert. Die wichtigsten Optionen des Tools fasst die Tabelle “Pcal-Optionen” zusammen. Die Manpage des Programms könnte durchaus benutzerfreundlicher ausfallen.
|
Aktion |
Option |
im Beispiel |
|---|---|---|
|
Angabe Kalenderkonfigurationsdatei |
|
|
|
Auswahl Sprache |
|
|
|
Europäisches Datumsformat |
|
– |
|
Papierformat |
|
|
|
Leere Felder für Tage außerhalb des Monats |
|
– |
|
Erster Wochentag |
|
1 für Montag |
|
Mondzustand täglich anzeigen |
|
– |
|
Mondphasen anzeigen |
|
Vollmond, Halbmond, Neumond |
|
Schriftart |
|
Helvetica, 12 Punkt |
|
Ausgabedatei |
|
– |
|
Kalendermonat |
|
– |
|
Kalenderjahr |
|
– |
|
Jahreskalender auf einer Seite |
|
– |
|
Farbe Schwarz für angegebenen Tag |
|
Samstag ( |
|
Abweichende Farbe |
|
Rot auf Hellbeige für Sonn- und Feiertage: |
TIPP
In der Voreinstellung gibt Pcal Sonn- und Feiertage in grauer Farbe aus, was bei Schwarzweißdrucken diese Tage in der Regel deutlicher hervorhebt.
Die Konfiguration des gewünschten Kalenders legen Sie in einer eigenen Datei ab, die in unserem Beispiel .pcal heißt. Darin legen Sie ein Kalenderjahr mit seinen Feiertagen fest. Im Listing 6 finden Sie das Muster für Deutschland mit regionalen Eigenheiten für Bayern.
Listing 6
Eigene .pcal
# Wochennummer beim Montag all Monday in all Woche %w Easter Ostern # Um Ostern wird +/- gerechnet # * nach Datum = Feiertag Monday after Easter* Ostermontag Good_Friday* Karfreitag 49th day after Easter* Pfingstsonntag 50th day after Easter* Pfingstmontag 39th day after Easter* Christi Himmelfahrt 60th day after Easter* Fronleichnam # kein * = kein Feiertag 48th day before Easter Rosenmontag 46th day before Easter Aschermittwoch 7th day before Easter Palmsonntag 01. 01.* Neujahr 06. 01.* Dreikönigsfest 01. 05.* Tag der Arbeit 08. 08.* Friedensfest (Augsburg) 15. 08.* Maria Himmelfahrt 03. 10.* Tag der deutschen Einheit 01. 11.* Allerheiligen 24. 12. Heiliger Abend 25. 12.* 1. Weihnachtsfeiertag 26. 12.* 2. Weihnachtsfeiertag 31. 12. Silvester sun on_or_before 24. 12. 4. Advent sun on_or_before 17.12. 3. Advent sun on_or_before 10.12. 2. Advent sun on_or_before 3.12. 1. Advent
Dabei gelten einige besondere Regeln. Für den jeweiligen Tag gibt es verschiedene Angaben. Mit all Tag bezeichnen Sie einen Tag, für den eine besondere Kennzeichnung erfolgen soll. Im Beispiel blenden wir jeden Montag das Wort “Woche” und die laufende Wochennummer ein. Die zweite Zeile zeigt Neujahr als Feiertag an. Zwischen den Angaben für Tag und Monat muss ein Leerzeichen stehen.
Damit ein Tag als Feiertag erscheint, setzen Sie ein Sternchen (*), gefolgt vom gewünschten Text. Viele Feiertage haben einen festen Abstand zu Ostern. Das finden Sie im Block unterhalb von Easter. Andere Feiertage funktionieren wie der Neujahrstag: Sie geben sie mit festem Datum an, gegebenenfalls mit Sternchen oder ohne Feiertagskennzeichnung.
An Weihnachten wird es kompliziert, denn der 24. Dezember kann auch der vierte Advent sein (zum Beispiel 2023). Hier arbeiten Sie mit on_or_before. Das ermöglicht, dass der 24. Dezember der vierte Advent sein kann, wenn er auf einen Sonntag fällt. Die Daten der restlichen Adventssonntage definieren Sie dann wie am Ende des Listings gezeigt.
Die deutschen Umlaute machen hier Probleme. Moderne Distributionen verwenden eine UTF-8-Kodierung, Pcal besteht aber auf ISO-8859-15. Mittels recode UTF-8..ISO-8859-15 .pcal erledigen Sie die Umstellung der Datei, sodass dann auch die Heiligen Drei Könige richtig erscheinen.
Einen Übersichtskalender mit roten Sonn- und Feiertagen mit dem Mondverlauf erzeugen Sie mit dem Aufruf aus Listing 7; Abbildung 8 zeigt das Ergebnis.
Listing 7
Jahreskalender
$ pcal -f .pcal -a de -E -P a4 \ -B -F 1 -M -g sun \ -s 1.0:0.0:0.0/1.0:1.0:0.8 \ -b sat -n Helvetica/10 -w \ -o Jahreskalender.ps 2021
Einen Monatskalender erstellen Sie ohne die Option -w, dafür mit Angabe des Monats vor dem Jahr (Listing 8). Das Ergebnis zeigt Abbildung 9. Die entstandene Postscript-Datei verarbeiten Sie durch Hinzufügen eines Fotos zum Beispiel mit Inkscape zu einem vollständigen Kalenderblatt weiter.
Listing 8
Monatskalender
$ pcal -f .pcal -a de -E -P a4 \ -B -F 1 -M -g sun \ -s 1.0:0.0:0.0/1.0:1.0:0.8 \ -b sat -n Helvetica/10 \ -o Januar-2021.ps 01 2021
Terminverwaltung
Mit dem kleinen, aber feinen Konsolenprogramm Calcurse, das sich in den Repositories aller gängigen Distributionen findet, verwalten Sie allgemeine und termingebundene Aufgaben. Die einfache Oberfläche fällt mehr oder weniger selbsterklärend aus. Haben Sie schon einmal mit Nano gearbeitet, kommen Sie mit der in Calcurse verwendeten Art der Menüsteuerung auf Anhieb zurecht. Zwischen den Feldern Termine, Kalender und Zu erledigen springen Sie mit dem Tabulator, innerhalb der Termine und des Kalenders gelangen Sie mit den Pfeiltasten zum Ziel. Abbildung 10 zeigt den vollständigen Bildschirm.
Um einen neuen Termin einzugeben, drücken Sie [A] und geben die Anfangs-, die Endzeit und den Beschreibungstext ein (Abbildung 11). Ein Druck auf die Eingabetaste speichert den neuen Termin (Abbildung 12). Mit [Strg]+[T] legen Sie eine neue Aufgabe an (Abbildung 13). Zuerst tragen Sie den Aufgabentext ein und drücken dann die Eingabetaste. Anschließend setzen Sie eine Priorität, die sich auf die Reihenfolge der Darstellung auswirkt. Abbildung 14 zeigt die Termin- und Aufgabeneinträge.

Abbildung 11: Für einen Termin geben Sie in Calcurse dessen Startzeit (oben), Endzeit (Mitte) und einen Beschreibungstext (unten) an.

Abbildung 13: In Calcurse tragen Sie Aufgaben ein (oben) und legen eine Priorität dafür fest (unten).
Mit [O] gelangen Sie zu den weiteren Befehlen und den Einstellungen. So können Sie die Kalendereinträge im ICAL- oder PCAL-Format exportieren beziehungsweise Daten aus diesen Formaten importieren. Rufen Sie Pcal mit der Option -a auf, zeigt es alle Termine für das aktuelle Datum auf der Konsole an (Abbildung 15).
TIPP
Aus Platzgründen nicht erwähnt haben wir das Konsolenprogramm Remind [7]: Dessen Möglichkeiten füllen ohne Weiteres einen eigenen Artikel.
Fazit
Das Erzeugen von Kalendern per Shell funktioniert zuverlässig, für die Gestaltung des Endprodukts stehen zahlreiche Einstellungen zur Auswahl. Einfache Datumseingaben in der Shell lassen sich mithilfe entsprechender Werkzeuge problemlos innerhalb eigener Skripte lösen. Eine Alternative bieten Auswahlkalender für die Datumseingabe mithilfe von Dialog, Yad oder auch Zenity [4]. (jlu)
Der Autor
Harald Zisler beschäftigt sich seit den frühen 1990er-Jahren mit FreeBSD und Linux. Zu Technik- und EDV-Themen verfasst er Zeitschriftenbeiträge und Bücher.
Infos
-
Textbasierte Oberflächen: Frank Hofmann, “Bunte Shell”, LU 09/2010, S. 76, https://www.linux-community.de/21116
-
Yad: Karsten Günther, “Neue Oberfläche”, LU 06/2014, S. 58, https://www.linux-community.de/30568
-
Smenu: Harald Zisler, “Keine Qual der Wahl”, LU 06/2017, S. 84, https://www.linux-community.de/38772
-
Dialoge in Shell-Skripts: Harald Zisler, “Mehr Komfort”, LU 03/2014, S. 30, https://www.linux-community.de/29273
-
Datum nach DIN 5008: https://de.wikipedia.org/wiki/Datumsformat#DIN_5008
-
Datum nach ISO 8601: https://de.wikipedia.org/wiki/Datumsformat#ISO_8601_und_EN_28601















