Date/heure : Luxon, formats allemands, pièges de fuseau horaire

Luxon dans n8n : produire des formats de date allemands avec toFormat et setLocale et éviter les pièges classiques de fuseau horaire dans les expressions.

n8n traite en interne la date et l'heure via la bibliothèque JavaScript Luxon et non via l'objet natif `Date` de JavaScript. Tu ne le remarques généralement que lorsqu'un workflow affiche une date décalée d'une heure, qu'un nom de mois apparaît en anglais au lieu de l'allemand, ou qu'un document se retrouve soudainement sur le mauvais jour en fin de mois. Dès que tu comprends comment Luxon sépare proprement fuseau horaire, langue et format, tu peux éviter précisément ces erreurs de manière ciblée, et tu gardes le contrôle sur la date qui se retrouve réellement sur la facture, dans le CRM ou dans le tableau.

Cet article se concentre volontairement sur le formatage de la date et de l'heure dans les expressions et dans le Date & Time Node, et non sur la logique de fuseau horaire du Schedule Trigger ou des expressions Cron. C'est un sujet à part avec ses propres pièges qui mérite un regard séparé.

Pourquoi n8n utilise Luxon

Le JavaScript pur ne connaît aucun concept intégré pour les fuseaux horaires ou les formats linguistiques allant au-delà du strict minimum. Luxon comble exactement cette lacune : chaque date que n8n génère en interne, par exemple via `$now` ou `$today`, est un objet Luxon `DateTime` avec son propre fuseau horaire, sa propre langue (locale) et ses propres méthodes de calcul, de comparaison et de formatage. Selon la documentation officielle sur le travail avec les dates et heures dans n8n, les valeurs de date sont transmises entre les nodes sous forme de chaînes de caractères et doivent d'abord être à nouveau analysées avec des fonctions Luxon pour les calculs ou le formatage. L'objet natif JavaScript `Date()` ne respecte pas le fuseau horaire défini dans n8n, raison pour laquelle la documentation recommande explicitement de rester avec Luxon pour tout ce qui concerne la date et l'heure.

Formater une date dans les expressions

Pour le formatage proprement dit, plusieurs voies sont possibles dans les expressions, plus ou moins adaptées aux exigences allemandes :

  • `.toFormat(fmt)` : la méthode native de Luxon avec laquelle tu construis toi-même un format à l'aide de tokens fixes, par exemple `dd.MM.yyyy`. Elle fonctionne partout, y compris dans le Code Node.
  • `.toLocaleString(opts)` : renvoie un format localisé, donc dépendant de la langue. Sans locale définie, le résultat suit la langue par défaut de l'instance n8n, ce qui en pratique signifie souvent l'anglais.
  • `format()` : une extension propre à n8n du langage d'expression pour le formatage des dates, qui, selon la référence d'expression DateTime, n'est pas disponible dans le Code Node. Là, tu utilises à la place le `.toFormat()` natif.
  • Formats prédéfinis dans le Date & Time Node : le Node propose des préréglages fixes comme `MM/DD/YYYY` ou `YYYY-MM-DD`, ainsi qu'une option pour un format personnalisé. Selon la documentation du Date & Time Node, n8n prend en charge pour cela tous les formats que Luxon lui-même connaît, sachant que les tokens sont sensibles à la casse.

Pour une date allemande purement numérique, `.toFormat()` avec un modèle de tokens fixe suffit généralement, tandis que `.toLocaleString()` et `.setLocale()` deviennent importants dès que des noms de mois ou de jours de la semaine en toutes lettres doivent apparaître en allemand.

Produire correctement des formats allemands

Pour la notation allemande classique `TT.MM.JJJJ`, une expression fixe sans dépendance à la locale suffit :

  • `{{$now.toFormat('dd.MM.yyyy')}}` donne par exemple `20.07.2026`.
  • `{{$now.toFormat('dd.MM.yyyy HH:mm')}}` ajoute l'heure au format 24 heures.

Dès que des noms en toutes lettres entrent en jeu, par exemple pour une facture ou un publipostage, tu as besoin en plus de la locale allemande, sinon le nom du mois est affiché en anglais :

  • `{{$now.setLocale('de-DE').toLocaleString({month: 'long', day: 'numeric', year: 'numeric'})}}` donne un résultat comme `20. Juli 2026`.
  • `{{$now.setLocale('de-DE').monthLong}}` renvoie directement le nom du mois en toutes lettres, par exemple `Juli`.

Important ici : `.setLocale()` modifie uniquement la langue de la sortie, pas le fuseau horaire. Tu dois définir les deux réglages séparément, sinon tu obtiens certes un mot allemand pour le mois, mais éventuellement quand même la mauvaise heure.

Pièges liés au fuseau horaire lors du formatage

