Skip to main content
Voir en Markdown

Actions de date

La famille d'actions date effectue le travail sur les dates sensible au fuseau horaire et à la locale à l'intérieur d'une automatisation : rendre un instant, en relire un depuis une chaîne, le décaler, mesurer entre deux instants et se caler sur une borne de calendrier. Huit opérateurs, pas un de plus — les absences sont délibérées et sont listées en fin de page.

app.yaml
- name: dueLabel
  type: date
  operator: format
  props:
    input: '{{trigger.data.dueAt}}'
    pattern: "EEEE d MMMM yyyy 'à' HH:mm"
    timezone: Europe/Paris
    locale: fr-FR

Les opérateurs

Opérateur Props requises Props optionnelles Sortie
format input, pattern timezone, locale { formatted }
parse input, pattern timezone { instant, valid }
add input + ≥1 composant timezone { instant }
subtract input + ≥1 composant timezone { instant }
diff from, to, unit timezone { value }
startOf input, unit timezone { instant }
endOf input, unit timezone { instant }
now (aucune) pattern, timezone, locale { instant }, plus formatted avec un pattern

instant est toujours une chaîne ISO 8601, jamais un Date : une sortie d'étape est persistée en JSON dans l'historique d'exécution, relue par les templates et renvoyée dans les corps de webhook, et un Date ne survit à aucun de ces sauts avec son type intact.

timezone est un identifiant IANA (Europe/Paris), avec UTC par défaut. Un instant ne porte aucun fuseau propre — timezone est ce dans quoi l'instant est lu. Un décalage fixe (+02:00) est accepté mais ne peut pas exprimer l'heure d'été : préférez un fuseau nommé partout où elle s'applique. locale est une étiquette BCP 47 (fr-FR, en-US par défaut) et n'affecte que les jetons de nom de mois et de jour ; un pattern purement numérique l'ignore.

Le jeu de jetons est fermé

pattern s'écrit en jetons Unicode LDML, et le vocabulaire est fermé :

Jeton Signification Analysable
yyyy Année civile, 4 chiffres (2026) oui
MM Mois, 2 chiffres (01–12) oui
dd Jour du mois, 2 chiffres (01–31) oui
HH Heure, 2 chiffres, format 24 h (00–23) oui
mm Minute, 2 chiffres (00–59) oui
ss Seconde, 2 chiffres (00–59) oui
MMMM Nom du mois, complet, localisé (mars) non
MMM Nom du mois, court, localisé (mars) non
EEEE Nom du jour, complet, localisé (samedi) non
EEE Nom du jour, court, localisé (sam.) non
YYYY Alias hérité de yyyy oui
DD Alias hérité de dd oui

Les quatre jetons de nom sont marqués non analysables. parse ne prend donc pas de locale, et un pattern contenant MMMM ou EEEE est rejeté du côté analyse — mars est ambigu selon les locales et les styles d'abréviation, et l'accepter relèverait de la devinette plutôt que de l'analyse.

parse rend la validité sous forme de donnée

app.yaml
- name: readDueDate
  type: date
  operator: parse
  props:
    input: '{{trigger.data.dueDate}}'
    pattern: dd/MM/yyyy
    timezone: Europe/Paris

La sortie est { instant, valid }. Une chaîne qui ne correspond pas au pattern fait réussir l'étape avec valid: false et un instant null, plutôt que de la faire échouer. C'est délibéré, et deux comportements en dépendent :

  • Les tentatives. Une étape en échec est retentée selon sa configuration retry. Retenter un verdict déterministe consomme le budget et retarde l'exécution pour un résultat qui ne peut pas changer.
  • Le flux de contrôle. Une étape en échec arrête la branche sauf si continueOnError est défini, si bien qu'un filter ou un path en aval censé router les lignes invalides ne s'exécuterait jamais. Renvoyer une donnée laisse la décision là où un auteur peut agir dessus.

Un pattern malformé est le cas inverse — une erreur d'auteur, pas une donnée — et fait bien échouer l'étape.

app.yaml
- name: routeInvalid
  type: filter
  operator: continue
  props:
    condition:
      conditions:
        - field: '{{readDueDate.valid}}'
          operator: equals
          value: true
    onFalse: skip

Arithmétique : unités de calendrier et temps écoulé

