Commit 69b6debd808 for php.net
commit 69b6debd8089a3b66cb33d32e6d647befc08c01c
Author: Derick Rethans <github@derickrethans.nl>
Date: Wed Aug 5 11:37:02 2026 +0100
Update to timelib 2026.01
diff --git a/NEWS b/NEWS
index 16a4ae4e99b..7dd05a2b1c7 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 00000000000..b5b0c766850
--- /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 da9262da999..fb10963d757 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 eb324f8430c..3380ba73265 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 07d9c0e7348..15a96f2af95 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 5dcbfe35063..8f9221e6aa0 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 00942007751..7757cd5edc8 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 c7f93580d72..c3cd79843b6 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 faf383a5fa1..787e8533416 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 d08aa77ea5e..97f76f048d7 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 42cbaa68dbb..eece57421fd 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