+/* Convert timestamp from pg_time_t to struct pg_tm. */
+
/*
* This file is in the public domain, so clarified as of
* 1996-06-05 by Arthur David Olson.
}
static int32
-detzcode(const char *codep)
+detzcode(const char *const codep)
{
int32 result;
int i;
}
static int64
-detzcode64(const char *codep)
+detzcode64(const char *const codep)
{
uint64 result;
int i;
int32 charcnt = detzcode(up->tzhead.tzh_charcnt);
char const *p = up->buf + tzheadsize;
+ /*
+ * Although tzfile(5) currently requires typecnt to be nonzero,
+ * support future formats that may allow zero typecnt in files that
+ * have a TZ string and no transitions.
+ */
if (!(0 <= leapcnt && leapcnt < TZ_MAX_LEAPS
- && 0 < typecnt && typecnt < TZ_MAX_TYPES
+ && 0 <= typecnt && typecnt < TZ_MAX_TYPES
&& 0 <= timecnt && timecnt < TZ_MAX_TIMES
&& 0 <= charcnt && charcnt < TZ_MAX_CHARS
&& (ttisstdcnt == typecnt || ttisstdcnt == 0)
struct state *ts = &lsp->u.st;
up->buf[nread - 1] = '\0';
- if (tzparse(&up->buf[1], ts, false)
- && ts->typecnt == 2)
+ if (tzparse(&up->buf[1], ts, false))
{
/*
* Attempt to reuse existing abbreviations. Without this,
int gotabbr = 0;
int charcnt = sp->charcnt;
- for (i = 0; i < 2; i++)
+ for (i = 0; i < ts->typecnt; i++)
{
char *tsabbr = ts->chars + ts->ttis[i].tt_abbrind;
int j;
}
}
}
- if (gotabbr == 2)
+ if (gotabbr == ts->typecnt)
{
sp->charcnt = charcnt;
sp->timecnt--;
for (i = 0; i < ts->timecnt; i++)
- if (sp->ats[sp->timecnt - 1] < ts->ats[i])
+ if (sp->timecnt == 0
+ || sp->ats[sp->timecnt - 1] < ts->ats[i])
break;
while (i < ts->timecnt
&& sp->timecnt < TZ_MAX_TIMES)
sp->timecnt++;
i++;
}
- sp->ttis[sp->typecnt++] = ts->ttis[0];
- sp->ttis[sp->typecnt++] = ts->ttis[1];
+ for (i = 0; i < ts->typecnt; i++)
+ sp->ttis[sp->typecnt++] = ts->ttis[i];
}
}
}
+ if (sp->typecnt == 0)
+ return EINVAL;
if (sp->timecnt > 1)
{
for (i = 1; i < sp->timecnt; ++i)
}
}
+ /*
+ * Infer sp->defaulttype from the data. Although this default type is
+ * always zero for data from recent tzdb releases, things are trickier for
+ * data from tzdb 2018e or earlier.
+ *
+ * The first set of heuristics work around bugs in 32-bit data generated
+ * by tzdb 2013c or earlier. The workaround is for zones like
+ * Australia/Macquarie where timestamps before the first transition have a
+ * time type that is not the earliest standard-time type. See:
+ * https://mm.icann.org/pipermail/tz/2013-May/019368.html
+ */
+
/*
* If type 0 is unused in transitions, it's the type to use for early
* times.
break;
}
+ /*
+ * The next heuristics are for data generated by tzdb 2018e or earlier,
+ * for zones like EST5EDT where the first transition is to DST.
+ */
+
/*
* If no result yet, find the first standard type. If there is none, punt
* to type zero.
break;
}
}
+
+ /*
+ * A simple 'sp->defaulttype = 0;' would suffice here if we didn't have to
+ * worry about 2018e-or-earlier data. Even simpler would be to remove the
+ * defaulttype member and just use 0 in its place.
+ */
sp->defaulttype = i;
+
return 0;
}
};
/*
- * Given a pointer into a time zone string, scan until a character that is not
- * a valid character in a zone name is found. Return a pointer to that
- * character.
+ * Given a pointer into a timezone string, scan until a character that is not
+ * a valid character in a time zone abbreviation is found.
+ * Return a pointer to that character.
*/
+
static const char *
getzname(const char *strp)
{
}
/*
- * Given a pointer into an extended time zone string, scan until the ending
- * delimiter of the zone name is located. Return a pointer to the delimiter.
+ * Given a pointer into an extended timezone string, scan until the ending
+ * delimiter of the time zone abbreviation is located.
+ * Return a pointer to the delimiter.
*
* As with getzname above, the legal character set is actually quite
* restricted, with other characters producing undefined results.
* We don't do any checking here; checking is done later in common-case code.
*/
+
static const char *
-getqzname(const char *strp, int delim)
+getqzname(const char *strp, const int delim)
{
int c;
}
/*
- * Given a pointer into a time zone string, extract a number from that string.
+ * Given a pointer into a timezone string, extract a number from that string.
* Check that the number is within a specified range; if it is not, return
* NULL.
* Otherwise, return a pointer to the first character not part of the number.
*/
+
static const char *
-getnum(const char *strp, int *nump, int min, int max)
+getnum(const char *strp, int *const nump, const int min, const int max)
{
char c;
int num;
}
/*
- * Given a pointer into a time zone string, extract a number of seconds,
+ * Given a pointer into a timezone string, extract a number of seconds,
* in hh[:mm[:ss]] form, from the string.
* If any error occurs, return NULL.
* Otherwise, return a pointer to the first character not part of the number
* of seconds.
*/
+
static const char *
-getsecs(const char *strp, int32 *secsp)
+getsecs(const char *strp, int32 *const secsp)
{
int num;
}
/*
- * Given a pointer into a time zone string, extract an offset, in
+ * Given a pointer into a timezone string, extract an offset, in
* [+-]hh[:mm[:ss]] form, from the string.
* If any error occurs, return NULL.
* Otherwise, return a pointer to the first character not part of the time.
*/
+
static const char *
-getoffset(const char *strp, int32 *offsetp)
+getoffset(const char *strp, int32 *const offsetp)
{
bool neg = false;
}
/*
- * Given a pointer into a time zone string, extract a rule in the form
+ * Given a pointer into a timezone string, extract a rule in the form
* date[/time]. See POSIX section 8 for the format of "date" and "time".
* If a valid rule is not found, return NULL.
* Otherwise, return a pointer to the first character not part of the rule.
*/
+
static const char *
-getrule(const char *strp, struct rule *rulep)
+getrule(const char *strp, struct rule *const rulep)
{
if (*strp == 'J')
{
* Given a year, a rule, and the offset from UT at the time that rule takes
* effect, calculate the year-relative time that rule takes effect.
*/
+
static int32
-transtime(int year, const struct rule *rulep,
- int32 offset)
+transtime(const int year, const struct rule *const rulep,
+ const int32 offset)
{
bool leapyear;
int32 value;
{
dstname = name;
name = getzname(name);
- dstlen = name - dstname; /* length of DST zone name */
+ dstlen = name - dstname; /* length of DST abbr. */
}
if (!dstlen)
return false;
/*
* Two transitions per year, from EPOCH_YEAR forward.
*/
- init_ttinfo(&sp->ttis[0], -dstoffset, true, stdlen + 1);
- init_ttinfo(&sp->ttis[1], -stdoffset, false, 0);
+ init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
+ init_ttinfo(&sp->ttis[1], -dstoffset, true, stdlen + 1);
sp->defaulttype = 0;
timecnt = 0;
janfirst = 0;
if (!increment_overflow_time
(&sp->ats[timecnt],
janoffset + starttime))
- sp->types[timecnt++] = reversed;
- else if (janoffset)
- sp->defaulttype = reversed;
+ sp->types[timecnt++] = !reversed;
sp->ats[timecnt] = janfirst;
if (!increment_overflow_time
(&sp->ats[timecnt],
janoffset + endtime))
{
- sp->types[timecnt++] = !reversed;
+ sp->types[timecnt++] = reversed;
yearlim = year + YEARSPERREPEAT + 1;
}
- else if (janoffset)
- sp->defaulttype = !reversed;
}
if (increment_overflow_time
(&janfirst, janoffset + yearsecs))
}
sp->timecnt = timecnt;
if (!timecnt)
+ {
+ sp->ttis[0] = sp->ttis[1];
sp->typecnt = 1; /* Perpetual DST. */
+ }
else if (YEARSPERREPEAT < year - yearbeg)
sp->goback = sp->goahead = true;
}
* otherwise, add the standard time offset to the
* transition time.
*/
-
/*
* Transitions from DST to DDST will effectively disappear
* since POSIX provides for only one DST offset.
}
static void
-gmtload(struct state *sp)
+gmtload(struct state *const sp)
{
if (tzload(gmt, NULL, sp, true) != 0)
tzparse(gmt, sp, true);
*/
static struct pg_tm *
localsub(struct state const *sp, pg_time_t const *timep,
- struct pg_tm *tmp)
+ struct pg_tm *const tmp)
{
const struct ttinfo *ttisp;
int i;
}
ttisp = &sp->ttis[i];
+ /*
+ * To get (wrong) behavior that's compatible with System V Release 2.0
+ * you'd replace the statement below with t += ttisp->tt_gmtoff;
+ * timesub(&t, 0L, sp, tmp);
+ */
result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
if (result)
{
*
* Except we have a private "struct state" for GMT, so no sp is passed in.
*/
+
static struct pg_tm *
-gmtsub(pg_time_t const *timep, int32 offset, struct pg_tm *tmp)
+gmtsub(pg_time_t const *timep, int32 offset,
+ struct pg_tm *tmp)
{
struct pg_tm *result;
return NULL; /* errno should be set by malloc */
gmtload(gmtptr);
}
+
result = timesub(timep, offset, gmtptr, tmp);
/*
* Return the number of leap years through the end of the given year
* where, to make the math easy, the answer for year zero is defined as zero.
*/
+
static int
leaps_thru_end_of_nonneg(int y)
{
+/* Compile .zi time zone data into TZif binary files. */
+
/*
* This file is in the public domain, so clarified as of
* 2006-07-17 by Arthur David Olson.
static void associate(void);
static void dolink(const char *, const char *, bool);
static char **getfields(char *buf);
-static zic_t gethms(const char *string, const char *errstring,
- bool);
+static zic_t gethms(const char *string, const char *errstring);
static zic_t getstdoff(char *, bool *);
static void infile(const char *filename);
static void inleap(char **fields, int nfields);
PERCENT_Z_LEN_BOUND = sizeof "+995959" - 1};
/* If true, work around a bug in Qt 5.6.1 and earlier, which mishandles
- tz binary files whose POSIX-TZ-style strings contain '<'; see
+ TZif files whose POSIX-TZ-style strings contain '<'; see
QTBUG-53071 <https://bugreports.qt.io/browse/QTBUG-53071>. This
workaround will no longer be needed when Qt 5.6.1 and earlier are
obsolete, say in the year 2021. */
#define ZF_RULE 3
#define ZF_FORMAT 4
#define ZF_TILYEAR 5
-#define ZF_TILMONTH 6
+#define ZF_TILMONTH 6
#define ZF_TILDAY 7
#define ZF_TILTIME 8
#define ZONE_MINFIELDS 5
#define ZFC_GMTOFF 0
#define ZFC_RULE 1
#define ZFC_FORMAT 2
-#define ZFC_TILYEAR 3
+#define ZFC_TILYEAR 3
#define ZFC_TILMONTH 4
#define ZFC_TILDAY 5
-#define ZFC_TILTIME 6
-#define ZONEC_MINFIELDS 3
-#define ZONEC_MAXFIELDS 7
+#define ZFC_TILTIME 6
+#define ZONEC_MINFIELDS 3
+#define ZONEC_MAXFIELDS 7
/*
* Which files are which on a Rule line.
#define RF_TOD 7
#define RF_STDOFF 8
#define RF_ABBRVAR 9
-#define RULE_FIELDS 10
+#define RULE_FIELDS 10
/*
* Which fields are which on a Link line.
#define LF_FROM 1
#define LF_TO 2
-#define LINK_FIELDS 3
+#define LINK_FIELDS 3
/*
* Which fields are which on a Leap line.
#define LP_TIME 4
#define LP_CORR 5
#define LP_ROLL 6
-#define LEAP_FIELDS 7
+#define LEAP_FIELDS 7
/*
* Year synonyms.
static zic_t const min_time = MINVAL(zic_t, TIME_T_BITS_IN_FILE);
static zic_t const max_time = MAXVAL(zic_t, TIME_T_BITS_IN_FILE);
-/*
- * Estimated time of the Big Bang, in seconds since the POSIX epoch.
- * rounded downward to the negation of a power of two that is
- * comfortably outside the error bounds.
- *
- * For the time of the Big Bang, see:
- *
- * Ade PAR, Aghanim N, Armitage-Caplan C et al. Planck 2013 results.
- * I. Overview of products and scientific results.
- * arXiv:1303.5062 2013-03-20 20:10:01 UTC
- * <https://arxiv.org/pdf/1303.5062v1> [PDF]
- *
- * Page 36, Table 9, row Age/Gyr, column Planck+WP+highL+BAO 68% limits
- * gives the value 13.798 plus-or-minus 0.037 billion years.
- * Multiplying this by 1000000000 and then by 31557600 (the number of
- * seconds in an astronomical year) gives a value that is comfortably
- * less than 2**59, so BIG_BANG is - 2**59.
- *
- * BIG_BANG is approximate, and may change in future versions.
- * Please do not rely on its exact value.
- */
-
-#ifndef BIG_BANG
-#define BIG_BANG (- (((zic_t) 1) << 59))
-#endif
-
-/* If true, work around GNOME bug 730332
- <https://bugzilla.gnome.org/show_bug.cgi?id=730332>
- by refusing to output time stamps before BIG_BANG.
- Such time stamps are physically suspect anyway.
-
- The GNOME bug is scheduled to be fixed in GNOME 3.22, and if so
- this workaround will no longer be needed when GNOME 3.21 and
- earlier are obsolete, say in the year 2021. */
-enum
-{
-WORK_AROUND_GNOME_BUG_730332 = true};
-
-static const zic_t early_time = (WORK_AROUND_GNOME_BUG_730332
- ? BIG_BANG
- : MINVAL(zic_t, TIME_T_BITS_IN_FILE));
-
/* Return true if NAME is a directory. */
static bool
itsdir(char const *name)
* A null string maps to zero.
* Call error with errstring and return zero on errors.
*/
+
static zic_t
-gethms(char const *string, char const *errstring, bool signable)
+gethms(char const *string, char const *errstring)
{
/* PG: make hh be int not zic_t to avoid sscanf portability issues */
int hh;
if (string == NULL || *string == '\0')
return 0;
- if (!signable)
- sign = 1;
- else if (*string == '-')
+ if (*string == '-')
{
sign = -1;
++string;
break;
}
}
- stdoff = gethms(field, _("invalid saved time"), true);
+ stdoff = gethms(field, _("invalid saved time"));
*isdst = dst < 0 ? stdoff != 0 : dst;
return stdoff;
}
error(_("wrong number of fields on Rule line"));
return;
}
- if (*fields[RF_NAME] == '\0')
+ switch (*fields[RF_NAME])
{
- error(_("nameless rule"));
- return;
+ case '\0':
+ case ' ':
+ case '\f':
+ case '\n':
+ case '\r':
+ case '\t':
+ case '\v':
+ case '+':
+ case '-':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ error(_("Invalid rule name \"%s\""), fields[RF_NAME]);
+ return;
}
r.r_filename = filename;
r.r_linenum = linenum;
}
z.z_filename = filename;
z.z_linenum = linenum;
- z.z_gmtoff = gethms(fields[i_gmtoff], _("invalid UT offset"), true);
+ z.z_gmtoff = gethms(fields[i_gmtoff], _("invalid UT offset"));
if ((cp = strchr(fields[i_format], '%')) != NULL)
{
if ((*++cp != 's' && *cp != 'z') || strchr(cp, '%')
return;
}
t = dayoff * SECSPERDAY;
- tod = gethms(fields[LP_TIME], _("invalid time of day"), false);
+ tod = gethms(fields[LP_TIME], _("invalid time of day"));
cp = fields[LP_CORR];
{
bool positive;
break;
}
}
- rp->r_tod = gethms(dp, _("invalid time of day"), false);
+ rp->r_tod = gethms(dp, _("invalid time of day"));
free(dp);
/*
}
static void
-writezone(const char *const name, const char *const string, char version)
+swaptypes(int i, int j)
+{
+ {
+ zic_t t = gmtoffs[i];
+
+ gmtoffs[i] = gmtoffs[j];
+ gmtoffs[j] = t;
+ }
+ {
+ char t = isdsts[i];
+
+ isdsts[i] = isdsts[j];
+ isdsts[j] = t;
+ }
+ {
+ unsigned char t = abbrinds[i];
+
+ abbrinds[i] = abbrinds[j];
+ abbrinds[j] = t;
+ }
+ {
+ bool t = ttisstds[i];
+
+ ttisstds[i] = ttisstds[j];
+ ttisstds[j] = t;
+ }
+ {
+ bool t = ttisgmts[i];
+
+ ttisgmts[i] = ttisgmts[j];
+ ttisgmts[j] = t;
+ }
+}
+
+static void
+writezone(const char *const name, const char *const string, char version,
+ int defaulttype)
{
FILE *fp;
ptrdiff_t i,
toi = 0;
fromi = 0;
- while (fromi < timecnt && attypes[fromi].at < early_time)
- ++fromi;
for (; fromi < timecnt; ++fromi)
{
- if (toi > 1 && ((attypes[fromi].at +
- gmtoffs[attypes[toi - 1].type]) <=
- (attypes[toi - 1].at +
- gmtoffs[attypes[toi - 2].type])))
+ if (toi != 0 && ((attypes[fromi].at +
+ gmtoffs[attypes[toi - 1].type]) <=
+ (attypes[toi - 1].at + gmtoffs[toi == 1 ? 0
+ : attypes[toi - 2].type])))
{
attypes[toi - 1].type =
attypes[fromi].type;
}
/*
- * Work around QTBUG-53071 for time stamps less than y2038_boundary - 1,
- * by inserting a no-op transition at time y2038_boundary - 1. This works
+ * Work around QTBUG-53071 for timestamps less than y2038_boundary - 1, by
+ * inserting a no-op transition at time y2038_boundary - 1. This works
* only for timestamps before the boundary, which should be good enough in
* practice as QTBUG-53071 should be long-dead by 2038.
*/
int thisleapi,
thisleapcnt,
thisleaplim;
- int writetype[TZ_MAX_TYPES];
+ int old0;
+ char omittype[TZ_MAX_TYPES];
int typemap[TZ_MAX_TYPES];
int thistypecnt;
char thischars[TZ_MAX_CHARS];
error(_("too many transition times"));
thistimelim = thistimei + thistimecnt;
thisleaplim = thisleapi + thisleapcnt;
- for (i = 0; i < typecnt; ++i)
- writetype[i] = thistimecnt == timecnt;
- if (thistimecnt == 0)
- {
- /*
- * No transition times fall in the current (32- or 64-bit) window.
- */
- if (typecnt != 0)
- writetype[typecnt - 1] = true;
- }
- else
- {
- for (i = thistimei - 1; i < thistimelim; ++i)
- if (i >= 0)
- writetype[types[i]] = true;
+ memset(omittype, true, typecnt);
+ omittype[defaulttype] = false;
+ for (i = thistimei; i < thistimelim; i++)
+ omittype[types[i]] = false;
+
+ /*
+ * Reorder types to make DEFAULTTYPE type 0. Use TYPEMAP to swap OLD0
+ * and DEFAULTTYPE so that DEFAULTTYPE appears as type 0 in the output
+ * instead of OLD0. TYPEMAP also omits unused types.
+ */
+ old0 = strlen(omittype);
+ swaptypes(old0, defaulttype);
- /*
- * For America/Godthab and Antarctica/Palmer
- */
- if (thistimei == 0)
- writetype[0] = true;
- }
#ifndef LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH
/*
mrudst = types[i];
else
mrustd = types[i];
- for (i = 0; i < typecnt; ++i)
- if (writetype[i])
+ for (i = old0; i < typecnt; i++)
+ if (!omittype[i])
{
if (isdsts[i])
hidst = i;
ttisstds[mrudst],
ttisgmts[mrudst]);
isdsts[mrudst] = 1;
- writetype[type] = true;
+ omittype[type] = false;
}
if (histd >= 0 && mrustd >= 0 && histd != mrustd &&
gmtoffs[histd] != gmtoffs[mrustd])
ttisstds[mrustd],
ttisgmts[mrustd]);
isdsts[mrustd] = 0;
- writetype[type] = true;
+ omittype[type] = false;
}
}
#endif /* !defined
* LEAVE_SOME_PRE_2011_SYSTEMS_IN_THE_LURCH */
thistypecnt = 0;
- for (i = 0; i < typecnt; ++i)
- typemap[i] = writetype[i] ? thistypecnt++ : -1;
+ for (i = old0; i < typecnt; i++)
+ if (!omittype[i])
+ typemap[i == old0 ? defaulttype
+ : i == defaulttype ? old0 : i]
+ = thistypecnt++;
+
for (i = 0; i < sizeof indmap / sizeof indmap[0]; ++i)
indmap[i] = -1;
thischarcnt = 0;
- for (i = 0; i < typecnt; ++i)
+ for (i = old0; i < typecnt; i++)
{
char *thisabbr;
- if (!writetype[i])
+ if (omittype[i])
continue;
if (indmap[abbrinds[i]] >= 0)
continue;
DO(tzh_typecnt);
DO(tzh_charcnt);
#undef DO
- for (i = thistimei; i < thistimelim; ++i)
- if (pass == 1)
- /*
- * Output an INT32_MIN "transition" if appropriate; see above.
- */
- puttzcode(((ats[i] < PG_INT32_MIN) ?
- PG_INT32_MIN : ats[i]), fp);
- else
+ /* PG: print current timezone abbreviations if requested */
+ if (print_abbrevs && pass == 2)
+ {
+ /* Print "type" data for periods ending after print_cutoff */
+ for (i = thistimei; i < thistimelim; ++i)
{
- puttzcode64(ats[i], fp);
-
- /* Print current timezone abbreviations if requested */
- if (print_abbrevs &&
- (i == thistimelim - 1 || ats[i + 1] > print_cutoff))
+ if (i == thistimelim - 1 || ats[i + 1] > print_cutoff)
{
- unsigned char tm = typemap[types[i]];
+ unsigned char tm = types[i];
char *thisabbrev = &thischars[indmap[abbrinds[tm]]];
/* filter out assorted junk entries */
isdsts[tm] ? "\tD" : "");
}
}
+ /* Print the default type if we have no transitions at all */
+ if (thistimei >= thistimelim)
+ {
+ unsigned char tm = defaulttype;
+ char *thisabbrev = &thischars[indmap[abbrinds[tm]]];
+
+ /* filter out assorted junk entries */
+ if (strcmp(thisabbrev, GRANDPARENTED) != 0 &&
+ strcmp(thisabbrev, "zzz") != 0)
+ fprintf(stdout, "%s\t" INT64_FORMAT "%s\n",
+ thisabbrev,
+ gmtoffs[tm],
+ isdsts[tm] ? "\tD" : "");
+ }
+ }
+
+ for (i = thistimei; i < thistimelim; ++i)
+ if (pass == 1)
+
+ /*
+ * Output an INT32_MIN "transition" if appropriate; see above.
+ */
+ puttzcode(((ats[i] < PG_INT32_MIN) ?
+ PG_INT32_MIN : ats[i]), fp);
+ else
+ puttzcode64(ats[i], fp);
for (i = thistimei; i < thistimelim; ++i)
{
unsigned char uc;
uc = typemap[types[i]];
fwrite(&uc, sizeof uc, 1, fp);
}
- for (i = 0; i < typecnt; ++i)
- if (writetype[i])
+ for (i = old0; i < typecnt; i++)
+ if (!omittype[i])
{
puttzcode(gmtoffs[i], fp);
putc(isdsts[i], fp);
puttzcode64(todo, fp);
puttzcode(corr[i], fp);
}
- for (i = 0; i < typecnt; ++i)
- if (writetype[i])
+ for (i = old0; i < typecnt; i++)
+ if (!omittype[i])
putc(ttisstds[i], fp);
- for (i = 0; i < typecnt; ++i)
- if (writetype[i])
+ for (i = old0; i < typecnt; i++)
+ if (!omittype[i])
putc(ttisgmts[i], fp);
+ swaptypes(old0, defaulttype);
}
fprintf(fp, "\n%s\n", string);
close_file(fp, directory, name);
zic_t one = 1;
zic_t y2038_boundary = one << 31;
zic_t max_year0;
+ int defaulttype = -1;
max_abbr_len = 2 + max_format_len + max_abbrvar_len;
max_envvar_len = 2 * max_abbr_len + 5 * 9;
*/
stdoff = 0;
zp = &zpfirst[i];
- usestart = i > 0 && (zp - 1)->z_untiltime > early_time;
+ usestart = i > 0 && (zp - 1)->z_untiltime > min_time;
useuntil = i < (zonecount - 1);
- if (useuntil && zp->z_untiltime <= early_time)
+ if (useuntil && zp->z_untiltime <= min_time)
continue;
gmtoff = zp->z_gmtoff;
eat(zp->z_filename, zp->z_linenum);
usestart = false;
}
else
- addtt(early_time, type);
+ defaulttype = type;
}
else
for (year = min_year; year <= max_year; ++year)
offset = oadd(zp->z_gmtoff, rp->r_stdoff);
type = addtype(offset, ab, rp->r_isdst,
rp->r_todisstd, rp->r_todisgmt);
+ if (defaulttype < 0 && !rp->r_isdst)
+ defaulttype = type;
if (rp->r_hiyear == ZIC_MAX
&& !(0 <= lastatmax
&& ktime < attypes[lastatmax].at))
if (*startbuf == '\0')
error(_("cannot determine time zone abbreviation to use just after until time"));
else
- addtt(starttime,
- addtype(startoff, startbuf,
- startoff != zp->z_gmtoff,
- startttisstd,
- startttisgmt));
+ {
+ bool isdst = startoff != zp->z_gmtoff;
+
+ type = addtype(startoff, startbuf, isdst,
+ startttisstd, startttisgmt);
+ if (defaulttype < 0 && !isdst)
+ defaulttype = type;
+ addtt(starttime, type);
+ }
}
/*
starttime = tadd(starttime, -gmtoff);
}
}
+ if (defaulttype < 0)
+ defaulttype = 0;
if (0 <= lastatmax)
attypes[lastatmax].dontmerge = true;
if (do_extend)
attypes[timecnt - 1].dontmerge = true;
}
}
- writezone(zpfirst->z_name, envvar, version);
+ writezone(zpfirst->z_name, envvar, version, defaulttype);
free(startbuf);
free(ab);
free(envvar);
static void
addtt(zic_t starttime, int type)
{
- if (starttime <= early_time
- || (timecnt == 1 && attypes[0].at < early_time))
- {
- gmtoffs[0] = gmtoffs[type];
- isdsts[0] = isdsts[type];
- ttisstds[0] = ttisstds[type];
- ttisgmts[0] = ttisgmts[type];
- if (abbrinds[type] != 0)
- strcpy(chars, &chars[abbrinds[type]]);
- abbrinds[0] = 0;
- charcnt = strlen(chars) + 1;
- typecnt = 1;
- timecnt = 0;
- type = 0;
- }
attypes = growalloc(attypes, sizeof *attypes, timecnt, &timecnt_alloc);
attypes[timecnt].at = starttime;
attypes[timecnt].dontmerge = false;
}
/* If A is an uppercase character in the C locale, return its lowercase
- * counterpart. Otherwise, return A. */
+ counterpart. Otherwise, return A. */
static char
lowerit(char a)
{
dayoff = 0;
m = TM_JANUARY;
y = EPOCH_YEAR;
+ if (y < wantedy)
+ {
+ wantedy -= y;
+ dayoff = (wantedy / YEARSPERREPEAT) * (SECSPERREPEAT / SECSPERDAY);
+ wantedy %= YEARSPERREPEAT;
+ wantedy += y;
+ }
+ else if (wantedy < 0)
+ {
+ dayoff = (wantedy / YEARSPERREPEAT) * (SECSPERREPEAT / SECSPERDAY);
+ wantedy %= YEARSPERREPEAT;
+ }
while (wantedy != y)
{
if (wantedy > y)
if (dayoff > max_time / SECSPERDAY)
return max_time;
t = (zic_t) dayoff * SECSPERDAY;
-
return tadd(t, rp->r_tod);
}