Как мне установить часовой пояс для Perl localtime ()? - PullRequest
16 голосов
/ 15 апреля 2009

В 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

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

Ответы [ 4 ]

19 голосов
/ 15 апреля 2009

Использование 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
9 голосов
/ 15 апреля 2009

Я бы настоятельно рекомендовал использовать модуль для этого. В частности, я бы предложил использовать 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 голосов
/ 15 апреля 2009

Хотя ваш код отлично работает для меня как в 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();

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

1 голос
/ 15 апреля 2009
use Time::Zone;

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...