在Perl中获得UTC偏移的最佳方法是什么?

时间:2010-01-26 23:35:09

标签: perl formatting timestamp

我需要在跨平台(Windows和各种Unix版本)方式中获取Perl中当前时区的UTC偏移量。它应该符合这种格式:

  

zzzzzz,表示与UTC相关的±hh:mm

看起来我应该可以通过strftime()获取它,但它看起来并不一致。

Unix的:

Input: perl -MPOSIX -e "print strftime(\"%z\", localtime());"
Output: -0700

视窗:

Input: perl -MPOSIX -e "print strftime(\"%z\", localtime());"
Output: Mountain Standard Time

虽然看起来Unix正在给我我想要的东西(或者至少接近某些东西),但Windows并非如此。我很确定我可以用Date::Time或类似的方式来做,但我真的很想不会因为我们的广泛安装基础而无法保证用户会有任何依赖。

我错过了一些明显的东西吗?提前谢谢。

5 个答案:

答案 0 :(得分:15)

Time::Local应该做的伎俩

use Time::Local;
@t = localtime(time);
$gmt_offset_in_seconds = timegm(@t) - timelocal(@t);

答案 1 :(得分:0)

我真的很想不会因为我们的广泛安装基础而无法保证用户会有任何依赖

如何在安装中包含Date :: Time的自定义副本(我们称之为My :: Date :: Time)?例如,

use lib 'my-module/dependencies/';

use My::Date::Time;

答案 2 :(得分:0)

您可以计算localtime($t)gmtime($t)之间的差异。这是我的版本受mobanswer启发:

use strict;
use warnings;    

sub tz_offset
{
    my $t = shift;
    my @l = localtime($t);
    my @g = gmtime($t);

    my $minutes = ($l[2] - $g[2] + ((($l[5]<<9)|$l[7]) <=> (($g[5]<<9)|$g[7])) * 24) * 60 + $l[1] - $g[1];
    return $minutes unless wantarray;
    return (int($minutes / 60), $minutes % 60);
}

push @ARGV, time;
foreach my $t (@ARGV) {
    printf "%s (%d): %+03d%02u\n", scalar localtime($t), $t, tz_offset($t);
}

答案 3 :(得分:0)

这是仅使用核心POSIX模块的便携式解决方案:

perl -MPOSIX -e 'my $tz = (localtime time)[8] * 60 - mktime(gmtime 0) / 60; printf "%+03d:%02d\n", $tz / 60, abs($tz) % 60;'

奖金::以下子例程将返回带有时区偏移和微秒的完整时间戳,如“ YYYY-MM-DD HH:MM:SS.nnnnnn [+-] HHMM”:< / p>

use POSIX qw[mktime strftime];
use Time::HiRes qw[gettimeofday];

sub timestamp () {
  my @now = gettimeofday;
  my $tz  = (localtime $now[0])[8] * 60 - mktime(gmtime 0) / 60;
  my $ts  = strftime("%Y-%m-%d %H:%M:%S", localtime $now[0]);
  return sprintf "%s.%06d %+03d%02d", $ts, $now[1], $tz / 60, abs($tz) % 60;
}

答案 4 :(得分:-1)

便携式方法是将localtime的输出与gmtime

进行比较
    $t = time;
    @a = localtime($t);
    @b = gmtime($t);

    $hh = $a[2] - $b[2];
    $mm = $a[1] - $b[1];
    # in the unlikely event that localtime and gmtime are in different years
    if ($a[5]*366+$a[4]*31+$a[3] > $b[5]*366+$b[4]*31+$b[3]) {
      $hh += 24;
    } elsif ($a[5]*366+$a[4]*31+$a[3] < $b[5]*366+$b[4]*31+$b[3]) {
      $hh -= 24;
    }
    if ($hh < 0 && $mm > 0) {
      $hh++;
      $mm = 60-$mm;
    }
    printf "%+03d:%02d\n", $hh, $mm;

有人指出这已经在5,4,3,......的某个模块中实现了。

相关问题