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 Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Subtracting two dates

Status
Not open for further replies.

unixfreak

ISP
Oct 4, 2003
632
0
0
GB
omg, how can this be so difficult? I've spent all morning Googling and reading docs that just never get to the point. I just need to check if two dates are more than 24h apart but can't even find a simple command that can convert a date into seconds...

Any ideas?

-----
Cheers,
Henrik Morsing
Join us on irc://chat.freenode.net channel ##aix
 
where are the dates comming from?

are they in a SQL DB, if so use the SQL date functionality.

if you are recieving them via a web form, I use JavaScript to do it date validation.

or in perl you could try the Date::Calc module.

"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you."

"If a shortcut was meant to be easy, it wouldn't be a shortcut, it would be the way!
 
Thanks, one is from 'date' or whatever you want to use (just need the current date), the other is grep'ed from 'dsmc' output. Only have Unix tools available and use ksh.

> or in perl you could try the Date::Calc module.

I'm sorry but it's statements like that I've been looking at all day but doesn't help me much. By the way, Date::Calc is at least the third module I've seen references to to do this, however, no references telling me how to actually do it.

-----
Cheers,
Henrik Morsing
Join us on irc://chat.freenode.net channel ##aix
 
Yes, there are quite a few modules for dates and times. I personally favour the DateTime series of modules. Each to their own, really.

You'll have to subtract the dates, to see how far apart they are, then compare them with a DateTime::Duration object that represents 24 hours. The 'compare' function returns 1 if the first duration is greater (i.e. the difference is greater than 24 hours), 0 if they're equal and -1 if the second is greater (i.e. less than 24 hour difference). This should be enough to get you started:
Code:
use DateTime;
use DateTime::Duration

my $duration = DateTime::Duration->new( hours => 24 );

my $dt1 = DateTime->new( year => 2009, month => 6, day => 22 );
my $dt2 = DateTime->new( year => 2009, month => 6, day => 21 );

if ( DateTime::Duration->compare( $dt1 - $dt2, $duration ) ) {
   # difference is > 24 hours
}
 
Here's one way you could parse the date output:

Code:
#!/usr/bin/perl -w

use Time::Local;

my %months = ( Jan => 0, Feb => 1, Mar => 2, Apr => 3, May =>  4, Jun =>  5,
               Jul => 6, Aug => 7, Sep => 8, Oct => 9, Nov => 10, Dec => 11, );

my $d = `date`;
my $time;

# Wed Jun 24 23:43:22 AUSEST 2009

if ($d =~ /^\w+ (\w+) (\d+) ([\d:]+) \S+ (\d+)$/) {
        my $mon = $months{$1};
        my $mday = $2;
        my ($hour, $min, $sec) = split(/:/, $3);
        my $year = $4 - 1900;
        $time = timelocal($sec,$min,$hour,$mday,$mon,$year);
        print "time is $time\n";
} else {
        die "couldn't parse date output: $d";
}

If you do the same for the date string from DSMC, you can just subtract the two results and if the difference is greater than 86400 they're more than a day apart.

This is a pretty clunky and locale-dependent way of doing it, I'm sure there are neater ways in the modules available.

Annihilannic.
 
I'm sorry but it's statements like that I've been looking at all day but doesn't help me much
why, doesn't the module work?

