Sync our copy of the timezone library with IANA release tzcode2016c.

We hadn't done this in about six years, which proves to have been a mistake
because there's been a lot of code churn upstream, making the merge rather
painful.  But putting it off any further isn't going to lessen the pain,
and there are at least two incompatible changes that we need to absorb
before someone starts complaining that --with-system-tzdata doesn't work
at all on their platform, or we get blindsided by a tzdata release that
our out-of-date zic can't compile.  Last week's "time zone abbreviation
differs from POSIX standard" mess was a wake-up call in that regard.

This is a sufficiently large patch that I'm afraid to back-patch it
immediately, though the foregoing considerations imply that we probably
should do so eventually.  For the moment, just put it in HEAD so that
it can get some testing.  Maybe we can wait till the end of the 9.6
beta cycle before deeming it okay.
This commit is contained in:
Tom Lane 2016-03-28 15:10:17 -04:00
parent e5a4dea80f
commit 1c1a7cbd6a
11 changed files with 2099 additions and 1383 deletions

View File

@ -19,7 +19,7 @@ include $(top_builddir)/src/Makefile.global
OBJS= localtime.o strftime.o pgtz.o
# files needed to build zic utility program
ZICOBJS= zic.o ialloc.o scheck.o localtime.o $(WIN32RES)
ZICOBJS= zic.o $(WIN32RES)
# timezone data files
TZDATA = africa antarctica asia australasia europe northamerica southamerica \

View File

@ -1,26 +1,24 @@
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:
ftp://ftp.iana.org/tz/releases/tzcode*.tar.gz
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
The latest versions of both the tzdata and tzcode tarballs are normally
available right from that page. Historical versions can be found
elsewhere on the site.
Since time zone rules change frequently in some parts of the world,
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
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,
which is the list that existed last time the tznames/ files were updated.
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
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
mappings in case they are removed in Windows, since we still need to
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.

View File

@ -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

View File

@ -256,7 +256,7 @@ pg_tzset(const char *name)
*/
if (strcmp(uppername, "GMT") == 0)
{
if (tzparse(uppername, &tzstate, TRUE) != 0)
if (tzparse(uppername, &tzstate, true) != 0)
{
/* This really, really should not happen ... */
elog(ERROR, "could not initialize GMT time zone");
@ -264,9 +264,9 @@ pg_tzset(const char *name)
/* Use uppercase name as canonical */
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) != 0)
{
/* Unknown timezone. Fail our call instead of loading GMT! */
return NULL;
@ -460,7 +460,7 @@ pg_tzenumerate_next(pg_tzenum *dir)
* the cache
*/
if (tzload(fullname + dir->baselen, dir->tz.TZname, &dir->tz.state,
TRUE) != 0)
true) != 0)
{
/* Zone could not be loaded, ignore it */
continue;

View File

@ -16,25 +16,26 @@
#ifndef _PGTZ_H
#define _PGTZ_H
#include "tzfile.h"
#include "pgtime.h"
#include "tzfile.h"
#define SMALLEST(a, b) (((a) < (b)) ? (a) : (b))
#define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
struct ttinfo
{ /* time type information */
long tt_gmtoff; /* UTC offset in seconds */
int tt_isdst; /* used to set tm_isdst */
int32 tt_gmtoff; /* UT offset in seconds */
bool tt_isdst; /* used to set tm_isdst */
int tt_abbrind; /* abbreviation list index */
int tt_ttisstd; /* TRUE if transition is std time */
int tt_ttisgmt; /* TRUE if transition is UTC */
bool tt_ttisstd; /* transition is std time */
bool tt_ttisgmt; /* transition is UT */
};
struct lsinfo
{ /* leap second information */
pg_time_t ls_trans; /* transition time */
long ls_corr; /* correction to apply */
int64 ls_corr; /* correction to apply */
};
struct state
@ -43,14 +44,15 @@ struct state
int timecnt;
int typecnt;
int charcnt;
int goback;
int goahead;
bool goback;
bool goahead;
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, 3 /* sizeof gmt */ ),
(2 * (TZ_STRLEN_MAX + 1)))];
struct lsinfo lsis[TZ_MAX_LEAPS];
int defaulttype; /* for early times or if no transitions */
};

View File

