jeudu 15 janvier 2026
Prenons ce petit fichier HTML :
<!DOCTYPE html><html><head><meta charset="utf-8><title></title></head><body><b>jeudi 01 janvier 2026</b><textarea name='0' rows='3' cols='75></textarea><b>vendredi 02 janvier 2026</b><textarea name='1' rows='3' cols='75></textarea><b>samedi 03 janvier 2026</b></body></html>
Dans un navigateur, Firefox dans mon cas, on obtient ceci
jeudi 01 janvier 2026 vendredi 02 janvier 2026 samedi 03 janvier 2026Sous chaque date on dispose d'une plage de saisie dans laquelle on peut ajouter, modifier ou supprimer du texte. Ensuite il suffit d'enregistrer le fichier, les modifications seront conservées.
L'inconvénient c'est qu'il faut écrire toutes les dates souhaitées et le code HTML qui va avec.
Le code an.c est un petit programme qui prend pour argument un entier, l'année (e.g. an 2026) et produit un fichier html comme celui du paragraphe précédent pour tous les jours de l'année, chaque date est suivie de sa plage de saisie.
Toute honte bue, je dois avouer qu'au départ j'avais oublié l'existence du tag <textarea> si bien que je m'étais fendu d'un programme en C et Gtk4 que j'avais nommé plan dont le fichier source est là plan.c.
Comme ci dessus je préparais un fichier ne comprenant que les dates de l'année comme suit (sans les textarea, donc) :
<body><h3 id="0>jeudi 01 janvier 20026</h3><h3 id="1>vendredi 02 janvier 2026</h3>...<h3 id="364>jeudi 31 décembre 20026</h3></body>
Merci à chatGPT pour la partie Gtk4.
Mon petit progrmme se lancait avec pour argument jj ou jj/mm ou jj//mm/yy qui est la date pour laquelle on veut éditer les informations. (Il prend le mois courant et/ou l'année courante si la date n'est pas complète.)
Il affiche alors une fenêtre comme ci-contre. Elle contient les informations déjà présentes pour la date considérée s'il y en a.
Une fois l'édition terminée, on clique sur le bouton OK pour enregistrer les modifications ou sur Cancel pour annuler.
La raison qui m'a amené à rédiger ce paragraphe peu glorieux, est que pour l'occasion j'avais codé une «librairie» que j'exposerai au paragraphe suivant.
Le module time.h m'énerve.
Dans la struct tm les jours du mois sont comptés de 1 à 31 mais les mois de 0 à 11. C'est d'une incohérence ! L'année à partir de 1900, mais la fonction time renvoie un entier long en secondes (pourquoi pas des nano secondes ?) mais à partir 1970. On perd son time à ajouter 126, ou 1 ou à les retrancher.
Si on veut utiliser le tm_wday ou tm_yday il ne faut pas négliger de faire un mktime. On perd aussi son temps dans les conversions entre les struct tm et time_t.
Depuis le temps que je me disais qu'il fallait faire une module pour les dates sans s'emmerder avec les heures d'hiver et d'été, sans diviser par 3600*24.
Voilà qui est fait cf. Day.h et Day.c.
Pour l'écrire je me suis inspiré des sources de python 3.14.
Voici l'interface Day.h :
#ifndef _MRD_DAY_H_#define _MRD_DAY_H_#include <stdlib.h>#include <stdio.h>#include <assert.h>/**month day d ∈ [1, 31] or d ∈ [1, 30] or less for februarymontt m ∈ [1, 12]year y the full year*/typedef struct Day {int d, m, y;} Day_t;/**Giving a string "" , "d", "d/m", "d/m/y" Day(s) sets a Day_tDay("") is todayUses the current data as defaults*/Day_t Day(char *);/**like tm_yday or toordinal in pythonReturns the ordinal of the day in its year*/int Day_yday(Day_t day);/*The converse of Day_yday*/Day_t Day_from_yday(int, int);/**European string i.e. 'full day' 'day of the month' 'full month' 'full year'e.g. 'Sunday 25 january 2026'One can change it in the source Day.c*/char * Day_Str(Day_t, char*);/**Day_str(day, s) => s = "25/01/2026"puts in s a kind of toStringOne can change the line strftime for his standard*/char * Day_str(Day_t day, char* s);#endif
Day_t est la surcouche de struct tm de C. struct Day un buffer (char buf[64]) pour avoir les fonctions Day_str et Day_Str plus commodes, mais ça prend de la place. Day_yday() et Day_from_yday() sont prévues pour effectuer des calculs sur les dates, bien que C accepte des "40/12/2026" et convertisse le dépassement. Et voilà mon petit programme pour tester ce code :
#include "Day.h"#include <locale.h>#include <string.h>// Ansi : Cyan, Rouge et Normaal#define C "\e[0;36m"#define R "\e[0;31m"#define N "\e[m"int main(int argc, char *argv[]){setlocale(LC_TIME, "");char buf[128] = {0};int n;puts("\nEnter a day : '' | 'd' | 'd/m' | 'd/m/Y' or Ctrl-D to quit");while(printf("\n%sfgets(buf, 128, stdin)%s >\t\t", C, N) &&fgets(buf, 128, stdin)) {Day_t day = Day(buf);printf("Short day string %sDay_str()%s:\t\t%s\n",C, N, Day_str(day, buf));printf("Full day string %sDay_Str()%s:\t\t%s\n",C, N, Day_Str(day, buf));printf("Ordinal Day_yday :\t\t\t%s%d%s\n",R, n = Day_yday(day), N);Day_t jour = Day_from_yday(n, day.y);printf("Recover this day from its ordinal(%s%d%s),\n",R, n, N);printf("%sDay_from_yday()%s:\t\t\t%s\n",C, N, Day_str(day, buf));printf("Let's check its ordinal:\t\t%s%d%s\n",R, n = Day_yday(jour), N);}}
J'ai surtout voulu tester que Day_yday et Day_from_yday fonctionnaient bien.