Как установить часовой пояс для Perl localtime()?

В Perl я бы хотел посмотреть местное время в определенном часовом поясе. Я использовал эту технику:

$ENV{TZ} = 'America/Los_Angeles';
my $now = scalar localtime;
print "It is now $now\n";
# WORKS: prints the current time in LA

Однако это ненадежно - особенно если я добавлю другой вызов localtime() перед установкой $ENV {TZ}, он прерывается:

localtime();
$ENV{TZ} = 'America/Los_Angeles';
my $now = scalar localtime;
print "It is now $now\n";
# FAILS: prints the current time for here instead of LA

Есть ли лучший способ сделать это?

Ответы

Ответ 1

Используйте POSIX:: tzset.

use POSIX qw(tzset);

my $was = localtime;
print "It was      $was\n";

$ENV{TZ} = 'America/Los_Angeles';

$was = localtime;
print "It is still $was\n";

tzset;

my $now = localtime;
print "It is now   $now\n";
$ perl -v

This is perl, v5.8.8 built for x86_64-linux-thread-multi

Copyright 1987-2006, Larry Wall

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl".  If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.

$ perl tzset-test.pl
It was      Wed Apr 15 15:58:10 2009
It is still Wed Apr 15 15:58:10 2009
It is now   Wed Apr 15 12:58:10 2009

Ответ 2

