SERVER-90147 Upgrade timelib.h to 2022.10 and timezone files to 2024a

Updates timelib.h to the latest available named version. Additionally
modifies the import script such that it always downloads the latest tz
dbs.

Changes from the original commit to `master`:
* `sbom.json` - deleted - does not exist at this point in time
* `BUILD.bazel` - deleted - changes we're translated to `SConscript`

No changes from `v8.0`.

GitOrigin-RevId: 93858dfa4829f700932447e54bc13543a5fb256e
This commit is contained in:
Catalin Sumanaru 2024-06-26 18:14:13 +01:00 committed by MongoDB Bot
parent 9be8e57f39
commit c8e9f20da4
42 changed files with 99223 additions and 26476 deletions

View File

@ -52,7 +52,7 @@ a notice will be included in
| [schemastore.org] | Apache-2.0 | 6847cfc3a1 | | |
| [scons] | MIT | 3.1.2 | | |
| [Snappy] | BSD-3-Clause | 1.1.7 | ✗ | ✗ |
| [timelib] | MIT | 2022.04 | | ✗ |
| [timelib] | MIT | 2022.10 | | ✗ |
| [TomCrypt] | Public Domain | 1.18.2 | ✗ | ✗ |
| [Unicode] | Unicode-DFS-2015 | 8.0.0 | ✗ | ✗ |
| [libunwind] | MIT | 1.6.2 + changes | | ✗ |
@ -62,6 +62,7 @@ a notice will be included in
| [Zlib] | Zlib | 1.3 | ✗ | ✗ |
| [Zstandard] | BSD-3-Clause | 1.5.5 | ✗ | ✗ |
[abseil-cpp]: https://github.com/abseil/abseil-cpp
[ASIO]: https://github.com/chriskohlhoff/asio
[benchmark]: https://github.com/google/benchmark

View File

@ -7,7 +7,7 @@ functions:
params:
working_dir: src
script: |
cd src/third_party/timelib/zones
cd src/third_party/timelib/dist/zones
make timezonedb.zip CFLAGS=-DHAVE_SNPRINTF=1
cp timezonedb.zip timezonedb-latest.zip
@ -17,7 +17,7 @@ functions:
aws_key: ${aws_key}
aws_secret: ${aws_secret}
local_files_include_filter:
- src/src/third_party/timelib/zones/timezonedb-*.zip
- src/src/third_party/timelib/dist/zones/timezonedb-*.zip
remote_file: olson_tz_db/
bucket: downloads.mongodb.org
permissions: public-read

View File

