Следующее работает как задумано:
my $dt = DateTime->new(
year => 2012,
month => 6,
day => 30,
hour => 23,
minute => 59,
second => 60,
time_zone => $utc,
);
Однако вызов parse_datetime
эффективно делает следующее:
my $dt = DateTime->new(
year => 2012,
month => 6,
day => 30,
hour => 23,
minute => 59,
second => 60,
time_zone => 'floating',
);
$dt->set_time_zone($utc);
Выше приведено DateTime->new
к метанию исключение, которое приводит к получению сообщения об ошибке.
Но я не могу ошибиться DateTime :: Format :: Strptime.
Часовой пояс, найденный в анализируемой строке (например, если используется %z
), передается в ->new
, а часовой пояс, передаваемый в конструктор, передается в ->set_time zone
. Это позволяет выполнять преобразование часового пояса, когда часовой пояс указан в обоих местах.
Например, допустим, что входное значение равно 2020-03-25T00:00:00-05:00
(обратите внимание на смещение). И скажем, вы передали time_zone => 'UTC'
и соответствующий шаблон в конструктор. Результирующий объект DateTime будет для 5 утра UT C вместо полуночи UT C -05: 00. Это хорошо.
Интересно, что можно создавать объекты DateTime с использованием плавающего часового пояса с 60
в течение секунд.
$ perl -MDateTime -e'
CORE::say
DateTime
->new(
year => 2012,
month => 6,
day => 30,
hour => 23,
minute => 59,
second => 60,
time_zone => "UTC",
)
->set_time_zone("floating");
'
2012-06-30T23:59:60
Но DateTime противоречиво разрешает it.
$ perl -MDateTime -e'
CORE::say
DateTime
->new(
year => 2012,
month => 6,
day => 30,
hour => 23,
minute => 59,
second => 60,
time_zone => "floating",
);
'
Invalid second value (60)
at -e line 1.
Подано сообщение об ошибке.
В качестве обходного пути включите часовой пояс в анализируемые данные.
my $ymdhms_parser = DateTime::Format::Strptime->new(
pattern => '%F %T%z',
locale => 'en_US',
strict => 1,
on_error => 'croak',
);
my $dt = $ymdhms_parser->parse_datetime($date.'Z');