Date Calculations in `bash`

Date calculations are often useful for maintenance routines. As an example, consider the situation where log files are stored in a hierarchal directory structure of the form:

/2012
/Jan
/Feb
/Mar
...
/Dec
/2013
/Jan
/Feb
...

We may now want to, for example, compress any log files that are related to the month before last, and delete any logs that relate to this month last year.

$ date
Wed  8 May 2013 14:55:44 BST

Instead of resorting to PERL or some other solution, we can simply use the built-in date calculations in the bash shell.

The date command is used to display or set the date on a UNIX/Linux system. For our purposes, we want to display the date. By default, date will display the current date:

$ date
Tue 7 May 2013 18:26:34 BST

It is possible to change the output format from date. For example, to find the directory that holds the current month's log files we could use:

$ date +/%Y/%b
/2013/May

This is useful for finding where to write this month's log files to, but what about finding the directory containing the files that need to be compressed or deleted? Again, date comes to our rescue. By default date shows the current date, but it can also be used to display other dates based on various date calculations. For example

$ date --date='4 months ago' +/%Y/%b
/2013/Jan

or

date --date='1 year ago' +%Y/%b
/2012/May

This works fine with GNU based implementations of date, but the syntax on BSD is different. To do the same thing on OS X, the format of date would be:

$ date -v -4m +/%Y/%b
/2013/Jan

and

$ date -v -1y +/%Y/%b
/2012/May

The --date parameter (-d for short) for GNU date or the equivalent -v parameter in BSD can take an expression that will change the date reported, rather than simply using the current date. The functionality is similar in both systems, but the syntax is different.

If you need to work out the length of the interval between 2 dates, then the data command can help again. The %s format returns the number of seconds since the start of 1970. Since this just gives a number of seconds, if both dates are converted to this format, a simple arithmetic subtraction can give the desired interval. For example, to work out how many days there were last month, we could use:

echo $(( ( $( date +%s )-$( date --date='-1 Month' +%s ))/86400 ))

on GNU, or

echo $(( ( $( date +%s )-$( date -v-1m +%s ))/86400 ))

on BSD. This gets the number of seconds since 1 Jan 1970 and subtracts from that then number of seconds between 1 Jan 1970 and the date one month ago. This difference is the number of seconds since 1 month ago. Divide the result by the number of seconds in a day and you get the number of days in the previous month.

 

This site uses cookies. By continuing to browse the site you are agreeing to our use of cookies.