Reputation: 3620
strftime(), as per cpan.org:
print strftime($template, @lt);
I just can't figure the right Perl code recipe for this one. It keeps reporting an error where I call strftime():
...
use Date::Format;
...
sub parse_date {
if ($_[0]) {
$_[0] =~ /(\d{4})/;
my $y = $1;
$_[0] =~ s/\d{4}//;
$_[0] =~ /(\d\d)\D(\d\d)/;
return [$2,$1,$y];
}
return [7,7,2010];
}
foreach my $groupnode ($groupnodes->get_nodelist) {
my $groupname = $xp->find('name/text()', $groupnode);
my $entrynodes = $xp->find('entry', $groupnode);
for my $entrynode ($entrynodes->get_nodelist) {
...
my $date_added = parse_date($xp->find('date_added/text()', $entrynode));
...
$groups{$groupname}{$entryname} = {...,'date_added'=>$date_added,...};
...
}
}
...
my $imday = $maxmonth <= 12 ? 0 : 1;
...
while (my ($groupname, $entries) = each %groups) {
...
while (my ($entryname, $details) = each %$entries) {
...
my $d = @{$details->{'date_added'}};
$writer->dataElement("creation", strftime($date_template, (0,0,12,@$d[0^$imday],@$d[1^$imday]-1,@$d[2],0,0,0)));
}
...
}
...
If I use () to pass the required array by strftime(), I get: Type of arg 2 to Date::Format::strftime must be array (not list) at ./blah.pl line 87, near "))"
If I use [] to pass the required array, I get: Type of arg 2 to Date::Format::strftime must be array (not anonymous list ([])) at ./blah.pl line 87, near "])"
How can I pass an array on the fly to a sub in Perl? This can easily be done with PHP, Python, JS, etc. But I just can't figure it with Perl.
EDIT: I reduced the code to these few lines, and I still got the exact same problem:
#!/usr/bin/perl
use warnings;
use strict;
use Date::Format;
my @d = [7,13,2010];
my $imday = 1;
print strftime( q"%Y-%m-%dT12:00:00", (0,0,12,$d[0^$imday],$d[1^$imday]-1,$d[2],0,0,0));
Upvotes: 5
Views: 1614
Reputation: 98398
Where an array is required and you have an ad hoc list, you need to actually create an array. It doesn't need to be a separate variable, you can do just:
strftime(
$date_template,
@{ [0,0,12,$d[0^$imday],$d[1^$imday],$d[2],0,0,0] }
);
I have no clue why Date::Format would subject you to this hideousness and not just expect multiple scalar parameters; seems senseless (and contrary to how other modules implement strftime). Graham Barr usually designs better interfaces than this. Maybe it dates from when prototypes still seemed like a cool idea for general purposes.
Upvotes: 7
Reputation: 139491
To use a list as an anonymous array for, say, string interpolation, you could write
print "@{[1, 2, 3]}\n";
to get
1 2 3
The same technique provides a workaround to Date::Format::strftime
's funky prototype:
print strftime(q"%Y-%m-%dT12:00:00",
@{[0,0,12,$d[0^$imday],$d[1^$imday]-1,$d[2],0,0,0]});
Output:
1900-24709920-00T12:00:00
Upvotes: 3
Reputation: 118605
Normally, it is easy to pass arrays "on-the-fly" to Perl subroutines. But Date::Format::strftime
is a special case with a special prototype ($\@;$)
that doesn't allow "list" arguments or "list assignment" arguments:
strftime($format, (0,0,12,13,7-1,2010-1900)); # not ok
strftime($format, @a=(0,0,12,13,7-1,2010-1900)); # not ok
The workaround is that you must call strftime
with an array variable.
my @time = (0,0,12,13,7-1,2010-1900); # note: @array = ( ... ), not [ ... ]
strftime($format, @time);
Upvotes: 2
Reputation: 19309
I looked again and I see the real problem in this code:
my $d = @{$details->{'date_added'}};
$writer->dataElement("creation", strftime($date_template, (0,0,12,@$d[0^$imday],@$d[1^$imday]-1,@$d[2],0,0,0)));
Specifically @{$details->{'date_added'}}
is a dereference. But you're assigning it to a scalar variable and you don't need to dereference in the line below it:
my @d = @{$details->{'date_added'}};
$writer->dataElement("creation", strftime($date_template, (0,0,12,$d[0^$imday],$d[1^$imday]-1,$d[2],0,0,0)));
I've created a regular array for your reference @d
and just accessed it as a regular array ( $d[ ... ]
instead of @$d[ ... ]
)
Upvotes: 0