Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Date Calculation on shell programming

5 views
Skip to first unread message

Patrick lo

unread,
Apr 24, 2002, 11:59:10 AM4/24/02
to
Hi,

I would like to ask if it is possible to calculate the date on shell
programming? For example, I would like to use the command "date" to
output the date of seven days before today in the format "YYYY-MM-DD".
Can I do that in a simple way?

Thanks a lot in advance.

Regards,
Patrick

Ben Altman

unread,
Apr 24, 2002, 12:42:32 PM4/24/02
to
"Patrick lo" <patric...@hotmail.com> wrote in message
news:7c74096d.02042...@posting.google.com...

> Hi,
>
> I would like to ask if it is possible to calculate the date on shell
> programming? For example, I would like to use the command "date" to
> output the date of seven days before today in the format "YYYY-MM-DD".
> Can I do that in a simple way?

date() {
perl -e 'print localtime(time() - 7*24*3600) . "\n";'
}

regards,
Ben

Pedro Díaz Jiménez

unread,
Apr 24, 2002, 5:51:21 PM4/24/02
to
another option, with the (gnu) date command:

[pdiaz]-> date=` date --date="7 days ago" +"%Y-%m-%d"`
[pdiaz]-> echo $date
2002-04-17
[pdiaz]-> date
Wed Apr 24 23:49:26 GMT 2002
[pdiaz]->

Cheers
Pedro

Ben Altman wrote:

--
/*
* Pedro Diaz Jimenez
* pdiaz "AT" pdiaz "DOT" homeunix "DOT" net,
*
* http://acm.asoc.fi.upm.es/~pdiaz
*/
--
SpamBot poisson:
iuboxaziloj@fupuabigox..co.uk qejue...@mapifaguebeah.es
wuohi...@celeotoebut.fr fijed...@welebuubaab.com
dosate...@tiapopiabar.au wejul...@yaopimiubig.au

Patrick lo

unread,
Apr 24, 2002, 7:33:59 PM4/24/02
to
"Ben Altman" <ben_a...@deadspam.com> wrote in message news:<aa6ncr$920$1...@news.nems.noaa.gov>...
Thank you, Ben. However, I would like to know if use of perl in the
Unix shell script will have bad performance?

Regards,
Patrick

HoboSong

unread,
Apr 24, 2002, 9:52:19 PM4/24/02
to

What platform/shell are you on? Do you need this to be portable?

--
---------------------------------------------------------------------
| Chris van Ophuijsen | chris*SPAM*vano@yahoo*DOT*com| RLU #195880 |
---------------------------------------------------------------------

Tapani Tarvainen

unread,
Apr 25, 2002, 1:19:56 AM4/25/02
to
patric...@hotmail.com (Patrick lo) writes:

> I would like to ask if it is possible to calculate the date on shell
> programming? For example, I would like to use the command "date" to
> output the date of seven days before today in the format "YYYY-MM-DD".
> Can I do that in a simple way?

With standard shell commands it's not simple, but definitely doable.
(If you can use perl or have Gnu date it's much easier.)

The following functions should work with ksh, bash or any
POSIX-compliant shell. By converting dates to and from Julian
Day Numbers you can calculate differences between dates as well
as those "date N days before/after" -type calculations.
E.g., to get seven days back:

julian2date $(( $(date2julian $DAY $MONTH $YEAR) - 7 ))

Rearranging the arguments to use YYYY-MM-DD format is left as
an exersize to the reader.

---------------------------------cut here----------------------------------
#! /usr/bin/sh

# Date calculations using POSIX shell
# Tapani Tarvainen July 1998, February 2001 (POSIXified)
# This code is in the public domain.

# Julian Day Number from calendar date
date2julian() # day month year
{
day=$1; month=$2; year=$3
tmpmonth=$((12 * year + month - 3))
tmpyear=$((tmpmonth / 12))
echo $(( (734 * tmpmonth + 15) / 24 - 2 * tmpyear + \
tmpyear/4 - tmpyear/100 + tmpyear/400 + day + 1721119 ))
}

# Calendar date from Julian Day Number
julian2date() # julianday
{
tmpday=$(($1 - 1721119))
centuries=$(( (4 * tmpday - 1) / 146097))
tmpday=$((tmpday + centuries - centuries/4))
year=$(( (4 * tmpday - 1) / 1461))
tmpday=$((tmpday - (1461 * year) / 4))
month=$(( (10 * tmpday - 5) / 306))
day=$((tmpday - (306 * month + 5) / 10))
month=$((month + 2))
year=$((year + month/12))
month=$((month % 12 + 1))
echo $day $month $year
}

# Day of week, Monday=1...Sunday=7
dow() # day month year
{
echo $(( $(date2julian $1 $2 $3) % 7 + 1 ))
}

################################# The End #################################
---------------------------------cut here----------------------------------

--
Tapani Tarvainen

Ben Altman

unread,
Apr 25, 2002, 9:50:38 AM4/25/02
to

"Patrick lo" <patric...@hotmail.com> wrote in message
news:7c74096d.02042...@posting.google.com...
> > date() {
> > perl -e 'print localtime(time() - 7*24*3600) . "\n";'
> > }
> Thank you, Ben. However, I would like to know if use of perl in the
> Unix shell script will have bad performance?

Why don't you run some tests yourself and see if it is adequate for your
needs? If you will need to run the function thousands of times then it
might pay to use one of the other options. On the other hand, why would you
want to know when 7 days ago was thousands of times - usually once a day is
adequate :-). BTW. when I ran it 1000 times on a Linux box it took 4.8
seconds.

