Zum Inhalt

Datum und Zeit

Pantarey speichert Daten als Text im ISO-Format und rechnet auf dem Server in UTC; der Browser zeigt sie in der Ortszeit der Person an. Wer diese zwei Regeln kennt, versteht fast alle Datumsfragen: warum ein Zeitpunkt in der Datenbank auf Z endet, warum sich ISO-Daten als Text vergleichen lassen und deutsche Daten nicht, und warum ein Timer-Start eine Zeitzone braucht. Diese Seite sammelt Speicherformate, Zeitzonen, alle Datumsfunktionen und das Zeitverhalten von Timern und Fristen an einem Ort.

Speicherformate

Im Daten Designer stehen in der Gruppe Datum & Zeit zwei Typen; einen eigenen Typ für eine Uhrzeit ohne Datum gibt es nicht.

Typ Beschreibung Gespeichert Beispiel Im Formular
Datum Tag, Monat, Jahr JJJJ-MM-TT (Format date) 2026-03-15 Kalenderfeld (dateInput); Vorbelegung today, today+7, today-1
Zeitpunkt Datum mit Uhrzeit ISO-Zeitstempel in UTC mit Z (Format date-time) 2026-03-15T09:30:00.000Z Datum und Uhrzeit in Ortszeit (dateTimeInput); Vorbelegung now

Eine Dauer ist eine Zahl mit dem Zahlenformat Dauer, gespeichert in Millisekunden. Systemfelder wie Erstell- und Änderungszeitpunkt eines Datensatzes sind Zeitpunkte im selben ISO-Format.

Beim Zeitpunkt gibt die Person Ortszeit ein; gespeichert wird die Umrechnung nach UTC. 10:30 in Augsburg im März wird zu 09:30:00.000Z, im Juli zu 08:30:00.000Z. Das Datum ohne Uhrzeit bleibt, wie eingegeben.

Anzeige

Eingabefelder zeigen Datum und Uhrzeit so, wie es der Browser für seine Sprache vorsieht; Pantarey legt kein Anzeigeformat fest. Die Datensatz-Ansicht zeigt Zeitpunkte als TT.MM.JJJJ HH:mm in der Zeitzone des Browsers; der Process Explorer zeigt Zeitpunkte als TT.MM.JJJJ, HH:mm:ss.

Datumsfeld-Grenzen

In eigenen Formularen (Formly-JSON) begrenzen dateInput und dateTimeInput den erlaubten Bereich; im Daten Designer werden diese Eigenschaften nicht eingestellt.

Eigenschaft (props) Wirkung
min, max feste Grenze: JJJJ-MM-TT, today, today+N, today-N; beim Zeitpunkt zusätzlich now oder eine Uhrzeit
minKey, maxKey Schlüssel eines anderen Datumsfelds derselben Ebene (in einer Wiederholung: derselben Zeile); dessen Wert ist die Grenze. Gilt zusätzlich eine feste Grenze, zählt die strengere.
followMin: true rückt das Feld aus minKey über den eigenen Wert hinaus, wird dieser übernommen; ein leeres Feld bleibt leer

Der Kalender graut Tage außerhalb der Grenzen aus; ein getippter Wert außerhalb meldet „Darf nicht vor ‚Von‘ liegen.“, „Darf nicht nach ‚Bis‘ liegen.“, „Frühestens am 05.11.2026.“ oder „Spätestens am 30.11.2026.“ (beim Zeitpunkt „Frühestens 05.11.2026, 09:00.“). Der Server prüft die Grenzen beim Absenden erneut.

[
  { "key": "von", "type": "dateInput", "props": { "label": "Von", "required": true }, "defaultValue": "today" },
  { "key": "bis", "type": "dateInput", "props": { "label": "Bis", "required": true, "minKey": "von", "followMin": true } }
]

Das Beispiel „Bis“ an „Von“ binden steht ausführlich im Arbeitskalender, die übrigen Feldtypen unter Formulare.

Zeitzonen