@ -25,6 +25,18 @@
#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
#define WIFEXITED(status) (((status) & 0xff) == 0)
#endif /* !defined WIFEXITED */
@ -35,6 +47,10 @@
/* Unlike <ctype.h>'s isdigit, this also works if c < 0 | c > UCHAR_MAX. */
#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.
*/
@ -45,31 +61,11 @@ extern int unlink(const char *filename);
#define remove unlink
#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.
*/
#ifndef TRUE
#define TRUE 1
#endif /* !defined TRUE */
#ifndef FALSE
#define FALSE 0
#endif /* !defined FALSE */
#ifndef TYPE_BIT
#define TYPE_BIT(type) (sizeof (type) * CHAR_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)
#endif /* !defined TYPE_SIGNED */
/*
* Since the definition of TYPE_INTEGRAL contains floating point numbers,
* it cannot be used in preprocessor directives.
*/
#define TWOS_COMPLEMENT(t) ((t) ~ (t) 0 < 0)
#ifndef TYPE_INTEGRAL
#define TYPE_INTEGRAL(type) (((type) 0.5) != 0.5)
#endif /* !defined TYPE_INTEGRAL */
/*
* Max and min values of the integer type T, of which only the bottom
* 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
/*
@ -95,34 +95,36 @@ extern const char *scheck(const char *string, const char *format);
* add one more for a minus sign if the type is signed.
*/
#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 */
/*
* INITIALIZE(x)
*/
#define INITIALIZE(x) ((x) = 0)
#undef _
#define _(msgid) (msgid)
#ifndef YEARSPERREPEAT
#define YEARSPERREPEAT 400 /* years before a Gregorian repeat */
#define YEARSPERREPEAT 400 /* years before a Gregorian repeat */
#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
#define AVGSECSPERYEAR 31556952L
#define AVGSECSPERYEAR 31556952L
#endif /* !defined AVGSECSPERYEAR */
#ifndef SECSPERREPEAT
#define SECSPERREPEAT ((int64) YEARSPERREPEAT * (int64) AVGSECSPERYEAR)
#define SECSPERREPEAT ((int64) YEARSPERREPEAT * (int64) AVGSECSPERYEAR)
#endif /* !defined SECSPERREPEAT */
#ifndef SECSPERREPEAT_BITS
#define SECSPERREPEAT_BITS 34 /* ceil(log2(SECSPERREPEAT)) */
#define SECSPERREPEAT_BITS 34 /* ceil(log2(SECSPERREPEAT)) */
#endif /* !defined SECSPERREPEAT_BITS */
/*
* UNIX was a registered trademark of The Open Group in 2003.
*/
#endif /* !defined PRIVATE_H */

View File

@ -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;
}

View File

