web-dev-qa-db-fra.com

`uuuu` contre` yyyy` dans les codes de modèle de formatage `DateTimeFormatter` en Java?

La documentation de la classe DateTimeFormatter indique ses codes de formatage pour l'année:

u année année 2004; 04

y l'année de l'année 2004; 04

Year: Le nombre de lettres détermine la largeur de champ minimale en dessous de laquelle le remplissage est utilisé. Si le nombre de lettres est deux, un formulaire à deux chiffres réduit est utilisé. Pour l'impression, les deux derniers chiffres les plus à droite sont générés. Pour l'analyse, cette analyse est effectuée à l'aide de la valeur de base de 2000, ce qui donne une année comprise entre 2000 et 2099 inclus. Si le nombre de lettres est inférieur à quatre (mais pas à deux), alors le signe n'est sorti que pour les années négatives, selon SignStyle.NORMAL. Sinon, le signe est généré si la largeur du pavé est dépassée, conformément à SignStyle.EXCEEDS_PAD.

Aucune autre mention de "l'époque".

Alors, quelle est la différence entre ces deux codes, u contre y, year contre year-of-era?

Quand dois-je utiliser quelque chose comme ce modèle uuuu-MM-dd et quand yyyy-MM-dd lorsque je travaille avec des dates en Java?

Semble que cet exemple de code écrit par ceux qui sont au courant utilise uuuu, mais pourquoi? 

D'autres classes de formatage, telles que l'héritage SimpleDateFormat n'ont que yyyy, je ne comprends donc pas pourquoi Java.time apporte cette uuuu pour «année de l'ère».

14
Basil Bourque

Dans le cadre de Java.time- package, nous pouvons dire:

  • Il est (il est plus sûr d'utiliser "u" au lieu de "y"} car DateTimeFormatter insistera sinon pour avoir une époque en combinaison avec "y" (= année-ère). Donc, utiliser "u" éviterait certaines exceptions imprévues dans le formatage/l'analyse strict. Voir aussi ceci SO-post . Une autre chose mineure qui est améliorée par le symbole "u" par rapport à "y" est l'impression/l'analyse des années grégoriennes négatives (dans le passé lointain).

  • Sinon, nous pouvons clairement indiquer que utiliser "u" au lieu de "y" rompt les habitudes de longue date de la programmation Java. Il n’est pas clair non plus intuitivement que "u" désigne toute sorte d’année car a) la première lettre du mot anglais "year" n’est pas en accord avec ce symbole et b) SimpleDateFormat a utilisé "u" à des fins différentes depuis Java -7 ( ISO-jour-nombre-de-semaine ). La confusion est garantie - pour toujours?

  • Nous devrions également voir que utiliser eras (symbole "G") dans le contexte de l'ISO est généralement dangereux si l'on considère les dates historiques. Si "G" est utilisé avec "u", les deux champs ne sont pas liés. Et si "G" est utilisé avec "y", le formateur est satisfait mais utilise toujours le calendrier grégorien proleptique lorsque la date historique impose différents calendriers et la gestion de la date.

Informations d'arrière-plan:

Lors du développement et de l'intégration de JSR-310 (paquets Java.time), les concepteurs ont décidé d'utiliser les spécifications CLDR/LDML comme base des symboles de modèle dans DateTimeFormatter. Le symbole "u" était déjà défini dans le CLDR comme année grégorienne proleptique. Ce sens a donc été adopté pour la nouvelle JSR-310 à venir (mais pas pour SimpleDateFormat pour des raisons de compatibilité ascendante).

Cependant, cette décision de suivre CLDR n'était pas tout à fait cohérente car JSR-310 avait également introduit de nouveaux symboles de modèle qui n'existaient pas et n'existent toujours pas dans CLDR, voir aussi cet ancien CLDR-ticket . Le symbole suggéré "I" a été modifié par CLDR en "VV" et finalement dépassé par JSR-310, y compris nouveaux symboles "x" et "X" . Mais "n" et "N" n'existent toujours pas dans CLDR, et comme cet ancien ticket est fermé, il n'est pas du tout clair si CLDR le supportera un jour au sens de JSR-310. De plus, le ticket ne mentionne pas le symbole "p" (instruction de remplissage dans JSR-310, mais non définie dans CLDR). Nous n'avons donc pas encore d'accord parfait entre les définitions de modèles de bibliothèques et de langages différents.

Et à propos de "y": il ne faut pas oublier non plus que CLDR associe cette année à au moins une sorte d’année mixte julien/grégorien et non à l’année proleptique grégorienne comme le fait la JSR-310 années négatives de côté). Donc, pas d'accord parfait entre le CLDR et la JSR-310 ici aussi.

14
Meno Hochschild

Dans la section javadoc - Modèles de formatage et d'analyse pour DateTimeFormatter, il répertorie les 3 symboles suivants:

Symbol  Meaning        Presentation  Examples
------  -------        ------------  -------
 G       era            text          AD; Anno Domini; A
 u       year           year          2004; 04
 y       year-of-era    year          2004; 04

À titre de comparaison, ces autres symboles sont assez faciles à comprendre:

 D       day-of-year    number        189
 d       day-of-month   number        10
 E       day-of-week    text          Tue; Tuesday; T

Les day-of-year, day-of-month et day-of-week sont évidemment les jour dans la portée donnée (année, mois, semaine).

Donc, year-of-era signifie le année dans la portée donnée (ère), et juste au-dessus de celui-ci, era est affiché avec un exemple de valeur de AD (l'autre valeur étant bien sûr BC).

year est l'année signée, où l'année 0 est 1 BC, l'année -1 est 2 BC et ainsi de suite.

Pour illustrer ceci: Quand Jules César a-t-il été assassiné ?

  • 15 mars 44 av. JC (à l'aide du modèle MMMM d, y GG)
  • 15 mars -43 (en utilisant le modèle MMMM d, u)

La distinction n'aura bien entendu d'importance que si l'année est nulle ou négative, et comme c'est rare, la plupart des gens s'en moquent, même s'ils le devraient.

Conclusion: Si vous utilisez y, vous devez également utiliser G. Puisque G est rarement utilisé, le symbole de l'année correcte est u et non pas y; sinon, une année non positive s'affichera de manière incorrecte.

Ceci est appelé programmation défensive :

La programmation défensive est une forme de conception défensive destinée à assurer la continuité du fonctionnement d'un logiciel dans des circonstances imprévues.


Notez que DateTimeFormatter est compatible avec SimpleDateFormat :

Letter  Date or Time Component  Presentation  Examples
------  ----------------------  ------------  --------
G       Era designator          Text          AD
y       Year                    Year          1996; 96

Les années négatives ont toujours été un problème, et ils l'ont maintenant corrigé en ajoutant u.

12
Andreas

Longue histoire courte

  1. Dans 99% des cas, vous pouvez lancer une pièce, peu importe si vous utilisez yyyy ou uuuu (ou si vous utilisez yy ou uu pour une année à deux chiffres).
  2. Cela dépend de ce que vous voulez faire au cas où un an plus tôt que 1 CE (1 AD) se produit. Le fait est que dans 99% des programmes, une telle année ne se produira jamais.

Deux autres réponses ont déjà présenté les faits sur la façon dont u et y fonctionnent très bien, mais je sentais toujours qu'il manquait quelque chose. Je contribue donc à la réponse légèrement plus basée sur l'opinion.

Pour le formatage

En supposant que vous ne vous attendiez pas à formater un an avant 1 CE, la meilleure chose à faire est de vérifier cette hypothèse et de réagir de manière appropriée en cas de rupture. Par exemple, en fonction des circonstances et des exigences, vous pouvez imprimer un message d'erreur ou émettre une exception. Un chemin de défaillance très souple pourrait être d’utiliser un modèle avec y (année d’ère) et G (époque) dans ce cas, et un modèle avec u ou y dans le cas normal de l’époque actuelle. Notez que si vous imprimez la date du jour ou la date à laquelle votre programme a été compilé, vous pouvez être sûr qu’il se trouve à l’époque commune et choisir d’ignorer le chèque.

Pour l'analyse

Dans de nombreux cas (la plupart?), L'analyse signifie également la validation, ce qui signifie que vous n'avez aucune garantie quant à l'apparence de votre chaîne d'entrée. En général, cela provient de l'utilisateur ou d'un autre système. Un exemple: une chaîne de date vient comme 2018-09-29. Ici, le choix entre uuuu et yyyy devrait dépendre de ce que vous voulez que se produise si la chaîne contient une année nulle ou négative (par exemple, 0000-08-17 ou -012-11-13). En supposant qu'il s'agisse d'une erreur, la réponse immédiate est: utilisez yyyy afin qu'une exception soit levée dans ce cas. Encore plus fin: utilisez uuuu et après l'analyse, effectuez un contrôle de plage de la date analysée. Cette dernière approche permet à la fois une validation plus fine et un meilleur message d'erreur en cas d'erreur de validation.

Cas spécial (déjà mentionné par Meno Hochschild): Si votre formateur utilise un style de résolveur strict et contient y sans G, l'analyse va toujours échouer car à proprement parler, année d'époque est ambiguë sans époque: 1950 pourrait signifier 1950 ou 1950 avant notre ère. (1950 av. J.-C.). Donc, dans ce cas, vous avez besoin de u (ou de fournir une ère par défaut, ceci est possible via une DateTimeFormatterBuilder).

Longue histoire courte encore

Il est préférable de vérifier vos dates, en particulier vos années, de manière explicite, plutôt que de vous fier au choix entre uuuu et yyyy pour capturer des années inattendues.

1
Ole V.V.