La plupart des erreurs ne proviennent pas du format lui-même, mais du fuseau horaire dans lequel le formatage a lieu. Quelques pièges qui reviennent régulièrement en pratique :

  • Fuseau horaire par défaut de l'instance au lieu d'Europe/Berlin : sans configuration explicite, une instance n8n auto-hébergée utilise par défaut, selon la documentation, `America/New York`, tandis que sur n8n Cloud le système revient au GMT. `$now` et `$today` suivent ce fuseau horaire de l'instance, sauf si un réglage propre au workflow ou une variable d'environnement `GENERIC_TIMEZONE` indique autre chose. Quiconque néglige cela obtient des horodatages décalés de plusieurs heures par rapport à l'heure allemande.
  • Formatage sans `.setZone()` préalable : `.toFormat()` et `.toLocaleString()` affichent toujours l'heure dans le fuseau horaire que possède actuellement l'objet `DateTime`, pas automatiquement Europe/Berlin. Si une date provient d'une API en UTC ou dans un fuseau horaire étranger, tu dois d'abord la convertir avec `.setZone('Europe/Berlin')` et seulement ensuite la formater, sinon un document créé à 23h30 heure allemande se retrouve soudainement sur le jour suivant dans l'analyse.
  • Heure d'été et heure d'hiver : Europe/Berlin change deux fois par an son décalage par rapport à l'UTC. Si tu calcules avec `.plus({days: n})` à travers un tel changement puis formates ensuite l'heure, la partie horaire peut se décaler d'une heure, bien que le jour calendaire soit correct. Pour de simples comparaisons de dates sans heure, cela n'est généralement pas critique, mais pour les processus sensibles au temps, tu dois le prévoir.
  • Transmettre `.toISO()` avec décalage : la chaîne ISO de Luxon contient par défaut le décalage de fuseau horaire, par exemple `+02:00`. Les systèmes qui attendent au contraire de l'UTC pur ou une chaîne sans décalage interprètent alors cette valeur de manière incorrecte. Vérifie dans le système cible quel format est réellement attendu avant de transmettre le résultat sans réfléchir.

Exemple pratique : afficher correctement la date de facture

Un cas typique de la pratique : un workflow récupère une date de document depuis une API qui fournit des horodatages UTC, et doit en générer une date de facture allemande. L'expression correspondante se présente, combinée, ainsi :

  • `{{ $json.createdAt.toDateTime().setZone('Europe/Berlin').setLocale('de-DE').toFormat('dd.MM.yyyy') }}`

L'ordre n'est pas un hasard : d'abord l'horodatage natif JavaScript est converti en `DateTime` Luxon, puis déplacé vers le bon fuseau horaire, ensuite la langue est définie, et c'est seulement à la fin qu'il est formaté. Si tu inverses les étapes de fuseau horaire et de formatage, tu obtiens certes une date allemande d'apparence correcte, mais éventuellement pour le mauvais jour calendaire.

Questions fréquentes

Quelle est la différence entre `.toFormat()` et `.toLocaleString()` ?

`.toFormat()` suit un modèle de tokens fixe que tu définis toi-même, comme `dd.MM.yyyy`, et fournit toujours la même mise en page indépendamment de la locale. `.toLocaleString()`, en revanche, suit la langue définie et adapte automatiquement l'ordre ainsi que l'orthographe, ce qui fait la différence surtout avec les noms de mois ou de jours de la semaine en toutes lettres.

Pourquoi le nom du mois apparaît-il en anglais alors que je travaille en Allemagne ?

Sans `.setLocale('de-DE')` explicite, Luxon utilise la langue par défaut de l'instance n8n, qui est souvent réglée sur l'anglais. Le fuseau horaire de l'instance et sa langue sont deux réglages distincts, raison pour laquelle un `Europe/Berlin` correctement défini seul ne garantit pas encore un nom de mois allemand.

Dois-je définir manuellement le fuseau horaire pour chaque date ?

Chaque fois qu'une date provient d'une source externe comme une API, une base de données ou un formulaire, oui. Ces valeurs se trouvent souvent en UTC ou dans un fuseau horaire étranger, et seuls `$now` ou `$today` suivent automatiquement le fuseau horaire de l'instance ou du workflow configuré dans n8n.

Cela s'applique-t-il aussi au Schedule Trigger ou aux expressions Cron ?

Non, des règles propres s'appliquent là-bas pour le moment d'exécution lui-même, pas pour le formatage des valeurs de date dans les expressions. Cet article traite exclusivement de la manière dont une date déjà existante au sein d'un workflow est correctement formatée.

Comment savoir quels tokens de format Luxon prend en charge ?

Selon la documentation du Date & Time Node, n8n prend en charge tous les tokens que Luxon lui-même connaît, sachant que la casse a chaque fois sa propre signification. Pour un aperçu complet de tous les tokens disponibles, il vaut la peine de consulter la référence de formatage Luxon liée directement depuis la documentation n8n.

À propos de NordFlux

NordFlux UG (haftungsbeschränkt)

NordFlux construit des employés numériques pour les organisations : des automatisations et des agents KI qui prennent en charge le travail répétitif. Vous gardez le contrôle.

En savoir plus sur nous
Analyse initiale gratuite

Des questions concrètes sur l’automatisation ou l’IA ?

Lors d’une analyse initiale gratuite, nous discutons directement de votre cas. Sans engagement.