#! perl -w use strict; my %dateformat; # memoization hash my @rule; foreach my $target (qw(DD/MM/YYYY DD/MM/RR YYYY/MM/DD)) { (my $input = $target) =~ s/\w/9/g; if(exists $dateformat{$input}) { die "Clashing target formats: $dateformat{$input} <-> $target"; } $dateformat{$input} = $target; (my $pattern = $input) =~ s/\W/\\W/g; push @rule, [ qr/^$pattern$/, $input, $target ]; } # memoized calculation: use Carp; sub convert { my $input = shift; return $dateformat{$input} ||= do { my $target; foreach my $ar (@rule) { my $re = $ar->[0]; if($input =~ /$re/) { # pattern matches, now apply differences $target = alter($input, @$ar); last; } } $target; } or croak "No format pattern found for $input"; } our $how; # 5 alternative ways to do the same thing sub alter { my($input, $re, $from, $to) = @_; if($how eq 'SPLIT') { # split into ('99', '-', '99', '-', '9999') # insert ('DD', 'MM', 'YYYY') into the even numbered positions (0, 2, 4) # and join again my @parts = split /(\W+)/, $input; @parts[grep !($_%2), 0 .. $#parts] = $to =~ /(\w+)/g; return join '', @parts; } elsif($how eq 'REPLACE_SUBSTR') { # replace each "9" with the character at the same position in the original target string $input =~ s(9){ substr $to, $-[0], 1 }ge; return $input; } elsif($how eq 'REPLACE_9') { # inject ('D', 'D', 'M', 'M', 'Y', 'Y', 'Y', 'Y') via s/// each replacing a "9" my @subst = $to =~ /(\w)/g; $input =~ s(9){ shift @subst }ge; return $input; } elsif($how eq 'REPLACE_9S') { # ditto but now replacing groups of nines # inject ('DD', 'MM', 'YYYY') via s/// my @subst = $to =~ /(\w+)/g; $input =~ s(9+){ shift @subst }ge; return $input; } elsif($how eq 'XOR') { # stringwise XOR with '9'^'D' for example # this will replace '9' with 'D' # XOR '-' with ('/'^'/') which is "\0", yields '-' # thus, only the nines will be affected my $xor = "$from" ^ "$to"; return "$input" ^ $xor; } else { die "Huh? What did you want me to do? '$how'?"; } } foreach $how (qw(REPLACE_SUBSTR SPLIT REPLACE_9 REPLACE_9S XOR)) { delete $dateformat{'99-99-9999'}; # kill memoized value; printf "%s: %s\n", $how, convert('99-99-9999'); }