Ben


laura fairhead

unread,
Apr 28, 2002, 3:17:14 PM4/28/02
to


#!/bin/sh
DAYS_BACK=7
eval `date "+%d %m %Y $DAYS_BACK" |
awk '
{
while(($1-=$4)<1){
$4=-$1
if(!(--$2)){$2=12;$3--}
R=31
if($2==4||$2==6||$2==9||$2==11)R--
if($2==2){
R=29
if(($3%4)||!($3%100)&&($3%400))R--
}
$1=R
}
print "d="$1" m="$2" y="$3
}
'`
echo date $DAYS_BACK day(s) ago=$d/$m/$y


>Regards,
>Patrick

byefrom

--
laura fairhead # la...@madonnaweb.com http://lf.8k.com
# if you are bored crack my sig.
1F8B0808CABB793C0000666667002D8E410E83300C04EF91F2877D00CA138A7A
EAA98F30C494480157B623C4EF1B508FDED1CEFA9152A23DE35D661593C5318E
630C313CD701BE92E390563326EE17A3CA818F5266E4C2461547F1F5267659CA
8EE2092F76C329ED02CA430C5373CC62FF94BAC6210B36D9F9BC4AB53378D978
80F2978A1A6E5D6F5133B67B6113178DC1059526698AFE5C17A5187E7D930492

Nikolay Arbuzov

unread,
Jun 3, 2002, 10:07:23 PM6/3/02
to
Tapani Tarvainen <t...@it.jyu.fi> wrote in
news:n6g01kf...@ogion.it.jyu.fi:

> patric...@hotmail.com (Patrick lo) writes:
>
>> I would like to ask if it is possible to calculate the date on shell
>> programming? For example, I would like to use the command "date" to
>> output the date of seven days before today in the format
>> "YYYY-MM-DD". Can I do that in a simple way?
>
> With standard shell commands it's not simple, but definitely doable.
> (If you can use perl or have Gnu date it's much easier.)
>

How about having some function which works with Unix time.
like mktime/ctime. I have something but it has loops in it. And
doesnt work very fast in programs where you need lots of
conversions like log parsing etc.

Thanks.

Viktor Chuyko

unread,
Jun 3, 2002, 10:39:34 PM6/3/02
to
Hello, gentlemen.
Definitely, it is possible in unix programming.
Look up the output of command:

man date

from command line in Unix for any 'date' formatting and just add some
simple script to calculate
'date -7' format. Probably, it could take using 'cut', 'paste', 'sed', or
some other basic commands.
Who, knows? You can try.
But, why do you need to reinvent the wheel?

God luck to you with your try.

Viktor C.

Nikolay Arbuzov

unread,
Jun 3, 2002, 11:29:11 PM6/3/02
to
Viktor Chuyko <vch...@earthlink.net> wrote in
news:3CFC28F1...@earthlink.net:

> Hello, gentlemen.
> Definitely, it is possible in unix programming.
> Look up the output of command:
>
> man date
>
> from command line in Unix for any 'date' formatting and just add some
> simple script to calculate
> 'date -7' format. Probably, it could take using 'cut', 'paste', 'sed', or
> some other basic commands.
> Who, knows? You can try.
> But, why do you need to reinvent the wheel?
>
>

what if you need more general function not only -7 days but it could be
-5 minutes or +2.5 years. Easiest way is convert date to Unix format
and then subtract whatever number of seconds you want and convert it
back to string.

BTW I already found it in some old posts if somebody interested:

#!/bin/ksh
#
# mktime is a generalization of timelocal() and timegm().
#
mktime() {
# Emulation of the Unix mktime(3C) library routine.
# Maps a tm structure to a Unix Epoch time.
# tm_struct: tm_sec(%S) tm_min(%M) tm_hour(%H) tm_mday(%d)
tm_mon(%m-1)
# tm_year(%y) tm_wday(%w) tm_yday(%j-1) tm_isdst

# 1 2 3 4 5 6 7 8 9
# %S %M %H %d %m-1 %y %w %j-1 tm_isdst

if [ $# -lt 8 ]; then
return 1
fi

typeset -i DAYS TIME
DAYS=$(( 365*($6 - 70) + ($6 - 69)/4 + $8 ))
# XXX This will begin to fail in 2100 A.D. unless the following
line
# XXX that adjusts for 100 and 400 years periods is uncommented.
#(( $6 >= 200 )) && DAYS=$(( $DAYS - ($6-100)/100 + ($6-100)/400 ))
TIME=$(( $1 + 60*($2 + 60*($3 + 24*$DAYS)) ))
# XXX Adjustments for leap seconds?
print $TIME

return 0
}


unixtime() {
# Emulation of the Unix time(2) system call -- writes to stdout the
# value of time in seconds since 00:00:00 UTC, January 1, 1970.
# No parameters.

typeset -i DAYS TIME
if type env >/dev/null 2>&1 ; then
set -- $(env LC_ALL=C LC_TIME=C LANG=C date -u '+%Y %j %H
%M %S')
else
set -- $(date -u '+%Y %j %H %M %S')
fi
[[ $? -ne 0 || $# -lt 5 ]] && return 1
DAYS=$(( 365*($1 - 1970) + ($1 - 1969)/4 + $2 -1 ))
# XXX This will begin to fail in 2100 A.D. unless the following
line
# XXX that adjusts for 100 and 400 years periods is uncommented.
#(( $1 >= 2100 )) && DAYS=$(( $DAYS - ($1-2000)/100 + ($1-2000)/400
))
TIME=$(( $5 + 60*($4 + 60*($3 + 24*$DAYS)) ))
# XXX Adjustments for leap seconds?
print $TIME

return 0
}

tt+gn20020...@it.jyu.fi

unread,
Jun 11, 2002, 2:27:13 AM6/11/02
to
Nikolay Arbuzov <ni...@podlodka.com> writes:

> what if you need more general function not only -7 days but it could be
> -5 minutes or +2.5 years.

Adding minutes or days or weeks is easy but using year or month as a
unit is problematic, as their lengths are not constant.
For example, what should you get by adding 2 years to 29 February 2000?
Or subtracting a month from 31 March, any year?

There is no completely general solution, I'm afraid. :-(

--
Tapani Tarvainen

Reinhard Skarbal

unread,
Jun 11, 2002, 4:58:14 AM6/11/02
to
I'm using ADU in my *.ksh
there was a posting 9 months ago :

! FROM: <Stan....@metronet.com>
! SUBJECT: ADU - A Date Utility
! DATE: 20-09-2001 15:35
!
! ADU (A Date Utility) is available for download via anonymous ftp to
! metronet.com. ADU is in the directory named "milam". ADU can be used to
! caluculate and format dates from a UNIX shell. Following is the ADU
! document page:
! ... snip ...

regards
Reinhard


<tt+gn20020...@it.jyu.fi> schrieb im Newsbeitrag
news:n6lm9me...@it.jyu.fi...

Peter J. Acklam

unread,
Jun 11, 2002, 5:16:00 AM6/11/02
to
"Reinhard Skarbal" <ska...@atc.co.at> wrote:

> I'm using ADU in my *.ksh
> there was a posting 9 months ago :
>
> ! FROM: <Stan....@metronet.com>
> ! SUBJECT: ADU - A Date Utility
> ! DATE: 20-09-2001 15:35
> !
> ! ADU (A Date Utility) is available for download via anonymous ftp to
> ! metronet.com. ADU is in the directory named "milam". ADU can be used to
> ! caluculate and format dates from a UNIX shell. Following is the ADU
> ! document page:
> ! ... snip ...

The source was located at

ftp://ftp.metronet.com/milam/adu.tar.gz
ftp://ftp.metronet.com/milam/adu.zip

but unfortunately ftp.metronet.com no longer exists.
Does anyone know where I can get hold of a copy?

Peter

--
Where do bit streams end? In bit rivers?

tt+gn20020...@it.jyu.fi

unread,
Jun 11, 2002, 6:29:08 AM6/11/02
to
"Reinhard Skarbal" <ska...@atc.co.at> writes:

> I'm using ADU in my *.ksh

I can't seem to find it anywhere now (ftp.metronet.com is gone),
so could you try and tell what does it do with these examples:

> > what should you get by adding 2 years to 29 February 2000?
> > Or subtracting a month from 31 March, any year?

The problem is that there is no way to _define_ such operations
consistently without some surprising results. You can come up
with definitions that suit specific purposes, but not one that'll
work for all situations.

For example, it would generally be desirable that (a+b)-b = a
but you can't make that hold when adding months or years
in the Gregorian calendar (try with the above examples).

--
Tapani Tarvainen

Reinhard Skarbal

unread,
Jun 11, 2002, 9:15:59 AM6/11/02
to
http://www.geocities.com/r_skarbal/index.html

Hi !

I have placed adu.zip (30 kByte) on my family-home-page.

Enjoy
the adu.zip, NOT the home-page :-)

regards
Reinhard


"Peter J. Acklam" <pjac...@online.no> schrieb im Newsbeitrag
news:uofeii...@online.no...

tt+gn20020...@it.jyu.fi

unread,
Jun 12, 2002, 2:16:01 AM6/12/02
to
"Reinhard Skarbal" <ska...@atc.co.at> writes:

> http://www.geocities.com/r_skarbal/index.html
>
> Hi !
>
> I have placed adu.zip (30 kByte) on my family-home-page.

Thanks. It seems ADU tries pretty hard to do the right thing,
but nonetheless you should be careful when adding months or
years, as such calculations are inevitably irreversible
and non-commutative: adding two years twice may get a
different result than adding four years at once, &c.
(That's not really ADU's fault but an unavoidable
consequence of irregularities in the calendar.)

As such, ADU doesn't seem to do much Gnu date couldn't do, but it is
worth noting that ADU handles many ambiguous cases differently.
Compare:

$ ./adu -C y2 29-Feb-2000
28-Feb-2002
$ date --date '29-Feb-2000 2 years' +%d-%b-%Y
01-Mar-2002

$ ./adu -C m1 31-Jan-2002
28-Feb-2002
$ date --date '31-Jan-2002 1 month' +%d-%b-%Y
03-Mar-2002

Which is better depends on your needs, but ADU would seem
better, less surprising, at least in some situations.
For example, let's try loopubg through the last days
of all months (assuming POSIXy shell):

s=31-Jan-2004
for i in 0 1 2 3 4 5 6 7 8 9 10 11
do
echo $s
s=$(./adu -C m1 $s)
done

gives wrong results, but

s=31-Jan-2004
for i in 0 1 2 3 4 5 6 7 8 9 10 11
do
./adu -C m$i $s
done

works as desired.

Achieving the same with Gnu date is trickier.
Neither of the above approaches will work, but
using first days and then subtracting one does:

s=01-Feb-2004
for i in 0 1 2 3 4 5 6 7 8 9 10 11
do
date --date "$s -1 day $i month" +%d-%b-%Y
done

Either way, you need to be aware of the limitations of
the program you're using and problems in date calculations
in general.

--
Tapani Tarvainen

Reinhard Skarbal

unread,
Jun 12, 2002, 7:26:37 AM6/12/02
to
Hi Tapani !

Thanks for pointing out those problems.

regards Reinhard

> ...
> ...


> Either way, you need to be aware of the limitations of
> the program you're using and problems in date calculations
> in general.

> Tapani Tarvainen


0 new messages