Como encontrar a diferença em dias entre duas datas?

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

Como encontrar a diferença em dias entre duas datas?

Se você tem date GNU, permite imprimir a representação de uma data arbitrária (opção -d ). Neste caso converta as datas para segundos desde EPOCH, subtraia e divida por 24 * 3600.

Ou você precisa de um caminho portátil?

A maneira bash – converta as datas em% y% m% d formato e então você pode fazer isso direto da linha de comando:

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

E em python

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

Cuidado! Muitas das soluções bash aqui são quebradas para intervalos de datas que abrangem a data em que o horário de verão começa (quando aplicável). Isso ocorre porque a construção $ ((math)) faz uma operação ‘floor’ / truncation no valor resultante, retornando apenas o número inteiro. Deixe-me ilustrar:

O horário de verão começou em 8 de março deste ano nos EUA, então vamos usar um intervalo de datas abrangendo:

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

Vamos ver o que conseguimos com os parênteses duplos:

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

Retorna ‘5’.

Fazer isso usando ‘bc’ com mais precisão nos dá um resultado diferente:

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

Retorna ‘5,95’ – o 0,05 ausente é a hora perdida da transição do horário de verão.

Então, como isso deve ser feito corretamente?
Eu sugeriria usar isso em vez disso:

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

Aqui, o ‘printf’ arredonda o resultado mais preciso calculado por ‘bc’, dando-nos o intervalo de datas correto de ‘6’.

Edit: destacando a resposta em um comentário de @ hank-schultz abaixo, que tenho usado ultimamente:

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

Isso também deve ser bissexto seguro, contanto que você sempre subtraia a data anterior da última, já que os segundos bissextos só adicionarão a diferença – o truncamento é efetivamente arredondado para o resultado correto.

Aqui está a versão MAC OS X para sua conveniência.

 $ 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!

Se a opção -d funciona no seu sistema, aqui está outra maneira de fazer isso. Há uma ressalva de que não levaria em conta os anos bissextos desde que eu considerei 365 dias por ano.

 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` 

Mesmo se você não tiver data do GNU, provavelmente terá o 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"; 

Isso retorna 398.041666666667 – 398 dias e uma hora devido ao horário de verão.


A questão voltou ao meu feed. Aqui está um método mais conciso usando um módulo empacotado 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 

Eu apresentaria outra solução possível em Ruby. Parece que é o menor e mais limpo até agora:

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

no unix você deve ter as datas do GNU instaladas. você não precisa se desviar do bash. Aqui está a solução de strung out considerando os dias, apenas para mostrar os passos. pode ser simplificado e estendido para datas completas.

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

Isso funciona para mim:

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

Impressões

 398 days 

O que está acontecendo?

  1. Forneça uma sequência de tempo válida em A e B
  2. Use date -d para manipular as seqüências de tempo
  3. Use a date %s para converter seqüências de tempo em segundos desde 1970 (unix epoche)
  4. Use a expansão do parâmetro bash para subtrair segundos
  5. dividir por segundos por dia (86400 = 60 * 60 * 24) para obter a diferença como dias
  6. ! DST não é levado em conta! Veja esta resposta em unix.stackexchange !

Experimente:

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

Outra versão do Python:

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

Suponha que nós rsync os backups do Oracle DB para um disco terciário manualmente. Então, queremos excluir backups antigos nesse disco. Então aqui está um pequeno 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 os dirs e o período de retenção (“30 dias”) para atender às suas necessidades.

Use as funções do shell em http://cfajohnson.com/shell/ssr/ssr-scripts.tar.gz ; eles funcionam em qualquer shell Unix padrão.

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

Veja a documentação em http://cfajohnson.com/shell/ssr/08-The-Dating-Game.shtml

Usando o 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: Somente as partes da data dos valores são usadas no cálculo

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

Isso pressupõe que um mês é 1/12 de um ano:

 #!/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 (talvez do Mac OS X yosemate),

Para obter o tempo de época (Seconds from 1970) de um arquivo e salvá-lo em um var: old_dt=`date -j -r YOUR_FILE "+%s"`

Para obter o horário atual do horário atual new_dt=`date -j "+%s"`

Para calcular a diferença acima do tempo de duas épocas (( diff = new_dt - old_dt ))

Para verificar se o diff é superior a 23 dias (( new_dt - old_dt > (23*86400) )) && echo Is more than 23 days