[prev in list] [next in list] [prev in thread] [next in thread] 

List:       php-cvs
Subject:    [PHP-CVS] =?utf-8?q?svn:_/php/php-src/_branches/PHP=5F5=5F3/NEWS_branches/PHP=5F5=5F3/ext/date/lib/p
From:       Derick_Rethans <derick () php ! net>
Date:       2011-11-25 15:51:37
Message-ID: svn-derick-1322236297-319829-1511347368 () svn ! php ! net
[Download RAW message or body]

derick                                   Fri, 25 Nov 2011 15:51:37 +0000

Revision: http://svn.php.net/viewvc?view=revision&revision=319829

Log:
- Fixed bug #54596 (incorrect years for DateTime objects created with 4-digit
  years).

Bug: https://bugs.php.net/54596 (Bogus) segfault when I run the PECL GEARMAN client example script
      
Changed paths:
    U   php/php-src/branches/PHP_5_3/NEWS
    U   php/php-src/branches/PHP_5_3/ext/date/lib/parse_date.c
    U   php/php-src/branches/PHP_5_3/ext/date/lib/parse_date.re
    A   php/php-src/branches/PHP_5_3/ext/date/tests/bug54597.phpt
    U   php/php-src/branches/PHP_5_4/ext/date/lib/parse_date.c
    U   php/php-src/branches/PHP_5_4/ext/date/lib/parse_date.re
    A   php/php-src/branches/PHP_5_4/ext/date/tests/bug54597.phpt
    U   php/php-src/trunk/ext/date/lib/parse_date.c
    U   php/php-src/trunk/ext/date/lib/parse_date.re
    A   php/php-src/trunk/ext/date/tests/bug54597.phpt


["svn-diffs-319829.txt" (text/x-diff)]

Modified: php/php-src/branches/PHP_5_3/NEWS
===================================================================
--- php/php-src/branches/PHP_5_3/NEWS	2011-11-25 15:47:11 UTC (rev 319828)
+++ php/php-src/branches/PHP_5_3/NEWS	2011-11-25 15:51:37 UTC (rev 319829)
@@ -33,6 +33,8 @@
     timestamp). (Derick)
   . Fixed bug #55253 (DateTime::add() and sub() result -1 hour on objects with
     time zone type 2). (Derick)
+  . Fixed bug #54596 (incorrect years for DateTime objects created with 4-digit
+    years). (Derick)

 - EXIF:
   . Fixed bug #60150 (Integer overflow during the parsing of invalid exif

Modified: php/php-src/branches/PHP_5_3/ext/date/lib/parse_date.c
===================================================================
--- php/php-src/branches/PHP_5_3/ext/date/lib/parse_date.c	2011-11-25 15:47:11 UTC \
                (rev 319828)
+++ php/php-src/branches/PHP_5_3/ext/date/lib/parse_date.c	2011-11-25 15:51:37 UTC \
(rev 319829) @@ -1,4 +1,4 @@
-/* Generated by re2c 0.13.5 on Sun Jun  5 15:26:42 2011 */
+/* Generated by re2c 0.13.5 on Fri Nov 25 16:42:41 2011 */
 #line 1 "ext/date/lib/parse_date.re"
 /*
    +----------------------------------------------------------------------+
@@ -121,8 +121,8 @@
 #define TIMELIB_DEINIT timelib_string_free(str)
 #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) == TIMELIB_UNSET) {         \
+#define TIMELIB_PROCESS_YEAR(x, l) { \
+	if (((x) == TIMELIB_UNSET) || ((l) >= 4)) { \
 	/*	(x) = 0; */          \
 	} else if ((x) < 100) {  \
 		if ((x) < 70) {      \
@@ -440,7 +440,7 @@
 	return tmp;
 }

-static timelib_sll timelib_get_nr(char **ptr, int max_length)
+static timelib_sll timelib_get_nr_ex(char **ptr, int max_length, int \
*scanned_length)  {
 	char *begin, *end, *str;
 	timelib_sll tmp_nr = TIMELIB_UNSET;
@@ -458,6 +458,9 @@
 		++len;
 	}
 	end = *ptr;
+	if (scanned_length) {
+		*scanned_length = end - begin;
+	}
 	str = calloc(1, end - begin + 1);
 	memcpy(str, begin, end - begin);
 	tmp_nr = strtoll(str, NULL, 10);
@@ -465,6 +468,11 @@
 	return tmp_nr;
 }

+static timelib_sll timelib_get_nr(char **ptr, int max_length)
+{
+	return timelib_get_nr_ex(ptr, max_length, NULL);
+}
+
 static void timelib_skip_day_suffix(char **ptr)
 {
 	if (isspace(**ptr)) {
@@ -863,11 +871,11 @@
 std:
 	s->tok = cursor;
 	s->len = 0;
-#line 989 "ext/date/lib/parse_date.re"
+#line 997 "ext/date/lib/parse_date.re"



-#line 871 "ext/date/lib/parse_date.c"
+#line 879 "ext/date/lib/parse_date.c"
 {
 	YYCTYPE yych;
 	unsigned int yyaccept = 0;
@@ -987,7 +995,7 @@
 	}
 yy2:
 	YYDEBUG(2, *YYCURSOR);
-#line 1074 "ext/date/lib/parse_date.re"
+#line 1082 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("firstdayof | lastdayof");
 		TIMELIB_INIT;
@@ -1003,7 +1011,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_LF_DAY_OF_MONTH;
 	}
-#line 1007 "ext/date/lib/parse_date.c"
+#line 1015 "ext/date/lib/parse_date.c"
 yy3:
 	YYDEBUG(3, *YYCURSOR);
 	++YYCURSOR;
@@ -1026,7 +1034,7 @@
 	}
 yy4:
 	YYDEBUG(4, *YYCURSOR);
-#line 1656 "ext/date/lib/parse_date.re"
+#line 1676 "ext/date/lib/parse_date.re"
 	{
 		int tz_not_found;
 		DEBUG_OUTPUT("tzcorrection | tz");
@@ -1039,7 +1047,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_TIMEZONE;
 	}
-#line 1043 "ext/date/lib/parse_date.c"
+#line 1051 "ext/date/lib/parse_date.c"
 yy5:
 	YYDEBUG(5, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -1350,12 +1358,12 @@
 	if (yych <= '9') goto yy1385;
 yy13:
 	YYDEBUG(13, *YYCURSOR);
-#line 1751 "ext/date/lib/parse_date.re"
+#line 1771 "ext/date/lib/parse_date.re"
 	{
 		add_error(s, "Unexpected character");
 		goto std;
 	}
-#line 1359 "ext/date/lib/parse_date.c"
+#line 1367 "ext/date/lib/parse_date.c"
 yy14:
 	YYDEBUG(14, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -2412,11 +2420,11 @@
 	if (yych <= '9') goto yy55;
 yy50:
 	YYDEBUG(50, *YYCURSOR);
-#line 1740 "ext/date/lib/parse_date.re"
+#line 1760 "ext/date/lib/parse_date.re"
 	{
 		goto std;
 	}
-#line 2420 "ext/date/lib/parse_date.c"
+#line 2428 "ext/date/lib/parse_date.c"
 yy51:
 	YYDEBUG(51, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -2425,12 +2433,12 @@
 	YYDEBUG(52, *YYCURSOR);
 	++YYCURSOR;
 	YYDEBUG(53, *YYCURSOR);
-#line 1745 "ext/date/lib/parse_date.re"
+#line 1765 "ext/date/lib/parse_date.re"
 	{
 		s->pos = cursor; s->line++;
 		goto std;
 	}
-#line 2434 "ext/date/lib/parse_date.c"
+#line 2442 "ext/date/lib/parse_date.c"
 yy54:
 	YYDEBUG(54, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -2817,7 +2825,7 @@
 	if (yych == 's') goto yy74;
 yy73:
 	YYDEBUG(73, *YYCURSOR);
-#line 1724 "ext/date/lib/parse_date.re"
+#line 1744 "ext/date/lib/parse_date.re"
 	{
 		timelib_ull i;
 		DEBUG_OUTPUT("relative");
@@ -2832,7 +2840,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_RELATIVE;
 	}
-#line 2836 "ext/date/lib/parse_date.c"
+#line 2844 "ext/date/lib/parse_date.c"
 yy74:
 	YYDEBUG(74, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -3594,7 +3602,7 @@
 	}
 yy167:
 	YYDEBUG(167, *YYCURSOR);
-#line 1587 "ext/date/lib/parse_date.re"
+#line 1607 "ext/date/lib/parse_date.re"
 	{
 		const timelib_relunit* relunit;
 		DEBUG_OUTPUT("daytext");
@@ -3611,7 +3619,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_WEEKDAY;
 	}
-#line 3615 "ext/date/lib/parse_date.c"
+#line 3623 "ext/date/lib/parse_date.c"
 yy168:
 	YYDEBUG(168, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -4131,7 +4139,7 @@
 	}
 yy194:
 	YYDEBUG(194, *YYCURSOR);
-#line 1646 "ext/date/lib/parse_date.re"
+#line 1666 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("monthtext");
 		TIMELIB_INIT;
@@ -4140,7 +4148,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_TEXT;
 	}
-#line 4144 "ext/date/lib/parse_date.c"
+#line 4152 "ext/date/lib/parse_date.c"
 yy195:
 	YYDEBUG(195, *YYCURSOR);
 	++YYCURSOR;
@@ -4191,19 +4199,20 @@
 	}
 yy199:
 	YYDEBUG(199, *YYCURSOR);
-#line 1396 "ext/date/lib/parse_date.re"
+#line 1412 "ext/date/lib/parse_date.re"
 	{
+		int length = 0;
 		DEBUG_OUTPUT("datetextual | datenoyear");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
 		s->time->m = timelib_get_month((char **) &ptr);
 		s->time->d = timelib_get_nr((char **) &ptr, 2);
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_TEXT;
 	}
-#line 4207 "ext/date/lib/parse_date.c"
+#line 4216 "ext/date/lib/parse_date.c"
 yy200:
 	YYDEBUG(200, *YYCURSOR);
 	yyaccept = 6;
@@ -4472,7 +4481,7 @@
 	}
 yy223:
 	YYDEBUG(223, *YYCURSOR);
-#line 1694 "ext/date/lib/parse_date.re"
+#line 1714 "ext/date/lib/parse_date.re"
 	{
 		int tz_not_found;
 		DEBUG_OUTPUT("dateshortwithtimeshort | dateshortwithtimelong | \
dateshortwithtimelongtz"); @@ -4501,7 +4510,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_SHORTDATE_WITH_TIME;
 	}
-#line 4505 "ext/date/lib/parse_date.c"
+#line 4514 "ext/date/lib/parse_date.c"
 yy224:
 	YYDEBUG(224, *YYCURSOR);
 	yyaccept = 7;
@@ -5199,7 +5208,7 @@
 	YYDEBUG(278, *YYCURSOR);
 	++YYCURSOR;
 	YYDEBUG(279, *YYCURSOR);
-#line 1670 "ext/date/lib/parse_date.re"
+#line 1690 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("dateshortwithtimeshort12 | dateshortwithtimelong12");
 		TIMELIB_INIT;
@@ -5222,7 +5231,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_SHORTDATE_WITH_TIME;
 	}
-#line 5226 "ext/date/lib/parse_date.c"
+#line 5235 "ext/date/lib/parse_date.c"
 yy280:
 	YYDEBUG(280, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -5400,19 +5409,20 @@
 	++YYCURSOR;
 yy295:
 	YYDEBUG(295, *YYCURSOR);
-#line 1370 "ext/date/lib/parse_date.re"
+#line 1384 "ext/date/lib/parse_date.re"
 	{
+		int length = 0;
 		DEBUG_OUTPUT("datenoday");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
 		s->time->m = timelib_get_month((char **) &ptr);
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		s->time->d = 1;
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_NO_DAY;
 	}
-#line 5416 "ext/date/lib/parse_date.c"
+#line 5426 "ext/date/lib/parse_date.c"
 yy296:
 	YYDEBUG(296, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -6632,19 +6642,20 @@
 	if (yych <= '9') goto yy365;
 yy364:
 	YYDEBUG(364, *YYCURSOR);
-#line 1510 "ext/date/lib/parse_date.re"
+#line 1528 "ext/date/lib/parse_date.re"
 	{
+		int length = 0;
 		DEBUG_OUTPUT("pgtextshort");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
 		s->time->m = timelib_get_month((char **) &ptr);
 		s->time->d = timelib_get_nr((char **) &ptr, 2);
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_PG_TEXT;
 	}
-#line 6648 "ext/date/lib/parse_date.c"
+#line 6659 "ext/date/lib/parse_date.c"
 yy365:
 	YYDEBUG(365, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -7282,7 +7293,7 @@
 	}
 yy393:
 	YYDEBUG(393, *YYCURSOR);
-#line 1566 "ext/date/lib/parse_date.re"
+#line 1586 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("ago");
 		TIMELIB_INIT;
@@ -7302,7 +7313,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_AGO;
 	}
-#line 7306 "ext/date/lib/parse_date.c"
+#line 7317 "ext/date/lib/parse_date.c"
 yy394:
 	YYDEBUG(394, *YYCURSOR);
 	yyaccept = 5;
@@ -9052,7 +9063,7 @@
 	++YYCURSOR;
 yy455:
 	YYDEBUG(455, *YYCURSOR);
-#line 1280 "ext/date/lib/parse_date.re"
+#line 1289 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("iso8601date4 | iso8601date2 | iso8601dateslash | dateslash");
 		TIMELIB_INIT;
@@ -9063,7 +9074,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_ISO_DATE;
 	}
-#line 9067 "ext/date/lib/parse_date.c"
+#line 9078 "ext/date/lib/parse_date.c"
 yy456:
 	YYDEBUG(456, *YYCURSOR);
 	yyaccept = 0;
@@ -9623,7 +9634,7 @@
 	}
 yy476:
 	YYDEBUG(476, *YYCURSOR);
-#line 1409 "ext/date/lib/parse_date.re"
+#line 1426 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("datenoyearrev");
 		TIMELIB_INIT;
@@ -9634,7 +9645,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_TEXT;
 	}
-#line 9638 "ext/date/lib/parse_date.c"
+#line 9649 "ext/date/lib/parse_date.c"
 yy477:
 	YYDEBUG(477, *YYCURSOR);
 	yyaccept = 10;
@@ -9775,7 +9786,7 @@
 	YYDEBUG(488, *YYCURSOR);
 	++YYCURSOR;
 	YYDEBUG(489, *YYCURSOR);
-#line 1136 "ext/date/lib/parse_date.re"
+#line 1144 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("timetiny12 | timeshort12 | timelong12");
 		TIMELIB_INIT;
@@ -9791,7 +9802,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_TIME12;
 	}
-#line 9795 "ext/date/lib/parse_date.c"
+#line 9806 "ext/date/lib/parse_date.c"
 yy490:
 	YYDEBUG(490, *YYCURSOR);
 	yyaccept = 11;
@@ -9804,7 +9815,7 @@
 	}
 yy491:
 	YYDEBUG(491, *YYCURSOR);
-#line 1173 "ext/date/lib/parse_date.re"
+#line 1181 "ext/date/lib/parse_date.re"
 	{
 		int tz_not_found;
 		DEBUG_OUTPUT("timeshort24 | timelong24 | iso8601long");
@@ -9829,7 +9840,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_TIME24_WITH_ZONE;
 	}
