How can I make a Readonly DateTime and DateTime::Duration in Perl
I have a Perl script that's trying to set some configured DateTime
and DateTime::Duration
instances as Readonly
constants. But I see strange behavior when trying to do mat开发者_如何学Goh on these objects if they are Readonly
. Here's a minimal example:
#!/usr/bin/perl -w
use strict;
use warnings;
use DateTime;
use Readonly;
Readonly my $X => DateTime->now;
my $x = DateTime->now;
Readonly my $Y => DateTime::Duration->new( days => 3 );
my $y = DateTime::Duration->new( days => 3 );
my $a = $X - $Y;
my $b = $x - $y;
print "$a\n";
print "$b\n";
On my system (Perl 5.10.0 on OSX) this displays:
$ ./datetime_test.pl
Argument "2011-07-12T20:36:08" isn't numeric in subtraction (-) at ./datetime_test.pl line 15.
-4305941629
2011-07-09T20:36:08
So it looks like making the DateTime
and the DateTime::Duration
Readonly
causes them to function incorrectly. Is this a bug? Or am I using Readonly
wrong? I've also tried Readonly::Scalar
and Readonly::Scalar1
, and both behave the same way.
The problem is that they're objects (references), not normal scalars. You would need to Readonly
the values contained in the references, not the references themselves; but this turns out to be tricky. Something like this appears to work:
use Readonly;
use DateTime;
# you can't just say "Readonly %$dt"; here at least, it dies on blessed refs
sub makeRO {
my $dt = shift;
while (my ($k, $v) = each %$dt) {
Readonly $dt->{$k} => $v;
}
}
my $x = DateTime::Duration->new(days => 3);
makeRO($x);
my $y = DateTime::Duration->new(days => 3);
my $a = $x - $y;
# print "$a\n"; # this isn't overloaded; you'll get "DateTime::Duration=HASH(...)"
print $a->days, "\n";
精彩评论