From 7cf3911cb8b26f90cca39e955d201fb88279ae34 Mon Sep 17 00:00:00 2001 From: Derick Rethans Date: Tue, 4 May 2010 15:11:41 +0000 Subject: - Fixed bug #49081 (DateTime::diff() mistake if start in January and interval > 28 days). (Derick) --- ext/date/lib/tm2unixtime.c | 75 ++++++++++++++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 25 deletions(-) (limited to 'ext/date/lib/tm2unixtime.c') diff --git a/ext/date/lib/tm2unixtime.c b/ext/date/lib/tm2unixtime.c index 3707771f67..59f7daf9fb 100644 --- a/ext/date/lib/tm2unixtime.c +++ b/ext/date/lib/tm2unixtime.c @@ -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; - } - if (*d > days_next_month) { - *d -= days_next_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); + } } - 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)); } -- cgit v1.2.1