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?

0
Daniel 28 nov. 2017 à 21:09

3 réponses

Meilleure réponse

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
1
karakfa 28 nov. 2017 à 18:46

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
...
1
randomir 28 nov. 2017 à 18:58

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
1
JNevill 28 nov. 2017 à 18:33
47538235