3

How do I do the following conversion in regex in Perl?

British style   US style
"2009-27-02" => "2009-02-27"

I am new to Perl and don't know much about regex, all I can think of is to extract different parts of the "-" then re-concatenate the string, since I need to do the conversion on the fly, I felt my approach will be pretty slow and ugly.

Mark Canlas
  • 9,385
  • 5
  • 41
  • 63
John
  • 221
  • 1
  • 5
  • 14
  • 1
    y-d-m is not British style, d-m-y is. While US style is m-d-y. y-m-d is closer to ISO than anything. – Quentin Jan 07 '10 at 20:19
  • 2
    FYI: This is fixed-width data with a standard separator, and that says to me that you really don't need a regex. I saw your comment on Axeman's post, and it's worth saying (again) that Perl is not simply "How can I do this in a regex." A regex is *not* always the best answer, even in Perl. – Telemachus Jan 07 '10 at 21:41

3 Answers3

14
use strict;
use warnings;
use v5.10;

my $date = "2009-27-02";
$date =~ s/(\d{4})-(\d{2})-(\d{2})/$1-$3-$2/;
say $date;
Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • 1
    By the way, I never know say is a perl keyword, was it introduced recently? – John Jan 07 '10 at 20:44
  • 3
    Yes, backported from Perl 6 into Perl 5.10 (hence the `use v5.10` line here). See `perldoc feature` http://perldoc.perl.org/feature.html#IMPLICIT-LOADING – ephemient Jan 07 '10 at 20:55
  • 1
    say was introduced in perl 5.10 but you need to `use v5.10` to enable it (like print but it automatically adds newlines). – ternaryOperator Jan 07 '10 at 20:56
5

You asked about regex, but for such an obvious substitution, you could also compose a function of split and parse. On my machine it's about 22% faster:

my @parts = split '-', $date;
my $ndate = join( '-', @parts[0,2,1] );

Also you could keep various orders around, like so:

my @ymd = qw<0 2 1>;
my @mdy = qw<2 1 0>;

And they can be used just like the literal sequence in the first section:

my $ndate = join( $date_separator, @date_parts[@$order] );

Just an idea to consider.

Axeman
  • 29,660
  • 2
  • 47
  • 102
  • I definitely could, and I wrote very much the same code as yours. However, I feel like I should choose regex as it is neat and improves readability (considering I am using perl). Thanks anyway. – John Jan 07 '10 at 21:09
  • @John: well, it could be faster, so it answers the "slow and ugly" part. And, as I showed, can be expanded to be a bit more flexible in approach. – Axeman Jan 07 '10 at 21:23
  • @John: I dunno, I think `$date = join '-', reverse split /-/, $date;` is at least as clear as the regex solution. – ephemient Jan 08 '10 at 04:37
4

You can also use Date::Parse for reading and converting dates. See this question for more information.

Community
  • 1
  • 1
James Thompson
  • 46,512
  • 18
  • 65
  • 82