Ort Zeitzone
Server (Prozesse, Services, JSONata, $now()) UTC
$$context.executedAt (Start, Benutzeraufgabe) ISO-Zeitstempel in UTC; $$context.finishedAt dagegen in Millisekunden seit 1970
Browser (Formulare, Datensatz-Ansicht, Process Explorer) Ortszeit der Person
Timer-Start mit cron(…) Einstellung Zeitzone: Deutschland (Berlin), Österreich (Wien), Schweiz (Zürich) oder UTC (ohne Sommerzeit); andere IANA-Zonen werden akzeptiert. Prozesse ohne Zeitzone laufen in UTC.
Timer-Start mit rate(…) ohne Zeitzone, Abstand ab dem Deploy
Zeitlimit einer Aufgabe mit Datum aus Prozessdaten ein reines Datum gilt bis 23:59:59 UTC, also bis 00:59 bzw. 01:59 Uhr des Folgetags in Deutschland
Datenanalyse (Athena) Zeitpunkte als timestamp in UTC, Daten als date
Arbeitskalender nimmt ein Datum „wie geschrieben“: 2026-06-14T22:00:00Z zählt als 14.06., obwohl es in Berlin schon der 15.06. ist

Wer eine Uhrzeit für Menschen ausgeben will, rechnet beim Formatieren um: in Handlebars mit {{dateTimeFormat datum "de-DE" "Europe/Berlin"}}, im Service Datum kalkulieren mit locale und timezone.

Funktionen

$fn('date_…') in JSONata und Platzhaltern

Diese Funktionen gelten in Input- und Output-Ausdrücken (JSONata) ebenso wie in Textfeldern mit Platzhaltern, siehe Template-Funktionen.

Funktion Ergebnis Beispiel
date_toGermanDate(datum) TT.MM.JJJJ; erwartet JJJJ-MM-TT ohne Uhrzeit $fn('date_toGermanDate', antrag_db.von) → 15.03.2026
date_toPath(datum) JJJJ/MM/TT aus einem Datum oder ISO-Zeitstempel; anderes bleibt unverändert $fn('date_toPath', $now()) → 2026/11/11
date_workdays(von, bis, arbeitstage?, halbStart?, halbEnde?) Arbeitstage nach dem Arbeitskalender, höchstens 3 Jahre $fn('date_workdays', antrag.von, antrag.bis) → 4.5
date_workdaysByYear(…) Arbeitstage je Jahr { "2026": 4, "2027": 4 }
date_isWorkday(datum, arbeitstage?) true oder false $fn('date_isWorkday', $substring($now(), 0, 10))
date_freeDays(von, bis) freie Tage als Liste [{ date, name, fraction }] $fn('date_freeDays', antrag.von, antrag.bis)

date_toGermanDate zerlegt den Text an den Bindestrichen. Ein Zeitstempel wird deshalb zuerst auf das Datum gekürzt: $fn('date_toGermanDate', $substring(prio_created_at, 0, 10)). Die Kalenderfunktionen kürzen Zeitstempel selbst; sie melden ungültige Daten („Ungültiges Datum für „Von“: … (erwartet JJJJ-MM-TT)“) und einen Zeitraum über drei Jahre als Fehler, der Schritt scheitert dann.

JSONata-Standard

Funktion Ergebnis Beispiel
$now() aktueller Zeitpunkt als ISO-Zeitstempel in UTC 2026-11-11T09:30:00.000Z
$substring($now(), 0, 10) heutiges Datum als JJJJ-MM-TT 2026-11-11
$millis() aktueller Zeitpunkt in Millisekunden 1794475800000
$toMillis(text) ISO-Datum oder -Zeitstempel in Millisekunden $toMillis(rechnung.datum)
$fromMillis(ms, bild?) Millisekunden als ISO-Zeitstempel oder nach einem Bild formatiert $fromMillis($toMillis(datum) + 14 * 86400000, '[Y0001]-[M01]-[D01]') → 2026-03-29
Vergleich ISO-Texte lassen sich direkt vergleichen rechnungsdatum <= $substring($now(), 0, 10)

Die Bilder von $fromMillis folgen der JSONata-Dokumentation, zum Beispiel [D01].[M01].[Y0001] für 15.03.2026; Zeitzonen kennen sie nicht, das Ergebnis ist UTC. Tage werden als Millisekunden addiert: 86400000 ist ein Tag. Mehr unter JSONata in Pantarey.

Handlebars in PDF- und E-Mail-Vorlagen

Helfer Beispiel Ergebnis
dateTimeFormat {{dateTimeFormat erstellt "de-DE" "Europe/Berlin"}} 11.11.2026, 10:30:00; alle drei Argumente nötig, sonst „(Fehlerhaftes Datum angegeben)“
dateTimeFormatWithSettings {{dateTimeFormatWithSettings erstellt "de-DE" "Europe/Berlin"}} 11.11.2026, 10:30; ein Optionen-Objekt überschreibt die Vorgaben
toGermanDate {{toGermanDate rechnungsdatum}} 15.03.2026; nimmt die ersten zehn Zeichen, Zeitstempel sind erlaubt, keine Zeitzonen-Umrechnung
currentDate {{currentDate "de-DE" "Europe/Berlin"}} 11.11.2026
currentDateTime {{currentDateTime "de-DE" "Europe/Berlin"}} 11.11.2026, 10:30:00
addDaysToCurrentDate {{addDaysToCurrentDate 14}} 25.11.2026 (heute plus Tage, Europe/Berlin)
month_name {{month_name rechnungsdatum}} März
year {{year rechnungsdatum}} 2026