-#line 9833 "ext/date/lib/parse_date.c"
+#line 9844 "ext/date/lib/parse_date.c"
 yy492:
 	YYDEBUG(492, *YYCURSOR);
 	yyaccept = 11;
@@ -10139,7 +10150,7 @@
 	YYDEBUG(523, *YYCURSOR);
 	++YYCURSOR;
 	YYDEBUG(524, *YYCURSOR);
-#line 1153 "ext/date/lib/parse_date.re"
+#line 1161 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("mssqltime");
 		TIMELIB_INIT;
@@ -10158,7 +10169,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_TIME24_WITH_ZONE;
 	}
-#line 10162 "ext/date/lib/parse_date.c"
+#line 10173 "ext/date/lib/parse_date.c"
 yy525:
 	YYDEBUG(525, *YYCURSOR);
 	yyaccept = 11;
@@ -10264,20 +10275,21 @@
 	if (yych <= '9') goto yy541;
 yy535:
 	YYDEBUG(535, *YYCURSOR);
-#line 1331 "ext/date/lib/parse_date.re"
+#line 1343 "ext/date/lib/parse_date.re"
 	{
+		int length = 0;
 		DEBUG_OUTPUT("datefull");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
 		s->time->d = timelib_get_nr((char **) &ptr, 2);
 		timelib_skip_day_suffix((char **) &ptr);
 		s->time->m = timelib_get_month((char **) &ptr);
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_FULL;
 	}
-#line 10281 "ext/date/lib/parse_date.c"
+#line 10293 "ext/date/lib/parse_date.c"
 yy536:
 	YYDEBUG(536, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -11014,7 +11026,7 @@
 	YYDEBUG(606, *YYCURSOR);
 	++YYCURSOR;
 	YYDEBUG(607, *YYCURSOR);
-#line 1345 "ext/date/lib/parse_date.re"
+#line 1358 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("pointed date YYYY");
 		TIMELIB_INIT;
@@ -11025,7 +11037,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_FULL_POINTED;
 	}
-#line 11029 "ext/date/lib/parse_date.c"
+#line 11041 "ext/date/lib/parse_date.c"
 yy608:
 	YYDEBUG(608, *YYCURSOR);
 	yyaccept = 11;
@@ -11061,19 +11073,20 @@
 	if (yych <= '9') goto yy605;
 yy612:
 	YYDEBUG(612, *YYCURSOR);
-#line 1357 "ext/date/lib/parse_date.re"
+#line 1370 "ext/date/lib/parse_date.re"
 	{
+		int length = 0;
 		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);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 2, &length);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_FULL_POINTED;
 	}
-#line 11077 "ext/date/lib/parse_date.c"
+#line 11090 "ext/date/lib/parse_date.c"
 yy613:
 	YYDEBUG(613, *YYCURSOR);
 	yyaccept = 11;
@@ -11714,19 +11727,20 @@
 	}
 yy657:
 	YYDEBUG(657, *YYCURSOR);
-#line 1318 "ext/date/lib/parse_date.re"
+#line 1329 "ext/date/lib/parse_date.re"
 	{
+		int length = 0;
 		DEBUG_OUTPUT("gnudateshort");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		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_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_ISO_DATE;
 	}
-#line 11730 "ext/date/lib/parse_date.c"
+#line 11744 "ext/date/lib/parse_date.c"
 yy658:
 	YYDEBUG(658, *YYCURSOR);
 	yyaccept = 13;
@@ -11832,21 +11846,22 @@
 	}
 yy667:
 	YYDEBUG(667, *YYCURSOR);
-#line 1265 "ext/date/lib/parse_date.re"
+#line 1273 "ext/date/lib/parse_date.re"
 	{
+		int length = 0;
 		DEBUG_OUTPUT("americanshort | american");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
 		s->time->m = timelib_get_nr((char **) &ptr, 2);
 		s->time->d = timelib_get_nr((char **) &ptr, 2);
 		if (*ptr == '/') {
-			s->time->y = timelib_get_nr((char **) &ptr, 4);
-			TIMELIB_PROCESS_YEAR(s->time->y);
+			s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
+			TIMELIB_PROCESS_YEAR(s->time->y, length);
 		}
 		TIMELIB_DEINIT;
 		return TIMELIB_AMERICAN;
 	}
-#line 11850 "ext/date/lib/parse_date.c"
+#line 11865 "ext/date/lib/parse_date.c"
 yy668:
 	YYDEBUG(668, *YYCURSOR);
 	yyaccept = 14;
@@ -12079,7 +12094,7 @@
 	if (yych <= ':') goto yy704;
 yy701:
 	YYDEBUG(701, *YYCURSOR);
-#line 1536 "ext/date/lib/parse_date.re"
+#line 1556 "ext/date/lib/parse_date.re"
 	{
 		int tz_not_found;
 		DEBUG_OUTPUT("clf");
@@ -12099,7 +12114,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_CLF;
 	}
-#line 12103 "ext/date/lib/parse_date.c"
+#line 12118 "ext/date/lib/parse_date.c"
 yy702:
 	YYDEBUG(702, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -12651,19 +12666,20 @@
 	}
 yy764:
 	YYDEBUG(764, *YYCURSOR);
-#line 1292 "ext/date/lib/parse_date.re"
+#line 1301 "ext/date/lib/parse_date.re"
 	{
+		int length = 0;
 		DEBUG_OUTPUT("iso8601date2");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		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_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_ISO_DATE;
 	}
-#line 12667 "ext/date/lib/parse_date.c"
+#line 12683 "ext/date/lib/parse_date.c"
 yy765:
 	YYDEBUG(765, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -12702,19 +12718,20 @@
 	YYDEBUG(771, *YYCURSOR);
 	++YYCURSOR;
 	YYDEBUG(772, *YYCURSOR);
-#line 1523 "ext/date/lib/parse_date.re"
+#line 1542 "ext/date/lib/parse_date.re"
 	{
+		int length = 0;
 		DEBUG_OUTPUT("pgtextreverse");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		s->time->m = timelib_get_month((char **) &ptr);
 		s->time->d = timelib_get_nr((char **) &ptr, 2);
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_PG_TEXT;
 	}
-#line 12718 "ext/date/lib/parse_date.c"
+#line 12735 "ext/date/lib/parse_date.c"
 yy773:
 	YYDEBUG(773, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -12852,7 +12869,7 @@
 	}
 yy784:
 	YYDEBUG(784, *YYCURSOR);
-#line 1557 "ext/date/lib/parse_date.re"
+#line 1577 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("year4");
 		TIMELIB_INIT;
@@ -12860,7 +12877,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_CLF;
 	}
-#line 12864 "ext/date/lib/parse_date.c"
+#line 12881 "ext/date/lib/parse_date.c"
 yy785:
 	YYDEBUG(785, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -13011,19 +13028,20 @@
 	}
 yy794:
 	YYDEBUG(794, *YYCURSOR);
-#line 1383 "ext/date/lib/parse_date.re"
+#line 1398 "ext/date/lib/parse_date.re"
 	{
+		int length = 0;
 		DEBUG_OUTPUT("datenodayrev");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		s->time->m = timelib_get_month((char **) &ptr);
 		s->time->d = 1;
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_NO_DAY;
 	}
-#line 13027 "ext/date/lib/parse_date.c"
+#line 13045 "ext/date/lib/parse_date.c"
 yy795:
 	YYDEBUG(795, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -13238,7 +13256,7 @@
 	if (yych <= '7') goto yy817;
 yy815:
 	YYDEBUG(815, *YYCURSOR);
-#line 1491 "ext/date/lib/parse_date.re"
+#line 1509 "ext/date/lib/parse_date.re"
 	{
 		timelib_sll w, d;
 		DEBUG_OUTPUT("isoweek");
@@ -13256,7 +13274,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_ISO_WEEK;
 	}
-#line 13260 "ext/date/lib/parse_date.c"
+#line 13278 "ext/date/lib/parse_date.c"
 yy816:
 	YYDEBUG(816, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -13266,7 +13284,7 @@
 	YYDEBUG(817, *YYCURSOR);
 	++YYCURSOR;
 	YYDEBUG(818, *YYCURSOR);
-#line 1472 "ext/date/lib/parse_date.re"
+#line 1490 "ext/date/lib/parse_date.re"
 	{
 		timelib_sll w, d;
 		DEBUG_OUTPUT("isoweekday");
@@ -13284,7 +13302,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_ISO_WEEK;
 	}
-#line 13288 "ext/date/lib/parse_date.c"
+#line 13306 "ext/date/lib/parse_date.c"
 yy819:
 	YYDEBUG(819, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -13348,19 +13366,20 @@
 	}
 yy822:
 	YYDEBUG(822, *YYCURSOR);
-#line 1459 "ext/date/lib/parse_date.re"
+#line 1476 "ext/date/lib/parse_date.re"
 	{
+		int length = 0;
 		DEBUG_OUTPUT("pgydotd");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		s->time->d = timelib_get_nr((char **) &ptr, 3);
 		s->time->m = 1;
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_PG_YEARDAY;
 	}
-#line 13364 "ext/date/lib/parse_date.c"
+#line 13383 "ext/date/lib/parse_date.c"
 yy823:
 	YYDEBUG(823, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -13463,7 +13482,7 @@
 	++YYCURSOR;
 yy843:
 	YYDEBUG(843, *YYCURSOR);
-#line 1433 "ext/date/lib/parse_date.re"
+#line 1450 "ext/date/lib/parse_date.re"
 	{
 		int tz_not_found;
 		DEBUG_OUTPUT("xmlrpc | xmlrpcnocolon | soap | wddx | exif");
@@ -13488,7 +13507,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_XMLRPC_SOAP;
 	}
-#line 13492 "ext/date/lib/parse_date.c"
+#line 13511 "ext/date/lib/parse_date.c"
 yy844:
 	YYDEBUG(844, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -13750,7 +13769,7 @@
 	}
 yy849:
 	YYDEBUG(849, *YYCURSOR);
-#line 1421 "ext/date/lib/parse_date.re"
+#line 1438 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("datenocolon");
 		TIMELIB_INIT;
@@ -13761,7 +13780,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_NOCOLON;
 	}
-#line 13765 "ext/date/lib/parse_date.c"
+#line 13784 "ext/date/lib/parse_date.c"
 yy850:
 	YYDEBUG(850, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -14681,19 +14700,20 @@
 	if (yych <= '9') goto yy996;
 yy974:
 	YYDEBUG(974, *YYCURSOR);
-#line 1305 "ext/date/lib/parse_date.re"
+#line 1315 "ext/date/lib/parse_date.re"
 	{
+		int length = 0;
 		DEBUG_OUTPUT("gnudateshorter");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		s->time->m = timelib_get_nr((char **) &ptr, 2);
 		s->time->d = 1;
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_ISO_DATE;
 	}
-#line 14697 "ext/date/lib/parse_date.c"
+#line 14717 "ext/date/lib/parse_date.c"
 yy975:
 	YYDEBUG(975, *YYCURSOR);
 	yyaccept = 22;
@@ -15702,7 +15722,7 @@
 	}
 yy1068:
 	YYDEBUG(1068, *YYCURSOR);
-#line 1199 "ext/date/lib/parse_date.re"
+#line 1207 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("gnunocolon");
 		TIMELIB_INIT;
@@ -15724,7 +15744,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_GNU_NOCOLON;
 	}
-#line 15728 "ext/date/lib/parse_date.c"
+#line 15748 "ext/date/lib/parse_date.c"
 yy1069:
 	YYDEBUG(1069, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -15816,7 +15836,7 @@
 	}
 yy1076:
 	YYDEBUG(1076, *YYCURSOR);
-#line 1245 "ext/date/lib/parse_date.re"
+#line 1253 "ext/date/lib/parse_date.re"
 	{
 		int tz_not_found;
 		DEBUG_OUTPUT("iso8601nocolon");
@@ -15835,7 +15855,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_ISO_NOCOLON;
 	}
-#line 15839 "ext/date/lib/parse_date.c"
+#line 15859 "ext/date/lib/parse_date.c"
 yy1077:
 	YYDEBUG(1077, *YYCURSOR);
 	yyaccept = 25;
@@ -16733,7 +16753,7 @@
 	}
 yy1118:
 	YYDEBUG(1118, *YYCURSOR);
-#line 1629 "ext/date/lib/parse_date.re"
+#line 1649 "ext/date/lib/parse_date.re"
 	{
 		timelib_sll i;
 		int         behavior = 0;
@@ -16749,7 +16769,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_RELATIVE;
 	}
-#line 16753 "ext/date/lib/parse_date.c"
+#line 16773 "ext/date/lib/parse_date.c"
 yy1119:
 	YYDEBUG(1119, *YYCURSOR);
 	++YYCURSOR;
@@ -16800,7 +16820,7 @@
 	YYDEBUG(1126, *YYCURSOR);
 	++YYCURSOR;
 	YYDEBUG(1127, *YYCURSOR);
-#line 1114 "ext/date/lib/parse_date.re"
+#line 1122 "ext/date/lib/parse_date.re"
 	{
 		timelib_sll i;
 		int         behavior = 0;
@@ -16821,7 +16841,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_WEEK_DAY_OF_MONTH;
 	}
-#line 16825 "ext/date/lib/parse_date.c"
+#line 16845 "ext/date/lib/parse_date.c"
 yy1128:
 	YYDEBUG(1128, *YYCURSOR);
 	yyaccept = 26;
@@ -16929,7 +16949,7 @@
 	}
 yy1142:
 	YYDEBUG(1142, *YYCURSOR);
-#line 1605 "ext/date/lib/parse_date.re"
+#line 1625 "ext/date/lib/parse_date.re"
 	{
 		timelib_sll i;
 		int         behavior = 0;
@@ -16952,7 +16972,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_RELATIVE;
 	}
-#line 16956 "ext/date/lib/parse_date.c"
+#line 16976 "ext/date/lib/parse_date.c"
 yy1143:
 	YYDEBUG(1143, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -19629,7 +19649,7 @@
 	goto yy1298;
 yy1295:
 	YYDEBUG(1295, *YYCURSOR);
-#line 1091 "ext/date/lib/parse_date.re"
+#line 1099 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("backof | frontof");
 		TIMELIB_INIT;
@@ -19651,7 +19671,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_LF_DAY_OF_MONTH;
 	}
-#line 19655 "ext/date/lib/parse_date.c"
+#line 19675 "ext/date/lib/parse_date.c"
 yy1296:
 	YYDEBUG(1296, *YYCURSOR);
 	yyaccept = 28;
@@ -21342,7 +21362,7 @@
 	if (yych <= '9') goto yy1385;
 yy1387:
 	YYDEBUG(1387, *YYCURSOR);
-#line 1049 "ext/date/lib/parse_date.re"
+#line 1057 "ext/date/lib/parse_date.re"
 	{
 		timelib_ull i;

@@ -21366,7 +21386,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_RELATIVE;
 	}
-#line 21370 "ext/date/lib/parse_date.c"
+#line 21390 "ext/date/lib/parse_date.c"
 yy1388:
 	YYDEBUG(1388, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -21802,7 +21822,7 @@
 	++YYCURSOR;
 yy1417:
 	YYDEBUG(1417, *YYCURSOR);
-#line 1037 "ext/date/lib/parse_date.re"
+#line 1045 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("tomorrow");
 		TIMELIB_INIT;
@@ -21813,7 +21833,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_RELATIVE;
 	}
