How to find the difference in days between two dates?

匿名 (未验证) 提交于 2019-12-03 08:33:39

问题:

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

How to find the difference in days between two dates?

回答1:

If you have GNU date, it allows to print the representation of an arbitrary date (-d option). In this case convert the dates to seconds since EPOCH, subtract and divide by 24*3600.

Or you need a portable way?



回答2:

The bash way - convert the dates into %y%m%d format and then you can do this straight from the command line:

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


回答3:

And in python

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


回答4:

Watch out! Many of the bash solutions here are broken for date ranges which span the date when daylight savings time begins (where applicable). This is because the $(( math )) construct does a 'floor'/truncation operation on the resulting value, returning only the whole number. Let me illustrate:

DST started March 8th this year in the US, so let's use a date range spanning that:

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

Let's see what we get with the double parentheses:

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

Returns '5'.

Doing this using 'bc' with more accuracy gives us a different result:

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

Returns '5.95' - the missing 0.05 being the lost hour from the DST switchover.

So how should this be done correctly?
I would suggest using this instead:

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

Here, the 'printf' rounds the more accurate result calculated by 'bc', giving us the correct date range of '6'.

Edit: highlighting the answer in a comment from @hank-schultz below, which I have been using lately:

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

This should also be leap second safe as long as you always subtract the earlier date from the later one, since leap seconds will only ever add to the difference - truncation effectively rounds down to the correct result.



回答5:

If the option -d works in your system, here's another way to do it. There is a caveat that it wouldn't account for leap years since I've considered 365 days per year.

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` 


回答6:

Here's the MAC OS X version for your convenience.

$ echo $(((`date -jf %Y-%d-%m $B +%s` - `date -jf %Y-%d-%m $A +%s`)/86400)) 

nJoy!



回答7:

Even if you don't have GNU date, you'll probably have Perl installed:

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

This returns 398.041666666667 -- 398 days and one hour due to daylight savings.


The question came back up on my feed. Here's a more concise method using a Perl bundled module

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 


回答8:

I'd submit another possible solution in Ruby. Looks like it's the be smallest and cleanest looking one so far:

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


回答9:

on unix you should have GNU dates installed. you do not need to deviate from bash. here is the strung out solution considering days, just to show the steps. it can be simplified and extended to full dates.

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


回答10:

Give this a try:

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


回答11:

Another Python version:

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


回答12:

Assume we rsync Oracle DB backups to a tertiary disk manually. Then we want to delete old backups on that disk. So here is a small bash script:

#!/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 

Modify the dirs and retention period ("30 days") to suit your needs.



回答13:

Use the shell functions from http://cfajohnson.com/shell/ssr/ssr-scripts.tar.gz; they work in any standard Unix shell.

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

See the documentation at http://cfajohnson.com/shell/ssr/08-The-Dating-Game.shtml



回答14:

Using mysql command

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

Result: 21

NOTE: Only the date parts of the values are used in the calculation

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



回答15:

This assumes that a month is 1/12 of a year:

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


回答16:

For MacOS sierra (maybe from Mac OS X yosemate),

To get epoch time(Seconds from 1970) from a file, and save it to a var: old_dt=`date -j -r YOUR_FILE "+%s"`

To get epoch time of current time new_dt=`date -j "+%s"`

To calculate difference of above two epoch time (( diff = new_dt - old_dt ))

To check if diff is more than 23 days (( new_dt - old_dt > (23*86400) )) && echo Is more than 23 days



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!