@ -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.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* 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
* 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 *_fmt(const char *, const struct pg_tm *, char *,
const char *, int *);
static char *_yconv(const int, const int, const int, const int,
char *, const char *const);
static char *_yconv(int, int, bool, bool, char *, const char *);
#define IN_NONE 0
#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
* completely different. (ado, 1993-05-24)
*/
pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 0,
pt, ptlim);
pt = _yconv(t->tm_year, TM_YEAR_BASE,
true, false, pt, ptlim);
continue;
case 'c':
{
@ -224,7 +243,7 @@ _fmt(const char *format, const struct pg_tm * t, char *pt, const char *ptlim,
case 'K':
/*
* * After all this time, still unclaimed!
* After all this time, still unclaimed!
*/
pt = _add("kitchen sink", pt, ptlim);
continue;
@ -296,7 +315,7 @@ _fmt(const char *format, const struct pg_tm * t, char *pt, const char *ptlim,
* (01-53)."
* (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
* 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
@ -367,11 +386,13 @@ _fmt(const char *format, const struct pg_tm * t, char *pt, const char *ptlim,
else if (*format == 'g')
{
*warnp = IN_ALL;
pt = _yconv(year, base, 0, 1,
pt = _yconv(year, base,
false, true,
pt, ptlim);
}
else
pt = _yconv(year, base, 1, 1,
pt = _yconv(year, base,
true, true,
pt, ptlim);
}
continue;
@ -409,11 +430,13 @@ _fmt(const char *format, const struct pg_tm * t, char *pt, const char *ptlim,
continue;
case 'y':
*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);
continue;
case 'Y':
pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 1,
pt = _yconv(t->tm_year, TM_YEAR_BASE,
true, true,
pt, ptlim);
continue;
case 'Z':
@ -427,7 +450,7 @@ _fmt(const char *format, const struct pg_tm * t, char *pt, const char *ptlim,
continue;
case 'z':
{
int diff;
long diff;
char const *sign;
if (t->tm_isdst < 0)
@ -441,9 +464,10 @@ _fmt(const char *format, const struct pg_tm * t, char *pt, const char *ptlim,
else
sign = "+";
pt = _add(sign, pt, ptlim);
diff /= 60;
pt = _conv((diff / 60) * 100 + diff % 60,
"%04d", pt, ptlim);
diff /= SECSPERMIN;
diff = (diff / MINSPERHOUR) * 100 +
(diff % MINSPERHOUR);
pt = _conv(diff, "%04d", pt, ptlim);
}
continue;
case '+':
@ -473,7 +497,7 @@ _conv(int n, const char *format, char *pt, const char *ptlim)
{
char buf[INT_STRLEN_MAXIMUM(int) +1];
(void) sprintf(buf, format, n);
sprintf(buf, format, n);
return _add(buf, pt, ptlim);
}
@ -493,13 +517,13 @@ _add(const char *str, char *pt, const char *ptlim)
* with more only if necessary.
*/
static char *
_yconv(const int a, const int b, const int convert_top,
const int convert_yy, char *pt, const char *const ptlim)
_yconv(int a, int b, bool convert_top, bool convert_yy,
char *pt, const char *ptlim)
{
int lead;
int trail;
#define DIVISOR 100
#define DIVISOR 100
trail = a % DIVISOR + b % DIVISOR;
lead = a / DIVISOR + b / DIVISOR + trail / DIVISOR;
trail %= DIVISOR;

View File

@ -33,8 +33,8 @@
struct tzhead
{
char tzh_magic[4]; /* TZ_MAGIC */
char tzh_version[1]; /* '\0' or '2' as of 2005 */
char tzh_reserved[15]; /* reserved--must be zero */
char tzh_version[1]; /* '\0' or '2' or '3' as of 2013 */
char tzh_reserved[15]; /* reserved; must be zero */
char tzh_ttisgmtcnt[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 */
@ -43,30 +43,29 @@ struct tzhead
char tzh_charcnt[4]; /* coded number of abbr. chars */
};
/*----------
/*
* . . .followed by. . .
*
* 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_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) that's an abbreviation list index
* tzh_charcnt (char)s '\0'-terminated zone abbreviations
* tzh_leapcnt repetitions of
* one (char [4]) coded leap second transition times
* one (char [4]) total correction after above
* tzh_ttisstdcnt (char)s indexed by type; if TRUE, transition
* time is standard time, if FALSE,
* tzh_ttisstdcnt (char)s indexed by type; if 1, transition
* time is standard time, if 0,
* transition time is wall clock time
* if absent, transition times are
* assumed to be wall clock time
* tzh_ttisgmtcnt (char)s indexed by type; if TRUE, transition
* time is UTC, if FALSE,
* tzh_ttisgmtcnt (char)s indexed by type; if 1, transition
* time is UT, if 0,
* transition time is local time
* if absent, transition times are
* assumed to be local time
*----------
*/
/*
@ -77,6 +76,13 @@ struct tzhead
* instants after the last transition time stored in the file
* (with nothing between the newlines if there is no POSIX 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.
* 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.
*/
#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_CHARS 50 /* Maximum number of abbreviation characters */
@ -100,7 +107,7 @@ struct tzhead
#define DAYSPERNYEAR 365
#define DAYSPERLYEAR 366
#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
#define SECSPERDAY ((long) SECSPERHOUR * HOURSPERDAY)
#define SECSPERDAY ((int32) SECSPERHOUR * HOURSPERDAY)
#define MONSPERYEAR 12
#define TM_SUNDAY 0
@ -143,6 +150,6 @@ struct tzhead
* We use this to avoid addition overflow problems.
*/
#define isleap_sum(a, b) isleap((a) % 400 + (b) % 400)
#define isleap_sum(a, b) isleap((a) % 400 + (b) % 400)
#endif /* !defined TZFILE_H */

File diff suppressed because it is too large Load Diff