http://www.perlmonks.org?node_id=1012285

adambot has asked for the wisdom of the Perl Monks concerning the following question:

I am trying to replicate the following in perl using only the posix module. Any help is appreciated

$date -d "Tue, 01 Jan 2013 16:05:53 +0000" Tue Jan 1 10:05:53 CST 2013

Replies are listed 'Best First'.
Re: Convert timezone using offset and posix perl module
by toolic (Bishop) on Jan 08, 2013 at 17:27 UTC
    POSIX::strftime and strftime
    use warnings; use strict; use POSIX qw(strftime); my $today = strftime('%a %b %d %H:%M:%S %Z %Y', localtime); print "$today\n"; __END__ Tue Jan 08 12:25:53 EST 2013
      thank you!! -- i will take the wisdom you imparted and learn from it, however, how do i give it a date in the past?
        how do i give it a date in the past?
        The POSIX doc I pointed to shows you how to do that.
      So i slept on it and came up with this in the morning:
      use DateTime; use DateTime::Format::Strptime; my @time = qw(Tue, 01 Jan 2013 16:05:53 +0000); my $tz=pop(@time); my $val="@time"; my $format = new DateTime::Format::Strptime( pattern => '%a, %d %b %Y %H:%M:%S', time_zone => "$tz", ); my $date = $format->parse_datetime($val); $date->set_time_zone("America/Chicago"); print $date->strftime("%a, %d %b %Y %H:%M:%S %Z")."\n";
      however, i would like to do it with all core modules... any help is appreciated -- posix is no longer required...
        #!/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)

        Time::Local is a core module. The only reason I used POSIX was to get the timezone abbreviation ("CST"); otherwise, that last step could have been easily done with just localtime and sprintf).

        - tye        

Re: Convert timezone using offset and posix perl module
by Anonymous Monk on Jan 08, 2013 at 17:24 UTC
    what did you try so far?
      That's the problem -- i'm not sure where to start -- i found this:
      ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);