I've not used it so sorry if it's a dud one :-(

"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you."

"If a shortcut was meant to be easy, it wouldn't be a shortcut, it would be the way!
 
1DMF: I'm sure the module works, but modules don't do anything, just load a bunch of routine definitions. Not going to subtract dates in itself.

ishnid: Thanks, but the DateTime module is not a part of my install

Annihilannic: Thanks, trying to get that to work but doesn't run clean at the moment. Will try to correct it.

-----
Cheers,
Henrik Morsing
Join us on irc://chat.freenode.net channel ##aix
 
OIC - you want us to write the code and do everything for you?

"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you."

"If a shortcut was meant to be easy, it wouldn't be a shortcut, it would be the way!
 
1DMF said:

> OIC - you want us to write the code and do everything for you?

No, but it's like you asking "How would I get a web server with PHP up and running?" and I'd go "AIX". Google is quite capable of telling me what Perl modules exist, doesn't really help me one bit in finding a command that can do it sensibly or even just get any command to do it which I can't seem to do. What are you doing here?

ishnid said:

> You could always install it?

No, need something that's in the standard build but thanks.

Thanks, got something to go have a look at anything, I'll probably come up with something. Just find it strange with such a comprehensive tool as Perl + four add-on modules for time alone, that you can't just do this.

-----
Cheers,
Henrik Morsing
Join us on irc://chat.freenode.net channel ##aix
 
in this whole thread you've not supplied one piece of code ,or shown us how far you've got, where you are stuck.

nothing, all you've done is moan and dissed our suggestions.


No, need something that's in the standard build but thanks.[/quite]

installing modules or having dependencies on modules outside the 'basic install' when needing to perform specific tasks is standard to perl, that's what perl is all about!

come on throw us a bone!

"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you."

"If a shortcut was meant to be easy, it wouldn't be a shortcut, it would be the way!
 
Ok, I was kinda hoping that a command could do it, rather than code. Or a couple of commands stringed together. If there was a command like 'time(2/3/9)' that would output seconds since epoch that would help immensely. For some reason there's a command to print the current time in seconds but not one to take an arbitrary command and output seconds which would have made it easy to do.

Don't think I've dissed or moaned, the code suggestions here are fine but when you're dealing with 300 servers and building new ones from scratch, you don't want to have to deal with additional software add-ons everytime. I'm looking into the code based on the Time::Local module, which I have, just need to correct for some local differences. Again though, it's quite a large chunk of code when I was hoping I could do something like perl -e 'time(now) - time($date)'.

Thanks

-----
Cheers,
Henrik Morsing
Join us on irc://chat.freenode.net channel ##aix
 
I'm assuming you have to supply the script to perform the function?

how is supplying a .pm at the same time as a .pl such a biggie?

there are a few ways of getting back to epoch...
Code:
use POSIX;

my $unixtime = mktime ($sec, $min, $hour, $day, $mon, $year, $wday, $yday);

Code:
DateTime::Format::Epoch - Convert DateTimes to/from epoch seconds

SYNOPSIS 
  use DateTime::Format::Epoch;

  my $dt = DateTime->new( year => 1970, month => 1, day => 1 );
  my $formatter = DateTime::Format::Epoch->new(
                      epoch          => $dt,
                      unit           => 'seconds',
                      type           => 'int',    # or 'float', 'bigint'
                      skip_leap_secondss => 1,
                      start_at       => 0,
                      local_epoch    => undef,
                  );

  my $dt2 = $formatter->parse_datetime( 1051488000 );
   # 2003-04-28T00:00:00

  $formatter->format_datetime($dt2);
   # 1051488000

or

Code:
Using the internal localtime or gmtime functions, localtime and gmtime return an array: 
my $time = time;	# or any other epoch timestamp 
my @months = ("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec");
my ($sec, $min, $hour, $day,$month,$year) = (localtime($time))[0,1,2,3,4,5,6]; 
# You can use 'gmtime' for GMT/UTC dates instead of 'localtime'
print "Unix time ".$time." converts to ".$months[$month]." ".$day.", ".($year+1900);
print " ".$hour.":".$min.":".$sec."\n";

or

Code:
For more advanced date manipulation, try using the DataTime module: 

use DateTime;
$dt = DateTime->from_epoch( epoch => $epoch );

$year   = $dt->year;
$month  = $dt->month; # 1-12 - also mon
$day    = $dt->day; # 1-31 - also day_of_month, mday
$dow    = $dt->day_of_week; # 1-7 (Monday is 1) - also dow, wday
$hour   = $dt->hour; # 0-23
$minute = $dt->minute; # 0-59 - also min
$second = $dt->second; # 0-61 (leap seconds!) - also sec
$doy    = $dt->day_of_year; # 1-366 (leap years) - also doy
$doq    = $dt->day_of_quarter; # 1.. - also doq
$qtr    = $dt->quarter; # 1-4
$ymd    = $dt->ymd; # 1974-11-30
$ymd    = $dt->ymd('/'); # 1974/11/30 - also date
$hms    = $dt->hms; # 13:30:00
$hms    = $dt->hms('|'); # 13!30!00 - also time

or

Code:
Converting from normal date to epoch in Perl
Using the Time::Local module: 
use Time::Local;
my $time = timelocal($sec,$min,$hours,$day,$month,$year); 
# replace 'timelocal' with 'timegm' if your input date is GMT/UTC

Using the DataTime module: 

use DateTime;
$dt = DateTime->new( year   => 1974, month  => 11, day    => 30, hour   => 13, minute => 30, 
	second => 0, nanosecond => 500000000, time_zone => 'Asia/Taipei' );
$epoch_time  = $dt->epoch;

"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you."

"If a shortcut was meant to be easy, it wouldn't be a shortcut, it would be the way!
 
No matter how many servers you're dealing with, having a pure-Perl module like DateTime on each is no more difficult than distributing the script you're writing. It's just a matter of copying a file into a directory that's in your Perl library, so your scripts know where to find it. Alternatively, you can use the standard FindBin module to specify a relative directory where dependent modules are located, or package the lot up with the 'pp' utility that comes with PAR.

If you're still determined to only use core modules, here's another suggestion:
Code:
use POSIX;

my $t1 = POSIX::mktime( 0, 0, 0, 22, 5, 109 );
my $t2 = POSIX::mktime( 0, 0, 0, 21, 5, 109 );

print "Number of seconds difference: " . abs( $t1-$t2 ) . "\n";

Run "perldoc POSIX" to get the details on the arguments to the function.
 
Right, this is my final script, just tested it and it works! Thanks :)

