The twist that makes this otherwise fairly trivial problem complicated is having to respect Daylight Savings Time. I once had to convert times given in UTC to their local equivalents for all of the US and Canada. We had to query a service in order to determine if the given city respected Daylight Savings Time or not, but after that we could use a hash to provide a close enough approximation. Since you want to convert to UTC, you most likely will need not the following code. But in the event you (or others who are reading) need to convert to local US and Canada time zones, the following can help. Just note that the data in the hash was determined 3 years ago and some areas might have changed.
use strict;
use warnings;
use Data::Dumper;
use DateTime;
use Time::ParseDate;
use DateTime::TimeZone;
our %TIMEZONES = (
# DST
'-3.5Y' => 'America/St_Johns',
'-4Y' => 'America/Halifax',
'-5Y' => 'America/New_York',
'-6Y' => 'America/Chicago',
'-7Y' => 'America/Denver',
'-8Y' => 'America/Los_Angeles',
'-9Y' => 'America/Anchorage',
'-10Y' => 'America/Adak',
# NOT DST
'-11N' => 'Pacific/Midway',
'-10N' => 'Pacific/Honolulu',
'-8N' => 'Pacific/Pitcairn',
'-7N' => 'America/Phoenix',
'-6N' => 'America/Managua',
'-4N' => 'America/St_Vincent',
'0N' => 'America/Danmarkshavn',
'9N' => 'Pacific/Palau',
'10N' => 'Pacific/Truk',
'11N' => 'Pacific/Efate',
'12N' => 'Pacific/Wallis',
);
sub timezone {
my ($utc_offset,$is_dst) = @_;
return DateTime::TimeZone->new( name => $TIMEZONES{$utc_offset . $
+is_dst} );
}
my $input = '11:50:45.242 EDT OCT 27 2015';
my $epoch = parsedate( $input );
my $dt = DateTime->from_epoch( epoch => $epoch );
$dt->set_time_zone( timezone( 0, 'N' ) );
print $dt->strftime( '%Y-%m-%d %H:%M:%S' ), $/;
So for your usage, the following would suffice:
$dt->set_time_zone( timezone( 0, 'N' ) );
But if you wanted to convert to some local time in Indiana, it could be any of the following:
$dt->set_time_zone( timezone( -5, 'Y' ) ); # Central with DST
$dt->set_time_zone( timezone( -6, 'N' ) ); # Eastern without DST
$dt->set_time_zone( timezone( -6, 'Y' ) ); # Eastern with DST
And you have to know beforehand (via some lookup table provided by some external source) what the rules are for the city you are converting to. This all makes you wonder why we still have DST, and if fact many people would like to abolish it.
P.S. My co-worker that helped derive this solution was going to release this as TimeZone::CloseEnough.
jeffa
L-LL-L--L-LL-L--L-LL-L--
-R--R-RR-R--R-RR-R--R-RR
B--B--B--B--B--B--B--B--
H---H---H---H---H---H---
(the triplet paradiddle with high-hat)
|