Odhran Roche
Odhran Roche

Reputation: 1111

Generic way to parse different date formats

I have several different date formats to parse, for example:

$date1 = '^(\d\d),(\d\d) (\d\d):(\d\d):(\d\d)'; # DD,MM HH:MM:SS
$date2 = '^(\d\d\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)'; # YYYY-MM-DD HH:MM:SS

I want to be left with the variables

($year, $day, $month, $hour, $minute, $second)

to be populated correctly. I can capture the first date format in Perl with a pattern like:

($day, $month, $hour, $minute, $second) = $log_line =~ /$date1/;
$year = current_year; # guess as date format has no year value

But to capture the second date, I would need to rearrange the order of the variables. I don't want to hardcode in the ordering for each type of date, but I know the info has to be contained somewhere.

I want this program to be scalable and maintainable; is there a simple solution for my program to adapt to the different formats?

EDIT: I realise the ordering has to be stored somewhere, I'm looking for the most concise option for doing this.

Upvotes: 2

Views: 161

Answers (2)

mpapec
mpapec

Reputation: 50677

You can use core Time::Piece module to parse dates,

use Time::Piece;

my @arr = (
  Time::Piece->strptime(Time::Piece->new->year ."01,02 13:24:01", "%Y%d,%m %H:%M:%S"),
  Time::Piece->strptime("2015-02-01 13:24:01", "%Y-%m-%d %H:%M:%S"),
);

for my $t (@arr) {
  my ($year, $day, $month, $hour, $minute, $second) = 
    ($t->year, $t->mday, $t->mon, $t->hour, $t->min, $t->sec);

  print "$year, $day, $month, $hour, $minute, $second\n";
}

Upvotes: 1

Alex
Alex

Reputation: 5893

You can solve you immediate problem with named capture groups:

if ( $str =~ /(?<year>\d\d\d\d)-(?<month>\d\d)-(?<day>\d\d)/ ) {
  $year = $+{year};
  $month = $+{month};
  $day = $+{day};
}

Your more general problem is best addressed with the various DateTime::Format modules from cpan.

Upvotes: 2

Related Questions