summaryrefslogtreecommitdiff
path: root/ext/date/lib/tm2unixtime.c
diff options
context:
space:
mode:
authorDerick Rethans <derick@php.net>2010-05-04 15:11:41 +0000
committerDerick Rethans <derick@php.net>2010-05-04 15:11:41 +0000
commit7cf3911cb8b26f90cca39e955d201fb88279ae34 (patch)
tree3cb2de644d5c91ede241417037fed28568d7ded7 /ext/date/lib/tm2unixtime.c
parentebae62d7c42442a576da3ed5917be74a239f36ed (diff)
downloadphp-git-7cf3911cb8b26f90cca39e955d201fb88279ae34.tar.gz
- Fixed bug #49081 (DateTime::diff() mistake if start in January and interval >
28 days). (Derick)
Diffstat (limited to 'ext/date/lib/tm2unixtime.c')
-rw-r--r--ext/date/lib/tm2unixtime.c75
1 files changed, 50 insertions, 25 deletions
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));
}