¿Cómo encontrar la diferencia en días entre dos fechas?

A = “2002-20-10”
B = “2003-22-11”

¿Cómo encontrar la diferencia en días entre dos fechas?

Si tiene date GNU, le permite imprimir la representación de una fecha arbitraria (opción -d ). En este caso convierta las fechas en segundos desde EPOCH, reste y divida por 24 * 3600.

¿O necesitas una forma portátil?

La forma bash: convierta las fechas en formato% y% m% d y luego puede hacerlo directamente desde la línea de comando:

 echo $(( ($(date --date="031122" +%s) - $(date --date="021020" +%s) )/(60*60*24) )) 

Y en python

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

¡Cuidado! Muchas de las soluciones bash aquí están rotas para rangos de fechas que abarcan la fecha en que comienza el horario de verano (cuando corresponda). Esto se debe a que el constructo $ ((math)) realiza una operación de “piso” / truncamiento en el valor resultante, devolviendo solo el número entero. Déjame ilustrar:

El horario de verano comenzó el 8 de marzo de este año en los EE. UU., Así que usemos un intervalo de fechas que abarque todo lo siguiente:

 start_ts=$(date -d "2015-03-05" '+%s') end_ts=$(date -d "2015-03-11" '+%s') 

Veamos qué obtenemos con el doble paréntesis:

 echo $(( ( end_ts - start_ts )/(60*60*24) )) 

Devuelve ‘5’.

Hacer esto usando ‘bc’ con más precisión nos da un resultado diferente:

 echo "scale=2; ( $end_ts - $start_ts )/(60*60*24)" | bc 

Devuelve ‘5.95’ – la falta de 0.05 es la hora perdida del cambio de horario de verano.

Entonces, ¿cómo debe hacerse esto correctamente?
Sugeriría usar esto en su lugar:

 printf "%.0f" $(echo "scale=2; ( $end_ts - $start_ts )/(60*60*24)" | bc) 

Aquí, el ‘printf’ redondea el resultado más preciso calculado por ‘bc’, lo que nos da el intervalo de fechas correcto de ‘6’.

Editar: resaltando la respuesta en un comentario de @ hank-schultz a continuación, que he estado usando últimamente:

 date_diff=$(( ($(date -d "2015-03-11 UTC" +%s) - $(date -d "2015-03-05 UTC" +%s) )/(60*60*24) )) 

Esto también debería ser un segundo seguro siempre que restas siempre la fecha anterior de la anterior, ya que los segundos intercalares sólo se sumn a la diferencia: el truncamiento redondea de manera efectiva al resultado correcto.

Aquí está la versión MAC OS X para su conveniencia.

 $ A="2002-20-10"; B="2003-22-11"; $ echo $(((`date -jf %Y-%d-%m $B +%s` - `date -jf %Y-%d-%m $A +%s`)/86400)) 

nJoy!

Si la opción -d funciona en su sistema, aquí hay otra forma de hacerlo. Hay una advertencia de que no tendría en cuenta los años bisiestos, ya que he considerado 365 días por año.

 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` 

Incluso si no tiene fecha GNU, probablemente tenga Perl instalado:

 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"; 

Esto devuelve 398.041666666667 – 398 días y una hora debido a los ahorros de luz diurna.


La pregunta volvió a mi alimentación. Aquí hay un método más conciso que usa un módulo integrado de Perl

 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 

Enviaría otra solución posible en Ruby. Parece que es el más pequeño y el más limpio hasta ahora:

 A=2003-12-11 B=2002-10-10 DIFF=$(ruby -rdate -e "puts Date.parse('$A') - Date.parse('$B')") echo $DIFF 

en Unix debe tener instaladas las fechas de GNU. no es necesario que te desvíes de bash. esta es la solución más complicada considerando días, solo para mostrar los pasos. se puede simplificar y extender a fechas completas.

 DATE=$(echo `date`) DATENOW=$(echo `date -d "$DATE" +%j`) DATECOMING=$(echo `date -d "20131220" +%j`) THEDAY=$(echo `expr $DATECOMING - $DATENOW`) echo $THEDAY 

Esto funciona para mí:

 A="2002-10-20" B="2003-11-22" echo $(( (`date -d $B +%s` - `date -d $A +%s`) / 86400 )) days 

Huellas dactilares

 398 days 

¿Que esta pasando?

  1. Proporcione una cadena de tiempo válida en A y B
  2. Use la date -d para manejar cadenas de tiempo
  3. Use la date %s para convertir cadenas de tiempo en segundos desde 1970 (unix epoche)
  4. Utilice la expansión del parámetro bash para restar segundos
  5. divida por segundos por día (86400 = 60 * 60 * 24) para obtener la diferencia en días
  6. ! ¡DST no se tiene en cuenta! ¡Vea esta respuesta en unix.stackexchange !

Prueba esto:

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

Otra versión de Python:

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

Supongamos que sincronizamos las copias de seguridad de Oracle DB a un disco terciario de forma manual. Entonces queremos eliminar copias de seguridad antiguas en ese disco. Así que aquí hay un pequeño 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 

Modifique los directorios y el período de retención (“30 días”) para satisfacer sus necesidades.

Use las funciones de shell de http://cfajohnson.com/shell/ssr/ssr-scripts.tar.gz ; funcionan en cualquier shell estándar de Unix.

 date1=2012-09-22 date2=2013-01-31 . date-funcs-sh _date2julian "$date1" jd1=$_DATE2JULIAN _date2julian "$date2" echo $(( _DATE2JULIAN - jd1 )) 

Consulte la documentación en http://cfajohnson.com/shell/ssr/08-The-Dating-Game.shtml

Usando el comando mysql

 $ echo "select datediff('2013-06-20 18:12:54+08:00', '2013-05-30 18:12:54+08:00');" | mysql -N 

Resultado: 21

NOTA: solo la fecha en que se usan las partes de los valores en el cálculo

Referencia: http://dev.mysql.com/doc/refman/5.6/en/date-and-time-functions.html#function_datediff

Esto supone que un mes es 1/12 de un año:

 #!/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]) } 

Para MacOS sierra (tal vez de Mac OS X yosemate),

Para obtener el tiempo de época (Segundos de 1970) de un archivo, y guardarlo en var: old_dt=`date -j -r YOUR_FILE "+%s"`

Para obtener la hora de época actual new_dt=`date -j "+%s"`

Para calcular la diferencia de los dos tiempos anteriores (( diff = new_dt - old_dt ))

Para verificar si diff es más de 23 días (( new_dt - old_dt > (23*86400) )) && echo Is more than 23 days