开发者

How I can I convert timezones in Perl?

I am trying to convert a date/time GMT 0 to GMT -6 in Perl.

For example, a DHCP Server lease time is in the following format:

2010/02/18 23:48:37

I am trying to convert that time to the Localtime zone (GMT -6) but need it to honor Daylight savings time.

The script below may be overkill, but I a开发者_StackOverflow中文版m not sure how to proceed from here. (Any suggestions would be awsome).

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

It will output the following lines:

2010-02-18T23:48:37

-21600

I need to be able to add -21600 to the date to get the local time zone of GMT -6 but I am not sure how to approch this.


Call set_time_zone method 2 times:

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

How it works:

  • when you create DateTime object without time zone specified, "floating" time zone is set
  • first call of set_time_zone change time zone to UTC without conversion
  • second call of set_time_zone change UTC to America/Chicago


This will convert UTC time into ETC time. You can also use date/time in any format using +FORMAT parameter of date.

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


Time::Piece is a very lightweight piece of code of good quality. Or you can just use built-ins and strftime and POSIX::strptime


Don't Use Timezones With `DateTime::Format::MySQL->parse_datetime`

There is a very good reason you shouldn't be using this when doing anything relating to timezones. Why? Because it has absolutely no support for timezones whatsoever. Please see the documentation:

All of the parsing methods set the returned DateTime object's time zone to the floating time zone, because MySQL does not provide time zone information. (Source: MetaCPAN: DateTime::Format::MySQL.)

If you DO use this, it will assume your system time zone default. This might not be the timezone you want to convert from! (Although this will work for many people, it only works as long as your servers don't change their default timezone — after that, everything breaks.)

Use `DateTime->new()`, Because It DOES Support TimeZones

Use the constructor that DateTime provides directly (Source: MetaCPAN: DateTime.):

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

Convert TimeZones with DateTime

Your starting time zone is whatever you feed into the constructor (i.e., America/Chicago in the above example). To convert a time to an ending time zone, use set_time_zone().

Working Code

In the code below, a time is converted from one timezone to another, and it does this perfectly every time, even you are converting New York time to San Francisco time with a server whose Linux OS is in Singapore time.

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',
}));

Output:

10:30:00


#!/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);
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