Perl Date :: Manip обнаруживает неправильный часовой пояс для EST и EDT - PullRequest
1 голос
/ 18 июня 2019

У меня есть сервер, где системный часовой пояс EST

Он был установлен с

# timedatectl set-timezone EST
# timedatectl 
  Local time: Tue 2019-06-18 03:29:42 EST
  Universal time: Tue 2019-06-18 08:29:42 UTC
    RTC time: Tue 2019-06-18 08:29:42
    Time zone: EST (EST, -0500)
    NTP enabled: yes
    NTP synchronized: no
    RTC in local TZ: no
    DST active: n/a

Затем в моем perl коде я пытаюсь определить часовой пояс и преобразовать время в UTC. И по какой-то причине часовой пояс определяется как EDT. В настоящее время (лето) EST является одним из наших после EDT

Мой код Perl

# cat test.cgi # code file is named test.cgi
#!/usr/bin/perl -w

use Date::Manip;

print "Local time: ".UnixDate("now","%Y-%m-%d %H:%M:%S %Z")."\n";

# get local system timezone
my $TZ = UnixDate("now","%Z");

# convert time to GMT 
my $dtlocal =  Date_ConvTZ(ParseDate(UnixDate("now","%g")),$TZ,"GMT");

# format GMT time
my $dt =  UnixDate($dtlocal,"%Y-%m-%d %H:%M:%S"); 

print "Timezone: $TZ\n";
print "UTC time: $dt\n";

И я выполняю сценарий

# date
Tue Jun 18 04:17:56 EST 2019
# date -u
Tue Jun 18 09:17:58 UTC 2019
# ./test.cgi 
Local time: 2019-06-18 04:18:00 EDT
Timezone: EDT
UTC time: 2019-06-18 08:18:00

В чем может быть причина того, что Date :: Manip неправильно определяет часовой пояс? Есть ли другой хороший способ определения часового пояса системы?

UPDATE.

Я только что обнаружил, что POSIX правильно определяет часовой пояс. Итак, проблема с датой :: Manip

 use POSIX;
 print strftime("%Z", localtime()), "\n";

Ответы [ 2 ]

3 голосов
/ 18 июня 2019

Один из способов найти часовой пояс - DateTime :: TimeZone .Используется с DateTime для других нужд

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

use DateTime; 
use DateTime::TimeZone; 

my $tz = DateTime::TimeZone->new(name => "local");
say $tz->name();                                   #--> America/Los_Angeles


my $dt = DateTime->now(time_zone => "local");
say "local: $dt";                             #--> local: 2019-06-18T09:57:58

$dt->set_time_zone("UTC"); 
say "UTC: $dt";                               #--> UTC: 2019-06-18T16:57:58

Подробности см. В документации, по крайней мере, для конструктора DateTime :: TimeZone .

Также обратите внимание на их рекомендацию не использовать «короткие» имена («EST»), под $ tz-> short_name ...


Как только вы работаете с DateTime, также может иметь смещение

my $dt = DateTime->now(time_zone => 'local');

say $dt->offset/(60*60);                       #--> -7

say $dt->strftime("%z");                       #--> -0700

Метод смещение возвращает смещение часового пояса в секундах.

strftime предлагают форматы, которые мы обычно ожидаем;В документах говорится: " любое отклонение от стандарта POSIX, вероятно, является ошибкой. " Пример полной отметки времени: $dt->strftime('%Y-%m-%dT%H:%M:%S%z').

2 голосов
/ 18 июня 2019

В документации Date :: Manip :: TZ есть раздел Определение часового пояса системы . Если вы прокрутите немного вниз, вы найдете список методов, которые используются (и в каком порядке) для определения часового пояса системы, в зависимости от того, работаете ли вы под Unix или Windows.

Судя по тому, что вы разместили в вопросе, похоже, что он правильно читает местное время, но не может определить правильный часовой пояс, поэтому вы сможете найти основную проблему, пройдя по списку TZ. методы идентификации, используемые в вашей ОС. (то есть для Unix, проверьте $::TZ, затем параметры среды zone и TZ, затем /etc/TIMEZONE и т. д., пока не найдете тот, который существует и имеет неправильный часовой пояс в списке)

...