J'ai un code simple, il fonctionne mais pas comme prévu. Le but principal de mon code est de diminuer la date donnée jusqu'à la date cible 2012-01-31,
Mais les résultats:
2017-10-28
2017-09-28
2017-08-28
2017-07-28
2017-06-28
2017-05-28
2017-04-28
2017-03-28
2017-02-28
2017-01-28
2016-12-28
2016-11-28
2016-10-28
2016-09-28
2016-08-28
2016-07-28
2016-06-28
2016-05-28
2016-04-28
2016-03-28
2016-02-28
2016-01-28
...
Le code:
#!/bin/bash
d=2017-10-31
while [ "$d" != 2012-01-31 ]; do
echo $d
d=$(date -I -d "$d -1 month")
done
Je souhaite vraiment les bons mois en place comme:
2017-10-31
2017-09-30
2017-08-31
2017-07-31
2017-06-30
2017-05-31
2017-04-30
2017-03-31
2017-02-28
2017-01-31
2016-12-31
2016-11-30
2016-10-31
2016-09-30
2016-08-31
2016-07-31
2016-06-30
2016-05-31
2016-04-30
2016-03-31
2016-02-29
2016-01-31
...
Comment puis-je y parvenir?
3 réponses
Il est plus facile de générer le début du mois et de faire une petite astuce pour obtenir la fin du mois sans vérifier les dates
$ d=2017-10-31; bd=$(date -I -d "$d +1 month");
while [ $d != 2012-01-31 ];
do
bd=$(date -I -d "$bd - 1 month");
d=$(date -I -d "$bd - 1 day");
echo $d;
done
2017-10-31
2017-09-30
2017-08-31
2017-07-31
...
2016-07-31
2016-06-30
2016-05-31
2016-04-30
2012-03-31
2012-02-29
2012-01-31
En supposant que votre date de début est toujours le dernier jour du mois, vous pouvez laisser date
s'occuper de compter les jours par mois si vous utilisez cet algorithme:
date = date +1 day -1 month -1 day
À savoir, retournez d'abord la date au 1er jour du mois suivant, puis soustrayez simplement un mois pour obtenir le 1er jour du mois en cours, et enfin soustrayez simplement 1 jour pour obtenir le dernier jour du mois précédent.
Par exemple:
#!/bin/bash
d=2017-10-31
while [ "$d" != 2012-01-31 ]; do
echo $d
d=$(date -I -d "$(date -I -d "$(date -I -d "$d +1 day") 1 month ago") 1 day ago")
done
Remarque 1 day ago
est utilisé à la place de -1 day
, car ce dernier peut être interprété comme un fuseau horaire par date
(gotcha connu).
Vous pouvez également définir manuellement le jour sur 01
(en utilisant l'expansion des paramètres du shell pour suppression du suffixe ${d%-*}
), puis soustrayez simplement 1 day
avec date
:
d=2017-10-31
while [ "$d" != 2012-01-31 ]; do
echo $d
d=$(date -I -d "${d%-*}-01 1 day ago")
done
La sortie est (dans les deux cas):
2017-10-31
2017-09-30
2017-08-31
2017-07-31
2017-06-30
2017-05-31
2017-04-30
...
Peut-être qu'au lieu de soustraire un mois (ce qui est notoire pour ce comportement), vous pouvez soustraire le nombre de jours du mois en cours
!/bin/bash
d=2017-10-31
while [ "$d" != 2012-01-31 ]; do
echo $d
days_in_month==$(cal $(date +"%m %Y" -d $d) | awk 'NF {DAYS = $NF}; END {print DAYS}')
d=$(date -I -d "$d $days_in_month day ago")
done
Questions connexes
De nouvelles questions
linux
LES QUESTIONS LINUX DOIVENT ÊTRE LIÉES À LA PROGRAMMATION. Utilisez cette balise uniquement si votre question concerne la programmation à l'aide d'API Linux ou un comportement spécifique à Linux, et pas uniquement parce que vous exécutez votre code sous Linux. Si vous avez besoin d'une prise en charge Linux, vous pouvez essayer https://unix.stackexchange.com ou le site Stack Exchange de la distribution Linux spécifique comme https://askubuntu.com ou https://elementaryos.stackexchange.com/