3 points par GN⁺ 2023-09-01 | 1 commentaires | Partager sur WhatsApp
  • Lorsqu’il s’agit de représenter la date et l’heure, RFC 3339 se rapproche d’un sous-ensemble restreint, facile à utiliser sur le web et Internet, tandis que ISO 8601-1:2019 couvre un ensemble de formats bien plus large
  • Le périmètre de comparaison est limité à ISO 8601-1:2019, et les expressions supplémentaires d’ISO 8601-2:2019 comme les saisons, ensembles, qualificatifs d’incertitude ou l’arithmétique des dates ne sont pas encore reflétées dans le tableau
  • Les deux standards traitent ensemble des formats de base de date et d’heure largement utilisés, comme 2026-06-26, 14:08:00Z, 2026-06-26T14:08:00Z et les offsets +00:00
  • ISO 8601 couvre aussi les siècles, décennies, jours ordinaux, dates par semaine, heures abrégées, décimales avec virgule, périodes (P1Y) et intervalles (2026-06-26/P1Y), alors que RFC 3339 les exclut pour la plupart dans le tableau
  • Pour la notation Date-Time, des différences comme le séparateur T, la casse, ou l’offset -00:00 déterminent concrètement la compatibilité entre parseurs

Périmètre de comparaison et hypothèses

  • Le tableau des formats n’est pas une liste exhaustive
  • Le standard visé est ISO 8601-1:2019
    • Il existe des différences importantes avec les éditions précédentes et les brouillons
  • ISO 8601-2:2019 inclut des expressions supplémentaires, mais elles ne sont pas encore reflétées sur cette page
    • Groupes infra-annuels, par exemple les saisons
    • Unités de regroupement
    • Ensembles
    • Qualificatifs d’incertitude
    • Arithmétique des dates
  • RFC 3339 propose que des sous-standards puissent remplacer T par un autre caractère, mais ne donne comme exemple que le caractère espace
  • Chaque standard définit des formats selon un usage donné, et les autres formats ne sont pas recommandés

ISO 8601 est plus large pour les notations de date

  • RFC 3339 et ISO 8601 prennent tous deux en charge les dates année-mois-jour comme 2026-06-26
  • ISO 8601 couvre davantage de représentations de date que RFC 3339
    • Siècle : 20
    • Décennie : 202
    • Année : 2026
    • Année-mois : 2026-06
    • Jour ordinal : 2026-177
    • Date par semaine : 2026-W26, 2026-W26-5
    • Format de base : 20260626, 2026177, 2026W26, 2026W265
  • Dans le tableau, RFC 3339 n’autorise pas ces formats de date propres à ISO

Différences dans la notation de l’heure

  • Les deux standards autorisent les heures à la seconde avec offset de fuseau horaire comme 14:08:00Z, 14:08:00+00:00 et 14:08:00.372+00:00
  • RFC 3339 ne distingue pas les majuscules et minuscules, si bien que T et Z peuvent aussi s’écrire t et z
    • Les éditions précédentes d’ISO 8601 ne distinguaient pas non plus la casse
  • ISO 8601 permet d’ajouter une partie fractionnaire à la plus petite unité de temps
    • Le tableau montre surtout des exemples avec un seul chiffre après la décimale, mais le standard autorise une précision arbitraire
    • La virgule et le point sont tous deux admis comme séparateurs décimaux, et sont interchangeables dans tous les formats
  • ISO 8601-1:2019 autorise l’omission de T dans les expressions d’heure seules lorsque cela ne crée pas d’ambiguïté
  • ISO 8601 prend en charge des représentations abrégées, de base ou à décimale avec virgule comme 14, 14:08, 14:08:00, 140800, T14:08:00, 14:08:00,372
  • RFC 3339 autorise l’offset -00:00 comme dans 14:08:00-00:00, alors que dans le tableau ISO 8601 ne l’autorise pas