-#line 21817 "ext/date/lib/parse_date.c"
+#line 21837 "ext/date/lib/parse_date.c"
 yy1418:
 	YYDEBUG(1418, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -21848,7 +21868,7 @@
 	}
 yy1420:
 	YYDEBUG(1420, *YYCURSOR);
-#line 1027 "ext/date/lib/parse_date.re"
+#line 1035 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("midnight | today");
 		TIMELIB_INIT;
@@ -21857,7 +21877,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_RELATIVE;
 	}
-#line 21861 "ext/date/lib/parse_date.c"
+#line 21881 "ext/date/lib/parse_date.c"
 yy1421:
 	YYDEBUG(1421, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -23869,7 +23889,7 @@
 	}
 yy1500:
 	YYDEBUG(1500, *YYCURSOR);
-#line 1006 "ext/date/lib/parse_date.re"
+#line 1014 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("now");
 		TIMELIB_INIT;
@@ -23877,7 +23897,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_RELATIVE;
 	}
-#line 23881 "ext/date/lib/parse_date.c"
+#line 23901 "ext/date/lib/parse_date.c"
 yy1501:
 	YYDEBUG(1501, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -24016,7 +24036,7 @@
 	}
 yy1508:
 	YYDEBUG(1508, *YYCURSOR);
-#line 1015 "ext/date/lib/parse_date.re"
+#line 1023 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("noon");
 		TIMELIB_INIT;
@@ -24027,7 +24047,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_RELATIVE;
 	}
-#line 24031 "ext/date/lib/parse_date.c"
+#line 24051 "ext/date/lib/parse_date.c"
 yy1509:
 	YYDEBUG(1509, *YYCURSOR);
 	yyaccept = 0;
@@ -24560,7 +24580,7 @@
 	++YYCURSOR;
 yy1531:
 	YYDEBUG(1531, *YYCURSOR);
-#line 994 "ext/date/lib/parse_date.re"
+#line 1002 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("yesterday");
 		TIMELIB_INIT;
@@ -24571,7 +24591,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_RELATIVE;
 	}
-#line 24575 "ext/date/lib/parse_date.c"
+#line 24595 "ext/date/lib/parse_date.c"
 yy1532:
 	YYDEBUG(1532, *YYCURSOR);
 	yyaccept = 0;
@@ -24744,7 +24764,7 @@
 		goto yy1531;
 	}
 }
-#line 1755 "ext/date/lib/parse_date.re"
+#line 1775 "ext/date/lib/parse_date.re"

 }

@@ -24868,6 +24888,7 @@
 	timelib_sll tmp;
 	Scanner in;
 	Scanner *s = &in;
+	int allow_extra = 0;

 	memset(&in, 0, sizeof(in));
 	in.errors = malloc(sizeof(struct timelib_error_container));
@@ -24937,11 +24958,14 @@
 				}
 				break;
 			case 'y': /* two digit year */
-				TIMELIB_CHECK_NUMBER;
-				if ((s->time->y = timelib_get_nr((char **) &ptr, 2)) == TIMELIB_UNSET) {
-					add_pbf_error(s, "A two digit year could not be found", string, begin);
+				{
+					int length = 0;
+					TIMELIB_CHECK_NUMBER;
+					if ((s->time->y = timelib_get_nr_ex((char **) &ptr, 2, &length)) == \
TIMELIB_UNSET) { +						add_pbf_error(s, "A two digit year could not be found", \
string, begin); +					}
+					TIMELIB_PROCESS_YEAR(s->time->y, length);
 				}
-				TIMELIB_PROCESS_YEAR(s->time->y);
 				break;
 			case 'Y': /* four digit year */
 				TIMELIB_CHECK_NUMBER;
@@ -25081,6 +25105,10 @@
 				timelib_eat_until_separator((char **) &ptr);
 				break;

+			case '+': /* allow extra chars in the format */
+				allow_extra = 1;
+				break;
+
 			default:
 				if (*fptr != *ptr) {
 					add_pbf_error(s, "The format separator does not match", string, begin);
@@ -25090,11 +25118,20 @@
 		fptr++;
 	}
 	if (*ptr) {
-		add_pbf_error(s, "Trailing data", string, ptr);
+		if (allow_extra) {
+			add_pbf_warning(s, "Trailing data", string, ptr);
+		} else {
+			add_pbf_error(s, "Trailing data", string, ptr);
+		}
 	}
+	/* ignore trailing +'s */
+	while (*fptr == '+') {
+		fptr++;
+	}
 	if (*fptr) {
 		/* Trailing | and ! specifiers are valid. */
-		while (*fptr) {
+		int done = 0;
+		while (*fptr && !done) {
 			switch (*fptr++) {
 				case '!': /* reset all fields to default */
 					timelib_time_reset_fields(s->time);
@@ -25106,6 +25143,7 @@

 				default:
 					add_pbf_error(s, "Data missing", string, ptr);
+					done = 1;
 			}
 		}
 	}

Modified: php/php-src/branches/PHP_5_3/ext/date/lib/parse_date.re
===================================================================
--- php/php-src/branches/PHP_5_3/ext/date/lib/parse_date.re	2011-11-25 15:47:11 UTC \
                (rev 319828)
+++ php/php-src/branches/PHP_5_3/ext/date/lib/parse_date.re	2011-11-25 15:51:37 UTC \
(rev 319829) @@ -119,8 +119,8 @@
 #define TIMELIB_DEINIT timelib_string_free(str)
 #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) == TIMELIB_UNSET) {         \
+#define TIMELIB_PROCESS_YEAR(x, l) { \
+	if (((x) == TIMELIB_UNSET) || ((l) >= 4)) { \
 	/*	(x) = 0; */          \
 	} else if ((x) < 100) {  \
 		if ((x) < 70) {      \
@@ -438,7 +438,7 @@
 	return tmp;
 }

-static timelib_sll timelib_get_nr(char **ptr, int max_length)
+static timelib_sll timelib_get_nr_ex(char **ptr, int max_length, int \
*scanned_length)  {
 	char *begin, *end, *str;
 	timelib_sll tmp_nr = TIMELIB_UNSET;
@@ -456,6 +456,9 @@
 		++len;
 	}
 	end = *ptr;
+	if (scanned_length) {
+		*scanned_length = end - begin;
+	}
 	str = calloc(1, end - begin + 1);
 	memcpy(str, begin, end - begin);
 	tmp_nr = strtoll(str, NULL, 10);
@@ -463,6 +466,11 @@
 	return tmp_nr;
 }

+static timelib_sll timelib_get_nr(char **ptr, int max_length)
+{
+	return timelib_get_nr_ex(ptr, max_length, NULL);
+}
+
 static void timelib_skip_day_suffix(char **ptr)
 {
 	if (isspace(**ptr)) {
@@ -1263,14 +1271,15 @@

 	americanshort | american
 	{
+		int length = 0;
 		DEBUG_OUTPUT("americanshort | american");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
 		s->time->m = timelib_get_nr((char **) &ptr, 2);
 		s->time->d = timelib_get_nr((char **) &ptr, 2);
 		if (*ptr == '/') {
-			s->time->y = timelib_get_nr((char **) &ptr, 4);
-			TIMELIB_PROCESS_YEAR(s->time->y);
+			s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
+			TIMELIB_PROCESS_YEAR(s->time->y, length);
 		}
 		TIMELIB_DEINIT;
 		return TIMELIB_AMERICAN;
@@ -1290,53 +1299,57 @@

 	iso8601date2
 	{
+		int length = 0;
 		DEBUG_OUTPUT("iso8601date2");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		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_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_ISO_DATE;
 	}

 	gnudateshorter
 	{
+		int length = 0;
 		DEBUG_OUTPUT("gnudateshorter");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		s->time->m = timelib_get_nr((char **) &ptr, 2);
 		s->time->d = 1;
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_ISO_DATE;
 	}

 	gnudateshort
 	{
+		int length = 0;
 		DEBUG_OUTPUT("gnudateshort");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		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_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_ISO_DATE;
 	}

 	datefull
 	{
+		int length = 0;
 		DEBUG_OUTPUT("datefull");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
 		s->time->d = timelib_get_nr((char **) &ptr, 2);
 		timelib_skip_day_suffix((char **) &ptr);
 		s->time->m = timelib_get_month((char **) &ptr);
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_FULL;
 	}
@@ -1355,52 +1368,56 @@

 	pointeddate2
 	{
+		int length = 0;
 		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);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 2, &length);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_FULL_POINTED;
 	}

 	datenoday
 	{
+		int length = 0;
 		DEBUG_OUTPUT("datenoday");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
 		s->time->m = timelib_get_month((char **) &ptr);
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		s->time->d = 1;
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_NO_DAY;
 	}

 	datenodayrev
 	{
+		int length = 0;
 		DEBUG_OUTPUT("datenodayrev");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		s->time->m = timelib_get_month((char **) &ptr);
 		s->time->d = 1;
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_NO_DAY;
 	}

 	datetextual | datenoyear
 	{
+		int length = 0;
 		DEBUG_OUTPUT("datetextual | datenoyear");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
 		s->time->m = timelib_get_month((char **) &ptr);
 		s->time->d = timelib_get_nr((char **) &ptr, 2);
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_TEXT;
 	}
@@ -1457,13 +1474,14 @@

 	pgydotd
 	{
+		int length = 0;
 		DEBUG_OUTPUT("pgydotd");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		s->time->d = timelib_get_nr((char **) &ptr, 3);
 		s->time->m = 1;
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_PG_YEARDAY;
 	}
@@ -1508,26 +1526,28 @@

 	pgtextshort
 	{
+		int length = 0;
 		DEBUG_OUTPUT("pgtextshort");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
 		s->time->m = timelib_get_month((char **) &ptr);
 		s->time->d = timelib_get_nr((char **) &ptr, 2);
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_PG_TEXT;
 	}

 	pgtextreverse
 	{
+		int length = 0;
 		DEBUG_OUTPUT("pgtextreverse");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		s->time->m = timelib_get_month((char **) &ptr);
 		s->time->d = timelib_get_nr((char **) &ptr, 2);
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_PG_TEXT;
 	}
@@ -1875,6 +1895,7 @@
 	timelib_sll tmp;
 	Scanner in;
 	Scanner *s = &in;
+	int allow_extra = 0;

 	memset(&in, 0, sizeof(in));
 	in.errors = malloc(sizeof(struct timelib_error_container));
@@ -1944,11 +1965,14 @@
 				}
 				break;
 			case 'y': /* two digit year */
-				TIMELIB_CHECK_NUMBER;
-				if ((s->time->y = timelib_get_nr((char **) &ptr, 2)) == TIMELIB_UNSET) {
-					add_pbf_error(s, "A two digit year could not be found", string, begin);
+				{
+					int length = 0;
+					TIMELIB_CHECK_NUMBER;
+					if ((s->time->y = timelib_get_nr_ex((char **) &ptr, 2, &length)) == \
TIMELIB_UNSET) { +						add_pbf_error(s, "A two digit year could not be found", \
string, begin); +					}
+					TIMELIB_PROCESS_YEAR(s->time->y, length);
 				}
-				TIMELIB_PROCESS_YEAR(s->time->y);
 				break;
 			case 'Y': /* four digit year */
 				TIMELIB_CHECK_NUMBER;
@@ -2088,6 +2112,10 @@
 				timelib_eat_until_separator((char **) &ptr);
 				break;

+			case '+': /* allow extra chars in the format */
+				allow_extra = 1;
+				break;
+
 			default:
 				if (*fptr != *ptr) {
 					add_pbf_error(s, "The format separator does not match", string, begin);
@@ -2097,11 +2125,20 @@
 		fptr++;
 	}
 	if (*ptr) {
-		add_pbf_error(s, "Trailing data", string, ptr);
+		if (allow_extra) {
+			add_pbf_warning(s, "Trailing data", string, ptr);
+		} else {
+			add_pbf_error(s, "Trailing data", string, ptr);
+		}
 	}
+	/* ignore trailing +'s */
+	while (*fptr == '+') {
+		fptr++;
+	}
 	if (*fptr) {
 		/* Trailing | and ! specifiers are valid. */
-		while (*fptr) {
+		int done = 0;
+		while (*fptr && !done) {
 			switch (*fptr++) {
 				case '!': /* reset all fields to default */
 					timelib_time_reset_fields(s->time);
@@ -2113,6 +2150,7 @@

 				default:
 					add_pbf_error(s, "Data missing", string, ptr);
+					done = 1;
 			}
 		}
 	}

Added: php/php-src/branches/PHP_5_3/ext/date/tests/bug54597.phpt
===================================================================
--- php/php-src/branches/PHP_5_3/ext/date/tests/bug54597.phpt	                        \
                (rev 0)
+++ php/php-src/branches/PHP_5_3/ext/date/tests/bug54597.phpt	2011-11-25 15:51:37 UTC \
(rev 319829) @@ -0,0 +1,18 @@
+--TEST--
+Bug #54597: incorrect years for DateTime objects created with 4-digit years
+--INI--
+date.timezone=Europe/London
+--FILE--
+<?php
+$tz = new DateTimeZone("Europe/Amsterdam");
+$dateObject = new DateTime( 'January 0099', $tz );
+echo $dateObject->format( 'Y' ), "\n";
+$dateObject = new DateTime( 'January 1, 0099', $tz );
+echo $dateObject->format( 'Y' ), "\n";
+$dateObject = new DateTime( '0099-01', $tz );
+echo $dateObject->format( 'Y' ), "\n";
+?>
+--EXPECT--
+0099
+0099
+0099

Modified: php/php-src/branches/PHP_5_4/ext/date/lib/parse_date.c
===================================================================
--- php/php-src/branches/PHP_5_4/ext/date/lib/parse_date.c	2011-11-25 15:47:11 UTC \
                (rev 319828)
+++ php/php-src/branches/PHP_5_4/ext/date/lib/parse_date.c	2011-11-25 15:51:37 UTC \
(rev 319829) @@ -1,4 +1,4 @@
-/* Generated by re2c 0.13.5 on Thu Jun 23 10:56:31 2011 */
+/* Generated by re2c 0.13.5 on Fri Nov 25 16:42:37 2011 */
 #line 1 "ext/date/lib/parse_date.re"
 /*
    +----------------------------------------------------------------------+
@@ -121,8 +121,8 @@
 #define TIMELIB_DEINIT timelib_string_free(str)
 #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) == TIMELIB_UNSET) {         \
+#define TIMELIB_PROCESS_YEAR(x, l) { \
+	if (((x) == TIMELIB_UNSET) || ((l) >= 4)) { \
 	/*	(x) = 0; */          \
 	} else if ((x) < 100) {  \
 		if ((x) < 70) {      \
@@ -440,7 +440,7 @@
 	return tmp;
 }

-static timelib_sll timelib_get_nr(char **ptr, int max_length)
+static timelib_sll timelib_get_nr_ex(char **ptr, int max_length, int \
*scanned_length)  {
 	char *begin, *end, *str;
 	timelib_sll tmp_nr = TIMELIB_UNSET;
@@ -458,6 +458,9 @@
 		++len;
 	}
 	end = *ptr;
+	if (scanned_length) {
+		*scanned_length = end - begin;
+	}
 	str = calloc(1, end - begin + 1);
 	memcpy(str, begin, end - begin);
 	tmp_nr = strtoll(str, NULL, 10);
@@ -465,6 +468,11 @@
 	return tmp_nr;
 }

+static timelib_sll timelib_get_nr(char **ptr, int max_length)
+{
+	return timelib_get_nr_ex(ptr, max_length, NULL);
+}
+
 static void timelib_skip_day_suffix(char **ptr)
 {
 	if (isspace(**ptr)) {
@@ -863,11 +871,11 @@
 std:
 	s->tok = cursor;
 	s->len = 0;
-#line 989 "ext/date/lib/parse_date.re"
+#line 997 "ext/date/lib/parse_date.re"



-#line 871 "ext/date/lib/parse_date.c"
+#line 879 "ext/date/lib/parse_date.c"
 {
 	YYCTYPE yych;
 	unsigned int yyaccept = 0;
@@ -987,7 +995,7 @@
 	}
 yy2:
 	YYDEBUG(2, *YYCURSOR);
-#line 1074 "ext/date/lib/parse_date.re"
+#line 1082 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("firstdayof | lastdayof");
 		TIMELIB_INIT;
@@ -1003,7 +1011,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_LF_DAY_OF_MONTH;
 	}
-#line 1007 "ext/date/lib/parse_date.c"
+#line 1015 "ext/date/lib/parse_date.c"
 yy3:
 	YYDEBUG(3, *YYCURSOR);
 	++YYCURSOR;
@@ -1026,7 +1034,7 @@
 	}
 yy4:
 	YYDEBUG(4, *YYCURSOR);
-#line 1656 "ext/date/lib/parse_date.re"
+#line 1676 "ext/date/lib/parse_date.re"
 	{
 		int tz_not_found;
 		DEBUG_OUTPUT("tzcorrection | tz");
@@ -1039,7 +1047,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_TIMEZONE;
 	}
-#line 1043 "ext/date/lib/parse_date.c"
+#line 1051 "ext/date/lib/parse_date.c"
 yy5:
 	YYDEBUG(5, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -1350,12 +1358,12 @@
 	if (yych <= '9') goto yy1385;
 yy13:
 	YYDEBUG(13, *YYCURSOR);
-#line 1751 "ext/date/lib/parse_date.re"
+#line 1771 "ext/date/lib/parse_date.re"
 	{
 		add_error(s, "Unexpected character");
 		goto std;
 	}
-#line 1359 "ext/date/lib/parse_date.c"
+#line 1367 "ext/date/lib/parse_date.c"
 yy14:
 	YYDEBUG(14, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -2412,11 +2420,11 @@
 	if (yych <= '9') goto yy55;
 yy50:
 	YYDEBUG(50, *YYCURSOR);
-#line 1740 "ext/date/lib/parse_date.re"
+#line 1760 "ext/date/lib/parse_date.re"
 	{
 		goto std;
 	}
-#line 2420 "ext/date/lib/parse_date.c"
+#line 2428 "ext/date/lib/parse_date.c"
 yy51:
 	YYDEBUG(51, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -2425,12 +2433,12 @@
 	YYDEBUG(52, *YYCURSOR);
 	++YYCURSOR;
 	YYDEBUG(53, *YYCURSOR);
-#line 1745 "ext/date/lib/parse_date.re"
+#line 1765 "ext/date/lib/parse_date.re"
 	{
 		s->pos = cursor; s->line++;
 		goto std;
 	}
-#line 2434 "ext/date/lib/parse_date.c"
+#line 2442 "ext/date/lib/parse_date.c"
 yy54:
 	YYDEBUG(54, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -2817,7 +2825,7 @@
 	if (yych == 's') goto yy74;
 yy73:
 	YYDEBUG(73, *YYCURSOR);
-#line 1724 "ext/date/lib/parse_date.re"
+#line 1744 "ext/date/lib/parse_date.re"
 	{
 		timelib_ull i;
 		DEBUG_OUTPUT("relative");
@@ -2832,7 +2840,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_RELATIVE;
 	}
-#line 2836 "ext/date/lib/parse_date.c"
+#line 2844 "ext/date/lib/parse_date.c"
 yy74:
 	YYDEBUG(74, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -3594,7 +3602,7 @@
 	}
 yy167:
 	YYDEBUG(167, *YYCURSOR);
-#line 1587 "ext/date/lib/parse_date.re"
+#line 1607 "ext/date/lib/parse_date.re"
 	{
 		const timelib_relunit* relunit;
 		DEBUG_OUTPUT("daytext");
@@ -3611,7 +3619,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_WEEKDAY;
 	}
-#line 3615 "ext/date/lib/parse_date.c"
+#line 3623 "ext/date/lib/parse_date.c"
 yy168:
 	YYDEBUG(168, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -4131,7 +4139,7 @@
 	}
 yy194:
 	YYDEBUG(194, *YYCURSOR);
-#line 1646 "ext/date/lib/parse_date.re"
+#line 1666 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("monthtext");
 		TIMELIB_INIT;
@@ -4140,7 +4148,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_TEXT;
 	}
-#line 4144 "ext/date/lib/parse_date.c"
+#line 4152 "ext/date/lib/parse_date.c"
 yy195:
 	YYDEBUG(195, *YYCURSOR);
 	++YYCURSOR;
@@ -4191,19 +4199,20 @@
 	}
 yy199:
 	YYDEBUG(199, *YYCURSOR);
-#line 1396 "ext/date/lib/parse_date.re"
+#line 1412 "ext/date/lib/parse_date.re"
 	{
+		int length = 0;
 		DEBUG_OUTPUT("datetextual | datenoyear");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
 		s->time->m = timelib_get_month((char **) &ptr);
 		s->time->d = timelib_get_nr((char **) &ptr, 2);
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_TEXT;
 	}
-#line 4207 "ext/date/lib/parse_date.c"
+#line 4216 "ext/date/lib/parse_date.c"
 yy200:
 	YYDEBUG(200, *YYCURSOR);
 	yyaccept = 6;
@@ -4472,7 +4481,7 @@
 	}
 yy223:
 	YYDEBUG(223, *YYCURSOR);
-#line 1694 "ext/date/lib/parse_date.re"
+#line 1714 "ext/date/lib/parse_date.re"
 	{
 		int tz_not_found;
 		DEBUG_OUTPUT("dateshortwithtimeshort | dateshortwithtimelong | \
dateshortwithtimelongtz"); @@ -4501,7 +4510,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_SHORTDATE_WITH_TIME;
 	}
-#line 4505 "ext/date/lib/parse_date.c"
+#line 4514 "ext/date/lib/parse_date.c"
 yy224:
 	YYDEBUG(224, *YYCURSOR);
 	yyaccept = 7;
@@ -5199,7 +5208,7 @@
 	YYDEBUG(278, *YYCURSOR);
 	++YYCURSOR;
 	YYDEBUG(279, *YYCURSOR);
-#line 1670 "ext/date/lib/parse_date.re"
+#line 1690 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("dateshortwithtimeshort12 | dateshortwithtimelong12");
 		TIMELIB_INIT;
@@ -5222,7 +5231,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_SHORTDATE_WITH_TIME;
 	}
-#line 5226 "ext/date/lib/parse_date.c"
+#line 5235 "ext/date/lib/parse_date.c"
 yy280:
 	YYDEBUG(280, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -5400,19 +5409,20 @@
 	++YYCURSOR;
 yy295:
 	YYDEBUG(295, *YYCURSOR);
-#line 1370 "ext/date/lib/parse_date.re"
+#line 1384 "ext/date/lib/parse_date.re"
 	{
+		int length = 0;
 		DEBUG_OUTPUT("datenoday");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
 		s->time->m = timelib_get_month((char **) &ptr);
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		s->time->d = 1;
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_NO_DAY;
 	}
-#line 5416 "ext/date/lib/parse_date.c"
+#line 5426 "ext/date/lib/parse_date.c"
 yy296:
 	YYDEBUG(296, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -6632,19 +6642,20 @@
 	if (yych <= '9') goto yy365;
 yy364:
 	YYDEBUG(364, *YYCURSOR);
-#line 1510 "ext/date/lib/parse_date.re"
+#line 1528 "ext/date/lib/parse_date.re"
 	{
+		int length = 0;
 		DEBUG_OUTPUT("pgtextshort");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
 		s->time->m = timelib_get_month((char **) &ptr);
 		s->time->d = timelib_get_nr((char **) &ptr, 2);
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_PG_TEXT;
 	}
-#line 6648 "ext/date/lib/parse_date.c"
+#line 6659 "ext/date/lib/parse_date.c"
 yy365:
 	YYDEBUG(365, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -7282,7 +7293,7 @@
 	}
 yy393:
 	YYDEBUG(393, *YYCURSOR);
-#line 1566 "ext/date/lib/parse_date.re"
+#line 1586 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("ago");
 		TIMELIB_INIT;
@@ -7302,7 +7313,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_AGO;
 	}
-#line 7306 "ext/date/lib/parse_date.c"
+#line 7317 "ext/date/lib/parse_date.c"
 yy394:
 	YYDEBUG(394, *YYCURSOR);
 	yyaccept = 5;
@@ -9052,7 +9063,7 @@
 	++YYCURSOR;
 yy455:
 	YYDEBUG(455, *YYCURSOR);
-#line 1280 "ext/date/lib/parse_date.re"
+#line 1289 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("iso8601date4 | iso8601date2 | iso8601dateslash | dateslash");
 		TIMELIB_INIT;
@@ -9063,7 +9074,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_ISO_DATE;
 	}
-#line 9067 "ext/date/lib/parse_date.c"
+#line 9078 "ext/date/lib/parse_date.c"
 yy456:
 	YYDEBUG(456, *YYCURSOR);
 	yyaccept = 0;
@@ -9623,7 +9634,7 @@
 	}
 yy476:
 	YYDEBUG(476, *YYCURSOR);
-#line 1409 "ext/date/lib/parse_date.re"
+#line 1426 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("datenoyearrev");
 		TIMELIB_INIT;
@@ -9634,7 +9645,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_TEXT;
 	}
-#line 9638 "ext/date/lib/parse_date.c"
+#line 9649 "ext/date/lib/parse_date.c"
 yy477:
 	YYDEBUG(477, *YYCURSOR);
 	yyaccept = 10;
@@ -9775,7 +9786,7 @@
 	YYDEBUG(488, *YYCURSOR);
 	++YYCURSOR;
 	YYDEBUG(489, *YYCURSOR);
-#line 1136 "ext/date/lib/parse_date.re"
+#line 1144 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("timetiny12 | timeshort12 | timelong12");
 		TIMELIB_INIT;
@@ -9791,7 +9802,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_TIME12;
 	}
