Skip Menu |

This queue is for tickets about the DateTime-Incomplete CPAN distribution.

Report information
The Basics
Id: 87442
Status: open
Priority: 0/
Queue: DateTime-Incomplete

People
Owner: Nobody in particular
Requestors: spudsoup [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: 0.00_07
Fixed in: (no value)



Subject: to_datetime fails for Febuary when today's day of the month > 29
DateTime::Incomplete::to_datetime Breaks on incomplete dates when the day of the month is not specified and today's day of the month is higher than the maximum valid day of the month for the supplied incomplete date. Steps to reproduce: $base = DateTime->last_day_of_month(month=>07,year=>2013); $dti = DateTime::Incomplete->new('year'=>2009, 'month'=>2); print $dti->to_datetime(base=>$base); # Invalid day of month (day = 31 - month = 2 - year = 2009) (Or wait till the the last day of any month except Feburay, when this bug will trigger without a base argument). Also affects methods that use to_datetime internaly. eg: epoch hires_epoch is_dst utc_rd_values utc_rd_as_seconds
Added a patch to fix the bug, with extra unit tests.
Subject: Fix_rt_87442.patch
diff -rupN DateTime-Incomplete-0.07/lib/DateTime/Incomplete.pm DateTime-Incomplete/lib/DateTime/Incomplete.pm --- DateTime-Incomplete-0.07/lib/DateTime/Incomplete.pm 2012-08-24 10:46:22.000000000 +0100 +++ DateTime-Incomplete/lib/DateTime/Incomplete.pm 2013-07-30 16:15:43.824501006 +0100 @@ -635,9 +635,31 @@ sub to_datetime { $result->set_time_zone( $value ); next; push @params, ( $key => $value ); } + + # See CPAN bug: https://rt.cpan.org/Ticket/Display.html?id=87442 + if( + ( 28 < $result->day_of_month ) + && + ( $self->has('month') ) + && + ( ! $self->has('day') ) + ) + { + # Find out which was the last day of the supplied month in the supplied + # year, (or this year if none is specified) + my $year = $self->year // DateTime->now()->year(); + my $last_of_that_month = DateTime->last_day_of_month( + 'year' => $year, 'month' => $self->month); + + if( $last_of_that_month->day_of_month() < $result->day_of_month ) + { + push @params, ( 'day' => $last_of_that_month->day_of_month() ); + } + } + $result->set( @params ); return $result; } diff -rupN DateTime-Incomplete-0.07/t/04base_overflow.t DateTime-Incomplete/t/04base_overflow.t --- DateTime-Incomplete-0.07/t/04base_overflow.t 2009-07-08 20:53:13.000000000 +0100 +++ DateTime-Incomplete/t/04base_overflow.t 2013-07-30 16:16:04.144896682 +0100 @@ -2,7 +2,7 @@ use strict; -use Test::More tests => 12; +use Test::More tests => 21; use DateTime; use DateTime::Incomplete; @@ -34,8 +34,60 @@ use DateTime::Incomplete; # 29 feb 2009 -> to_datetime fails... { my $dti = DateTime::Incomplete->new( month => 2, day => 29, year=>2000); - ok($dti->ymd(), "2000-02-29"); - ok($dti->to_datetime(), "29 feb 2000"); + is($dti->ymd(), "2000-02-29", 'ymd() works for 29th Feb 2000'); + is_deeply( + $dti->to_datetime(), + DateTime->last_day_of_month(year=>2000,month=>2), + "to_datetime() works for 29 feb 2000" + ); +} + +# Also broken if the day of the month is not specified. +# CPAN bug: https://rt.cpan.org/Ticket/Display.html?id=87442 +{ + my $as_datetime = undef; + my $this_year = DateTime->now()->year(); + + # Febuary only has 28 days. + my $dti = DateTime::Incomplete->new( month => 2); # year and day undef + is($dti->ymd(), "xxxx-02-xx", 'ymd() works for Feb (unknown day & year)'); + + # Base date for a month with 31 days. + my $base = DateTime->last_day_of_month(year=>2010,month=>1); + + eval{ $as_datetime = $dti->to_datetime(base=>$base) }; + ok( !($@), 'Can call to_datetime() for feb with a base date of the 31st of a month ..'); + + is_deeply( + $as_datetime, + DateTime->last_day_of_month(year=>2010,month=>2), + ".. And the returned DateTime is valid and as expected.", + ); + + # Specify the year. + $dti->set(year=>2001); # day still undef + is($dti->ymd(), "2001-02-xx", 'ymd() works for Feb 2001 (unknown day)'); + + eval{ $as_datetime = $dti->to_datetime(base=>$base) }; + ok( !($@), 'Can call to_datetime() for feb with a base date of the 31st of a month ..'); + + is_deeply( + $as_datetime, + DateTime->last_day_of_month(year=>2001,month=>2), + ".. And the returned DateTime is valid and as expected.", + ); + + # Specify only the year. + $dti = DateTime::Incomplete->new( year => 2001); # month and day undef + is($dti->ymd(), "2001-xx-xx", 'ymd() works for 2001 (unknown month & day)'); + eval{ $as_datetime = $dti->to_datetime(base=>$base) }; + ok( !($@), 'Can call to_datetime() with a base date of the 31st of a month ..'); + + is_deeply( + $as_datetime, + DateTime->last_day_of_month(year=>2001,month=>1), + ".. And the returned DateTime is valid and as expected.", + ); } # Test: require day=30
Subject: Re: [rt.cpan.org #87442] to_datetime fails for Febuary when today's day of the month > 29
Date: Wed, 31 Jul 2013 21:42:10 +0200
To: bug-DateTime-Incomplete [...] rt.cpan.org
From: "Flavio S. Glock" <fglock [...] gmail.com>
This is actually the documented behavior for this method: "=item * to_datetime ... This method may die if it results in a datetime that doesn't actually exist, such as February 30, for example." Note that is also the default behavior for DateTime: "All constructors can die when invalid parameters are given." If you have a use case for auto-correcting, maybe this could be an extra argument. For example: $dti->to_datetime( base => $base, truncate_on_overflow => 1 ) 2013/7/30 David Pottage via RT <bug-DateTime-Incomplete@rt.cpan.org>: Show quoted text
> Queue: DateTime-Incomplete > Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=87442 > > > Added a patch to fix the bug, with extra unit tests.