#!/usr/bin/perl -w

use warnings;
use Time::Local;

my $line = `dsmc q filespace / | tail -1`;
#my $line = " 1 25/06/09 03:04:18 JFS2 /";

if (my ($day, $month, $year, $hour, $min, $sec) = $line =~ m/^\s*\d+\s+([\d]+)\/([\d]+)\/([\d]+)\s+([\d]+):([\d]+):([\d]+)/) {

my $time_backup = timelocal($sec,$min,$hour,$day,--$month,$year);
my $time_local = time();

my $time_diff = $time_local - $time_backup;

if ($time_diff > 86400) {
print "Backup too old\n";
}

}


-----
Cheers,
Henrik Morsing
Join us on irc://chat.freenode.net channel ##aix
 
so you finally succumb to using the Time::Local modle eh!

Glad you got a working script, but when posting code can you surround it in 'code' tags please :)



"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you."

"If a shortcut was meant to be easy, it wouldn't be a shortcut, it would be the way!
 
Time::Local was there, Date:Time was the one I didn't want to install :)

This site isn't intuitive to use which is why I can't even figure out how to quote people...

-----
Cheers,
Henrik Morsing
Join us on irc://chat.freenode.net channel ##aix
 
this forum is very old and handrolled in coldfusion , so yes , its user friendlyness could certainly be improved.

but it does use the same [ open square bracket , code or quote , closed square bracket ] , syntax

"In complete darkness we are all the same, only our knowledge and wisdom separates us, don't let your eyes deceive you."

"If a shortcut was meant to be easy, it wouldn't be a shortcut, it would be the way!
 
Incidentally, perl -w and use warnings; are equivalent, perhaps you meant to put use strict;?

Annihilannic.
 
Yeah, use strict is a good idea although slightly annoying. I think the 'use warnings' has been pasted in from various snippets of code though, I'll remove the -w, it's neater

-----
Cheers,
Henrik Morsing
Join us on irc://chat.freenode.net channel ##aix
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top