Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Re: Timezone Conversion

by jeffa (Bishop)
on Oct 28, 2015 at 16:37 UTC ( #1146303=note: print w/replies, xml ) Need Help??


in reply to Timezone Conversion

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)

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1146303]
help
Chatterbox?
and snow settles gently...

How do I use this? | Other CB clients
Other Users?
Others imbibing at the Monastery: (8)
As of 2018-05-25 08:08 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Notices?