Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Calculating Time elapsed 1

Status
Not open for further replies.

pho01

Programmer
Mar 17, 2003
218
US
How to calculate time elapsed in unix shell script assuming I have two variables in time format of yyyymmdd hh:mm:ss

for example, i need to calculate the time elapsed of:
var1="20061010 12:15:35"
var2="20061011 1:15:32"

Just want to calculate the time difference betweeb var2 and var1.
Thanks!
 
Hi

Prints the difference in seconds :
Code:
echo $(($(date -d "$var2" +%s)-$(date -d "$var1" +%s)))
Tested with [tt]bash[/tt] and GNU [tt]date[/tt]. Try with yours, could work.

Feherke.
 
Thanks Feherke.
It didn't work for me. here's the errors:

date: illegal option -- d
Usage: date [-u] [+format]
date [-u] [mmddhhmm[[cc]yy]]
date [-a [-]sss.fff]
date: illegal option -- d
Usage: date [-u] [+format]
date [-u] [mmddhhmm[[cc]yy]]
date [-a [-]sss.fff]
./test.sh[5]: -: Expression is not complete; more tokens expected.

This is test.sh
#!/usr/bin/sh

var1="20061010 12:15:35"
var2="20061011 1:15:32"
echo $(($(date -d "$var2" +%s)-$(date -d "$var1" +%s)))

Did you test it with the same date format?
Thanks!
 
I tried to do this using perl but I can't for the life of me figure out why it's giving me the wrong result:

Code:
#!/usr/bin/perl
#
# ./datediff2.pl "20061010 12:15:35" "20061011 1:15:32"
use Time::Local;

($year,$mon,$mday,$hour,$min,$sec) = ( $ARGV[0] =~ /^(\d\d\d\d)(\d\d)(\d\d) (\d+):(\d+):(\d+)/ );
print "$year $mon $mday  $hour $min $sec\n";
$mon -= 1; # months are 0-11
$time1 = timelocal($sec,$min,$hour,$mday,$mon,$year);
($year,$mon,$mday,$hour,$min,$sec) = ( $ARGV[1] =~ /^(\d\d\d\d)(\d\d)(\d\d) (\d+):(\d+):(\d+)/ );
print "$year $mon $mday  $hour $min $sec\n";
$mon -= 1; # months are 0-11
$time2 = timelocal($sec,$min,$hour,$mday,$mon,$year);
print $time1; print "\n";
print scalar localtime $time1; print "\n";
print $time2; print "\n";
print scalar localtime $time2;print "\n";
print scalar localtime $time2-$time1; print "\n";
my ($sec,$min,$hour) = localtime $time2-$time1;
printf("%02d:%02d:%02d\n",$hour,$min,$sec);

[tt]$ ./datediff2.pl "20061010 12:15:35" "20061011 1:15:32"
2006 10 10 12 15 35
2006 10 11 1 15 32
1160478935
Tue Oct 10 12:15:35 2006
1160525732
Wed Oct 11 01:15:32 2006
Thu Jan 1 13:59:57 1970
13:59:57
$[/tt]

The answer should be 12:59:57, where is that extra hour coming from??

Annihilannic.
 
Annihilannic,

I think the reason is
my ($sec,$min,$hour) = localtime $time2-$time1;

I suppose your localtime is not GMT, but GMT + 1 hour?

regards
 
Of course it is. :-D Thanks Hoinz.

So this gives the correct result:

Code:
#!/usr/bin/perl
#
# ./datediff.pl "20061010 12:15:35" "20061011 1:15:32"
use Time::Local;

($year,$mon,$mday,$hour,$min,$sec) = ( $ARGV[0] =~ /^(\d\d\d\d)(\d\d)(\d\d) (\d+):(\d+):(\d+)/ );
$mon -= 1; # months are 0-11
$time1 = timelocal($sec,$min,$hour,$mday,$mon,$year);
($year,$mon,$mday,$hour,$min,$sec) = ( $ARGV[1] =~ /^(\d\d\d\d)(\d\d)(\d\d) (\d+):(\d+):(\d+)/ );
$mon -= 1; # months are 0-11
$time2 = timelocal($sec,$min,$hour,$mday,$mon,$year);
my ($sec,$min,$hour) = gmtime $time2-$time1;

