[php-src] master: Update to timelib 2026.01

Derick Rethans <[email protected]>
Newsgroups gmane.comp.php.cvs.general
Message-ID <[email protected]>
Author: Derick Rethans (derickr)
Date: 2026-08-05T12:34:56+01:00

Commit: https://github.com/php/php-src/commit/69b6debd8089a3b66cb33d32e6d647befc08c01c
Raw diff: https://github.com/php/php-src/commit/69b6debd8089a3b66cb33d32e6d647befc08c01c.diff

Update to timelib 2026.01

Changed paths:
  A  ext/date/lib/duration.c
  M  NEWS
  M  ext/date/lib/interval.c
  M  ext/date/lib/parse_date.c
  M  ext/date/lib/parse_date.re
  M  ext/date/lib/parse_iso_intervals.c
  M  ext/date/lib/parse_iso_intervals.re
  M  ext/date/lib/parse_tz.c
  M  ext/date/lib/timelib.c
  M  ext/date/lib/timelib.h
  M  ext/date/lib/timelib_private.h


Diff:

diff --git a/NEWS b/NEWS
index 16a4ae4e99b8..7dd05a2b1c72 100644
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,9 @@ PHP                                                                        NEWS
   . Changed run-tests.php to run test subprocesses without a shell where
     possible. (NickSdot)
 
+- Date:
+  . Update timelib to 2026.01. (Derick, timwolla)
+
 - GMP:
   . Added optional $definitely_prime output parameter to gmp_prevprime().
     (Weilin Du)
diff --git a/ext/date/lib/duration.c b/ext/date/lib/duration.c
new file mode 100644
index 000000000000..b5b0c7668504
--- /dev/null
+++ b/ext/date/lib/duration.c
@@ -0,0 +1,429 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2015-2026 Derick Rethans
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "timelib.h"
+#include "timelib_private.h"
+
+int timelib_duration_ctor_static(
+	timelib_duration *duration,
+	timelib_ull       seconds,
+	uint32_t          nanoseconds,
+	bool              negative
+) {
+	if (seconds > MAX_DURATION_SECONDS) {
+		return TIMELIB_ERROR_SECONDS_OUT_OF_RANGE;
+	}
+	if (nanoseconds >= NSECS_PER_SEC) {
+		return TIMELIB_ERROR_NANOSECONDS_OUT_OF_RANGE;
+	}
+
+	duration->seconds = seconds;
+	duration->nanoseconds = nanoseconds;
+
+	if (seconds != 0 || nanoseconds != 0) {
+		duration->negative = negative;
+	} else {
+		duration->negative = false;
+	}
+
+	return TIMELIB_ERROR_NO_ERROR;
+}
+
+timelib_duration *timelib_duration_ctor(
+	timelib_ull            seconds,
+	uint32_t               nanoseconds,
+	bool                   negative,
+	int                   *error_code
+) {
+	timelib_duration *tmp = calloc(1, sizeof(timelib_duration));
+
+	*error_code = timelib_duration_ctor_static(tmp, seconds, nanoseconds, negative);
+
+	if (*error_code != TIMELIB_ERROR_NO_ERROR) {
+		free(tmp);
+		return NULL;
+	}
+
+	return tmp;
+}
+
+timelib_duration *timelib_duration_create_from_iso8601string(
+	const char *string,
+	int        *error_code
+) {
+	timelib_time            *b = NULL, *e = NULL;
+	timelib_rel_time        *p = NULL;
+	int                      r = -1;
+	timelib_error_container *errors;
+	timelib_duration        *new_duration = NULL;
+
+	timelib_strtointerval(string, strlen(string), &b, &e, &p, &r, &errors);
+
+	if (errors->error_count > 0 || errors->warning_count > 0) {
+		*error_code = TIMELIB_ERROR_ISO8601_DURATION_PARSE_FAILURE;
+		goto free_elements;
+	}
+
+	if (!p) {
+		*error_code = TIMELIB_ERROR_DURATION_MISSING_PERIOD;
+		goto free_elements;
+	}
+
+	if (b != NULL || e != NULL || r != -1) {
+		*error_code = TIMELIB_ERROR_DURATION_ONLY_PERIOD_ALLOWED;
+		goto free_elements;
+	}
+
+	if (p->y > 0 || p->m >0 || p->d > 0) {
+		*error_code = TIMELIB_ERROR_DURATION_DAYS_FOUND;
+		goto free_elements;
+	}
+
+	new_duration = calloc(1, sizeof(timelib_duration));
+
+	*error_code = timelib_duration_ctor_static(new_duration, p->h * 3600 + p->i * 60 + p->s, 0, false);
+
+	if (*error_code != TIMELIB_ERROR_NO_ERROR) {
+		free(new_duration);
+		new_duration = NULL;
+	}
+
+free_elements:
+	if (b) {
+		timelib_time_dtor(b);
+	}
+	if (e) {
+		timelib_time_dtor(e);
+	}
+	if (p) {
+		timelib_rel_time_dtor(p);
+	}
+	timelib_error_container_dtor(errors);
+
+	return new_duration;
+}
+
+void timelib_duration_dtor(timelib_duration *duration)
+{
+	free(duration);
+}
+
+static int timelib_duration_add_abs_internal(
+	timelib_duration       *new_duration,
+	const timelib_duration *original,
+	const timelib_duration *additional
+) {
+	timelib_ull seconds = original->seconds + additional->seconds;
+	uint32_t nanoseconds = original->nanoseconds + additional->nanoseconds;
+
+	if (nanoseconds >= NSECS_PER_SEC) {
+		seconds++;
+		nanoseconds -= NSECS_PER_SEC;
+	}
+
+	return timelib_duration_ctor_static(new_duration, seconds, nanoseconds, original->negative);
+}
+
+
+static int timelib_duration_sub_abs_internal(
+	timelib_duration       *new_duration,
+	const timelib_duration *original,
+	const timelib_duration *minus
+) {
+	timelib_ull seconds = original->seconds - minus->seconds;
+	timelib_sll nanoseconds = (timelib_sll)original->nanoseconds - (timelib_sll)minus->nanoseconds;
+
+	if (nanoseconds < 0) {
+		seconds--;
+		nanoseconds += NSECS_PER_SEC;
+	}
+
+	return timelib_duration_ctor_static(new_duration, seconds, nanoseconds, original->negative);
+}
+
+static int timelib_duration_null_abs_internal(timelib_duration *new_duration)
+{
+	new_duration->negative = false;
+	new_duration->seconds = 0;
+	new_duration->nanoseconds = 0;
+
+	return TIMELIB_ERROR_NO_ERROR;
+}
+
+
+int timelib_duration_add_static(
+	timelib_duration       *new_duration,
+	const timelib_duration *original,
+	const timelib_duration *additional
+) {
+	int c = 0;
+
+	/* ++ / -- */
+	if (original->negative == additional->negative) {
+		return timelib_duration_add_abs_internal(new_duration, original, additional);
+	}
+
+	/* +- / -+ */
+	c = timelib_duration_abs_compare(original, additional);
+
+	switch (c)
+	{
+		case -1:
+			/* additional has the larger value */
+			return timelib_duration_sub_abs_internal(new_duration, additional, original);
+
+		case 0:
+			return timelib_duration_null_abs_internal(new_duration);
+
+		case 1:
+			/* original has the larger value */
+			return timelib_duration_sub_abs_internal(new_duration, original, additional);
+	}
+
+	/* Should not be reachable due to semantics of timelib_duration_abs_compare() */
+	return TIMELIB_ERROR_NO_ERROR;
+}
+
+timelib_duration *timelib_duration_add(
+	const timelib_duration *original,
+	const timelib_duration *additional,
+	int                    *error_code
+) {
+	timelib_duration *tmp = calloc(1, sizeof(timelib_duration));
+
+	*error_code = timelib_duration_add_static(tmp, original, additional);
+
+	if (*error_code != TIMELIB_ERROR_NO_ERROR) {
+		free(tmp);
+		return NULL;
+	}
+
+	return tmp;
+}
+
+
+int timelib_duration_sub_static(
+	timelib_duration       *new_duration,
+	const timelib_duration *original,
+	const timelib_duration *minus
+) {
+	int c = 0;
+
+	/* +- / -+ */
+	if (original->negative != minus->negative) {
+		return timelib_duration_add_abs_internal(new_duration, original, minus);
+	}
+
+	/* ++ / -- */
+	c = timelib_duration_abs_compare(original, minus);
+
+	switch (c)
+	{
+		case -1: {
+			/* minus has the larger value */
+			timelib_duration tmp_duration;
+
+			int result = timelib_duration_sub_abs_internal(&tmp_duration, minus, original);
+			if (result != TIMELIB_ERROR_NO_ERROR) {
+				return result;
+			}
+
+			return timelib_duration_negate_static(new_duration, &tmp_duration);
+		}
+
+		case 0:
+			return timelib_duration_null_abs_internal(new_duration);
+
+		case 1:
+			/* original has the larger value */
+			return timelib_duration_sub_abs_internal(new_duration, original, minus);
+	}
+
+	/* Should not be reachable due to semantics of comparisons above */
+	return TIMELIB_ERROR_NO_ERROR;
+}
+
+timelib_duration *timelib_duration_sub(
+	const timelib_duration *original,
+	const timelib_duration *minus,
+	int                    *error_code
+) {
+	timelib_duration *tmp = calloc(1, sizeof(timelib_duration));
+
+	*error_code = timelib_duration_sub_static(tmp, original, minus);
+
+	if (*error_code != TIMELIB_ERROR_NO_ERROR) {
+		free(tmp);
+		return NULL;
+	}
+
+	return tmp;
+}
+
+int timelib_duration_mul_static(
+	timelib_duration       *new_duration,
+	const timelib_duration *original,
+	uint64_t                factor
+) {
+	uint64_t seconds, extra_seconds, nanoseconds;
+
+	if (factor == 0) {
+		return timelib_duration_null_abs_internal(new_duration);
+	}
+
+	if (original->seconds > UINT64_MAX / factor) {
+		return TIMELIB_ERROR_OVERFLOW;
+	}
+
+	seconds = original->seconds * factor;
+
+	/* Calculate the number of whole seconds in the nanoseconds product.
+	 *
+	 * extra_seconds is guaranteed to be smaller than factor, because
+	 * original->nanoseconds is smaller than NSECS_PER_SEC. */
+	extra_seconds = original->nanoseconds * (factor / NSECS_PER_SEC);
+
+	/* This cannot overflow either, because NSECS_PER_SEC * NSECS_PER_SEC fits uint64_t.
+	 *
+	 * (nanoseconds * factor) % NSECS_PER_SEC is mathematically equivalent
+	 * to (nanoseconds * (factor % NSECS_PER_SEC)) % NSECS_PER_SEC. */
+	nanoseconds = original->nanoseconds * (factor % NSECS_PER_SEC);
+	extra_seconds += nanoseconds / NSECS_PER_SEC;
+	nanoseconds %= NSECS_PER_SEC;
+
+	if (UINT64_MAX - extra_seconds < seconds) {
+		return TIMELIB_ERROR_OVERFLOW;
+	}
+
+	seconds += extra_seconds;
+
+	return timelib_duration_ctor_static(new_duration, seconds, nanoseconds, original->negative);
+}
+
+timelib_duration *timelib_duration_mul(
+	const timelib_duration *original,
+	uint64_t                factor,
+	int                    *error_code
+) {
+	timelib_duration *tmp = calloc(1, sizeof(timelib_duration));
+
+	*error_code = timelib_duration_mul_static(tmp, original, factor);
+
+	if (*error_code != TIMELIB_ERROR_NO_ERROR) {
+		free(tmp);
+		return NULL;
+	}
+
+	return tmp;
+}
+
+int timelib_duration_div_static(
+	timelib_duration       *new_duration,
+	const timelib_duration *original,
+	uint64_t                divisor
+) {
+	timelib_ull seconds;
+	uint32_t nanoseconds;
+
+	if (divisor < 1) {
+		return TIMELIB_ERROR_DIVISION_BY_ZERO;
+	}
+
+	seconds = original->seconds / divisor;
+	nanoseconds = original->nanoseconds + ((original->seconds % divisor) * NSECS_PER_SEC);
+	nanoseconds /= divisor;
+
+	return timelib_duration_ctor_static(new_duration, seconds, nanoseconds, original->negative);
+}
+
+timelib_duration *timelib_duration_div(
+	const timelib_duration *original,
+	uint64_t                divisor,
+	int                    *error_code
+) {
+	timelib_duration *tmp = calloc(1, sizeof(timelib_duration));
+
+	*error_code = timelib_duration_div_static(tmp, original, divisor);
+
+	if (*error_code != TIMELIB_ERROR_NO_ERROR) {
+		free(tmp);
+		return NULL;
+	}
+
+	return tmp;
+}
+
+int timelib_duration_negate_static(timelib_duration *new_duration, const timelib_duration *original)
+{
+	return timelib_duration_ctor_static(new_duration, original->seconds, original->nanoseconds, !original->negative);
+}
+
+timelib_duration *timelib_duration_negate(const timelib_duration *original, int *error_code)
+{
+	timelib_duration *tmp = calloc(1, sizeof(timelib_duration));
+
+	*error_code = timelib_duration_negate_static(tmp, original);
+
+	if (*error_code != TIMELIB_ERROR_NO_ERROR) {
+		free(tmp);
+		return NULL;
+	}
+
+	return tmp;
+}
+
+int timelib_duration_abs_compare(const timelib_duration *one, const timelib_duration *two)
+{
+	if (one->seconds < two->seconds) {
+		return -1;
+	}
+	if (one->seconds > two->seconds) {
+		return 1;
+	}
+
+	if (one->nanoseconds < two->nanoseconds) {
+		return -1;
+	}
+	if (one->nanoseconds > two->nanoseconds) {
+		return 1;
+	}
+
+	return 0;
+}
+
+int timelib_duration_compare(const timelib_duration *one, const timelib_duration *two)
+{
+	if (one->negative && !two->negative) {
+		return -1;
+	}
+	if (!one->negative && two->negative) {
+		return 1;
+	}
+
+	if (one->negative && two->negative) {
+		return timelib_duration_abs_compare(two, one);
+	}
+
+	return timelib_duration_abs_compare(one, two);
+}
diff --git a/ext/date/lib/interval.c b/ext/date/lib/interval.c
index da9262da999b..fb10963d7572 100644
--- a/ext/date/lib/interval.c
+++ b/ext/date/lib/interval.c
@@ -201,7 +201,10 @@ int timelib_diff_days(timelib_time *one, timelib_time *two)
 			days--;
 		}
 	} else {
-		days = fabs(floor(one->sse - two->sse) / 86400);
+		/* FIXME: This truncates the range of days to INT_MAX to avoid an
+		 * overflow later on. Ideally, all APIs have better error handling. */
+		double ddays = fabs(floor(one->sse - two->sse) / 86400);
+		days = ddays <= INT_MAX ? ddays : INT_MAX;
 	}
 
 	return days;
