I need to do date arithmetic in Unix shell scripts that I use to control the execution of third party programs.
I\'m using a function to increment a day and another
If you want to continue with awk, then the mktime and strftime functions are useful:
BEGIN { dateinit }
{ newdate=daysadd(OldDate,DaysToAdd)}
# daynum: convert DD-MON-YYYY to day count
#-----------------------------------------
function daynum(date, d,m,y,i,n)
{
y=substr(date,8,4)
m=gmonths[toupper(substr(date,4,3))]
d=substr(date,1,2)
return mktime(y" "m" "d" 12 00 00")
}
#numday: convert day count to DD-MON-YYYY
#-------------------------------------------
function numday(n, y,m,d)
{
m=toupper(substr(strftime("%B",n),1,3))
return strftime("%d-"m"-%Y",n)
}
# daysadd: add (or subtract) days from date (DD-MON-YYYY), return new date (DD-MON-YYYY)
#------------------------------------------
function daysadd(date, days)
{
return numday(daynum(date)+(days*86400))
}
#init variables for date calcs
#-----------------------------------------
function dateinit( x,y,z)
{
# Stuff for date calcs
split("JAN:1,FEB:2,MAR:3,APR:4,MAY:5,JUN:6,JUL:7,AUG:8,SEP:9,OCT:10,NOV:11,DEC:12", z)
for (x in z)
{
split(z[x],y,":")
gmonths[y[1]]=y[2]
}
}
If the GNU version of date works for you, why don't you grab the source and compile it on AIX and Solaris?
http://www.gnu.org/software/coreutils/
In any case, the source ought to help you get the date arithmetic correct if you are going to write you own code.
As an aside, comments like "that solution is good but surely you can note it's not as good as can be. It seems nobody thought of tinkering with dates when constructing Unix." don't really get us anywhere. I found each one of the suggestions so far to be very useful and on target.
This works for me:
TZ=GMT+6;
export TZ
mes=`date --date='2 days ago' '+%m'`
dia=`date --date='2 days ago' '+%d'`
anio=`date --date='2 days ago' '+%Y'`
hora=`date --date='2 days ago' '+%H'`
To do arithmetic with dates on UNIX you get the date as the number seconds since the UNIX epoch, do some calculation, then convert back to your printable date format. The date command should be able to both give you the seconds since the epoch and convert from that number back to a printable date. My local date command does this,
% date -n
1219371462
% date 1219371462
Thu Aug 21 22:17:42 EDT 2008
%
See your local date(1)
man page.
To increment a day add 86400 seconds.
For BSD / OS X compatibility, you can also use the date utility with -j
and -v
to do date math. See the FreeBSD manpage for date. You could combine the previous Linux answers with this answer which might provide you with sufficient compatibility.
On BSD, as Linux, running date
will give you the current date:
$ date
Wed 12 Nov 2014 13:36:00 AEDT
Now with BSD's date you can do math with -v
, for example listing tomorrow's date (+1d
is plus one day):
$ date -v +1d
Thu 13 Nov 2014 13:36:34 AEDT
You can use an existing date as the base, and optionally specify the parse format using strftime, and make sure you use -j
so you don't change your system date:
$ date -j -f "%a %b %d %H:%M:%S %Y %z" "Sat Aug 09 13:37:14 2014 +1100"
Sat 9 Aug 2014 12:37:14 AEST
And you can use this as the base of date calculations:
$ date -v +1d -f "%a %b %d %H:%M:%S %Y %z" "Sat Aug 09 13:37:14 2014 +1100"
Sun 10 Aug 2014 12:37:14 AEST
Note that -v
implies -j
.
Multiple adjustments can be provided sequentially:
$ date -v +1m -v -1w
Fri 5 Dec 2014 13:40:07 AEDT
See the manpage for more details.
date --date='1 days ago' '+%a'
It's not a very compatible solution. It will work only in Linux. At least, it didn't worked in Aix and Solaris.
It works in RHEL:
date --date='1 days ago' '+%Y%m%d'
20080807