sortBy sortiert Texte alphabetisch: ISO-Daten landen damit in der richtigen Reihenfolge, deutsche Daten TT.MM.JJJJ nicht. Alle Helfer unter Handlebars-Helfer.

Service „Datum kalkulieren“

Der Service Datum kalkulieren rechnet mit Zeitpunkten in einem eigenen Schritt. operation ist Pflicht, Eingaben sind ISO-Texte oder Millisekunden.

Operation Eingabe Ergebnis
add date, amount (negativ zieht ab), unit von millisecond bis year { "result": "<ISO>", "timestamp": ms }
difference date, date2, unit (Standard day) { "difference": 14, "differenceExact": 14.25, "differenceMs": … }; bei month und year zählen nur Monats- und Jahreszahl
format date, format oder locale mit timezone { "formatted": "15.03.2026", "iso": …, "timestamp": … }; mit locale wird in die Zeitzone umgerechnet
now – aktueller Zeitpunkt mit Einzelteilen (components, dayOfWeek 0 = Sonntag) in UTC
startOf, endOf date, unit Anfang oder Ende der Einheit in UTC; Woche Montag bis Sonntag

Für eine Frist in Tagen reicht meist der JSONata-Einzeiler mit $fromMillis; der Service ist die Wahl für Monate, Jahre, Differenzen und startOf/endOf.

Arbeitskalender

Der Arbeitskalender des Kontos kennt Feiertage des Bundeslandes, örtliche Feiertage und freie Tage der Firma. Darauf bauen date_workdays, date_workdaysByYear, date_isWorkday und date_freeDays auf, das Formularfeld workday-count („Arbeitstage“, „ohne Feiertage und freie Tage der Firma“) zeigt die Tage schon beim Ausfüllen, und ein verbundener KI-Assistent zählt mit count_workdays. Ohne Einstellungen gelten die bundesweiten Feiertage und Montag bis Freitag.

Timer und Fristen

Element Einstellung Verhalten
Timer-Start (Zeitplan) Zeitplan rate(1 hour) oder cron(Minute Stunde Tag Monat Wochentag Jahr), Zeitzone cron braucht sechs Felder; Tag oder Wochentag ist ?. L steht für den letzten Tag im Monat, MON#1 für den ersten Montag; Wochentage auch als Zahl 1–7 mit 1 = Sonntag. Beispiele: cron(0 9 ? * MON-FRI *) werktags 9 Uhr, cron(0 9 1 1 ? *) am 1. Januar um 9 Uhr. Die Nachricht beginnt leer bis auf $$context.
Timer-Zwischenereignis (Warten) Wartezeit (Sekunden), Standard 15, auch als Platzhalter $(wartezeit) nur ganze Sekunden über 0; 86400 ist ein Tag, 259200 drei Tage
Zeitlimit einer Benutzeraufgabe oder externen Aufgabe Modus Standard: 30 Tage, Zeitspanne (Minuten, Stunden, Tage) oder Datum aus Prozessdaten mit $(frist); Verhalten bei Zeitüberschreitung Abbruch (Fehler) oder Weiter (automatisch fortfahren) Der Platzhalter liefert ein ISO-Datum oder eine Zahl in Sekunden. Ein reines Datum gilt bis 23:59:59 UTC; ein Datum in der Vergangenheit meldet „Frist bereits abgelaufen“, ein deutsches Datum „weder eine Zahl (Sekunden) noch ein gültiges ISO-Datum“. Bei Weiter steht danach $$context.timedOut auf true.

Typische Fehler