diff --git a/ext/date/lib/parse_date.c b/ext/date/lib/parse_date.c
index eb324f8430c5..3380ba732658 100644
--- a/ext/date/lib/parse_date.c
+++ b/ext/date/lib/parse_date.c
@@ -1,4 +1,4 @@
-/* Generated by re2c 1.0.3 on Wed Jan 14 14:21:53 2026 */
+/* Generated by re2c 1.0.3 on Wed Aug  5 11:34:24 2026 */
 #line 1 "ext/date/lib/parse_date.re"
 /*
  * The MIT License (MIT)
@@ -34,16 +34,6 @@
 #include <assert.h>
 #include <limits.h>
 
-#if defined(_MSC_VER)
-# define strtoll(s, f, b) _atoi64(s)
-#elif !defined(HAVE_STRTOLL)
-# if defined(HAVE_ATOLL)
-#  define strtoll(s, f, b) atoll(s)
-# else
-#  define strtoll(s, f, b) strtol(s, f, b)
-# endif
-#endif
-
 #define EOI      257
 #define TIME     258
 #define DATE     259
@@ -557,7 +547,6 @@ static timelib_ull timelib_get_signed_nr(Scanner *s, const char **ptr, int max_l
 	int len = 0;
 
 	/* Skip over non-numeric chars */
