Skip Menu |

Preferred bug tracker

Please visit the preferred bug tracker to report your issue.

This queue is for tickets about the DateTime CPAN distribution.

Report information
The Basics
Id: 77844
Status: resolved
Priority: 0/
Queue: DateTime

People
Owner: Nobody in particular
Requestors: rt-cpan [...] triv.org
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: 0.75
Fixed in: 0.76



Subject: DateTime::subtract() does not honor end_of_month
DateTime::subtract() does not honor a given end_of_month parameter. This is because the subtract() just makes a duration object and calls add_duration() with the inverse of that duration object, which causes the end_of_month parameter tro get lost in the shuffle. Fix attacted. -- Chris Reinhardt perl@triv.org
Subject: subtract_eom_fix.diff
diff --git a/lib/DateTime.pm b/lib/DateTime.pm index bf97833..4c39a68 100644 --- a/lib/DateTime.pm +++ b/lib/DateTime.pm @@ -1630,8 +1630,15 @@ sub add { sub subtract { my $self = shift; - - return $self->subtract_duration( $self->duration_class->new(@_) ); + my %p = @_; + + my %extras; + $extras{end_of_month} = delete $p{end_of_month} + if exists $p{end_of_month}; + + my $duration = $self->duration_class->new( %p )->inverse( %extras ); + + return $self->add_duration( $duration ); } sub subtract_duration { return $_[0]->add_duration( $_[1]->inverse ) } diff --git a/lib/DateTime/Duration.pm b/lib/DateTime/Duration.pm index bf82a1c..196c5ea 100644 --- a/lib/DateTime/Duration.pm +++ b/lib/DateTime/Duration.pm @@ -409,8 +409,8 @@ of the month the new date will also be. For instance, adding one month to Feb 29, 2000 will result in Mar 31, 2000. For positive durations, the "end_of_month" parameter defaults to wrap. -For negative durations, the default is "limit". This should match how -most people "intuitively" expect datetime math to work. +For negative durations, the default is "preserve". This should match +how most people "intuitively" expect datetime math to work. =item * clone diff --git a/t/10subtract.t b/t/10subtract.t index 43d1c97..3260f70 100644 --- a/t/10subtract.t +++ b/t/10subtract.t @@ -427,4 +427,54 @@ use DateTime; ); } +{ + my $dt1 = DateTime->new( + year => 2005, month => 2, day => 28, + time_zone => 'UTC' + ); + + my $dt2 = $dt1->clone->subtract(months => 1, end_of_month => 'wrap'); + + is($dt2->month, 1, 'feb 28 - 1 month in jan'); + is($dt2->day, 28, 'and on the 28th with wrap'); +} + + +{ + my $dt1 = DateTime->new( + year => 2005, month => 2, day => 28, + time_zone => 'UTC' + ); + + my $dt2 = $dt1->clone->subtract(months => 1, end_of_month => 'limit'); + + is($dt2->month, 1, 'feb 28 - 1 month in jan'); + is($dt2->day, 28, 'and on the 28th with limit'); +} + + +{ + my $dt1 = DateTime->new( + year => 2005, month => 2, day => 28, + time_zone => 'UTC' + ); + + my $dt2 = $dt1->clone->subtract(months => 1, end_of_month => 'preserve'); + + is($dt2->month, 1, 'feb 28 - 1 month in jan'); + is($dt2->day, 31, 'and on the 31th with preserve'); +} + +{ + my $dt1 = DateTime->new( + year => 2005, month => 2, day => 28, + time_zone => 'UTC' + ); + + my $dt2 = $dt1->clone->subtract(months => 1); + + is($dt2->month, 1, 'feb 28 - 1 month in jan'); + is($dt2->day, 31, 'and on the 31th with default (preserve)'); +} + done_testing();