-#line 9795 "ext/date/lib/parse_date.c"
+#line 9806 "ext/date/lib/parse_date.c"
 yy490:
 	YYDEBUG(490, *YYCURSOR);
 	yyaccept = 11;
@@ -9804,7 +9815,7 @@
 	}
 yy491:
 	YYDEBUG(491, *YYCURSOR);
-#line 1173 "ext/date/lib/parse_date.re"
+#line 1181 "ext/date/lib/parse_date.re"
 	{
 		int tz_not_found;
 		DEBUG_OUTPUT("timeshort24 | timelong24 | iso8601long");
@@ -9829,7 +9840,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_TIME24_WITH_ZONE;
 	}
-#line 9833 "ext/date/lib/parse_date.c"
+#line 9844 "ext/date/lib/parse_date.c"
 yy492:
 	YYDEBUG(492, *YYCURSOR);
 	yyaccept = 11;
@@ -10139,7 +10150,7 @@
 	YYDEBUG(523, *YYCURSOR);
 	++YYCURSOR;
 	YYDEBUG(524, *YYCURSOR);
-#line 1153 "ext/date/lib/parse_date.re"
+#line 1161 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("mssqltime");
 		TIMELIB_INIT;
@@ -10158,7 +10169,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_TIME24_WITH_ZONE;
 	}
-#line 10162 "ext/date/lib/parse_date.c"
+#line 10173 "ext/date/lib/parse_date.c"
 yy525:
 	YYDEBUG(525, *YYCURSOR);
 	yyaccept = 11;
@@ -10264,20 +10275,21 @@
 	if (yych <= '9') goto yy541;
 yy535:
 	YYDEBUG(535, *YYCURSOR);
-#line 1331 "ext/date/lib/parse_date.re"
+#line 1343 "ext/date/lib/parse_date.re"
 	{
+		int length = 0;
 		DEBUG_OUTPUT("datefull");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
 		s->time->d = timelib_get_nr((char **) &ptr, 2);
 		timelib_skip_day_suffix((char **) &ptr);
 		s->time->m = timelib_get_month((char **) &ptr);
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_FULL;
 	}
-#line 10281 "ext/date/lib/parse_date.c"
+#line 10293 "ext/date/lib/parse_date.c"
 yy536:
 	YYDEBUG(536, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -11014,7 +11026,7 @@
 	YYDEBUG(606, *YYCURSOR);
 	++YYCURSOR;
 	YYDEBUG(607, *YYCURSOR);
-#line 1345 "ext/date/lib/parse_date.re"
+#line 1358 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("pointed date YYYY");
 		TIMELIB_INIT;
@@ -11025,7 +11037,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_FULL_POINTED;
 	}
-#line 11029 "ext/date/lib/parse_date.c"
+#line 11041 "ext/date/lib/parse_date.c"
 yy608:
 	YYDEBUG(608, *YYCURSOR);
 	yyaccept = 11;
@@ -11061,19 +11073,20 @@
 	if (yych <= '9') goto yy605;
 yy612:
 	YYDEBUG(612, *YYCURSOR);
-#line 1357 "ext/date/lib/parse_date.re"
+#line 1370 "ext/date/lib/parse_date.re"
 	{
+		int length = 0;
 		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);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 2, &length);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_FULL_POINTED;
 	}
-#line 11077 "ext/date/lib/parse_date.c"
+#line 11090 "ext/date/lib/parse_date.c"
 yy613:
 	YYDEBUG(613, *YYCURSOR);
 	yyaccept = 11;
@@ -11714,19 +11727,20 @@
 	}
 yy657:
 	YYDEBUG(657, *YYCURSOR);
-#line 1318 "ext/date/lib/parse_date.re"
+#line 1329 "ext/date/lib/parse_date.re"
 	{
+		int length = 0;
 		DEBUG_OUTPUT("gnudateshort");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		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_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_ISO_DATE;
 	}
-#line 11730 "ext/date/lib/parse_date.c"
+#line 11744 "ext/date/lib/parse_date.c"
 yy658:
 	YYDEBUG(658, *YYCURSOR);
 	yyaccept = 13;
@@ -11832,21 +11846,22 @@
 	}
 yy667:
 	YYDEBUG(667, *YYCURSOR);
-#line 1265 "ext/date/lib/parse_date.re"
+#line 1273 "ext/date/lib/parse_date.re"
 	{
+		int length = 0;
 		DEBUG_OUTPUT("americanshort | american");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
 		s->time->m = timelib_get_nr((char **) &ptr, 2);
 		s->time->d = timelib_get_nr((char **) &ptr, 2);
 		if (*ptr == '/') {
-			s->time->y = timelib_get_nr((char **) &ptr, 4);
-			TIMELIB_PROCESS_YEAR(s->time->y);
+			s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
+			TIMELIB_PROCESS_YEAR(s->time->y, length);
 		}
 		TIMELIB_DEINIT;
 		return TIMELIB_AMERICAN;
 	}
