summaryrefslogtreecommitdiff
path: root/ext/date
diff options
context:
space:
mode:
authorDerick Rethans <derick@php.net>2007-07-12 18:58:00 +0000
committerDerick Rethans <derick@php.net>2007-07-12 18:58:00 +0000
commit4b64dbb9a19b962d9a4ec72dc128e5d48c425c9b (patch)
treeade8ff7d09186faa9a883efe7d1ba678049fa588 /ext/date
parente206802652c4ffe46338879d64ece4731f89fd30 (diff)
downloadphp-git-4b64dbb9a19b962d9a4ec72dc128e5d48c425c9b.tar.gz
- MFH: Fixed bug #41964 (strtotime returns a timestamp for non-time string of
pattern '(A|a) .+'). - MFH: Fixed bug #41844 (Format returns incorrect number of digits for negative years -0001 to -0999). - MFH: Fixed bug #41842 (Cannot create years < 0100 & negative years with date_create or new DateTime). - MFH: Fixed bug #41709 (strtotime() does not handle 00.00.0000). - MFH: Fixed bug #41523 (strtotime('0000-00-00 00:00:00') is parsed as 1999-11-30).
Diffstat (limited to 'ext/date')
-rw-r--r--ext/date/lib/parse_date.re99
-rw-r--r--ext/date/lib/timelib.c4
-rw-r--r--ext/date/lib/unixtime2tm.c2
-rw-r--r--ext/date/tests/bug35499.phpt70
-rw-r--r--ext/date/tests/bug41523.phpt45
-rw-r--r--ext/date/tests/bug41709.phpt33
-rw-r--r--ext/date/tests/bug41842.phpt11
-rw-r--r--ext/date/tests/bug41844.phpt17
-rw-r--r--ext/date/tests/bug41964.phpt59
9 files changed, 299 insertions, 41 deletions
diff --git a/ext/date/lib/parse_date.re b/ext/date/lib/parse_date.re
index 20e72ef922..72816a955a 100644
--- a/ext/date/lib/parse_date.re
+++ b/ext/date/lib/parse_date.re
@@ -42,6 +42,8 @@
# endif
#endif
+#define TIMELIB_UNSET -99999
+
#define TIMELIB_SECOND 1
#define TIMELIB_MINUTE 2
#define TIMELIB_HOUR 3
@@ -112,7 +114,7 @@ typedef unsigned char uchar;
#define TIMELIB_ADJUST_RELATIVE_WEEKDAY() if (in->time.have_weekday_relative && (in.rel.d > 0)) { in.rel.d -= 7; }
#define TIMELIB_PROCESS_YEAR(x) { \
- if ((x) == -1) { \
+ if ((x) == TIMELIB_UNSET) { \
/* (x) = 0; */ \
} else if ((x) < 100) { \
if ((x) < 70) { \
@@ -381,12 +383,12 @@ static char *timelib_string(Scanner *s)
static timelib_sll timelib_get_nr(char **ptr, int max_length)
{
char *begin, *end, *str;
- timelib_sll tmp_nr = -1;
+ timelib_sll tmp_nr = TIMELIB_UNSET;
int len = 0;
while ((**ptr < '0') || (**ptr > '9')) {
if (**ptr == '\0') {
- return -1;
+ return TIMELIB_UNSET;
}
++*ptr;
}
@@ -416,12 +418,12 @@ static void timelib_skip_day_suffix(char **ptr)
static double timelib_get_frac_nr(char **ptr, int max_length)
{
char *begin, *end, *str;
- double tmp_nr = -1;
+ double tmp_nr = TIMELIB_UNSET;
int len = 0;
while ((**ptr != '.') && ((**ptr < '0') || (**ptr > '9'))) {
if (**ptr == '\0') {
- return -1;
+ return TIMELIB_UNSET;
}
++*ptr;
}
@@ -444,7 +446,7 @@ static timelib_ull timelib_get_unsigned_nr(char **ptr, int max_length)
while (((**ptr < '0') || (**ptr > '9')) && (**ptr != '+') && (**ptr != '-')) {
if (**ptr == '\0') {
- return -1;
+ return TIMELIB_UNSET;
}
++*ptr;
}
@@ -794,12 +796,13 @@ day = ([0-2]?[0-9] | "3"[01]) daysuf?;
year = [0-9]{1,4};
year2 = [0-9]{2};
year4 = [0-9]{4};
+year4withsign = [+-]? [0-9]{4};
dayofyear = "00"[1-9] | "0"[1-9][0-9] | [1-2][0-9][0-9] | "3"[0-5][0-9] | "36"[0-6];
weekofyear = "0"[1-9] | [1-4][0-9] | "5"[0-3];
-monthlz = "0" [1-9] | "1" [0-2];
-daylz = "0" [1-9] | [1-2][0-9] | "3" [01];
+monthlz = "0" [0-9] | "1" [0-2];
+daylz = "0" [0-9] | [1-2][0-9] | "3" [01];
dayfull = 'sunday' | 'monday' | 'tuesday' | 'wednesday' | 'thursday' | 'friday' | 'saturday';
dayabbr = 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat' | 'sun';
@@ -834,10 +837,12 @@ americanshort = month "/" day;
american = month "/" day "/" year;
iso8601dateslash = year4 "/" monthlz "/" daylz "/"?;
dateslash = year4 "/" month "/" day;
+iso8601date4 = year4withsign "-" monthlz "-" daylz;
+iso8601date2 = year2 "-" monthlz "-" daylz;
gnudateshorter = year4 "-" month;
gnudateshort = year "-" month "-" day;
-iso8601date = year4 "-" monthlz "-" daylz;
-pointeddate = day [.\t-] month [.-] year;
+pointeddate4 = day [.\t-] month [.-] year4;
+pointeddate2 = day [.\t-] month [.-] year2;
datefull = day ([ \t.-])* monthtext ([ \t.-])* year;
datenoday = monthtext ([ .\t-])* year4;
datenodayrev = year4 ([ .\t-])* monthtext;
@@ -1088,14 +1093,27 @@ relativetext = reltextnumber space reltextunit;
return TIMELIB_AMERICAN;
}
- iso8601date | iso8601dateslash | dateslash
+ iso8601date4 | iso8601dateslash | dateslash
+ {
+ DEBUG_OUTPUT("iso8601date4 | iso8601date2 | iso8601dateslash | dateslash");
+ TIMELIB_INIT;
+ TIMELIB_HAVE_DATE();
+ s->time->y = timelib_get_unsigned_nr((char **) &ptr, 4);
+ s->time->m = timelib_get_nr((char **) &ptr, 2);
+ s->time->d = timelib_get_nr((char **) &ptr, 2);
+ TIMELIB_DEINIT;
+ return TIMELIB_ISO_DATE;
+ }
+
+ iso8601date2
{
- DEBUG_OUTPUT("iso8601date | iso8601dateslash | dateslash");
+ DEBUG_OUTPUT("iso8601date2");
TIMELIB_INIT;
TIMELIB_HAVE_DATE();
s->time->y = timelib_get_nr((char **) &ptr, 4);
s->time->m = timelib_get_nr((char **) &ptr, 2);
s->time->d = timelib_get_nr((char **) &ptr, 2);
+ TIMELIB_PROCESS_YEAR(s->time->y);
TIMELIB_DEINIT;
return TIMELIB_ISO_DATE;
}
@@ -1139,14 +1157,26 @@ relativetext = reltextnumber space reltextunit;
return TIMELIB_DATE_FULL;
}
- pointeddate
+ pointeddate4
{
- DEBUG_OUTPUT("pointed date");
+ DEBUG_OUTPUT("pointed date YYYY");
TIMELIB_INIT;
TIMELIB_HAVE_DATE();
s->time->d = timelib_get_nr((char **) &ptr, 2);
s->time->m = timelib_get_nr((char **) &ptr, 2);
s->time->y = timelib_get_nr((char **) &ptr, 4);
+ TIMELIB_DEINIT;
+ return TIMELIB_DATE_FULL_POINTED;
+ }
+
+ pointeddate2
+ {
+ DEBUG_OUTPUT("pointed date YY");
+ TIMELIB_INIT;
+ TIMELIB_HAVE_DATE();
+ s->time->d = timelib_get_nr((char **) &ptr, 2);
+ s->time->m = timelib_get_nr((char **) &ptr, 2);
+ s->time->y = timelib_get_nr((char **) &ptr, 2);
TIMELIB_PROCESS_YEAR(s->time->y);
TIMELIB_DEINIT;
return TIMELIB_DATE_FULL_POINTED;
@@ -1535,7 +1565,7 @@ timelib_time* timelib_strtotime(char *s, int len, struct timelib_error_container
e--;
}
}
- if (e - s < 1) {
+ if (e - s < 0) {
in.time = timelib_time_ctor();
add_error(&in, "Empty string");
if (errors) {
@@ -1543,8 +1573,7 @@ timelib_time* timelib_strtotime(char *s, int len, struct timelib_error_container
} else {
timelib_error_container_dtor(in.errors);
}
- in.time->y = in.time->d = in.time->m = in.time->h = in.time->i = in.time->s = in.time->f = in.time->dst = -1;
- in.time->z = -999999;
+ in.time->y = in.time->d = in.time->m = in.time->h = in.time->i = in.time->s = in.time->f = in.time->dst = in.time->z = TIMELIB_UNSET;
in.time->is_localtime = in.time->zone_type = 0;
return in.time;
}
@@ -1556,15 +1585,15 @@ timelib_time* timelib_strtotime(char *s, int len, struct timelib_error_container
in.lim = in.str + (e - s) + YYMAXFILL;
in.cur = in.str;
in.time = timelib_time_ctor();
- in.time->y = -1;
- in.time->d = -1;
- in.time->m = -1;
- in.time->h = -1;
- in.time->i = -1;
- in.time->s = -1;
- in.time->f = -1;
- in.time->z = -999999;
- in.time->dst = -1;
+ in.time->y = TIMELIB_UNSET;
+ in.time->d = TIMELIB_UNSET;
+ in.time->m = TIMELIB_UNSET;
+ in.time->h = TIMELIB_UNSET;
+ in.time->i = TIMELIB_UNSET;
+ in.time->s = TIMELIB_UNSET;
+ in.time->f = TIMELIB_UNSET;
+ in.time->z = TIMELIB_UNSET;
+ in.time->dst = TIMELIB_UNSET;
in.tzdb = tzdb;
in.time->is_localtime = 0;
in.time->zone_type = 0;
@@ -1593,15 +1622,15 @@ void timelib_fill_holes(timelib_time *parsed, timelib_time *now, int options)
parsed->s = 0;
parsed->f = 0;
}
- if (parsed->y == -1) parsed->y = now->y != -1 ? now->y : 0;
- if (parsed->d == -1) parsed->d = now->d != -1 ? now->d : 0;
- if (parsed->m == -1) parsed->m = now->m != -1 ? now->m : 0;
- if (parsed->h == -1) parsed->h = now->h != -1 ? now->h : 0;
- if (parsed->i == -1) parsed->i = now->i != -1 ? now->i : 0;
- if (parsed->s == -1) parsed->s = now->s != -1 ? now->s : 0;
- if (parsed->f == -1) parsed->f = now->f != -1 ? now->f : 0;
- if (parsed->z == -999999) parsed->z = now->z != -999999 ? now->z : 0;
- if (parsed->dst == -1) parsed->dst = now->dst != -1 ? now->dst : 0;
+ if (parsed->y == TIMELIB_UNSET) parsed->y = now->y != TIMELIB_UNSET ? now->y : 0;
+ if (parsed->d == TIMELIB_UNSET) parsed->d = now->d != TIMELIB_UNSET ? now->d : 0;
+ if (parsed->m == TIMELIB_UNSET) parsed->m = now->m != TIMELIB_UNSET ? now->m : 0;
+ if (parsed->h == TIMELIB_UNSET) parsed->h = now->h != TIMELIB_UNSET ? now->h : 0;
+ if (parsed->i == TIMELIB_UNSET) parsed->i = now->i != TIMELIB_UNSET ? now->i : 0;
+ if (parsed->s == TIMELIB_UNSET) parsed->s = now->s != TIMELIB_UNSET ? now->s : 0;
+ if (parsed->f == TIMELIB_UNSET) parsed->f = now->f != TIMELIB_UNSET ? now->f : 0;
+ if (parsed->z == TIMELIB_UNSET) parsed->z = now->z != TIMELIB_UNSET ? now->z : 0;
+ if (parsed->dst == TIMELIB_UNSET) parsed->dst = now->dst != TIMELIB_UNSET ? now->dst : 0;
if (!parsed->tz_abbr) {
parsed->tz_abbr = now->tz_abbr ? strdup(now->tz_abbr) : NULL;
diff --git a/ext/date/lib/timelib.c b/ext/date/lib/timelib.c
index f926d97a3a..5179d27e27 100644
--- a/ext/date/lib/timelib.c
+++ b/ext/date/lib/timelib.c
@@ -167,8 +167,8 @@ void timelib_dump_date(timelib_time *d, int options)
if ((options & 2) == 2) {
printf("TYPE: %d ", d->zone_type);
}
- printf("TS: %lld | %04lld-%02lld-%02lld %02lld:%02lld:%02lld",
- d->sse, d->y, d->m, d->d, d->h, d->i, d->s);
+ printf("TS: %lld | %s%04lld-%02lld-%02lld %02lld:%02lld:%02lld",
+ d->sse, d->y < 0 ? "-" : "", llabs(d->y), d->m, d->d, d->h, d->i, d->s);
if (d->f > +0.0) {
printf(" %.5f", d->f);
}
diff --git a/ext/date/lib/unixtime2tm.c b/ext/date/lib/unixtime2tm.c
index 14075daed6..1d67305e70 100644
--- a/ext/date/lib/unixtime2tm.c
+++ b/ext/date/lib/unixtime2tm.c
@@ -69,9 +69,11 @@ void timelib_unixtime2gmt(timelib_time* tm, timelib_sll ts)
/* Guess why this might be for, it has to do with a pope ;-). It's also
* only valid for Great Brittain and it's colonies. It needs fixing for
* other locales. *sigh*, why is this crap so complex! */
+ /*
if (ts <= TIMELIB_LL_CONST(-6857352000)) {
tmp_days -= 11;
}
+ */
while (tmp_days <= 0) {
cur_year--;
diff --git a/ext/date/tests/bug35499.phpt b/ext/date/tests/bug35499.phpt
index 2fbcbf0bfa..03f5205daa 100644
--- a/ext/date/tests/bug35499.phpt
+++ b/ext/date/tests/bug35499.phpt
@@ -6,11 +6,73 @@ date_default_timezone_set("UTC");
echo date(DATE_ISO8601, strtotime("11/20/2005 8:00 AM \r\n")) . "\n";
echo date(DATE_ISO8601, strtotime(" 11/20/2005 8:00 AM \r\n")) . "\n";
-var_dump(strtotime(" a "));
-var_dump(strtotime(" \n "));
+var_dump(date_parse(" a "));
+var_dump(date_parse(" \n "));
?>
--EXPECT--
2005-11-20T08:00:00+0000
2005-11-20T08:00:00+0000
-bool(false)
-bool(false)
+array(16) {
+ ["year"]=>
+ bool(false)
+ ["month"]=>
+ bool(false)
+ ["day"]=>
+ bool(false)
+ ["hour"]=>
+ bool(false)
+ ["minute"]=>
+ bool(false)
+ ["second"]=>
+ bool(false)
+ ["fraction"]=>
+ bool(false)
+ ["warning_count"]=>
+ int(0)
+ ["warnings"]=>
+ array(0) {
+ }
+ ["error_count"]=>
+ int(0)
+ ["errors"]=>
+ array(0) {
+ }
+ ["is_localtime"]=>
+ bool(true)
+ ["zone_type"]=>
+ int(2)
+ ["zone"]=>
+ int(-60)
+ ["is_dst"]=>
+ bool(false)
+ ["tz_abbr"]=>
+ string(1) "A"
+}
+array(12) {
+ ["year"]=>
+ bool(false)
+ ["month"]=>
+ bool(false)
+ ["day"]=>
+ bool(false)
+ ["hour"]=>
+ bool(false)
+ ["minute"]=>
+ bool(false)
+ ["second"]=>
+ bool(false)
+ ["fraction"]=>
+ bool(false)
+ ["warning_count"]=>
+ int(0)
+ ["warnings"]=>
+ array(0) {
+ }
+ ["error_count"]=>
+ int(0)
+ ["errors"]=>
+ array(0) {
+ }
+ ["is_localtime"]=>
+ bool(false)
+}
diff --git a/ext/date/tests/bug41523.phpt b/ext/date/tests/bug41523.phpt
new file mode 100644
index 0000000000..c8aa00fd76
--- /dev/null
+++ b/ext/date/tests/bug41523.phpt
@@ -0,0 +1,45 @@
+--TEST--
+Bug #41523 (strtotime('0000-00-00 00:00:00') is parsed as 1999-11-30)
+--FILE--
+<?php
+date_default_timezone_set("UTC");
+
+var_dump( date_parse('0000-00-00 00:00:00') );
+var_dump( strtotime('0000-00-00 00:00:00') );
+var_dump( $dt = new DateTime('0000-00-00 00:00:00') );
+echo $dt->format( DateTime::ISO8601 ), "\n";
+
+?>
+--EXPECT--
+array(12) {
+ ["year"]=>
+ int(0)
+ ["month"]=>
+ int(0)
+ ["day"]=>
+ int(0)
+ ["hour"]=>
+ int(0)
+ ["minute"]=>
+ int(0)
+ ["second"]=>
+ int(0)
+ ["fraction"]=>
+ float(0)
+ ["warning_count"]=>
+ int(0)
+ ["warnings"]=>
+ array(0) {
+ }
+ ["error_count"]=>
+ int(0)
+ ["errors"]=>
+ array(0) {
+ }
+ ["is_localtime"]=>
+ bool(false)
+}
+bool(false)
+object(DateTime)#1 (0) {
+}
+-0001-11-30T00:00:00+0000
diff --git a/ext/date/tests/bug41709.phpt b/ext/date/tests/bug41709.phpt
new file mode 100644
index 0000000000..69c7cb4f47
--- /dev/null
+++ b/ext/date/tests/bug41709.phpt
@@ -0,0 +1,33 @@
+--TEST--
+Bug #41709 (strtotime() does not handle 00.00.0000)
+--FILE--
+<?php
+date_default_timezone_set("UTC");
+
+$date_string = '00.00.0000 - 00:00:00';
+print_r(date_parse($date_string));
+
+?>
+--EXPECT--
+Array
+(
+ [year] => 0
+ [month] => 0
+ [day] => 0
+ [hour] => 0
+ [minute] => 0
+ [second] => 0
+ [fraction] => 0
+ [warning_count] => 0
+ [warnings] => Array
+ (
+ )
+
+ [error_count] => 1
+ [errors] => Array
+ (
+ [11] => Unexpected character
+ )
+
+ [is_localtime] =>
+)
diff --git a/ext/date/tests/bug41842.phpt b/ext/date/tests/bug41842.phpt
new file mode 100644
index 0000000000..b2a5ef32ac
--- /dev/null
+++ b/ext/date/tests/bug41842.phpt
@@ -0,0 +1,11 @@
+--TEST--
+Bug #41842 (Cannot create years < 0100 & negative years with date_create or new DateTime)
+--FILE--
+<?php
+date_default_timezone_set("UTC");
+
+$date = new DateTime('-2007-06-28 00:00:00');
+echo $date->format(DATE_ISO8601);
+?>
+--EXPECT--
+-2007-06-28T00:00:00+0000
diff --git a/ext/date/tests/bug41844.phpt b/ext/date/tests/bug41844.phpt
new file mode 100644
index 0000000000..c18b2f7736
--- /dev/null
+++ b/ext/date/tests/bug41844.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Bug #41844 (Format returns incorrect number of digits for negative years -0001 to -0999)
+--FILE--
+<?php
+date_default_timezone_set("UTC");
+
+$date = new DateTime('2007-06-28');
+$date->modify('-3006 years');
+echo $date->format(DATE_ISO8601), "\n";
+
+$date = new DateTime('2007-06-28');
+$date->modify('-2008 years');
+echo $date->format(DATE_ISO8601), "\n";
+?>
+--EXPECT--
+-0999-06-28T00:00:00+0000
+-0001-06-28T00:00:00+0000
diff --git a/ext/date/tests/bug41964.phpt b/ext/date/tests/bug41964.phpt
new file mode 100644
index 0000000000..022a1861b4
--- /dev/null
+++ b/ext/date/tests/bug41964.phpt
@@ -0,0 +1,59 @@
+--TEST--
+Bug #41964 (strtotime returns a timestamp for non-time string of pattern '(A|a) .+')
+--FILE--
+<?php
+date_default_timezone_set("UTC");
+
+error_reporting(0);
+
+$res = date_parse('Ask the Experts');
+var_dump($res['zone'], $res['tz_abbr']);
+echo "\n";
+
+$res = date_parse('A ');
+var_dump($res['zone'], $res['tz_abbr']);
+echo "\n";
+
+$res = date_parse('A');
+var_dump($res['zone'], $res['tz_abbr']);
+echo "\n";
+
+$res = date_parse('a ');
+var_dump($res['zone'], $res['tz_abbr']);
+echo "\n";
+
+$res = date_parse('a');
+var_dump($res['zone'], $res['tz_abbr']);
+echo "\n";
+
+$res = date_parse('A Revolution in Development');
+var_dump($res['zone'], $res['tz_abbr']);
+echo "\n";
+
+$res = date_parse('a nothing');
+var_dump($res['zone'], $res['tz_abbr']);
+echo "\n";
+
+
+?>
+--EXPECT--
+NULL
+NULL
+
+int(-60)
+string(1) "A"
+
+int(-60)
+string(1) "A"
+
+int(-60)
+string(1) "A"
+
+int(-60)
+string(1) "A"
+
+int(-60)
+string(1) "A"
+
+int(-60)
+string(1) "A"