-
 	while (((**ptr < '0') || (**ptr > '9')) && (**ptr != '+') && (**ptr != '-')) {
 		if (**ptr == '\0') {
 			add_error(s, TIMELIB_ERR_UNEXPECTED_DATA, "Found unexpected data");
@@ -571,6 +560,7 @@ static timelib_ull timelib_get_signed_nr(Scanner *s, const char **ptr, int max_l
 	str[0] = '+'; /* First position is the sign */
 	str_ptr = str + 1;
 
+
 	while ((**ptr == '+') || (**ptr == '-')) {
 		if (**ptr == '-') {
 			str[0] = str[0] == '+' ? '-' : '+';
@@ -1028,11 +1018,11 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 std:
 	s->tok = cursor;
 	s->len = 0;
-#line 1161 "ext/date/lib/parse_date.re"
+#line 1151 "ext/date/lib/parse_date.re"
 
 
 
-#line 1036 "ext/date/lib/parse_date.c"
+#line 1026 "ext/date/lib/parse_date.c"
 {
 	YYCTYPE yych;
 	unsigned int yyaccept = 0;
@@ -1213,23 +1203,23 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	YYDEBUG(2, *YYCURSOR);
 	++YYCURSOR;
 	YYDEBUG(3, *YYCURSOR);
-#line 1994 "ext/date/lib/parse_date.re"
+#line 1984 "ext/date/lib/parse_date.re"
 	{
 		s->pos = cursor; s->line++;
 		goto std;
 	}
-#line 1222 "ext/date/lib/parse_date.c"
+#line 1212 "ext/date/lib/parse_date.c"
 yy4:
 	YYDEBUG(4, *YYCURSOR);
 	++YYCURSOR;
 yy5:
 	YYDEBUG(5, *YYCURSOR);
-#line 2000 "ext/date/lib/parse_date.re"
+#line 1990 "ext/date/lib/parse_date.re"
 	{
 		add_error(s, TIMELIB_ERR_UNEXPECTED_CHARACTER, "Unexpected character");
 		goto std;
 	}
-#line 1233 "ext/date/lib/parse_date.c"
+#line 1223 "ext/date/lib/parse_date.c"
 yy6:
 	YYDEBUG(6, *YYCURSOR);
 	yyaccept = 0;
@@ -1244,11 +1234,11 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	if (yych <= '9') goto yy58;
 yy8:
 	YYDEBUG(8, *YYCURSOR);
-#line 1989 "ext/date/lib/parse_date.re"
+#line 1979 "ext/date/lib/parse_date.re"
 	{
 		goto std;
 	}
-#line 1252 "ext/date/lib/parse_date.c"
+#line 1242 "ext/date/lib/parse_date.c"
 yy9:
 	YYDEBUG(9, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -1282,11 +1272,11 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	YYDEBUG(11, *YYCURSOR);
 	++YYCURSOR;
 	YYDEBUG(12, *YYCURSOR);
-#line 1984 "ext/date/lib/parse_date.re"
+#line 1974 "ext/date/lib/parse_date.re"
 	{
 		goto std;
 	}
-#line 1290 "ext/date/lib/parse_date.c"
+#line 1280 "ext/date/lib/parse_date.c"
 yy13:
 	YYDEBUG(13, *YYCURSOR);
 	yyaccept = 1;
@@ -1787,7 +1777,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	}
 yy20:
 	YYDEBUG(20, *YYCURSOR);
-#line 1899 "ext/date/lib/parse_date.re"
+#line 1889 "ext/date/lib/parse_date.re"
 	{
 		int tz_not_found;
 		DEBUG_OUTPUT("tzcorrection | tz");
@@ -1801,7 +1791,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_TIMEZONE;
 	}
-#line 1805 "ext/date/lib/parse_date.c"
+#line 1795 "ext/date/lib/parse_date.c"
 yy21:
 	YYDEBUG(21, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -3606,7 +3596,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	}
 yy81:
 	YYDEBUG(81, *YYCURSOR);
-#line 1646 "ext/date/lib/parse_date.re"
+#line 1636 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("datenoyearrev");
 		TIMELIB_INIT;
@@ -3617,7 +3607,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_TEXT;
 	}
-#line 3621 "ext/date/lib/parse_date.c"
+#line 3611 "ext/date/lib/parse_date.c"
 yy82:
 	YYDEBUG(82, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -4132,7 +4122,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	}
 	if (yych == '.') goto yy289;
 	YYDEBUG(114, *YYCURSOR);
-#line 1221 "ext/date/lib/parse_date.re"
+#line 1211 "ext/date/lib/parse_date.re"
 	{
 		timelib_ull i;
 
@@ -4157,7 +4147,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_RELATIVE;
 	}
-#line 4161 "ext/date/lib/parse_date.c"
+#line 4151 "ext/date/lib/parse_date.c"
 yy115:
 	YYDEBUG(115, *YYCURSOR);
 	++YYCURSOR;
@@ -5883,7 +5873,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	}
 yy177:
 	YYDEBUG(177, *YYCURSOR);
-#line 1387 "ext/date/lib/parse_date.re"
+#line 1377 "ext/date/lib/parse_date.re"
 	{
 		int tz_not_found;
 		DEBUG_OUTPUT("timetiny24 | timeshort24 | timelong24 | iso8601long");
@@ -5910,7 +5900,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_TIME24_WITH_ZONE;
 	}
-#line 5914 "ext/date/lib/parse_date.c"
+#line 5904 "ext/date/lib/parse_date.c"
 yy178:
 	YYDEBUG(178, *YYCURSOR);
 	yyaccept = 4;
@@ -6939,7 +6929,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	}
 yy224:
 	YYDEBUG(224, *YYCURSOR);
-#line 1481 "ext/date/lib/parse_date.re"
+#line 1471 "ext/date/lib/parse_date.re"
 	{
 		int length = 0;
 		DEBUG_OUTPUT("americanshort | american");
@@ -6954,7 +6944,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_AMERICAN;
 	}
-#line 6958 "ext/date/lib/parse_date.c"
+#line 6948 "ext/date/lib/parse_date.c"
 yy225:
 	YYDEBUG(225, *YYCURSOR);
 	yyaccept = 5;
@@ -7197,7 +7187,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	if (yych <= '9') goto yy431;
 yy251:
 	YYDEBUG(251, *YYCURSOR);
-#line 1563 "ext/date/lib/parse_date.re"
+#line 1553 "ext/date/lib/parse_date.re"
 	{
 		int length = 0;
 		DEBUG_OUTPUT("datefull");
@@ -7211,7 +7201,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_FULL;
 	}
-#line 7215 "ext/date/lib/parse_date.c"
+#line 7205 "ext/date/lib/parse_date.c"
 yy252:
 	YYDEBUG(252, *YYCURSOR);
 	yyaccept = 3;
@@ -7325,7 +7315,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	if (yych == 'e') goto yy440;
 yy260:
 	YYDEBUG(260, *YYCURSOR);
-#line 1968 "ext/date/lib/parse_date.re"
+#line 1958 "ext/date/lib/parse_date.re"
 	{
 		timelib_ull i;
 		DEBUG_OUTPUT("relative");
@@ -7340,7 +7330,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_RELATIVE;
 	}
-#line 7344 "ext/date/lib/parse_date.c"
+#line 7334 "ext/date/lib/parse_date.c"
 yy261:
 	YYDEBUG(261, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -7786,7 +7776,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	if (yych <= '9') goto yy471;
 yy290:
 	YYDEBUG(290, *YYCURSOR);
-#line 1247 "ext/date/lib/parse_date.re"
+#line 1237 "ext/date/lib/parse_date.re"
 	{
 		timelib_sll i;
 		timelib_ull us;
@@ -7825,7 +7815,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_RELATIVE;
 	}
-#line 7829 "ext/date/lib/parse_date.c"
+#line 7819 "ext/date/lib/parse_date.c"
 yy291:
 	YYDEBUG(291, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -7850,7 +7840,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	}
 yy293:
 	YYDEBUG(293, *YYCURSOR);
-#line 1809 "ext/date/lib/parse_date.re"
+#line 1799 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("ago");
 		TIMELIB_INIT;
@@ -7870,7 +7860,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_AGO;
 	}
-#line 7874 "ext/date/lib/parse_date.c"
+#line 7864 "ext/date/lib/parse_date.c"
 yy294:
 	YYDEBUG(294, *YYCURSOR);
 	yyaccept = 7;
@@ -7909,7 +7899,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	}
 yy295:
 	YYDEBUG(295, *YYCURSOR);
-#line 1889 "ext/date/lib/parse_date.re"
+#line 1879 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("monthtext");
 		TIMELIB_INIT;
@@ -7918,7 +7908,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_TEXT;
 	}
-#line 7922 "ext/date/lib/parse_date.c"
+#line 7912 "ext/date/lib/parse_date.c"
 yy296:
 	YYDEBUG(296, *YYCURSOR);
 	yyaccept = 7;
@@ -8493,7 +8483,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	}
 yy315:
 	YYDEBUG(315, *YYCURSOR);
-#line 1830 "ext/date/lib/parse_date.re"
+#line 1820 "ext/date/lib/parse_date.re"
 	{
 		const timelib_relunit* relunit;
 		DEBUG_OUTPUT("daytext");
@@ -8510,7 +8500,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_WEEKDAY;
 	}
-#line 8514 "ext/date/lib/parse_date.c"
+#line 8504 "ext/date/lib/parse_date.c"
 yy316:
 	YYDEBUG(316, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -8778,7 +8768,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	}
 yy325:
 	YYDEBUG(325, *YYCURSOR);
-#line 1632 "ext/date/lib/parse_date.re"
+#line 1622 "ext/date/lib/parse_date.re"
 	{
 		int length = 0;
 		DEBUG_OUTPUT("datetextual | datenoyear");
@@ -8791,7 +8781,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_TEXT;
 	}
