date difference

hi,

i have 2 dates in the form: '20080315120030' and '20080310140030'. i.e. YYYYMMDDHHMMSS.

i need a way of getting the difference between them using shell script.

any thoughts?

note i only have the following date utility:

usage: date [-u] mmddHHMM[[cc]yy][.SS]
date [-u] [+format]
date -a [-]sss[.fff]

at present i have this:

for file in `find ${my_dir}/ -name "*_statsfile_??????????????.gz" -print`
do
ONEDAY=86400
NOW=$(date -u +%Y%m%d%H%M%S)

    FILEDATE=\`echo $file | sed -e 's/^.*\_stats_//g' -e 's/\\.gz$//g'\`

    \(\(DIFF=$NOW - $FILEDATE\)\)
    CALC_DIFF=$\(\($DIFF / $ONEDAY\)\)

    echo "[$file], Current Time: $NOW. File Time: $FILEDATE. Difference: $CALC_DIFF."

done

both dates need to be in UTC. Is there a way to make them BOTH UTC. the date 'NOW' is UTC but the 'FILEDATE' isnt. :confused:

It's possible but it would help if you could say which time zone the second one is.

The standard solution would be to convert them both to a canonical format (maybe epoch, that is, seconds since Jan 1 1970) and then the problem is just how to format the result back as a human-readable time expression. In what form would you like the output?

I would use Perl or Python because they come with handy libraries which can do the grunt work for you.

at the moment the first date, NOW is using date -u (UTC) and the file names will also be UTC. At present i have created dummy files with made up time stamps.

i basically want to delete files over 3 days old in a directory using the current date as a marker...i cant use -mtime as a person may modify the file and the modified time will not be the same as the filename. So therefore i am using the filename as the second time stamp. if you follow me?

im only after the number of days between the 2 dates.

If you have control over the file names then simply compare the date stamp in the file's name with the output of

date -d "3 days ago" -u +%Y%m%d%H%M%S

thats where the problem is, i get the following error:

date: illegal option -- d
usage: date [-u] mmddHHMM[[cc]yy][.SS]
date [-u] [+format]
date -a [-]sss[.fff]
:frowning:

And you are on Linux? What version of date do you have (does it grok "date --version")?

Check your PATH, you might have some weird ancient BSD relic date in your PATH overshadowing the real McCoy ...? (Does "type -all date" reveal any shadows?)

If you have Perl, the Perl FAQ has a nice answer.

my bad I'm actually on a solaris box :rolleyes:

typing date --version threw:

date: illegal option -- -
date: illegal option -- v
date: illegal option -- e
date: illegal option -- r
date: illegal option -- s
date: illegal option -- i
date: illegal option -- o
date: illegal option -- n
usage: date [-u] mmddHHMM[[cc]yy][.SS]
date [-u] [+format]
date -a [-]sss[.fff]

type -all date
date is /usr/bin/date

Actually the "Similar threads" list at the bottom of this page has some nice links. Weird date difference problem looks like d�j� vu all over again.

This is the Linux forum, otherwise I would not even have suggested date -d. /-:

Why don't use find to do the job?

find <dir> -name <files> -mtime <+n> -exec rm -f {} \;

Check the manpage for more details of the used options.

Regards

The OP is not on a GNU based platofrm I guess. try perl:

#!/bin/ksh
sec()
{
        perl -e '
                use POSIX qw(strftime);
                $fmt = "%s";  # %s = seconds in epoch
                $mday = substr("$ARGV[0]", 7, 2);
                $mon =  substr("$ARGV[0]", 4 ,2);
                $year = substr("$ARGV[0]", 0 ,4);    
                $hour = substr("$ARGV[0]", 9 ,2);    
                $min =  substr("$ARGV[0]", 11 ,2);                 
                $sec = substr("$ARGV[0]", 13 ,2);    
                $secs =
                  strftime($fmt, $sec, $min, $hour, $mday , $mon - 1, $year - 1900, -1, -1, -1);
                print int $secs;
                ' "$1"
}

today=$( date "+%Y%m%d%H%M%S" )
today=$( sec $today )
oldat=$( sec "20080313101504" )
ddiff=$(( $today - $oldat ))
echo "$today minus $oldat = $ddiff which is \c"
if [[ $ddiff -lt 259200 ]] ; then
   echo "less than three days \c"
else
   echo "greater than three days \c"
fi  
echo " (259200 seconds)" 

Thanks Jim,

I tried the above code and i noticed you had the substr co ordinates wrong.

i changed it to:

$mday = substr("$ARGV[0]", 6, 2);
$mon = substr("$ARGV[0]", 4 ,2);
$year = substr("$ARGV[0]", 0 ,4);
$hour = substr("$ARGV[0]", 8 ,2);
$min = substr("$ARGV[0]", 10 ,2);
$sec = substr("$ARGV[0]", 12 ,2);

however whenever i run the script i get:

0 minus 0 = 0 which is less than three days

the current date is: 20080318110043 and the test date is the same you used. :confused:

Hmm. Maybe the coordinates I had were correct.... or not -
here is an updated version

#!/bin/ksh
sec()
{
        perl -e '
                use POSIX qw(strftime);
                $fmt = "%s";  # %s = seconds in epoch
                $mday = substr("$ARGV[0]", 6, 2);
                $mon =  substr("$ARGV[0]", 4 ,2);
                $year = substr("$ARGV[0]", 0 ,4);    
                $hour = substr("$ARGV[0]", 8 ,2);    
                $min =  substr("$ARGV[0]", 10 ,2);                 
                $sec = substr("$ARGV[0]", 12 ,2);    
                $secs =
                  strftime($fmt, $sec, $min, $hour, $mday , $mon - 1, $year - 1900, -1, -1, -1);
                print int $secs;
                ' "$1"
}
echo "today is = `date` `date "+%s"` as a sanity check"
today=$( date "+%Y%m%d%H%M%S" )
today=$( sec $today )
oldat=$( sec "20080313101504" )
ddiff=$(( $today - $oldat ))
echo "$today minus $oldat = $ddiff which is \c"
if [[ $ddiff -lt 259200 ]] ; then
   echo "less than three days \c"
else
   echo "greater than three days \c"
fi  
echo " (259200 seconds)" 


output

csadev:/home/jmcnama> ddiff.pl
today is = Tue Mar 18 09:39:21 CDT 2008 1205851161 as a sanity check
1205851161 minus 1205421304 = 429857 which is greater than three days  (259200 seconds)

Using Jim's clever way of working out the seconds i ended up getting it to work using Perl's Time::Local library.

Here is my eventual code:

#!/bin/ksh

epoch_sec()
{
        perl -e '
                use Time::Local;

                $fmt = "%s";  # %s = seconds in epoch
                $mday = substr("$ARGV[0]", 6, 2);
                $mon =  substr("$ARGV[0]", 4 ,2);
                $year = substr("$ARGV[0]", 0 ,4);
                $hour = substr("$ARGV[0]", 8 ,2);
                $min =  substr("$ARGV[0]", 10 ,2);
                $sec = substr("$ARGV[0]", 12 ,2);
                $time = timelocal($sec,$min,$hour,$mday,$mon,$year);
                print int $time;
                ' "$1"
}

time_now=$( date -u "+%Y%m%d%H%M%S" )

echo ""
echo "Deletion Progress. Directory ${my_dir}. Time Now: $time_now."
echo "========================================================================================"

file_count=0
delete_file_count=0

for file in `find ${my_dir}/ -name "*_report_??????????????.gz" -print`
do
        file_count=`expr $file_count + 1`

        filedate=`echo $file | sed -e 's/^.*_report_//g' -e 's/\.gz$//g'`
        today=$( date -u "+%Y%m%d%H%M%S" )

        # Calculate Epochs
        timenow_epoch=$( epoch_sec $today )
        file_epoch=$( epoch_sec $filedate )

        # Work out difference
        diff=$(( $timenow_epoch - $file_epoch ))

        # 259200 = 3 days
        if [[ $diff -gt 259200 ]] ; then
                echo ""
                echo "File: [$file]"
                echo "   File Date: $filedate"
                echo "   Remove [$file]!."
                echo ""
                delete_file_count=`expr $delete_file_count + 1`
          
                rm -f $file 
        fi
done

I didnt use -mtime Franklin52 as the file names contain the dates which need to be used NOT the modification date :).

:smiley:

Once again many thanks to Jim and Era and others who helped me :b: :slight_smile: