Bappa
Bappa

Reputation: 81

Perl Format dates

use Date::Calc qw(:all);
use Time::Piece;
use POSIX qw(strftime);
$a1 = '01.01.1963';
($year, $month, $day) = Decode_Date_US($a1);
print "$year $month $day\n";
$formatted = strftime('%m/%d/%Y',$month,$day,$year);
print "$formatted\n";

I am trying to format dates in a consistent format using POSIX(strftime). I am uncertain what the input format might be. I am using Decode_Date_US to extract the relevant year, month, day information. I am then trying to format the dates in consistent manner using strftime. I am getting following error Usage: POSIX::strftime(fmt, sec, min, hour, mday, mon, year, wday = -1, yday = -1, isdst = -1) at test_dates.pl line 60

Any help would appreciated. "use Time::Piece" would be eventually used to sort the dates.

Thanks

Upvotes: 0

Views: 848

Answers (2)

Bappa
Bappa

Reputation: 81

I ended up using DateTime module's strftime function which can handle dates earlier than 1970. "Crashing" -Perl command line interpreter has stopped working. If it helps, I am using a windows machine and a very infrequent perl user.

this worked for me

use Date::Calc qw(:all);
use DateTime;
$dateformat = "%m/%d/%Y";
($year, $month, $day) = Decode_Date_US($date);
$date = DateTime->new(
                  year=>$year,
                  month=>$month,
                  day=>$day,            
        );
$date = $date->strftime($dateformat);

Upvotes: 0

Sobrique
Sobrique

Reputation: 53508

Just use Time::Piece and strptime

#!/usr/bin/env perl
use strict;
use warnings;

use Time::Piece;

my $date = '01.01.1963';
my $timestamp = Time::Piece->strptime( $date, "%m.%d.%Y" );
print $timestamp -> strftime( "%m/%d/%Y")

But if the format is inconsistent, then you're onto a loser - for starters, there's plenty of places that transpose day/month ordering, or represent year as two digits (that sometimes will clash with month or day).

It's inherently ambiguous. You can - at best - apply some very crude guessing by grabbing groups of digits and assuming that they're in a consistent order.

E.g.

my ( $day, $month, $year ) = m/(\d{2}).*(\d{2}).*(\d{4})/; 

$timestamp = Time::Piece -> strptime ( "$year-$month-$day", "%Y-%m-%d" ); 

But you'll be tripped up by dates like 10/11/12 because you simply can't know which number is which field. You can try guessing, by evaling the strptime and just retrying different formats until you get one that does decode to something valid.

As you indicate - Decode_Date_US basically does this so:

use strict;
use warnings;
use Date::Calc qw(:all);
use Time::Piece;
my $a1 = '01.01.1963';
my ($year, $month, $day) = Decode_Date_US($a1);
my $time = Time::Piece -> strptime("$year/$month/$day", "%Y/%m/%d");
print $time->strftime("%Y-%m-%d"),"\n";

Also - use strict; use warnings; is good.

And - there's one correct way to write dates. If you're going to reformat at all, then the one that isn't ambiguous is the best choice.

Upvotes: 2

Related Questions