-#line 11850 "ext/date/lib/parse_date.c"
+#line 11865 "ext/date/lib/parse_date.c"
 yy668:
 	YYDEBUG(668, *YYCURSOR);
 	yyaccept = 14;
@@ -12079,7 +12094,7 @@
 	if (yych <= ':') goto yy704;
 yy701:
 	YYDEBUG(701, *YYCURSOR);
-#line 1536 "ext/date/lib/parse_date.re"
+#line 1556 "ext/date/lib/parse_date.re"
 	{
 		int tz_not_found;
 		DEBUG_OUTPUT("clf");
@@ -12099,7 +12114,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_CLF;
 	}
-#line 12103 "ext/date/lib/parse_date.c"
+#line 12118 "ext/date/lib/parse_date.c"
 yy702:
 	YYDEBUG(702, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -12651,19 +12666,20 @@
 	}
 yy764:
 	YYDEBUG(764, *YYCURSOR);
-#line 1292 "ext/date/lib/parse_date.re"
+#line 1301 "ext/date/lib/parse_date.re"
 	{
+		int length = 0;
 		DEBUG_OUTPUT("iso8601date2");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		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_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_ISO_DATE;
 	}
-#line 12667 "ext/date/lib/parse_date.c"
+#line 12683 "ext/date/lib/parse_date.c"
 yy765:
 	YYDEBUG(765, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -12702,19 +12718,20 @@
 	YYDEBUG(771, *YYCURSOR);
 	++YYCURSOR;
 	YYDEBUG(772, *YYCURSOR);
-#line 1523 "ext/date/lib/parse_date.re"
+#line 1542 "ext/date/lib/parse_date.re"
 	{
+		int length = 0;
 		DEBUG_OUTPUT("pgtextreverse");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		s->time->m = timelib_get_month((char **) &ptr);
 		s->time->d = timelib_get_nr((char **) &ptr, 2);
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_PG_TEXT;
 	}
-#line 12718 "ext/date/lib/parse_date.c"
+#line 12735 "ext/date/lib/parse_date.c"
 yy773:
 	YYDEBUG(773, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -12852,7 +12869,7 @@
 	}
 yy784:
 	YYDEBUG(784, *YYCURSOR);
-#line 1557 "ext/date/lib/parse_date.re"
+#line 1577 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("year4");
 		TIMELIB_INIT;
@@ -12860,7 +12877,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_CLF;
 	}
-#line 12864 "ext/date/lib/parse_date.c"
+#line 12881 "ext/date/lib/parse_date.c"
 yy785:
 	YYDEBUG(785, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -13011,19 +13028,20 @@
 	}
 yy794:
 	YYDEBUG(794, *YYCURSOR);
-#line 1383 "ext/date/lib/parse_date.re"
+#line 1398 "ext/date/lib/parse_date.re"
 	{
+		int length = 0;
 		DEBUG_OUTPUT("datenodayrev");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		s->time->m = timelib_get_month((char **) &ptr);
 		s->time->d = 1;
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_NO_DAY;
 	}
-#line 13027 "ext/date/lib/parse_date.c"
+#line 13045 "ext/date/lib/parse_date.c"
 yy795:
 	YYDEBUG(795, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -13238,7 +13256,7 @@
 	if (yych <= '7') goto yy817;
 yy815:
 	YYDEBUG(815, *YYCURSOR);
-#line 1491 "ext/date/lib/parse_date.re"
+#line 1509 "ext/date/lib/parse_date.re"
 	{
 		timelib_sll w, d;
 		DEBUG_OUTPUT("isoweek");
@@ -13256,7 +13274,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_ISO_WEEK;
 	}
-#line 13260 "ext/date/lib/parse_date.c"
+#line 13278 "ext/date/lib/parse_date.c"
 yy816:
 	YYDEBUG(816, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -13266,7 +13284,7 @@
 	YYDEBUG(817, *YYCURSOR);
 	++YYCURSOR;
 	YYDEBUG(818, *YYCURSOR);
-#line 1472 "ext/date/lib/parse_date.re"
+#line 1490 "ext/date/lib/parse_date.re"
 	{
 		timelib_sll w, d;
 		DEBUG_OUTPUT("isoweekday");
@@ -13284,7 +13302,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_ISO_WEEK;
 	}
-#line 13288 "ext/date/lib/parse_date.c"
+#line 13306 "ext/date/lib/parse_date.c"
 yy819:
 	YYDEBUG(819, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -13348,19 +13366,20 @@
 	}
 yy822:
 	YYDEBUG(822, *YYCURSOR);
-#line 1459 "ext/date/lib/parse_date.re"
+#line 1476 "ext/date/lib/parse_date.re"
 	{
+		int length = 0;
 		DEBUG_OUTPUT("pgydotd");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		s->time->d = timelib_get_nr((char **) &ptr, 3);
 		s->time->m = 1;
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_PG_YEARDAY;
 	}
-#line 13364 "ext/date/lib/parse_date.c"
+#line 13383 "ext/date/lib/parse_date.c"
 yy823:
 	YYDEBUG(823, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -13463,7 +13482,7 @@
 	++YYCURSOR;
 yy843:
 	YYDEBUG(843, *YYCURSOR);
-#line 1433 "ext/date/lib/parse_date.re"
+#line 1450 "ext/date/lib/parse_date.re"
 	{
 		int tz_not_found;
 		DEBUG_OUTPUT("xmlrpc | xmlrpcnocolon | soap | wddx | exif");
@@ -13488,7 +13507,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_XMLRPC_SOAP;
 	}
-#line 13492 "ext/date/lib/parse_date.c"
+#line 13511 "ext/date/lib/parse_date.c"
 yy844:
 	YYDEBUG(844, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -13750,7 +13769,7 @@
 	}
 yy849:
 	YYDEBUG(849, *YYCURSOR);
-#line 1421 "ext/date/lib/parse_date.re"
+#line 1438 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("datenocolon");
 		TIMELIB_INIT;
@@ -13761,7 +13780,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_NOCOLON;
 	}
-#line 13765 "ext/date/lib/parse_date.c"
+#line 13784 "ext/date/lib/parse_date.c"
 yy850:
 	YYDEBUG(850, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -14681,19 +14700,20 @@
 	if (yych <= '9') goto yy996;
 yy974:
 	YYDEBUG(974, *YYCURSOR);
-#line 1305 "ext/date/lib/parse_date.re"
+#line 1315 "ext/date/lib/parse_date.re"
 	{
+		int length = 0;
 		DEBUG_OUTPUT("gnudateshorter");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		s->time->m = timelib_get_nr((char **) &ptr, 2);
 		s->time->d = 1;
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_ISO_DATE;
 	}
-#line 14697 "ext/date/lib/parse_date.c"
+#line 14717 "ext/date/lib/parse_date.c"
 yy975:
 	YYDEBUG(975, *YYCURSOR);
 	yyaccept = 22;
@@ -15702,7 +15722,7 @@
 	}
 yy1068:
 	YYDEBUG(1068, *YYCURSOR);
-#line 1199 "ext/date/lib/parse_date.re"
+#line 1207 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("gnunocolon");
 		TIMELIB_INIT;
@@ -15724,7 +15744,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_GNU_NOCOLON;
 	}
-#line 15728 "ext/date/lib/parse_date.c"
+#line 15748 "ext/date/lib/parse_date.c"
 yy1069:
 	YYDEBUG(1069, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -15816,7 +15836,7 @@
 	}
 yy1076:
 	YYDEBUG(1076, *YYCURSOR);
-#line 1245 "ext/date/lib/parse_date.re"
+#line 1253 "ext/date/lib/parse_date.re"
 	{
 		int tz_not_found;
 		DEBUG_OUTPUT("iso8601nocolon");
@@ -15835,7 +15855,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_ISO_NOCOLON;
 	}
-#line 15839 "ext/date/lib/parse_date.c"
+#line 15859 "ext/date/lib/parse_date.c"
 yy1077:
 	YYDEBUG(1077, *YYCURSOR);
 	yyaccept = 25;
@@ -16733,7 +16753,7 @@
 	}
 yy1118:
 	YYDEBUG(1118, *YYCURSOR);
-#line 1629 "ext/date/lib/parse_date.re"
+#line 1649 "ext/date/lib/parse_date.re"
 	{
 		timelib_sll i;
 		int         behavior = 0;
@@ -16749,7 +16769,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_RELATIVE;
 	}
-#line 16753 "ext/date/lib/parse_date.c"
+#line 16773 "ext/date/lib/parse_date.c"
 yy1119:
 	YYDEBUG(1119, *YYCURSOR);
 	++YYCURSOR;
@@ -16800,7 +16820,7 @@
 	YYDEBUG(1126, *YYCURSOR);
 	++YYCURSOR;
 	YYDEBUG(1127, *YYCURSOR);
-#line 1114 "ext/date/lib/parse_date.re"
+#line 1122 "ext/date/lib/parse_date.re"
 	{
 		timelib_sll i;
 		int         behavior = 0;
@@ -16821,7 +16841,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_WEEK_DAY_OF_MONTH;
 	}
-#line 16825 "ext/date/lib/parse_date.c"
+#line 16845 "ext/date/lib/parse_date.c"
 yy1128:
 	YYDEBUG(1128, *YYCURSOR);
 	yyaccept = 26;
@@ -16929,7 +16949,7 @@
 	}
 yy1142:
 	YYDEBUG(1142, *YYCURSOR);
-#line 1605 "ext/date/lib/parse_date.re"
+#line 1625 "ext/date/lib/parse_date.re"
 	{
 		timelib_sll i;
 		int         behavior = 0;
@@ -16952,7 +16972,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_RELATIVE;
 	}
-#line 16956 "ext/date/lib/parse_date.c"
+#line 16976 "ext/date/lib/parse_date.c"
 yy1143:
 	YYDEBUG(1143, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -19629,7 +19649,7 @@
 	goto yy1298;
 yy1295:
 	YYDEBUG(1295, *YYCURSOR);
-#line 1091 "ext/date/lib/parse_date.re"
+#line 1099 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("backof | frontof");
 		TIMELIB_INIT;
@@ -19651,7 +19671,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_LF_DAY_OF_MONTH;
 	}
-#line 19655 "ext/date/lib/parse_date.c"
+#line 19675 "ext/date/lib/parse_date.c"
 yy1296:
 	YYDEBUG(1296, *YYCURSOR);
 	yyaccept = 28;
@@ -21342,7 +21362,7 @@
 	if (yych <= '9') goto yy1385;
 yy1387:
 	YYDEBUG(1387, *YYCURSOR);
-#line 1049 "ext/date/lib/parse_date.re"
+#line 1057 "ext/date/lib/parse_date.re"
 	{
 		timelib_ull i;

@@ -21366,7 +21386,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_RELATIVE;
 	}
-#line 21370 "ext/date/lib/parse_date.c"
+#line 21390 "ext/date/lib/parse_date.c"
 yy1388:
 	YYDEBUG(1388, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -21802,7 +21822,7 @@
 	++YYCURSOR;
 yy1417:
 	YYDEBUG(1417, *YYCURSOR);
-#line 1037 "ext/date/lib/parse_date.re"
+#line 1045 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("tomorrow");
 		TIMELIB_INIT;
@@ -21813,7 +21833,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_RELATIVE;
 	}
-#line 21817 "ext/date/lib/parse_date.c"
+#line 21837 "ext/date/lib/parse_date.c"
 yy1418:
 	YYDEBUG(1418, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -21848,7 +21868,7 @@
 	}
 yy1420:
 	YYDEBUG(1420, *YYCURSOR);
-#line 1027 "ext/date/lib/parse_date.re"
+#line 1035 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("midnight | today");
 		TIMELIB_INIT;
@@ -21857,7 +21877,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_RELATIVE;
 	}
-#line 21861 "ext/date/lib/parse_date.c"
+#line 21881 "ext/date/lib/parse_date.c"
 yy1421:
 	YYDEBUG(1421, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -23869,7 +23889,7 @@
 	}
 yy1500:
 	YYDEBUG(1500, *YYCURSOR);
-#line 1006 "ext/date/lib/parse_date.re"
+#line 1014 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("now");
 		TIMELIB_INIT;
@@ -23877,7 +23897,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_RELATIVE;
 	}
-#line 23881 "ext/date/lib/parse_date.c"
+#line 23901 "ext/date/lib/parse_date.c"
 yy1501:
 	YYDEBUG(1501, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -24016,7 +24036,7 @@
 	}
 yy1508:
 	YYDEBUG(1508, *YYCURSOR);
-#line 1015 "ext/date/lib/parse_date.re"
+#line 1023 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("noon");
 		TIMELIB_INIT;
@@ -24027,7 +24047,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_RELATIVE;
 	}
-#line 24031 "ext/date/lib/parse_date.c"
+#line 24051 "ext/date/lib/parse_date.c"
 yy1509:
 	YYDEBUG(1509, *YYCURSOR);
 	yyaccept = 0;
@@ -24560,7 +24580,7 @@
 	++YYCURSOR;
 yy1531:
 	YYDEBUG(1531, *YYCURSOR);
-#line 994 "ext/date/lib/parse_date.re"
+#line 1002 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("yesterday");
 		TIMELIB_INIT;
@@ -24571,7 +24591,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_RELATIVE;
 	}
-#line 24575 "ext/date/lib/parse_date.c"
+#line 24595 "ext/date/lib/parse_date.c"
 yy1532:
 	YYDEBUG(1532, *YYCURSOR);
 	yyaccept = 0;
@@ -24744,7 +24764,7 @@
 		goto yy1531;
 	}
 }
-#line 1755 "ext/date/lib/parse_date.re"
+#line 1775 "ext/date/lib/parse_date.re"

 }

@@ -24938,11 +24958,14 @@
 				}
 				break;
 			case 'y': /* two digit year */