@ -35,7 +35,7 @@ thirdPartyEnvironmentModifications = {
# SAFEINT_USE_INTRINSICS=0 for overflow-safe constexpr multiply. See comment in SafeInt.hpp.
'CPPDEFINES': [('SAFEINT_USE_INTRINSICS', 0)],
},
'timelib': {'CPPPATH': ['#/src/third_party/timelib'], },
'timelib': {'CPPPATH': ['#/src/third_party/timelib/dist'], },
'unwind': {},
'mozjs': {
'CPPPATH': [

View File

@ -1,141 +0,0 @@
#!/bin/bash
set -o verbose
set -o errexit
# This script downloads and imports timelib
# timelib does not use any autotools/cmake/config system to it is a simple import.
# This script is designed to run on Linux or Mac OS X
#
VERSION=2022.04
NAME=timelib
TARBALL=$VERSION.tar.gz
TARBALL_DIR=$NAME-$VERSION
if grep -q Microsoft /proc/version; then
TEMP_DIR=$(wslpath -u $(powershell.exe -Command "Get-ChildItem Env:TEMP | Get-Content | Write-Host"))
else
TEMP_DIR="/tmp"
fi
TEMP_DIR=$(mktemp -d $TEMP_DIR/$NAME.XXXXXX)
DEST_DIR=`git rev-parse --show-toplevel`/src/third_party/$NAME
# Check prerequisites: re2c, wget
if ! [ -x "$(command -v re2c)" ]; then
echo 'Error: re2c is not installed.' >&2
exit 1
fi
if ! [ -x "$(command -v wget)" ]; then
echo 'Error: wget is not installed.' >&2
exit 1
fi
# Derick may not upload a tarball for a release. In that case, better to create a tarball manually.
# Can create $TARBALL manually using the following commands. For example,
# $ cd ~
# $ VERSION=2022.04
# $ TARBALL=$VERSION.tar.gz
# $ git clone git@github.com:derickr/timelib.git
# $ cd timelib
# Derick made the change to v2022 branch for 2022.04 version
# $ git checkout v2022
# .git sub-directory is unnecessary in the tarball
# $ rm -rf .git
# $ cd ..
# tarball directory should be in the directory timelib-$VERSION
# $ mv timelib timelib-$VERSION
# $ tar czvf $TARBALL timelib-$VERSION
# $ mv $TARBALL ~/mongo/src/third_party/scripts
if [ ! -f $TARBALL ]; then
echo "Get tarball"
wget https://github.com/derickr/timelib/archive/$TARBALL
fi
echo $TARBALL
tar -zxvf $TARBALL
rm -rf $TEMP_DIR
mv $TARBALL_DIR $TEMP_DIR
mkdir $DEST_DIR || true
cp -r $TEMP_DIR/* $DEST_DIR
cd $DEST_DIR
# Prune files
rm -rf $DEST_DIR/tests
rm $DEST_DIR/zones/old-tzcode-32-bit-output.tar.gz || true
# Create parsers
echo "Creating parsers"
make parse_date.c parse_iso_intervals.c
# Create SConscript file
cat <<EOF > SConscript
# This is a generated file, please do not modify. It is generated by
# timelib_get_sources.sh
Import('env')
env = env.Clone()
try:
env.AppendUnique(CCFLAGS=[
'-DHAVE_GETTIMEOFDAY',
'-DHAVE_STRING_H',
])
if env.TargetOSIs('windows'):
env.AppendUnique(CCFLAGS=[
'-DHAVE_IO_H',
'-DHAVE_WINSOCK2_H',
])
# C4996: '...': was declared deprecated
env.Append(CCFLAGS=['/wd4996'])
elif env.TargetOSIs('solaris'):
env.AppendUnique(CCFLAGS=[
'-DHAVE_DIRENT_H',
'-DHAVE_STRINGS_H',
'-DHAVE_UNISTD_H',
'-D_POSIX_C_SOURCE=200112L',
])
elif env.TargetOSIs('darwin'):
env.AppendUnique(CCFLAGS=[
'-DHAVE_DIRENT_H',
'-DHAVE_SYS_TIME_H',
'-DHAVE_UNISTD_H',
])
else:
env.AppendUnique(CCFLAGS=[
'-DHAVE_DIRENT_H',
'-DHAVE_SYS_TIME_H',
'-DHAVE_UNISTD_H',
'-D_GNU_SOURCE',
])
except ValueError:
pass
env.Library(
target='timelib',
source=[
'astro.c',
'dow.c',
'interval.c',
'parse_date.c',
'parse_iso_intervals.c',
'parse_tz.c',
'parse_posix.c',
'parse_zoneinfo.c',
'timelib.c',
'tm2unixtime.c',
'unixtime2tm.c',
],
LIBDEPS_TAGS=[
'init-no-global-side-effects',
],
)
EOF
echo "Done"

View File

@ -16,8 +16,10 @@ try:
'-DHAVE_WINSOCK2_H',
])
# C4996: '...': was declared deprecated
env.Append(CCFLAGS=['/wd4996'])
env.Append(CCFLAGS=[
'/wd4067', # C4067: '...': expected a newline
'/wd4996', # C4996: '...': was declared deprecated
])
elif env.TargetOSIs('solaris'):
env.AppendUnique(CCFLAGS=[
'-DHAVE_DIRENT_H',
@ -44,17 +46,17 @@ except ValueError:
env.Library(
target='timelib',
source=[
'astro.c',
'dow.c',
'interval.c',
'parse_date.c',
'parse_iso_intervals.c',
'parse_tz.c',
'parse_posix.c',
'parse_zoneinfo.c',
'timelib.c',
'tm2unixtime.c',
'unixtime2tm.c',
'dist/astro.c',
'dist/dow.c',
'dist/interval.c',
'dist/parse_date.c',
'dist/parse_iso_intervals.c',
'dist/parse_tz.c',
'dist/parse_posix.c',
'dist/parse_zoneinfo.c',
'dist/timelib.c',
'dist/tm2unixtime.c',
'dist/unixtime2tm.c',
],
LIBDEPS_TAGS=[
'init-no-global-side-effects',

View File

@ -1,4 +1,5 @@
FLAGS=-O0 -ggdb3 \
-fPIC \
-Wall -Werror -Wextra \
-Wempty-body \
-Wenum-compare \
@ -24,23 +25,25 @@ FLAGS=-O0 -ggdb3 \
-fno-exceptions \
-fno-omit-frame-pointer \
-fno-optimize-sibling-calls \
-fsanitize=address \
-fsanitize=undefined \
-fstack-protector \
-pedantic \
-DHAVE_STDINT_H -DHAVE_GETTIMEOFDAY -DHAVE_UNISTD_H -DHAVE_DIRENT_H -I.# -DDEBUG_PARSER
CFLAGS=-Wdeclaration-after-statement ${FLAGS}
CFLAGS_BASE=-Wdeclaration-after-statement ${FLAGS}
CFLAGS=-fsanitize=address -fsanitize=undefined ${CFLAGS_BASE}
CPPFLAGS=${FLAGS}
CPPFLAGS=-fsanitize=address -fsanitize=undefined ${FLAGS}
LDFLAGS=-lm -fsanitize=undefined -l:libubsan.so
LDFLAGS_BASE=-lm
LDFLAGS=${LDFLAGS_BASE} -fsanitize=undefined -l:libubsan.so
TEST_LDFLAGS=-lCppUTest
CC=gcc
CXX=g++
FILES=parse_iso_intervals.o parse_date.o unixtime2tm.o tm2unixtime.o dow.o parse_tz.o parse_zoneinfo.o timelib.o astro.o interval.o parse_posix.o
MANUAL_TESTS=tests/tester-parse-interval \
tests/tester-iso-week tests/test-abbr-to-id \
tests/enumerate-timezones tests/date_from_isodate
@ -58,13 +61,13 @@ C_TESTS=tests/c/timelib_get_current_offset_test.o tests/c/timelib_decimal_hour.o
tests/c/timelib_hmsf_to_decimal_hour.o tests/c/dow.o \
tests/c/timelib_get_offset_info_test.o tests/c/add.o tests/c/sub.o
TEST_BINARIES=${MANUAL_TESTS} ${AUTO_TESTS}
TEST_BINARIES=${MANUAL_TESTS} ${AUTO_TESTS} ctest
EXAMPLE_BINARIES=docs/date-from-iso-parts docs/date-from-parts docs/date-from-string \
docs/date-to-parts docs/show-tzinfo
all: parse_date.o tm2unixtime.o unixtime2tm.o dow.o astro.o interval.o \
${TEST_BINARIES} ${EXAMPLE_BINARIES} ctest
all: parse_date.o tm2unixtime.o unixtime2tm.o dow.o astro.o interval.o timelib.a timelib.so \
${TEST_BINARIES} ${EXAMPLE_BINARIES}
parse_date.c: timezonemap.h parse_date.re
re2c -d -b parse_date.re > parse_date.c
@ -72,8 +75,11 @@ parse_date.c: timezonemap.h parse_date.re
parse_iso_intervals.c: parse_iso_intervals.re
re2c -d -b parse_iso_intervals.re > parse_iso_intervals.c
timelib.a: parse_iso_intervals.o parse_date.o unixtime2tm.o tm2unixtime.o dow.o parse_tz.o parse_zoneinfo.o timelib.o astro.o interval.o parse_posix.o
ar -rc timelib.a parse_iso_intervals.o parse_date.o unixtime2tm.o tm2unixtime.o dow.o parse_tz.o parse_zoneinfo.o timelib.o astro.o interval.o parse_posix.o
timelib.a: ${FILES}
ar -rc timelib.a ${FILES}
timelib.so: ${FILES}
$(CC) $(CFLAGS_BASE) -shared -o timelib.so ${FILES} $(LDFLAGS_BASE)
tests/tester-diff: timelib.a tests/tester-diff.c
$(CC) $(CFLAGS) -o tests/tester-diff tests/tester-diff.c timelib.a $(LDFLAGS)
@ -136,13 +142,13 @@ clean-all: clean
rm -f timezonemap.h
clean:
rm -f parse_iso_intervals.c parse_date.c *.o tests/c/*.o timelib.a ${TEST_BINARIES}
rm -f parse_iso_intervals.c parse_date.c *.o tests/c/*.o timelib.a timelib.so ${TEST_BINARIES}
#%.o: %.cpp timelib.a
# $(CXX) -c $(CPPFLAGS) $(LDFLAGS) $< -o $@
ctest: tests/c/all_tests.cpp timelib.a ${C_TESTS}
$(CXX) $(CPPFLAGS) $(LDFLAGS) tests/c/all_tests.cpp ${C_TESTS} timelib.a $(TEST_LDFLAGS) -o ctest
$(CXX) $(CPPFLAGS) $(LDFLAGS) tests/c/all_tests.cpp ${C_TESTS} $(TEST_LDFLAGS) timelib.a -o ctest
test: ctest
@./ctest -c

View File

@ -36,25 +36,6 @@ static void swap_times(timelib_time **one, timelib_time **two, timelib_rel_time
rt->invert = 1;
}
static void swap_if_negative(timelib_rel_time *rt)
{
if (rt->y == 0 && rt->m == 0 && rt->d == 0 && rt->h == 0 && rt->i == 0 && rt->s == 0 && rt->us == 0) {
return;
}
if (rt->y >= 0 && rt->m >= 0 && rt->d >= 0 && rt->h >= 0 && rt->i >= 0 && rt->s >= 0 && rt->us >= 0) {
return;
}
rt->invert = 1 - rt->invert;
rt->y = 0 - rt->y;
rt->m = 0 - rt->m;
rt->d = 0 - rt->d;
rt->h = 0 - rt->h;
rt->i = 0 - rt->i;
rt->s = 0 - rt->s;
rt->us = 0 - rt->us;
}
static void sort_old_to_new(timelib_time **one, timelib_time **two, timelib_rel_time *rt)
{
/* Check whether date/times need to be inverted. If both times are
@ -115,80 +96,48 @@ static timelib_rel_time *timelib_diff_with_tzid(timelib_time *one, timelib_time
rt->days = timelib_diff_days(one, two);
/* Fall Back: Cater for transition period, where rt->invert is 0, but there are negative numbers */
if (one->dst == 1 && two->dst == 0) {
/* First for two "Type 3" times */
if (one->zone_type == TIMELIB_ZONETYPE_ID && two->zone_type == TIMELIB_ZONETYPE_ID) {
int success = timelib_get_time_zone_offset_info(two->sse, two->tz_info, &trans_offset, &trans_transition_time, NULL);
if (
success &&
one->sse < trans_transition_time &&
one->sse >= trans_transition_time + dst_corr
) {
timelib_sll flipped = SECS_PER_HOUR + (rt->i * 60) + (rt->s);
rt->h = flipped / SECS_PER_HOUR;
rt->i = (flipped - rt->h * SECS_PER_HOUR) / 60;
rt->s = flipped % 60;
}
} else if (rt->h == 0 && (rt->i < 0 || rt->s < 0)) {
/* Then for all the others */
timelib_sll flipped = SECS_PER_HOUR + (rt->i * 60) + (rt->s);
rt->h = flipped / SECS_PER_HOUR;
rt->i = (flipped - rt->h * SECS_PER_HOUR) / 60;
rt->s = flipped % 60;
dst_corr += SECS_PER_HOUR;
dst_h_corr++;
}
if (two->sse < one->sse) {
timelib_sll flipped = llabs((rt->i * 60) + (rt->s) - dst_corr);
rt->h = flipped / SECS_PER_HOUR;
rt->i = (flipped - rt->h * SECS_PER_HOUR) / 60;
rt->s = flipped % 60;
rt->invert = 1 - rt->invert;
}
timelib_do_rel_normalize(rt->invert ? one : two, rt);
/* Do corrections for "Type 3" times with the same TZID */
if (one->zone_type == TIMELIB_ZONETYPE_ID && two->zone_type == TIMELIB_ZONETYPE_ID && strcmp(one->tz_info->name, two->tz_info->name) == 0) {
if (one->dst == 1 && two->dst == 0) { /* Fall Back */
if (two->tz_info) {
int success = timelib_get_time_zone_offset_info(two->sse, two->tz_info, &trans_offset, &trans_transition_time, NULL);
if (
success &&
two->sse >= trans_transition_time &&
((two->sse - one->sse + dst_corr) % SECS_PER_DAY) > (two->sse - trans_transition_time)
) {
rt->h -= dst_h_corr;
rt->i -= dst_m_corr;
}
}
} else if (one->dst == 0 && two->dst == 1) { /* Spring Forward */
if (two->tz_info) {
int success = timelib_get_time_zone_offset_info(two->sse, two->tz_info, &trans_offset, &trans_transition_time, NULL);
if (
success &&
!((one->sse + SECS_PER_DAY > trans_transition_time) && (one->sse + SECS_PER_DAY <= (trans_transition_time + dst_corr))) &&
two->sse >= trans_transition_time &&
((two->sse - one->sse + dst_corr) % SECS_PER_DAY) > (two->sse - trans_transition_time)
) {
rt->h -= dst_h_corr;
rt->i -= dst_m_corr;
}
}
} else if (two->sse - one->sse >= SECS_PER_DAY) {
/* Check whether we're in the period to the next transition time */
if (timelib_get_time_zone_offset_info(two->sse - two->z, two->tz_info, &trans_offset, &trans_transition_time, NULL)) {
dst_corr = one->z - trans_offset;
if (two->sse >= trans_transition_time - dst_corr && two->sse < trans_transition_time) {
rt->d--;
rt->h = 24;
}
if (one->dst == 1 && two->dst == 0) { /* Fall Back */
if (two->tz_info) {
if ((two->sse - one->sse + dst_corr) < SECS_PER_DAY) {
rt->h -= dst_h_corr;
rt->i -= dst_m_corr;
}
}
} else {
rt->h -= dst_h_corr;
rt->i -= dst_m_corr;
} else if (one->dst == 0 && two->dst == 1) { /* Spring Forward */
if (two->tz_info) {
int success = timelib_get_time_zone_offset_info(two->sse, two->tz_info, &trans_offset, &trans_transition_time, NULL);
swap_if_negative(rt);
if (
success &&
!((one->sse + SECS_PER_DAY > trans_transition_time) && (one->sse + SECS_PER_DAY <= (trans_transition_time + dst_corr))) &&
two->sse >= trans_transition_time &&
((two->sse - one->sse + dst_corr) % SECS_PER_DAY) > (two->sse - trans_transition_time)
) {
rt->h -= dst_h_corr;
rt->i -= dst_m_corr;
}
}
} else if (two->sse - one->sse >= SECS_PER_DAY) {
/* Check whether we're in the period to the next transition time */
if (timelib_get_time_zone_offset_info(two->sse - two->z, two->tz_info, &trans_offset, &trans_transition_time, NULL)) {
dst_corr = one->z - trans_offset;
timelib_do_rel_normalize(rt->invert ? one : two, rt);
if (two->sse >= trans_transition_time - dst_corr && two->sse < trans_transition_time) {
rt->d--;
rt->h = 24;
}
}
}
return rt;

25583
src/third_party/timelib/dist/parse_date.c vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2015-2019 Derick Rethans
* Copyright (c) 2015-2023 Derick Rethans
* Copyright (c) 2018 MongoDB, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
@ -27,6 +27,7 @@
#include "timelib_private.h"
#include <ctype.h>
#include <errno.h>
#include <math.h>
#include <assert.h>
#include <limits.h>
@ -580,7 +581,13 @@ static timelib_ull timelib_get_signed_nr(Scanner *s, const char **ptr, int max_l
++len;
}
errno = 0;
tmp_nr = strtoll(str, NULL, 10);
if (errno == ERANGE) {
timelib_free(str);
add_error(s, TIMELIB_ERR_NUMBER_OUT_OF_RANGE, "Number out of range");
return 0;
}
timelib_free(str);
@ -654,9 +661,21 @@ static timelib_long timelib_get_month(const char **ptr)
static void timelib_eat_spaces(const char **ptr)
{
while (**ptr == ' ' || **ptr == '\t') {
++*ptr;
}
do {
if (**ptr == ' ' || **ptr == '\t') {
++*ptr;
continue;
}
if ((*ptr)[0] == '\xe2' && (*ptr)[1] == '\x80' && (*ptr)[2] == '\xaf') { // NNBSP
*ptr += 3;
continue;
}
if ((*ptr)[0] == '\xc2' && (*ptr)[1] == '\xa0') { // NBSP
*ptr += 2;
continue;
}
break;
} while (true);
}
static void timelib_eat_until_separator(const char **ptr)
@ -692,6 +711,17 @@ static const timelib_relunit* timelib_lookup_relunit(const char **ptr)
return value;
}
static void add_with_overflow(Scanner *s, timelib_sll *e, timelib_sll amount, int multiplier)
{
#if defined(__has_builtin) && __has_builtin(__builtin_saddll_overflow)
if (__builtin_saddll_overflow(*e, amount * multiplier, e)) {
add_error(s, TIMELIB_ERR_NUMBER_OUT_OF_RANGE, "Number out of range");
}
#else
*e += (amount * multiplier);
#endif
}
/**
* The time_part parameter is a flag. It can be TIMELIB_TIME_PART_KEEP in case
* the time portion should not be reset to midnight, or
@ -707,13 +737,13 @@ static void timelib_set_relative(const char **ptr, timelib_sll amount, int behav
}
switch (relunit->unit) {
case TIMELIB_MICROSEC: s->time->relative.us += amount * relunit->multiplier; break;
case TIMELIB_SECOND: s->time->relative.s += amount * relunit->multiplier; break;
case TIMELIB_MINUTE: s->time->relative.i += amount * relunit->multiplier; break;
case TIMELIB_HOUR: s->time->relative.h += amount * relunit->multiplier; break;
case TIMELIB_DAY: s->time->relative.d += amount * relunit->multiplier; break;
case TIMELIB_MONTH: s->time->relative.m += amount * relunit->multiplier; break;
case TIMELIB_YEAR: s->time->relative.y += amount * relunit->multiplier; break;
case TIMELIB_MICROSEC: add_with_overflow(s, &s->time->relative.us, amount, relunit->multiplier); break;
case TIMELIB_SECOND: add_with_overflow(s, &s->time->relative.s, amount, relunit->multiplier); break;
case TIMELIB_MINUTE: add_with_overflow(s, &s->time->relative.i, amount, relunit->multiplier); break;
case TIMELIB_HOUR: add_with_overflow(s, &s->time->relative.h, amount, relunit->multiplier); break;
case TIMELIB_DAY: add_with_overflow(s, &s->time->relative.d, amount, relunit->multiplier); break;
case TIMELIB_MONTH: add_with_overflow(s, &s->time->relative.m, amount, relunit->multiplier); break;
case TIMELIB_YEAR: add_with_overflow(s, &s->time->relative.y, amount, relunit->multiplier); break;
case TIMELIB_WEEKDAY:
TIMELIB_HAVE_WEEKDAY_RELATIVE();
@ -985,7 +1015,9 @@ std:
/*!re2c
any = [\000-\377];
space = [ \t]+;
nbsp = [\302][\240];
nnbsp = [\342][\200][\257];
space = [ \t]+ | nbsp+ | nnbsp+;
frac = "."[0-9]+;
ago = 'ago';
@ -1312,6 +1344,7 @@ weekdayof = (reltextnumber|reltexttext) space (dayfulls|dayfull|dayabbr)
s->time->s = timelib_get_nr(&ptr, 2);
}
}
timelib_eat_spaces(&ptr);
s->time->h += timelib_meridian(&ptr, s->time->h);
TIMELIB_DEINIT;
return TIMELIB_TIME12;
@ -1739,6 +1772,9 @@ weekdayof = (reltextnumber|reltexttext) space (dayfulls|dayfull|dayabbr)
s->time->h = timelib_get_nr(&ptr, 2);
s->time->i = timelib_get_nr(&ptr, 2);
s->time->s = timelib_get_nr(&ptr, 2);
timelib_eat_spaces(&ptr);
s->time->z = timelib_parse_zone(&ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper);
if (tz_not_found) {
add_error(s, TIMELIB_ERR_TZID_NOT_FOUND, "The timezone could not be found in the database");
@ -1852,6 +1888,7 @@ weekdayof = (reltextnumber|reltexttext) space (dayfulls|dayfull|dayabbr)
DEBUG_OUTPUT("tzcorrection | tz");
TIMELIB_INIT;
TIMELIB_HAVE_TZ();
timelib_eat_spaces(&ptr);
s->time->z = timelib_parse_zone(&ptr, &s->time->dst, s->time, &tz_not_found, s->tzdb, tz_get_wrapper);
if (tz_not_found) {
add_error(s, TIMELIB_ERR_TZID_NOT_FOUND, "The timezone could not be found in the database");
@ -1930,7 +1967,12 @@ weekdayof = (reltextnumber|reltexttext) space (dayfulls|dayfull|dayabbr)
return TIMELIB_RELATIVE;
}
[ .,\t]
[.,]
{
goto std;
}
space
{
goto std;
}

View File

@ -187,14 +187,22 @@ timelib_long timelib_date_to_int(timelib_time *d, int *error)
void timelib_decimal_hour_to_hms(double h, int *hour, int *min, int *sec)
{
if (h > 0) {
*hour = floor(h);
*min = floor((h - *hour) * 60);
*sec = (h - *hour - ((float) *min / 60)) * 3600;
} else {
*hour = ceil(h);
*min = 0 - ceil((h - *hour) * 60);
*sec = 0 - (h - *hour - ((float) *min / -60)) * 3600;
bool swap = false;
int seconds;
if (h < 0) {
swap = true;
h = fabs(h);
}
*hour = floor(h);
seconds = floor((h - *hour) * 3600);
*min = seconds / 60;
*sec = seconds % 60;
if (swap) {
*hour = 0 - *hour;
}
}

View File

@ -1,7 +1,7 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2015-2022 Derick Rethans
* Copyright (c) 2015-2023 Derick Rethans
* Copyright (c) 2018,2021 MongoDB, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
@ -30,9 +30,9 @@
# include "timelib_config.h"
#endif
#define TIMELIB_VERSION 202204
#define TIMELIB_EXTENDED_VERSION 20220401
#define TIMELIB_ASCII_VERSION "2022.04"
#define TIMELIB_VERSION 202210
#define TIMELIB_EXTENDED_VERSION 20221001
#define TIMELIB_ASCII_VERSION "2022.10"
#include <stdlib.h>
#include <stdbool.h>
@ -321,6 +321,7 @@ typedef struct _timelib_abbr_info {
#define TIMELIB_ERR_INVALID_TZ_OFFSET 0x223
#define TIMELIB_ERR_FORMAT_LITERAL_MISMATCH 0x224
#define TIMELIB_ERR_MIX_ISO_WITH_NATURAL 0x225
#define TIMELIB_ERR_NUMBER_OUT_OF_RANGE 0x226
#define TIMELIB_ZONETYPE_NONE 0
#define TIMELIB_ZONETYPE_OFFSET 1
@ -378,7 +379,7 @@ typedef struct _timelib_tzdb {
#define TIMELIB_OVERRIDE_TIME 0x01
#define TIMELIB_NO_CLONE 0x02
#define TIMELIB_UNSET -99999
#define TIMELIB_UNSET -9999999
/* An entry for each of these error codes is also in the
* timelib_error_messages array in timelib.c.

View File

@ -32,8 +32,16 @@ static int days_in_month[13] = { 31, 31, 28, 31, 30, 31, 30, 31, 3
static void do_range_limit(timelib_sll start, timelib_sll end, timelib_sll adj, timelib_sll *a, timelib_sll *b)
{
if (*a < start) {
*b -= (start - *a - 1) / adj + 1;
*a += adj * ((start - *a - 1) / adj + 1);
/* We calculate 'a + 1' first as 'start - *a - 1' causes an int64_t overflows if *a is
* LONG_MIN. 'start' is 0 in this context, and '0 - LONG_MIN > LONG_MAX'. */
timelib_sll a_plus_1 = *a + 1;
*b -= (start - a_plus_1) / adj + 1;
/* This code add the extra 'adj' separately, as otherwise this can overflow int64_t in
* situations where *b is near LONG_MIN. */
*a += adj * ((start - a_plus_1) / adj);
*a += adj;
}
if (*a >= end) {
*b += *a / adj;
@ -462,9 +470,15 @@ void timelib_update_ts(timelib_time* time, timelib_tzinfo* tzi)
do_adjust_relative(time);
do_adjust_special(time);
time->sse =
(timelib_epoch_days_from_time(time) * SECS_PER_DAY) +
timelib_hms_to_seconds(time->h, time->i, time->s);
/* You might be wondering, why this code does this in two steps. This is because
* timelib_epoch_days_from_time(time) * SECS_PER_DAY with the lowest limit of
* timelib_epoch_days_from_time() is less than the range of an int64_t. This then overflows. In
* order to be able to still allow for any time in that day that only halfly fits in the int64_t
* range, we add the time element first, which is always positive, and then twice half the value
* of the earliest day as expressed as unix timestamp. */
time->sse = timelib_hms_to_seconds(time->h, time->i, time->s);
time->sse += timelib_epoch_days_from_time(time) * (SECS_PER_DAY / 2);
time->sse += timelib_epoch_days_from_time(time) * (SECS_PER_DAY / 2);
// This modifies time->sse, if needed
do_adjust_timezone(time, tzi);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

67
src/third_party/timelib/scripts/import.sh vendored Executable file
View File

@ -0,0 +1,67 @@
#!/bin/bash
#
# The script fetches the sources for 'derickr/timelib', downloads the latest Olson timezone
# database and generates the necessary sources for the imports. The sources will be generated
# inside 'src/third_party/timelib/dist/' and should be commited to the repository.
#
# The library does not use any autotools/cmake/config system to it, as it is a simple import.
# This script is designed to run on Linux or Mac OS X.
#
# Usage: ./src/third_party/timelib/scripts/import.sh
VERSION=2022.10
NAME=timelib
set -o verbose
set -o errexit
if grep -q Microsoft /proc/version; then
TEMP_DIR=$(wslpath -u $(powershell.exe -Command "Get-ChildItem Env:TEMP | Get-Content | Write-Host"))
else
TEMP_DIR="/tmp"
fi
TEMP_DIR=$(mktemp -d $TEMP_DIR/$NAME.XXXXXX)
DEST_DIR=`git rev-parse --show-toplevel`/src/third_party/$NAME/dist
if [[ -d $DEST_DIR ]]; then
echo "You must remove '$DEST_DIR' before running $0" >&2
exit 1
fi
# Check prerequisites: re2c, wget and php.
if ! [ -x "$(command -v re2c)" ]; then
echo 'Error: re2c is not installed.' >&2
exit 1
fi
if ! [ -x "$(command -v wget)" ]; then
echo 'Error: wget is not installed.' >&2
exit 1
fi
if ! [ -x "$(command -v php)" ]; then
echo 'Error: php is not installed.' >&2
exit 1
fi
mkdir -p $DEST_DIR
pushd $TEMP_DIR
git clone --branch $VERSION --depth 1 git@github.com:derickr/timelib.git .
# Avoid embedding the git repository itself.
rm -rf .git*
# Prune unneeded files.
rm -rf tests/
# Download the latest Olson timezone database and generate 'timezonedb.h'.
make -C zones
# Generate the parsers.
make parse_date.c parse_iso_intervals.c
# Clean up the build artifacts and copy the end sources to the destination directory.
make -C zones clean
cp -r * $DEST_DIR
popd
echo "Done"