T et les séparateurs dans Date-Time

  • RFC 3339 et ISO 8601 autorisent tous deux des Date-Time comme 2026-06-26T14:08:00Z et 2026-06-26T14:08:00+00:00
  • Dans la représentation Date-Time d’ISO 8601, T est toujours obligatoire
    • Les éditions précédentes autorisaient aussi l’omission de T dans Date-Time
    • Même dans les éditions précédentes, l’insertion de caractères de remplacement comme un espace ou un souligné n’était pas autorisée
  • Dans le tableau, RFC 3339 autorise les variantes Date-Time suivantes
    • t et z en minuscules : 2026-06-26t14:08:00z
    • Séparateur espace : 2026-06-26 14:08:00Z
    • Séparateur souligné : 2026-06-26_14:08:00Z
    • Offset -00:00 : 2026-06-26T14:08:00-00:00
  • ISO 8601 couvre des Date-Time abrégés ainsi que des Date-Time fondés sur le jour ordinal ou la date par semaine, comme 2026-06-26T14, 2026-06-26T14:08, 2026-06-26T14:08:00, 2026-177T14:08, 2026-W26-5T14:08

Les périodes et intervalles relèvent surtout d’ISO 8601

  • Dans le tableau, les formats de période (Periods) ne sont cochés que pour ISO 8601
    • Ex. : P1Y, P1M, P1W, P1D
    • Avec heure : PT1H, PT1M, PT1S
    • Combinaison : P1Y1M1DT1H1M1S
    • Exemples fractionnaires : P1.5Y, P1,5W, PT1.5S
  • Les formats d’intervalle (Ranges) ne sont eux aussi cochés que pour ISO 8601
    • Date et période : 2026-06-26/P1Y
    • Date et date : 2026-06-26/2026-06-26
    • Période et date : P1Y/2026-06-26
    • Date-Time et période : 2026-06-26T14:08/P1DT1H
    • Intervalles répétés : R/2026-06-26/P1Y, R10/2026-06-26/P1Y

Clés de format et outil de test

  • Le tableau des formats utilise des clés de format comme %Y, %M, %D, %h, %m, %s
    • %Y : Year
    • %M : Month
    • %D : Day
    • %V : Week Year
    • %W : Week
    • %w : Week Day
    • %O : Ordinal Day
    • %h : Hour
    • %m : Minute
    • %s : Second
    • %u : Microsecond
    • %n : Nanosecond
    • %Z : heure de fuseau avec + ou -
    • %z : minute de fuseau horaire
  • Le validateur de formats vérifie seulement si le format saisi correspond à l’un des formats du tableau
    • Il ne teste pas tous les formats possibles
  • ISO 8601 as a Service est un service en bêta-test
    • Il prend actuellement en charge seulement Date, Time et DateTime
    • Period et Range ne sont pas pris en charge
  • Le code source est publié sur GitHub