-#line 8795 "ext/date/lib/parse_date.c"
+#line 8785 "ext/date/lib/parse_date.c"
 yy326:
 	YYDEBUG(326, *YYCURSOR);
 	yyaccept = 10;
@@ -9485,7 +9475,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	}
 yy351:
 	YYDEBUG(351, *YYCURSOR);
-#line 1178 "ext/date/lib/parse_date.re"
+#line 1168 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("now");
 		TIMELIB_INIT;
@@ -9493,7 +9483,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_RELATIVE;
 	}
-#line 9497 "ext/date/lib/parse_date.c"
+#line 9487 "ext/date/lib/parse_date.c"
 yy352:
 	YYDEBUG(352, *YYCURSOR);
 	yyaccept = 2;
@@ -10996,7 +10986,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	}
 yy420:
 	YYDEBUG(420, *YYCURSOR);
-#line 1415 "ext/date/lib/parse_date.re"
+#line 1405 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("gnunocolon");
 		TIMELIB_INIT;
@@ -11018,7 +11008,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_GNU_NOCOLON;
 	}
-#line 11022 "ext/date/lib/parse_date.c"
+#line 11012 "ext/date/lib/parse_date.c"
 yy421:
 	YYDEBUG(421, *YYCURSOR);
 	yyaccept = 13;
@@ -11099,7 +11089,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	}
 yy422:
 	YYDEBUG(422, *YYCURSOR);
-#line 1800 "ext/date/lib/parse_date.re"
+#line 1790 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("year4");
 		TIMELIB_INIT;
@@ -11107,7 +11097,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_CLF;
 	}
-#line 11111 "ext/date/lib/parse_date.c"
+#line 11101 "ext/date/lib/parse_date.c"
 yy423:
 	YYDEBUG(423, *YYCURSOR);
 	yyaccept = 3;
@@ -11714,7 +11704,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	YYDEBUG(456, *YYCURSOR);
 	++YYCURSOR;
 	YYDEBUG(457, *YYCURSOR);
-#line 1349 "ext/date/lib/parse_date.re"
+#line 1339 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("timetiny12 | timeshort12 | timelong12");
 		TIMELIB_INIT;
@@ -11731,7 +11721,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_TIME12;
 	}
-#line 11735 "ext/date/lib/parse_date.c"
+#line 11725 "ext/date/lib/parse_date.c"
 yy458:
 	YYDEBUG(458, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -13058,7 +13048,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	}
 yy526:
 	YYDEBUG(526, *YYCURSOR);
-#line 1187 "ext/date/lib/parse_date.re"
+#line 1177 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("noon");
 		TIMELIB_INIT;
@@ -13069,7 +13059,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_RELATIVE;
 	}
-#line 13073 "ext/date/lib/parse_date.c"
+#line 13063 "ext/date/lib/parse_date.c"
 yy527:
 	YYDEBUG(527, *YYCURSOR);
 	yyaccept = 2;
@@ -14115,7 +14105,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	}
 yy567:
 	YYDEBUG(567, *YYCURSOR);
-#line 1549 "ext/date/lib/parse_date.re"
+#line 1539 "ext/date/lib/parse_date.re"
 	{
 		int length = 0;
 		DEBUG_OUTPUT("gnudateshort");
@@ -14128,7 +14118,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_ISO_DATE;
 	}
-#line 14132 "ext/date/lib/parse_date.c"
+#line 14122 "ext/date/lib/parse_date.c"
 yy568:
 	YYDEBUG(568, *YYCURSOR);
 	yyaccept = 15;
@@ -14579,7 +14569,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	}
 yy600:
 	YYDEBUG(600, *YYCURSOR);
-#line 1618 "ext/date/lib/parse_date.re"
+#line 1608 "ext/date/lib/parse_date.re"
 	{
 		int length = 0;
 		DEBUG_OUTPUT("datenodayrev");
@@ -14592,7 +14582,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_NO_DAY;
 	}
-#line 14596 "ext/date/lib/parse_date.c"
+#line 14586 "ext/date/lib/parse_date.c"
 yy601:
 	YYDEBUG(601, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -15967,7 +15957,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	YYDEBUG(696, *YYCURSOR);
 	++YYCURSOR;
 	YYDEBUG(697, *YYCURSOR);
-#line 1604 "ext/date/lib/parse_date.re"
+#line 1594 "ext/date/lib/parse_date.re"
 	{
 		int length = 0;
 		DEBUG_OUTPUT("datenoday");
@@ -15980,7 +15970,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_NO_DAY;
 	}
-#line 15984 "ext/date/lib/parse_date.c"
+#line 15974 "ext/date/lib/parse_date.c"
 yy698:
 	YYDEBUG(698, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -16541,7 +16531,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	}
 yy722:
 	YYDEBUG(722, *YYCURSOR);
-#line 1199 "ext/date/lib/parse_date.re"
+#line 1189 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("midnight | today");
 		TIMELIB_INIT;
@@ -16550,7 +16540,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_RELATIVE;
 	}
-#line 16554 "ext/date/lib/parse_date.c"
+#line 16544 "ext/date/lib/parse_date.c"
 yy723:
 	YYDEBUG(723, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -16860,7 +16850,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	if (yych <= '9') goto yy897;
 yy739:
 	YYDEBUG(739, *YYCURSOR);
-#line 1590 "ext/date/lib/parse_date.re"
+#line 1580 "ext/date/lib/parse_date.re"
 	{
 		int length = 0;
 		DEBUG_OUTPUT("pointed date YY");
@@ -16873,7 +16863,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_FULL_POINTED;
 	}
-#line 16877 "ext/date/lib/parse_date.c"
+#line 16867 "ext/date/lib/parse_date.c"
 yy740:
 	YYDEBUG(740, *YYCURSOR);
 	yyaccept = 15;
@@ -16985,7 +16975,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	}
 yy752:
 	YYDEBUG(752, *YYCURSOR);
-#line 1535 "ext/date/lib/parse_date.re"
+#line 1525 "ext/date/lib/parse_date.re"
 	{
 		int length = 0;
 		DEBUG_OUTPUT("gnudateshorter");
@@ -16998,7 +16988,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_ISO_DATE;
 	}
-#line 17002 "ext/date/lib/parse_date.c"
+#line 16992 "ext/date/lib/parse_date.c"
 yy753:
 	YYDEBUG(753, *YYCURSOR);
 	yyaccept = 18;
@@ -17247,7 +17237,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	}
 yy777:
 	YYDEBUG(777, *YYCURSOR);
-#line 1461 "ext/date/lib/parse_date.re"
+#line 1451 "ext/date/lib/parse_date.re"
 	{
 		int tz_not_found;
 		DEBUG_OUTPUT("iso8601nocolon");
@@ -17266,7 +17256,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_ISO_NOCOLON;
 	}
-#line 17270 "ext/date/lib/parse_date.c"
+#line 17260 "ext/date/lib/parse_date.c"
 yy778:
 	YYDEBUG(778, *YYCURSOR);
 	yyaccept = 19;
@@ -18494,7 +18484,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	}
 yy849:
 	YYDEBUG(849, *YYCURSOR);
-#line 1938 "ext/date/lib/parse_date.re"
+#line 1928 "ext/date/lib/parse_date.re"
 	{
 		int tz_not_found;
 		DEBUG_OUTPUT("dateshortwithtimeshort | dateshortwithtimelong | dateshortwithtimelongtz");
@@ -18523,7 +18513,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_SHORTDATE_WITH_TIME;
 	}
-#line 18527 "ext/date/lib/parse_date.c"
+#line 18517 "ext/date/lib/parse_date.c"
 yy850:
 	YYDEBUG(850, *YYCURSOR);
 	yyaccept = 20;
@@ -19567,7 +19557,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	}
 yy926:
 	YYDEBUG(926, *YYCURSOR);
-#line 1696 "ext/date/lib/parse_date.re"
+#line 1686 "ext/date/lib/parse_date.re"
 	{
 		int length = 0;
 		DEBUG_OUTPUT("pgydotd");
@@ -19580,7 +19570,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_PG_YEARDAY;
 	}
-#line 19584 "ext/date/lib/parse_date.c"
+#line 19574 "ext/date/lib/parse_date.c"
 yy927:
 	YYDEBUG(927, *YYCURSOR);
 	yyaccept = 21;
@@ -19834,7 +19824,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	if (yych <= '7') goto yy1059;
 yy942:
 	YYDEBUG(942, *YYCURSOR);
-#line 1729 "ext/date/lib/parse_date.re"
+#line 1719 "ext/date/lib/parse_date.re"
 	{
 		timelib_sll w, d;
 		DEBUG_OUTPUT("isoweek");
@@ -19852,7 +19842,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_ISO_WEEK;
 	}
