1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-30 11:03:19 +03:00

Adjust our timezone library to use pg_time_t (typedef'd as int64) in

place of time_t, as per prior discussion.  The behavior does not change
on machines without a 64-bit-int type, but on machines with one, which
is most, we are rid of the bizarre boundary behavior at the edges of
the 32-bit-time_t range (1901 and 2038).  The system will now treat
times over the full supported timestamp range as being in your local
time zone.  It may seem a little bizarre to consider that times in
4000 BC are PST or EST, but this is surely at least as reasonable as
propagating Gregorian calendar rules back that far.

I did not modify the format of the zic timezone database files, which
means that for the moment the system will not know about daylight-savings
periods outside the range 1901-2038.  Given the way the files are set up,
it's not a simple decision like 'widen to 64 bits'; we have to actually
think about the range of years that need to be supported.  We should
probably inquire what the plans of the upstream zic people are before
making any decisions of our own.
This commit is contained in:
Tom Lane
2004-06-03 02:08:07 +00:00
parent 473ac70aca
commit 921d749bd4
28 changed files with 419 additions and 786 deletions

View File

@ -3,7 +3,7 @@
* 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov).
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/timezone/localtime.c,v 1.6 2004/05/21 20:59:10 tgl Exp $
* $PostgreSQL: pgsql/src/timezone/localtime.c,v 1.7 2004/06/03 02:08:07 tgl Exp $
*/
/*
@ -69,7 +69,7 @@ struct ttinfo
struct lsinfo
{ /* leap second information */
time_t ls_trans; /* transition time */
pg_time_t ls_trans; /* transition time */
long ls_corr; /* correction to apply */
};
@ -81,7 +81,7 @@ struct state
int timecnt;
int typecnt;
int charcnt;
time_t ats[TZ_MAX_TIMES];
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, sizeof gmt),
@ -114,23 +114,11 @@ static const char *getsecs(const char *strp, long *secsp);
static const char *getoffset(const char *strp, long *offsetp);
static const char *getrule(const char *strp, struct rule * rulep);
static void gmtload(struct state * sp);
static void gmtsub(const time_t *timep, long offset, struct pg_tm * tmp);
static void localsub(const time_t *timep, long offset, struct pg_tm * tmp);
static int increment_overflow(int *number, int delta);
static int normalize_overflow(int *tensptr, int *unitsptr, int base);
static time_t time1(struct pg_tm * tmp,
void (*funcp) (const time_t *, long, struct pg_tm *),
long offset);
static time_t time2(struct pg_tm * tmp,
void (*funcp) (const time_t *, long, struct pg_tm *),
long offset, int *okayp);
static time_t time2sub(struct pg_tm * tmp,
void (*funcp) (const time_t *, long, struct pg_tm *),
long offset, int *okayp, int do_norm_secs);
static void timesub(const time_t *timep, long offset,
static void gmtsub(const pg_time_t *timep, long offset, struct pg_tm * tmp);
static void localsub(const pg_time_t *timep, long offset, struct pg_tm * tmp);
static void timesub(const pg_time_t *timep, long offset,
const struct state * sp, struct pg_tm * tmp);
static int tmcomp(const struct pg_tm * atmp, const struct pg_tm * btmp);
static time_t transtime(time_t janfirst, int year,
static pg_time_t transtime(pg_time_t janfirst, int year,
const struct rule * rulep, long offset);
static int tzload(const char *name, struct state * sp);
static int tzparse(const char *name, struct state * sp, int lastditch);
@ -503,12 +491,12 @@ getrule(const char *strp, register struct rule * rulep)
* year, a rule, and the offset from UTC at the time that rule takes effect,
* calculate the Epoch-relative time that rule takes effect.
*/
static time_t
transtime(const time_t janfirst, const int year,
static pg_time_t
transtime(const pg_time_t janfirst, const int year,
register const struct rule * rulep, const long offset)
{
register int leapyear;
register time_t value = 0;
register pg_time_t value = 0;
register int i;
int d,
m1,
@ -612,7 +600,7 @@ tzparse(const char *name, register struct state * sp, const int lastditch)
size_t dstlen;
long stdoffset;
long dstoffset;
register time_t *atp;
register pg_time_t *atp;
register unsigned char *typep;
register char *cp;
register int load_result;
@ -663,9 +651,9 @@ tzparse(const char *name, register struct state * sp, const int lastditch)
struct rule start;
struct rule end;
register int year;
register time_t janfirst;
time_t starttime;
time_t endtime;
register pg_time_t janfirst;
pg_time_t starttime;
pg_time_t endtime;
++name;
if ((name = getrule(name, &start)) == NULL)
@ -886,12 +874,12 @@ pg_tzset(const char *name)
* The unused offset argument is for the benefit of mktime variants.
*/
static void
localsub(const time_t *timep, const long offset, struct pg_tm * tmp)
localsub(const pg_time_t *timep, const long offset, struct pg_tm * tmp)
{
register struct state *sp;
register const struct ttinfo *ttisp;
register int i;
const time_t t = *timep;
const pg_time_t t = *timep;
sp = lclptr;
if (sp->timecnt == 0 || t < sp->ats[0])
@ -920,7 +908,7 @@ localsub(const time_t *timep, const long offset, struct pg_tm * tmp)
struct pg_tm *
pg_localtime(const time_t *timep)
pg_localtime(const pg_time_t *timep)
{
localsub(timep, 0L, &tm);
return &tm;
@ -931,7 +919,7 @@ pg_localtime(const time_t *timep)
* gmtsub is to gmtime as localsub is to localtime.
*/
static void
gmtsub(const time_t *timep, const long offset, struct pg_tm * tmp)
gmtsub(const pg_time_t *timep, const long offset, struct pg_tm * tmp)
{
if (!gmt_is_set)
{
@ -952,7 +940,7 @@ gmtsub(const time_t *timep, const long offset, struct pg_tm * tmp)
}
struct pg_tm *
pg_gmtime(const time_t *timep)
pg_gmtime(const pg_time_t *timep)
{
gmtsub(timep, 0L, &tm);
return &tm;
@ -960,11 +948,13 @@ pg_gmtime(const time_t *timep)
static void
timesub(const time_t *timep, const long offset,
timesub(const pg_time_t *timep, const long offset,
register const struct state * sp, register struct pg_tm * tmp)
{
register const struct lsinfo *lp;
register long days;
/* expand days to 64 bits to support full Julian-day range */
register int64 days;
register int idays;
register long rem;
register int y;
register int yleap;
@ -1036,335 +1026,38 @@ timesub(const time_t *timep, const long offset,
if (tmp->tm_wday < 0)
tmp->tm_wday += DAYSPERWEEK;
y = EPOCH_YEAR;
#define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)])
/*
* Note: the point of adding 4800 is to ensure we make the same assumptions
* as Postgres' Julian-date routines about the placement of leap years
* in centuries BC, at least back to 4713BC which is as far as we'll go.
* This is effectively extending Gregorian timekeeping into pre-Gregorian
* centuries, which is a tad bogus but it conforms to the SQL spec...
*/
#define LEAPS_THRU_END_OF(y) (((y) + 4800) / 4 - ((y) + 4800) / 100 + ((y) + 4800) / 400)
while (days < 0 || days >= (int64) year_lengths[yleap = isleap(y)])
{
register int newy;
newy = y + days / DAYSPERNYEAR;
if (days < 0)
--newy;
days -= (newy - y) * DAYSPERNYEAR +
days -= ((int64) (newy - y)) * DAYSPERNYEAR +
LEAPS_THRU_END_OF(newy - 1) -
LEAPS_THRU_END_OF(y - 1);
y = newy;
}
tmp->tm_year = y - TM_YEAR_BASE;
tmp->tm_yday = (int) days;
idays = (int) days; /* no longer have a range problem */
tmp->tm_yday = idays;
ip = mon_lengths[yleap];
for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon))
days = days - (long) ip[tmp->tm_mon];
tmp->tm_mday = (int) (days + 1);
for (i = 0; idays >= ip[i]; ++i)
idays -= ip[i];
tmp->tm_mon = i;
tmp->tm_mday = idays + 1;
tmp->tm_isdst = 0;
tmp->tm_gmtoff = offset;
}
/*
* Adapted from code provided by Robert Elz, who writes:
* The "best" way to do mktime I think is based on an idea of Bob
* Kridle's (so its said...) from a long time ago.
* [kridle@xinet.com as of 1996-01-16.]
* It does a binary search of the time_t space. Since time_t's are
* just 32 bits, its a max of 32 iterations (even at 64 bits it
* would still be very reasonable).
*/
#define WRONG (-1)
/*
* Simplified normalize logic courtesy Paul Eggert (eggert@twinsun.com).
*/
static int
increment_overflow(int *number, int delta)
{
int number0;
number0 = *number;
*number += delta;
return (*number < number0) != (delta < 0);
}
static int
normalize_overflow(int *tensptr, int *unitsptr, const int base)
{
register int tensdelta;
tensdelta = (*unitsptr >= 0) ?
(*unitsptr / base) :
(-1 - (-1 - *unitsptr) / base);
*unitsptr -= tensdelta * base;
return increment_overflow(tensptr, tensdelta);
}
static int
tmcomp(register const struct pg_tm * atmp, register const struct pg_tm * btmp)
{
register int result;
if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
(result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
(result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
(result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
(result = (atmp->tm_min - btmp->tm_min)) == 0)
result = atmp->tm_sec - btmp->tm_sec;
return result;
}
static time_t
time2sub(struct pg_tm * tmp,
void (*funcp) (const time_t *, long, struct pg_tm *),
const long offset, int *okayp, const int do_norm_secs)
{
register const struct state *sp;
register int dir;
register int bits;
register int i,
j;
register int saved_seconds;
time_t newt;
time_t t;
struct pg_tm yourtm,
mytm;
*okayp = FALSE;
yourtm = *tmp;
if (do_norm_secs)
{
if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,
SECSPERMIN))
return WRONG;
}
if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
return WRONG;
if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
return WRONG;
if (normalize_overflow(&yourtm.tm_year, &yourtm.tm_mon, MONSPERYEAR))
return WRONG;
/*
* Turn yourtm.tm_year into an actual year number for now. It is
* converted back to an offset from TM_YEAR_BASE later.
*/
if (increment_overflow(&yourtm.tm_year, TM_YEAR_BASE))
return WRONG;
while (yourtm.tm_mday <= 0)
{
if (increment_overflow(&yourtm.tm_year, -1))
return WRONG;
i = yourtm.tm_year + (1 < yourtm.tm_mon);
yourtm.tm_mday += year_lengths[isleap(i)];
}
while (yourtm.tm_mday > DAYSPERLYEAR)
{
i = yourtm.tm_year + (1 < yourtm.tm_mon);
yourtm.tm_mday -= year_lengths[isleap(i)];
if (increment_overflow(&yourtm.tm_year, 1))
return WRONG;
}
for (;;)
{
i = mon_lengths[isleap(yourtm.tm_year)][yourtm.tm_mon];
if (yourtm.tm_mday <= i)
break;
yourtm.tm_mday -= i;
if (++yourtm.tm_mon >= MONSPERYEAR)
{
yourtm.tm_mon = 0;
if (increment_overflow(&yourtm.tm_year, 1))
return WRONG;
}
}
if (increment_overflow(&yourtm.tm_year, -TM_YEAR_BASE))
return WRONG;
if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)
saved_seconds = 0;
else if (yourtm.tm_year + TM_YEAR_BASE < EPOCH_YEAR)
{
/*
* We can't set tm_sec to 0, because that might push the time
* below the minimum representable time. Set tm_sec to 59
* instead. This assumes that the minimum representable time is
* not in the same minute that a leap second was deleted from,
* which is a safer assumption than using 58 would be.
*/
if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
return WRONG;
saved_seconds = yourtm.tm_sec;
yourtm.tm_sec = SECSPERMIN - 1;
}
else
{
saved_seconds = yourtm.tm_sec;
yourtm.tm_sec = 0;
}
/*
* Divide the search space in half (this works whether time_t is
* signed or unsigned).
*/
bits = TYPE_BIT(time_t) -1;
/*
* If time_t is signed, then 0 is just above the median, assuming
* two's complement arithmetic. If time_t is unsigned, then (1 <<
* bits) is just above the median.
*/
t = TYPE_SIGNED(time_t) ? 0 : (((time_t) 1) << bits);
for (;;)
{
(*funcp) (&t, offset, &mytm);
dir = tmcomp(&mytm, &yourtm);
if (dir != 0)
{
if (bits-- < 0)
return WRONG;
if (bits < 0)
--t; /* may be needed if new t is minimal */
else if (dir > 0)
t -= ((time_t) 1) << bits;
else
t += ((time_t) 1) << bits;
continue;
}
if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
break;
/*
* Right time, wrong type. Hunt for right time, right type.
* It's okay to guess wrong since the guess gets checked.
*/
/*
* The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
*/
sp = (const struct state *)
(((void *) funcp == (void *) localsub) ?
lclptr : gmtptr);
for (i = sp->typecnt - 1; i >= 0; --i)
{
if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
continue;
for (j = sp->typecnt - 1; j >= 0; --j)
{
if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
continue;
newt = t + sp->ttis[j].tt_gmtoff -
sp->ttis[i].tt_gmtoff;
(*funcp) (&newt, offset, &mytm);
if (tmcomp(&mytm, &yourtm) != 0)
continue;
if (mytm.tm_isdst != yourtm.tm_isdst)
continue;
/*
* We have a match.
*/
t = newt;
goto label;
}
}
return WRONG;
}
label:
newt = t + saved_seconds;
if ((newt < t) != (saved_seconds < 0))
return WRONG;
t = newt;
(*funcp) (&t, offset, tmp);
*okayp = TRUE;
return t;
}
static time_t
time2(struct pg_tm * tmp,
void (*funcp) (const time_t *, long, struct pg_tm *),
const long offset, int *okayp)
{
time_t t;
/*
* First try without normalization of seconds (in case tm_sec
* contains a value associated with a leap second). If that fails,
* try with normalization of seconds.
*/
t = time2sub(tmp, funcp, offset, okayp, FALSE);
return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE);
}
static time_t
time1(struct pg_tm * tmp,
void (*funcp) (const time_t *, long, struct pg_tm *),
const long offset)
{
register time_t t;
register const struct state *sp;
register int samei,
otheri;
register int sameind,
otherind;
register int i;
register int nseen;
int seen[TZ_MAX_TYPES];
int types[TZ_MAX_TYPES];
int okay;
if (tmp->tm_isdst > 1)
tmp->tm_isdst = 1;
t = time2(tmp, funcp, offset, &okay);
if (okay || tmp->tm_isdst < 0)
return t;
/*
* We're supposed to assume that somebody took a time of one type
* and did some math on it that yielded a "struct pg_tm" that's bad.
* We try to divine the type they started from and adjust to the
* type they need.
*/
/*
* The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
*/
sp = (const struct state *) (((void *) funcp == (void *) localsub) ?
lclptr : gmtptr);
for (i = 0; i < sp->typecnt; ++i)
seen[i] = FALSE;
nseen = 0;
for (i = sp->timecnt - 1; i >= 0; --i)
if (!seen[sp->types[i]])
{
seen[sp->types[i]] = TRUE;
types[nseen++] = sp->types[i];
}
for (sameind = 0; sameind < nseen; ++sameind)
{
samei = types[sameind];
if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
continue;
for (otherind = 0; otherind < nseen; ++otherind)
{
otheri = types[otherind];
if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
continue;
tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
sp->ttis[samei].tt_gmtoff;
tmp->tm_isdst = !tmp->tm_isdst;
t = time2(tmp, funcp, offset, &okay);
if (okay)
return t;
tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff -
sp->ttis[samei].tt_gmtoff;
tmp->tm_isdst = !tmp->tm_isdst;
}
}
return WRONG;
}
time_t
pg_mktime(struct pg_tm * tmp)
{
return time1(tmp, localsub, 0L);
}
/*
* Return the name of the current timezone

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/timezone/pgtz.c,v 1.16 2004/05/25 19:46:21 tgl Exp $
* $PostgreSQL: pgsql/src/timezone/pgtz.c,v 1.17 2004/06/03 02:08:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -16,12 +16,14 @@
#include <ctype.h>
#include <sys/stat.h>
#include <time.h>
#include "miscadmin.h"
#include "pgtime.h"
#include "pgtz.h"
#include "storage/fd.h"
#include "tzfile.h"
#include "utils/datetime.h"
#include "utils/elog.h"
#include "utils/guc.h"
@ -107,7 +109,7 @@ win32_get_timezone_abbrev(const char *tz)
#endif
/*
* Convenience subroutine to convert y/m/d to time_t
* Convenience subroutine to convert y/m/d to time_t (NOT pg_time_t)
*/
static time_t
build_time_t(int year, int month, int day)
@ -148,6 +150,7 @@ static bool
try_timezone(const char *tzname, struct tztry *tt)
{
int i;
pg_time_t pgtt;
struct tm *systm;
struct pg_tm *pgtm;
char cbuf[TZ_STRLEN_MAX + 1];
@ -158,14 +161,15 @@ try_timezone(const char *tzname, struct tztry *tt)
/* Check for match at all the test times */
for (i = 0; i < tt->n_test_times; i++)
{
pgtm = pg_localtime(&(tt->test_times[i]));
pgtt = (pg_time_t) (tt->test_times[i]);
pgtm = pg_localtime(&pgtt);
if (!pgtm)
return false; /* probably shouldn't happen */
systm = localtime(&(tt->test_times[i]));
if (!compare_tm(systm, pgtm))
{
elog(DEBUG4, "Reject TZ \"%s\": at %lu %04d-%02d-%02d %02d:%02d:%02d %s versus %04d-%02d-%02d %02d:%02d:%02d %s",
tzname, (unsigned long) tt->test_times[i],
elog(DEBUG4, "Reject TZ \"%s\": at %ld %04d-%02d-%02d %02d:%02d:%02d %s versus %04d-%02d-%02d %02d:%02d:%02d %s",
tzname, (long) pgtt,
pgtm->tm_year + 1900, pgtm->tm_mon + 1, pgtm->tm_mday,
pgtm->tm_hour, pgtm->tm_min, pgtm->tm_sec,
pgtm->tm_isdst ? "dst" : "std",
@ -183,8 +187,8 @@ try_timezone(const char *tzname, struct tztry *tt)
strftime(cbuf, sizeof(cbuf) - 1, "%Z", systm); /* zone abbr */
if (strcmp(TZABBREV(cbuf), pgtm->tm_zone) != 0)
{
elog(DEBUG4, "Reject TZ \"%s\": at %lu \"%s\" versus \"%s\"",
tzname, (unsigned long) tt->test_times[i],
elog(DEBUG4, "Reject TZ \"%s\": at %ld \"%s\" versus \"%s\"",
tzname, (long) pgtt,
pgtm->tm_zone, cbuf);
return false;
}
@ -470,21 +474,17 @@ scan_available_timezones(char *tzdir, char *tzdirsub, struct tztry *tt)
bool
tz_acceptable(void)
{
struct pg_tm tt;
time_t time2000;
struct pg_tm *tt;
pg_time_t time2000;
/*
* To detect leap-second timekeeping, compute the time_t value for
* local midnight, 2000-01-01. Insist that this be a multiple of 60;
* any partial-minute offset has to be due to leap seconds.
* To detect leap-second timekeeping, run pg_localtime for what should
* be GMT midnight, 2000-01-01. Insist that the tm_sec value be zero;
* any other result has to be due to leap seconds.
*/
MemSet(&tt, 0, sizeof(tt));
tt.tm_year = 100;
tt.tm_mon = 0;
tt.tm_mday = 1;
tt.tm_isdst = -1;
time2000 = pg_mktime(&tt);
if ((time2000 % 60) != 0)
time2000 = (POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * 86400;
tt = pg_localtime(&time2000);
if (tt->tm_sec != 0)
return false;
return true;

View File

@ -15,7 +15,7 @@
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/timezone/strftime.c,v 1.3 2004/05/21 20:59:10 tgl Exp $
* $PostgreSQL: pgsql/src/timezone/strftime.c,v 1.4 2004/06/03 02:08:07 tgl Exp $
*/
#include "postgres.h"
@ -265,21 +265,6 @@ _fmt(const char *format, const struct pg_tm * t, char *pt, const char *ptlim,
case 'S':
pt = _conv(t->tm_sec, "%02d", pt, ptlim);
continue;
case 's':
{
struct pg_tm tm;
char buf[INT_STRLEN_MAXIMUM(time_t) +1];
time_t mkt;
tm = *t;
mkt = pg_mktime(&tm);
if (TYPE_SIGNED(time_t))
(void) sprintf(buf, "%ld", (long) mkt);
else
(void) sprintf(buf, "%lu", (unsigned long) mkt);
pt = _add(buf, pt, ptlim);
}
continue;
case 'T':
pt = _fmt("%H:%M:%S", t, pt, ptlim, warnp);
continue;

View File

@ -3,12 +3,13 @@
* 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov).
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/timezone/zic.c,v 1.7 2004/05/21 20:59:10 tgl Exp $
* $PostgreSQL: pgsql/src/timezone/zic.c,v 1.8 2004/06/03 02:08:07 tgl Exp $
*/
#include "postgres.h"
#include <locale.h>
#include <limits.h>
#include "pgtz.h"
#include "private.h"
@ -71,7 +72,7 @@ struct rule
const char *r_abbrvar; /* variable part of abbreviation */
int r_todo; /* a rule to do (used in outzone) */
time_t r_temp; /* used in outzone */
pg_time_t r_temp; /* used in outzone */
};
/*
@ -98,14 +99,14 @@ struct zone
int z_nrules;
struct rule z_untilrule;
time_t z_untiltime;
pg_time_t z_untiltime;
};
extern int link(const char *fromname, const char *toname);
static void addtt(time_t starttime, int type);
static void addtt(pg_time_t starttime, int type);
static int addtype(long gmtoff, const char *abbr, int isdst,
int ttisstd, int ttisgmt);
static void leapadd(time_t t, int positive, int rolling, int count);
static void leapadd(pg_time_t t, int positive, int rolling, int count);
static void adjleap(void);
static void associate(void);
static int ciequal(const char *ap, const char *bp);
@ -138,13 +139,13 @@ static long oadd(long t1, long t2);
static void outzone(const struct zone * zp, int ntzones);
static void puttzcode(long code, FILE *fp);
static int rcomp(const void *leftp, const void *rightp);
static time_t rpytime(const struct rule * rp, int wantedy);
static pg_time_t rpytime(const struct rule * rp, int wantedy);
static void rulesub(struct rule * rp,
const char *loyearp, const char *hiyearp,
const char *typep, const char *monthp,
const char *dayp, const char *timep);
static void setboundaries(void);
static time_t tadd(time_t t1, long t2);
static pg_time_t tadd(pg_time_t t1, long t2);
static void usage(void);
static void writezone(const char *name);
static int yearistype(int year, const char *type);
@ -158,10 +159,10 @@ static int errors;
static const char *filename;
static int leapcnt;
static int linenum;
static time_t max_time;
static pg_time_t max_time;
static int max_year;
static int max_year_representable;
static time_t min_time;
static pg_time_t min_time;
static int min_year;
static int min_year_representable;
static int noise;
@ -354,7 +355,7 @@ static const int len_years[2] = {
static struct attype
{
time_t at;
pg_time_t at;
unsigned char type;
} attypes[TZ_MAX_TIMES];
static long gmtoffs[TZ_MAX_TYPES];
@ -363,7 +364,7 @@ static unsigned char abbrinds[TZ_MAX_TYPES];
static char ttisstds[TZ_MAX_TYPES];
static char ttisgmts[TZ_MAX_TYPES];
static char chars[TZ_MAX_CHARS];
static time_t trans[TZ_MAX_LEAPS];
static pg_time_t trans[TZ_MAX_LEAPS];
static long corr[TZ_MAX_LEAPS];
static char roll[TZ_MAX_LEAPS];
@ -684,27 +685,26 @@ dolink(const char *fromfile, const char *tofile)
* change to the tz file format.
*/
#define MAX_BITS_IN_FILE 32
#define TIME_T_BITS_IN_FILE ((TYPE_BIT(time_t) < MAX_BITS_IN_FILE) ? TYPE_BIT(time_t) : MAX_BITS_IN_FILE)
#define TIME_T_BITS_IN_FILE 32
static void
setboundaries(void)
{
if (TYPE_SIGNED(time_t))
{
min_time = ~(time_t) 0;
min_time <<= TIME_T_BITS_IN_FILE - 1;
max_time = ~(time_t) 0 - min_time;
if (sflag)
min_time = 0;
}
else
{
min_time = 0;
max_time = 2 - sflag;
max_time <<= TIME_T_BITS_IN_FILE - 1;
--max_time;
}
/*
* pg_time_t is always signed, but might be only 32 bits ...
*/
min_time = ~(pg_time_t) 0;
min_time <<= TYPE_BIT(pg_time_t) - 1;
max_time = ~(pg_time_t) 0 - min_time;
/*
* For the moment, hard-wire the range as 1901 to 2038. We cannot
* go wider without adopting an incompatible zone file format, which
* is a step I'd just as soon not take just yet.
*/
min_time = Max(min_time, (pg_time_t) INT_MIN);
max_time = Min(max_time, (pg_time_t) INT_MAX);
min_year = TM_YEAR_BASE + pg_gmtime(&min_time)->tm_year;
max_year = TM_YEAR_BASE + pg_gmtime(&max_time)->tm_year;
min_year_representable = min_year;
@ -1170,7 +1170,7 @@ inleap(register char **fields, const int nfields)
day;
long dayoff,
tod;
time_t t;
pg_time_t t;
if (nfields != LEAP_FIELDS)
{
@ -1223,11 +1223,6 @@ inleap(register char **fields, const int nfields)
return;
}
dayoff = oadd(dayoff, eitol(day - 1));
if (dayoff < 0 && !TYPE_SIGNED(time_t))
{
error(_("time before zero"));
return;
}
if (dayoff < min_time / SECSPERDAY)
{
error(_("time too small"));
@ -1238,7 +1233,7 @@ inleap(register char **fields, const int nfields)
error(_("time too large"));
return;
}
t = (time_t) dayoff *SECSPERDAY;
t = (pg_time_t) dayoff *SECSPERDAY;
tod = gethms(fields[LP_TIME], _("invalid time of day"), FALSE);
cp = fields[LP_CORR];
@ -1525,7 +1520,7 @@ writezone(const char *name)
j;
static char *fullname;
static struct tzhead tzh;
time_t ats[TZ_MAX_TIMES];
pg_time_t ats[TZ_MAX_TIMES];
unsigned char types[TZ_MAX_TIMES];
/*
@ -1711,8 +1706,8 @@ outzone(const struct zone * zpfirst, const int zonecount)
j;
register int usestart,
useuntil;
register time_t starttime = 0;
register time_t untiltime = 0;
register pg_time_t starttime = 0;
register pg_time_t untiltime = 0;
register long gmtoff;
register long stdoff;
register int year;
@ -1790,7 +1785,7 @@ outzone(const struct zone * zpfirst, const int zonecount)
for (;;)
{
register int k;
register time_t jtime,
register pg_time_t jtime,
ktime = 0;
register long offset;
char buf[BUFSIZ];
@ -1911,7 +1906,7 @@ outzone(const struct zone * zpfirst, const int zonecount)
}
static void
addtt(const time_t starttime, int type)
addtt(const pg_time_t starttime, int type)
{
if (starttime <= min_time ||
(timecnt == 1 && attypes[0].at < min_time))
@ -1999,7 +1994,7 @@ addtype(const long gmtoff, const char *abbr, const int isdst,
}
static void
leapadd(const time_t t, const int positive, const int rolling, int count)
leapadd(const pg_time_t t, const int positive, const int rolling, int count)
{
register int i,
j;
@ -2191,10 +2186,10 @@ oadd(const long t1, const long t2)
return t;
}
static time_t
tadd(const time_t t1, const long t2)
static pg_time_t
tadd(const pg_time_t t1, const long t2)
{
register time_t t;
register pg_time_t t;
if (t1 == max_time && t2 > 0)
return max_time;
@ -2214,14 +2209,14 @@ tadd(const time_t t1, const long t2)
* 1970, 00:00 LOCAL time - in that year that the rule refers to.
*/
static time_t
static pg_time_t
rpytime(register const struct rule * rp, register const int wantedy)
{
register int y,
m,
i;
register long dayoff; /* with a nod to Margaret O. */
register time_t t;
register pg_time_t t;
if (wantedy == INT_MIN)
return min_time;
@ -2302,13 +2297,11 @@ rpytime(register const struct rule * rp, register const int wantedy)
(void) exit(EXIT_FAILURE);
}
}
if (dayoff < 0 && !TYPE_SIGNED(time_t))
return min_time;
if (dayoff < min_time / SECSPERDAY)
return min_time;
if (dayoff > max_time / SECSPERDAY)
return max_time;
t = (time_t) dayoff *SECSPERDAY;
t = (pg_time_t) dayoff *SECSPERDAY;
return tadd(t, rp->r_tod);
}