Les dates et l’encodage (ANSI, UTF-8, UTF-16) ont toujours été et restent des épines dans le pied des développeurs. Le bug de l’an 2000 est passé, mais nous avons tout de même subi une anomalie de date en fin d’année 2021 sur un de nos projets entre Noël et le premier de l’An. Que s’est-il passé ? Comment y remédier ? Nos conseils.
La batterie de tests unitaires automatisés en place sur le projet (avec ScalaTest – je pourrais en parler plus longuement dans un article dédié) nous a permis de réduire drastiquement les anomalies. Mais les tests restent faillibles, puisqu’ils sont écrits par des humains. En combinant des tests unitaires automatisés et des tests d’intégrations basés sur des vraies données, il est possible de réduire nettement le risque d’anomalie.
Dans notre traitement Spark, nous recevons des données CSV avec des dates que nous devons reformater. C’est évidemment une tâche récurrente sur les projets BI et Big Data.
Java : La casse de l’année
Notre application est opérationnelle depuis plusieurs mois sans incident, mais le 27 décembre 2021, nous recevons une alerte de notre client. Nous envoyons des données enrichies sur 2022 sur 2 champs dates (sur une quinzaine de dates) !
Nous n’avions pas fait de nouvelle livraison depuis plusieurs jours puisque nous étions en période de gel applicatif. Comment une anomalie pouvait-elle apparaitre du jour au lendemain sans nouvelle livraison ?
Heureusement, la source du problème a été identifiée et corrigée rapidement. Dans un de nos traitements, la transformation de l’année était indiquée en “YYYY” au lieu de “yyyy”. Une petite différence de casse, mais qui a une conséquence importante la dernière semaine de l’année !
En effet, quand on regarde la documentation Java sur les formats de date, on constate que :
- “y” donne “year” donc l’année,
- “Y” donne “Week year” donc l’année de la semaine.
NB : Spark ayant été écrit en Scala (voir mon article sur le développement en Spark et Scala des projets Big Data), la librairie se basent sur les fonctions de format de date de Scala, qui elle-même se base sur Java.
Que signifie donc “week year” (l’année de la semaine) ?
Une année est découpée en jours, en semaines, en mois, en trimestres et en semestres. Une année est composée de 2 semestres. Un semestre est composé de 2 trimestres, un trimestre de 3 mois, et un mois de 28 à 31 jours. Jusqu’ici, tout va bien.
Mais la semaine est une notion annexe qui ne rentre pas dans ces découpages. La semaine est très facile à se représenter et est pratique pour découper plus finement le temps. La norme est de dire qu’une année a 52 semaines. Or, en réalité, les 2 semaines de début et de fin d’année sont incomplètes.
Dans la Business Intelligence (BI), on veut souvent comparer des périodes identiques. Ainsi, pour pouvoir comparer les semaines d’une année sur l’autre, il est possible de récupérer le numéro de la semaine courante avec des semaines complètes. La première semaine de l’année commencera alors dès le lundi de l’année précédente lorsque le changement d’année se fait en cours de semaine.
Nos cas de tests n’avaient pas été assez couvrants sur les fonctions calculant ces 2 dates. Bien qu’ils contiennent des cas ajoutés manuellement et des cas réels, il est nécessaire, pour les dates, de rajouter les cas particuliers de début et fin d’année. Attention à bien choisir une année à cheval sur une semaine pour les tests. L’année 2024 commencera un lundi 1 janvier, c’est donc un cas à éviter pour ce genre de test.
Nos jeux de tests ont été enrichis pour prendre en compte ce cas. Nous nous servons du 27/12/2021 comme date de référence de nos tests, en rappel à la date de l’incident. Ainsi, la correction réalisée est directement validée par le nouveau cas de tests, et ils serviront aussi pour garantir une non-régression. Pour illustrer plus dynamiquement mes propos, voici un petit extrait de code Scala permettant de constater la différence de résultat entre YYYY et yyyy :
La numérotation des semaines en France
En France, officiellement, la première semaine de l’année commence avec la semaine comprenant le 4 janvier. C’est la norme ISO 8601 qui définit cette règle. Elle est utilisée par le gouvernement et les entreprises comme référence comptable.
Si vous utilisez les numéros de semaine, attention à bien définir le paramètre Locale (associé aux normes à suivre) dans votre code pour vous assurer d’avoir la bonne méthode de calcul. En précisant « France », vous aurez bien la première semaine de l’année qui commence à partir du 4 janvier. En laissant la valeur par défaut, tout dépendra de la configuration sur vos serveurs, ce qui est risqué.
Voici un nouvel extrait de code pour illustrer l’importance de la définition de la Locale :
J’espère vous avoir éclairé sur cette subtilité de casse qui peut causer des problèmes importants, surtout que celle-ci surviendra toujours au pire moment de l’année (pendant les fêtes et les congés).
Il est donc primordial de communiquer dessus, mais aussi de bien réfléchir aux tests à leurs couvertures. Notez aussi que la définition de la Locale est également importante, surtout si vous utilisez les semaines.
Lors de vos tests sur votre environnement en local, ou sur une pré-production, vous pourriez avoir des résultats différents de la production. Forcer la locale (mais aussi le timezone), c’est une garantie de résultats identiques sur tous les environnements.
Votre adresse de messagerie est uniquement utilisée par Business & Decision, responsable de traitement, aux fins de traitement de votre demande et d’envoi de toute communication de Business & Decision en relation avec votre demande uniquement. En savoir plus sur la gestion de vos données et vos droits.