A = "2002-20-10"
B = "2003-22-11"
¿Cómo encontrar la diferencia de días entre dos fechas?
A = "2002-20-10"
B = "2003-22-11"
¿Cómo encontrar la diferencia de días entre dos fechas?
Respuestas:
Si tiene GNU date
, permite imprimir la representación de una fecha arbitraria ( -d
opción). En este caso, convierta las fechas a segundos desde EPOCH, reste y divida por 24 * 3600.
¿O necesitas una forma portátil?
echo "( `date -d $B +%s` - `date -d $A +%s`) / (24*3600)" | bc -l
El método bash: convierta las fechas en el 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%m%d
formato. Por ejemplo, gnu date aceptará el %Y-%m-%d
formato que utilizó el OP. En general, ISO-8601 es una buena opción (y el formato de OP es uno de esos formatos). Es mejor evitar los formatos con años de 2 dígitos.
days_diff=$(( (`date -d $B +%s` - `date -d "00:00" +%s`) / (24*3600) ))
. tenga en cuenta que $days_diff
será un número entero (es decir, sin decimales)
date
instalado. Funciona para GNU date
. No funciona con POSIX date
. Probablemente esto no sea un problema para la mayoría de los lectores, pero vale la pena señalarlo.
%Y-%m-%d
, hasta que lo presentamos August 2.0
y October 2.0
el formato de OP es %Y-%d-%m
. Relevante xkcd: xkcd.com/1179
tl; dr
date_diff=$(( ($(date -d "2015-03-11 UTC" +%s) - $(date -d "2015-03-05 UTC" +%s)) / (60*60*24) ))
¡Cuidado! Muchas de las soluciones bash aquí están divididas para rangos de fechas que abarcan la fecha en que comienza el horario de verano (cuando corresponda). Esto se debe a que la construcción $ ((matemáticas)) realiza una operación de 'piso' / truncamiento en el valor resultante, devolviendo solo el número entero. Déjame ilustrarte:
El horario de verano comenzó el 8 de marzo de este año en los EE. UU., Así que usemos un rango de fechas que abarque eso:
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'; el 0,05 que falta es la hora perdida del cambio de horario de verano.
Entonces, ¿cómo se debe hacer esto correctamente?
Sugeriría usar esto en su lugar:
printf "%.0f" $(echo "scale=2; ( $end_ts - $start_ts )/(60*60*24)" | bc)
Aquí, 'printf' redondea el resultado más preciso calculado por 'bc', lo que nos da el rango 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 intercalar seguro siempre que reste siempre la fecha anterior de la última, ya que los segundos intercalares solo aumentarán la diferencia: el truncamiento se redondea efectivamente al resultado correcto.
echo $(( ($(date --date="2015-03-11 UTC" +%s) - $(date --date="2015-03-05 UTC" +%s) )/(60*60*24) ))
que devuelve 6, en lugar de 5.
Y en pitón
$python -c "from datetime import date; print (date(2003,11,22)-date(2002,10,20)).days"
398
bash
y shell
, así que creo que podemos asumir que estamos hablando de un sistema * nix. Dentro de tales sistemas, echo
y date
están presentes de manera confiable, pero Python no lo está.
Esto funciona para mi:
A="2002-10-20"
B="2003-11-22"
echo $(( ($(date -d $B +%s) - $(date -d $A +%s)) / 86400 )) days
Huellas dactilares
398 days
¿Qué está pasando?
date -d
para manejar cadenas de tiempodate %s
para convertir cadenas de tiempo a segundos desde 1970 (unix epoche)Si la opción -d funciona en su sistema, aquí hay otra forma de hacerlo. Hay una advertencia de que no daría cuenta de los años bisiestos, ya que he considerado 365 días al 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`
Aquí está la versión de 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!
A="2002-20-10"; B="2003-22-11"
echo $(((`date -jf "%Y-%d-%m" "$B" +%s` - `date -jf "%Y-%d-%m" "$A" +%s`)/86400))
, es decir, envolver ambos formatos y variables en comillas dobles, de lo contrario puede fallar en diferente formato de fecha (por ejemplo, %b %d, %Y
/ Jul 5, 2017
)
Incluso si no tiene la fecha de 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 regresa 398.041666666667
: 398 días y una hora debido al horario de verano.
La pregunta volvió a aparecer en mi feed. Aquí hay un método más conciso usando un módulo incluido 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
Aquí está mi enfoque de trabajo usando zsh. Probado en OSX:
# Calculation dates
## A random old date
START_DATE="2015-11-15"
## Today's date
TODAY=$(date +%Y-%m-%d)
# Import zsh date mod
zmodload zsh/datetime
# Calculate number of days
DIFF=$(( ( $(strftime -r %Y-%m-%d $TODAY) - $(strftime -r %Y-%m-%d $START_DATE) ) / 86400 ))
echo "Your value: " $DIFF
Resultado:
Your value: 1577
Básicamente, usamos strftime
la -r
función reverse ( ) para transformar nuestra cadena de fecha nuevamente en una marca de tiempo, luego hacemos nuestro cálculo.
Presentaría otra posible solución 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
date
o algún lenguaje de programación) y honestamente creo que Ruby es una buena forma de hacerlo. Esta solución es muy corta y no utiliza bibliotecas no estándar ni otras dependencias. De hecho, creo que hay más posibilidades de tener Ruby instalado que de tener GNU date instalado.
Utilice 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 las partes de la fecha de los valores se utilizan en el cálculo
Referencia: http://dev.mysql.com/doc/refman/5.6/en/date-and-time-functions.html#function_datediff
en Unix debería tener instaladas las fechas GNU. no es necesario que se desvíe de bash. aquí está la solución encadenada considerando días, solo para mostrar los pasos. se puede simplificar y ampliar 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 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])
}
Prueba esto:
perl -e 'use Date::Calc qw(Delta_Days); printf "%d\n", Delta_Days(2002,10,20,2003,11,22);'
Supongamos que sincronizamos manualmente las copias de seguridad de la base de datos de Oracle en un disco terciario. Entonces queremos eliminar las copias de seguridad antiguas en ese disco. Así que aquí hay un pequeño script de 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 adaptarlos a sus necesidades.
Para MacOS sierra (tal vez de Mac OS X yosemate),
Para obtener el tiempo de época (segundos desde 1970) de un archivo y guardarlo en una var:
old_dt=`date -j -r YOUR_FILE "+%s"`
Para obtener el tiempo de época del tiempo actual
new_dt=`date -j "+%s"`
Para calcular la diferencia del tiempo de dos épocas anteriores
(( diff = new_dt - old_dt ))
Para comprobar si la diferencia es superior a 23 días
(( new_dt - old_dt > (23*86400) )) && echo Is more than 23 days
echo $(date +%d/%h/%y) date_today
echo " The other date is 1970/01/01"
TODAY_DATE="1970-01-01"
BEFORE_DATE=$(date +%d%h%y)
echo "THE DIFFERNS IS " $(( ($(date -d $BEFORE_DATE +%s) - $(date -d $TODAY_DATE +%s)) )) SECOUND
Úselo para obtener su fecha de hoy y su segundo desde la fecha que desea. si lo quieres con días solo divídelo con 86400
echo $(date +%d/%h/%y) date_today
echo " The other date is 1970/01/01"
TODAY_DATE="1970-01-01"
BEFORE_DATE=$(date +%d%h%y)
echo "THE DIFFERNS IS " $(( ($(date -d $BEFORE_DATE +%s) - $(date -d $TODAY_DATE +%s))/ 86400)) SECOUND