-#line 19856 "ext/date/lib/parse_date.c"
+#line 19846 "ext/date/lib/parse_date.c"
 yy943:
 	YYDEBUG(943, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -20328,7 +20318,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	if (yych == 'e') goto yy1094;
 yy982:
 	YYDEBUG(982, *YYCURSOR);
-#line 1872 "ext/date/lib/parse_date.re"
+#line 1862 "ext/date/lib/parse_date.re"
 	{
 		timelib_sll i;
 		int         behavior = 0;
@@ -20344,7 +20334,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_RELATIVE;
 	}
-#line 20348 "ext/date/lib/parse_date.c"
+#line 20338 "ext/date/lib/parse_date.c"
 yy983:
 	YYDEBUG(983, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -20691,7 +20681,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	YYDEBUG(1020, *YYCURSOR);
 	++YYCURSOR;
 	YYDEBUG(1021, *YYCURSOR);
-#line 1578 "ext/date/lib/parse_date.re"
+#line 1568 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("pointed date YYYY");
 		TIMELIB_INIT;
@@ -20702,7 +20692,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_FULL_POINTED;
 	}
-#line 20706 "ext/date/lib/parse_date.c"
+#line 20696 "ext/date/lib/parse_date.c"
 yy1022:
 	YYDEBUG(1022, *YYCURSOR);
 	++YYCURSOR;
@@ -20731,7 +20721,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	}
 yy1025:
 	YYDEBUG(1025, *YYCURSOR);
-#line 1509 "ext/date/lib/parse_date.re"
+#line 1499 "ext/date/lib/parse_date.re"
 	{
 		int length = 0;
 		DEBUG_OUTPUT("iso8601date2");
@@ -20744,7 +20734,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_ISO_DATE;
 	}
-#line 20748 "ext/date/lib/parse_date.c"
+#line 20738 "ext/date/lib/parse_date.c"
 yy1026:
 	YYDEBUG(1026, *YYCURSOR);
 	yyaccept = 15;
@@ -20964,7 +20954,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	}
 yy1043:
 	YYDEBUG(1043, *YYCURSOR);
-#line 1497 "ext/date/lib/parse_date.re"
+#line 1487 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("iso8601date4 | iso8601date2 | iso8601dateslash | dateslash");
 		TIMELIB_INIT;
@@ -20975,7 +20965,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_ISO_DATE;
 	}
-#line 20979 "ext/date/lib/parse_date.c"
+#line 20969 "ext/date/lib/parse_date.c"
 yy1044:
 	YYDEBUG(1044, *YYCURSOR);
 	yyaccept = 26;
@@ -21090,7 +21080,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	}
 yy1048:
 	YYDEBUG(1048, *YYCURSOR);
-#line 1658 "ext/date/lib/parse_date.re"
+#line 1648 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("datenocolon");
 		TIMELIB_INIT;
@@ -21101,7 +21091,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_DATE_NOCOLON;
 	}
-#line 21105 "ext/date/lib/parse_date.c"
+#line 21095 "ext/date/lib/parse_date.c"
 yy1049:
 	YYDEBUG(1049, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -21171,7 +21161,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	YYDEBUG(1059, *YYCURSOR);
 	++YYCURSOR;
 	YYDEBUG(1060, *YYCURSOR);
-#line 1710 "ext/date/lib/parse_date.re"
+#line 1700 "ext/date/lib/parse_date.re"
 	{
 		timelib_sll w, d;
 		DEBUG_OUTPUT("isoweekday");
@@ -21189,7 +21179,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_ISO_WEEK;
 	}
-#line 21193 "ext/date/lib/parse_date.c"
+#line 21183 "ext/date/lib/parse_date.c"
 yy1061:
 	YYDEBUG(1061, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -21252,7 +21242,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	if (yych <= '9') goto yy1143;
 yy1070:
 	YYDEBUG(1070, *YYCURSOR);
-#line 1748 "ext/date/lib/parse_date.re"
+#line 1738 "ext/date/lib/parse_date.re"
 	{
 		int length = 0;
 		DEBUG_OUTPUT("pgtextshort");
@@ -21265,7 +21255,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_PG_TEXT;
 	}
-#line 21269 "ext/date/lib/parse_date.c"
+#line 21259 "ext/date/lib/parse_date.c"
 yy1071:
 	YYDEBUG(1071, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -21738,7 +21728,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	++YYCURSOR;
 yy1107:
 	YYDEBUG(1107, *YYCURSOR);
-#line 1209 "ext/date/lib/parse_date.re"
+#line 1199 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("tomorrow");
 		TIMELIB_INIT;
@@ -21749,7 +21739,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_RELATIVE;
 	}
-#line 21753 "ext/date/lib/parse_date.c"
+#line 21743 "ext/date/lib/parse_date.c"
 yy1108:
 	YYDEBUG(1108, *YYCURSOR);
 	yyaccept = 28;
@@ -22086,7 +22076,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	YYDEBUG(1140, *YYCURSOR);
 	++YYCURSOR;
 	YYDEBUG(1141, *YYCURSOR);
-#line 1762 "ext/date/lib/parse_date.re"
+#line 1752 "ext/date/lib/parse_date.re"
 	{
 		int length = 0;
 		DEBUG_OUTPUT("pgtextreverse");
@@ -22099,7 +22089,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_PG_TEXT;
 	}
-#line 22103 "ext/date/lib/parse_date.c"
+#line 22093 "ext/date/lib/parse_date.c"
 yy1142:
 	YYDEBUG(1142, *YYCURSOR);
 	++YYCURSOR;
@@ -22143,7 +22133,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	}
 yy1145:
 	YYDEBUG(1145, *YYCURSOR);
-#line 1304 "ext/date/lib/parse_date.re"
+#line 1294 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("backof | frontof");
 		TIMELIB_INIT;
@@ -22165,7 +22155,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_LF_DAY_OF_MONTH;
 	}
-#line 22169 "ext/date/lib/parse_date.c"
+#line 22159 "ext/date/lib/parse_date.c"
 yy1146:
 	YYDEBUG(1146, *YYCURSOR);
 	yyaccept = 29;
@@ -22489,7 +22479,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	}
 yy1172:
 	YYDEBUG(1172, *YYCURSOR);
-#line 1848 "ext/date/lib/parse_date.re"
+#line 1838 "ext/date/lib/parse_date.re"
 	{
 		timelib_sll i;
 		int         behavior = 0;
@@ -22512,7 +22502,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_RELATIVE;
 	}
-#line 22516 "ext/date/lib/parse_date.c"
+#line 22506 "ext/date/lib/parse_date.c"
 yy1173:
 	YYDEBUG(1173, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -22524,7 +22514,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	++YYCURSOR;
 yy1175:
 	YYDEBUG(1175, *YYCURSOR);
-#line 1166 "ext/date/lib/parse_date.re"
+#line 1156 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("yesterday");
 		TIMELIB_INIT;
@@ -22535,7 +22525,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_RELATIVE;
 	}
-#line 22539 "ext/date/lib/parse_date.c"
+#line 22529 "ext/date/lib/parse_date.c"
 yy1176:
 	YYDEBUG(1176, *YYCURSOR);
 	yyaccept = 31;
@@ -23028,7 +23018,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	YYDEBUG(1222, *YYCURSOR);
 	++YYCURSOR;
 	YYDEBUG(1223, *YYCURSOR);
-#line 1914 "ext/date/lib/parse_date.re"
+#line 1904 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("dateshortwithtimeshort12 | dateshortwithtimelong12");
 		TIMELIB_INIT;
@@ -23051,7 +23041,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_SHORTDATE_WITH_TIME;
 	}
-#line 23055 "ext/date/lib/parse_date.c"
+#line 23045 "ext/date/lib/parse_date.c"
 yy1224:
 	YYDEBUG(1224, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -23553,7 +23543,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	YYDEBUG(1268, *YYCURSOR);
 	++YYCURSOR;
 	YYDEBUG(1269, *YYCURSOR);
-#line 1327 "ext/date/lib/parse_date.re"
+#line 1317 "ext/date/lib/parse_date.re"
 	{
 		timelib_sll i;
 		int         behavior = 0;
@@ -23574,7 +23564,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_WEEK_DAY_OF_MONTH;
 	}
-#line 23578 "ext/date/lib/parse_date.c"
+#line 23568 "ext/date/lib/parse_date.c"
 yy1270:
 	YYDEBUG(1270, *YYCURSOR);
 	yyaccept = 24;
@@ -23621,7 +23611,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	YYDEBUG(1273, *YYCURSOR);
 	++YYCURSOR;
 	YYDEBUG(1274, *YYCURSOR);
-#line 1287 "ext/date/lib/parse_date.re"
+#line 1277 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("firstdayof | lastdayof");
 		TIMELIB_INIT;
@@ -23637,12 +23627,12 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_LF_DAY_OF_MONTH;
 	}
