Reputation: 27
Please see the Perl code first.
use DateTime::Format::Strptime;
my $strp = DateTime::Format::Strptime->new(
pattern => '%Y-%m-%d%H:%M:%S',
);
my $dt = $strp->parse_datetime('2015-07-0611:21:33');
print $dt->epoch, "\n";
print $dt->ymd . ' ' . $dt->hms, "\n";
$dt->set_time_zone( 'local' );
print $dt->epoch,"\n";
print $dt->ymd . ' ' . $dt->hms, "\n";
output:
1436181693
2015-07-06 11:21:33
1436149293
2015-07-06 11:21:33
I want to change the time zone.
$dt->epoch
changes, but $dt->ymd
and $dt->hms
are unchanged.
I do not know why.
Help me please.
Upvotes: 1
Views: 616
Reputation: 54323
You are dealing with a floating time zone.
my $dt = $strp->parse_datetime('2015-07-0611:21:33');
say $dt->time_zone;
On my machine, which is in the Europe/Berlin timezone, this gives:
DateTime::TimeZone::Floating=HASH(0x1dd1f68)
The DateTime docs have this to say:
If the old time zone was a floating time zone, then no adjustments to the local time are made, except to account for leap seconds. If the new time zone is floating, then the UTC time is adjusted in order to leave the local time untouched.
The output of the rest of your program on my machine is:
1436181693
2015-07-06 11:21:33
1436174493
2015-07-06 11:21:33
The difference between the two epoch values is 7200
. That's two hours.
$dt->set_time_zone( 'local' );
say $dt->time_zone;
# DateTime::TimeZone::Europe::Berlin=HASH(0x27dc1d8)
Let's look at the timezone thing. DateTime::TimeZone::Floating is used when there is no timezone given in a DateTime object. Setting the timezone to local
updates the object.
It assumes that the floating timezone is UTC time, so it adds one hour for UTC to Berlin, and another one because at that time, Berlin has daylight saving time.
That's all a bit theoretical. The point is, setting the time_zone
on a
DateTime object does not convert it immediately. If you start with a floating timezone, it changes the timezone attached to the date and time. That's a difference. Only when you call it again, it will convert.
use strict;
use warnings;
use feature 'say';
use DateTime::Format::Strptime;
my $strp = DateTime::Format::Strptime->new(
pattern => '%Y-%m-%d%H:%M:%S',
);
my $dt = $strp->parse_datetime('2015-07-0611:21:33');
say $dt->time_zone;
say $dt->epoch;
say $dt;
say "changing to UTC...";
$dt->set_time_zone( 'UTC' );
say $dt->time_zone;
say $dt->epoch;
say $dt;
say "changing to local...";
$dt->set_time_zone( 'local' );
say $dt->time_zone;
say $dt->epoch;
say $dt;
Here is the output on my machine:
DateTime::TimeZone::Floating=HASH(0x1887f98)
1436181693
2015-07-06T11:21:33
changing to UTC...
DateTime::TimeZone::UTC=HASH(0x177dfd8)
1436181693
2015-07-06T11:21:33
changing to local
DateTime::TimeZone::Europe::Berlin=HASH(0x19a84c0)
1436181693
2015-07-06T13:21:33
As you can see, the first set_time_zone
makes the DateTime object not be in a floating timezone any more. The second call converts from one actual timezone to another, and the time changes.
Upvotes: 7