Datum/Uhrzeit: Luxon, deutsche Formate, Zeitzonen-Fallen
Luxon in n8n: deutsche Datumsformate mit toFormat und setLocale erzeugen und typische Zeitzonen-Fallen in Ausdrücken vermeiden.
n8n verarbeitet Datum und Uhrzeit intern über die JavaScript-Bibliothek Luxon und nicht über das native `Date`-Objekt von JavaScript. Das merkst Du meistens erst dann, wenn ein Workflow ein Datum ausgibt, das eine Stunde daneben liegt, ein Monatsname auf Englisch statt auf Deutsch erscheint oder ein Beleg am Monatsende plötzlich auf dem falschen Tag landet. Sobald Du verstehst, wie Luxon Zeitzone, Sprache und Format sauber trennt, lassen sich genau diese Fehler gezielt vermeiden, und Du behältst die Kontrolle darüber, welches Datum am Ende wirklich in Rechnung, CRM oder Tabelle steht.
Dieser Artikel konzentriert sich bewusst auf die Formatierung von Datum und Uhrzeit in Ausdrücken und im Date & Time Node, nicht auf die Zeitzonen-Logik des Schedule Triggers oder von Cron-Ausdrücken. Das ist ein eigenes Thema mit eigenen Stolperfallen, das einen separaten Blick verdient.
Warum n8n überhaupt Luxon nutzt
Reines JavaScript kennt kein eingebautes Konzept für Zeitzonen oder Sprachformate, die über das Grundlegendste hinausgehen. Luxon füllt genau diese Lücke: Jedes Datum, das n8n intern erzeugt, etwa über `$now` oder `$today`, ist ein Luxon-`DateTime`-Objekt mit eigener Zeitzone, eigener Sprache (Locale) und eigenen Methoden zum Rechnen, Vergleichen und Formatieren. Laut der offiziellen Dokumentation zur Arbeit mit Datum und Uhrzeit in n8n werden Datumswerte zwischen Nodes als Strings weitergereicht und müssen für Berechnungen oder Formatierungen erst wieder mit Luxon-Funktionen geparst werden. Das native JavaScript-`Date()` respektiert die in n8n eingestellte Zeitzone nicht, weshalb die Dokumentation ausdrücklich empfiehlt, für alles rund um Datum und Uhrzeit bei Luxon zu bleiben.
Ein Datum in Ausdrücken formatieren
Für die eigentliche Formatierung stehen in Ausdrücken mehrere Wege offen, die unterschiedlich gut für deutsche Anforderungen geeignet sind:
- `.toFormat(fmt)`: die native Luxon-Methode, mit der Du ein Format über feste Tokens selbst zusammenbaust, etwa `dd.MM.yyyy`. Sie funktioniert überall, auch im Code-Node.
- `.toLocaleString(opts)`: liefert ein lokalisiertes, also sprachabhängiges Format. Ohne gesetzte Locale orientiert sich das Ergebnis an der Standardsprache der n8n-Instanz, was in der Praxis oft Englisch bedeutet.
- `format()`: eine n8n-eigene Erweiterung der Ausdruckssprache für Datumsformatierung, die laut der DateTime-Ausdrucksreferenz im Code-Node nicht verfügbar ist. Dort greifst Du stattdessen auf das native `.toFormat()` zurück.
- Voreingestellte Formate im Date & Time Node: Der Node bringt feste Presets wie `MM/DD/YYYY` oder `YYYY-MM-DD` mit, dazu eine Option für ein eigenes Format. Laut Dokumentation zum Date & Time Node unterstützt n8n dafür alle Formate, die auch Luxon selbst kennt, wobei die Tokens groß-/kleinschreibungssensitiv sind.
Für ein rein numerisches deutsches Datum reicht meistens `.toFormat()` mit einem festen Token-Muster, während `.toLocaleString()` und `.setLocale()` dann wichtig werden, sobald ausgeschriebene Monats- oder Wochentagsnamen auf Deutsch erscheinen sollen.
Deutsche Formate sauber erzeugen
Für die klassische deutsche Schreibweise `TT.MM.JJJJ` reicht ein fester Ausdruck ohne Locale-Abhängigkeit:
- `{{$now.toFormat('dd.MM.yyyy')}}` ergibt zum Beispiel `20.07.2026`.
- `{{$now.toFormat('dd.MM.yyyy HH:mm')}}` ergänzt die Uhrzeit im 24-Stunden-Format.
Sobald ausgeschriebene Namen ins Spiel kommen, etwa für eine Rechnung oder einen Serienbrief, brauchst Du zusätzlich die deutsche Locale, weil sonst der Monatsname auf Englisch ausgegeben wird:
- `{{$now.setLocale('de-DE').toLocaleString({month: 'long', day: 'numeric', year: 'numeric'})}}` liefert ein Ergebnis wie `20. Juli 2026`.
- `{{$now.setLocale('de-DE').monthLong}}` gibt direkt den ausgeschriebenen Monatsnamen zurück, etwa `Juli`.
Wichtig dabei: `.setLocale()` ändert ausschließlich die Sprache der Ausgabe, nicht die Zeitzone. Beide Einstellungen musst Du getrennt voneinander setzen, sonst bekommst Du zwar ein deutsches Wort für den Monat, aber unter Umständen trotzdem die falsche Uhrzeit.
Zeitzonen-Fallen bei der Formatierung
Die meisten Fehler entstehen nicht beim Format selbst, sondern bei der Zeitzone, in der formatiert wird. Ein paar Fallen, die in der Praxis immer wieder auftauchen:
- Instanz-Standardzeitzone statt Europe/Berlin: Ohne explizite Konfiguration nutzt eine selbst gehostete n8n-Instanz laut Dokumentation standardmäßig `America/New York`, auf n8n Cloud fällt das System auf GMT zurück. `$now` und `$today` orientieren sich an dieser Instanz-Zeitzone, sofern kein Workflow-eigenes Setting oder keine `GENERIC_TIMEZONE`-Umgebungsvariable etwas anderes vorgibt. Wer das übersieht, bekommt Zeitstempel, die um mehrere Stunden von der deutschen Uhrzeit abweichen.
- Formatierung ohne vorheriges `.setZone()`: `.toFormat()` und `.toLocaleString()` geben immer die Uhrzeit in der Zeitzone aus, die das `DateTime`-Objekt gerade hat, nicht automatisch Europe/Berlin. Kommt ein Datum aus einer API in UTC oder in einer fremden Zeitzone, solltest Du es zuerst mit `.setZone('Europe/Berlin')` umrechnen und erst danach formatieren, sonst landet ein Beleg, der um 23:30 Uhr deutscher Zeit erstellt wurde, in der Auswertung plötzlich auf dem Folgetag.
- Sommerzeit und Winterzeit: Europe/Berlin wechselt zweimal im Jahr die Uhrzeitverschiebung zu UTC. Rechnest Du mit `.plus({days: n})` über einen solchen Wechsel hinweg und formatierst danach die Uhrzeit, kann sich der Zeitanteil um eine Stunde verschieben, obwohl der Kalendertag stimmt. Für reine Datums-ohne-Uhrzeit-Vergleiche ist das meist unkritisch, für zeitkritische Prozesse solltest Du es einplanen.
- `.toISO()` mit Offset weiterreichen: Der ISO-String von Luxon enthält standardmäßig den Zeitzonen-Offset, etwa `+02:00`. Systeme, die stattdessen reines UTC oder einen offset-losen String erwarten, interpretieren diesen Wert sonst falsch weiter. Prüfe im Zielsystem, welches Format tatsächlich erwartet wird, bevor Du das Ergebnis blind übergibst.
Praxisbeispiel: Rechnungsdatum korrekt ausgeben
Ein typischer Fall aus der Praxis: Ein Workflow holt ein Belegdatum aus einer API, die UTC-Zeitstempel liefert, und soll daraus ein deutsches Rechnungsdatum erzeugen. Der Ausdruck dafür sieht kombiniert so aus:
- `{{ $json.createdAt.toDateTime().setZone('Europe/Berlin').setLocale('de-DE').toFormat('dd.MM.yyyy') }}`
Die Reihenfolge ist dabei kein Zufall: Zuerst wird der native JavaScript-Zeitstempel in ein Luxon-`DateTime` umgewandelt, dann in die richtige Zeitzone verschoben, danach die Sprache gesetzt und erst zum Schluss formatiert. Vertauschst Du Zeitzonen- und Formatierungsschritt, bekommst Du zwar ein korrekt aussehendes deutsches Datum, aber möglicherweise für den falschen Kalendertag.
Häufige Fragen
Was ist der Unterschied zwischen `.toFormat()` und `.toLocaleString()`?
`.toFormat()` folgt einem festen, von Dir selbst definierten Token-Muster wie `dd.MM.yyyy` und liefert unabhängig von der Locale immer dasselbe Layout. `.toLocaleString()` orientiert sich dagegen an der gesetzten Sprache und passt Reihenfolge sowie Schreibweise automatisch an, was besonders bei ausgeschriebenen Monats- oder Wochentagsnamen den Unterschied macht.
Warum erscheint der Monatsname auf Englisch, obwohl ich in Deutschland arbeite?
Ohne ein explizites `.setLocale('de-DE')` verwendet Luxon die Standardsprache der n8n-Instanz, die häufig auf Englisch steht. Die Zeitzone der Instanz und ihre Sprache sind zwei getrennte Einstellungen, weshalb ein korrekt eingestelltes `Europe/Berlin` allein noch keinen deutschen Monatsnamen garantiert.
Muss ich für jedes Datum manuell die Zeitzone setzen?
Immer dann, wenn ein Datum aus einer externen Quelle wie einer API, einer Datenbank oder einem Formular stammt, ja. Solche Werte liegen oft in UTC oder in einer fremden Zeitzone vor, und nur `$now` beziehungsweise `$today` folgen automatisch der in n8n konfigurierten Instanz- oder Workflow-Zeitzone.
Gilt das auch für den Schedule Trigger oder Cron-Ausdrücke?
Nein, dort gelten eigene Regeln für die Ausführungszeit selbst, nicht für die Formatierung von Datumswerten in Ausdrücken. Dieser Artikel behandelt ausschließlich, wie ein bereits vorhandenes Datum innerhalb eines Workflows korrekt formatiert wird.
Wie finde ich heraus, welche Format-Tokens Luxon unterstützt?
n8n unterstützt laut Dokumentation zum Date & Time Node sämtliche Tokens, die auch Luxon selbst kennt, wobei Groß- und Kleinschreibung jeweils eine eigene Bedeutung hat. Für den vollständigen Überblick über alle verfügbaren Tokens lohnt sich ein Blick in die verlinkte Luxon-Formatierungsreferenz direkt aus der n8n-Dokumentation heraus.
NordFlux UG (haftungsbeschränkt)
NordFlux baut Organisationen digitale Mitarbeiter: Automatisierungen und KI-Agenten, die wiederkehrende Arbeit abnehmen. Sie behalten die Kontrolle.
Konkrete Fragen zu Automatisierung oder KI?
In der kostenlosen Erstanalyse besprechen wir Ihren Fall direkt. Unverbindlich.