如何为Perl的localtime()设置时区?

时间:2009-04-15 19:34:31

标签: perl

在Perl中,我想在特定时区查找本地时间。我一直在使用这种技术:

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

但是,这不可靠 - 值得注意的是,如果我在设置$ ENV {TZ}之前添加了另一个localtime()调用,它就会中断:

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

有更好的方法吗?

6 个答案:

答案 0 :(得分:19)

使用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

答案 1 :(得分:9)

我强烈建议使用模块来执行此操作。具体来说,我建议使用DateTime(请参阅Perl DateTime WikiCPAN

然后您应该可以执行以下操作:

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";

答案 2 :(得分:3)

虽然您的代码在Linux(Perl 5.10.0)和MacOS X(5.8.9)上都适用于我,但有一种可能的解决方案。

Perl使用的基础C函数(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()

答案 3 :(得分:1)

use Time::Zone;

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

似乎在这里工作。 ('scalar'在这里是多余的,因为$ now现在给它标量上下文,但显式也很好。)

根据评论,我得到了原始问题。这似乎解决了我,但鉴于其他人没有原来的问题,“似乎在这里工作”一点是为了邀请那些人尝试这个解决方案,以确保它不会破坏任何东西。 (我不得不想知道alnitak是否注意到我发布的帖子和原帖之间的区别?)

答案 4 :(得分:0)

执行摘要:

设置$ ENV {TZ} =' / *& + 000000000005'并调用Time :: Piece :: _ tzset()修复localtime()以同意windoz系统时钟。

血腥的血腥细节:

在草莓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()。并且,没有明显的迹象。他们什么都不做,什么都不说。

windoz上没有tzset(): POSIX :: tzset未在此架构上实现

甚至没有POSIX的任何概念??? C:\ bin> cpan install POSIX ... 警告:无法安装POSIX,不知道它是什么。 尝试命令i / POSIX /

它似乎被融入win8并且有一些点NOT库。

对于德克萨斯州奥斯汀,在中间星系时间的中心,你正确的$ ENV {TZ}给了我一个标量的本地时间(),它与o / s级时间函数和windoz时钟一致: ' / *&安培; + 5' !是的Slash-Star-Ampersand-Plus-5有效!

,P:\ BR1 \ sxsw.2015 \ SX-2015.0318 \完成>时间 当前时间是16:36:39.44 ... 时间= 2015年4月14日16:36:42,ENV-> TZ = / *& +5

通过运行for循环并尝试各种帖子中的随机值,对于Strawberry Perl uname =' Win32 strawberry-perl 5.18.2.2 ......'有已知的时区错误,我试过的任何3个字符(没有尝试+或 - )后跟+/-和少数工作。以下是一组文本值及其输出:

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之外,大多数人都尝试过任何东西。 + | - 。整数给了UTC,但是很多都是无缘无故的一小时(America / 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
  • 即使找到并安装了圣杯,奥尔森数据库的TzFile模块,它仍然是搞砸了,没有区别!

    安装C:\ bin \ strawberry_perl_5_18 \ perl \ site \ lib \ DateTime \ TimeZone \ Tzfile.pm ZEFRAM /日期,时区,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",标量@atz,加入(",",@ atz));

所有tz名称[349] =非洲/阿比让,非洲/阿克拉,非洲/阿尔及尔,非洲/比绍,非洲/开罗,非洲/卡萨布兰卡,非洲/休达,非洲/ El_Aaiun,非洲/约翰内斯堡,非洲/喀土穆,非洲/拉各斯,非洲/马普托,非洲/蒙罗维亚,非洲/内罗毕,非洲/恩贾梅纳,非洲/的黎波里,非洲/突尼斯,非洲/温得和克,美洲/阿达克,美洲/安克雷奇,美洲/阿拉瓜伊纳,美洲/阿根廷/布宜诺斯艾利斯, America / Argentina / Catamarca,America / Argentina / Cordoba,America / Argentina / Jujuy,America / Argentina / La_Rioja,America / Argentina / Mendoza,America / Argentina / Rio_Gallegos,America / Argentina / Salta,America / Argentina / San_Juan,America / Argentina / San_Luis,America / Argentina / Tucuman,America / Argentina / Ushuaia,America / Asuncion,America / Atikokan,America / Bahia,America / Bahia_Banderas,America / Barbados,America / Belem,America / Belize,America / Blanc-Sablon, America / Boa_Vista,America / Bogota,America / Boise,America / Cambridge_Bay,America / Campo_Grande,America / Cancun,America / Caracas,America / Cayenne,America / C hicago,America / Chihuahua,America / Costa_Rica,America / Creston,America / Cuiaba,America / Curacao,America / Danmarkshavn,America / Dawson,America / Dawson_Creek,America / Denver,America / Detroit,America / Edmonton,America / Eirunepe, America / El_Salvador,America / Fortaleza,America / Glace_Bay,America / Godthab,America / Goose_Bay,America / Grand_Turk,America / Guatemala,America / Guayaquil,America / Guyana,America / Halifax,America / Havana,America / Hermosillo,America / Indiana / Indianapolis,America / Indiana / Knox,America / Indiana / Marengo,America / Indiana / Petersburg,America / Indiana / Tell_City,America / Indiana / Vevay,America / Indiana / Vincennes,America / Indiana / Winamac,America / Inuvik, America / Iqaluit,America / Jamaica,America / Juneau,America / Kentucky / Louisville,America / Kentucky / Monticello,America / La_Paz,America / Lima,America / Los_Angeles,America / Maceio,America / Managua,America / Manaus,America / Martinique,America / Matamoros,America / Mazatlan,America / Menominee,America / Merida,America / Metlakatla,America / M exico_City,America / Miquelon,America / Moncton,America / Monterrey,America / Montevideo,America / Montreal,America / Nassau,America / New_York,America / Nipigon,America / Nome,America / Noronha,America / North_Dakota / Beulah,America / North_Dakota / Center,America / North_Dakota / New_Salem,America / Ojinaga,America / Panama,America / Pangnirtung,America / Paramaribo,America / Phoenix,America / Port-au-Prince,America / Port_of_Spain,America / Porto_Velho,America / Puerto_Rico, America / Rainy_River,America / Rankin_Inlet,America / Recife,America / Regina,America / Resolute,America / Rio_Branco,America / Santa_Isabel,America / Santarem,America / Santiago,America / Santo_Domingo,America / Sao_Paulo,America / Scoresbysund,America / Sitka,America / St_Johns,America / Swift_Current,America / Tegucigalpa,America / Thule,America / Thunder_Bay,America / Tijuana,America / Toronto,America / Vancouver,America / Whitehorse,America / Winnipeg,America / Yakutat,America / Yellowknife, Antarctica / Casey,Antarctica / Davis,Antarctica / DumontDUrville,Anta rctica / Macquarie,Antarctica / Mawson,Antarctica / Palmer,Antarctica / Rothera,Antarctica / Syowa,Antarctica / Troll,Antarctica / Vostok,Asia / Almaty,Asia / Amman,Asia / Anadyr,Asia / Aqtau,Asia / Aqtobe,Asia /阿什哈巴德,亚洲/巴格达,亚洲/巴库,亚洲/曼谷,亚洲/贝鲁特,亚洲/比什凯克,亚洲/文莱,亚洲/赤塔,亚洲/乔巴山,亚洲/科伦坡,亚洲/大马士革,亚洲/达卡,亚洲/帝力,亚洲/迪拜,亚洲/杜尚别,亚洲/加沙,亚洲/希伯伦,亚洲/ Ho_Chi_Minh,亚洲/香港,亚洲/ Hovd,亚洲/伊尔库茨克,亚洲/雅加达,亚洲/查亚普拉,亚洲/耶路撒冷,亚洲/喀布尔,亚洲/堪察加,亚洲/卡拉奇,亚洲/加德满都,亚洲/ Khandyga,亚洲/加尔各答,亚洲/克拉斯诺亚尔斯克,亚洲/ Kuala_Lumpur,亚洲/古晋,亚洲/澳门,亚洲/马加丹,亚洲/望加锡,亚洲/马尼拉,亚洲/尼科西亚,亚洲/新库兹涅茨克,亚洲/新西伯利亚,亚洲/鄂木斯克,亚洲/欧陆,亚洲/坤甸,亚洲/平壤,亚洲/卡塔尔,亚洲/ Qyzylorda,亚洲/仰光,亚洲/利雅得,亚洲/萨哈林,亚洲/撒马尔罕,亚洲/首尔,亚洲/上海,亚洲/新加坡,亚洲/ Srednekolymsk,亚洲/台北,亚洲/塔什干,As ia / Tbilisi,亚洲/德黑兰,亚洲/廷布,亚洲/东京,亚洲/乌兰巴托,亚洲/乌鲁木齐,亚洲/乌斯季 - 奈拉,亚洲/符拉迪沃斯托克,亚洲/雅库茨克,亚洲/叶卡捷琳堡,亚洲/埃里温,大西洋/亚速尔群岛,大西洋/百慕大,大西洋/金丝雀,大西洋/ Cape_Verde,大西洋/法罗,大西洋/马德拉,大西洋/雷克雅未克,大西洋/南乔治亚,大西洋/斯坦利,澳大利亚/阿德莱德,澳大利亚/布里斯班,澳大利亚/ Broken_Hill,澳大利亚/ Currie,澳大利亚/澳大利亚达尔文/澳大利亚/澳大利亚/澳大利亚霍巴特/澳大利亚林德曼/澳大利亚/澳大利亚/澳大利亚/澳大利亚/珀斯,澳大利亚/悉尼,CET,CST6CDT,EET,EST,EST5EDT,欧洲/阿姆斯特丹,欧洲/安道尔,欧洲/雅典,欧洲/贝尔格莱德,欧洲/柏林,欧洲/布鲁塞尔,欧洲/布加勒斯特,欧洲/布达佩斯,欧洲/基希讷乌,欧洲/哥本哈根,欧洲/都柏林,欧洲/直布罗陀,欧洲/赫尔辛基,欧洲/伊斯坦布尔,欧洲/加里宁格勒,欧洲/基辅,欧洲/里斯本,欧洲/伦敦,欧洲/卢森堡,欧洲/马德里,欧洲/马耳他,欧洲/明斯克,欧洲/摩纳哥,欧洲/莫斯科,欧洲/奥斯陆,欧洲/巴黎,欧洲/布拉格,欧洲/里加,欧洲/罗马,欧洲/萨马拉,欧洲/辛菲罗波尔,欧洲/索非亚,欧洲/斯德哥尔摩,欧洲/塔林,欧洲/地拉那,欧洲/乌日哥罗德,欧洲/维也纳,欧洲/维尔纽斯,欧洲/伏尔加格勒,欧洲/华沙,欧洲/扎波罗热,欧洲/苏黎世,HST,印度/查戈斯,印度/圣诞节,印度/科科斯,印度/ Kerguelen,印度/马埃岛,印度/马尔代夫,印度/毛里求斯,印度/ Reunion,MET,MST,MST7MDT,PST8PDT,Pacific / Apia,Pacific / Auckland,Pacific / Bougainville,Pacific / Chatham,Pacific / Chuuk,Pacific / Easter,Pacific / Efate,Pacific / Enderbury,Pacific / Fakaofo,Pacific / Fiji, Pacific / Funafuti,Pacific / Galapagos,Pacific / Gambier,Pacific / Guadalcanal,Pacific / Guam,Pacific / Honolulu,Pacific / Kiritimati,Pacific / Kosrae,Pacific / Kwajalein,Pacific / Majuro,Pacific / Marquesas,Pacific / Nauru,Pacific /纽埃,太平洋/诺福克,太平洋/努美阿,太平洋/帕果帕戈,太平洋/帕劳,太平洋/皮特凯恩,太平洋/波纳佩,太平洋/ Port_Moresby,太平洋/拉罗汤加,太平洋/塔希提岛,太平洋/塔拉瓦,太平洋ific / Tongatapu,Pacific / Wake,Pacific / Wallis,UTC,WET

答案 5 :(得分:0)

在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,但是从芝加哥到UTC它是6小时='CST6'。

请参阅http://science.ksc.nasa.gov/software/winvn/userguide/3_1_4.htm