mirror of
https://github.com/php/php-src.git
synced 2024-11-24 10:24:11 +08:00
- Fixed bug #49081 (DateTime::diff() mistake if start in January and interval >
28 days). (Derick)
This commit is contained in:
parent
ebae62d7c4
commit
7cf3911cb8
2
NEWS
2
NEWS
@ -129,6 +129,8 @@ PHP NEWS
|
||||
- Fixed bug #49429 (odbc_autocommit doesn't work). (Felipe)
|
||||
- Fixed bug #49234 (mysqli_ssl_set not found). (Andrey)
|
||||
- Fixed bug #49192 (PHP crashes when GC invoked on COM object). (Stas)
|
||||
- Fixed bug #49081 (DateTime::diff() mistake if start in January and interval >
|
||||
28 days). (Derick)
|
||||
- Fixed bug #49059 (DateTime::diff() repeats previous sub() operation).
|
||||
(yoarvi@gmail.com, Derick)
|
||||
- Fixed bug #48983 (DomDocument : saveHTMLFile wrong charset). (Rob)
|
||||
|
@ -56,7 +56,7 @@ timelib_rel_time *timelib_diff(timelib_time *one, timelib_time *two)
|
||||
rt->s = two->s - one->s;
|
||||
rt->days = abs(floor((one->sse - two->sse - (dst_h_corr * 3600) - (dst_m_corr * 60)) / 86400));
|
||||
|
||||
timelib_do_rel_normalize(one, rt);
|
||||
timelib_do_rel_normalize(rt->invert ? one : two, rt);
|
||||
|
||||
timelib_apply_localtime(one, 1);
|
||||
timelib_apply_localtime(two, 1);
|
||||
|
@ -41,39 +41,64 @@ static int do_range_limit(timelib_sll start, timelib_sll end, timelib_sll adj, t
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_range_limit_days_relative(timelib_sll *base_y, timelib_sll *base_m, timelib_sll *y, timelib_sll *m, timelib_sll *d)
|
||||
static void inc_month(timelib_sll *y, timelib_sll *m)
|
||||
{
|
||||
(*m)++;
|
||||
if (*m > 12) {
|
||||
*m -= 12;
|
||||
(*y)++;
|
||||
}
|
||||
}
|
||||
|
||||
static void dec_month(timelib_sll *y, timelib_sll *m)
|
||||
{
|
||||
(*m)--;
|
||||
if (*m < 1) {
|
||||
*m += 12;
|
||||
(*y)--;
|
||||
}
|
||||
}
|
||||
|
||||
static void do_range_limit_days_relative(timelib_sll *base_y, timelib_sll *base_m, timelib_sll *y, timelib_sll *m, timelib_sll *d, timelib_sll invert)
|
||||
{
|
||||
timelib_sll leapyear;
|
||||
timelib_sll days_this_month;
|
||||
timelib_sll next_month, next_year;
|
||||
timelib_sll days_next_month;
|
||||
timelib_sll month, year;
|
||||
timelib_sll days;
|
||||
|
||||
do_range_limit(1, 13, 12, base_m, base_y);
|
||||
|
||||
leapyear = timelib_is_leap(*base_y);
|
||||
days_this_month = leapyear ? days_in_month_leap[*base_m] : days_in_month[*base_m];
|
||||
next_month = (*base_m) + 1;
|
||||
year = *base_y;
|
||||
month = *base_m;
|
||||
|
||||
if (next_month > 12) {
|
||||
next_month -= 12;
|
||||
next_year = (*base_y) + 1;
|
||||
/*
|
||||
printf( "S: Y%d M%d %d %d %d %d\n", year, month, *y, *m, *d, days);
|
||||
*/
|
||||
if (!invert) {
|
||||
while (*d < 0) {
|
||||
dec_month(&year, &month);
|
||||
leapyear = timelib_is_leap(year);
|
||||
days = leapyear ? days_in_month_leap[month] : days_in_month[month];
|
||||
|
||||
/* printf( "I Y%d M%d %d %d %d %d\n", year, month, *y, *m, *d, days); */
|
||||
|
||||
*d += days;
|
||||
(*m)--;
|
||||
}
|
||||
} else {
|
||||
next_year = (*base_y);
|
||||
}
|
||||
leapyear = timelib_is_leap(next_year);
|
||||
days_next_month = leapyear ? days_in_month_leap[next_month] : days_in_month[next_month];
|
||||
while (*d < 0) {
|
||||
leapyear = timelib_is_leap(year);
|
||||
days = leapyear ? days_in_month_leap[month] : days_in_month[month];
|
||||
|
||||
if (*d < 0) {
|
||||
*d += days_this_month;
|
||||
(*m)--;
|
||||
return 1;
|
||||
/* printf( "I Y%d M%d %d %d %d %d\n", year, month, *y, *m, *d, days); */
|
||||
|
||||
*d += days;
|
||||
(*m)--;
|
||||
inc_month(&year, &month);
|
||||
}
|
||||
}
|
||||
if (*d > days_next_month) {
|
||||
*d -= days_next_month;
|
||||
(*m)++;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
/*
|
||||
printf( "E: Y%d M%d %d %d %d %d\n", year, month, *y, *m, *d, days);
|
||||
*/
|
||||
}
|
||||
|
||||
static int do_range_limit_days(timelib_sll *y, timelib_sll *m, timelib_sll *d)
|
||||
@ -150,7 +175,7 @@ void timelib_do_rel_normalize(timelib_time *base, timelib_rel_time *rt)
|
||||
do {} while (do_range_limit(0, 24, 24, &rt->h, &rt->d));
|
||||
do {} while (do_range_limit(0, 12, 12, &rt->m, &rt->y));
|
||||
|
||||
do {} while (do_range_limit_days_relative(&base->y, &base->m, &rt->y, &rt->m, &rt->d));
|
||||
do_range_limit_days_relative(&base->y, &base->m, &rt->y, &rt->m, &rt->d, rt->invert);
|
||||
do {} while (do_range_limit(0, 12, 12, &rt->m, &rt->y));
|
||||
}
|
||||
|
||||
|
22
ext/date/tests/bug49081.phpt
Normal file
22
ext/date/tests/bug49081.phpt
Normal file
@ -0,0 +1,22 @@
|
||||
--TEST--
|
||||
Bug #49081 (DateTime::diff() mistake if start in January and interval > 28 days)
|
||||
--FILE--
|
||||
<?php
|
||||
date_default_timezone_set('Europe/Berlin');
|
||||
$d1 = new DateTime('2010-01-01 06:00:00');
|
||||
$d2 = new DateTime('2010-01-31 10:00:00');
|
||||
$d = $d1->diff($d2);
|
||||
print_r($d);
|
||||
?>
|
||||
--EXPECT--
|
||||
DateInterval Object
|
||||
(
|
||||
[y] => 0
|
||||
[m] => 0
|
||||
[d] => 30
|
||||
[h] => 4
|
||||
[i] => 0
|
||||
[s] => 0
|
||||
[invert] => 0
|
||||
[days] => 30
|
||||
)
|
57
ext/date/tests/date_diff.phpt
Normal file
57
ext/date/tests/date_diff.phpt
Normal file
@ -0,0 +1,57 @@
|
||||
--TEST--
|
||||
Extensive test for date_diff().
|
||||
--FILE--
|
||||
<?php
|
||||
$ok = 0;
|
||||
define( 'COUNT', 120 );
|
||||
$d0 = new DateTime('2009-11-20');
|
||||
for ( $i = 0; $i < COUNT * 12; $i++ )
|
||||
{
|
||||
$d = clone $d0;
|
||||
$dates[$i] = $d->add( new DateInterval( "P{$i}D" ) );
|
||||
}
|
||||
|
||||
for ( $i = 0; $i < COUNT; $i++)
|
||||
{
|
||||
// echo $dates[$i]->format( "Y-m-d\n" );
|
||||
for ( $j = 0; $j < COUNT * 12; $j++)
|
||||
{
|
||||
$diff = date_diff( $dates[$i], $dates[$j] );
|
||||
/*
|
||||
printf( "\t%s %s %3d %s\n",
|
||||
$dates[$i]->format( 'Y-m-d' ),
|
||||
$dates[$j]->format( 'Y-m-d' ),
|
||||
$diff->format( '%a' ),
|
||||
$diff->format( '%y-%m-%d' )
|
||||
);
|
||||
*/
|
||||
|
||||
$current = clone $dates[$i];
|
||||
$int = new DateInterval( $diff->format( 'P%yY%mM%dD' ) );
|
||||
if ( $current > $dates[$j] )
|
||||
{
|
||||
$current->sub( $int );
|
||||
}
|
||||
else
|
||||
{
|
||||
$current->add( $int );
|
||||
}
|
||||
if ( $current != $dates[$j] )
|
||||
{
|
||||
echo "FAIL: ",
|
||||
$dates[$i]->format( 'Y-m-d' ), " + ",
|
||||
$int->format( '%y-%m-%d' ), " = ",
|
||||
$current->format( 'Y-m-d' ), " (",
|
||||
$dates[$j]->format( 'Y-m-d' ), ")\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
$ok++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo $ok, "\n";
|
||||
?>
|
||||
--EXPECT--
|
||||
172800
|
Loading…
Reference in New Issue
Block a user