cajwine
cajwine

Reputation: 3160

Time::Piece (localtime/gmtime) calculation vs bash date

Have this bash script:

future="${1:-Dec 08 2017 22:00:00}"
t1=$(date -j -f "%b %d %Y %H:%M:%S" "$future" +%s)  #using OS X
t0=$(date +%s)

echo "Current: $(date)"
echo "Future : $future"
echo "Diff   : $(( $t1 - $t0 )) secs"

It prints:

Current: pi   8. december 2017 21:25:25 CET
Future : Dec 08 2017 22:00:00
Diff   : 2075 secs

The result (diff) is correct.

Now trying to do the same using perl:

use strict;
use warnings;
use feature 'say';

use Time::Piece;

my $format = '%b %d %Y %H:%M:%S';

my $future = shift // 'Dec 08 2017 22:00:00';
say "Future: $future";

say "localtime: ", scalar localtime();
say "gmtime   : ", scalar gmtime();

my $tf = Time::Piece->strptime($future, $format);
say 'localtime-diff : ', $tf-localtime();
say 'gmtime-diff    : ', $tf-gmtime();

it prints

Future: Dec 08 2017 22:00:00
localtime: Fri Dec  8 21:27:45 2017  #correct
gmtime   : Fri Dec  8 20:27:45 2017  #correct
localtime-diff : 5535 #incorrect (expecting 3600 secs less)
gmtime-diff    : 5535 #ok

What is wrong? Mean, why it prints the same diff for the localtime and gmtime but the scalar localtime and scalar gmtime prints different (and correct) strings?

EDIT: So, the main question is: how to get the same result as in bash using perl?

Upvotes: 3

Views: 636

Answers (1)

ikegami
ikegami

Reputation: 385647

Both localtime() and gmtime() return an object that represents now.


You are doing:

2017-12-08T22:00:00+00:00 - 2017-12-08T21:25:25+01:00   # $tf-localtime()
2017-12-08T22:00:00+00:00 - 2017-12-08T20:25:25+00:00   # $tf-gmtime()

It looks like you want to do

2017-12-08T22:00:00+01:00 - 2017-12-08T21:25:25+01:00

Using Time::Piece:

use Time::Piece qw( localtime );

my $future_str = 'Dec 08 2017 23:00:00';

my $format = '%b %d %Y %H:%M:%S';

my $future_dt = localtime->strptime($future_str, $format);
say $future_dt - localtime();  # 2241 (instead of 5841)

Using DateTime:

use DateTime::Format::Strptime qw( );

my $future_str = 'Dec 08 2017 23:00:00';

my $format = DateTime::Format::Strptime->new(
   pattern   => '%b %d %Y %H:%M:%S',
   locale    => 'en',
   time_zone => 'local',
   on_error  => 'croak',
);

my $future_dt = $format->parse_datetime($future_str);
say $future_dt->epoch - time();  # 2241 (instead of 5841)

Upvotes: 6

Related Questions