Håkon Hægland
Håkon Hægland

Reputation: 40778

Using strptime to parse timestamp relative to the local time

I am trying to do some date calculation relative to the current local time. For example:

use feature qw(say);
use strict;
use warnings;

use Time::Piece;

my $fmt = '%Y-%m-%d_%H:%M:%S';
my $timestamp = "2015-04-12_11:07:27";

# This gives incorrect $t1 relative to localtime
my $t1 = Time::Piece->strptime( $timestamp, $fmt );
my $t2 = localtime;

say "Local time: " . localtime;
say "Local time epoch: " . time;

say $t1->epoch();
say $t2->epoch();

my $timestamp1 = $t1->strftime( $fmt );
my $timestamp2 = $t2->strftime( $fmt );

say $timestamp1;
say $timestamp2;

my $delta = $t2 - $t1;

say $delta;

A sample output:

Local time: Sun Apr 12 12:21:49 2015
Local time epoch: 1428834109
1428836847
1428834109
2015-04-12_11:07:27
2015-04-12_12:21:49
-2738

Which clearly gives the a wrong time difference of -2738. ( It should be a positive number)

Upvotes: 0

Views: 777

Answers (2)

Toto
Toto

Reputation: 91518

If the date-time you parse has no time zone information, it's assumed to be UTC. You can see this by adding the following two lines in your script:

say "tzo1 = ",$t1->tzoffset;
say "tzo2 = ",$t2->tzoffset;

In Paris, the above outputs the following:

tzo1 = 0
tzo2 = 7200

You can override the default to be the local time zone by using the undocumented feature of using localtime instead of Time::Piece as the invocant.

$ perl -MTime::Piece -E'
   say Time::Piece->strptime("2015-04-12_11:07:27", "%Y-%m-%d_%H:%M:%S")->tzoffset;
   say localtime  ->strptime("2015-04-12_11:07:27", "%Y-%m-%d_%H:%M:%S")->tzoffset;
'
0
7200

Doing that minor change gives the answer you were expecting.

$ perl -MTime::Piece -E'
   say localtime->strptime("2015-04-12_11:07:27", "%Y-%m-%d_%H:%M:%S") - localtime;
'
5524

Upvotes: 4

Håkon Hægland
Håkon Hægland

Reputation: 40778

I think this can be done using Date::Time :

use feature qw(say);
use strict;
use warnings;

use DateTime;
use DateTime::Format::Strptime;
use DateTime::Duration;

my $strp = DateTime::Format::Strptime->new(
    pattern   => '%Y-%m-%d_%H:%M:%S',
    time_zone => 'local',
);

my $timestamp = "2015-04-12_11:07:27";
my $dt1 = $strp->parse_datetime( $timestamp );
my $dt2 = DateTime->now();
say $dt2->subtract_datetime_absolute( $dt1 )->seconds();

Upvotes: 2

Related Questions