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 ) }
 
 {
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.