-#line 23641 "ext/date/lib/parse_date.c"
+#line 23631 "ext/date/lib/parse_date.c"
 yy1275:
 	YYDEBUG(1275, *YYCURSOR);
 	++YYCURSOR;
 	YYDEBUG(1276, *YYCURSOR);
-#line 1523 "ext/date/lib/parse_date.re"
+#line 1513 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("iso8601datex");
 		TIMELIB_INIT;
@@ -23653,7 +23643,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_ISO_DATE;
 	}
-#line 23657 "ext/date/lib/parse_date.c"
+#line 23647 "ext/date/lib/parse_date.c"
 yy1277:
 	YYDEBUG(1277, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -23756,7 +23746,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	YYDEBUG(1290, *YYCURSOR);
 	++YYCURSOR;
 	YYDEBUG(1291, *YYCURSOR);
-#line 1367 "ext/date/lib/parse_date.re"
+#line 1357 "ext/date/lib/parse_date.re"
 	{
 		DEBUG_OUTPUT("mssqltime");
 		TIMELIB_INIT;
@@ -23775,7 +23765,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_TIME24_WITH_ZONE;
 	}
-#line 23779 "ext/date/lib/parse_date.c"
+#line 23769 "ext/date/lib/parse_date.c"
 yy1292:
 	YYDEBUG(1292, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -24199,7 +24189,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	if (yych <= '9') goto yy1331;
 yy1329:
 	YYDEBUG(1329, *YYCURSOR);
-#line 1670 "ext/date/lib/parse_date.re"
+#line 1660 "ext/date/lib/parse_date.re"
 	{
 		int tz_not_found;
 		DEBUG_OUTPUT("xmlrpc | xmlrpcnocolon | soap | wddx | exif");
@@ -24224,7 +24214,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_XMLRPC_SOAP;
 	}
-#line 24228 "ext/date/lib/parse_date.c"
+#line 24218 "ext/date/lib/parse_date.c"
 yy1330:
 	YYDEBUG(1330, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -24594,7 +24584,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	if (yych <= ':') goto yy1383;
 yy1375:
 	YYDEBUG(1375, *YYCURSOR);
-#line 1776 "ext/date/lib/parse_date.re"
+#line 1766 "ext/date/lib/parse_date.re"
 	{
 		int tz_not_found;
 		DEBUG_OUTPUT("clf");
@@ -24617,7 +24607,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 		TIMELIB_DEINIT;
 		return TIMELIB_CLF;
 	}
-#line 24621 "ext/date/lib/parse_date.c"
+#line 24611 "ext/date/lib/parse_date.c"
 yy1376:
 	YYDEBUG(1376, *YYCURSOR);
 	yyaccept = 33;
@@ -24849,7 +24839,7 @@ static int scan(Scanner *s, timelib_tz_get_wrapper tz_get_wrapper)
 	if (yych == ':') goto yy1286;
 	goto yy1329;
 }
-#line 2004 "ext/date/lib/parse_date.re"
+#line 1994 "ext/date/lib/parse_date.re"
 
 }
 
@@ -24870,7 +24860,7 @@ timelib_time *timelib_strtotime(const char *s, size_t len, timelib_error_contain
 	in.errors->error_messages = NULL;
 
 	if (len > 0) {
-		while (isspace((unsigned char)*s) && s < e) {
+		while (isspace((unsigned char)*s) && s <= e) {
 			s++;
 		}
 		while (isspace((unsigned char)*e) && e > s) {
diff --git a/ext/date/lib/parse_date.re b/ext/date/lib/parse_date.re
index 07d9c0e73488..15a96f2af95b 100644
--- a/ext/date/lib/parse_date.re
+++ b/ext/date/lib/parse_date.re
@@ -32,16 +32,6 @@
 #include <assert.h>
 #include <limits.h>
 
-#if defined(_MSC_VER)
-# define strtoll(s, f, b) _atoi64(s)
-#elif !defined(HAVE_STRTOLL)
-# if defined(HAVE_ATOLL)
-#  define strtoll(s, f, b) atoll(s)
-# else
-#  define strtoll(s, f, b) strtol(s, f, b)
-# endif
-#endif
-
 #define EOI      257
 #define TIME     258
 #define DATE     259
diff --git a/ext/date/lib/parse_iso_intervals.c b/ext/date/lib/parse_iso_intervals.c
index 5dcbfe350639..8f9221e6aa08 100644
--- a/ext/date/lib/parse_iso_intervals.c
+++ b/ext/date/lib/parse_iso_intervals.c
@@ -1,4 +1,4 @@
-/* Generated by re2c 1.0.3 on Mon Sep 15 10:40:09 2025 */
+/* Generated by re2c 1.0.3 on Wed Aug  5 11:34:39 2026 */
 #line 1 "ext/date/lib/parse_iso_intervals.re"
 /*
  * The MIT License (MIT)
@@ -29,16 +29,6 @@
 
 #include <ctype.h>
 
-#if defined(_MSC_VER)
-# define strtoll(s, f, b) _atoi64(s)
-#elif !defined(HAVE_STRTOLL)
-# if defined(HAVE_ATOLL)
-#  define strtoll(s, f, b) atoll(s)
-# else
-#  define strtoll(s, f, b) strtol(s, f, b)
-# endif
-#endif
-
 #define EOI      257
 
 #define TIMELIB_PERIOD  260
@@ -176,11 +166,11 @@ static int scan(Scanner *s)
 std:
 	s->tok = cursor;
 	s->len = 0;
-#line 204 "ext/date/lib/parse_iso_intervals.re"
+#line 194 "ext/date/lib/parse_iso_intervals.re"
 
 
 
-#line 184 "ext/date/lib/parse_iso_intervals.c"
+#line 174 "ext/date/lib/parse_iso_intervals.c"
 {
 	YYCTYPE yych;
 	unsigned int yyaccept = 0;
@@ -247,32 +237,32 @@ static int scan(Scanner *s)
 	YYDEBUG(2, *YYCURSOR);
 	++YYCURSOR;
 	YYDEBUG(3, *YYCURSOR);
-#line 311 "ext/date/lib/parse_iso_intervals.re"
+#line 301 "ext/date/lib/parse_iso_intervals.re"
 	{
 		s->pos = cursor; s->line++;
 		goto std;
 	}
-#line 256 "ext/date/lib/parse_iso_intervals.c"
+#line 246 "ext/date/lib/parse_iso_intervals.c"
 yy4:
 	YYDEBUG(4, *YYCURSOR);
 	++YYCURSOR;
 yy5:
 	YYDEBUG(5, *YYCURSOR);
-#line 317 "ext/date/lib/parse_iso_intervals.re"
+#line 307 "ext/date/lib/parse_iso_intervals.re"
 	{
 		add_error(s, "Unexpected character");
 		goto std;
 	}
-#line 267 "ext/date/lib/parse_iso_intervals.c"
+#line 257 "ext/date/lib/parse_iso_intervals.c"
 yy6:
 	YYDEBUG(6, *YYCURSOR);
 	++YYCURSOR;
 	YYDEBUG(7, *YYCURSOR);
-#line 306 "ext/date/lib/parse_iso_intervals.re"
+#line 296 "ext/date/lib/parse_iso_intervals.re"
 	{
 		goto std;
 	}
-#line 276 "ext/date/lib/parse_iso_intervals.c"
+#line 266 "ext/date/lib/parse_iso_intervals.c"
 yy8:
 	YYDEBUG(8, *YYCURSOR);
 	yyaccept = 0;
@@ -289,7 +279,7 @@ static int scan(Scanner *s)
 	if (yych == 'T') goto yy15;
 yy10:
 	YYDEBUG(10, *YYCURSOR);
-#line 244 "ext/date/lib/parse_iso_intervals.re"
+#line 234 "ext/date/lib/parse_iso_intervals.re"
 	{
 		timelib_sll nr;
 		int         in_time = 0;
@@ -330,7 +320,7 @@ static int scan(Scanner *s)
 		TIMELIB_DEINIT;
 		return TIMELIB_PERIOD;
 	}
-#line 334 "ext/date/lib/parse_iso_intervals.c"
+#line 324 "ext/date/lib/parse_iso_intervals.c"
 yy11:
 	YYDEBUG(11, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -389,7 +379,7 @@ static int scan(Scanner *s)
 		goto yy16;
 	}
 	YYDEBUG(18, *YYCURSOR);
-#line 209 "ext/date/lib/parse_iso_intervals.re"
+#line 199 "ext/date/lib/parse_iso_intervals.re"
 	{
 		DEBUG_OUTPUT("recurrences");
 		TIMELIB_INIT;
@@ -399,7 +389,7 @@ static int scan(Scanner *s)
 		s->have_recurrences = 1;
 		return TIMELIB_PERIOD;
 	}
-#line 403 "ext/date/lib/parse_iso_intervals.c"
+#line 393 "ext/date/lib/parse_iso_intervals.c"
 yy19:
 	YYDEBUG(19, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -894,7 +884,7 @@ static int scan(Scanner *s)
 	YYDEBUG(89, *YYCURSOR);
 	++YYCURSOR;
 	YYDEBUG(90, *YYCURSOR);
-#line 220 "ext/date/lib/parse_iso_intervals.re"
+#line 210 "ext/date/lib/parse_iso_intervals.re"
 	{
 		timelib_time *current;
 
@@ -917,7 +907,7 @@ static int scan(Scanner *s)
 		TIMELIB_DEINIT;
 		return TIMELIB_ISO_DATE;
 	}
-#line 921 "ext/date/lib/parse_iso_intervals.c"
+#line 911 "ext/date/lib/parse_iso_intervals.c"
 yy91:
 	YYDEBUG(91, *YYCURSOR);
 	yych = *++YYCURSOR;
@@ -937,7 +927,7 @@ static int scan(Scanner *s)
 	YYDEBUG(95, *YYCURSOR);
 	++YYCURSOR;
 	YYDEBUG(96, *YYCURSOR);
-#line 286 "ext/date/lib/parse_iso_intervals.re"
+#line 276 "ext/date/lib/parse_iso_intervals.re"
 	{
 		DEBUG_OUTPUT("combinedrep");
 		TIMELIB_INIT;
@@ -956,9 +946,9 @@ static int scan(Scanner *s)
 		TIMELIB_DEINIT;
 		return TIMELIB_PERIOD;
 	}
-#line 960 "ext/date/lib/parse_iso_intervals.c"
+#line 950 "ext/date/lib/parse_iso_intervals.c"
 }
-#line 321 "ext/date/lib/parse_iso_intervals.re"
+#line 311 "ext/date/lib/parse_iso_intervals.re"
 
 }
 #ifdef PHP_WIN32
diff --git a/ext/date/lib/parse_iso_intervals.re b/ext/date/lib/parse_iso_intervals.re
index 009420077513..7757cd5edc8b 100644
--- a/ext/date/lib/parse_iso_intervals.re
+++ b/ext/date/lib/parse_iso_intervals.re
@@ -27,16 +27,6 @@
 
 #include <ctype.h>
 
-#if defined(_MSC_VER)
-# define strtoll(s, f, b) _atoi64(s)
-#elif !defined(HAVE_STRTOLL)
-# if defined(HAVE_ATOLL)
-#  define strtoll(s, f, b) atoll(s)
-# else
-#  define strtoll(s, f, b) strtol(s, f, b)
-# endif
-#endif
-
 #define EOI      257
 
 #define TIMELIB_PERIOD  260
diff --git a/ext/date/lib/parse_tz.c b/ext/date/lib/parse_tz.c
index c7f93580d725..c3cd79843b68 100644
--- a/ext/date/lib/parse_tz.c
+++ b/ext/date/lib/parse_tz.c
@@ -211,6 +211,7 @@ static int read_64bit_transitions(const unsigned char **tzf, timelib_tzinfo *tz)
 			buffer[i] = timelib_conv_int64_signed(buffer[i]);
 			/* Sanity check to see whether TS is just increasing */
 			if (i > 0 && !(buffer[i] > buffer[i - 1])) {
+				timelib_free(buffer);
 				return TIMELIB_ERROR_CORRUPT_TRANSITIONS_DONT_INCREASE;
 			}
 		}
@@ -543,7 +544,7 @@ void timelib_dump_tzinfo(timelib_tzinfo *tz)
 		timelib_free(trans_str);
 	}
 	for (i = 0; i < tz->bit64.leapcnt; i++) {
-		date_str = format_ut_time(tz->trans[i], tz);
+		date_str = format_ut_time(tz->leap_times[i].trans, tz);
 		printf (
 			"%s (%20ld) = %d\n",
 			date_str,
diff --git a/ext/date/lib/timelib.c b/ext/date/lib/timelib.c
index faf383a5fa12..787e85334167 100644
--- a/ext/date/lib/timelib.c
+++ b/ext/date/lib/timelib.c
@@ -35,7 +35,7 @@
 
 #define TIMELIB_LLABS(y) (y < 0 ? (y * -1) : y)
 
-const char *timelib_error_messages[10] = {
+const char *timelib_error_messages[18] = {
 	"No error",
 	"Cannot allocate buffer for parsing",
 	"Corrupt tzfile: The transitions in the file don't always increase",
@@ -45,7 +45,15 @@ const char *timelib_error_messages[10] = {
 	"No timezone with this name could be found",
 	"A 'slim' timezone file has been detected",
 	"The embedded POSIX string is not valid",
-	"The embedded POSIX string is empty"
+	"The embedded POSIX string is empty",
+	"Seconds value out of range",
+	"Nanoseconds value out of range",
+	"Division by zero",
+	"Integer Overflow",
+	"The ISO8601 duration string may only contain the period (P) aspect",
+	"The ISO8601 duration string is missing the perido (P) aspect",
+	"The ISO8601 duration string may only contain the time (T) aspect",
+	"The ISO8601 duration string could not be parsed",
 };
 
 const char *timelib_get_error_message(int error_code)
diff --git a/ext/date/lib/timelib.h b/ext/date/lib/timelib.h
index d08aa77ea5e5..97f76f048d7b 100644
--- a/ext/date/lib/timelib.h
+++ b/ext/date/lib/timelib.h
@@ -30,83 +30,17 @@
 # include "timelib_config.h"
 #endif
 
-#define TIMELIB_VERSION 202217
-#define TIMELIB_EXTENDED_VERSION 20221701
-#define TIMELIB_ASCII_VERSION "2022.17"
+#define TIMELIB_VERSION 202601
+#define TIMELIB_EXTENDED_VERSION 20260101
+#define TIMELIB_ASCII_VERSION "2026.01"
 
 #include <stdlib.h>
 #include <stdbool.h>
 #include <limits.h>
 #include <inttypes.h>
 
-# ifndef HAVE_INT32_T
-#  if SIZEOF_INT == 4
-typedef int int32_t;
-#  elif SIZEOF_LONG == 4
-typedef long int int32_t;
-#  endif
-# endif
-
-# ifndef HAVE_UINT32_T
-#  if SIZEOF_INT == 4
-typedef unsigned int uint32_t;
-#  elif SIZEOF_LONG == 4
-typedef unsigned long int uint32_t;
-#  endif
-# endif
-
 #ifdef _WIN32
-# if _MSC_VER >= 1600
 # include <stdint.h>
-# endif
-# ifndef SIZEOF_INT
-#  define SIZEOF_INT 4
-# endif
-# ifndef SIZEOF_LONG
-#  define SIZEOF_LONG 4
-# endif
-# ifndef int32_t
-typedef __int32           int32_t;
-# endif
-# ifndef uint32_t
-typedef unsigned __int32  uint32_t;
-# endif
-# ifndef int64_t
-typedef __int64           int64_t;
-# endif
-# ifndef uint64_t
-typedef unsigned __int64  uint64_t;
-# endif
-# ifndef PRId32
-#  define PRId32       "I32d"
-# endif
-# ifndef PRIu32
-#  define PRIu32       "I32u"
-# endif
-# ifndef PRId64
-#  define PRId64       "I64d"
-# endif
-# ifndef PRIu64
-#  define PRIu64       "I64u"
-# endif
-# ifndef INT32_MAX
-#define INT32_MAX    _I32_MAX
-# endif
-# ifndef INT32_MIN
-#define INT32_MIN    ((int32_t)_I32_MIN)
-# endif
-# ifndef UINT32_MAX
-#define UINT32_MAX   _UI32_MAX
-# endif
-# ifndef INT64_MIN
-#define INT64_MIN    ((int64_t)_I64_MIN)
-# endif
-# ifndef INT64_MAX
-#define INT64_MAX    _I64_MAX
-# endif
-# ifndef UINT64_MAX
-#define UINT64_MAX   _UI64_MAX
-# endif
 #endif
 
 #if (defined(__x86_64__) || defined(__LP64__) || defined(_LP64) || defined(_WIN64)) && !defined(TIMELIB_FORCE_LONG32)
@@ -276,6 +210,12 @@ typedef struct _timelib_abbr_info {
 	int          dst;
 } timelib_abbr_info;
 
+typedef struct _timelib_duration {
+	timelib_ull  seconds;
+	uint32_t     nanoseconds;
+	bool         negative;
+} timelib_duration;
+
 #define TIMELIB_WARN_MASK                      0x1ff
 #define TIMELIB_ERR_MASK                       0x2ff
 
@@ -373,6 +313,8 @@ typedef struct _timelib_tzdb {
 #  define TIMELIB_USE_BUILTIN_STRNDUP 0
 #  define timelib_strndup strndup
 # endif
+#else
+# define TIMELIB_USE_BUILTIN_STRNDUP 0
 #endif
 
 #define TIMELIB_NONE             0x00
@@ -394,6 +336,14 @@ typedef struct _timelib_tzdb {
 #define TIMELIB_ERROR_SLIM_FILE                           0x07 /* Warns if the file is SLIM, but we can't read it */
 #define TIMELIB_ERROR_CORRUPT_POSIX_STRING                0x08
 #define TIMELIB_ERROR_EMPTY_POSIX_STRING                  0x09 /* Warns if the POSIX string is empty, but still produces results */
+#define TIMELIB_ERROR_SECONDS_OUT_OF_RANGE                0x0A /* Durations only allow 0..9223372035 */
+#define TIMELIB_ERROR_NANOSECONDS_OUT_OF_RANGE            0x0B /* Durations only allow 0..999999999 */
+#define TIMELIB_ERROR_DIVISION_BY_ZERO                    0x0C
+#define TIMELIB_ERROR_OVERFLOW                            0x0D
+#define TIMELIB_ERROR_DURATION_ONLY_PERIOD_ALLOWED        0x0E
+#define TIMELIB_ERROR_DURATION_MISSING_PERIOD             0x0F
+#define TIMELIB_ERROR_DURATION_DAYS_FOUND                 0x10
+#define TIMELIB_ERROR_ISO8601_DURATION_PARSE_FAILURE      0x11
 
 #ifdef __cplusplus
 extern "C" {
@@ -1097,6 +1047,149 @@ timelib_posix_str* timelib_parse_posix_str(const char *posix);
 void timelib_get_transitions_for_year(timelib_tzinfo *tz, timelib_sll year, timelib_posix_transitions *transitions);
 
 
+/* from duration.c */
+
+/* Returns a newly allocated timelib_duration struct upon success, or NULL
+ * upon failure (such as out of range for seconds/nanoseconds) with
+ * *error_code set to a value from the TIMELIB_ERROR_* set.
+ */
+timelib_duration *timelib_duration_ctor(
+	timelib_ull  seconds,
+	uint32_t     nanoseconds,
+	bool         negative,
+	int         *error_code
+);
+
+/* Updates 'duration' with the values of 'seconds', 'nanoseconds', and
+ * 'negative', after checking 'seconds' and 'nanoseconds' for their range. If
+ * either of them is out of range, it returns an error code from the
+ * TIMELIB_ERROR_* set. It also only sets 'negative' to true if 'seconds' and
+ * 'nanoseconds' aren't both NULL.
+ */
+int timelib_duration_ctor_static(
+	timelib_duration *duration,
+	timelib_ull       seconds,
+	uint32_t          nanoseconds,
+	bool              negative
+);
+
+/* Returns a newly allocated timelib_duration struct upon success, or NULL
+ * upon failure with *error set to a newly allocated error_message container
+ * (which you'll have to free). */
+timelib_duration *timelib_duration_create_from_iso8601string(
+	const char *string,
+	int        *error_code
+);
+
+/* Frees up memory allocated for the duration struct. You must not use it or
+ * its elements after calling this function. */
+void timelib_duration_dtor(timelib_duration *duration);
+
+/* Adds two durations together, and returns a newly allocated one, or NULL
+ * upon failure (such as out of range) with *error_code set to a value from
+ * the TIMELIB_ERROR_* set. */
+timelib_duration *timelib_duration_add(
+	const timelib_duration *original,
+	const timelib_duration *additional,
+	int                    *error_code
+);
+
+/* Adds two durations together, and updates the 'new_duration' argument with
+ * the calculated values. It returns an error code (from the TIMELIB_ERROR_*
+ * set), or TIMELIB_ERROR_NO_ERROR, if there was no error. */
+int timelib_duration_add_static(
+	timelib_duration       *new_duration,
+	const timelib_duration *original,
+	const timelib_duration *additional
+);
+
+/* Subtracts the second duration from the first one, and returns a newly
+ * allocated one, or NULL upon failure (such as out of range) with *error_code
+ * set to a value from the TIMELIB_ERROR_* set. */
+timelib_duration *timelib_duration_sub (
+	const timelib_duration *original,
+	const timelib_duration *minus,
+	int                    *error_code
+);
+
+/* Subtracts the second duration from the first one, and updates the
+ * 'new_duration' argument with the calculated values. It returns an error
+ * code (from the TIMELIB_ERROR_* set), or TIMELIB_ERROR_NO_ERROR, if there
+ * was no error. */
+int timelib_duration_sub_static(
+	timelib_duration       *new_duration,
+	const timelib_duration *original,
+	const timelib_duration *minus
+);
+
+/* Multiplies the duration with a certain integer factor. It returns a newly
+ * allocated duration, or NULL, upon failure (such as out of range) with
+ * *error_code set to a value from the TIMELIB_ERROR_* set. */
+timelib_duration *timelib_duration_mul (
+	const timelib_duration *original,
+	uint64_t                factor,
+	int                    *error_code
+);
+
+/* Multiplies the duration with a certain integer factor, and updates the
+ * 'new_duration' argument with the calculated values. It returns an error
+ * code (from the TIMELIB_ERROR_* set), or TIMELIB_ERROR_NO_ERROR, if there
+ * was no error. */
+int timelib_duration_mul_static(
+	timelib_duration       *new_duration,
+	const timelib_duration *original,
+	uint64_t                factor
+);
+
+/* Divides the duration with a certain integer divisor. It returns a newly
+ * allocated duration, or NULL upon failure (such as div-by-0) with
+ * *error_code set to a value from the TIMELIB_ERROR_* set. */
+timelib_duration *timelib_duration_div (
+	const timelib_duration *original,
+	uint64_t                divisor,
+	int                    *error_code
+);
+
+/* Divides the duration with a certain integer divisor, and updates the
+ * 'new_duration' argument with the calculated values. It returns an error
+ * code (from the TIMELIB_ERROR_* set), or TIMELIB_ERROR_NO_ERROR, if there
+ * was no error. */
+int timelib_duration_div_static(
+	timelib_duration       *new_duration,
+	const timelib_duration *original,
+	uint64_t                divisor
+);
+
+/* Switches the 'negate' flag of 'original' in a newly allocated duration, or
+ * NULL upon failure with *error_code set to a value from the TIMELIB_ERROR_*
+ * set */
+timelib_duration *timelib_duration_negate(
+	const timelib_duration *original,
+	int                    *error_code
+);
+
+/* Switches the 'negate' flag of 'original', and updates the 'new_duration'
+ * argument with the calculated value. It returns an error code (from the
+ * TIMELIB_ERROR_* set), or TIMELIB_ERROR_NO_ERROR, if there was no error. */
+int timelib_duration_negate_static(
+	timelib_duration       *new_duration,
+	const timelib_duration *original
+);
+
+/* Returns -1 if one is smaller than two, 0 if they're equal, and 1 if one is
+ * larger than two — IGNORING the negate flags */
+int timelib_duration_abs_compare(
+	const timelib_duration *one,
+	const timelib_duration *two
+);
+
+/* Returns -1 if one is smaller than two, 0 if they're equal, and 1 if one is
+ * larger than two. */
+int timelib_duration_compare(
+	const timelib_duration *one,
+	const timelib_duration *two
+);
+
 #ifdef __cplusplus
 } /* extern "C" */
 #endif
diff --git a/ext/date/lib/timelib_private.h b/ext/date/lib/timelib_private.h
index 42cbaa68dbbf..eece57421fd3 100644
--- a/ext/date/lib/timelib_private.h
+++ b/ext/date/lib/timelib_private.h
@@ -45,19 +45,17 @@
 #include <sys/types.h>
 #endif
 
-#if defined(HAVE_STDINT_H)
-# include <stdint.h>
-#endif
+#include <stdint.h>
 
-#if HAVE_UNISTD_H
+#if defined(HAVE_UNISTD_H)
 # include <unistd.h>
 #endif
 
-#if HAVE_IO_H
+#if defined(HAVE_IO_H)
 # include <io.h>
 #endif
 
-#if HAVE_DIRENT_H
+#if defined(HAVE_DIRENT_H)
 # include <dirent.h>
 #endif
 
@@ -89,6 +87,8 @@
 #define SECS_PER_DAY   86400
 #define SECS_PER_HOUR   3600
 #define USECS_PER_HOUR TIMELIB_LL_CONST(3600000000)
+#define NSECS_PER_SEC  TIMELIB_LL_CONST(1000000000)
+#define MAX_DURATION_SECONDS TIMELIB_LL_CONST(9223372035)
 
 #define DAYS_PER_WEEK      7
 #define DAYS_PER_YEAR    365
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.