vlatkovr
vlatkovr

Reputation: 19

Perl date comparison doesn't work

I am trying to do some date comparison in Perl but seems it is not working as expected. What might I be doing wrong?

my $lCurrentTime = Time::Piece->new;
my $l15MinsAGo   = $lCurrentTime - 900;
my $lEffDate     = Time::Piece->strptime($opt_effdate, '%d-%m-%Y %H:%M:%S');

print("\n lCurrentTime = $lCurrentTime     l15MinsAGo = $l15MinsAGo     lEffDate = $lEffDate\n");

if ($lEffDate < $lCurrentTime) {
    print("Eff date $lEffDate is smaller than 15 mins ago $l15MinsAGo\n");
} elsif ($lEffDate >= $lCurrentTime) {
    print("Eff date $lEffDate is larger than 15 mins ago $l15MinsAGo\n");
}

This prints:

lCurrentTime = Fri Jun  2 10:32:53 2017     
l15MinsAGo = Fri Jun  2 10:17:53 2017     
lEffDate = Fri Jun  2 10:07:00 2017

Eff date Fri Jun  2 10:07:00 2017 is larger than 15 mins ago Fri Jun  2 10:17:53 2017

Any ideas?

Upvotes: 0

Views: 94

Answers (2)

Borodin
Borodin

Reputation: 126722

There are several problems here:

  • The test lEffDate < $lCurrentTime should be lEffDate < $l15MinsAGo

  • You are creating $lEffDate without a time zone, whereas $lCurrentTime is created with the local time zone, Daylight savings are current in effect, so the to are bound to differ

Also

  • Time::Piece exports localtime which overrides the built-in operator. It functions in the same way both as the original call and as a Time::Piece object according to how it is used

  • Please don't use hungarianNotationAndCamelCase. It's not very readable, expecially for those whose first language isn't English. Experienced Perl developers mostly use snake_case, and your leading l presumably means "longword", which is irrelevant on Perl

You can parse a date in the same time zone as the local one by calling strptime on $lCurrentTime instead of on the class name Time::Piece

Like this

use strict;
use warnings 'all';

use Time::Piece;
use Time::Seconds 'ONE_MINUTE';

my $opt_eff_date = '02-06-2017 10:00:00';

my $now         = localtime;
my $past_15mins = $now - 15 * ONE_MINUTE;
my $eff_date    = $now->strptime( $opt_eff_date, '%d-%m-%Y %H:%M:%S' );

print <<END;

now         = $now
past_15mins = $past_15mins
eff_date    = $eff_date

END

if ( $eff_date < $past_15mins ) {
    print "Effective date $eff_date is smaller than 15 mins ago $past_15mins\n";
}
else {
    print "Effective date $eff_date is larger than 15 mins ago $past_15mins\n";
}

output

now         = Fri Jun  2 10:36:26 2017
past_15mins = Fri Jun  2 10:21:26 2017
eff_date    = Fri Jun  2 10:00:00 2017

Eff date Fri Jun  2 10:00:00 2017 is smaller than 15 mins ago Fri Jun  2 10:21:26 2017

Upvotes: 2

Sobrique
Sobrique

Reputation: 53478

What timezone are you in?

This may enlighten you as to what is happening:

print $lEffDate -> epoch,"\n";
print $lCurrentTime -> epoch,"\n";

print $lEffDate -> tzoffset,"\n";
print $lCurrentTime -> tzoffset,"\n";

I suspect that (like me) the strptime date is zero offset, and the one you got from new is your timezone.

So there's a couple of hours different in the actual timestamps.

To correct this - there's a few different approaches:

  • Parse a timezone into your string, using %Z or %z.
  • Adjust the time by the timezone $time += $time->localtime->tzoffset;
  • Just work in 'UTC' - strptime is assuming it. So you can instead do $lCurrentTime = gmtime; I think.

Upvotes: 2

Related Questions