views:

1434

answers:

3

Probably an easy answer: how do I convert this without importing external modules? I've read the CPAN but couldn't explicitly pinpoint a method that does the following:

Convert: 20080428 to 28-APR-08

Any ideas?

Even directing me to a tutorial would be appreciated.

Regards, PIAS

+1  A: 

Have you checked these addresses http://www.go4expert.com/forums/showthread.php?t=15533 and this perl documentation http://perldoc.perl.org/functions/localtime.html

Izabela
+1  A: 
my %map = ( '01' => 'JAN', '02' => 'FEB', '03' => 'MAR', '04' => 'APR' ); # You can do the rest yourself ;-)
my $in = '20080428';
if ( $in =~ m/..(..)(..)(..)/ ) {
    my ( $y, $m, $d ) = ( $1, $2, $3 );
    my $out = sprintf '%02d-%s-%02d', $d, $map{$m}, $y;
}   
else {
    die "Illegal date format";
}
innaM
Those need to be [0-9] not \d unless you have the bytes pragma enabled (\d matches things other than [0-9] in Perl 5.8 and 5.10). Alternatively you could say /(....)(..)(..)/ if you don't care about the exact type.
Chas. Owens
This code likes dates like 99998877. Also, dates from 1900-1999 will be printed incorrectly.
daotoad
Good points folks (altough I was assuming - and still am - that only valid dates will form the input). I fixed those - the simple way. @Chas: What will \d match that is not a digit?
innaM
+1  A: 

This code fails in Y10k, but that should be good enough. The regex could be stricter, but if the date has already been validated (or will be validated in the new form) then it doesn't matter.

#!/usr/bin/perl

use strict;
use warnings;

my @mon = qw/null JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC/;

my $d = "20080428";

$d =~ s/..(..)(..)(..)/$3-$mon[$2]-$1/;

print "date is now $d\n";

Or, if you are insane and want to validate in the regex (requires Perl 5.10):

#!/usr/bin/env perl5.10.0

use strict;
use warnings;

my @mon = qw/null JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC/;

my $d = join '', @ARGV;

# only validates between 1600 and 9999
# because of calendar weirdness prior to 1600 
$d =~ s/
    ^
    (?:
        # non-leap years and everything but 29th of Feb in leap years
        (?:
            1[6-9]     (?<y> [0-9]{2}) | 
            [2-9][0-9] (?<y> [0-9]{2})
        )
        (?: #any month 1st through 28th
            (?: (?<m> 0[1-9] | 1[0-2]) (?<d> 0[0-9] | 1[0-9] | 2[0-8]) )
            | #or 30th of any month but 2
            (?: (?<m>0[13-9] | 1[0-2]) (?<d> 30) )
            | # or 31st of 1, 3, 5, 7, 8, 10, or 12
            (?: (?<m>0[13578] | 1[02]) (?<d> 31) )
        )
        | # or 29th of Feb in leap years
        (?:
            (?: #centuries divisible by 4 minus the ones divisible by 100
                16          |    
                [2468][048] |
                [3579][26]
            )
            (?<y> 00)
            | #or non-centuries divisible by 4
            (?: 1[6-9] | [2-9][0-9] )
            (?<y>
                0[48]       | 
                [2468][048] |
                [13579][26]
            )
        )
        (?<m> 02) (?<d> 29)
    )
    $
/$+{y}-$mon[$+{m}]-$+{d}/x or die "invalid date: $d";

print "date is now $d\n";
Chas. Owens