Fehler Erklärung
Daten als Text vergleichen ISO-Texte JJJJ-MM-TT und Zeitstempel sind alphabetisch gleich chronologisch, rechnungsdatum <= $substring($now(), 0, 10) stimmt. Deutsche Daten TT.MM.JJJJ sind es nicht: 01.04.2026 steht vor 15.03.2026. In SQL wird eine date-Spalte nicht mit einem Text verglichen, sondern mit einem Datumsliteral wie DATE '2026-01-01'.
Zeitstempel in date_toGermanDate liefert ein falsches Ergebnis; zuerst mit $substring(wert, 0, 10) kürzen. Der Handlebars-Helfer toGermanDate kürzt selbst.
Zeitstempel im Arbeitskalender wird auf das Datum gekürzt, ohne in die Ortszeit umzurechnen; ein Zeitpunkt um 23 Uhr UTC zählt zum UTC-Tag. Daten als JJJJ-MM-TT übergeben.
Sommerzeit Ein Timer-Start mit Zeitzone UTC läuft im Sommer eine Stunde später in Deutschland als im Winter. Mit Deutschland (Berlin) bleibt 9 Uhr das ganze Jahr 9 Uhr.
Monatsende add mit unit: month rechnet mit Kalendermonaten: 31. Januar plus ein Monat fällt in den März. difference mit month zählt nur Monatsnummern, der Tag spielt keine Rolle. Für den letzten Tag im Monat im Timer-Start L nutzen.
Millisekunden und ISO gemischt $$context.executedAt ist ISO, $$context.finishedAt sind Millisekunden. $fromMillis und $toMillis wandeln um; der Service Datum kalkulieren nimmt beides.
Deutsche Daten in Fristen Datum aus Prozessdaten und die Kalenderfunktionen verlangen JJJJ-MM-TT; der CSV-Import wandelt TT.MM.JJJJ beim Einlesen um.

Beispiel

Die Musterfirma GmbH berechnet beim Speichern einer Rechnung die Frist im Input des Datenbank-Elements: "frist": $fromMillis($toMillis(rechnung.rechnungsdatum) + 14 * 86400000, '[Y0001]-[M01]-[D01]') ergibt aus 2026-03-15 den 2026-03-29. Die Benutzeraufgabe „Zahlungseingang prüfen“ hat als Zeitlimit Datum aus Prozessdaten $(rechnung_db.frist) mit Weiter (automatisch fortfahren); ein Gateway prüft $(pruefung.$$context.timedOut) === true. Die Mahnung verschickt ein zweiter Prozess mit Timer-Start cron(0 9 ? * MON-FRI *) und Zeitzone Deutschland (Berlin): Sein Datenbank-Element liest die fälligen Rechnungen mit frist < $substring($now(), 0, 10) und bekommt den Output-Ausdruck { "rechnungen": $, "werktag": $fn('date_isWorkday', $substring($now(), 0, 10)) } mit Ergebnispfad faellig. Das Gateway dahinter lässt mit $(faellig.werktag) === true nur an Arbeitstagen nach dem Arbeitskalender Mahnungen zu, an Feiertagen endet der Vorgang.

Häufige Fragen

Warum steht in der Datenbank eine andere Uhrzeit als eingegeben?

Zeitpunkte werden in UTC gespeichert und enden auf Z. Die Anzeige in Formularen und in der Datensatz-Ansicht rechnet in die Ortszeit zurück; in Rohdaten, SQL und E-Mail-Vorlagen erscheint UTC, dort mit dateTimeFormat und "Europe/Berlin" formatieren.

Wie wird ein Datum in deutscher Schreibweise ausgegeben?

In JSONata und Platzhaltern mit $fn('date_toGermanDate', datum) für JJJJ-MM-TT, bei Zeitstempeln vorher $substring(datum, 0, 10). In Vorlagen mit {{toGermanDate datum}} oder, mit Uhrzeit, {{dateTimeFormat datum "de-DE" "Europe/Berlin"}}.

Wie wird heute plus 14 Tage berechnet?

$fromMillis($millis() + 14 * 86400000, '[Y0001]-[M01]-[D01]') in JSONata oder der Service Datum kalkulieren mit operation: "add", amount: 14, unit: "day". In einer Vorlage {{addDaysToCurrentDate 14}}.

Warum startet der Timer eine Stunde zu spät?

Der Prozess hat keine Zeitzone und läuft in UTC. Zeitzone auf Deutschland (Berlin) setzen und neu deployen.

Gibt es ein Feld nur für eine Uhrzeit?

Nein. Eine Uhrzeit wird als Zeitpunkt mit Datum oder als Text gespeichert; eine Dauer als Zahl mit dem Format Dauer in Millisekunden.

Warum zählt der Arbeitskalender einen Tag zu wenig?

Übergeben wurde ein Zeitstempel kurz vor Mitternacht UTC; er zählt zum UTC-Tag. Daten als JJJJ-MM-TT übergeben, etwa aus einem Feld vom Typ Datum.

Nächster Schritt

Kochbuch: fertige Rezepte für Rechnungsnummern, Summen, Dateien, Status, Bedingungen und Fristen.