-				TIMELIB_CHECK_NUMBER;
-				if ((s->time->y = timelib_get_nr((char **) &ptr, 2)) == TIMELIB_UNSET) {
-					add_pbf_error(s, "A two digit year could not be found", string, begin);
+				{
+					int length = 0;
+					TIMELIB_CHECK_NUMBER;
+					if ((s->time->y = timelib_get_nr_ex((char **) &ptr, 2, &length)) == \
TIMELIB_UNSET) { +						add_pbf_error(s, "A two digit year could not be found", \
string, begin); +					}
+					TIMELIB_PROCESS_YEAR(s->time->y, length);
 				}
-				TIMELIB_PROCESS_YEAR(s->time->y);
 				break;
 			case 'Y': /* four digit year */
 				TIMELIB_CHECK_NUMBER;
@@ -25106,8 +25129,8 @@
 		fptr++;
 	}
 	if (*fptr) {
+		/* Trailing | and ! specifiers are valid. */
 		int done = 0;
-		/* Trailing | and ! specifiers are valid. */
 		while (*fptr && !done) {
 			switch (*fptr++) {
 				case '!': /* reset all fields to default */

Modified: php/php-src/branches/PHP_5_4/ext/date/lib/parse_date.re
===================================================================
--- php/php-src/branches/PHP_5_4/ext/date/lib/parse_date.re	2011-11-25 15:47:11 UTC \
                (rev 319828)
+++ php/php-src/branches/PHP_5_4/ext/date/lib/parse_date.re	2011-11-25 15:51:37 UTC \
(rev 319829) @@ -119,8 +119,8 @@
 #define TIMELIB_DEINIT timelib_string_free(str)
 #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) == TIMELIB_UNSET) {         \
+#define TIMELIB_PROCESS_YEAR(x, l) { \
+	if (((x) == TIMELIB_UNSET) || ((l) >= 4)) { \
 	/*	(x) = 0; */          \
 	} else if ((x) < 100) {  \
 		if ((x) < 70) {      \
@@ -438,7 +438,7 @@
 	return tmp;
 }

-static timelib_sll timelib_get_nr(char **ptr, int max_length)
+static timelib_sll timelib_get_nr_ex(char **ptr, int max_length, int \
*scanned_length)  {
 	char *begin, *end, *str;
 	timelib_sll tmp_nr = TIMELIB_UNSET;
@@ -456,6 +456,9 @@
 		++len;
 	}
 	end = *ptr;
+	if (scanned_length) {
+		*scanned_length = end - begin;
+	}
 	str = calloc(1, end - begin + 1);
 	memcpy(str, begin, end - begin);
 	tmp_nr = strtoll(str, NULL, 10);
@@ -463,6 +466,11 @@
 	return tmp_nr;
 }

+static timelib_sll timelib_get_nr(char **ptr, int max_length)
+{
+	return timelib_get_nr_ex(ptr, max_length, NULL);
+}
+
 static void timelib_skip_day_suffix(char **ptr)
 {
 	if (isspace(**ptr)) {
@@ -1263,14 +1271,15 @@

 	americanshort | american
 	{
+		int length = 0;
 		DEBUG_OUTPUT("americanshort | american");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
 		s->time->m = timelib_get_nr((char **) &ptr, 2);
 		s->time->d = timelib_get_nr((char **) &ptr, 2);
 		if (*ptr == '/') {
-			s->time->y = timelib_get_nr((char **) &ptr, 4);
-			TIMELIB_PROCESS_YEAR(s->time->y);
+			s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
+			TIMELIB_PROCESS_YEAR(s->time->y, length);
 		}
 		TIMELIB_DEINIT;
 		return TIMELIB_AMERICAN;
@@ -1290,53 +1299,57 @@

 	iso8601date2
 	{
+		int length = 0;
 		DEBUG_OUTPUT("iso8601date2");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		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_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_ISO_DATE;
 	}

 	gnudateshorter
 	{
+		int length = 0;
 		DEBUG_OUTPUT("gnudateshorter");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		s->time->m = timelib_get_nr((char **) &ptr, 2);
 		s->time->d = 1;
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_ISO_DATE;
 	}

 	gnudateshort
 	{
+		int length = 0;
 		DEBUG_OUTPUT("gnudateshort");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		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_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_ISO_DATE;
 	}

 	datefull
 	{
+		int length = 0;
 		DEBUG_OUTPUT("datefull");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
 		s->time->d = timelib_get_nr((char **) &ptr, 2);
 		timelib_skip_day_suffix((char **) &ptr);
 		s->time->m = timelib_get_month((char **) &ptr);
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_FULL;
 	}
@@ -1355,52 +1368,56 @@

 	pointeddate2
 	{
+		int length = 0;
 		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);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 2, &length);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_FULL_POINTED;
 	}

 	datenoday
 	{
+		int length = 0;
 		DEBUG_OUTPUT("datenoday");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
 		s->time->m = timelib_get_month((char **) &ptr);
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		s->time->d = 1;
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_NO_DAY;
 	}

 	datenodayrev
 	{
+		int length = 0;
 		DEBUG_OUTPUT("datenodayrev");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		s->time->m = timelib_get_month((char **) &ptr);
 		s->time->d = 1;
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_NO_DAY;
 	}

 	datetextual | datenoyear
 	{
+		int length = 0;
 		DEBUG_OUTPUT("datetextual | datenoyear");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
 		s->time->m = timelib_get_month((char **) &ptr);
 		s->time->d = timelib_get_nr((char **) &ptr, 2);
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_TEXT;
 	}
@@ -1457,13 +1474,14 @@

 	pgydotd
 	{
+		int length = 0;
 		DEBUG_OUTPUT("pgydotd");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		s->time->d = timelib_get_nr((char **) &ptr, 3);
 		s->time->m = 1;
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_PG_YEARDAY;
 	}
@@ -1508,26 +1526,28 @@

 	pgtextshort
 	{
+		int length = 0;
 		DEBUG_OUTPUT("pgtextshort");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
 		s->time->m = timelib_get_month((char **) &ptr);
 		s->time->d = timelib_get_nr((char **) &ptr, 2);
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_PG_TEXT;
 	}

 	pgtextreverse
 	{
+		int length = 0;
 		DEBUG_OUTPUT("pgtextreverse");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		s->time->m = timelib_get_month((char **) &ptr);
 		s->time->d = timelib_get_nr((char **) &ptr, 2);
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_PG_TEXT;
 	}
@@ -1945,11 +1965,14 @@
 				}
 				break;
 			case 'y': /* two digit year */
-				TIMELIB_CHECK_NUMBER;
-				if ((s->time->y = timelib_get_nr((char **) &ptr, 2)) == TIMELIB_UNSET) {
-					add_pbf_error(s, "A two digit year could not be found", string, begin);
+				{
+					int length = 0;
+					TIMELIB_CHECK_NUMBER;
+					if ((s->time->y = timelib_get_nr_ex((char **) &ptr, 2, &length)) == \
TIMELIB_UNSET) { +						add_pbf_error(s, "A two digit year could not be found", \
string, begin); +					}
+					TIMELIB_PROCESS_YEAR(s->time->y, length);
 				}
-				TIMELIB_PROCESS_YEAR(s->time->y);
 				break;
 			case 'Y': /* four digit year */
 				TIMELIB_CHECK_NUMBER;
@@ -2113,8 +2136,8 @@
 		fptr++;
 	}
 	if (*fptr) {
+		/* Trailing | and ! specifiers are valid. */
 		int done = 0;
-		/* Trailing | and ! specifiers are valid. */
 		while (*fptr && !done) {
 			switch (*fptr++) {
 				case '!': /* reset all fields to default */

Added: php/php-src/branches/PHP_5_4/ext/date/tests/bug54597.phpt
===================================================================
--- php/php-src/branches/PHP_5_4/ext/date/tests/bug54597.phpt	                        \
                (rev 0)
+++ php/php-src/branches/PHP_5_4/ext/date/tests/bug54597.phpt	2011-11-25 15:51:37 UTC \
(rev 319829) @@ -0,0 +1,18 @@
+--TEST--
+Bug #54597: incorrect years for DateTime objects created with 4-digit years
+--INI--
+date.timezone=Europe/London
+--FILE--
+<?php
+$tz = new DateTimeZone("Europe/Amsterdam");
+$dateObject = new DateTime( 'January 0099', $tz );
+echo $dateObject->format( 'Y' ), "\n";
+$dateObject = new DateTime( 'January 1, 0099', $tz );
+echo $dateObject->format( 'Y' ), "\n";
+$dateObject = new DateTime( '0099-01', $tz );
+echo $dateObject->format( 'Y' ), "\n";
+?>
+--EXPECT--
+0099
+0099
+0099

Modified: php/php-src/trunk/ext/date/lib/parse_date.c
===================================================================
--- php/php-src/trunk/ext/date/lib/parse_date.c	2011-11-25 15:47:11 UTC (rev 319828)
+++ php/php-src/trunk/ext/date/lib/parse_date.c	2011-11-25 15:51:37 UTC (rev 319829)
@@ -1,4 +1,4 @@
-/* Generated by re2c 0.13.5 on Thu Jun 23 10:58:11 2011 */
+/* Generated by re2c 0.13.5 on Fri Nov 25 16:42:45 2011 */
 #line 1 "ext/date/lib/parse_date.re"
 /*
    +----------------------------------------------------------------------+
@@ -121,8 +121,8 @@
 #define TIMELIB_DEINIT timelib_string_free(str)
 #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) == TIMELIB_UNSET) {         \
+#define TIMELIB_PROCESS_YEAR(x, l) { \
+	if (((x) == TIMELIB_UNSET) || ((l) >= 4)) { \
 	/*	(x) = 0; */          \
 	} else if ((x) < 100) {  \
 		if ((x) < 70) {      \
@@ -440,7 +440,7 @@
 	return tmp;
 }

-static timelib_sll timelib_get_nr(char **ptr, int max_length)
+static timelib_sll timelib_get_nr_ex(char **ptr, int max_length, int \
*scanned_length)  {
 	char *begin, *end, *str;
 	timelib_sll tmp_nr = TIMELIB_UNSET;
@@ -458,6 +458,9 @@
 		++len;
 	}
 	end = *ptr;
+	if (scanned_length) {
+		*scanned_length = end - begin;
+	}
 	str = calloc(1, end - begin + 1);
 	memcpy(str, begin, end - begin);
 	tmp_nr = strtoll(str, NULL, 10);
@@ -465,6 +468,11 @@
 	return tmp_nr;
 }

+static timelib_sll timelib_get_nr(char **ptr, int max_length)
+{
+	return timelib_get_nr_ex(ptr, max_length, NULL);
+}
+
 static void timelib_skip_day_suffix(char **ptr)
 {
 	if (isspace(**ptr)) {
@@ -863,11 +871,11 @@
 std:
 	s->tok = cursor;
 	s->len = 0;
-#line 989 "ext/date/lib/parse_date.re"
+#line 997 "ext/date/lib/parse_date.re"



-#line 871 "ext/date/lib/parse_date.c"
+#line 879 "ext/date/lib/parse_date.c"
 {
 	YYCTYPE yych;
 	unsigned int yyaccept = 0;
@@ -987,7 +995,7 @@
 	}
 yy2:
 	YYDEBUG(2, *YYCURSOR);
-#line 1074 "ext/date/lib/parse_date.re"
+#line 1082 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("firstdayof | lastdayof");
 		TIMELIB_INIT;
@@ -1003,7 +1011,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_LF_DAY_OF_MONTH;
 	}
-#line 1007 "ext/date/lib/parse_date.c"
+#line 1015 "ext/date/lib/parse_date.c"
 yy3:
 	YYDEBUG(3, *YYCURSOR);
 	++YYCURSOR;
@@ -1026,7 +1034,7 @@
 	}
 yy4:
 	YYDEBUG(4, *YYCURSOR);
-#line 1656 "ext/date/lib/parse_date.re"
+#line 1676 "ext/date/lib/parse_date.re"
 	{
 		int tz_not_found;
 		DEBUG_OUTPUT("tzcorrection | tz");
@@ -1039,7 +1047,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_TIMEZONE;
 	}
-#line 1043 "ext/date/lib/parse_date.c"
+#line 1051 "ext/date/lib/parse_date.c"
 yy5:
 	YYDEBUG(5, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -1350,12 +1358,12 @@
 	if (yych <= '9') goto yy1385;
 yy13:
 	YYDEBUG(13, *YYCURSOR);
-#line 1751 "ext/date/lib/parse_date.re"
+#line 1771 "ext/date/lib/parse_date.re"
 	{
 		add_error(s, "Unexpected character");
 		goto std;
 	}
-#line 1359 "ext/date/lib/parse_date.c"
+#line 1367 "ext/date/lib/parse_date.c"
 yy14:
 	YYDEBUG(14, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -2412,11 +2420,11 @@
 	if (yych <= '9') goto yy55;
 yy50:
 	YYDEBUG(50, *YYCURSOR);
-#line 1740 "ext/date/lib/parse_date.re"
+#line 1760 "ext/date/lib/parse_date.re"
 	{
 		goto std;
 	}
-#line 2420 "ext/date/lib/parse_date.c"
+#line 2428 "ext/date/lib/parse_date.c"
 yy51:
 	YYDEBUG(51, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -2425,12 +2433,12 @@
 	YYDEBUG(52, *YYCURSOR);
 	++YYCURSOR;
 	YYDEBUG(53, *YYCURSOR);
-#line 1745 "ext/date/lib/parse_date.re"
+#line 1765 "ext/date/lib/parse_date.re"
 	{
 		s->pos = cursor; s->line++;
 		goto std;
 	}
-#line 2434 "ext/date/lib/parse_date.c"
+#line 2442 "ext/date/lib/parse_date.c"
 yy54:
 	YYDEBUG(54, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -2817,7 +2825,7 @@
 	if (yych == 's') goto yy74;
 yy73:
 	YYDEBUG(73, *YYCURSOR);
-#line 1724 "ext/date/lib/parse_date.re"
+#line 1744 "ext/date/lib/parse_date.re"
 	{
 		timelib_ull i;
 		DEBUG_OUTPUT("relative");
@@ -2832,7 +2840,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_RELATIVE;
 	}
-#line 2836 "ext/date/lib/parse_date.c"
+#line 2844 "ext/date/lib/parse_date.c"
 yy74:
 	YYDEBUG(74, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -3594,7 +3602,7 @@
 	}
 yy167:
 	YYDEBUG(167, *YYCURSOR);
-#line 1587 "ext/date/lib/parse_date.re"
+#line 1607 "ext/date/lib/parse_date.re"
 	{
 		const timelib_relunit* relunit;
 		DEBUG_OUTPUT("daytext");
@@ -3611,7 +3619,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_WEEKDAY;
 	}
-#line 3615 "ext/date/lib/parse_date.c"
+#line 3623 "ext/date/lib/parse_date.c"
 yy168:
 	YYDEBUG(168, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -4131,7 +4139,7 @@
 	}
 yy194:
 	YYDEBUG(194, *YYCURSOR);
-#line 1646 "ext/date/lib/parse_date.re"
+#line 1666 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("monthtext");
 		TIMELIB_INIT;
@@ -4140,7 +4148,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_TEXT;
 	}
-#line 4144 "ext/date/lib/parse_date.c"
+#line 4152 "ext/date/lib/parse_date.c"
 yy195:
 	YYDEBUG(195, *YYCURSOR);
 	++YYCURSOR;
@@ -4191,19 +4199,20 @@
 	}
 yy199:
 	YYDEBUG(199, *YYCURSOR);
-#line 1396 "ext/date/lib/parse_date.re"
+#line 1412 "ext/date/lib/parse_date.re"
 	{
+		int length = 0;
 		DEBUG_OUTPUT("datetextual | datenoyear");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
 		s->time->m = timelib_get_month((char **) &ptr);
 		s->time->d = timelib_get_nr((char **) &ptr, 2);
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_TEXT;
 	}
-#line 4207 "ext/date/lib/parse_date.c"
+#line 4216 "ext/date/lib/parse_date.c"
 yy200:
 	YYDEBUG(200, *YYCURSOR);
 	yyaccept = 6;
@@ -4472,7 +4481,7 @@
 	}
 yy223:
 	YYDEBUG(223, *YYCURSOR);
-#line 1694 "ext/date/lib/parse_date.re"
+#line 1714 "ext/date/lib/parse_date.re"
 	{
 		int tz_not_found;
 		DEBUG_OUTPUT("dateshortwithtimeshort | dateshortwithtimelong | \
dateshortwithtimelongtz"); @@ -4501,7 +4510,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_SHORTDATE_WITH_TIME;
 	}
-#line 4505 "ext/date/lib/parse_date.c"
+#line 4514 "ext/date/lib/parse_date.c"
 yy224:
 	YYDEBUG(224, *YYCURSOR);
 	yyaccept = 7;
@@ -5199,7 +5208,7 @@
 	YYDEBUG(278, *YYCURSOR);
 	++YYCURSOR;
 	YYDEBUG(279, *YYCURSOR);
-#line 1670 "ext/date/lib/parse_date.re"
+#line 1690 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("dateshortwithtimeshort12 | dateshortwithtimelong12");
 		TIMELIB_INIT;
@@ -5222,7 +5231,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_SHORTDATE_WITH_TIME;
 	}
-#line 5226 "ext/date/lib/parse_date.c"
+#line 5235 "ext/date/lib/parse_date.c"
 yy280:
 	YYDEBUG(280, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -5400,19 +5409,20 @@
 	++YYCURSOR;
 yy295:
 	YYDEBUG(295, *YYCURSOR);
-#line 1370 "ext/date/lib/parse_date.re"
+#line 1384 "ext/date/lib/parse_date.re"
 	{
+		int length = 0;
 		DEBUG_OUTPUT("datenoday");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
 		s->time->m = timelib_get_month((char **) &ptr);
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		s->time->d = 1;
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_NO_DAY;
 	}
-#line 5416 "ext/date/lib/parse_date.c"
+#line 5426 "ext/date/lib/parse_date.c"
 yy296:
 	YYDEBUG(296, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -6632,19 +6642,20 @@
 	if (yych <= '9') goto yy365;
 yy364:
 	YYDEBUG(364, *YYCURSOR);
-#line 1510 "ext/date/lib/parse_date.re"
+#line 1528 "ext/date/lib/parse_date.re"
 	{
+		int length = 0;
 		DEBUG_OUTPUT("pgtextshort");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
 		s->time->m = timelib_get_month((char **) &ptr);
 		s->time->d = timelib_get_nr((char **) &ptr, 2);
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_PG_TEXT;
 	}
-#line 6648 "ext/date/lib/parse_date.c"
+#line 6659 "ext/date/lib/parse_date.c"
 yy365:
 	YYDEBUG(365, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -7282,7 +7293,7 @@
 	}
 yy393:
 	YYDEBUG(393, *YYCURSOR);
-#line 1566 "ext/date/lib/parse_date.re"
+#line 1586 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("ago");
 		TIMELIB_INIT;
@@ -7302,7 +7313,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_AGO;
 	}
-#line 7306 "ext/date/lib/parse_date.c"
+#line 7317 "ext/date/lib/parse_date.c"
 yy394:
 	YYDEBUG(394, *YYCURSOR);
 	yyaccept = 5;
@@ -9052,7 +9063,7 @@
 	++YYCURSOR;
 yy455:
 	YYDEBUG(455, *YYCURSOR);
-#line 1280 "ext/date/lib/parse_date.re"
+#line 1289 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("iso8601date4 | iso8601date2 | iso8601dateslash | dateslash");
 		TIMELIB_INIT;
@@ -9063,7 +9074,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_ISO_DATE;
 	}
-#line 9067 "ext/date/lib/parse_date.c"
+#line 9078 "ext/date/lib/parse_date.c"
 yy456:
 	YYDEBUG(456, *YYCURSOR);
 	yyaccept = 0;
@@ -9623,7 +9634,7 @@
 	}
 yy476:
 	YYDEBUG(476, *YYCURSOR);
-#line 1409 "ext/date/lib/parse_date.re"
+#line 1426 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("datenoyearrev");
 		TIMELIB_INIT;
@@ -9634,7 +9645,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_TEXT;
 	}
-#line 9638 "ext/date/lib/parse_date.c"
+#line 9649 "ext/date/lib/parse_date.c"
 yy477:
 	YYDEBUG(477, *YYCURSOR);
 	yyaccept = 10;
@@ -9775,7 +9786,7 @@
 	YYDEBUG(488, *YYCURSOR);
 	++YYCURSOR;
 	YYDEBUG(489, *YYCURSOR);
-#line 1136 "ext/date/lib/parse_date.re"
+#line 1144 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("timetiny12 | timeshort12 | timelong12");
 		TIMELIB_INIT;
@@ -9791,7 +9802,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_TIME12;
 	}
-#line 9795 "ext/date/lib/parse_date.c"
+#line 9806 "ext/date/lib/parse_date.c"
 yy490:
 	YYDEBUG(490, *YYCURSOR);
 	yyaccept = 11;
@@ -9804,7 +9815,7 @@
 	}
 yy491:
 	YYDEBUG(491, *YYCURSOR);
-#line 1173 "ext/date/lib/parse_date.re"
+#line 1181 "ext/date/lib/parse_date.re"
 	{
 		int tz_not_found;
 		DEBUG_OUTPUT("timeshort24 | timelong24 | iso8601long");
@@ -9829,7 +9840,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_TIME24_WITH_ZONE;
 	}
-#line 9833 "ext/date/lib/parse_date.c"
+#line 9844 "ext/date/lib/parse_date.c"
 yy492:
 	YYDEBUG(492, *YYCURSOR);
 	yyaccept = 11;
@@ -10139,7 +10150,7 @@
 	YYDEBUG(523, *YYCURSOR);
 	++YYCURSOR;
 	YYDEBUG(524, *YYCURSOR);
-#line 1153 "ext/date/lib/parse_date.re"
+#line 1161 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("mssqltime");
 		TIMELIB_INIT;
@@ -10158,7 +10169,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_TIME24_WITH_ZONE;
 	}