Я бы предложил использовать модуль для этого. В частности, я бы предложил использовать DateTime (см. Perl DateTime Wiki или CPAN

Затем вы сможете сделать что-то вроде следующего:

use strict;
use warnings;
use DateTime;
my $dt = DateTime->now(); # *your* local time assuming your system knows it!


my $clone1 = $dt->clone; # taking a copy.
$clone1->set_time_zone('America/Los_Angeles');


print "$clone1\n";   # output using ISO 8601 format (there a lot of choices)
print "$dt\n";

Ответ 3

Несмотря на то, что ваш код отлично работает для меня как на Linux (Perl 5.10.0), так и на MacOS X (5.8.9), существует возможное решение.

Подходящие функции C, используемые Perl (ctime(), localtime() и т.д.), вызывают tzset() при первом вызове, но не обязательно после этого. Вызывая его самостоятельно, вы должны убедиться, что структуры часового пояса правильно переинициализированы после любого изменения на $TZ.

К счастью, это легко - функция tzset() доступна в модуле POSIX:

#!/usr/bin/perl -w
use POSIX qw[tzset];

$ENV{'TZ'} = 'Europe/London';
tzset();
print scalar localtime();

NB: некоторые поисковые запросы Google предполагают, что это необходимо только с версиями Perl вплоть до 5.8.8. Более поздние версии всегда вызывают tzset() автоматически перед каждым вызовом localtime().

Ответ 4

use Time::Zone;

my $TZ = 'America/Los_Angeles';
my $now = scalar localtime time() + tz_offset($TZ);
print "It is now $now\n";

похоже, работает здесь. ( "Скаляр" здесь избыточен, так как $теперь дает ему скалярный контекст, но также хорошо быть явным.)

В соответствии с комментарием, я получил исходную проблему. Кажется, это исправляет это для меня, но, учитывая, что у других нет оригинальной проблемы, бит "кажется, работает здесь" предназначен для приглашения этих людей попробовать это решение, чтобы гарантировать, что он ничего не сломает, (Мне нужно задаться вопросом, заметила ли alnitak разницу между тем, что я опубликовал, и оригинальным сообщением?)

Ответ 5

Резюме:

Установка $ENV {TZ} = '/* & +000000000005' и вызов Time:: Piece:: _ tzset() фиксирует localtime(), чтобы согласовать с системными часами windoz.

Сведения о Sanguinarily gory:

В Strawberry Perl, windoz 7/64, ни один из "стандартных" часовых поясов не работает в переменной окружения TZ для локализации localtime(). "Америка/Чикаго" дает точно то же время, что и "Америка/Лос-Анжелес" == 'CDT' == 'CST' == 'UTC' == '-01: 00' и т.д. Список бесконечен.

Каждый часовой пояс на http://www.timeanddate.com/time/zones/, который я пробовал, дает правильное время, если вы находитесь в Гринвиче.

Каждый раз из: http://en.wikipedia.org/wiki/List_of_tz_database_time_zones также не удается изменить localtime() вообще. И нет никаких очевидных признаков. Они ничего не делают и ничего не говорят.

Нет NO tzset() на windoz: POSIX:: tzset не реализована в этой архитектуре

Нет даже понятия POSIX??? C:\bin > cpan установить POSIX ... Предупреждение: не удается установить POSIX, не знаю, что это такое. Попробуйте выполнить команду i/POSIX/

Кажется, что он запечен в win8, и для него есть некоторые библиотеки dot NOT.

Для Остина, Техас, в самом Центре Центрального Межгалактического времени, вы правы $ENV {TZ}, который дает мне скалярное локальное время(), которое ~ согласуется с функцией времени уровня o/s, и часы windoz: '/* & +5'!!! Да Slash-Star-Ampersand-Plus-5 работает!

P:\br1\sxsw.2015\SX-2015,0318\сделано > время Текущее время: 16: 36: 39.44 ... Время = 14 апреля 16:36:42 2015, ENV- > TZ =/* & +5

Запустив цикл for и пробуя случайные значения из разных сообщений, для Strawberry Perl uname = 'Win32 strawberry-perl 5.18.2.2...' с известными ошибками часового пояса, любые три символа, которые я пробовал (не пытались + или -), за которым следует +/-, а небольшое число сработало. Вот массив текстовых значений и их вывод ниже:

use Time::Piece;
@tz = ('', 'CDT+5', 'CST+5', 'FKU+5', 'XYZ+5', '+5', '+05', '+05.00', 
    'America/Chicago', 'America/Los_Angeles', 'CDT', 
    'CST', 'UTC', 'PDT', 'PST', '-01:00', '+01:00', '-05:00'.
    'ACDT', 'EASST', '5000', '+0500', '+5:00', '+05:00', 'SSS+1', 'SSS+0',
    'zzz-1', 'ZZ1+5', '123+5', '___+5', '/*&+5', , '/*&+05', '/*&+005',
    '/*&+000000000005');
foreach $tz (@tz)  {
    $ENV{TZ} = $tz         if $tz;
    Time::Piece::_tzset()  if $tz;
    printf("T%s, ENV->TZ=%s\n", scalar localtime, $ENV{TZ}  ||  'NoTZ');
}

Большинство из них стараются ничего, кроме XXX. + | -. integer дал UTC, но многие из них были часами без причины (Америка/Los_Angeles и America/Chicago дали такое же значение). Я почти уверен, что я убирался с помощью только CDT и CST, возможно, на Activestate (переключился на Strawberry, чтобы скомпилировать мои собственные модули Perl, а не полагаться на Activestate для всего). Это первый крупный рык.

Я восстановил DateTime с нуля, и он работал нормально. DateTime:: TimeZone:: Local:: Win32 "не удалось выполнить команду" Win32:: TieRegistry "

Здесь отсортированный результат попыток зон выше:

    P:\br1\sxsw.2015\sx-2015.0318\done>bb | sort
    Running c:/bin/bb.pl  Tue Apr 14 21:43:56 2015
    TTue Apr 14 16:43:56 2015, ENV->TZ=/*&+000000000005
    TTue Apr 14 16:43:56 2015, ENV->TZ=/*&+005
    TTue Apr 14 16:43:56 2015, ENV->TZ=/*&+05
    TTue Apr 14 16:43:56 2015, ENV->TZ=/*&+5
    TTue Apr 14 16:43:56 2015, ENV->TZ=___+5
    TTue Apr 14 16:43:56 2015, ENV->TZ=123+5
    TTue Apr 14 16:43:56 2015, ENV->TZ=CDT+5
    TTue Apr 14 16:43:56 2015, ENV->TZ=CST+5
    TTue Apr 14 16:43:56 2015, ENV->TZ=FKU+5
    TTue Apr 14 16:43:56 2015, ENV->TZ=XYZ+5
    TTue Apr 14 16:43:56 2015, ENV->TZ=ZZ1+5
    ABOVE ALL WORKED Below most failed with UTC or +1 hour???
    TTue Apr 14 20:43:56 2015, ENV->TZ=SSS+1
    TTue Apr 14 21:43:56 2015, ENV->TZ=-01:00
    TTue Apr 14 21:43:56 2015, ENV->TZ=+01:00
    TTue Apr 14 21:43:56 2015, ENV->TZ=+05
    TTue Apr 14 21:43:56 2015, ENV->TZ=+05:00
    TTue Apr 14 21:43:56 2015, ENV->TZ=+0500
    TTue Apr 14 21:43:56 2015, ENV->TZ=+5
    TTue Apr 14 21:43:56 2015, ENV->TZ=+5:00
    TTue Apr 14 21:43:56 2015, ENV->TZ=5000
    TTue Apr 14 21:43:56 2015, ENV->TZ=CDT
    TTue Apr 14 21:43:56 2015, ENV->TZ=CDT
    TTue Apr 14 21:43:56 2015, ENV->TZ=CST
    TTue Apr 14 21:43:56 2015, ENV->TZ=PDT
    TTue Apr 14 21:43:56 2015, ENV->TZ=PST
    TTue Apr 14 21:43:56 2015, ENV->TZ=SSS+0
    TTue Apr 14 21:43:56 2015, ENV->TZ=UTC
    TTue Apr 14 22:43:56 2015, ENV->TZ=-05:00ACDT
    TTue Apr 14 22:43:56 2015, ENV->TZ=+05.00
    TTue Apr 14 22:43:56 2015, ENV->TZ=America/Chicago
    TTue Apr 14 22:43:56 2015, ENV->TZ=America/Los_Angeles
    TTue Apr 14 22:43:56 2015, ENV->TZ=EASST
    TTue Apr 14 22:43:56 2015, ENV->TZ=zzz-1
  • Даже после обнаружения и установки Holy Grail, модуля TzFile для базы данных Olsen, он все еще вкручен, никакой разницы!

    Установка C:\bin\strawberry_perl_5_18\perl\site\lib\DateTime\TimeZone\Tzfile.pm ZEFRAM/DateTime-TimeZone-Tzfile-0.010.tar.gz C:\bin\strawberry_perl_5_18\perl\bin\perl.exe./Build install --uninst 1 - OK

Вот все предполагаемые часовые пояса, которые ничего не делают на этой платформе:   @atz = DateTime:: TimeZone- > all_names();   printf ( "Все имена tz [% d] =% s\n", scalar @atz, join ( ",", @atz));

Все названия tz [349] = Африка/Абиджан, Африка/Аккра, Африка/Алжир, Африка/Бисау, Африка/Каир, Африка/Касабланка, Африка/Сеута, Африка/Эль-Ааюн, Африка/Йоханнесбург, Африка/Хартум, Африка/Лагос, Африка/Мапуту, Африка/Монровия, Африка/Найроби, Африка/Нджамена, Африка/Триполи, Африка/Тунис, Африка/Виндхук, Америка/Адак, Америка/Анкоридж, Америка/Арагуайна, Америка/Аргентина/Буэнос-Айрес, Америка/Аргентина/Катамарка, Америка/Аргентина/Кордова, Америка/Аргентина/Жужуй, Америка/Аргентина/Ла-Риоха, Америка/Аргентина/Мендоса, Америка/Аргентина/Рио-Маджогус, Америка/Аргентина/Сальта, Америка/Аргентина/Сан-Джуан, Аргентина/Сан-Луис, Америка/Аргентина/Тукуман, Америка/Аргентина/Ушуайя, Америка/Асунсьон, Америка/Атикокан, Америка/Баия, Америка/Баия_Бандерас, Америка/Барбадос, Америка/Белен, Америка/Белиз, Америка/Блан-Саблон, Америка/Боа_Виста, Америка/Богота, Америка/Бойсе, Америка/Кембридж_Бей, Америка/Кампо_Гранде, Америка/Канкун, Америка/Каракас, Америка/Кайенна, Америка /C Америка/Дьявол, Америка/Чикаго, Америка/Коста-Рика, Америка/Кристон, Америка/Куйаба, Америка/Кюрасао, Америка/Данарксхавн, Америка/Доусон, Америка/Даусон_Крик, Америка/Денвер, Америка/Детройт, Америка/Эдмонтон, Америка/Эль-Салвадор, Америка/Форталеза, Америка /Glace _Bay, Америка/Godthab, America/Goose_Bay, America/Grand_Turk, Америка/Гватемала, Америка/Гуаякиль, Америка/Гайана, Америка/Галифакс, Америка/Гавана, Америка/Эрмосильо, Индиана/Индианаполис, Америка/Индиана/Нокс, Америка/Индиана/Маренго, Америка/Индиана/Петербург, Америка/Индиана/Tell_City, Америка/Индиана/Вевей, Америка/Индиана/Венсен, Америка/Индиана/Винамак, Америка/Инувик, Америка/Икалуит, Америка/Ямайка, Америка/Джуно, Америка/Кентукки/Луисвилл, Америка/Кентукки/Монтичелло, Америка/Ла-Пас, Америка/Лима, Америка/Лос-Анджелесе, Америка/Масейо, Америка/Манагуа, Америка/Манаус, Мартиника, Америка/Матаморос, Америка/Мазатлан, Америка/Меномине, Америка/Мерида, Америка/Метлакатла, Америка/М exico_City, Америка/Микелон, Америка/Монктон, Америка/Монтеррей, Америка/Монтевидео, Америка/Монреаль, Америка/Нассау, Америка/Нью-Йорк, Америка/Нипигон, Америка/Ном, Америка/Норонья, Америка/Северная_Дакота/Северная_Дакота/Центр, Америка/Северная_Дакота/Нью_Салем, Америка/Ожинага, Америка/Панама, Америка/Пангниртунг, Америка/Парамарибо, Америка/Феникс, Америка/Порт-о-Пренс, Америка/Порт_Фона, Америка/Порто-Вельхо, Америка/Пуэрто-Рико, Америка/Райникс, Америка/Рэнкин, Америка/Реджине, Америка/Реджина, Америка/Резолют, Америка/Рио_Бранко, Америка/Санта-Исабель, Америка/Сантарем, Америка/Сантьяго, Америка/Санто_Доминго, Америка/Сао_Пауло, Америка/Скосбиссунд, Ситка, Америка /St _Johns, Америка/Swift_Current, Америка/Тегусигальпа, Америка/Туле, Америка /Thunder _Bay, Америка/Тихуана, Америка/Торонто, Америка/Ванкувер, Америка/Уайтхорс, Америка/Виннипег, Америка/Якутат, Америка/Йеллоунайф, Антарктида/Кейси, Антарктида/Дэвис, Антарктида/ДюмонтДурвилль, Анта rctica/Macquarie, Антарктида/Мольсон, Антарктида/Палмер, Антарктида/Ротера, Антарктида/Сева, Антарктида/Тролль, Антарктида/Восток, Азия/Алматы, Азия/Амман, Азия/Анадырь, Азия/Актау, Азия/Актюба, Азия/Ашхабад, Азия/Багдад, Азия/Баку, Азия/Бангкок, Азия/Бейрут, Азия/Бишкек, Азия/Бруней, Азия/Чита, Азия/Чойбалсан, Азия/Коломбо, Азия/Дамаск, Азия/Дакка, Азия/Дили, Азия/Дубай, Азия/Душанбе, Азия/Газа, Азия/Хеврон, Азия /Ho _Chi_Minh, Азия/Гонконг, Азия/Ховд, Азия/Иркутск, Азия/Джакарта, Азия/Джаяпура, Азия/Иерусалим, Азия/Кабул, Азия/Камчатка, Азия/Карачи, Азия/Катманду, Азия/Хандыга, Азия/Калькутта, Азия/Красноярск, Азия/Куала_Люмпур, Азия/Кучинг, Азия/Макао, Азия/Магадан, Азия/Макассар, Азия/Манила, Азия/Никосия, Азия/Новокузнецк, Азия/Новосибирск, Азия/Омск, Азия/Орал, Азия/Понтианак, Азия/Пхеньян, Азия/Катар, Азия/Кызылорда, Азия/Рангун, Азия/Эр-Рияд, Азия/Сахалин, Азия/Самарканд, Азия/Сеул, Азия/Шанхай, Азия/Сингапур, Азия/Среднеколымск, Азия/Тайбэй, Азия/Ташкент, As ia/Тбилиси, Азия/Тегеран, Азия/Тхимпху, Азия/Токио, Азия/Улан-Батор, Азия/Урумчи, Азия/Усть-Нера, Азия/Владивосток, Азия/Якутск, Азия/Екатеринбург, Азия/Ереван, Атлантик/Азорские острова, Атлантик/Канарские острова, Атлантик/Кабо-Верде, Атлантик/Фарерские острова, Атлантик/Мадейра, Атлантик/Рейкьявик, Атлантик/Юг_Горгия, Атлантик/Стэнли, Австралия/Аделаида, Австралия/Брисбен, Австралия /Broken _Hill, Австралия/Керри, Австралия/Дарвин, Австралия/Эукла, Австралия/Хобарт, Австралия/Линдеман, Австралия/Лорд_Howe, Австралия/Мельбурн, Австралия/Перт, Австралия/Сидней, CET, CST6CDT, EET, EST, EST5EDT, Европа/Амстердам, Европа/Андорра, Европа/Афины, Европа/Белград, Европа/Берлин, Европа/Брюссель, Европа/Бухарест, Европа/Будапешт, Европа/Кишинэу, Европа/Копенгаген, Европа/Дублин, Европа/Гибралтар, Европа/Хельсинки, Европа/Стамбул, Европа/Калининград, Европа/Киев, Европа/Лиссабон, Европа/Лондон, Европа/Люксембург, Европа/Мадрид, Европа/Мальта, Европа/Минск, Европа/Монако, Европа/Москва, Европа/Осло, Европа/Париж, Европа/Прага, Европа/Рига, Европа/Рим, Европа/Самара, Европа/Симферополь, Европа/София, Европа/Стокгольм, Европа/Таллинн, Европа/Тиран, Европа/Ужгород, Европа/Вена, Европа/Вильнюс, Европа/Волгоград, Европа/Варшава, Европа/Запорожье, Европа/Цюрих, HST, Индийский/Чагос, Индийский/Макеевский, Индийский/Маврикий, Индийский/Маврикий, Индийский/Реюньон, МЕТ, МСТ, MST7MDT, PST8PDT, Тихий океан/Апиа, Тихий океан/Окленд, Тихий океан/Бугенвиль, Тихий океан/Чатем,Тихоокеанский регион/Тихоокеанский регион/Тихоокеанский регион/Тихоокеанский регион/Тихоокеанский регион/Тихоокеанский регион/Тихоокеанский регион/Тихоокеанский регион/Тихоокеанский регион/Тихоокеанский регион/Тихоокеанский регион/Тихоокеанский регион/Тихоокеанский регион/Тихоокеанский регион/Тихоокеанский регион/Тихоокеанский регион/Тихоокеанский регион/Тихоокеанский регион/Тихоокеанский регион/Паго_Паго, Тихий океан/Палау, Тихий океан/Питкэрн, Тихий океан/Понпеи, Тихий океан/Тихоокеанский регион/Тихоокеанский регион/Тихоокеанский регион/Тихий океан/Тарава, Тихий океан/Тонгатапу, Тихий океан/Уэйк, Тихий океан/Уоллис, UTC, WET

Ответ 6

Развернув ответ на BrianP007, вы используете как TZ, так и _tzset

$was = localtime;
print "It was $was\n";
$ENV{TZ} = 'CST6CDT'; # America/Chicago
Time::Piece::_tzset(); # Local time is now Chicago Time
$was = localtime;
print "It is $was\n"; # Right now in Chicago

Трюк: TZ устанавливается из вашего местоположения в GMT. Таким образом, вы, как правило, считаете, что Чикаго - UTC-6, но из Чикаго - 6 часов в UTC, который = 'CST6'.

См. http://science.ksc.nasa.gov/software/winvn/userguide/3_1_4.htm