Как я могу сделать только для чтения DateTime и DateTime :: Duration в Perl - PullRequest
3 голосов
/ 13 июля 2011

У меня есть скрипт Perl, который пытается установить некоторые настроенные экземпляры DateTime и DateTime::Duration в качестве Readonly констант. Но я вижу странное поведение при попытке сделать математику на этих объектах, если они 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";

В моей системе (Perl 5.10.0 в OSX) это отображает:

$ ./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, и оба ведут себя одинаково.

1 Ответ

5 голосов
/ 13 июля 2011

Проблема в том, что это объекты (ссылки), а не нормальные скаляры. Вам необходимо 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";
...