mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-09-04 14:57:20 +02:00
Sync back-branch copies of the timezone code with IANA release tzcode2016c.
Back-patch commit1c1a7cbd6a
, along with subsequent portability fixes, into all active branches. Also, back-patch commits696027727
and596857043
(addition of zic -P option) into 9.1 and 9.2, just to reduce differences between the branches. src/timezone/ is now largely identical in all active branches, except that in 9.1, pgtz.c retains the initial-timezone-selection code that was moved over to initdb in 9.2. Ordinarily we wouldn't risk this much code churn in back branches, but it seems necessary in this case, because among the changes are two feature additions in the "zic" zone data file compiler (a larger limit on the number of allowed DST transitions, and addition of a "%z" escape in zone abbreviations). IANA have not yet started to use those features in their tzdata files, but presumably they will before too long. If we don't update then we'll be unable to adopt new timezone data. Also, installations built with --with-system-tzdata (which includes most distro-supplied builds, I believe) might fail even if we don't update our copies of the data files. There are assorted bug fixes too, mostly affecting obscure timezones or post-2037 dates. Discussion: <13601.1468868947@sss.pgh.pa.us>
This commit is contained in:
parent
bdeed0944f
commit
19d477aa68
@ -99,15 +99,15 @@ pg_load_tz(const char *name)
|
|||||||
*/
|
*/
|
||||||
if (strcmp(name, "GMT") == 0)
|
if (strcmp(name, "GMT") == 0)
|
||||||
{
|
{
|
||||||
if (tzparse(name, &tz.state, TRUE) != 0)
|
if (!tzparse(name, &tz.state, true))
|
||||||
{
|
{
|
||||||
/* This really, really should not happen ... */
|
/* This really, really should not happen ... */
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (tzload(name, NULL, &tz.state, TRUE) != 0)
|
else if (tzload(name, NULL, &tz.state, true) != 0)
|
||||||
{
|
{
|
||||||
if (name[0] == ':' || tzparse(name, &tz.state, FALSE) != 0)
|
if (name[0] == ':' || !tzparse(name, &tz.state, false))
|
||||||
{
|
{
|
||||||
return NULL; /* unknown timezone */
|
return NULL; /* unknown timezone */
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ include $(top_builddir)/src/Makefile.global
|
|||||||
OBJS= localtime.o strftime.o pgtz.o
|
OBJS= localtime.o strftime.o pgtz.o
|
||||||
|
|
||||||
# files needed to build zic utility program
|
# files needed to build zic utility program
|
||||||
ZICOBJS= zic.o ialloc.o scheck.o localtime.o $(WIN32RES)
|
ZICOBJS= zic.o $(WIN32RES)
|
||||||
|
|
||||||
# timezone data files
|
# timezone data files
|
||||||
TZDATA = africa antarctica asia australasia europe northamerica southamerica \
|
TZDATA = africa antarctica asia australasia europe northamerica southamerica \
|
||||||
|
@ -1,26 +1,24 @@
|
|||||||
src/timezone/README
|
src/timezone/README
|
||||||
|
|
||||||
Timezone
|
This is a PostgreSQL adapted version of the IANA timezone library from
|
||||||
========
|
|
||||||
|
|
||||||
This is a PostgreSQL adapted version of the timezone library from
|
|
||||||
http://www.iana.org/time-zones
|
http://www.iana.org/time-zones
|
||||||
|
|
||||||
The source code can be found at:
|
The latest versions of both the tzdata and tzcode tarballs are normally
|
||||||
|
available right from that page. Historical versions can be found
|
||||||
ftp://ftp.iana.org/tz/releases/tzcode*.tar.gz
|
elsewhere on the site.
|
||||||
|
|
||||||
The code is currently synced with release 2010c. 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.
|
|
||||||
|
|
||||||
The data files under data/ are an exact copy of the latest data set from:
|
|
||||||
|
|
||||||
ftp://ftp.iana.org/tz/releases/tzdata*.tar.gz
|
|
||||||
|
|
||||||
Since time zone rules change frequently in some parts of the world,
|
Since time zone rules change frequently in some parts of the world,
|
||||||
we should endeavor to update the data files before each PostgreSQL
|
we should endeavor to update the data files before each PostgreSQL
|
||||||
release.
|
release. The code need not be updated as often, but we must track
|
||||||
|
changes that might affect interpretation of the data files.
|
||||||
|
|
||||||
|
|
||||||
|
Time Zone data
|
||||||
|
==============
|
||||||
|
|
||||||
|
The data files under data/ are an exact copy of the latest tzdata set,
|
||||||
|
except that we omit some files that are not of interest for our purposes.
|
||||||
|
|
||||||
While the files under data/ can just be duplicated when updating, manual
|
While the files under data/ can just be duplicated when updating, manual
|
||||||
effort is needed to update the time zone abbreviation lists under tznames/.
|
effort is needed to update the time zone abbreviation lists under tznames/.
|
||||||
@ -32,7 +30,9 @@ which will produce a file showing all abbreviations that are in current
|
|||||||
use according to the data/ files. Compare this to known_abbrevs.txt,
|
use according to the data/ files. Compare this to known_abbrevs.txt,
|
||||||
which is the list that existed last time the tznames/ files were updated.
|
which is the list that existed last time the tznames/ files were updated.
|
||||||
Update tznames/ as seems appropriate, then replace known_abbrevs.txt
|
Update tznames/ as seems appropriate, then replace known_abbrevs.txt
|
||||||
in the same commit.
|
in the same commit. Usually, if a known abbreviation has changed meaning,
|
||||||
|
the appropriate fix is to make it refer to a long-form zone name instead
|
||||||
|
of a fixed GMT offset.
|
||||||
|
|
||||||
When there has been a new release of Windows (probably including Service
|
When there has been a new release of Windows (probably including Service
|
||||||
Packs), the list of matching timezones need to be updated. Run the
|
Packs), the list of matching timezones need to be updated. Run the
|
||||||
@ -40,3 +40,64 @@ script in src/tools/win32tzlist.pl on a Windows machine running this new
|
|||||||
release and apply any new timezones that it detects. Never remove any
|
release and apply any new timezones that it detects. Never remove any
|
||||||
mappings in case they are removed in Windows, since we still need to
|
mappings in case they are removed in Windows, since we still need to
|
||||||
match properly on the old version.
|
match properly on the old version.
|
||||||
|
|
||||||
|
|
||||||
|
Time Zone code
|
||||||
|
==============
|
||||||
|
|
||||||
|
The code in this directory is currently synced with tzcode release 2016c.
|
||||||
|
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.
|
||||||
|
|
||||||
|
For the most part we want to use the upstream code as-is, but there are
|
||||||
|
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.)
|
||||||
|
|
||||||
|
* We need the code to follow Postgres' portability conventions; this
|
||||||
|
includes relying on configure's results rather than hand-hacked #defines,
|
||||||
|
and not relying on <stdint.h> features that may not exist on old systems.
|
||||||
|
(In particular this means using Postgres' definitions of the int32 and
|
||||||
|
int64 typedefs, not int_fast32_t/int_fast64_t.)
|
||||||
|
|
||||||
|
* Since Postgres is typically built on a system that has its own copy
|
||||||
|
of the <time.h> functions, we must avoid conflicting with those. This
|
||||||
|
mandates renaming typedef time_t to pg_time_t, and similarly for most
|
||||||
|
other exposed names.
|
||||||
|
|
||||||
|
* 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.
|
||||||
|
|
||||||
|
* There's a fair amount of code we don't need and have removed,
|
||||||
|
including all the nonstandard optional APIs. We have also added
|
||||||
|
a few functions of our own at the bottom of localtime.c.
|
||||||
|
|
||||||
|
* In zic.c, we have added support for a -P (print_abbrevs) switch, which
|
||||||
|
is used to create the "abbrevs.txt" summary of currently-in-use zone
|
||||||
|
abbreviations that was described above.
|
||||||
|
|
||||||
|
|
||||||
|
The most convenient way to compare a new tzcode release to our code is
|
||||||
|
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/int_fast32_t/int32/g' \
|
||||||
|
-e 's/int_fast64_t/int64/g' \
|
||||||
|
-e 's/struct[ \t]+tm\b/struct pg_tm/g' \
|
||||||
|
-e 's/\btime_t\b/pg_time_t/g' \
|
||||||
|
|
||||||
|
and then run them through pgindent. (The first three 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.
|
||||||
|
@ -1,76 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is in the public domain, so clarified as of
|
|
||||||
* 2006-07-17 by Arthur David Olson.
|
|
||||||
*
|
|
||||||
* IDENTIFICATION
|
|
||||||
* src/timezone/ialloc.c
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "postgres_fe.h"
|
|
||||||
|
|
||||||
#include "private.h"
|
|
||||||
|
|
||||||
|
|
||||||
#define nonzero(n) (((n) == 0) ? 1 : (n))
|
|
||||||
|
|
||||||
char *
|
|
||||||
imalloc(int n)
|
|
||||||
{
|
|
||||||
return malloc((size_t) nonzero(n));
|
|
||||||
}
|
|
||||||
|
|
||||||
char *
|
|
||||||
icalloc(int nelem, int elsize)
|
|
||||||
{
|
|
||||||
if (nelem == 0 || elsize == 0)
|
|
||||||
nelem = elsize = 1;
|
|
||||||
return calloc((size_t) nelem, (size_t) elsize);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *
|
|
||||||
irealloc(void *pointer, int size)
|
|
||||||
{
|
|
||||||
if (pointer == NULL)
|
|
||||||
return imalloc(size);
|
|
||||||
return realloc((void *) pointer, (size_t) nonzero(size));
|
|
||||||
}
|
|
||||||
|
|
||||||
char *
|
|
||||||
icatalloc(char *old, const char *new)
|
|
||||||
{
|
|
||||||
char *result;
|
|
||||||
int oldsize,
|
|
||||||
newsize;
|
|
||||||
|
|
||||||
newsize = (new == NULL) ? 0 : strlen(new);
|
|
||||||
if (old == NULL)
|
|
||||||
oldsize = 0;
|
|
||||||
else if (newsize == 0)
|
|
||||||
return old;
|
|
||||||
else
|
|
||||||
oldsize = strlen(old);
|
|
||||||
if ((result = irealloc(old, oldsize + newsize + 1)) != NULL)
|
|
||||||
if (new != NULL)
|
|
||||||
(void) strcpy(result + oldsize, new);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *
|
|
||||||
icpyalloc(const char *string)
|
|
||||||
{
|
|
||||||
return icatalloc((char *) NULL, string);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ifree(char *p)
|
|
||||||
{
|
|
||||||
if (p != NULL)
|
|
||||||
(void) free(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
icfree(char *p)
|
|
||||||
{
|
|
||||||
if (p != NULL)
|
|
||||||
(void) free(p);
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -256,7 +256,7 @@ pg_tzset(const char *name)
|
|||||||
*/
|
*/
|
||||||
if (strcmp(uppername, "GMT") == 0)
|
if (strcmp(uppername, "GMT") == 0)
|
||||||
{
|
{
|
||||||
if (tzparse(uppername, &tzstate, TRUE) != 0)
|
if (!tzparse(uppername, &tzstate, true))
|
||||||
{
|
{
|
||||||
/* This really, really should not happen ... */
|
/* This really, really should not happen ... */
|
||||||
elog(ERROR, "could not initialize GMT time zone");
|
elog(ERROR, "could not initialize GMT time zone");
|
||||||
@ -264,9 +264,9 @@ pg_tzset(const char *name)
|
|||||||
/* Use uppercase name as canonical */
|
/* Use uppercase name as canonical */
|
||||||
strcpy(canonname, uppername);
|
strcpy(canonname, uppername);
|
||||||
}
|
}
|
||||||
else if (tzload(uppername, canonname, &tzstate, TRUE) != 0)
|
else if (tzload(uppername, canonname, &tzstate, true) != 0)
|
||||||
{
|
{
|
||||||
if (uppername[0] == ':' || tzparse(uppername, &tzstate, FALSE) != 0)
|
if (uppername[0] == ':' || !tzparse(uppername, &tzstate, false))
|
||||||
{
|
{
|
||||||
/* Unknown timezone. Fail our call instead of loading GMT! */
|
/* Unknown timezone. Fail our call instead of loading GMT! */
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -460,7 +460,7 @@ pg_tzenumerate_next(pg_tzenum *dir)
|
|||||||
* the cache
|
* the cache
|
||||||
*/
|
*/
|
||||||
if (tzload(fullname + dir->baselen, dir->tz.TZname, &dir->tz.state,
|
if (tzload(fullname + dir->baselen, dir->tz.TZname, &dir->tz.state,
|
||||||
TRUE) != 0)
|
true) != 0)
|
||||||
{
|
{
|
||||||
/* Zone could not be loaded, ignore it */
|
/* Zone could not be loaded, ignore it */
|
||||||
continue;
|
continue;
|
||||||
|
@ -16,25 +16,26 @@
|
|||||||
#ifndef _PGTZ_H
|
#ifndef _PGTZ_H
|
||||||
#define _PGTZ_H
|
#define _PGTZ_H
|
||||||
|
|
||||||
#include "tzfile.h"
|
|
||||||
#include "pgtime.h"
|
#include "pgtime.h"
|
||||||
|
#include "tzfile.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define SMALLEST(a, b) (((a) < (b)) ? (a) : (b))
|
||||||
#define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
|
#define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
|
||||||
|
|
||||||
struct ttinfo
|
struct ttinfo
|
||||||
{ /* time type information */
|
{ /* time type information */
|
||||||
long tt_gmtoff; /* UTC offset in seconds */
|
int32 tt_gmtoff; /* UT offset in seconds */
|
||||||
int tt_isdst; /* used to set tm_isdst */
|
bool tt_isdst; /* used to set tm_isdst */
|
||||||
int tt_abbrind; /* abbreviation list index */
|
int tt_abbrind; /* abbreviation list index */
|
||||||
int tt_ttisstd; /* TRUE if transition is std time */
|
bool tt_ttisstd; /* transition is std time */
|
||||||
int tt_ttisgmt; /* TRUE if transition is UTC */
|
bool tt_ttisgmt; /* transition is UT */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct lsinfo
|
struct lsinfo
|
||||||
{ /* leap second information */
|
{ /* leap second information */
|
||||||
pg_time_t ls_trans; /* transition time */
|
pg_time_t ls_trans; /* transition time */
|
||||||
long ls_corr; /* correction to apply */
|
int64 ls_corr; /* correction to apply */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct state
|
struct state
|
||||||
@ -43,14 +44,15 @@ struct state
|
|||||||
int timecnt;
|
int timecnt;
|
||||||
int typecnt;
|
int typecnt;
|
||||||
int charcnt;
|
int charcnt;
|
||||||
int goback;
|
bool goback;
|
||||||
int goahead;
|
bool goahead;
|
||||||
pg_time_t ats[TZ_MAX_TIMES];
|
pg_time_t ats[TZ_MAX_TIMES];
|
||||||
unsigned char types[TZ_MAX_TIMES];
|
unsigned char types[TZ_MAX_TIMES];
|
||||||
struct ttinfo ttis[TZ_MAX_TYPES];
|
struct ttinfo ttis[TZ_MAX_TYPES];
|
||||||
char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, 3 /* sizeof gmt */ ),
|
char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, 3 /* sizeof gmt */ ),
|
||||||
(2 * (TZ_STRLEN_MAX + 1)))];
|
(2 * (TZ_STRLEN_MAX + 1)))];
|
||||||
struct lsinfo lsis[TZ_MAX_LEAPS];
|
struct lsinfo lsis[TZ_MAX_LEAPS];
|
||||||
|
int defaulttype; /* for early times or if no transitions */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -67,7 +69,7 @@ extern int pg_open_tzfile(const char *name, char *canonname);
|
|||||||
|
|
||||||
/* in localtime.c */
|
/* in localtime.c */
|
||||||
extern int tzload(const char *name, char *canonname, struct state * sp,
|
extern int tzload(const char *name, char *canonname, struct state * sp,
|
||||||
int doextend);
|
bool doextend);
|
||||||
extern int tzparse(const char *name, struct state * sp, int lastditch);
|
extern bool tzparse(const char *name, struct state * sp, bool lastditch);
|
||||||
|
|
||||||
#endif /* _PGTZ_H */
|
#endif /* _PGTZ_H */
|
||||||
|
@ -25,6 +25,18 @@
|
|||||||
|
|
||||||
#define GRANDPARENTED "Local time zone must be set--see zic manual page"
|
#define GRANDPARENTED "Local time zone must be set--see zic manual page"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ENOTSUP
|
||||||
|
#define ENOTSUP EINVAL
|
||||||
|
#endif
|
||||||
|
#ifndef EOVERFLOW
|
||||||
|
#define EOVERFLOW EINVAL
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef WIFEXITED
|
#ifndef WIFEXITED
|
||||||
#define WIFEXITED(status) (((status) & 0xff) == 0)
|
#define WIFEXITED(status) (((status) & 0xff) == 0)
|
||||||
#endif /* !defined WIFEXITED */
|
#endif /* !defined WIFEXITED */
|
||||||
@ -35,6 +47,10 @@
|
|||||||
/* Unlike <ctype.h>'s isdigit, this also works if c < 0 | c > UCHAR_MAX. */
|
/* Unlike <ctype.h>'s isdigit, this also works if c < 0 | c > UCHAR_MAX. */
|
||||||
#define is_digit(c) ((unsigned)(c) - '0' <= 9)
|
#define is_digit(c) ((unsigned)(c) - '0' <= 9)
|
||||||
|
|
||||||
|
#ifndef SIZE_MAX
|
||||||
|
#define SIZE_MAX ((size_t) -1)
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SunOS 4.1.1 libraries lack remove.
|
* SunOS 4.1.1 libraries lack remove.
|
||||||
*/
|
*/
|
||||||
@ -45,31 +61,11 @@ extern int unlink(const char *filename);
|
|||||||
#define remove unlink
|
#define remove unlink
|
||||||
#endif /* !defined remove */
|
#endif /* !defined remove */
|
||||||
|
|
||||||
/*
|
|
||||||
* Private function declarations.
|
|
||||||
*/
|
|
||||||
extern char *icalloc(int nelem, int elsize);
|
|
||||||
extern char *icatalloc(char *old, const char *new);
|
|
||||||
extern char *icpyalloc(const char *string);
|
|
||||||
extern char *imalloc(int n);
|
|
||||||
extern void *irealloc(void *pointer, int size);
|
|
||||||
extern void icfree(char *pointer);
|
|
||||||
extern void ifree(char *pointer);
|
|
||||||
extern const char *scheck(const char *string, const char *format);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Finally, some convenience items.
|
* Finally, some convenience items.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef TRUE
|
|
||||||
#define TRUE 1
|
|
||||||
#endif /* !defined TRUE */
|
|
||||||
|
|
||||||
#ifndef FALSE
|
|
||||||
#define FALSE 0
|
|
||||||
#endif /* !defined FALSE */
|
|
||||||
|
|
||||||
#ifndef TYPE_BIT
|
#ifndef TYPE_BIT
|
||||||
#define TYPE_BIT(type) (sizeof (type) * CHAR_BIT)
|
#define TYPE_BIT(type) (sizeof (type) * CHAR_BIT)
|
||||||
#endif /* !defined TYPE_BIT */
|
#endif /* !defined TYPE_BIT */
|
||||||
@ -78,14 +74,18 @@ extern const char *scheck(const char *string, const char *format);
|
|||||||
#define TYPE_SIGNED(type) (((type) -1) < 0)
|
#define TYPE_SIGNED(type) (((type) -1) < 0)
|
||||||
#endif /* !defined TYPE_SIGNED */
|
#endif /* !defined TYPE_SIGNED */
|
||||||
|
|
||||||
/*
|
#define TWOS_COMPLEMENT(t) ((t) ~ (t) 0 < 0)
|
||||||
* Since the definition of TYPE_INTEGRAL contains floating point numbers,
|
|
||||||
* it cannot be used in preprocessor directives.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef TYPE_INTEGRAL
|
/*
|
||||||
#define TYPE_INTEGRAL(type) (((type) 0.5) != 0.5)
|
* Max and min values of the integer type T, of which only the bottom
|
||||||
#endif /* !defined TYPE_INTEGRAL */
|
* B bits are used, and where the highest-order used bit is considered
|
||||||
|
* to be a sign bit if T is signed.
|
||||||
|
*/
|
||||||
|
#define MAXVAL(t, b) \
|
||||||
|
((t) (((t) 1 << ((b) - 1 - TYPE_SIGNED(t))) \
|
||||||
|
- 1 + ((t) 1 << ((b) - 1 - TYPE_SIGNED(t)))))
|
||||||
|
#define MINVAL(t, b) \
|
||||||
|
((t) (TYPE_SIGNED(t) ? - TWOS_COMPLEMENT(t) - MAXVAL(t, b) : 0))
|
||||||
|
|
||||||
#ifndef INT_STRLEN_MAXIMUM
|
#ifndef INT_STRLEN_MAXIMUM
|
||||||
/*
|
/*
|
||||||
@ -95,9 +95,15 @@ extern const char *scheck(const char *string, const char *format);
|
|||||||
* add one more for a minus sign if the type is signed.
|
* add one more for a minus sign if the type is signed.
|
||||||
*/
|
*/
|
||||||
#define INT_STRLEN_MAXIMUM(type) \
|
#define INT_STRLEN_MAXIMUM(type) \
|
||||||
((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + 1 + TYPE_SIGNED(type))
|
((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + \
|
||||||
|
1 + TYPE_SIGNED(type))
|
||||||
#endif /* !defined INT_STRLEN_MAXIMUM */
|
#endif /* !defined INT_STRLEN_MAXIMUM */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* INITIALIZE(x)
|
||||||
|
*/
|
||||||
|
#define INITIALIZE(x) ((x) = 0)
|
||||||
|
|
||||||
#undef _
|
#undef _
|
||||||
#define _(msgid) (msgid)
|
#define _(msgid) (msgid)
|
||||||
|
|
||||||
@ -106,7 +112,7 @@ extern const char *scheck(const char *string, const char *format);
|
|||||||
#endif /* !defined YEARSPERREPEAT */
|
#endif /* !defined YEARSPERREPEAT */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** The Gregorian year averages 365.2425 days, which is 31556952 seconds.
|
* The Gregorian year averages 365.2425 days, which is 31556952 seconds.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef AVGSECSPERYEAR
|
#ifndef AVGSECSPERYEAR
|
||||||
@ -121,8 +127,4 @@ extern const char *scheck(const char *string, const char *format);
|
|||||||
#define SECSPERREPEAT_BITS 34 /* ceil(log2(SECSPERREPEAT)) */
|
#define SECSPERREPEAT_BITS 34 /* ceil(log2(SECSPERREPEAT)) */
|
||||||
#endif /* !defined SECSPERREPEAT_BITS */
|
#endif /* !defined SECSPERREPEAT_BITS */
|
||||||
|
|
||||||
/*
|
|
||||||
* UNIX was a registered trademark of The Open Group in 2003.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#endif /* !defined PRIVATE_H */
|
#endif /* !defined PRIVATE_H */
|
||||||
|
@ -1,62 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is in the public domain, so clarified as of
|
|
||||||
* 2006-07-17 by Arthur David Olson.
|
|
||||||
*
|
|
||||||
* IDENTIFICATION
|
|
||||||
* src/timezone/scheck.c
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "postgres_fe.h"
|
|
||||||
|
|
||||||
#include "private.h"
|
|
||||||
|
|
||||||
|
|
||||||
const char *
|
|
||||||
scheck(const char *string, const char *format)
|
|
||||||
{
|
|
||||||
char *fbuf;
|
|
||||||
const char *fp;
|
|
||||||
char *tp;
|
|
||||||
int c;
|
|
||||||
const char *result;
|
|
||||||
char dummy;
|
|
||||||
|
|
||||||
result = "";
|
|
||||||
if (string == NULL || format == NULL)
|
|
||||||
return result;
|
|
||||||
fbuf = imalloc((int) (2 * strlen(format) + 4));
|
|
||||||
if (fbuf == NULL)
|
|
||||||
return result;
|
|
||||||
fp = format;
|
|
||||||
tp = fbuf;
|
|
||||||
while ((*tp++ = c = *fp++) != '\0')
|
|
||||||
{
|
|
||||||
if (c != '%')
|
|
||||||
continue;
|
|
||||||
if (*fp == '%')
|
|
||||||
{
|
|
||||||
*tp++ = *fp++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
*tp++ = '*';
|
|
||||||
if (*fp == '*')
|
|
||||||
++fp;
|
|
||||||
while (is_digit(*fp))
|
|
||||||
*tp++ = *fp++;
|
|
||||||
if (*fp == 'l' || *fp == 'h')
|
|
||||||
*tp++ = *fp++;
|
|
||||||
else if (*fp == '[')
|
|
||||||
do
|
|
||||||
*tp++ = *fp++;
|
|
||||||
while (*fp != '\0' && *fp != ']');
|
|
||||||
if ((*tp++ = *fp++) == '\0')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
*(tp - 1) = '%';
|
|
||||||
*tp++ = 'c';
|
|
||||||
*tp = '\0';
|
|
||||||
if (sscanf(string, fbuf, &dummy) != 1)
|
|
||||||
result = (char *) format;
|
|
||||||
ifree(fbuf);
|
|
||||||
return result;
|
|
||||||
}
|
|
@ -1,18 +1,38 @@
|
|||||||
|
/* Convert a broken-down time stamp to a string. */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1989 The Regents of the University of California.
|
* Copyright 1989 The Regents of the University of California.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms are permitted
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* provided that the above copyright notice and this paragraph are
|
* modification, are permitted provided that the following conditions
|
||||||
* duplicated in all such forms and that any documentation,
|
* are met:
|
||||||
* advertising materials, and other materials related to such
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
* distribution and use acknowledge that the software was developed
|
* notice, this list of conditions and the following disclaimer.
|
||||||
* by the University of California, Berkeley. The name of the
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
* University may not be used to endorse or promote products derived
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
* from this software without specific prior written permission.
|
* documentation and/or other materials provided with the distribution.
|
||||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
* may be used to endorse or promote products derived from this software
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Based on the UCB version with the copyright notice appearing above.
|
||||||
|
*
|
||||||
|
* This is ANSIish only when "multibyte character == plain character".
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* src/timezone/strftime.c
|
* src/timezone/strftime.c
|
||||||
@ -92,8 +112,7 @@ static char *_add(const char *, char *, const char *);
|
|||||||
static char *_conv(int, const char *, char *, const char *);
|
static char *_conv(int, const char *, char *, const char *);
|
||||||
static char *_fmt(const char *, const struct pg_tm *, char *,
|
static char *_fmt(const char *, const struct pg_tm *, char *,
|
||||||
const char *, int *);
|
const char *, int *);
|
||||||
static char *_yconv(const int, const int, const int, const int,
|
static char *_yconv(int, int, bool, bool, char *, const char *);
|
||||||
char *, const char *const);
|
|
||||||
|
|
||||||
#define IN_NONE 0
|
#define IN_NONE 0
|
||||||
#define IN_SOME 1
|
#define IN_SOME 1
|
||||||
@ -162,8 +181,8 @@ _fmt(const char *format, const struct pg_tm * t, char *pt, const char *ptlim,
|
|||||||
* ...whereas now POSIX 1003.2 calls for something
|
* ...whereas now POSIX 1003.2 calls for something
|
||||||
* completely different. (ado, 1993-05-24)
|
* completely different. (ado, 1993-05-24)
|
||||||
*/
|
*/
|
||||||
pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 0,
|
pt = _yconv(t->tm_year, TM_YEAR_BASE,
|
||||||
pt, ptlim);
|
true, false, pt, ptlim);
|
||||||
continue;
|
continue;
|
||||||
case 'c':
|
case 'c':
|
||||||
{
|
{
|
||||||
@ -224,7 +243,7 @@ _fmt(const char *format, const struct pg_tm * t, char *pt, const char *ptlim,
|
|||||||
case 'K':
|
case 'K':
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* * After all this time, still unclaimed!
|
* After all this time, still unclaimed!
|
||||||
*/
|
*/
|
||||||
pt = _add("kitchen sink", pt, ptlim);
|
pt = _add("kitchen sink", pt, ptlim);
|
||||||
continue;
|
continue;
|
||||||
@ -296,7 +315,7 @@ _fmt(const char *format, const struct pg_tm * t, char *pt, const char *ptlim,
|
|||||||
* (01-53)."
|
* (01-53)."
|
||||||
* (ado, 1993-05-24)
|
* (ado, 1993-05-24)
|
||||||
*
|
*
|
||||||
* From "http://www.ft.uni-erlangen.de/~mskuhn/iso-time.html" by Markus Kuhn:
|
* From <http://www.ft.uni-erlangen.de/~mskuhn/iso-time.html> by Markus Kuhn:
|
||||||
* "Week 01 of a year is per definition the first week which has the
|
* "Week 01 of a year is per definition the first week which has the
|
||||||
* Thursday in this year, which is equivalent to the week which contains
|
* Thursday in this year, which is equivalent to the week which contains
|
||||||
* the fourth day of January. In other words, the first week of a new year
|
* the fourth day of January. In other words, the first week of a new year
|
||||||
@ -367,11 +386,13 @@ _fmt(const char *format, const struct pg_tm * t, char *pt, const char *ptlim,
|
|||||||
else if (*format == 'g')
|
else if (*format == 'g')
|
||||||
{
|
{
|
||||||
*warnp = IN_ALL;
|
*warnp = IN_ALL;
|
||||||
pt = _yconv(year, base, 0, 1,
|
pt = _yconv(year, base,
|
||||||
|
false, true,
|
||||||
pt, ptlim);
|
pt, ptlim);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
pt = _yconv(year, base, 1, 1,
|
pt = _yconv(year, base,
|
||||||
|
true, true,
|
||||||
pt, ptlim);
|
pt, ptlim);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
@ -409,11 +430,13 @@ _fmt(const char *format, const struct pg_tm * t, char *pt, const char *ptlim,
|
|||||||
continue;
|
continue;
|
||||||
case 'y':
|
case 'y':
|
||||||
*warnp = IN_ALL;
|
*warnp = IN_ALL;
|
||||||
pt = _yconv(t->tm_year, TM_YEAR_BASE, 0, 1,
|
pt = _yconv(t->tm_year, TM_YEAR_BASE,
|
||||||
|
false, true,
|
||||||
pt, ptlim);
|
pt, ptlim);
|
||||||
continue;
|
continue;
|
||||||
case 'Y':
|
case 'Y':
|
||||||
pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 1,
|
pt = _yconv(t->tm_year, TM_YEAR_BASE,
|
||||||
|
true, true,
|
||||||
pt, ptlim);
|
pt, ptlim);
|
||||||
continue;
|
continue;
|
||||||
case 'Z':
|
case 'Z':
|
||||||
@ -427,7 +450,7 @@ _fmt(const char *format, const struct pg_tm * t, char *pt, const char *ptlim,
|
|||||||
continue;
|
continue;
|
||||||
case 'z':
|
case 'z':
|
||||||
{
|
{
|
||||||
int diff;
|
long diff;
|
||||||
char const *sign;
|
char const *sign;
|
||||||
|
|
||||||
if (t->tm_isdst < 0)
|
if (t->tm_isdst < 0)
|
||||||
@ -441,9 +464,10 @@ _fmt(const char *format, const struct pg_tm * t, char *pt, const char *ptlim,
|
|||||||
else
|
else
|
||||||
sign = "+";
|
sign = "+";
|
||||||
pt = _add(sign, pt, ptlim);
|
pt = _add(sign, pt, ptlim);
|
||||||
diff /= 60;
|
diff /= SECSPERMIN;
|
||||||
pt = _conv((diff / 60) * 100 + diff % 60,
|
diff = (diff / MINSPERHOUR) * 100 +
|
||||||
"%04d", pt, ptlim);
|
(diff % MINSPERHOUR);
|
||||||
|
pt = _conv(diff, "%04d", pt, ptlim);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
case '+':
|
case '+':
|
||||||
@ -473,7 +497,7 @@ _conv(int n, const char *format, char *pt, const char *ptlim)
|
|||||||
{
|
{
|
||||||
char buf[INT_STRLEN_MAXIMUM(int) +1];
|
char buf[INT_STRLEN_MAXIMUM(int) +1];
|
||||||
|
|
||||||
(void) sprintf(buf, format, n);
|
sprintf(buf, format, n);
|
||||||
return _add(buf, pt, ptlim);
|
return _add(buf, pt, ptlim);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -493,8 +517,8 @@ _add(const char *str, char *pt, const char *ptlim)
|
|||||||
* with more only if necessary.
|
* with more only if necessary.
|
||||||
*/
|
*/
|
||||||
static char *
|
static char *
|
||||||
_yconv(const int a, const int b, const int convert_top,
|
_yconv(int a, int b, bool convert_top, bool convert_yy,
|
||||||
const int convert_yy, char *pt, const char *const ptlim)
|
char *pt, const char *ptlim)
|
||||||
{
|
{
|
||||||
int lead;
|
int lead;
|
||||||
int trail;
|
int trail;
|
||||||
|
@ -33,8 +33,8 @@
|
|||||||
struct tzhead
|
struct tzhead
|
||||||
{
|
{
|
||||||
char tzh_magic[4]; /* TZ_MAGIC */
|
char tzh_magic[4]; /* TZ_MAGIC */
|
||||||
char tzh_version[1]; /* '\0' or '2' as of 2005 */
|
char tzh_version[1]; /* '\0' or '2' or '3' as of 2013 */
|
||||||
char tzh_reserved[15]; /* reserved--must be zero */
|
char tzh_reserved[15]; /* reserved; must be zero */
|
||||||
char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */
|
char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */
|
||||||
char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */
|
char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */
|
||||||
char tzh_leapcnt[4]; /* coded number of leap seconds */
|
char tzh_leapcnt[4]; /* coded number of leap seconds */
|
||||||
@ -43,30 +43,29 @@ struct tzhead
|
|||||||
char tzh_charcnt[4]; /* coded number of abbr. chars */
|
char tzh_charcnt[4]; /* coded number of abbr. chars */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*----------
|
/*
|
||||||
* . . .followed by. . .
|
* . . .followed by. . .
|
||||||
*
|
*
|
||||||
* tzh_timecnt (char [4])s coded transition times a la time(2)
|
* tzh_timecnt (char [4])s coded transition times a la time(2)
|
||||||
* tzh_timecnt (unsigned char)s types of local time starting at above
|
* tzh_timecnt (unsigned char)s types of local time starting at above
|
||||||
* tzh_typecnt repetitions of
|
* tzh_typecnt repetitions of
|
||||||
* one (char [4]) coded UTC offset in seconds
|
* one (char [4]) coded UT offset in seconds
|
||||||
* one (unsigned char) used to set tm_isdst
|
* one (unsigned char) used to set tm_isdst
|
||||||
* one (unsigned char) that's an abbreviation list index
|
* one (unsigned char) that's an abbreviation list index
|
||||||
* tzh_charcnt (char)s '\0'-terminated zone abbreviations
|
* tzh_charcnt (char)s '\0'-terminated zone abbreviations
|
||||||
* tzh_leapcnt repetitions of
|
* tzh_leapcnt repetitions of
|
||||||
* one (char [4]) coded leap second transition times
|
* one (char [4]) coded leap second transition times
|
||||||
* one (char [4]) total correction after above
|
* one (char [4]) total correction after above
|
||||||
* tzh_ttisstdcnt (char)s indexed by type; if TRUE, transition
|
* tzh_ttisstdcnt (char)s indexed by type; if 1, transition
|
||||||
* time is standard time, if FALSE,
|
* time is standard time, if 0,
|
||||||
* transition time is wall clock time
|
* transition time is wall clock time
|
||||||
* if absent, transition times are
|
* if absent, transition times are
|
||||||
* assumed to be wall clock time
|
* assumed to be wall clock time
|
||||||
* tzh_ttisgmtcnt (char)s indexed by type; if TRUE, transition
|
* tzh_ttisgmtcnt (char)s indexed by type; if 1, transition
|
||||||
* time is UTC, if FALSE,
|
* time is UT, if 0,
|
||||||
* transition time is local time
|
* transition time is local time
|
||||||
* if absent, transition times are
|
* if absent, transition times are
|
||||||
* assumed to be local time
|
* assumed to be local time
|
||||||
*----------
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -77,6 +76,13 @@ struct tzhead
|
|||||||
* instants after the last transition time stored in the file
|
* instants after the last transition time stored in the file
|
||||||
* (with nothing between the newlines if there is no POSIX representation for
|
* (with nothing between the newlines if there is no POSIX representation for
|
||||||
* such instants).
|
* 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.
|
||||||
|
* 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.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -84,8 +90,9 @@ struct tzhead
|
|||||||
* exceed any of the limits below.
|
* exceed any of the limits below.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define TZ_MAX_TIMES 1200
|
#define TZ_MAX_TIMES 2000
|
||||||
|
|
||||||
|
/* 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 */
|
#define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */
|
||||||
|
|
||||||
#define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */
|
#define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */
|
||||||
@ -100,7 +107,7 @@ struct tzhead
|
|||||||
#define DAYSPERNYEAR 365
|
#define DAYSPERNYEAR 365
|
||||||
#define DAYSPERLYEAR 366
|
#define DAYSPERLYEAR 366
|
||||||
#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
|
#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
|
||||||
#define SECSPERDAY ((long) SECSPERHOUR * HOURSPERDAY)
|
#define SECSPERDAY ((int32) SECSPERHOUR * HOURSPERDAY)
|
||||||
#define MONSPERYEAR 12
|
#define MONSPERYEAR 12
|
||||||
|
|
||||||
#define TM_SUNDAY 0
|
#define TM_SUNDAY 0
|
||||||
|
2021
src/timezone/zic.c
2021
src/timezone/zic.c
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user