Patch: don't hardcode duration class
[email protected] (Sartak)
| Newsgroups | perl.datetime |
|---|---|
| Message-ID | <[email protected]> |
Hi all, I'm working on RT4 and very happily gutting our currently ad hoc date handling (a hodgepodge of Time::Local, Time::ParseDate, POSIX::tzset, and a lot of date/time logic) with DateTime. We're subclassing DateTime and it turns out we need to subclass DateTime::Duration as well. As Dave and I have learned from working with Class::MOP and Moose, it's very useful for extensibility to have class names be retrieved with method dispatch. This patch makes the duration class of DateTime easily changeable. It defines a duration_class method in DateTime for subclasses to override; it just returns the string "DateTime::Duration" so there's no worry about back-compat issues. It also adds some tests. Thanks, Shawn
duration_class.diff
(application/octet-stream, 2.8 KB)
Index: t/42duration_class.t
===================================================================
--- t/42duration_class.t (revision 0)
+++ t/42duration_class.t (revision 0)
@@ -0,0 +1,26 @@
+#!/usr/bin/perl -w
+use strict;
+use Test::More tests => 3;
+use DateTime;
+
+do {
+ package DateTime::MySubclass;
+ use base 'DateTime';
+
+ sub duration_class { 'DateTime::Duration::MySubclass' }
+
+ package DateTime::Duration::MySubclass;
+ use base 'DateTime::Duration';
+
+ sub is_my_subclass { 1 }
+};
+
+my $dt = DateTime::MySubclass->now;
+my $delta = $dt - $dt;
+
+isa_ok($delta, 'DateTime::Duration::MySubclass');
+isa_ok($dt + $delta, 'DateTime::MySubclass');
+
+my $delta_days = $dt->delta_days($dt);
+isa_ok($delta_days, 'DateTime::Duration::MySubclass');
+
Index: lib/DateTime.pm
===================================================================
--- lib/DateTime.pm (revision 4124)
+++ lib/DateTime.pm (working copy)
@@ -76,6 +76,8 @@
use constant SECONDS_PER_DAY => 86400;
+use constant duration_class => 'DateTime::Duration';
+
my( @MonthLengths, @LeapYearMonthLengths );
BEGIN
@@ -1323,7 +1325,7 @@
}
return
- DateTime::Duration->new
+ $dt1->duration_class->new
( months => $months,
days => $days,
minutes => $minutes,
@@ -1401,7 +1403,7 @@
}
return
- DateTime::Duration->new
+ $self->duration_class->new
( seconds => $seconds,
nanoseconds => $nanoseconds,
);
@@ -1431,8 +1433,8 @@
$smaller->_month_length( $smaller->year, $smaller->month ),
);
- return DateTime::Duration->new( months => $months,
- days => $days );
+ return $self->duration_class->new( months => $months,
+ days => $days );
}
sub delta_days
@@ -1442,7 +1444,7 @@
my ( $smaller, $bigger ) = sort( ($self->local_rd_values)[0], ($dt->local_rd_values)[0] );
- DateTime::Duration->new( days => $bigger - $smaller );
+ $self->duration_class->new( days => $bigger - $smaller );
}
sub delta_ms
@@ -1461,7 +1463,7 @@
$p{minutes} = $dur->minutes;
$p{seconds} = $dur->seconds;
- return DateTime::Duration->new(%p);
+ return $self->duration_class->new(%p);
}
sub _add_overload
@@ -1516,10 +1518,18 @@
}
}
-sub add { return shift->add_duration( DateTime::Duration->new(@_) ) }
+sub add {
+ my $self = shift;
-sub subtract { return shift->subtract_duration( DateTime::Duration->new(@_) ) }
+ return $self->add_duration( $self->duration_class->new(@_) );
+}
+sub subtract {
+ my $self = shift;
+
+ return $self->subtract_duration( $self->duration_class->new(@_) );
+}
+
sub subtract_duration { return $_[0]->add_duration( $_[1]->inverse ) }
{