12

我正在尝试在 Perl 中将日期/时间 GMT 0 转换为 GMT -6。

例如,DHCP 服务器租用时间的格式如下:

2010/02/18 23:48:37

我正在尝试将该时间转换为本地时区(GMT -6),但需要它来遵守夏令时。

下面的脚本可能有点矫枉过正,但我​​不知道如何从这里开始。(任何建议都会很棒)。

my $TIMESTART;

$TIMESTART = "2010/02/18 23:48:37";
$TIMESTART =~ s/\//-/g;

use DateTime;
use DateTime::TimeZone;

use DateTime::Format::MySQL;
my $dt = DateTime::Format::MySQL->parse_datetime($TIMESTART);

my $tz = DateTime::TimeZone->new( name => 'America/Chicago' );

print $tz->offset_for_datetime($dt) . "\n";

它将输出以下行:

2010-02-18T23:48:37
-21600

我需要能够将 -21600 添加到日期以获取 GMT -6 的本地时区,但我不知道如何解决这个问题。

4

5 回答 5

18

调用set_time_zone方法2次:

my $dt = DateTime::Format::MySQL->parse_datetime($TIMESTART);
$dt->set_time_zone('UTC'); ## set timezone of parsed date time
$dt->set_time_zone('America/Chicago'); ## change timezone in safe way

print DateTime::Format::MySQL->format_datetime($dt),"\n"; ## check the result

这个怎么运作:

  • 当您创建DateTime没有指定时区的对象时,会设置“浮动”时区
  • 第一次调用set_time_zone将时区更改为UTC不进行转换
  • 第二次呼吁set_time_zone改变UTCAmerica/Chicago
于 2010-02-24T21:27:34.340 回答
1

这会将 UTC 时间转换为 ETC 时间。您还可以使用日期的 +FORMAT 参数以任何格式使用日期/时间。

日期 --date='TZ="ETC" 18:30'

于 2016-04-11T08:33:41.813 回答
0

Time::Piece是一段非常轻量级的高质量代码。或者你可以只使用内置的strftimePOSIX::strptime

于 2010-02-24T21:24:24.770 回答
0

不要在 `DateTime::Format::MySQL->parse_datetime` 中使用时区

在做任何与时区相关的事情时,你不应该使用它是有充分理由的。为什么?因为它绝对不支持任何时区。请参阅文档:

所有的解析方法都将返回的 DateTime 对象的时区设置为浮动时区,因为 MySQL不提供时区信息。(来源:MetaCPAN:DateTime::Format::MySQL。)

如果您确实使用它,它将假定您的系统时区为默认值。这可能不是您要转换的时区!(虽然这对很多人都有效,但它只在您的服务器不更改其默认时区时才有效——在那之后,一切都会中断。)

使用 `DateTime->new()`,因为它确实支持时区

使用DateTime直接提供的构造函数(来源:MetaCPAN:DateTime。):

my $dt = DateTime->new(
    year       => 1966,
    month      => 10,
    day        => 25,
    hour       => 7,
    minute     => 15,
    second     => 47,
    nanosecond => 500000000,
    time_zone  => 'America/Chicago',
);

使用 DateTime 转换时区

您的起始时区是您输入构造函数的任何内容(即,America/Chicago在上面的示例中)。要将时间转换为结束时区,请使用set_time_zone().

工作代码

在下面的代码中,时间从一个时区转换为另一个时区,并且每次都完美地完成此操作,即使您使用 Linux 操作系统为新加坡时间的服务器将纽约时间转换为旧金山时间。

use strict;
use DateTime;

sub convertTimeZonesForTime {
        my ($args) = @_;

        my $time = $args->{time};
        my $date = $args->{date};
        my $totimezone = $args->{totimezone};
        my $fromtimezone = $args->{fromtimezone};
        my $format = $args->{format} || '%H:%M:%S';

        my ($year, $month, $day) = map {int $_} split('-', $date);
        my ($hour, $minute, $second) = map {int $_} split(':', $time);

        $year ||= 1999 if !defined $year;
        $month ||= 1 if !defined $month;
        $day ||= 1 if !defined $day;
        $hour ||= 12 if !defined $hour;
        $minute ||= 30 if !defined $minute;
        $second ||= 0 if !defined $second;

        my $dt = DateTime->new(
                year=>$year,
                month=>$month,
                day=>$day,
                hour=>$hour,
                minute=>$minute,
                second=>$second,
                time_zone => $fromtimezone,
        );
        my $formatter = new DateTime::Format::Strptime(pattern => $format);
        $dt->set_formatter($formatter);
        $dt->set_time_zone($totimezone);

        return "$dt";
}

print(convertTimeZonesForTime({
    'totimezone'=>'America/Denver',
    'fromtimezone'=>'US/Eastern',
    'time'=>'12:30:00',
}));

输出:

10:30:00

于 2022-01-19T18:46:41.443 回答
-2
#!/usr/bin/perl -w
($sec,$min,$hour,$mday,$mon,$year) = gmtime(time+21600);
$year = $year + 1900;
printf("%02d:%02d:%02d %02d.%02d.%04d\n", $hour,$min,$sec,$mday,$mon,$year);
于 2013-08-29T19:57:27.893 回答