web-dev-qa-db-fra.com

Obtenez la date d'hier en bash sur Linux, DST-safe

J'ai un script Shell qui fonctionne sur Linux et utilise cet appel pour obtenir la date d'hier au format YYYY-MM-DD:

date -d "1 day ago" '+%Y-%m-%d'

Cela fonctionne la plupart du temps, mais lorsque le script a été exécuté hier matin à 2013-03-11 0:35 CDT, il a renvoyé "2013-03-09" au lieu de "2013-03-10".

L'heure d'été (qui a commencé hier) est probablement à blâmer. Je suppose que la façon dont "1 day ago" est mis en œuvre est soustraite 24 heures et 24 heures avant que 2013-03-11 0:35 CDT soit 2013-03-09 23:35 CST, ce qui conduit au résultat de "2013-03-09".

Alors, quel est le bon moyen de vérifier la date d'hier avec Linux?

124
Ike Walker

Je pense que cela devrait fonctionner, peu importe la fréquence et quand vous le lancez ... 

date -d "yesterday 13:00" '+%Y-%m-%d'
203
tink

Bash sous Mac OSX est légèrement différent.

Pour hier

echo `date -v-1d +%F`

Pour la semaine dernière

echo `date -v-1w +%F`
42
Aries

Cela devrait aussi marcher, mais c'est peut-être trop:

date -d @$(( $(date +"%s") - 86400)) +"%Y-%m-%d"
11
perreal

Si vous êtes certain que le script s'exécute dans les premières heures de la journée, vous pouvez simplement le faire.

  date -d "12 hours ago" '+%Y-%m-%d'

En passant, si le script fonctionne quotidiennement à 00h35 (via crontab?), Vous devez vous demander ce qui se passera si un changement d'heure d'été tombe dans cette heure; le script n'a pas pu être exécuté ou exécuté deux fois dans certains cas. Les implémentations modernes de cron sont assez intelligentes à cet égard, cependant.

4
leonbloy

Voici une solution qui fonctionnera également avec Solaris et AIX.

Il est possible de manipuler le fuseau horaire pour modifier l’horloge de quelques heures .

Vous êtes sûr qu'hier, c'est il y a 20 ou 30 heures. Laquelle? Eh bien, le plus récent n'est pas aujourd'hui.

echo -e "$(TZ=GMT+30 date +%Y-%m-%d)\n$(TZ=GMT+20 date +%Y-%m-%d)" | grep -v $(date +%Y-%m-%d) | tail -1

Le paramètre -e utilisé dans la commande echo est nécessaire avec bash, mais ne fonctionnera pas avec ksh . Dans ksh, vous pouvez utiliser la même commande sans l'indicateur -e.

Lorsque votre script sera utilisé dans différents environnements, vous pouvez le démarrer avec #!/Bin/ksh ou #!/Bin/bash. Vous pouvez également remplacer le\n par une nouvelle ligne:

echo "$(TZ=GMT+30 date +%Y-%m-%d)
$(TZ=GMT+20 date +%Y-%m-%d)" | grep -v $(date +%Y-%m-%d) | tail -1
3
Walter A

vous pouvez utiliser

date -d "30 days ago" +"%d/%m/%Y"

pour obtenir la date d'il y a 30 jours, vous pouvez également remplacer 30 par x nombre de jours

2
Dan Pickard

Utilisez juste date et des secondes fiables:

Comme vous l'avez fait remarquer à juste titre, de nombreux détails sur le calcul sous-jacent sont masqués si vous utilisez l'arithmétique du temps anglais. Par exemple. -d yesterday et -d 1 day ago auront un comportement différent.

Au lieu de cela, vous pouvez compter de manière fiable sur les secondes (documentées avec précision) depuis l’Unix Epoch UTC et sur l’arithmétique de base pour obtenir le moment souhaité:

date -d @$(( $(date +"%s") - 24*3600)) +"%Y-%m-%d"

Cela a été souligné dans un autre réponse . Ce formulaire est plus portable sur toutes les plates-formes avec différents indicateurs de ligne de commande date, est indépendant de la langue (par exemple, "hier" et "hier" en français), et franchement (à long terme) sera plus facile à mémoriser, car bon, tu le sais déjà. Vous pourriez autrement continuer à vous demander: "était-ce encore -d 2 hours ago ou -d 2 hour ago?" ou "Est-ce que c'est -d yesterday ou -d 1 day ago que je veux?"). Le seul élément délicat ici est le @.

Armé de bash et de rien d'autre:

Bash uniquement sur bash, vous pouvez également obtenir l'heure d'hier, via le script printf intégré:

 %(datefmt)T
     causes printf to output the date-time string resulting from using
     datefmt as a format string for strftime(3).  The  corresponding  argu‐
     ment  is an integer representing the number of seconds since the
     Epoch.  Two special argument values may be used: -1 represents the
     current time, and -2 represents the time the Shell was invoked.
     If no argument is specified, conversion behaves as if -1 had
     been  given.
     This is an exception to the usual printf behavior.

Alors,

# inner printf gets you the current unix time in seconds
# outer printf spits it out according to the format
printf "%(%Y-%m-%d)T\n" $(( $(printf "%(%s)T" -1) - 24*3600 ))

ou, de manière équivalente à une variable temp (sous-shell externe facultatif, mais conserve l'environnement vars propre). 

(
  now=$(printf "%(%s)T" -1);
  printf "%(%Y-%m-%d)T\n" $((now - 24*3600));
)

Remarque: malgré la page de manuel indiquant qu'aucun argument pour le formateur %()T assumera un -1 par défaut, il semblerait que j'obtienne un 0 (merci, version de bash manuel 4.3.48)}

0
init_js