Annihilannic.
 
Thanks all, thanks Annihilannic.

Annihilannic, it looks pretty good. However, this doesn't work on the machine i work on, it doesn't have Time::Local installed. This is production server, we can't install it on unless we go through lengthy process.

can we focus on unix shell script only, or if it has to be on perl, then it has to be whatever go with the OS, no additional modules will be allowed.

this is an hpux system, date -d doesn't work
Thanks!
 
pure ksh and some awk (but I could probably get rid of the awk bit if I really tried):

Code:
#!/bin/ksh
#####

# days preceding a month for standard and leap year
mos[1]=0     mol[1]=0
mos[2]=31    mol[2]=31
mos[3]=59    mol[3]=60
mos[4]=90    mol[4]=91
mos[5]=120   mol[5]=121
mos[6]=151   mol[6]=152
mos[7]=181   mol[7]=182
mos[8]=212   mol[8]=213
mos[9]=243   mol[9]=244
mos[10]=273  mol[10]=274
mos[11]=304  mol[11]=305
mos[12]=334  mol[12]=335

# seconds in a year, leapyear and day
((secy=365*24*60*60))
((secl=366*24*60*60))
((secd=24*60*60))

# maybe the epoch year needs to be lowered further on
epoch=2000

# your vars
var1="20061010 12:15:35"
var2="20061011 1:15:32"

# print out origina vars
echo $var1
echo $var2

# canonicalize dates
echo $var1|awk '{split($2,tm,":");
                 print substr($1,1,4),substr($1,5,2),substr($1,7,2),
                       tm[1], tm[2], tm[3]}'|read yr1 mo1 dy1 hr1 mi1 sc1
echo $var2|awk '{split($2,tm,":");
                 print substr($1,1,4),substr($1,5,2),substr($1,7,2),
                       tm[1], tm[2], tm[3]}'|read yr2 mo2 dy2 hr2 mi2 sc2

# print out canonicalized vars
echo $yr1 $mo1 $dy1 $hr1 $mi1 $sc1
echo $yr2 $mo2 $dy2 $hr2 $mi2 $sc2

# shell function to check for leap year
leapyear()
{
 ((l=1))
 ((r4=$1%4))
 ((r100=$1%100))
 ((r400=$1%400))
 if ((r4==0))
 then
  if ((r100!=0))
  then
   ((l=0))
  else
   if ((r400==0))
   then
    ((l=0))
   fi
  fi
 fi
 return $l
}

# calculate julian dates
if leapyear $yr1
then
 ((ju1=${mol[mo1]}+dy1))
else
 ((ju1=${mos[mo1]}+dy1))
fi
if leapyear $yr2
then
 ((ju2=${mol[mo2]}+dy2))
else
 ((ju2=${mos[mo2]}+dy2))
fi

# convert time to seconds
((se1=hr1*3600+mi1*60+sc1))
((se2=hr2*3600+mi2*60+sc2))

# print out julian date and seconds
echo $yr1.$ju1.$se1
echo $yr2.$ju2.$se2

# possibly first lower the epoch year
while ((epoch>yr1))
do
 ((epoch=epoch-1))
done
while ((epoch>yr2))
do
 ((epoch=epoch-1))
done

# print out epoch
echo $epoch

# convert year and julian dates to seconds
((yr=epoch))
while ((yr<yr1))
do
 if leapyear $yr
 then
  ((se1=se1+secl))
 else
  ((se1=se1+secy))
 fi
 ((yr=yr+1))
done
((se1=se1+ju1*secd))
((yr=epoch))
while ((yr<yr2))
do
 if leapyear $yr
 then
  ((se2=se2+secl))
 else
  ((se2=se2+secy))
 fi
 ((yr=yr+1))
done
((se2=se2+ju2*secd))

# print out date/time converted to seconds since epoch
echo $se1
echo $se2

# calculate difference in seconds
((ds=se2-se1))

# print out difference in dates in seconds
echo $ds



HTH,

p5wizard
 
Note however that this script does not account for daylight savings time variations and neither does it do a check to see if the dates provided are valid dates...


HTH,

p5wizard
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top