-#line 10162 "ext/date/lib/parse_date.c"
+#line 10173 "ext/date/lib/parse_date.c"
 yy525:
 	YYDEBUG(525, *YYCURSOR);
 	yyaccept = 11;
@@ -10264,20 +10275,21 @@
 	if (yych <= '9') goto yy541;
 yy535:
 	YYDEBUG(535, *YYCURSOR);
-#line 1331 "ext/date/lib/parse_date.re"
+#line 1343 "ext/date/lib/parse_date.re"
 	{
+		int length = 0;
 		DEBUG_OUTPUT("datefull");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
 		s->time->d = timelib_get_nr((char **) &ptr, 2);
 		timelib_skip_day_suffix((char **) &ptr);
 		s->time->m = timelib_get_month((char **) &ptr);
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_FULL;
 	}
-#line 10281 "ext/date/lib/parse_date.c"
+#line 10293 "ext/date/lib/parse_date.c"
 yy536:
 	YYDEBUG(536, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -11014,7 +11026,7 @@
 	YYDEBUG(606, *YYCURSOR);
 	++YYCURSOR;
 	YYDEBUG(607, *YYCURSOR);
-#line 1345 "ext/date/lib/parse_date.re"
+#line 1358 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("pointed date YYYY");
 		TIMELIB_INIT;
@@ -11025,7 +11037,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_FULL_POINTED;
 	}
-#line 11029 "ext/date/lib/parse_date.c"
+#line 11041 "ext/date/lib/parse_date.c"
 yy608:
 	YYDEBUG(608, *YYCURSOR);
 	yyaccept = 11;
@@ -11061,19 +11073,20 @@
 	if (yych <= '9') goto yy605;
 yy612:
 	YYDEBUG(612, *YYCURSOR);
-#line 1357 "ext/date/lib/parse_date.re"
+#line 1370 "ext/date/lib/parse_date.re"
 	{
+		int length = 0;
 		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);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 2, &length);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_FULL_POINTED;
 	}
-#line 11077 "ext/date/lib/parse_date.c"
+#line 11090 "ext/date/lib/parse_date.c"
 yy613:
 	YYDEBUG(613, *YYCURSOR);
 	yyaccept = 11;
@@ -11714,19 +11727,20 @@
 	}
 yy657:
 	YYDEBUG(657, *YYCURSOR);
-#line 1318 "ext/date/lib/parse_date.re"
+#line 1329 "ext/date/lib/parse_date.re"
 	{
+		int length = 0;
 		DEBUG_OUTPUT("gnudateshort");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		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_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_ISO_DATE;
 	}
-#line 11730 "ext/date/lib/parse_date.c"
+#line 11744 "ext/date/lib/parse_date.c"
 yy658:
 	YYDEBUG(658, *YYCURSOR);
 	yyaccept = 13;
@@ -11832,21 +11846,22 @@
 	}
 yy667:
 	YYDEBUG(667, *YYCURSOR);
-#line 1265 "ext/date/lib/parse_date.re"
+#line 1273 "ext/date/lib/parse_date.re"
 	{
+		int length = 0;
 		DEBUG_OUTPUT("americanshort | american");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
 		s->time->m = timelib_get_nr((char **) &ptr, 2);
 		s->time->d = timelib_get_nr((char **) &ptr, 2);
 		if (*ptr == '/') {
-			s->time->y = timelib_get_nr((char **) &ptr, 4);
-			TIMELIB_PROCESS_YEAR(s->time->y);
+			s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
+			TIMELIB_PROCESS_YEAR(s->time->y, length);
 		}
 		TIMELIB_DEINIT;
 		return TIMELIB_AMERICAN;
 	}
-#line 11850 "ext/date/lib/parse_date.c"
+#line 11865 "ext/date/lib/parse_date.c"
 yy668:
 	YYDEBUG(668, *YYCURSOR);
 	yyaccept = 14;
@@ -12079,7 +12094,7 @@
 	if (yych <= ':') goto yy704;
 yy701:
 	YYDEBUG(701, *YYCURSOR);
-#line 1536 "ext/date/lib/parse_date.re"
+#line 1556 "ext/date/lib/parse_date.re"
 	{
 		int tz_not_found;
 		DEBUG_OUTPUT("clf");
@@ -12099,7 +12114,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_CLF;
 	}
-#line 12103 "ext/date/lib/parse_date.c"
+#line 12118 "ext/date/lib/parse_date.c"
 yy702:
 	YYDEBUG(702, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -12651,19 +12666,20 @@
 	}
 yy764:
 	YYDEBUG(764, *YYCURSOR);
-#line 1292 "ext/date/lib/parse_date.re"
+#line 1301 "ext/date/lib/parse_date.re"
 	{
+		int length = 0;
 		DEBUG_OUTPUT("iso8601date2");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		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_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_ISO_DATE;
 	}
-#line 12667 "ext/date/lib/parse_date.c"
+#line 12683 "ext/date/lib/parse_date.c"
 yy765:
 	YYDEBUG(765, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -12702,19 +12718,20 @@
 	YYDEBUG(771, *YYCURSOR);
 	++YYCURSOR;
 	YYDEBUG(772, *YYCURSOR);
-#line 1523 "ext/date/lib/parse_date.re"
+#line 1542 "ext/date/lib/parse_date.re"
 	{
+		int length = 0;
 		DEBUG_OUTPUT("pgtextreverse");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		s->time->m = timelib_get_month((char **) &ptr);
 		s->time->d = timelib_get_nr((char **) &ptr, 2);
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_PG_TEXT;
 	}
-#line 12718 "ext/date/lib/parse_date.c"
+#line 12735 "ext/date/lib/parse_date.c"
 yy773:
 	YYDEBUG(773, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -12852,7 +12869,7 @@
 	}
 yy784:
 	YYDEBUG(784, *YYCURSOR);
-#line 1557 "ext/date/lib/parse_date.re"
+#line 1577 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("year4");
 		TIMELIB_INIT;
@@ -12860,7 +12877,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_CLF;
 	}
-#line 12864 "ext/date/lib/parse_date.c"
+#line 12881 "ext/date/lib/parse_date.c"
 yy785:
 	YYDEBUG(785, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -13011,19 +13028,20 @@
 	}
 yy794:
 	YYDEBUG(794, *YYCURSOR);
-#line 1383 "ext/date/lib/parse_date.re"
+#line 1398 "ext/date/lib/parse_date.re"
 	{
+		int length = 0;
 		DEBUG_OUTPUT("datenodayrev");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		s->time->m = timelib_get_month((char **) &ptr);
 		s->time->d = 1;
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_NO_DAY;
 	}
-#line 13027 "ext/date/lib/parse_date.c"
+#line 13045 "ext/date/lib/parse_date.c"
 yy795:
 	YYDEBUG(795, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -13238,7 +13256,7 @@
 	if (yych <= '7') goto yy817;
 yy815:
 	YYDEBUG(815, *YYCURSOR);
-#line 1491 "ext/date/lib/parse_date.re"
+#line 1509 "ext/date/lib/parse_date.re"
 	{
 		timelib_sll w, d;
 		DEBUG_OUTPUT("isoweek");
@@ -13256,7 +13274,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_ISO_WEEK;
 	}
-#line 13260 "ext/date/lib/parse_date.c"
+#line 13278 "ext/date/lib/parse_date.c"
 yy816:
 	YYDEBUG(816, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -13266,7 +13284,7 @@
 	YYDEBUG(817, *YYCURSOR);
 	++YYCURSOR;
 	YYDEBUG(818, *YYCURSOR);
-#line 1472 "ext/date/lib/parse_date.re"
+#line 1490 "ext/date/lib/parse_date.re"
 	{
 		timelib_sll w, d;
 		DEBUG_OUTPUT("isoweekday");
@@ -13284,7 +13302,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_ISO_WEEK;
 	}
-#line 13288 "ext/date/lib/parse_date.c"
+#line 13306 "ext/date/lib/parse_date.c"
 yy819:
 	YYDEBUG(819, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -13348,19 +13366,20 @@
 	}
 yy822:
 	YYDEBUG(822, *YYCURSOR);
-#line 1459 "ext/date/lib/parse_date.re"
+#line 1476 "ext/date/lib/parse_date.re"
 	{
+		int length = 0;
 		DEBUG_OUTPUT("pgydotd");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		s->time->d = timelib_get_nr((char **) &ptr, 3);
 		s->time->m = 1;
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_PG_YEARDAY;
 	}
-#line 13364 "ext/date/lib/parse_date.c"
+#line 13383 "ext/date/lib/parse_date.c"
 yy823:
 	YYDEBUG(823, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -13463,7 +13482,7 @@
 	++YYCURSOR;
 yy843:
 	YYDEBUG(843, *YYCURSOR);
-#line 1433 "ext/date/lib/parse_date.re"
+#line 1450 "ext/date/lib/parse_date.re"
 	{
 		int tz_not_found;
 		DEBUG_OUTPUT("xmlrpc | xmlrpcnocolon | soap | wddx | exif");
@@ -13488,7 +13507,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_XMLRPC_SOAP;
 	}
-#line 13492 "ext/date/lib/parse_date.c"
+#line 13511 "ext/date/lib/parse_date.c"
 yy844:
 	YYDEBUG(844, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -13750,7 +13769,7 @@
 	}
 yy849:
 	YYDEBUG(849, *YYCURSOR);
-#line 1421 "ext/date/lib/parse_date.re"
+#line 1438 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("datenocolon");
 		TIMELIB_INIT;
@@ -13761,7 +13780,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_NOCOLON;
 	}
-#line 13765 "ext/date/lib/parse_date.c"
+#line 13784 "ext/date/lib/parse_date.c"
 yy850:
 	YYDEBUG(850, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -14681,19 +14700,20 @@
 	if (yych <= '9') goto yy996;
 yy974:
 	YYDEBUG(974, *YYCURSOR);
-#line 1305 "ext/date/lib/parse_date.re"
+#line 1315 "ext/date/lib/parse_date.re"
 	{
+		int length = 0;
 		DEBUG_OUTPUT("gnudateshorter");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		s->time->m = timelib_get_nr((char **) &ptr, 2);
 		s->time->d = 1;
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_ISO_DATE;
 	}
-#line 14697 "ext/date/lib/parse_date.c"
+#line 14717 "ext/date/lib/parse_date.c"
 yy975:
 	YYDEBUG(975, *YYCURSOR);
 	yyaccept = 22;
@@ -15702,7 +15722,7 @@
 	}
 yy1068:
 	YYDEBUG(1068, *YYCURSOR);
-#line 1199 "ext/date/lib/parse_date.re"
+#line 1207 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("gnunocolon");
 		TIMELIB_INIT;
@@ -15724,7 +15744,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_GNU_NOCOLON;
 	}
-#line 15728 "ext/date/lib/parse_date.c"
+#line 15748 "ext/date/lib/parse_date.c"
 yy1069:
 	YYDEBUG(1069, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -15816,7 +15836,7 @@
 	}
 yy1076:
 	YYDEBUG(1076, *YYCURSOR);
-#line 1245 "ext/date/lib/parse_date.re"
+#line 1253 "ext/date/lib/parse_date.re"
 	{
 		int tz_not_found;
 		DEBUG_OUTPUT("iso8601nocolon");
@@ -15835,7 +15855,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_ISO_NOCOLON;
 	}
-#line 15839 "ext/date/lib/parse_date.c"
+#line 15859 "ext/date/lib/parse_date.c"
 yy1077:
 	YYDEBUG(1077, *YYCURSOR);
 	yyaccept = 25;
@@ -16733,7 +16753,7 @@
 	}
 yy1118:
 	YYDEBUG(1118, *YYCURSOR);
