开发者

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";
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