Description
S’il est une chose que, pour l’instant et nativement, le SSG Hugo n’est pas capable de fournir, c’est bien le numéro d’une semaine d’année.
Pourtant le langage Go fournit la méthode IsoWeek(). Mais ce n’est pas implémentée dans Hugo, c’est “en cours de réflexion” !
Trouver le numéro de semaine répond à un besoin, certes peu courant, mais utile. Admettons que vous créez une newsletter hebdomadaire ;)
Je vais vous présenter deux méthodes différentes :
- la fonction
getIsoWeek - celle nommée
getWeekNumber
getisoweek
Dans un premier temps, création d’un modèle partial : /func/getIsoWeek
Voici le code :
{{- $date := time . -}}
{{- $weekday := $date.Weekday }}
{{/* 1. Normalize Weekday (Mon=1 ... Sun=7) */}}
{{- $isoDay := cond (eq $weekday 0) 7 (int $weekday) -}}
{{/* 2. Find Thursday (ISO Week belongs to the year of its Thursday) */}}
{{- $offset := sub 4 $isoDay -}}
{{- $thursday := $date.AddDate 0 0 $offset -}}
{{/* 3. Calculate Week Number */}}
{{- $isoYear := $thursday.Year -}}
{{- $isoWeek := add (div (sub $thursday.YearDay 1) 7) 1 -}}
{{/* 4. Return the data */}}
{{- $str := dict "week" (printf "%02d" $isoWeek) "year" (printf "%04d" $isoYear) -}}
{{- $data := dict "week" $isoWeek "year" $isoYear "str" $str -}}
{{- return $data -}}
L’appel se faisant :
{{- partial "func/getisoweek" .Date -}}
Ou toute autre variable faisant appel à Time, tel que now.
⇒ Remarquez l’appel à la “fonction” getIsoWeek :
- si je veux les valeurs en entier de la semaine et l’année, j’appele
$data.weeket$data.year - si je veux les valeurs en chaîne de caractères, j’appele
$data.str.weeket$data.str.year
Personnellement, j’ai en plus crée un modèle partial nommé utils/formatIsoDate
dont le code est le suivant :
{{- $data := partial "func/getIsoWeek" . -}}
{{- return (printf "w%02d-y%04d" $data.week $data.year) -}}
Et que je peux ainsi appeler soit depuis le fichier default.md dans l’archetypes,
soit ailleurs dans les modèles ou les shortcodes, selon l’envie, tels :
{{ partial "utils/formatIsoDate" .Date }} ou {{ partial "utils/formatIsoDate" now }}.
getweeknumber
Cette deuxième manière d’obtenir le numéro de semaine est un peu plus ardu !
Cette fois-ci, j’ai deux fichiers principaux.
⇒ le premier nommé func/splitNameYMO a pour fonction “d’éclater” une date
normée (AAAA-MM-DD) en jour, mois, année correspondants et de retourner
un dictionnaire.
{{- $str := split . "-" -}}
{{- $d = (int (index $str 2)) -}}
{{- $m = (int (index $str 1)) -}}
{{- $y = (int (index $str 0)) -}}
{{- return (dict "day" $d "month" $m "year" $y) -}}
Si j’ai créé ce fichier, c’est parce qu’au-travers de mon code, je le réutilise souvent…
⇒ le deuxième fichier est la fonction primordiale, nommé func/getWeekNumber
{{- $date := "" -}}
{{- $tz := site.Params.timeZone -}}
{{- $week := 0 -}}
{{ $type := printf "%T" . }}
{{ if eq $type "string" }}
{{- $data := partial "func/splitNameYMO" . }}
{{- $date = time (printf "%04d-%02d-%02d" $data.year $data.month $data.day) $tz -}}
{{ else }}
{{- $date = time . $tz -}}
{{- end -}}
{{/* Calcul 'doy: day of the year', 'dow: day of the week' */}}
{{- $doy := $date.YearDay -}}
{{- $dow := int $date.Weekday -}}
{{- $year := $date.Year -}}
{{/* calcul week number */}}
{{- $week = div (add (sub $doy $dow) 10) 7 -}}
{{- if eq $dow 0 -}}
{{- $week = sub $week 1 -}}
{{- end -}}
{{- $str := dict "week" (printf "%02d" $week) "year" (printf "%04d" $year) -}}
{{- $data := dict "week" $week "year" $year "str" $str -}}
{{- return $data -}}
Explications :
-
En premier lieu, je cherche à savoir de quel type est la valeur que j’injecte dans l’appel du fichier, si c’est une
stringou autre chose, en l’occurence une valeur de temps — gardez à l’esprit que Hugo ne sait pas annoncer un type de valeur pour une valeur de temps, néanmoins dans le référentiel, elle est définie àTime.time. -
Ensuite, je cherche à quel jour de l’année correspond la date (
$doy), quelle est correspondance du jour dans la semaine ($dow) et pour finir l’année, bien-sûr. -
Le calcul du numéro de semaine est connu :
- il faut soustraire le jour de la semaine au jour de l’année
- ajouter l’entier
10 - et diviser le tout par
7. - et pour finir si le jour de la semaine est un dimanche, je soustrais
1au numéro de semaine trouvé — c’est relatif à Hugo, dont les semaines commencent le dimanche.
Voilà deux manières différentes de faire la même chose : une recherche de numéro de semaine !