web-dev-qa-db-fra.com

Comment trouver la différence en jours entre deux dates?

A = "2002-20-10"
B = "2003-22-11" 

Comment trouver la différence en jours entre deux dates?

64
Tree

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?

25
user332325

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) ))
52
techjacker

Et en python

$python -c "from datetime import date; print (date(2003,11,22)-date(2002,10,20)).days"
398
15
Fred Laurent

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.

14
evan_b

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!

6
nickl-

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
4
glenn jackman

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`
4
Ruchi

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?

  1. Fournir une chaîne de temps valide dans A et B 
  2. Utilisez date -d pour gérer les chaînes de temps
  3. Utilisez date %s pour convertir les chaînes de temps en secondes depuis 1970 (unix epoche)
  4. Utilisez bash paramètre expansion pour soustraire des secondes
  5. divisez par secondes par jour (86400 = 60 * 60 * 24) pour obtenir la différence en jours 
  6. ! DST n'est pas pris en compte! Voir cette réponse sous unix.stackexchange !
3
jschnasse

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
1
GreyCat

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 
1
mattymik

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

0
osexp2003

Une autre version de Python:

python -c "from datetime import date; print date(2003, 11, 22).toordinal() - date(2002, 10, 20).toordinal()"
0
Ulf

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

0
bruce

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
0
Gotxi

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])
}
0
Steven Penny

Essayez ceci:

Perl -e 'use Date::Calc qw(Delta_Days); printf "%d\n", Delta_Days(2002,10,20,2003,11,22);'
0
Dennis Williamson

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.

0
Alex Cherkas

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

0
Chris F.A. Johnson