1 commentaires

 
GN⁺ 2023-09-01
Avis sur Hacker News
  • Il est étrange qu’il n’existe aucun moyen de spécifier une date/heure future dans un fuseau horaire donné. Par exemple, on peut vouloir planifier une réunion le 1er juillet 2030 à 18 h, heure locale de Londres, et il faudrait que cela reste « 18 h à Londres », quelles que soient les modifications des règles du fuseau horaire britannique d’ici là
    Le Royaume-Uni utilise actuellement, en gros, Z+00:00 de novembre à mars et l’heure d’été Z+01:00 d’avril à octobre[0], mais d’ici 2030 il pourrait adopter l’heure d’Europe centrale[1], retenter la British Double Summer Time[2] ou supprimer l’heure d’été. Le même « 18 h » pourrait donc varier fortement par rapport à un epoch donné
    Je veux mettre dans un événement de calendrier « 18 h selon l’heure de Londres à ce moment-là », mais il n’existe pas de manière standard et interopérable de représenter 2030-07-01 18:00:00 Europe/London
    [0] https://en.wikipedia.org/wiki/British_Summer_Time
    [1] https://en.wikipedia.org/wiki/Central_European_Time
    [2] https://en.wikipedia.org/wiki/British_Summer_Time#Periods_of...

    • Il existe un brouillon de document pour ce type de format, IXDTF (Internet Extended Date/Time Format)[0]. On peut ajouter un fuseau horaire sous forme de nom tz entre crochets après une chaîne RFC 3339, et pour exprimer une heure locale il faut aussi fournir une estimation du décalage UTC
      Par exemple, 2030-07-01 18:00:00 Europe/London devient 2030-07-01T18:00:00+01:00[Europe/London]. Si les règles britanniques changent avant cette date, l’horodatage devient « incohérent » et c’est à l’application de décider comment le traiter. En revanche, si l’on met ! devant le nom du fuseau horaire entre crochets, il ne faut pas suivre aveuglément le décalage UTC et le problème doit être détecté
      Ce format d’horodatage étendu est aussi utilisé par la bibliothèque Temporal proposée pour JavaScript[1], et la fonction de parsing ZonedDateTime.from()[2] permet de contrôler, via l’option offset, quel côté privilégier dans un horodatage incohérent. Il est également possible d’omettre le décalage UTC et de n’indiquer que le fuseau horaire, mais la documentation avertit que l’heure répétée lors du passage à l’heure d’été est ambiguë
      [0] https://www.ietf.org/archive/id/draft-ietf-sedate-datetime-e...
      [1] https://tc39.es/proposal-temporal/docs/strings.html#iana-tim...
      [2] https://tc39.es/proposal-temporal/docs/ambiguity.html#ambigu...
    • En réalité, il semble qu’il faille une information plus précise qu’un fuseau horaire. Imaginons par exemple que l’on veuille se retrouver non pas à Londres, mais à Glasgow, en Écosse, le 1er juillet 2030 à 18 h : aujourd’hui, Glasgow se trouve dans le fuseau Europe/London
      Mais il n’est pas inimaginable qu’entre-temps l’Écosse organise un nouveau référendum d’indépendance et rejoigne l’heure d’Europe centrale, ou crée une Scottish Standard Time
    • Le piège de ce type de représentation, c’est qu’elle produit des horodatages ambigus ou impossibles. 2023-11-05 01:30:00 America/New_York correspond à l’un de deux instants différents
      Dans un calendrier, « la même heure à l’horloge murale » est généralement le sens recherché, donc c’est légitime, mais il y a des difficultés d’interface pour gérer les heures bizarres, et l’on peut vouloir intégrer à la syntaxe une façon de lever l’ambiguïté. Heureusement, ces transitions ont généralement lieu au milieu de la nuit, mais j’ai déjà vu ce cas dans un contexte professionnel réel
      Si vous invitez quelqu’un dont le fuseau horaire n’a pas d’heure d’été, l’heure bougera dans son calendrier, et il arrive que des collègues internationaux doivent faire avec
    • Dans le monde des calendriers, iCal le prend déjà en charge. Une date-heure sans fuseau horaire signifie uniquement l’heure locale[0]
      [0]: https://www.rfc-editor.org/rfc/rfc5545#section-3.3.5
    • Les informations nécessaires sont au nombre de trois : la date, le lieu et l’heure locale. En réalité, ce que l’on veut n’est pas forcément un fuseau horaire. Il faut se demander quoi faire si un lieu donné, autre que Londres, passe dans un autre fuseau horaire
      Les formats date-heure courants ont été conçus pour représenter un instant précis, mais dans ce cas cet instant précis n’existe pas encore. Il est fréquent que des spécifications de date/heure aient une structure non triviale : réunion le dernier vendredi de chaque mois, réunion mensuelle commençant le 31 janvier, deux jours avant la fin du trimestre, etc.
      Si l’on veut créer une norme couvrant tous les cas que les gens peuvent imaginer, cela risque vite de devenir complexe. Si une simple date, une heure ou un instant ne suffisent pas, il semble inévitable de créer une structure distincte contenant tous les éléments nécessaires
  • La spécification ISO n’étant pas disponible gratuitement, il vaut généralement mieux suivre la RFC, et comme beaucoup d’implémentations open source reposent aussi sur des brouillons, on peut difficilement dire que ce soit pleinement favorable à l’open source. C’est aussi une lourde charge pour les développeurs open source
    Si l’on construit quelque chose qui manipule des dates futures, on finit presque toujours par vouloir stocker l’heure d’horloge murale + le lieu. Malheureusement, il n’existe pas de standard pour cela. En Europe et aux États-Unis, les fuseaux horaires sont assez stables, donc on peut ne pas bien le ressentir, mais dans de nombreuses régions ils changent souvent, si bien que stocker le décalage n’est pas fiable
    5 juin 2026 13:30 à l’horloge murale, Paris correspond à ce que la plupart des gens veulent dire, et selon ce que l’UE décidera de faire avec l’heure d’été, cela pourra être UTC+2 ou UTC+1. Pour une API qui manipule des instants passés, il suffit d’utiliser un timestamp POSIX en secondes, millisecondes, microsecondes ou nanosecondes

    • iCalendar est le standard RFC prévu pour cela[1]. Toutefois, lors des changements liés à l’heure d’été, certains instants ont deux représentations, et d’autres ne peuvent pas être représentés dans ce format
      iCal ne prend pas non plus en compte le problème d’un lieu réaffecté à un autre fuseau horaire. De plus, un fichier iCal correct contient toutes les données des fuseaux horaires référencés, ce qui est lourd quand on veut simplement produire une seule date-heure
      [1] https://icalendar.org/iCalendar-RFC-5545/3-3-5-date-time.htm...
    • Il existe un projet de standard, IXDTF, qui étend RFC 3339 en plaçant le nom de fuseau horaire IANA entre crochets : 2026-06-05T13:30+0200[Europe/Paris]
      https://www.ietf.org/archive/id/draft-ietf-sedate-datetime-e...
  • Un aspect souvent ignoré dans les standards est la représentation des durées
    Voir la section 5.5.4.2 “Representation of time-interval by duration only”, page 21, de http://xml.coverpages.org/ISO-FDIS-8601.pdf. Ce serait bien que les parseurs JSON des langages statiques puissent définir un champ comme une durée et le sérialiser dans un format valide
    Un exemple de proposition pour Crystal est ici : https://github.com/crystal-lang/crystal/issues/11942
    Par exemple, 15 jours, 5 heures et 20 secondes s’écrivent P15DT5H0M20S, et 7 semaines P7W

    • On peut aussi se référer à la définition de duration dans l’ABNF de l’annexe A de la RFC 3339
    • Je ne comprends pas pourquoi on voudrait représenter sous forme de chaîne des données qui peuvent être structurées
      Par exemple, avec "duration": { "days": 15, "hours": 5, "seconds": 20 }, le parseur JSON n’a pas besoin de comprendre la signification des données, et un validateur d’entrée peut s’en charger. De toute façon, quelle que soit la manière dont JSON représente ces données, il faudra une étape de conversion susceptible d’échouer
  • Ce qui est « drôle », c’est que RFC 3339 et ISO 8601 contiennent de nombreux formats de date-heure redondants aux objectifs qui se recoupent, mais qu’aucun des deux n’inclut le format le plus utilisé partout et pourtant évident, 2023-09-01 15:30:59
    De plus, les deux standards sont très peu clairs sur la manière de représenter les dates avant notre ère et les dates postérieures à 9999-12-31 ou antérieures à -9999-01-01, et les bibliothèques courantes ne les gèrent généralement pas du tout. Même lorsqu’elles les gèrent, le comportement de 00-01-01 est pratiquement non défini
    Le calendrier grégorien est étrange, car l’année qui suit 1 av. J.-C. est 1 ap. J.-C., et presque tous les logiciels, à l’exception des logiciels d’astronomie spécialisés, gèrent mal les dates hors de la plage Unix du futur proche. Même pour des choses qu’il suffirait de stocker sous forme de chaîne, comme les années de naissance et de mort de l’empereur Auguste, ce serait bien que les standards les définissent clairement

    • ISO 8601 autorise ce format s’il existe un accord mutuel. « Accord mutuel » peut sembler grandiloquent, mais il suffit d’une simple restriction du type ISO 8601 où l’on autorise à remplacer le T par un espace. RFC 3339 fait quelque chose de similaire, de façon beaucoup plus verbeuse
      Il est aussi difficile d’affirmer que 2023-09-01 15:30:59 est le format de date-heure le plus utilisé. La langue la plus utilisée est le chinois, et des séparateurs propres comme dans 2023年9月1日 y sont courants
      ISO 8601 autorise aussi, par accord mutuel, les années antérieures à 1582 ou postérieures à 9999. Si elles ne tiennent pas sur quatre chiffres, il faut les faire précéder d’un seul caractère de signe. Ces dates permettent peu de traitements réellement utiles et ne sont donc généralement pas prises en charge, mais j’ai vu un certain nombre de bibliothèques les parser, surtout lorsqu’elles étaient implémentées indépendamment de C
      00-01-01 est défini comme le 1er janvier de l’an 1 av. J.-C.. ISO 8601 précise clairement que la numérotation des années suit le calendrier grégorien proleptique (proleptic Gregorian calendar), donc elle s’extrapole jusqu’à l’infini négatif
    • Le format séparé par des espaces est bien plus lisible. Après avoir respecté le standard pendant près de 20 ans, j’ai récemment commencé à ignorer les deux au profit du meilleur format avec séparation par espaces
      Je comprends pourquoi il fallait un caractère qui ne soit pas une espace, mais on aurait au moins pu utiliser un underscore ou un point. Et comme il s’agit d’une chaîne, je ne comprends pas non plus pourquoi on a sacrifié l’universalité du format en limitant la partie année à quatre chiffres
  • Les années à 6 chiffres donnent l’impression d’être une solution à un problème qui n’arrivera pas vraiment, juste pour paraître tourné vers l’avenir. Il est impensable que la technologie actuelle ou les normes sociales actuelles durent 8000 ans

    • On n’utilise pas les ordinateurs uniquement pour des choses liées à aujourd’hui. Par exemple, si l’on lance de très longs calculs climatiques, on pourrait certes ignorer les erreurs dues aux dates, mais ce serait mieux qu’elles ne se produisent pas, non ?
    • Que ce soit 5 ou 7 chiffres, on peut utiliser n’importe quelle longueur sur laquelle les deux parties peuvent se mettre d’accord avant de commencer à communiquer. La deuxième partie du standard contient même un exemple d’année à 10 chiffres
    • Les années à 6 chiffres sont une solution à un problème qui existe déjà. Il suffit d’imaginer un géologue qui simule la dérive des continents
  • L’explication selon laquelle l’ISO 8601 utiliserait U+2010 HYPHEN et U+2212 MINUS, et qu’il faudrait utiliser U+2D HYPHEN-MINUS dans les jeux de caractères ne disposant pas de ces caractères, est incorrecte
    En réalité, l’ISO 8601 précise que si le jeu de caractères cible est basé sur ISO/IEC 646, il faut utiliser le caractère hyphen-minus dans les deux cas. Unicode en fait clairement partie. Il subsiste une légère ambiguïté, mais l’interprétation est claire pour Unicode, et cela ressemble à une manière indirecte de garantir la compatibilité avec d’autres jeux de caractères basés sur 646 en spécifiant le mappage canonique de 646

    • Le paragraphe concerné se trouve dans ISO 8601-1:2019 §3.2.1
      Il dit en substance que « tous les caractères utilisés dans les représentations de dates et d’heures appartiennent au répertoire ISO/IEC 646, à l’exception de ‘hyphen’, ‘minus’ et ‘plus-minus’. Dans les environnements utilisant un répertoire de caractères basé sur ISO/IEC 646, ‘hyphen’ et ‘minus’ doivent tous deux être mappés vers ‘hyphen-minus’ »
      Unicode étant basé sur ISO 8859, et ISO 8859 étant basé sur ISO 646, l’intention semble bien être d’utiliser U+2D hyphen-minus dans le jeu de caractères Unicode
  • Sous Windows, le deux-points étant un caractère spécial, il est souvent agaçant qu’il n’existe pas de méthode conforme à RFC 3339 pour mettre une date et une heure dans un nom de fichier
    Ce serait bien de pouvoir rester conforme à l’ISO 8601 en utilisant des traits d’union dans la date tout en omettant les deux-points. Par exemple, 20230831T1510-0500 est conforme et utilisable dans un nom de fichier, mais 2023-08-31T1510-0500 et les variantes similaires ne le sont pas. Au passage, la fonction Get-Date de PowerShell ne comprend pas le premier timestamp, sans traits d’union ni deux-points

    • Supprimer les deux-points reste sûr et ne rend pas ambiguës les dates ni les dates-heures RFC 3339. On peut toujours rétablir les deux-points sans perte
    • Je ne savais pas que Windows avait ce problème. MacOS a aussi un autre problème lié aux deux-points dans les noms de fichiers. Si deux des trois systèmes d’exploitation les plus utilisés ont ce problème, c’est clairement que la conception n’y a pas assez réfléchi
  • C’est une excellente visualisation de ce sujet
    Pour séparer la partie date de la partie heure, je préfère une espace ou un underscore à T, mais pour éviter les problèmes avec les traitements qui ne gèrent que l’ISO 8601 et par souci de cohérence, je continue généralement à utiliser T

    • Je préfère T. On ne risque pas de découper accidentellement ce genre de chaîne sur T
  • Deux choses m’intriguent. D’abord, quelle est la justification des années sur 6 chiffres ? Aucun système conçu aujourd’hui n’existera encore dans 100 000 ans, non ?
    Ensuite, l’ISO 8601 est très répandue, mais RFC 3339 est-elle aussi beaucoup utilisée et adoptée dans les systèmes réels ?

    • Vu le temps qu’il faut pour se débarrasser complètement des anciennes technologies, je ne serais pas surpris qu’on soit encore en train d’émuler x86 sur des ordinateurs quantiques dans 100 000 ans
    • Quand une bibliothèque dit prendre en charge l’ISO 8601, dans 90 % des cas elle n’implémente pas vraiment les parties les plus obscures de l’ISO 8601
    • Le package officiel time de Golang et Chrono de Rust disposent d’outils intégrés pour gérer RFC 3339, mais pas RFC 8601
      De mémoire, RFC 8601 avait des problèmes d’ambiguïté absents de RFC 3339, et je crois que Python a aussi eu pour cette raison des problèmes d’aller-retour de dates
    • Des outils scientifiques peuvent vouloir représenter des dates très lointaines dans le futur
    • Y10k (:
  • Il n’existe pas de format où le fuseau horaire est indiqué sur quatre chiffres sans deux-points, alors que date +%z renvoie ±NNNN

    • Heureusement, %:z existe. À ce sujet, on peut aussi apprendre à date à afficher cela par défaut : https://gist.github.com/d081dad407432d53172e30d0d35c39db
      $ date
      2023-08-31T11:15:00-07:00
    • ±NNNN est valide sans deux-points lorsqu’il est utilisé dans le cadre du « format de base ». Autrement dit, il ne doit y avoir ni traits d’union ni deux-points nulle part dans le format complet
      Les deux formes suivantes sont donc équivalentes et toutes deux valides :
      2023-09-01T09:40:01+08:00
      20230901T094001+0800