A="2002-20-10"
B="2003-22-11"
How to find the difference in days between two dates?
A="2002-20-10"
B="2003-22-11"
How to find the difference in days between two dates?
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.
Example using GNU date (from https://mcmap.net/q/188966/-how-do-i-get-the-difference-between-two-dates-under-bash-duplicate):
let DIFF=($(date +%s -d 20210131)-$(date +%s -d 20210101))/86400
echo $DIFF
30
This also works with dates in other formats, for example "2021-01-31".
Other answers suggest ways to do it that don't require GNU date.
echo "( `date -d $B +%s` - `date -d $A +%s`) / (24*3600)" | bc -l
–
Gobi -d
option of (GNU-)date
is NOT a part of POSIX date, therefore less portable. As long as the OP is not working on Unix distributions like Solaris, but only "common Linux", this works. If not, check user332325's link above! @ jschnasse's answer also uses date -d
–
Teshatesla date: illegal time format [...] bash: let: DIFF=(-)/86400: syntax error: operand expected (error token is ")/86400")
–
Cyclamen 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) ))
%y%m%d
format. E.g. gnu date will accept the %Y-%m-%d
format the OP used. In general, ISO-8601 is a good choice (and the OP's format is one such format). Formats with 2 digit years are better avoided. –
Bespatter days_diff=$(( (`date -d $B +%s` - `date -d "00:00" +%s`) / (24*3600) ))
. note that $days_diff
will be an integer (i.e. no decimals) –
Sello date
installed. It works for GNU date
. It doesn't work with POSIX date
. This probably isn't a problem for most readers, but it's worth noting. –
Bespatter %Y-%m-%d
, until we introduce August 2.0
and October 2.0
OP's format is %Y-%d-%m
. Relevant xkcd: xkcd.com/1179 –
Future date: illegal option -- - [...] bash: ( - )/(60*60*24) : syntax error: operand expected (error token is ")/(60*60*24) ")
–
Cyclamen 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.
Example using GNU date (from https://mcmap.net/q/188966/-how-do-i-get-the-difference-between-two-dates-under-bash-duplicate):
let DIFF=($(date +%s -d 20210131)-$(date +%s -d 20210101))/86400
echo $DIFF
30
This also works with dates in other formats, for example "2021-01-31".
Other answers suggest ways to do it that don't require GNU date.
echo "( `date -d $B +%s` - `date -d $A +%s`) / (24*3600)" | bc -l
–
Gobi -d
option of (GNU-)date
is NOT a part of POSIX date, therefore less portable. As long as the OP is not working on Unix distributions like Solaris, but only "common Linux", this works. If not, check user332325's link above! @ jschnasse's answer also uses date -d
–
Teshatesla date: illegal time format [...] bash: let: DIFF=(-)/86400: syntax error: operand expected (error token is ")/86400")
–
Cyclamen tl;dr
date_diff=$(( ($(date -d "2015-03-11 UTC" +%s) - $(date -d "2015-03-05 UTC" +%s)) / (60*60*24) ))
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.
echo $(( ($(date --date="2015-03-11 UTC" +%s) - $(date --date="2015-03-05 UTC" +%s) )/(60*60*24) ))
, which returns 6, instead of 5. –
Kolosick LC_ALL=C
(with bash, might be different with other shells) yields the correct number 25. –
Anadem bash: ( - ) / (60*60*24) : syntax error: operand expected (error token is ") / (60*60*24) ")
–
Cyclamen And in python
$python -c "from datetime import date; print (date(2003,11,22)-date(2002,10,20)).days"
398
bash
and shell
, so I think we can assume that we're talking about a *nix system. Within such systems, echo
and date
are reliably present, but python is not. –
Bespatter This works for me:
A="2002-10-20"
B="2003-11-22"
echo $(( ($(date -d $B +%s) - $(date -d $A +%s)) / 86400 )) days
Prints
398 days
What is happening?
date -d
to handle time stringsdate %s
to convert time strings to seconds since 1970 (unix epoche)bash: ( - ) / 86400 : syntax error: operand expected (error token is ") / 86400 ")
–
Cyclamen )/86400
does fix it? –
Baddie date -d
sets the kernel's value for daylight saving time. It does not accept a date in that position. –
Cyclamen -jf
instead? If it works, I would add that variant to my answer. Initally I posted my answer because most of the others didn´t explain why they use certain parameters. Also the info about DST I referenced in the link was not prominent available. So my claim is not to provide a plattform independent solution. But together we can work towards that. –
Baddie brew install coreutils
and you've got gdate. Maybe worth a try. –
Baddie Here's the MacOS X / *BSD version for your convenience.
$ 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"
–
Overijssel echo $(((`date -jf "%Y-%d-%m" "$B" +%s` - `date -jf "%Y-%d-%m" "$A" +%s`)/86400))
, i.e. wrapping both formats and variables into double quotes, otherwise may fail on different date format (e.g. %b %d, %Y
/Jul 5, 2017
) –
Overijssel 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`
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
Here's my working approach using zsh. Tested on 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
Result:
Your value: 1577
Basically, we use strftime
reverse (-r
) feature to transform our date string back to a timestamp, then we make our calculation.
Command line bash solution
echo $((($(date +%s -d 20210131)-$(date +%s -d 20210101))/86400)) days
will print
30 days
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
This is the simplest i managed to get working on 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
If you have datediff command (for example dateutils package in some Linux distributions),
datediff 2003-11-22 2002-10-20
This gives an integer as number of days (398). The input should conform to some standard date like ISO format: YYYY-MM-DD
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
date
or some scripting language) and I honestly think that Ruby is a good way to go here. This solution is very short and does not use any non-standard libraries or other dependencies. In fact, I think that there's a higher chance of having Ruby installed than one would have GNU date installed. –
Ginkgo Another Python version:
python -c "from datetime import date; print date(2003, 11, 22).toordinal() - date(2002, 10, 20).toordinal()"
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
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
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])
}
Give this a try:
perl -e 'use Date::Calc qw(Delta_Days); printf "%d\n", Delta_Days(2002,10,20,2003,11,22);'
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.
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
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
use it to get your date today and your sec since the date you want. if you want it with days just divide it with 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
Instead of hard coding the expiration to a set amount of days when generating self-signed certificates, I wanted to have them expire just before the Y2k38 problem kicks in (on 19 January 2028). But, OpenSSL only allow the expiration to be set using -days
, which is the number of days from the current date.
I ended up using this:
openssl req -newkey rsa -new -x509 \
-days $((( $((2**31)) - $(date +%s))/86400-1)) \
-nodes -out new.crt -keyout new.key -subj '/CN=SAML_SP/'
for zsh (Only works if dates in the same year)
echo $(($(date -d "today" +%j) - $(date -d "08 Jan 2021" +%j) )) days
Using postgresql psql
command
$ echo "select '2003-2-11'::date - '2002-2-10'::date;" | psql -A -t
Result: 366
$ echo "select age('2003-2-11'::date, '2002-2-10'::date);" | psql -A -t
Result: 1 year 1 day
pip install diffdate
diffdate 10-20-2002 11-22-2003
One may encounter issues with local date format. The following worked for me just fine.
$ START_TIME=$(date --rfc-3339=ns --utc)
$ echo "Starting at $(date --date="$START_TIME")"
$ sleep 5
$ END_TIME=$(date --rfc-3339=ns --utc)
$ TIME_DIFF=$(( $(date --date="$END_TIME" +%s) - $(date --date="$START_TIME" +%s) ))
$ echo "Finished at $(date --date="$END_TIME")"
$ echo "DONE in $(date --date="@$TIME_DIFF" --utc +%T)"
© 2022 - 2024 — McMap. All rights reserved.