如何在Perl中创建只读DateTime和DateTime::Duration

如何在Perl中创建只读DateTime和DateTime::Duration,perl,datetime,readonly,Perl,Datetime,Readonly,我有一个Perl脚本,它试图将一些已配置的DateTime和DateTime::Duration实例设置为Readonly常量。但如果这些对象是只读的,我在尝试对它们进行数学运算时会看到奇怪的行为。下面是一个简单的例子: #!/usr/bin/perl -w use strict; use warnings; use DateTime; use Readonly; Readonly my $X => DateTime->now; my $x = DateTime->now

我有一个Perl脚本,它试图将一些已配置的
DateTime
DateTime::Duration
实例设置为
Readonly
常量。但如果这些对象是
只读的
,我在尝试对它们进行数学运算时会看到奇怪的行为。下面是一个简单的例子:

#!/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";
在我的系统(OSX上的Perl 5.10.0)上显示:

$ ./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

因此,使
DateTime
DateTime::Duration
Readonly
看起来会导致它们无法正常工作。这是虫子吗?还是我使用的
Readonly
错误?我还尝试了
Readonly::Scalar
Readonly::Scalar1
,它们的行为方式都相同。

问题是它们是对象(引用),而不是普通的标量。您需要
Readonly
引用中包含的值,而不是引用本身;但事实证明这很棘手。类似这样的方法似乎有效:

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

Readonly并不声称能够正确地使用受祝福的引用(这是您从DateTime模块创建的)。