A = "2002-20-10"
B = "2003-22-11"
Comment trouver la différence en jours entre deux dates?
Si vous avez GNU date
, cela permet d’imprimer la représentation d’une date quelconque (option -d
) . Dans ce cas, convertissez les dates en secondes depuis Epoch, soustrayez et divisez par 24 * 3600.
Ou vous avez besoin d'un moyen portable?
La méthode bash - convertissez les dates au format% y% m% d et vous pourrez le faire directement à partir de la ligne de commande
echo $(( ($(date --date="031122" +%s) - $(date --date="021020" +%s) )/(60*60*24) ))
Et en python
$python -c "from datetime import date; print (date(2003,11,22)-date(2002,10,20)).days"
398
Fais attention! La plupart des solutions bash proposées ici sont cassées pour les plages de dates qui couvrent la date du début de l'heure d'été (le cas échéant). Cela est dû au fait que la construction $ ((math)) effectue une opération de "plancher"/troncature sur la valeur résultante, en ne renvoyant que le nombre entier. Me laisser illustrer:
L’été a commencé le 8 mars aux États-Unis, utilisons donc une plage de dates couvrant les domaines suivants:
start_ts=$(date -d "2015-03-05" '+%s')
end_ts=$(date -d "2015-03-11" '+%s')
Voyons ce que nous obtenons avec les doubles parenthèses:
echo $(( ( end_ts - start_ts )/(60*60*24) ))
Retourne '5'.
Faire cela avec 'bc' avec plus de précision nous donne un résultat différent:
echo "scale=2; ( $end_ts - $start_ts )/(60*60*24)" | bc
Renvoie '5.95' - 0,05 manquant étant l'heure perdue depuis le passage à l'heure d'été.
Alors, comment cela devrait-il être fait correctement?
Je suggère d'utiliser ceci à la place:
printf "%.0f" $(echo "scale=2; ( $end_ts - $start_ts )/(60*60*24)" | bc)
Ici, "printf" arrondit le résultat plus précis calculé par "bc", nous donnant la plage de dates correcte de "6".
Edit: soulignant la réponse dans un commentaire de @ hank-schultz ci-dessous, que j’utilise depuis peu:
date_diff=$(( ($(date -d "2015-03-11 UTC" +%s) - $(date -d "2015-03-05 UTC" +%s) )/(60*60*24) ))
Cela devrait également être une valeur de seconde intercalaire aussi longtemps que vous soustrayez toujours la date la plus rapprochée de la dernière, car les secondes intercalaires ne feront qu'ajouter à la différence - la troncature arrondit effectivement le résultat correct.
Voici la version MAC OS X pour votre commodité.
$ A="2002-20-10"; B="2003-22-11";
$ echo $(((`date -jf %Y-%d-%m $B +%s` - `date -jf %Y-%d-%m $A +%s`)/86400))
nonJoy!
Même si vous n'avez pas la date GNU, Perl sera probablement installé:
use Time::Local;
sub to_Epoch {
my ($t) = @_;
my ($y, $d, $m) = ($t =~ /(\d{4})-(\d{2})-(\d{2})/);
return timelocal(0, 0, 0, $d+0, $m-1, $y-1900);
}
sub diff_days {
my ($t1, $t2) = @_;
return (abs(to_Epoch($t2) - to_Epoch($t1))) / 86400;
}
print diff_days("2002-20-10", "2003-22-11"), "\n";
Cela renvoie 398.041666666667
- 398 jours et une heure en raison de l'heure avancée.
La question est revenue sur mon flux. Voici une méthode plus concise utilisant un module Perl fourni
days=$(Perl -MDateTime -le '
sub parse_date {
@f = split /-/, shift;
return DateTime->new(year=>$f[0], month=>$f[2], day=>$f[1]);
}
print parse_date(shift)->delta_days(parse_date(shift))->in_units("days");
' $A $B)
echo $days # => 398
Si l'option -d fonctionne dans votre système, voici une autre façon de procéder. Il y a une mise en garde selon laquelle cela ne prendrait pas en compte les années bissextiles puisque j'ai pris en compte 365 jours par an.
date1yrs=`date -d "20100209" +%Y`
date1days=`date -d "20100209" +%j`
date2yrs=`date +%Y`
date2days=`date +%j`
diffyr=`expr $date2yrs - $date1yrs`
diffyr2days=`expr $diffyr \* 365`
diffdays=`expr $date2days - $date1days`
echo `expr $diffyr2days + $diffdays`
Cela fonctionne pour moi:
A="2002-10-20"
B="2003-11-22"
echo $(( ($(date -d $B +%s) - $(date -d $A +%s)) / 86400 )) days
Impressions
398 days
Qu'est-ce qui se passe?
date -d
pour gérer les chaînes de tempsdate %s
pour convertir les chaînes de temps en secondes depuis 1970 (unix epoche)Je soumettrais une autre solution possible en Ruby. On dirait que c'est le plus petit et le plus propre à ce jour:
A=2003-12-11
B=2002-10-10
DIFF=$(Ruby -rdate -e "puts Date.parse('$A') - Date.parse('$B')")
echo $DIFF
sous unix, vous devez avoir GNU dates installées. vous n'avez pas besoin de dévier de bash. voici la solution tendue depuis des jours, juste pour montrer les étapes. il peut être simplifié et étendu aux dates complètes.
DATE=$(echo `date`)
DATENOW=$(echo `date -d "$DATE" +%j`)
DATECOMING=$(echo `date -d "20131220" +%j`)
THEDAY=$(echo `expr $DATECOMING - $DATENOW`)
echo $THEDAY
Pour MacOS Sierra (peut-être de Mac OS X yosemate),
Pour obtenir l’époque (secondes de 1970) à partir d’un fichier et l’enregistrer dans un fichier var:
old_dt=`date -j -r YOUR_FILE "+%s"`
Pour obtenir l’époque de l’heure actuelle
new_dt=`date -j "+%s"`
Calculer la différence de plus de deux époques
(( diff = new_dt - old_dt ))
Pour vérifier si la différence est supérieure à 23 jours
(( new_dt - old_dt > (23*86400) )) && echo Is more than 23 days
Une autre version de Python:
python -c "from datetime import date; print date(2003, 11, 22).toordinal() - date(2002, 10, 20).toordinal()"
Utiliser la commande mysql
$ echo "select datediff('2013-06-20 18:12:54+08:00', '2013-05-30 18:12:54+08:00');" | mysql -N
Résultat: 21
REMARQUE: Seules les parties de date des valeurs sont utilisées dans le calcul.
Référence: http://dev.mysql.com/doc/refman/5.6/en/date-and-time-functions.html#function_datediff
C’est le plus simple que j’ai réussi à faire travailler sur centos 7:
OLDDATE="2018-12-31"
TODAY=$(date -d $(date +%Y-%m-%d) '+%s')
LINUXDATE=$(date -d "$OLDDATE" '+%s')
DIFFDAYS=$(( ($TODAY - $LINUXDATE) / (60*60*24) ))
echo $DIFFDAYS
Cela suppose qu'un mois correspond à 1/12 de l'année:
#!/usr/bin/awk -f
function mktm(datespec) {
split(datespec, q, "-")
return q[1] * 365.25 + q[3] * 365.25 / 12 + q[2]
}
BEGIN {
printf "%d\n", mktm(ARGV[2]) - mktm(ARGV[1])
}
Essayez ceci:
Perl -e 'use Date::Calc qw(Delta_Days); printf "%d\n", Delta_Days(2002,10,20,2003,11,22);'
Supposons que nous synchronisons manuellement les sauvegardes de la base de données Oracle sur un disque tertiaire. Ensuite, nous voulons supprimer les anciennes sauvegardes sur ce disque. Alors voici un petit script bash:
#!/bin/sh
for backup_dir in {'/backup/cmsprd/local/backupset','/backup/cmsprd/local/autobackup','/backup/cfprd/backupset','/backup/cfprd/autobackup'}
do
for f in `find $backup_dir -type d -regex '.*_.*_.*' -printf "%f\n"`
do
f2=`echo $f | sed -e 's/_//g'`
days=$(((`date "+%s"` - `date -d "${f2}" "+%s"`)/86400))
if [ $days -gt 30 ]; then
rm -rf $backup_dir/$f
fi
done
done
Modifiez le répertoire et la durée de conservation ("30 jours") en fonction de vos besoins.
Utilisez les fonctions Shell à partir de http://cfajohnson.com/Shell/ssr/ssr-scripts.tar.gz ; ils fonctionnent dans n'importe quel shell Unix standard.
date1=2012-09-22
date2=2013-01-31
. date-funcs-sh
_date2julian "$date1"
jd1=$_DATE2JULIAN
_date2julian "$date2"
echo $(( _DATE2JULIAN - jd1 ))
Voir la documentation à http://cfajohnson.com/Shell/ssr/08-The-Dating-Game.shtml