Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I often want to make some quick date calculations, such as:

  • What is the difference between these two dates?
  • What is the date n weeks after this other date?

I usually open a calendar and count the days, but I think there should be a program/script that I can use to do these kinds of calculations. Any suggestions?

share|improve this question
2  
See also Tool in UNIX to subtract dates for when GNU date is not available. –  Gilles Nov 15 '11 at 23:26

6 Answers 6

up vote 20 down vote accepted

The "n weeks after a date" is easy with GNU date(1):

$ date -d 'now + 3 weeks'
Tue Dec  6 23:58:04 EST 2011
$ date -d 'Aug 4 + 3 weeks'
Thu Aug 25 00:00:00 EST 2011
$ date -d 'Jan 1 1982 + 11 weeks'
Fri Mar 19 00:00:00 EST 1982

I don't know of a simple way to calculate the difference between two dates, but you can wrap a little logic around date(1) with a shell function.

datediff() {
    d1=$(date -d "$1" +%s)
    d2=$(date -d "$2" +%s)
    echo $(( (d1 - d2) / 86400 )) days
}
$ datediff '1 Nov' '1 Aug'
91 days

Swap d1 and d2 if you want the date calculation the other way, or get a bit fancier to make it not matter. Furthermore, in case there is a non-DST to DST transition in the interval, one of the days will be only 23 hours long; you can compensate by adding ½ day to the sum.

echo $(( (((d1-d2) > 0 ? (d1-d2) : (d2-d1)) + 43200) / 86400 )) days
share|improve this answer

A python example for calculating the number of days I've walked the planet:

$ python
>>> from datetime import date as D
>>> print (D.today() - D(1980, 6, 14)).days
11476
share|improve this answer

For a set of portable tools try my very own dateutils. Your two examples would boil down to one-liners:

ddiff 2011-11-15 2012-04-11
=>
  148

or in weeks and days:

ddiff 2011-11-15 2012-04-11 -f '%w %d'
=>
  21 1

and

dadd 2011-11-15 21w
=>
  2012-04-10
share|improve this answer

I usually prefer having the time/date in unix utime format (number of seconds since the epoch, when the seventies begun, UTC). That way it always boils down to plain subtraction or addition of seconds.

The problem the usually becomes transforming a date/time into this format.

If you have GNU date, you can get it with date '+%s' At the time of writing, the current time is 1321358027.

To compare with 2011-11-04 (my birthday), date '+%s' -d 2011-11-04, yielding 1320361200. Subtract: expr 1321358027 - 1320361200 gives 996827 seconds, which is expr 996827 / 86400 = 11 days ago.

The problem is converting from utime (1320361200 format) into a date. I don't know of a readily available tool to do this, but it's very simple to do in for instance C or perl.

share|improve this answer
4  
With GNU date, date -d @1234567890 converts from seconds since the epoch to whatever date format you specify. –  Gilles Nov 15 '11 at 23:21
1  
@Gilles: that is brilliant. Couldn't find that on the manpage. Where did you learn that? –  MattBianco Nov 16 '11 at 9:48
1  
@MattBianco, see info date, especially the Seconds since the Epoch node: “If you precede a number with `@', it represents an internal time stamp as a count of seconds.” –  manatwork Nov 16 '11 at 10:15

I frequently use SQL for date calculations. For example MySQL, PostgreSQL or SQLite:

bash-4.2$ mysql <<< "select datediff(current_date,'1980-06-14')"
datediff(current_date,'1980-06-14')
11477

bash-4.2$ psql <<< "select current_date-'1980-06-14'"
 ?column? 
----------
    11477
(1 row)

bash-4.2$ sqlite2 <<< "select julianday('now')-julianday('1980-06-14');"
11477.3524537035

Other times I just feel in mood for JavaScript. For example SpiderMonkey, WebKit, Seed or Node.js:

bash-4.2$ js -e 'print((new Date()-new Date(1980,5,14))/1000/60/60/24)'
11477.477526192131

bash-4.2$ jsc-1 -e 'print((new Date()-new Date(1980,5,14))/1000/60/60/24)'
11477.47757960648

bash-4.2$ seed -e '(new Date()-new Date(1980,5,14))/1000/60/60/24'
11477.4776318287

bash-4.2$ node -pe '(new Date()-new Date(1980,5,14))/1000/60/60/24'
11624.520061481482

(Watch out when passing the month to the JavaScript Date object's constructor. Starts with 0.)

share|improve this answer

If a graphical tool is OK for you, I heartily recommend qalculate (a calculator with an emphasis on unit conversions, it comes with a GTK and KDE interface, IIRC). There you can say e.g.

days(1900-05-21, 1900-01-01)

to get the number of days (140, since 1900 was not a leap year) between the dates, but of course you can also do the same for times:

17:12:45 − 08:45:12

yields 8.4591667 hours or, if you set the output to time formatting, 8:27:33.

share|improve this answer
    
That's great, and even more so because qalculate does have a CLI. Try qalc, then help days. –  Sparhawk Jul 4 at 12:19

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.