jagdish eashwar wrote:
>I came across some unexpected behaviour in datetime. In the following
>script, I first define $date1. Then I set $day1 = $date1. Then I add 2 days
>to $day1. Why does $date1 also get incremented?
Because a DateTime object doesn't represent a date-and-time per se; it
implements a variable that is typed to hold a date and time. Walkthrough:
>my $date1 = DateTime->new(year => 2007,
> month => 12,
> day => 23);
You create a date/time variable, initialised as holding the date
2007-12-23. You set $date1 to be a reference to that variable.
>my $day1 = $date1;
You copy the reference to the date/time variable from $date1 to $day1.
Both of these Perl variables now refer to the same date/time variable.
>$day1->add(days => 2);
You reference the date/time variable (via $day1), and tell it to modify
the date value that it holds by advancing it by two days. The date/time
variable now holds the date 2007-12-25.
>print "day1 = ",$day1,"\n"; # gives me 2007-12-25 correctly.
You reference the date/time variable (via $day1), and ask it to display
the date that it holds (2007-12-25).
>print "date1 = ",$date1,"\n"; # why does $date1 also change to 2007-12-25?
You reference the date/time variable (via $date1), and ask it again to
display the date that it holds (2007-12-25).
The stage that should have rung alarm bells for you is
$day1->add(days => 2);
where you're doing date arithmetic calling a method on an object and
*ignoring its return value*. This method operates by having a side effect
on the object. If, instead, DateTime objects actually represented dates
and times per se, then there wouldn't be any of these side effects,
and this step in the program (combined with the previous step) would
instead be something like
my $day1 = $date1->plus(days => 2);
As it is, you need to create a second date/time variable, initialised
by copying the value from the first one. So instead of
my $day1 = $date1;
do
my $day1 = $date1->clone;
Then the ->add call will side-effect this second date/time variable,
the one referenced by $day1, and leave the original date/time variable,
the one referenced by $date1, alone.
-zefram