#!/usr/bin/perl -w use strict; # Emulate: # $ date -d "Tue, 01 Jan 2013 16:05:53 +0000" # Tue Jan 1 10:05:53 CST 2013 use Time::Local qw< timegm >; use POSIX qw< strftime >; my @Mons = qw< jan feb mar apr may jun jul aug sep oct nov dec >; my %Mons; @Mons{@Mons} = 1..@Mons; print datetime_offset2local( "@ARGV" ), $/; exit; sub datetime_offset2local { my( $date ) = @_; # Parse out the date parts: my( $dow, $day, $mon, $yr, $time, $off, $ex ) = split /,? /, $date, -1; die "Too many fields ($ex) in input datetime ($date)\n" if defined $ex; my( $hr, $min, $sec ) = split /:/, $time; $mon = $Mons{ lc $mon } || die "Invalid month name ($mon): $date\n"; # Convert input date to epoch seconds (ignoring GMT offset): $sec = timegm( $sec, $min, $hr, $day, $mon-1, $yr ); # Parse the GMT offset and apply it: ( my $sign, $hr, $min ) = $off =~ /^([-+])([0-9][0-9])([0-9]*)$/ or die "Invalid offset ($off): $date\n"; $off = $hr*60; $off += $min || 0; $off *= 60; $off *= -1 if '-' eq $sign; # Convert epoch seconds to string using local time zone and locale: return strftime( "%a, %b %d %Y %T %Z (%z)", localtime( $sec - $off ) ); } __END__ $ TZ=US/Central perl offset2local.pl Tue, 01 Jan 2013 16:05:53 +0000 Tue, Jan 01 2013 10:05:53 CST (-0600) $ TZ=US/Central perl offset2local.pl Tue, 01 Jan 2013 16:05:53 -0600 Tue, Jan 01 2013 16:05:53 CST (-0600) $ perl offset2local.pl Tue, 01 Jan 2013 16:05:53 +0000 Tue, Jan 01 2013 08:05:53 PST (-0800)