in reply to Re: Time::Piece reversibility
in thread Time::Piece reversibility

That's very helpful, @cguevara, thank you.

So to summarize that result, Time::Piece->strptime always returns a gmtime instance (tzoffset = 0). If you want it in localtime, you need to convert that to a localtime instance. Correct?

My follow-up question, then, is how to achieve that same result if the time zone is not part of the date string? IOW, I want to parse "2017-06-19 10:07:42" into a localtime Time::Piece instance with epoch seconds of 1497892062 and a tzoffset of -25200.

I can use Time::Local and do this:

$ENV{'TZ'} = 'America/Los_Angeles'; my $epoch = timelocal(42,07,10,19,05,2017); print "timelocal epoch: $epoch\n"; print "timelocal date: ", scalar localtime($epoch), "\n";

Produces:

timelocal epoch: 1497892062 timelocal date: Mon Jun 19 10:07:42 2017

But since strptime() always returns gmtime, is there a way to do that with Time::Piece currently? It will be treated as UTC and converting it to a localtime() will offset it by 7 hours (in this case).

#!/usr/bin/env perl use strict; use warnings; use Time::Local; use Time::Piece; $ENV{'TZ'} = 'America/Los_Angeles'; my $datestr = '2017-06-19 10:07:42'; my $gmt = Time::Piece->strptime($datestr, '%Y-%m-%d %H:%M:%S'); my $local = localtime($gmt->epoch); print "gmt epoch: ", $gmt->epoch, "\n", "local epoch: ", $local->epoch, "\n", "datestr: $datestr\n", "T::P gmt strftime: ", $gmt->strftime, "\n", "T::P local strftime: ", $local->strftime, "\n" ;

Produces

gmt epoch: 1497866862 local epoch: 1497866862 datestr: 2017-06-19 10:07:42 T::P gmt strftime: Mon, 19 Jun 2017 10:07:42 UTC T::P local strftime: Mon, 19 Jun 2017 03:07:42 PDT

Of course you could always append the zone that you want to the date string, but that's cheating ;)

Replies are listed 'Best First'.
Re^3: Time::Piece reversibility
by cguevara (Vicar) on Jun 18, 2017 at 20:19 UTC
    #!/usr/bin/env perl use strict; use warnings; use Test::More ('no_plan'); use Time::Piece; $ENV{'TZ'} = 'America/Los_Angeles'; my $datestr = '2017-06-19 10:07:42'; my $t = localtime->strptime($datestr, '%Y-%m-%d %H:%M:%S'); is($Time::Piece::VERSION, 1.31); is($t->epoch, 1497892062); is($t->tzoffset, -25200); is($t->strftime, 'Mon, 19 Jun 2017 10:07:42 PDT'); is($t->strftime('%Y-%m-%d %H:%M:%S'), $datestr);

      Thanks again. So localtime()->strptime does behave differently.

      So localtime()->strptime's handling of time zones is the underlying issue. Certainly these two should be equivalent, no?

      #!/usr/bin/env perl use strict; use warnings; use Test::More ('no_plan'); use Time::Piece; $ENV{'TZ'} = 'America/Los_Angeles'; my @tests = ( ['2017-06-19 10:07:42', '%Y-%m-%d %H:%M:%S'], ['2017-06-19 10:07:42-0700', '%Y-%m-%d %H:%M:%S%z'], ); is($Time::Piece::VERSION, 1.31); foreach my $test (@tests) { my ($datestr, $fmt) = @$test; my $t = localtime->strptime($datestr, $fmt); is($t->epoch, 1497892062); is($t->tzoffset, -25200); is($t->strftime, 'Mon, 19 Jun 2017 10:07:42 PDT'); is($t->strftime('%Y-%m-%d %H:%M:%S'), $datestr); }

      Result

      ok 1 ok 2 ok 3 ok 4 ok 5 not ok 6 # Failed test at ./try7 line 22. # got: '1497917262' # expected: '1497892062' ok 7 not ok 8 # Failed test at ./try7 line 24. # got: 'Mon, 19 Jun 2017 17:07:42 PDT' # expected: 'Mon, 19 Jun 2017 10:07:42 PDT' not ok 9 # Failed test at ./try7 line 25. # got: '2017-06-19 17:07:42' # expected: '2017-06-19 10:07:42-0700' 1..9 # Looks like you failed 3 tests of 9.

        I've only used localtime->strptime() to get a localtime instance from a time without a time zone.

        To get a localtime instance directly from a time with a time zone, I just combine localtime and Time::Piece->strptime()->epoch.

        #!/usr/bin/env perl use strict; use warnings; use Test::More ('no_plan'); use Time::Piece; $ENV{'TZ'} = 'America/Los_Angeles'; my $datestr = '2017-06-19 10:07:42-0700'; my $t = localtime(Time::Piece->strptime($datestr, '%Y-%m-%d %H:%M:%S%z +')->epoch); is($Time::Piece::VERSION, 1.31); is($t->epoch, 1497892062); is($t->tzoffset, -25200); is($t->strftime, 'Mon, 19 Jun 2017 10:07:42 PDT'); is($t->strftime('%Y-%m-%d %H:%M:%S%z'), $datestr);