-#line 1629 "ext/date/lib/parse_date.re"
+#line 1649 "ext/date/lib/parse_date.re"
 	{
 		timelib_sll i;
 		int         behavior = 0;
@@ -16749,7 +16769,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_RELATIVE;
 	}
-#line 16753 "ext/date/lib/parse_date.c"
+#line 16773 "ext/date/lib/parse_date.c"
 yy1119:
 	YYDEBUG(1119, *YYCURSOR);
 	++YYCURSOR;
@@ -16800,7 +16820,7 @@
 	YYDEBUG(1126, *YYCURSOR);
 	++YYCURSOR;
 	YYDEBUG(1127, *YYCURSOR);
-#line 1114 "ext/date/lib/parse_date.re"
+#line 1122 "ext/date/lib/parse_date.re"
 	{
 		timelib_sll i;
 		int         behavior = 0;
@@ -16821,7 +16841,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_WEEK_DAY_OF_MONTH;
 	}
-#line 16825 "ext/date/lib/parse_date.c"
+#line 16845 "ext/date/lib/parse_date.c"
 yy1128:
 	YYDEBUG(1128, *YYCURSOR);
 	yyaccept = 26;
@@ -16929,7 +16949,7 @@
 	}
 yy1142:
 	YYDEBUG(1142, *YYCURSOR);
-#line 1605 "ext/date/lib/parse_date.re"
+#line 1625 "ext/date/lib/parse_date.re"
 	{
 		timelib_sll i;
 		int         behavior = 0;
@@ -16952,7 +16972,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_RELATIVE;
 	}
-#line 16956 "ext/date/lib/parse_date.c"
+#line 16976 "ext/date/lib/parse_date.c"
 yy1143:
 	YYDEBUG(1143, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -19629,7 +19649,7 @@
 	goto yy1298;
 yy1295:
 	YYDEBUG(1295, *YYCURSOR);
-#line 1091 "ext/date/lib/parse_date.re"
+#line 1099 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("backof | frontof");
 		TIMELIB_INIT;
@@ -19651,7 +19671,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_LF_DAY_OF_MONTH;
 	}
-#line 19655 "ext/date/lib/parse_date.c"
+#line 19675 "ext/date/lib/parse_date.c"
 yy1296:
 	YYDEBUG(1296, *YYCURSOR);
 	yyaccept = 28;
@@ -21342,7 +21362,7 @@
 	if (yych <= '9') goto yy1385;
 yy1387:
 	YYDEBUG(1387, *YYCURSOR);
-#line 1049 "ext/date/lib/parse_date.re"
+#line 1057 "ext/date/lib/parse_date.re"
 	{
 		timelib_ull i;

@@ -21366,7 +21386,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_RELATIVE;
 	}
-#line 21370 "ext/date/lib/parse_date.c"
+#line 21390 "ext/date/lib/parse_date.c"
 yy1388:
 	YYDEBUG(1388, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -21802,7 +21822,7 @@
 	++YYCURSOR;
 yy1417:
 	YYDEBUG(1417, *YYCURSOR);
-#line 1037 "ext/date/lib/parse_date.re"
+#line 1045 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("tomorrow");
 		TIMELIB_INIT;
@@ -21813,7 +21833,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_RELATIVE;
 	}
-#line 21817 "ext/date/lib/parse_date.c"
+#line 21837 "ext/date/lib/parse_date.c"
 yy1418:
 	YYDEBUG(1418, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -21848,7 +21868,7 @@
 	}
 yy1420:
 	YYDEBUG(1420, *YYCURSOR);
-#line 1027 "ext/date/lib/parse_date.re"
+#line 1035 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("midnight | today");
 		TIMELIB_INIT;
@@ -21857,7 +21877,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_RELATIVE;
 	}
-#line 21861 "ext/date/lib/parse_date.c"
+#line 21881 "ext/date/lib/parse_date.c"
 yy1421:
 	YYDEBUG(1421, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -23869,7 +23889,7 @@
 	}
 yy1500:
 	YYDEBUG(1500, *YYCURSOR);
-#line 1006 "ext/date/lib/parse_date.re"
+#line 1014 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("now");
 		TIMELIB_INIT;
@@ -23877,7 +23897,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_RELATIVE;
 	}
-#line 23881 "ext/date/lib/parse_date.c"
+#line 23901 "ext/date/lib/parse_date.c"
 yy1501:
 	YYDEBUG(1501, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -24016,7 +24036,7 @@
 	}
 yy1508:
 	YYDEBUG(1508, *YYCURSOR);
-#line 1015 "ext/date/lib/parse_date.re"
+#line 1023 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("noon");
 		TIMELIB_INIT;
@@ -24027,7 +24047,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_RELATIVE;
 	}
-#line 24031 "ext/date/lib/parse_date.c"
+#line 24051 "ext/date/lib/parse_date.c"
 yy1509:
 	YYDEBUG(1509, *YYCURSOR);
 	yyaccept = 0;
@@ -24560,7 +24580,7 @@
 	++YYCURSOR;
 yy1531:
 	YYDEBUG(1531, *YYCURSOR);
-#line 994 "ext/date/lib/parse_date.re"
+#line 1002 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("yesterday");
 		TIMELIB_INIT;
@@ -24571,7 +24591,7 @@
 		TIMELIB_DEINIT;
 		return TIMELIB_RELATIVE;
 	}
-#line 24575 "ext/date/lib/parse_date.c"
+#line 24595 "ext/date/lib/parse_date.c"
 yy1532:
 	YYDEBUG(1532, *YYCURSOR);
 	yyaccept = 0;
@@ -24744,7 +24764,7 @@
 		goto yy1531;
 	}
 }
-#line 1755 "ext/date/lib/parse_date.re"
+#line 1775 "ext/date/lib/parse_date.re"

 }

@@ -24938,11 +24958,14 @@
 				}
 				break;
 			case 'y': /* two digit year */
-				TIMELIB_CHECK_NUMBER;
-				if ((s->time->y = timelib_get_nr((char **) &ptr, 2)) == TIMELIB_UNSET) {
-					add_pbf_error(s, "A two digit year could not be found", string, begin);
+				{
+					int length = 0;
+					TIMELIB_CHECK_NUMBER;
+					if ((s->time->y = timelib_get_nr_ex((char **) &ptr, 2, &length)) == \
TIMELIB_UNSET) { +						add_pbf_error(s, "A two digit year could not be found", \
string, begin); +					}
+					TIMELIB_PROCESS_YEAR(s->time->y, length);
 				}
-				TIMELIB_PROCESS_YEAR(s->time->y);
 				break;
 			case 'Y': /* four digit year */
 				TIMELIB_CHECK_NUMBER;

Modified: php/php-src/trunk/ext/date/lib/parse_date.re
===================================================================
--- php/php-src/trunk/ext/date/lib/parse_date.re	2011-11-25 15:47:11 UTC (rev 319828)
+++ php/php-src/trunk/ext/date/lib/parse_date.re	2011-11-25 15:51:37 UTC (rev 319829)
@@ -119,8 +119,8 @@
 #define TIMELIB_DEINIT timelib_string_free(str)
 #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) == TIMELIB_UNSET) {         \
+#define TIMELIB_PROCESS_YEAR(x, l) { \
+	if (((x) == TIMELIB_UNSET) || ((l) >= 4)) { \
 	/*	(x) = 0; */          \
 	} else if ((x) < 100) {  \
 		if ((x) < 70) {      \
@@ -438,7 +438,7 @@
 	return tmp;
 }

-static timelib_sll timelib_get_nr(char **ptr, int max_length)
+static timelib_sll timelib_get_nr_ex(char **ptr, int max_length, int \
*scanned_length)  {
 	char *begin, *end, *str;
 	timelib_sll tmp_nr = TIMELIB_UNSET;
@@ -456,6 +456,9 @@
 		++len;
 	}
 	end = *ptr;
+	if (scanned_length) {
+		*scanned_length = end - begin;
+	}
 	str = calloc(1, end - begin + 1);
 	memcpy(str, begin, end - begin);
 	tmp_nr = strtoll(str, NULL, 10);
@@ -463,6 +466,11 @@
 	return tmp_nr;
 }

+static timelib_sll timelib_get_nr(char **ptr, int max_length)
+{
+	return timelib_get_nr_ex(ptr, max_length, NULL);
+}
+
 static void timelib_skip_day_suffix(char **ptr)
 {
 	if (isspace(**ptr)) {
@@ -1263,14 +1271,15 @@

 	americanshort | american
 	{
+		int length = 0;
 		DEBUG_OUTPUT("americanshort | american");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
 		s->time->m = timelib_get_nr((char **) &ptr, 2);
 		s->time->d = timelib_get_nr((char **) &ptr, 2);
 		if (*ptr == '/') {
-			s->time->y = timelib_get_nr((char **) &ptr, 4);
-			TIMELIB_PROCESS_YEAR(s->time->y);
+			s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
+			TIMELIB_PROCESS_YEAR(s->time->y, length);
 		}
 		TIMELIB_DEINIT;
 		return TIMELIB_AMERICAN;
@@ -1290,53 +1299,57 @@

 	iso8601date2
 	{
+		int length = 0;
 		DEBUG_OUTPUT("iso8601date2");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		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_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_ISO_DATE;
 	}

 	gnudateshorter
 	{
+		int length = 0;
 		DEBUG_OUTPUT("gnudateshorter");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		s->time->m = timelib_get_nr((char **) &ptr, 2);
 		s->time->d = 1;
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_ISO_DATE;
 	}

 	gnudateshort
 	{
+		int length = 0;
 		DEBUG_OUTPUT("gnudateshort");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		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_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_ISO_DATE;
 	}

 	datefull
 	{
+		int length = 0;
 		DEBUG_OUTPUT("datefull");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
 		s->time->d = timelib_get_nr((char **) &ptr, 2);
 		timelib_skip_day_suffix((char **) &ptr);
 		s->time->m = timelib_get_month((char **) &ptr);
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_FULL;
 	}
@@ -1355,52 +1368,56 @@

 	pointeddate2
 	{
+		int length = 0;
 		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);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 2, &length);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_FULL_POINTED;
 	}

 	datenoday
 	{
+		int length = 0;
 		DEBUG_OUTPUT("datenoday");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
 		s->time->m = timelib_get_month((char **) &ptr);
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		s->time->d = 1;
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_NO_DAY;
 	}

 	datenodayrev
 	{
+		int length = 0;
 		DEBUG_OUTPUT("datenodayrev");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		s->time->m = timelib_get_month((char **) &ptr);
 		s->time->d = 1;
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_NO_DAY;
 	}

 	datetextual | datenoyear
 	{
+		int length = 0;
 		DEBUG_OUTPUT("datetextual | datenoyear");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
 		s->time->m = timelib_get_month((char **) &ptr);
 		s->time->d = timelib_get_nr((char **) &ptr, 2);
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_TEXT;
 	}
@@ -1457,13 +1474,14 @@

 	pgydotd
 	{
+		int length = 0;
 		DEBUG_OUTPUT("pgydotd");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		s->time->d = timelib_get_nr((char **) &ptr, 3);
 		s->time->m = 1;
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_PG_YEARDAY;
 	}
@@ -1508,26 +1526,28 @@

 	pgtextshort
 	{
+		int length = 0;
 		DEBUG_OUTPUT("pgtextshort");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
 		s->time->m = timelib_get_month((char **) &ptr);
 		s->time->d = timelib_get_nr((char **) &ptr, 2);
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_PG_TEXT;
 	}

 	pgtextreverse
 	{
+		int length = 0;
 		DEBUG_OUTPUT("pgtextreverse");
 		TIMELIB_INIT;
 		TIMELIB_HAVE_DATE();
-		s->time->y = timelib_get_nr((char **) &ptr, 4);
+		s->time->y = timelib_get_nr_ex((char **) &ptr, 4, &length);
 		s->time->m = timelib_get_month((char **) &ptr);
 		s->time->d = timelib_get_nr((char **) &ptr, 2);
-		TIMELIB_PROCESS_YEAR(s->time->y);
+		TIMELIB_PROCESS_YEAR(s->time->y, length);
 		TIMELIB_DEINIT;
 		return TIMELIB_PG_TEXT;
 	}
@@ -1945,11 +1965,14 @@
 				}
 				break;
 			case 'y': /* two digit year */
-				TIMELIB_CHECK_NUMBER;
-				if ((s->time->y = timelib_get_nr((char **) &ptr, 2)) == TIMELIB_UNSET) {
-					add_pbf_error(s, "A two digit year could not be found", string, begin);
+				{
+					int length = 0;
+					TIMELIB_CHECK_NUMBER;
+					if ((s->time->y = timelib_get_nr_ex((char **) &ptr, 2, &length)) == \
TIMELIB_UNSET) { +						add_pbf_error(s, "A two digit year could not be found", \
string, begin); +					}
+					TIMELIB_PROCESS_YEAR(s->time->y, length);
 				}
-				TIMELIB_PROCESS_YEAR(s->time->y);
 				break;
 			case 'Y': /* four digit year */
 				TIMELIB_CHECK_NUMBER;

Added: php/php-src/trunk/ext/date/tests/bug54597.phpt
===================================================================
--- php/php-src/trunk/ext/date/tests/bug54597.phpt	                        (rev 0)
+++ php/php-src/trunk/ext/date/tests/bug54597.phpt	2011-11-25 15:51:37 UTC (rev \
319829) @@ -0,0 +1,18 @@
+--TEST--
+Bug #54597: incorrect years for DateTime objects created with 4-digit years
+--INI--
+date.timezone=Europe/London
+--FILE--
+<?php
+$tz = new DateTimeZone("Europe/Amsterdam");
+$dateObject = new DateTime( 'January 0099', $tz );
+echo $dateObject->format( 'Y' ), "\n";
+$dateObject = new DateTime( 'January 1, 0099', $tz );
+echo $dateObject->format( 'Y' ), "\n";
+$dateObject = new DateTime( '0099-01', $tz );
+echo $dateObject->format( 'Y' ), "\n";
+?>
+--EXPECT--
+0099
+0099
+0099



-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic