本文介绍了如何将Time :: Piece将本地时间转换为UTC时尊重DST?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想将时间戳从本地时间转换为GMT。我有旧代码,可以使用 Time :: Local :: timelocal() gmtime 手动执行此操作。它可以工作,但是我不喜欢它,而是想使用 Time :: Piece 来代替。我使用了(尽管它们正以相反的方式进行转换,但是我能够替换 + -:-))。

I want to convert a timestamp from localtime to GMT. I have legacy code that does this "manually" with Time::Local::timelocal() and gmtime. It works, but I don't like it and wanted to use Time::Piece instead. I used this answer to do so (albeit they are converting the other way round, but I was able to replace + with - :-)).

这是我的代码:

#!/usr/bin/env perl

use strict;
use warnings;
use Time::Local;
use Time::Piece;
use POSIX qw(strftime);

sub local_to_utc_timelocal
{
    my $local_ts = shift;
    my ( $year, $mon, $mday, $hour, $min, $sec ) 
        = ( $local_ts =~ /(\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)/ );
    my $local_secs = Time::Local::timelocal( $sec, $min, $hour, $mday, $mon - 1, $year );
    return POSIX::strftime( '%y-%m-%d %H:%M:%S', gmtime($local_secs) );
}

sub local_to_utc_timepiece
{
    my $local_ts = shift;
    my $local_tp = Time::Piece->strptime( $local_ts, '%y-%m-%d %H:%M:%S' );
    my $utc_tp   = $local_tp - localtime->tzoffset(); # ***
    return $utc_tp->strftime('%y-%m-%d %H:%M:%S');
}

my $local;

# DST in effect (April 19 2016):
$local = '16-04-19 14:30:00';
print "DST in effect:\n";
printf("utc(%s) = %s (using timelocal)\n", $local, local_to_utc_timelocal($local));
printf("utc(%s) = %s (using timepiece)\n\n", $local, local_to_utc_timepiece($local));

# DST NOT in effect (Feb 19 2016):
$local = '16-02-19 14:30:00';
print "DST NOT in effect:\n";
printf("utc(%s) = %s (using timelocal)\n", $local, local_to_utc_timelocal($local));
printf("utc(%s) = %s (using timepiece)\n", $local, local_to_utc_timepiece($local));

不幸的是,Time :: Piece代码在DST上似乎无法正常工作。我住在德国,所以目前(春季/夏季,DST有效)我们是UTC + 2。对于 2016年4月19日,上面的代码给出:

Unfortunately the Time::Piece code doesn't seem to work properly wrt DST. I'm living in Germany, so currently (spring/summer, DST in effect) we are UTC+2. For "April 19 2016" the above code gives:

DST in effect:
utc(16-04-19 14:30:00) = 16-04-19 12:30:00 (using timelocal)
utc(16-04-19 14:30:00) = 16-04-19 12:30:00 (using timepiece)

这是正确的。但是对于 2016年2月19日(当我们是UTC + 1时),相同的代码给出:

which is correct. But for "Feb 19 2016" (when we are UTC+1) the same code gives:

DST NOT in effect:
utc(16-02-19 14:30:00) = 16-02-19 13:30:00 (using timelocal)
utc(16-02-19 14:30:00) = 16-02-19 12:30:00 (using timepiece)

即: gmtime(Time :: Local :: timelocal($ timestamp))给出正确的1小时偏移,而 Time :: Piece 仍然给出2小时

That is: The gmtime(Time::Local::timelocal($timestamp)) gives correct 1 hour offset while Time::Piece still gives 2 hours offset.

这是 Time :: Piece 中的错误吗?还是我使用错误?

Is this a bug in Time::Piece or do I use it wrongly?

我知道有很多方法可以将本地时间转换为UTC,但是我想使用 Time :: Piece 由于其简单性。另外,我不能使用 DateTime ,因为那样会涉及将其部署在十几台生产计算机上。

I know there are plenty of ways to convert localtime to UTC but I'd like to use Time::Piece because of its simplicity. Plus I cannot use DateTime because that would involve deploying it on a dozen of production machines.

推荐答案

问题1



localtime 现在返回,因此 localtime-> ; tzoffset()现在返回偏移量。更改

Problem 1

localtime returns now, so localtime->tzoffset() returns the offset for now. Change

my $utc_tp = $local_tp - localtime->tzoffset();

my $utc_tp = $local_tp - $local_tp->tzoffset();

但是,将 $ utc_tp 标记为本地时间,所以您真的想要:

However, that leaves $utc_tp flagged as a localtime, so you really want:

my $utc_tp = gmtime( $local_tp->epoch );



问题2



尽管它的名字, $ local_tp 不是本地时间,因此 $ local_tp-> tzoffset()为零。更改

Problem 2

Despite its name, $local_tp is not a local time, so $local_tp->tzoffset() is zero. Change

Time::Piece->strptime( $local_ts, '%y-%m-%d %H:%M:%S' )

localtime->strptime( $local_ts, '%y-%m-%d %H:%M:%S' );

这篇关于如何将Time :: Piece将本地时间转换为UTC时尊重DST?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-20 23:07