mirror of
https://github.com/postgres/postgres.git
synced 2026-07-06 16:25:55 -04:00
Sync our copy of the timezone library with IANA release tzcode2026b.
This was moderately tedious, because upstream has been busy since we last did this in 2020. Notably, they changed the signatures of both tzload() and tzparse(), which we'd unwisely exposed as API for callers to use. I concluded that the best answer was to change them both back to "static" and instead expose a new API function of our own choosing, pg_tzload(). That change may be a sufficient reason not to back-patch this update, as I'd normally want to do. There's probably not a good reason for extensions to be calling those functions, but on the other hand there are few pressing reasons for a back-patch. The one bug we have run into (a Valgrind uninitialized-data complaint about zic) appears to have no field-visible consequences. A few of the files generated by this version of zic are not byte-for-byte the same as before, but "zdump -v" avers that they represent the same sets of transitions. Discussion: https://postgr.es/m/2294297.1780270682@sss.pgh.pa.us
This commit is contained in:
parent
d322348554
commit
aeb07c55fa
10 changed files with 3012 additions and 1847 deletions
|
|
@ -96,23 +96,10 @@ pg_load_tz(const char *name)
|
|||
return NULL; /* not going to fit */
|
||||
|
||||
/*
|
||||
* "GMT" is always sent to tzparse(); see comments for pg_tzset().
|
||||
* Let the IANA tzdb code interpret the time zone name.
|
||||
*/
|
||||
if (strcmp(name, "GMT") == 0)
|
||||
{
|
||||
if (!tzparse(name, &tz.state, true))
|
||||
{
|
||||
/* This really, really should not happen ... */
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else if (tzload(name, NULL, &tz.state, true) != 0)
|
||||
{
|
||||
if (name[0] == ':' || !tzparse(name, &tz.state, false))
|
||||
{
|
||||
return NULL; /* unknown timezone */
|
||||
}
|
||||
}
|
||||
if (!pg_tzload(name, NULL, &tz.state))
|
||||
return NULL; /* unknown timezone */
|
||||
|
||||
strcpy(tz.TZname, name);
|
||||
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ Windows, since we still need to match properly on older versions.
|
|||
Time Zone code
|
||||
==============
|
||||
|
||||
The code in this directory is currently synced with tzcode release 2020d.
|
||||
The code in this directory is currently synced with tzcode release 2026b.
|
||||
There are many cosmetic (and not so cosmetic) differences from the
|
||||
original tzcode library, but diffs in the upstream version should usually
|
||||
be propagated to our version. Here are some notes about that.
|
||||
|
|
@ -71,9 +71,7 @@ several considerations preventing an exact match:
|
|||
|
||||
* For readability/maintainability we reformat the code to match our own
|
||||
conventions; this includes pgindent'ing it and getting rid of upstream's
|
||||
overuse of "register" declarations. (It used to include conversion of
|
||||
old-style function declarations to C89 style, but thank goodness they
|
||||
fixed that.)
|
||||
overuse of "register" declarations.
|
||||
|
||||
* We need the code to follow Postgres' portability conventions; this
|
||||
includes relying on configure's results rather than hand-hacked
|
||||
|
|
@ -88,11 +86,8 @@ other exposed names.
|
|||
"lineno" in our typedefs list would cause unfortunate pgindent behavior
|
||||
in some other files where we have variables named that.
|
||||
|
||||
* We have exposed the tzload() and tzparse() internal functions, and
|
||||
slightly modified the API of the former, in part because it now relies
|
||||
on our own pg_open_tzfile() rather than opening files for itself.
|
||||
|
||||
* tzparse() is adjusted to never try to load the TZDEFRULES zone.
|
||||
* tzload() now relies on our own pg_open_tzfile() rather than opening
|
||||
files for itself.
|
||||
|
||||
* There's a fair amount of code we don't need and have removed,
|
||||
including all the nonstandard optional APIs. We have also added
|
||||
|
|
@ -109,18 +104,17 @@ to first run the tzcode source files through a sed filter like this:
|
|||
sed -r \
|
||||
-e 's/^([ \t]*)\*\*([ \t])/\1 *\2/' \
|
||||
-e 's/^([ \t]*)\*\*$/\1 */' \
|
||||
-e 's|^\*/| */|' \
|
||||
-e 's/\bregister[ \t]//g' \
|
||||
-e 's/\bATTRIBUTE_PURE[ \t]//g' \
|
||||
-e 's/struct[ \t]+tm\b/struct pg_tm/g' \
|
||||
-e 's/\btime_t\b/pg_time_t/g' \
|
||||
-e 's/lineno/lineno_t/g' \
|
||||
-i *.h *.c
|
||||
|
||||
and then run them through pgindent. (The first three sed patterns deal
|
||||
and then run them through pgindent. (The first two sed patterns deal
|
||||
with conversion of their block comment style to something pgindent
|
||||
won't make a hash of; the remainder address other points noted above.)
|
||||
After that, the files can be diff'd directly against our corresponding
|
||||
files. Also, it's typically helpful to diff against the previous tzcode
|
||||
release (after processing that the same way), and then try to apply the
|
||||
release (after processing that the same way), and then try to apply that
|
||||
diff to our files. This will take care of most of the changes
|
||||
mechanically.
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -219,16 +219,6 @@ init_timezone_hashtable(void)
|
|||
/*
|
||||
* Load a timezone from file or from cache.
|
||||
* Does not verify that the timezone is acceptable!
|
||||
*
|
||||
* "GMT" is always interpreted as the tzparse() definition, without attempting
|
||||
* to load a definition from the filesystem. This has a number of benefits:
|
||||
* 1. It's guaranteed to succeed, so we don't have the failure mode wherein
|
||||
* the bootstrap default timezone setting doesn't work (as could happen if
|
||||
* the OS attempts to supply a leap-second-aware version of "GMT").
|
||||
* 2. Because we aren't accessing the filesystem, we can safely initialize
|
||||
* the "GMT" zone definition before my_exec_path is known.
|
||||
* 3. It's quick enough that we don't waste much time when the bootstrap
|
||||
* default timezone setting is later overridden from postgresql.conf.
|
||||
*/
|
||||
pg_tz *
|
||||
pg_tzset(const char *tzname)
|
||||
|
|
@ -249,8 +239,8 @@ pg_tzset(const char *tzname)
|
|||
/*
|
||||
* Upcase the given name to perform a case-insensitive hashtable search.
|
||||
* (We could alternatively downcase it, but we prefer upcase so that we
|
||||
* can get consistently upcased results from tzparse() in case the name is
|
||||
* a POSIX-style timezone spec.)
|
||||
* can get consistently upcased results from pg_tzload() in case the name
|
||||
* is a POSIX-style timezone spec.)
|
||||
*/
|
||||
p = uppername;
|
||||
while (*tzname)
|
||||
|
|
@ -268,27 +258,17 @@ pg_tzset(const char *tzname)
|
|||
}
|
||||
|
||||
/*
|
||||
* "GMT" is always sent to tzparse(), as per discussion above.
|
||||
* Let the IANA tzdb code interpret the time zone name.
|
||||
*/
|
||||
if (strcmp(uppername, "GMT") == 0)
|
||||
if (!pg_tzload(uppername, canonname, &tzstate))
|
||||
{
|
||||
if (!tzparse(uppername, &tzstate, true))
|
||||
if (strcmp(uppername, "GMT") == 0)
|
||||
{
|
||||
/* This really, really should not happen ... */
|
||||
elog(ERROR, "could not initialize GMT time zone");
|
||||
}
|
||||
/* Use uppercase name as canonical */
|
||||
strcpy(canonname, uppername);
|
||||
}
|
||||
else if (tzload(uppername, canonname, &tzstate, true) != 0)
|
||||
{
|
||||
if (uppername[0] == ':' || !tzparse(uppername, &tzstate, false))
|
||||
{
|
||||
/* Unknown timezone. Fail our call instead of loading GMT! */
|
||||
return NULL;
|
||||
}
|
||||
/* For POSIX timezone specs, use uppercase name as canonical */
|
||||
strcpy(canonname, uppername);
|
||||
/* Unknown timezone. Fail our call instead of loading GMT! */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Save timezone in the cache */
|
||||
|
|
@ -467,12 +447,12 @@ pg_tzenumerate_next(pg_tzenum *dir)
|
|||
}
|
||||
|
||||
/*
|
||||
* Load this timezone using tzload() not pg_tzset(), so we don't fill
|
||||
* the cache. Also, don't ask for the canonical spelling: we already
|
||||
* know it, and pg_open_tzfile's way of finding it out is pretty
|
||||
* inefficient.
|
||||
* Load this timezone using pg_tzload() not pg_tzset(), so we don't
|
||||
* fill the cache. Also, don't ask for the canonical spelling: we
|
||||
* already know it, and pg_open_tzfile's way of finding it out is
|
||||
* pretty inefficient.
|
||||
*/
|
||||
if (tzload(fullname + dir->baselen, NULL, &dir->tz.state, true) != 0)
|
||||
if (!pg_tzload(fullname + dir->baselen, NULL, &dir->tz.state))
|
||||
{
|
||||
/* Zone could not be loaded, ignore it */
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -19,28 +19,72 @@
|
|||
#include "pgtime.h"
|
||||
#include "tzfile.h"
|
||||
|
||||
/*
|
||||
* Support leap seconds in TZ files.
|
||||
* Maybe we should disable this?
|
||||
*/
|
||||
#define TZ_RUNTIME_LEAPS 1
|
||||
|
||||
#define SMALLEST(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
|
||||
/*
|
||||
* Limit to time zone abbreviation length in proleptic TZ strings.
|
||||
* This is distinct from TZ_MAX_CHARS, which limits TZif file contents.
|
||||
* It defaults to 254, not 255, so that desigidx_type can be an unsigned char.
|
||||
* unsigned char suffices for TZif files, so the only reason to increase
|
||||
* TZNAME_MAXIMUM is to support TZ strings specifying abbreviations
|
||||
* longer than 254 bytes. There is little reason to do that, though,
|
||||
* as strings that long are hardly "abbreviations".
|
||||
*/
|
||||
#define TZNAME_MAXIMUM 254
|
||||
|
||||
typedef unsigned char desigidx_type;
|
||||
|
||||
/*
|
||||
* A type that can represent any 32-bit two's complement integer,
|
||||
* i.e., any integer in the range -2**31 .. 2**31 - 1.
|
||||
*/
|
||||
typedef int_fast32_t int_fast32_2s;
|
||||
|
||||
struct ttinfo
|
||||
{ /* time type information */
|
||||
int_fast32_t tt_utoff; /* UT offset in seconds */
|
||||
int_least32_t tt_utoff; /* UT offset in seconds; in the range -2**31 +
|
||||
* 1 .. 2**31 - 1 */
|
||||
desigidx_type tt_desigidx; /* abbreviation list index */
|
||||
bool tt_isdst; /* used to set tm_isdst */
|
||||
int tt_desigidx; /* abbreviation list index */
|
||||
bool tt_ttisstd; /* transition is std time */
|
||||
bool tt_ttisut; /* transition is UT */
|
||||
};
|
||||
|
||||
struct lsinfo
|
||||
{ /* leap second information */
|
||||
pg_time_t ls_trans; /* transition time */
|
||||
int_fast64_t ls_corr; /* correction to apply */
|
||||
pg_time_t ls_trans; /* transition time (positive) */
|
||||
int_fast32_2s ls_corr; /* correction to apply */
|
||||
};
|
||||
|
||||
/* This abbreviation means local time is unspecified. */
|
||||
static char const UNSPEC[] = "-00";
|
||||
|
||||
/*
|
||||
* How many extra bytes are needed at the end of struct state's chars array.
|
||||
* This needs to be at least 1 for null termination in case the input
|
||||
* data isn't properly terminated, and it also needs to be big enough
|
||||
* for ttunspecified to work without crashing.
|
||||
*/
|
||||
enum
|
||||
{
|
||||
CHARS_EXTRA = Max(sizeof UNSPEC, 2) - 1};
|
||||
|
||||
/*
|
||||
* A representation of the contents of a TZif file. Ideally this
|
||||
* would have no size limits; the following sizes should suffice for
|
||||
* practical use. This struct should not be too large, as instances
|
||||
* are put on the stack and stacks are relatively small on some platforms.
|
||||
* See tzfile.h for more about the sizes.
|
||||
*/
|
||||
struct state
|
||||
{
|
||||
#if TZ_RUNTIME_LEAPS
|
||||
int leapcnt;
|
||||
#endif
|
||||
int timecnt;
|
||||
int typecnt;
|
||||
int charcnt;
|
||||
|
|
@ -49,16 +93,11 @@ struct state
|
|||
pg_time_t ats[TZ_MAX_TIMES];
|
||||
unsigned char types[TZ_MAX_TIMES];
|
||||
struct ttinfo ttis[TZ_MAX_TYPES];
|
||||
char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, 4 /* sizeof gmt */ ),
|
||||
(2 * (TZ_STRLEN_MAX + 1)))];
|
||||
char chars[Max(Max(TZ_MAX_CHARS + CHARS_EXTRA, sizeof "UTC"),
|
||||
2 * (TZNAME_MAXIMUM + 1))];
|
||||
#if TZ_RUNTIME_LEAPS
|
||||
struct lsinfo lsis[TZ_MAX_LEAPS];
|
||||
|
||||
/*
|
||||
* The time type to use for early times or if no transitions. It is always
|
||||
* zero for recent tzdb releases. It might be nonzero for data from tzdb
|
||||
* 2018e or earlier.
|
||||
*/
|
||||
int defaulttype;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -74,8 +113,6 @@ struct pg_tz
|
|||
extern int pg_open_tzfile(const char *name, char *canonname);
|
||||
|
||||
/* in localtime.c */
|
||||
extern int tzload(const char *name, char *canonname, struct state *sp,
|
||||
bool doextend);
|
||||
extern bool tzparse(const char *name, struct state *sp, bool lastditch);
|
||||
extern bool pg_tzload(const char *name, char *canonname, struct state *sp);
|
||||
|
||||
#endif /* _PGTZ_H */
|
||||
|
|
|
|||
|
|
@ -20,20 +20,67 @@
|
|||
* Thank you!
|
||||
*/
|
||||
|
||||
#include <limits.h> /* for CHAR_BIT et al. */
|
||||
#include <sys/wait.h> /* for WIFEXITED and WEXITSTATUS */
|
||||
#include <unistd.h> /* for F_OK and R_OK */
|
||||
/*
|
||||
* IANA now expects this symbol to be defined via a compiler switch,
|
||||
* but in PG we don't want to do it that way.
|
||||
*/
|
||||
#define TZDEFAULT "/etc/localtime"
|
||||
|
||||
#include "pgtime.h"
|
||||
/*
|
||||
* IANA messes with some feature-test macros here, but in PG we want pretty
|
||||
* much all of that to be done by PG's configure script and c.h header.
|
||||
*/
|
||||
|
||||
/*
|
||||
* For pre-C23 compilers, a substitute for static_assert.
|
||||
* Some of these compilers may warn if it is used outside the top level.
|
||||
*/
|
||||
#if __STDC_VERSION__ < 202311 && !defined static_assert
|
||||
#define static_assert(cond) extern int static_assert_check[(cond) ? 1 : -1]
|
||||
#endif
|
||||
|
||||
/* This string was in the Factory zone through version 2016f. */
|
||||
#ifndef GRANDPARENTED
|
||||
#define GRANDPARENTED "Local time zone must be set--see zic manual page"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* IANA has a bunch of HAVE_FOO #defines here, but in PG we want pretty
|
||||
* much all of that to be done by PG's configure script.
|
||||
* much all of that to be done by PG's configure script and c.h header.
|
||||
*/
|
||||
|
||||
#define ATTRIBUTE_FALLTHROUGH pg_fallthrough
|
||||
#define ATTRIBUTE_MAYBE_UNUSED pg_attribute_unused()
|
||||
#define ATTRIBUTE_NORETURN pg_noreturn
|
||||
#define ATTRIBUTE_PURE_114833
|
||||
#define ATTRIBUTE_PURE_114833_HACK
|
||||
|
||||
/*
|
||||
* Nested includes
|
||||
* In PG, much of this was already done by c.h.
|
||||
*/
|
||||
|
||||
#include "pgtime.h"
|
||||
|
||||
#include <limits.h> /* for CHAR_BIT et al. */
|
||||
#include <unistd.h> /* for F_OK and R_OK */
|
||||
|
||||
#ifndef EINVAL
|
||||
#define EINVAL ERANGE
|
||||
#endif
|
||||
|
||||
#ifndef ELOOP
|
||||
#define ELOOP EINVAL
|
||||
#endif
|
||||
#ifndef ENAMETOOLONG
|
||||
#define ENAMETOOLONG EINVAL
|
||||
#endif
|
||||
#ifndef ENOMEM
|
||||
#define ENOMEM EINVAL
|
||||
#endif
|
||||
#ifndef ENOTCAPABLE
|
||||
#define ENOTCAPABLE EINVAL
|
||||
#endif
|
||||
#ifndef ENOTSUP
|
||||
#define ENOTSUP EINVAL
|
||||
#endif
|
||||
|
|
@ -41,17 +88,71 @@
|
|||
#define EOVERFLOW EINVAL
|
||||
#endif
|
||||
|
||||
/* Unlike <ctype.h>'s isdigit, this also works if c < 0 | c > UCHAR_MAX. */
|
||||
#define is_digit(c) ((unsigned)(c) - '0' <= 9)
|
||||
/*
|
||||
* The maximum size of any created object, as a signed integer.
|
||||
* Although the C standard does not outright prohibit larger objects,
|
||||
* behavior is undefined if the result of pointer subtraction does not
|
||||
* fit into ptrdiff_t, and the code assumes in several places that
|
||||
* pointer subtraction works. As a practical matter it's OK to not
|
||||
* support objects larger than this.
|
||||
*/
|
||||
#define INDEX_MAX ((ptrdiff_t) min(PTRDIFF_MAX, SIZE_MAX))
|
||||
|
||||
/*
|
||||
* Support ckd_add, ckd_sub, ckd_mul on C23 or recent-enough GCC-like
|
||||
* hosts, unless compiled with -DHAVE_STDCKDINT_H=0 or with pre-C23 EDG.
|
||||
*/
|
||||
#if !defined HAVE_STDCKDINT_H && defined __has_include
|
||||
#if __has_include(<stdckdint.h>)
|
||||
#define HAVE_STDCKDINT_H 1
|
||||
#endif
|
||||
#endif
|
||||
#ifdef HAVE_STDCKDINT_H
|
||||
#if HAVE_STDCKDINT_H
|
||||
#include <stdckdint.h>
|
||||
#endif
|
||||
#elif defined __EDG__
|
||||
/* Do nothing, to work around EDG bug <https://bugs.gnu.org/53256>. */
|
||||
#elif defined __has_builtin
|
||||
#if __has_builtin(__builtin_add_overflow)
|
||||
#define ckd_add(r, a, b) __builtin_add_overflow(a, b, r)
|
||||
#endif
|
||||
#if __has_builtin(__builtin_sub_overflow)
|
||||
#define ckd_sub(r, a, b) __builtin_sub_overflow(a, b, r)
|
||||
#endif
|
||||
#if __has_builtin(__builtin_mul_overflow)
|
||||
#define ckd_mul(r, a, b) __builtin_mul_overflow(a, b, r)
|
||||
#endif
|
||||
#elif 7 <= __GNUC__
|
||||
#define ckd_add(r, a, b) __builtin_add_overflow(a, b, r)
|
||||
#define ckd_sub(r, a, b) __builtin_sub_overflow(a, b, r)
|
||||
#define ckd_mul(r, a, b) __builtin_mul_overflow(a, b, r)
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* In PG, we always have these fields in struct pg_tm.
|
||||
*/
|
||||
#define TM_GMTOFF tm_gmtoff
|
||||
#define TM_ZONE tm_zone
|
||||
|
||||
|
||||
/*
|
||||
* Finally, some convenience items.
|
||||
*/
|
||||
|
||||
#define TYPE_BIT(type) (sizeof (type) * CHAR_BIT)
|
||||
#define TYPE_BIT(type) (CHAR_BIT * (ptrdiff_t) sizeof(type))
|
||||
#define TYPE_SIGNED(type) (((type) -1) < 0)
|
||||
#define TWOS_COMPLEMENT(t) ((t) ~ (t) 0 < 0)
|
||||
#define TWOS_COMPLEMENT(type) (TYPE_SIGNED (type) && (! ~ (type) -1))
|
||||
|
||||
/*
|
||||
* Minimum and maximum of two values. Use lower case to avoid
|
||||
* naming clashes with standard include files.
|
||||
*/
|
||||
#undef max
|
||||
#undef min
|
||||
#define max(a, b) ((a) > (b) ? (a) : (b))
|
||||
#define min(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
/*
|
||||
* Max and min values of the integer type T, of which only the bottom
|
||||
|
|
@ -83,48 +184,94 @@
|
|||
*/
|
||||
#define INITIALIZE(x) ((x) = 0)
|
||||
|
||||
#define unreachable() pg_unreachable()
|
||||
|
||||
/*
|
||||
* For the benefit of GNU folk...
|
||||
* '_(MSGID)' uses the current locale's message library string for MSGID.
|
||||
* The default is to use gettext if available, and use MSGID otherwise.
|
||||
* For PG's purposes, there is no need to support localization in zic.
|
||||
*/
|
||||
|
||||
#undef _
|
||||
#define _(msgid) (msgid)
|
||||
#define N_(msgid) (msgid)
|
||||
|
||||
/* Handy macros that are independent of tzfile implementation. */
|
||||
/* Handy constants that are independent of tzfile implementation. */
|
||||
|
||||
#define YEARSPERREPEAT 400 /* years before a Gregorian repeat */
|
||||
/* 2**31 - 1 as a signed integer, and usable in #if. */
|
||||
#define TWO_31_MINUS_1 2147483647
|
||||
|
||||
enum
|
||||
{
|
||||
SECSPERMIN = 60,
|
||||
MINSPERHOUR = 60,
|
||||
SECSPERHOUR = SECSPERMIN * MINSPERHOUR,
|
||||
HOURSPERDAY = 24,
|
||||
DAYSPERWEEK = 7,
|
||||
DAYSPERNYEAR = 365,
|
||||
DAYSPERLYEAR = DAYSPERNYEAR + 1,
|
||||
MONSPERYEAR = 12,
|
||||
YEARSPERREPEAT = 400 /* years before a Gregorian repeat */
|
||||
};
|
||||
|
||||
#define SECSPERMIN 60
|
||||
#define MINSPERHOUR 60
|
||||
#define HOURSPERDAY 24
|
||||
#define DAYSPERWEEK 7
|
||||
#define DAYSPERNYEAR 365
|
||||
#define DAYSPERLYEAR 366
|
||||
#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
|
||||
#define SECSPERDAY ((int_fast32_t) SECSPERHOUR * HOURSPERDAY)
|
||||
#define MONSPERYEAR 12
|
||||
|
||||
#define TM_SUNDAY 0
|
||||
#define TM_MONDAY 1
|
||||
#define TM_TUESDAY 2
|
||||
#define TM_WEDNESDAY 3
|
||||
#define TM_THURSDAY 4
|
||||
#define TM_FRIDAY 5
|
||||
#define TM_SATURDAY 6
|
||||
#define DAYSPERREPEAT ((int_fast32_t) 400 * 365 + 100 - 4 + 1)
|
||||
#define SECSPERREPEAT ((int_fast64_t) DAYSPERREPEAT * SECSPERDAY)
|
||||
#define AVGSECSPERYEAR (SECSPERREPEAT / YEARSPERREPEAT)
|
||||
|
||||
#define TM_JANUARY 0
|
||||
#define TM_FEBRUARY 1
|
||||
#define TM_MARCH 2
|
||||
#define TM_APRIL 3
|
||||
#define TM_MAY 4
|
||||
#define TM_JUNE 5
|
||||
#define TM_JULY 6
|
||||
#define TM_AUGUST 7
|
||||
#define TM_SEPTEMBER 8
|
||||
#define TM_OCTOBER 9
|
||||
#define TM_NOVEMBER 10
|
||||
#define TM_DECEMBER 11
|
||||
/*
|
||||
* How many years to generate (in zic.c) or search through (in localtime.c).
|
||||
* This is two years larger than the obvious 400, to avoid edge cases.
|
||||
* E.g., suppose a rule applies from 2012 on with transitions
|
||||
* in March and September, plus one-off transitions in November 2013,
|
||||
* and suppose the rule cannot be expressed as a proleptic TZ string.
|
||||
* If zic looked only at the last 400 years, it would set max_year=2413,
|
||||
* with the intent that the 400 years 2014 through 2413 will be repeated.
|
||||
* The last transition listed in the tzfile would be in 2413-09,
|
||||
* less than 400 years after the last one-off transition in 2013-11.
|
||||
* Two years is not overkill for localtime.c, as a one-year bump
|
||||
* would mishandle 2023d's America/Ciudad_Juarez for November 2422.
|
||||
*/
|
||||
enum
|
||||
{
|
||||
years_of_observations = YEARSPERREPEAT + 2};
|
||||
|
||||
#define TM_YEAR_BASE 1900
|
||||
enum
|
||||
{
|
||||
TM_SUNDAY,
|
||||
TM_MONDAY,
|
||||
TM_TUESDAY,
|
||||
TM_WEDNESDAY,
|
||||
TM_THURSDAY,
|
||||
TM_FRIDAY,
|
||||
TM_SATURDAY
|
||||
};
|
||||
|
||||
#define EPOCH_YEAR 1970
|
||||
#define EPOCH_WDAY TM_THURSDAY
|
||||
enum
|
||||
{
|
||||
TM_JANUARY,
|
||||
TM_FEBRUARY,
|
||||
TM_MARCH,
|
||||
TM_APRIL,
|
||||
TM_MAY,
|
||||
TM_JUNE,
|
||||
TM_JULY,
|
||||
TM_AUGUST,
|
||||
TM_SEPTEMBER,
|
||||
TM_OCTOBER,
|
||||
TM_NOVEMBER,
|
||||
TM_DECEMBER
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
TM_YEAR_BASE = 1900,
|
||||
TM_WDAY_BASE = TM_MONDAY,
|
||||
EPOCH_YEAR = 1970,
|
||||
EPOCH_WDAY = TM_THURSDAY
|
||||
};
|
||||
|
||||
#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
|
||||
|
||||
|
|
@ -142,14 +289,4 @@
|
|||
|
||||
#define isleap_sum(a, b) isleap((a) % 400 + (b) % 400)
|
||||
|
||||
|
||||
/*
|
||||
* The Gregorian year averages 365.2425 days, which is 31556952 seconds.
|
||||
*/
|
||||
|
||||
#define AVGSECSPERYEAR 31556952L
|
||||
#define SECSPERREPEAT \
|
||||
((int_fast64_t) YEARSPERREPEAT * (int_fast64_t) AVGSECSPERYEAR)
|
||||
#define SECSPERREPEAT_BITS 34 /* ceil(log2(SECSPERREPEAT)) */
|
||||
|
||||
#endif /* !defined PRIVATE_H */
|
||||
|
|
|
|||
|
|
@ -59,8 +59,6 @@ struct lc_time_T
|
|||
const char *date_fmt;
|
||||
};
|
||||
|
||||
#define Locale (&C_time_locale)
|
||||
|
||||
static const struct lc_time_T C_time_locale = {
|
||||
{
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
|
|
@ -80,19 +78,15 @@ static const struct lc_time_T C_time_locale = {
|
|||
"%H:%M:%S",
|
||||
|
||||
/*
|
||||
* x_fmt
|
||||
*
|
||||
* C99 and later require this format. Using just numbers (as here) makes
|
||||
* Quakers happier; it's also compatible with SVR4.
|
||||
* x_fmt C99 and later require this format. Using just numbers (as here)
|
||||
* makes Quakers happier; it's also compatible with SVR4.
|
||||
*/
|
||||
"%m/%d/%y",
|
||||
|
||||
/*
|
||||
* c_fmt
|
||||
*
|
||||
* C99 and later require this format. Previously this code used "%D %X",
|
||||
* but we now conform to C99. Note that "%a %b %d %H:%M:%S %Y" is used by
|
||||
* Solaris 2.3.
|
||||
* c_fmt C99 and later require this format. Previously this code used "%D
|
||||
* %X", but we now conform to C99. Note that "%a %b %d %H:%M:%S %Y" is
|
||||
* used by Solaris 2.3.
|
||||
*/
|
||||
"%a %b %e %T %Y",
|
||||
|
||||
|
|
@ -162,6 +156,8 @@ static char *
|
|||
_fmt(const char *format, const struct pg_tm *t, char *pt,
|
||||
const char *ptlim, enum warn *warnp)
|
||||
{
|
||||
struct lc_time_T const *Locale = &C_time_locale;
|
||||
|
||||
for (; *format; ++format)
|
||||
{
|
||||
if (*format == '%')
|
||||
|
|
@ -169,7 +165,14 @@ _fmt(const char *format, const struct pg_tm *t, char *pt,
|
|||
label:
|
||||
switch (*++format)
|
||||
{
|
||||
case '\0':
|
||||
default:
|
||||
|
||||
/*
|
||||
* Output unknown conversion specifiers as-is, to aid
|
||||
* debugging. This includes '%' at format end. This
|
||||
* conforms to C23 section 7.29.3.5 paragraph 6, which
|
||||
* says behavior is undefined here.
|
||||
*/
|
||||
--format;
|
||||
break;
|
||||
case 'A':
|
||||
|
|
@ -478,9 +481,7 @@ _fmt(const char *format, const struct pg_tm *t, char *pt,
|
|||
char const *sign;
|
||||
bool negative;
|
||||
|
||||
if (t->tm_isdst < 0)
|
||||
continue;
|
||||
diff = t->tm_gmtoff;
|
||||
diff = t->TM_GMTOFF;
|
||||
negative = diff < 0;
|
||||
if (diff == 0)
|
||||
{
|
||||
|
|
@ -506,13 +507,6 @@ _fmt(const char *format, const struct pg_tm *t, char *pt,
|
|||
warnp);
|
||||
continue;
|
||||
case '%':
|
||||
|
||||
/*
|
||||
* X311J/88-090 (4.12.3.5): if conversion char is
|
||||
* undefined, behavior is undefined. Print out the
|
||||
* character itself as printf(3) also does.
|
||||
*/
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -555,7 +549,8 @@ _yconv(int a, int b, bool convert_top, bool convert_yy,
|
|||
int lead;
|
||||
int trail;
|
||||
|
||||
#define DIVISOR 100
|
||||
int DIVISOR = 100;
|
||||
|
||||
trail = a % DIVISOR + b % DIVISOR;
|
||||
lead = a / DIVISOR + b / DIVISOR + trail / DIVISOR;
|
||||
trail %= DIVISOR;
|
||||
|
|
|
|||
|
|
@ -22,24 +22,19 @@
|
|||
|
||||
/*
|
||||
* Information about time zone files.
|
||||
* See Internet RFC 9636 for more details about the following format.
|
||||
*/
|
||||
|
||||
#define TZDEFAULT "/etc/localtime"
|
||||
#define TZDEFRULES "posixrules"
|
||||
|
||||
|
||||
/* See Internet RFC 8536 for more details about the following format. */
|
||||
|
||||
/*
|
||||
* Each file begins with. . .
|
||||
*/
|
||||
|
||||
#define TZ_MAGIC "TZif"
|
||||
#define TZ_MAGIC "TZif"
|
||||
|
||||
struct tzhead
|
||||
{
|
||||
char tzh_magic[4]; /* TZ_MAGIC */
|
||||
char tzh_version[1]; /* '\0' or '2' or '3' as of 2013 */
|
||||
char tzh_version[1]; /* '\0' or '2'-'4' as of 2021 */
|
||||
char tzh_reserved[15]; /* reserved; must be zero */
|
||||
char tzh_ttisutcnt[4]; /* coded number of trans. time flags */
|
||||
char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */
|
||||
|
|
@ -79,14 +74,16 @@ struct tzhead
|
|||
* If tzh_version is '2' or greater, the above is followed by a second instance
|
||||
* of tzhead and a second instance of the data in which each coded transition
|
||||
* time uses 8 rather than 4 chars,
|
||||
* then a POSIX-TZ-environment-variable-style string for use in handling
|
||||
* then a POSIX.1-2017 proleptic TZ string for use in handling
|
||||
* instants after the last transition time stored in the file
|
||||
* (with nothing between the newlines if there is no POSIX representation for
|
||||
* such instants).
|
||||
* (with nothing between the newlines if there is no POSIX.1-2017
|
||||
* representation for such instants).
|
||||
*
|
||||
* If tz_version is '3' or greater, the above is extended as follows.
|
||||
* First, the POSIX TZ string's hour offset may range from -167
|
||||
* through 167 as compared to the POSIX-required 0 through 24.
|
||||
* If tz_version is '3' or greater, the TZ string can be any POSIX.1-2024
|
||||
* proleptic TZ string, which means the above is extended as follows.
|
||||
* First, the TZ string's hour offset may range from -167
|
||||
* through 167 as compared to the range 0 through 24 required
|
||||
* by POSIX.1-2017 and earlier.
|
||||
* Second, its DST start time may be January 1 at 00:00 and its stop
|
||||
* time December 31 at 24:00 plus the difference between DST and
|
||||
* standard time, indicating DST all year.
|
||||
|
|
@ -97,14 +94,32 @@ struct tzhead
|
|||
* exceed any of the limits below.
|
||||
*/
|
||||
|
||||
#define TZ_MAX_TIMES 2000
|
||||
#ifndef TZ_MAX_TIMES
|
||||
/*
|
||||
* The following limit applies to localtime.c; zic has no such limit.
|
||||
* The limit must be at least 310 for Asia/Hebron with 'zic -b fat'.
|
||||
*/
|
||||
#define TZ_MAX_TIMES 2000
|
||||
#endif /* !defined TZ_MAX_TIMES */
|
||||
|
||||
/* This must be at least 17 for Europe/Samara and Europe/Vilnius. */
|
||||
#define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */
|
||||
#ifndef TZ_MAX_TYPES
|
||||
/* This must be at least 18 for Europe/Vilnius with 'zic -b fat'. */
|
||||
#define TZ_MAX_TYPES 256 /* Limited to 256 by Internet RFC 9636. */
|
||||
#endif /* !defined TZ_MAX_TYPES */
|
||||
|
||||
#define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */
|
||||
/* (limited by what unsigned chars can hold) */
|
||||
#ifndef TZ_MAX_CHARS
|
||||
/* This must be at least 40 for America/Anchorage. */
|
||||
#define TZ_MAX_CHARS 256 /* Maximum number of abbreviation characters */
|
||||
/* (limited to 256 by Internet RFC 9636) */
|
||||
#endif /* !defined TZ_MAX_CHARS */
|
||||
|
||||
#define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */
|
||||
#ifndef TZ_MAX_LEAPS
|
||||
/*
|
||||
* The following limit applies to localtime.c; zic has no such limit.
|
||||
* The limit must be at least 27 for leap seconds from 1972 through mid-2023.
|
||||
* There's a plan to discontinue leap seconds by 2035.
|
||||
*/
|
||||
#define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */
|
||||
#endif /* !defined TZ_MAX_LEAPS */
|
||||
|
||||
#endif /* !defined TZFILE_H */
|
||||
|
|
|
|||
3039
src/timezone/zic.c
3039
src/timezone/zic.c
File diff suppressed because it is too large
Load diff
|
|
@ -3720,6 +3720,7 @@ deparse_context
|
|||
deparse_expr_cxt
|
||||
deparse_namespace
|
||||
derives_hash
|
||||
desigidx_type
|
||||
dev_t
|
||||
disassembledLeaf
|
||||
dlist_head
|
||||
|
|
@ -3892,6 +3893,7 @@ int64_t
|
|||
int8
|
||||
int8_t
|
||||
int8x16_t
|
||||
int_fast32_2s
|
||||
int_fast32_t
|
||||
int_fast64_t
|
||||
internalPQconninfoOption
|
||||
|
|
|
|||
Loading…
Reference in a new issue