Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Simple (I thought) time comparison?

by sjessie (Novice)
on Dec 19, 2016 at 23:09 UTC ( [id://1178137]=perlquestion: print w/replies, xml ) Need Help??

sjessie has asked for the wisdom of the Perl Monks concerning the following question:

Greetings All. I thought this should be really simple using Time::Piece, however I am not getting the result I would expect. As part of a larger script, I just want find if a datetime in a specific format is within the last 30 minutes.

use strict; use warnings; use Time::Piece; my $ctime = Time::Piece->new; my $oldtime = Time::Piece->strptime('Dec 19 17:01:00 2016', '%b %d %T +%Y'); print "The current time is $ctime\n"; print "The old time is $oldtime\n"; my $halfago = $ctime - 1800; print "Half an hour ago is $halfago\n"; if ($oldtime > $halfago) { print "Old time is within a half hour\n"; } else { print "Old time is outside a half hour\n"; }

I ran the script just now, and this is the output:

The current time is Mon Dec 19 17:07:06 2016 The old time is Mon Dec 19 17:01:00 2016 Half an hour ago is Mon Dec 19 16:37:06 2016 Old time is outside a half hour

It doesn't matter what time I set in the script, it always drops down to the else block. I though perhaps I saw something about strptime and GMT, but now I can't find that page again... I think I am probably totally frazzled at this point and am missing something simple. Thanks!

Replies are listed 'Best First'.
Re: Simple (I thought) time comparison?
by davido (Cardinal) on Dec 19, 2016 at 23:40 UTC

    Your constructor sets time in terms of localtime. Your half-hour calcuation subtracts a half hour from the object that was based on localtime. Your $oldtime object is constructed using strptime, and is not setting a timezone offset.

    You can see this in action by adding the following lines:

    print "\$ctime tzoffset: ", $ctime->tzoffset, "\n"; print "\$halfago tzoffset: ", $halfago->tzoffset, "\n"; print "\$oldtime tzoffset: ", $oldtime->tzoffset, "\n";

    which will produce output along the line of:

    $ctime tzoffset: -25200 $halfago tzoffset: -25200 $oldtime tzoffset: 0

    (...except that the offsets will be in your own localtime, not mine.)

    You might be able to set the $oldtime->tzoffset($some_value), or preferably by providing a %Z or %z field to strptime.


    Dave

Re: Simple (I thought) time comparison?
by hippo (Bishop) on Dec 19, 2016 at 23:43 UTC

    Replacing your time with one here which should trigger the if branch (rather than the else) I am unable to reproduce your findings.

    $ perl 1178137.pl The current time is Mon Dec 19 23:40:37 2016 The old time is Mon Dec 19 23:31:00 2016 Half an hour ago is Mon Dec 19 23:10:37 2016 Old time is within a half hour

    If you think you have timezone (or DST) problems it is always best to output the epoch times as a diagnostic aid. I suggest you give that a try.

      Strange... Or more likely I don't understand what is going on here, being a noob. Your suggestion about using the epochs helped me at least figure out a way around my problem. If I add:

      $oldtime = $oldtime - $ctime->tzoffset;

      I get the desired results, although my statement

      print "The old time is $oldtime\n";

      Then prints a formatted time 6 hours in the future. I needed to update that to

      print "The old time is ", $oldtime + $ctime->tzoffset, "\n";

      To get it to print the correct time. That isn't a great concern as I actually won't ever be using the print statements, only the calculations, in the bigger script I am retrofitting. Still, it shows I am missing something basic in how this all works and that concerns me.

        Note: where I am tzoffset is -21600 (-6 hours, CST).

Re: Simple (I thought) time comparison?
by haukex (Archbishop) on Dec 20, 2016 at 14:08 UTC

    Hi sjessie,

    As hippo and davido have already identified, the issue is with time zones. Personally, I like to use the DateTime module since it includes a lot of functionality, including time zones. (Because of that it's a little more heavyweight, but that should only be noticeable if your script does a lot of date/time calculations, so personally I just throw all of my date/time stuff at the DateTime suite because it can handle it all, and only consider using other modules as an optimization if necessary.)

    Anyway, here are two methods that work. Note that this handles time zones properly, for example try changing the first "America/New_York" to "America/Chicago". Update: Just to emphasize this, the key is that all the DateTime objects involved in the calculations and comparisons need to have their time zones set properly.

    use warnings; use strict; use DateTime; use DateTime::Format::Strptime; my $old_str = 'Dec 19 17:01:00 2016'; # normally, $now = DateTime->now my $now = DateTime->new(year=>2016,month=>12,day=>19, hour=>17,minute=>7,second=>6,time_zone=>'America/New_York'); print "now=", $now->strftime('%Y-%m-%d-%H-%M-%S %Z'), "\n"; my $strp = DateTime::Format::Strptime->new( on_error=>'croak', pattern => '%b %d %T %Y', time_zone=>'America/New_York' ); my $old = $strp->parse_datetime($old_str); print "old=", $old->strftime('%Y-%m-%d-%H-%M-%S %Z'), "\n"; # approach one: difference my $diff_sec = $now->subtract_datetime_absolute($old) ->in_units('seconds'); print "diff_sec: $diff_sec (", sprintf("%.1f",$diff_sec/60), " minutes)\n"; # approach two: compare to another DateTime my $halfago = $now->clone->subtract(minutes=>30); print "halfago=", $halfago->strftime('%Y-%m-%d-%H-%M-%S %Z'), "\n"; # note comparators are overloaded for DateTime objects print "halfago ", ($halfago>$old?'>':'<='), " old\n";

    Hope this helps,
    -- Hauke D

Re: Simple (I thought) time comparison?
by sjessie (Novice) on Dec 20, 2016 at 16:02 UTC

    Wohoo! Thanks for helping out a goofy noob, Monks! You guys rock! I hadn't really touched Perl (I know, blasphemy) for the last 10 years or so, so I really appreciate you all getting me back on the road. It is coming back to me. Slowly.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1178137]
Approved by davido
Front-paged by davido
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chilling in the Monastery: (5)
As of 2024-04-24 19:06 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found