add et subtract prennent au moins un composant de durée. Les quantités sont au pluriel (days: 7) alors que les noms d'unités ailleurs sont au singulier — quantités contre noms, le même partage que celui de Temporal et de java.time. N'en déclarer aucun est une erreur de configuration.

Composant Résolu comme
years Calendrier — sensible à l'heure d'été, heure murale préservée
months Calendrier — 31 janvier + 1 mois donne le 28 février
weeks Calendrier — sensible à l'heure d'été, heure murale préservée
days Calendrier — un jour à cheval sur un changement d'heure fait 23 ou 25 h
hours Écoulé — une heure fait toujours 60 minutes
minutes Écoulé — insensible à l'heure d'été
seconds Écoulé — insensible à l'heure d'été

Les grandes unités s'appliquent avant les petites, si bien que le rabotage de fin de mois a lieu en premier : 31 janvier + { months: 1, hours: 6 } est ramené au 28 février puis reçoit six heures.

app.yaml
- name: reminderAt
  type: date
  operator: subtract
  props:
    input: '{{trigger.data.dueAt}}'
    days: 2
    hours: 3
    timezone: Europe/Paris

diff — signé et tronqué vers zéro

app.yaml
- name: daysLate
  type: date
  operator: diff
  props:
    from: '{{trigger.data.dueAt}}'
    to: '{{now.instant}}'
    unit: day
    timezone: Europe/Paris

unit est au singulier : year, month, week, day, hour, minute, second ou millisecond. Le résultat est signé — négatif quand to précède from — et tronqué vers zéro, si bien qu'un écart de 47 heures vaut un day, pas deux. Les unités de calendrier sont comptées contre le fuseau, celles de temps écoulé non.

Comme diff répond déjà avec un signe, il n'existe pas d'opérateurs isBefore / isAfter / isBetween ; comparez plutôt le résultat dans une condition de filter ou de path.

startOf / endOf — bornes de calendrier

app.yaml
- name: monthStart
  type: date
  operator: startOf
  props:
    input: '{{trigger.data.occurredAt}}'
    unit: month
    timezone: Europe/Paris

unit vaut year, month, week, day, hour, minute ou second — le même vocabulaire singulier que diff, moins millisecond, sur lequel aucune borne ne se cale. La borne est calculée dans timezone : le début d'un jour à Europe/Paris est donc 22 h ou 23 h UTC la veille au soir, selon la saison.

now

app.yaml
- name: stamp
  type: date
  operator: now
  props:
    pattern: yyyy-MM-dd
    timezone: Europe/Paris

Renvoie { instant } — un instant UTC — et ajoute formatted lorsqu'un pattern est fourni. C'est le seul opérateur sans prop requise.

Ce qui est délibérément absent

Les huit opérateurs ont été choisis contre un domaine de capacités plutôt que contre la surface d'API d'une bibliothèque de dates, si bien que plusieurs noms familiers manquent volontairement :

  • isBefore / isAfter / isBetween — relèvent d'une condition de filter ou de path ; diff renvoie déjà une réponse signée.
  • toTimezone — un instant ne porte aucun fuseau, donc ce nom enseigne un modèle faux. Le timezone de format couvre le besoin.
  • dayOfWeek / isWeekday / isWeekendformat avec EEEE, plus un filtre. Trois opérateurs pour un seul jeton, c'est exactement la prolifération que cette famille existe pour éviter.
  • timestamp / fromTimestamp — les jetons d'epoch sont une question de jeu de jetons, pas d'opérateur.
  • L'arithmétique de jours ouvrés et de jours fériés — exige un calendrier que la plateforme n'a pas, et une réponse fausse y est pire que pas de réponse.

Appeler les opérateurs de date depuis du code

Chaque opérateur est joignable depuis une action code via context.actions.date.<operator>(props). Ce chemin ne décode pas les props contre le schéma : le gestionnaire réapplique donc lui-même les garde-fous — un fuseau invalide ou un jeton non reconnu y échoue exactement comme il le ferait au démarrage.

Pages liées

Dernière mise à jour 28 août 2026

Cette documentation a été rédigée avec de l'IA : des erreurs ou du contenu obsolète sont donc possibles. Sovrium est en bêta. Les contributions et corrections sont les bienvenues.

Construit avec Sovrium