mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-10-28 11:25:21 +01:00
Import tzcode 2026d
This commit is contained in:
1 parent
2479b6921a
commit
4d4fdb78db
17 files changed
+531
-428
No files matched your search
+1
-1
@@ -22,7 +22,7 @@ To email small changes, please run a POSIX shell command like
|
||||
For more-elaborate or possibly controversial changes,
|
||||
such as renaming, adding or removing zones, please read
|
||||
“Theory and pragmatics of the tz code and data”
|
||||
<https://www.iana.org/time-zones/repository/theory.html>.
|
||||
<https://data.iana.org/time-zones/theory.html>
|
||||
It is also good to browse the mailing list archives
|
||||
<https://lists.iana.org/hyperkitty/list/[email protected]/>
|
||||
for examples of patches that tend to work well.
|
||||
|
||||
@@ -172,9 +172,9 @@ EXPIRES_LINE= 0
|
||||
|
||||
TZDATA_TEXT= leapseconds tzdata.zi
|
||||
|
||||
# For backward-compatibility links for old zone names, use
|
||||
# For backward-compatibility links and zones for old names, use
|
||||
# BACKWARD= backward
|
||||
# To omit these links, use
|
||||
# To omit these links and zones, use
|
||||
# BACKWARD=
|
||||
|
||||
BACKWARD= backward
|
||||
@@ -574,7 +574,7 @@ SAFE_CHAR= '[]'$(SAFE_CHARSET)'-]'
|
||||
# These non-alphabetic, non-ASCII printable characters are
|
||||
# used in commentary or in generated *.txt files
|
||||
# and are not likely to cause confusion.
|
||||
UNUSUAL_OK_CHARSET= §«°±»½¾×–‘’“”•→−≤★⟨⟩⯪
|
||||
UNUSUAL_OK_CHARSET= §«°±»½¾¿×–‘’“”•→−≤★⟨⟩⯪
|
||||
|
||||
# Put this in a bracket expression to match spaces.
|
||||
s = [:space:]
|
||||
@@ -922,7 +922,7 @@ check_mild: check_web check_zishrink \
|
||||
UTF8_LOCALE_MISSING = \
|
||||
{ test ! '$(UTF8_LOCALE)' \
|
||||
|| ! printf 'A\304\200B\n' \
|
||||
| LC_ALL='$(UTF8_LOCALE)' grep -q '^A.B$$' >/dev/null 2>&1 \
|
||||
| LC_ALL='$(UTF8_LOCALE)' grep -q '^A[[:alpha:]]B$$' >/dev/null 2>&1 \
|
||||
|| { export LC_ALL='$(UTF8_LOCALE)'; false; }; }
|
||||
|
||||
character-set.ck: $(ENCHILADA)
|
||||
@@ -1006,11 +1006,11 @@ now.ck: checknow.awk date tzdata.zi zdump zic zone1970.tab zonenow.tab
|
||||
now=$(CHECK_NOW_TIMESTAMP) && \
|
||||
future=$$(($(CHECK_NOW_FUTURE_SECS) + $$now)) && \
|
||||
./zdump -i -t $$now,$$future \
|
||||
$$(find "$$PWD/$@d"/????*/ -type f) \
|
||||
$$(find "$$PWD/$@d"/????*/ -type f -o -type l) \
|
||||
>$@d/zdump-now.tab && \
|
||||
./zdump -i -t 0,$$future \
|
||||
$$(find "$$PWD/$@d" -name Etc -prune \
|
||||
-o -type f ! -name '*.tab' -print) \
|
||||
-o \( -type f -o -type l \) ! -name '*.tab' -print) \
|
||||
>$@d/zdump-1970.tab && \
|
||||
$(AWK) \
|
||||
-v now=$$now \
|
||||
@@ -1018,7 +1018,12 @@ now.ck: checknow.awk date tzdata.zi zdump zic zone1970.tab zonenow.tab
|
||||
-v zdump_table=$@d/zdump-now.tab \
|
||||
-f checknow.awk zonenow.tab
|
||||
$(AWK) \
|
||||
'BEGIN {print "-\t-\tUTC"} /^Zone/ {print "-\t-\t" $$2}' \
|
||||
'BEGIN { \
|
||||
SysVzone["EST5EDT"] = 1; SysVzone["CST6CDT"] = 1; \
|
||||
SysVzone["MST7MDT"] = 1; SysVzone["PST8PDT"] = 1; \
|
||||
print "-\t-\tUTC" \
|
||||
} \
|
||||
$$1 == "Zone" && !SysVzone[$$2] {print "-\t-\t" $$2}' \
|
||||
$(PRIMARY_YDATA) backward factory | \
|
||||
$(AWK) \
|
||||
-v zdump_table=$@d/zdump-1970.tab \
|
||||
|
||||
@@ -1,5 +1,87 @@
|
||||
News for the tz database
|
||||
|
||||
Release 2026d - 2026-09-11 15:21:07 -0700
|
||||
|
||||
Briefly:
|
||||
Canada’s Northwest Territories moved to permanent -06 on 2026-08-21.
|
||||
Obsolescent settings like TZ="EST5EDT" now conform better to POSIX.
|
||||
Fix security, performance and porting bugs in zic and localtime.
|
||||
|
||||
Changes to future timestamps
|
||||
|
||||
Canada’s Northwest Territories will not fall back on 2026-11-01
|
||||
and will stay on -06 year-round, matching Alberta’s recent change.
|
||||
Model this with its traditional abbreviation CST. Although the
|
||||
change to permanent -06 legally took place on 2026-08-21,
|
||||
temporarily model the change to occur on 2026-11-01 at 02:00
|
||||
for the same reason as other recent temporary hacks. (Caution:
|
||||
see “NOTE FOR 2026b TEMPORARY HACK FOR CLDR AND CANADA” below.)
|
||||
This affects only America/Inuvik as the rest of the territory is
|
||||
covered by America/Edmonton, for which the equivalent change was
|
||||
released in 2026c.
|
||||
|
||||
Changes to past timestamps
|
||||
|
||||
Colombia’s 1992-05-02 spring forward was at 00:00, not 24:00.
|
||||
|
||||
Iran’s 1979-05-26 spring forward was at 00:00, not 24:00.
|
||||
(Thanks to N.F. Hase.)
|
||||
|
||||
The backward-compatibility names EST5EDT, CST6CDT, MST7MDT, and
|
||||
PST8PDT now conform better to POSIX. For example, EST5EDT now
|
||||
always uses the abbreviation "EST" for standard time (now always 5
|
||||
hours behind UT) and "EDT" for daylight saving time, whereas it
|
||||
formerly had different UT offsets before standard time was
|
||||
introduced and sometimes used abbreviations like "LMT", "EWT" and
|
||||
"EPT", all contrary to POSIX. Also, though not required by POSIX
|
||||
these names now use US federal rules rather than rules of places
|
||||
like New York, reverting to 2024a behavior. This change affects
|
||||
only timestamps before 1966-10-30 at 01:00 standard time.
|
||||
|
||||
Other data changes
|
||||
|
||||
The temporary hacks used for North American timekeeping changes
|
||||
now work around a libstdc++ std::chrono bug in GCC 14.1-14.4,
|
||||
15.1-15.2, and 16.1; see GCC bug 124851. This data change does
|
||||
not affect TZif files or timestamps. The change does not work
|
||||
around the related but less serious GCC bugs 116110 and 124513.
|
||||
These GCC bugs are all fixed in GCC 16.2.
|
||||
|
||||
Changes to code
|
||||
|
||||
zic now rejects Link targets that would have invalid names, and
|
||||
more efficiently processes Expires, Leap and Rule lines with years
|
||||
far in the past or future. (Thanks to Darren Carreras.)
|
||||
|
||||
zic now ports to systems that report lack of link support via
|
||||
EINVAL, ENOSYS or EPERM errno values. (Thanks to Tom Lane.)
|
||||
|
||||
When tzset and related functions encounter a TZif file that is too
|
||||
large for them, they now consistently fail instead of sometimes
|
||||
silently ignoring excess parts of the file.
|
||||
|
||||
localtime-related functions no longer mishandle extreme timestamps
|
||||
when given TZif files holding some unlikely timezone histories.
|
||||
(Problem reported by David Sarkisyan.)
|
||||
|
||||
localtime-related functions no longer check the values of TZif
|
||||
files’ standard/wall and UT/local indicators, which these
|
||||
functions have not used since 2026a’s removal of the old
|
||||
posixrules feature.
|
||||
|
||||
tzcode has been ported to Haiku.
|
||||
|
||||
localtime.c now works again by default on AIX and DragonFly BSD.
|
||||
|
||||
zic now rejects ‘:’ and ‘\’ in Zone and Link names when running on
|
||||
Microsoft Windows. (Problem reported by David Diaz.)
|
||||
|
||||
Changes to documentation
|
||||
|
||||
URLs for release tarballs in tz-link.html have been updated to
|
||||
reflect their new canonical URLs on data.iana.org.
|
||||
|
||||
|
||||
Release 2026c - 2026-07-08 10:23:58 -0700
|
||||
|
||||
Briefly:
|
||||
@@ -15,7 +97,13 @@ Release 2026c - 2026-07-08 10:23:58 -0700
|
||||
CST. Although the change to permanent -06 legally took place on
|
||||
2026-06-18, temporarily model the change to occur on 2026-11-01 at
|
||||
02:00 instead, for the same reason we introduced a similarly
|
||||
temporary hack for British Columbia in 2026b.
|
||||
temporary hack for British Columbia in 2026b. (Caution: see
|
||||
“NOTE FOR 2026b TEMPORARY HACK FOR CLDR AND CANADA” below.)
|
||||
|
||||
As the change affects both America/Edmonton and its backward
|
||||
compatibility link, the obsolescent setting TZ="Canada/Mountain"
|
||||
will now use the abbreviation CST for affected timestamps,
|
||||
akin to TZ="Canada/Pacific" behavior introduced in 2026b.
|
||||
|
||||
Although another TZDB release will likely be needed soon because
|
||||
Northwest Territories will likely follow Alberta, the legal
|
||||
@@ -67,6 +155,7 @@ Release 2026b - 2026-04-22 23:06:43 -0700
|
||||
|
||||
Briefly:
|
||||
British Columbia moved to permanent -07 on 2026-03-09.
|
||||
zic no longer mishandles a last transition to a new time type.
|
||||
Some more overflow bugs have been fixed in zic.
|
||||
|
||||
Changes to future timestamps
|
||||
@@ -79,9 +168,33 @@ Release 2026b - 2026-04-22 23:06:43 -0700
|
||||
limitation in CLDR 48.1 (2026-01-08). This temporary hack is
|
||||
planned to be removed after CLDR is fixed.
|
||||
|
||||
To match longstanding practice for -07 standard time in North
|
||||
America, such as for America/Dawson, America/Dawson_Creek,
|
||||
America/Fort_Nelson and America/Whitehorse, affected BC
|
||||
timestamps use the abbreviation MST. As the change affects both
|
||||
America/Vancouver and its backward compatibility link, the
|
||||
obsolescent setting TZ="Canada/Pacific" will now use the
|
||||
abbreviation MST. Future TZDB releases may change the
|
||||
abbreviation if something else becomes popular across areas
|
||||
observing -07, and may change it to "-07" if no alphabetic
|
||||
consensus emerges.
|
||||
|
||||
Changes to code
|
||||
|
||||
zic no longer mishandles a last transition to a new time type.
|
||||
NOTE FOR 2026b TEMPORARY HACK FOR CLDR AND CANADA:
|
||||
This zic fix is needed for the temporary hack (mentioned above)
|
||||
that works around the Canadian timekeeping bug in Unicode CLDR.
|
||||
Without the fix, the temporary hack causes zic versions 2023d
|
||||
through 2026a, in their default mode that generates slim output,
|
||||
to generate a TZif file that violates Internet RFC 9636 §3.3.
|
||||
The buggy file in turn causes some TZif readers, including tzcode
|
||||
itself, to ignore America/Vancouver’s 2026-11-01 02:00 transition
|
||||
from PDT (tm_isdst=1) to MST (tm_isdst=0). Although the buggy
|
||||
file does not cause any known TZif reader to mishandle UT offsets,
|
||||
caution is advised when using zic 2023d through 2026a to compile
|
||||
data from more-recent tz releases. To work around this problem
|
||||
when using these older zic versions, use ‘zic -b fat’.
|
||||
|
||||
zic no longer overflows a buffer when generating a TZ string like
|
||||
"PST-167:59:58PDT-167:59:59,M11.5.6/-167:59:59,M12.5.6/-167:59:59",
|
||||
|
||||
@@ -10,7 +10,7 @@ locations around the globe. It is updated periodically to reflect
|
||||
changes made by political bodies to time zone boundaries, UTC offsets,
|
||||
and daylight-saving rules.
|
||||
|
||||
See <https://www.iana.org/time-zones/repository/tz-link.html> or the
|
||||
See <https://data.iana.org/time-zones/tz-link.html> or the
|
||||
file tz-link.html for how to acquire the code and data.
|
||||
|
||||
Once acquired, read the leading comments in the file ‘Makefile’
|
||||
|
||||
+167
-232
@@ -64,7 +64,7 @@ struct stat { char st_ctime, st_dev, st_ino; };
|
||||
# endif
|
||||
# if THREAD_PREFER_SINGLE
|
||||
# ifndef HAVE___ISTHREADED
|
||||
# if defined __FreeBSD__ || defined __OpenBSD__
|
||||
# if defined __FreeBSD__ || defined __OpenBSD__ || defined __DragonFly__
|
||||
# define HAVE___ISTHREADED 1
|
||||
# else
|
||||
# define HAVE___ISTHREADED 0
|
||||
@@ -348,6 +348,10 @@ static int fstatat(int dd, char const *path, struct stat *st, int flags)
|
||||
# include <sys/auxv.h>
|
||||
# endif
|
||||
|
||||
/* Avoid clash if headers declare but libraries do not define issetugid. */
|
||||
# undef issetugid
|
||||
# define issetugid localtime_issetugid
|
||||
|
||||
/* Return 1 if the process is privileged, 0 otherwise. */
|
||||
static int
|
||||
issetugid(void)
|
||||
@@ -475,8 +479,6 @@ struct ttinfo { /* time type information */
|
||||
-2**31 + 1 .. 2**31 - 1 */
|
||||
desigidx_type tt_desigidx; /* abbreviation list index */
|
||||
bool tt_isdst; /* used to set tm_isdst */
|
||||
bool tt_ttisstd; /* transition is std time */
|
||||
bool tt_ttisut; /* transition is UT */
|
||||
};
|
||||
|
||||
struct lsinfo { /* leap second information */
|
||||
@@ -505,7 +507,6 @@ struct state {
|
||||
int timecnt;
|
||||
int typecnt;
|
||||
int charcnt;
|
||||
bool goback;
|
||||
bool goahead;
|
||||
time_t ats[TZ_MAX_TIMES];
|
||||
unsigned char types[TZ_MAX_TIMES];
|
||||
@@ -569,12 +570,11 @@ struct rule {
|
||||
};
|
||||
|
||||
static struct tm *gmtsub(struct state const *, time_t const *, int_fast32_t,
|
||||
struct tm *);
|
||||
static bool increment_overflow(int *, int);
|
||||
struct tm *, time_t *);
|
||||
static bool increment_overflow_time(time_t *, int_fast32_2s);
|
||||
static int_fast32_2s leapcorr(struct state const *, time_t);
|
||||
static struct tm *timesub(time_t const *, int_fast32_t, struct state const *,
|
||||
struct tm *);
|
||||
struct tm *, time_t *);
|
||||
static bool tzparse(char const *, struct state *, struct state const *);
|
||||
|
||||
#ifndef ALL_STATE
|
||||
@@ -641,8 +641,6 @@ init_ttinfo(struct ttinfo *s, int_fast32_t utoff, bool isdst,
|
||||
s->tt_utoff = utoff;
|
||||
s->tt_isdst = isdst;
|
||||
s->tt_desigidx = desigidx;
|
||||
s->tt_ttisstd = false;
|
||||
s->tt_ttisut = false;
|
||||
}
|
||||
|
||||
/* Return true if SP's time type I does not specify local time. */
|
||||
@@ -838,10 +836,11 @@ tzfile_changed(int fd, struct stat *st)
|
||||
resolution if available, as this can help distinguish files on
|
||||
non-POSIX platforms where st_dev and st_ino are unreliable. */
|
||||
struct timespec ctim;
|
||||
#if HAVE_STRUCT_STAT_ST_CTIM
|
||||
ctim = st->st_ctim;
|
||||
#else
|
||||
/* Copy via members, as AIX 7.3 defaults to an incompatible st_ctim. */
|
||||
ctim.tv_sec = st->st_ctime;
|
||||
#if HAVE_STRUCT_STAT_ST_CTIM
|
||||
ctim.tv_nsec = st->st_ctim.tv_nsec;
|
||||
#else
|
||||
ctim.tv_nsec = 0;
|
||||
#endif
|
||||
|
||||
@@ -896,9 +895,19 @@ union local_storage {
|
||||
};
|
||||
|
||||
/* These tzload flags can be ORed together, and fit into 'char'. */
|
||||
enum { TZLOAD_FROMENV = 1 }; /* The TZ string came from the environment. */
|
||||
enum { TZLOAD_TZSTRING = 2 }; /* Read any newline-surrounded TZ string. */
|
||||
enum { TZLOAD_TZDIR_SUB = 4 }; /* TZ should be a file under TZDIR. */
|
||||
|
||||
/* TZLOAD_FROMENV means the TZ string is a process-wide setting either
|
||||
taken from the TZ environment variable or inferred from TZ being unset.
|
||||
When 0 <= tz_change_interval, TZLOAD_FROMENV lets us skip reanalysis
|
||||
of a TZif file that did not change during the interval. */
|
||||
enum { TZLOAD_FROMENV = 1 };
|
||||
|
||||
/* Read any newline-surrounded TZ string. */
|
||||
enum { TZLOAD_TZSTRING = 2 };
|
||||
|
||||
/* TZ should be a file under TZDIR. */
|
||||
enum { TZLOAD_TZDIR_SUB = 4 };
|
||||
|
||||
|
||||
/* Load tz data from the file named NAME into *SP. Respect TZLOADFLAGS.
|
||||
Use **LSPP for temporary storage. Return 0 on
|
||||
@@ -923,7 +932,7 @@ tzloadbody(char const *name, struct state *sp, char tzloadflags,
|
||||
struct stat st;
|
||||
st.st_ctime = 0;
|
||||
|
||||
sp->goback = sp->goahead = false;
|
||||
sp->goahead = false;
|
||||
|
||||
if (! name) {
|
||||
name = TZDEFAULT;
|
||||
@@ -1198,30 +1207,9 @@ tzloadbody(char const *name, struct state *sp, char tzloadflags,
|
||||
}
|
||||
set_leapcount(sp, leapcnt);
|
||||
|
||||
for (i = 0; i < sp->typecnt; ++i) {
|
||||
register struct ttinfo * ttisp;
|
||||
|
||||
ttisp = &sp->ttis[i];
|
||||
if (ttisstdcnt == 0)
|
||||
ttisp->tt_ttisstd = false;
|
||||
else {
|
||||
if (*p != true && *p != false)
|
||||
return EFTYPE;
|
||||
ttisp->tt_ttisstd = *p++;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < sp->typecnt; ++i) {
|
||||
register struct ttinfo * ttisp;
|
||||
|
||||
ttisp = &sp->ttis[i];
|
||||
if (ttisutcnt == 0)
|
||||
ttisp->tt_ttisut = false;
|
||||
else {
|
||||
if (*p != true && *p != false)
|
||||
return EFTYPE;
|
||||
ttisp->tt_ttisut = *p++;
|
||||
}
|
||||
}
|
||||
/* Do not bother to validate standard/wall and UT/local
|
||||
indicators, as they are no longer used here. */
|
||||
p += ttisstdcnt + ttisutcnt;
|
||||
}
|
||||
|
||||
nread -= p - up->buf;
|
||||
@@ -1232,13 +1220,13 @@ tzloadbody(char const *name, struct state *sp, char tzloadflags,
|
||||
break;
|
||||
}
|
||||
if ((tzloadflags & TZLOAD_TZSTRING) && nread > 2 &&
|
||||
up->buf[0] == '\n' && up->buf[nread - 1] == '\n' &&
|
||||
sp->typecnt + 2 <= TZ_MAX_TYPES) {
|
||||
up->buf[0] == '\n' && up->buf[nread - 1] == '\n') {
|
||||
struct state *ts = &lsp->u.st;
|
||||
|
||||
up->buf[nread - 1] = '\0';
|
||||
if (tzparse(&up->buf[1], ts, sp)) {
|
||||
|
||||
if (!tzparse(&up->buf[1], ts, sp))
|
||||
return EFTYPE;
|
||||
else {
|
||||
/* Attempt to reuse existing abbreviations.
|
||||
Without this, America/Anchorage would
|
||||
consume 50 bytes for abbreviations, as
|
||||
@@ -1246,7 +1234,6 @@ tzloadbody(char const *name, struct state *sp, char tzloadflags,
|
||||
AHDT YST AKDT AKST) and ts->charcnt equals 10
|
||||
(for AKST AKDT). Reusing means sp->charcnt can
|
||||
stay 40 in this example. */
|
||||
int gotabbr = 0;
|
||||
int charcnt = sp->charcnt;
|
||||
for (i = 0; i < ts->typecnt; i++) {
|
||||
char *tsabbr = ts->chars + ts->ttis[i].tt_desigidx;
|
||||
@@ -1254,22 +1241,25 @@ tzloadbody(char const *name, struct state *sp, char tzloadflags,
|
||||
for (j = 0; j < charcnt; j++)
|
||||
if (strcmp(sp->chars + j, tsabbr) == 0) {
|
||||
ts->ttis[i].tt_desigidx = j;
|
||||
gotabbr++;
|
||||
break;
|
||||
}
|
||||
if (! (j < charcnt)) {
|
||||
int tsabbrlen = strnlen(tsabbr, TZ_MAX_CHARS - j);
|
||||
if (j + tsabbrlen < TZ_MAX_CHARS) {
|
||||
if (TZ_MAX_CHARS <= j + tsabbrlen)
|
||||
return EOVERFLOW;
|
||||
else {
|
||||
char *cp = sp->chars + j;
|
||||
cp = mempcpy(cp, tsabbr, tsabbrlen);
|
||||
*cp = '\0';
|
||||
charcnt = j + tsabbrlen + 1;
|
||||
ts->ttis[i].tt_desigidx = j;
|
||||
gotabbr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (gotabbr == ts->typecnt) {
|
||||
|
||||
if (TZ_MAX_TYPES - sp->typecnt < ts->typecnt)
|
||||
return EOVERFLOW;
|
||||
else {
|
||||
sp->charcnt = charcnt;
|
||||
|
||||
/* Ignore any trailing, no-op transitions generated
|
||||
@@ -1288,10 +1278,8 @@ tzloadbody(char const *name, struct state *sp, char tzloadflags,
|
||||
|| (0 < sp->timecnt
|
||||
&& t <= sp->ats[sp->timecnt - 1]))
|
||||
continue;
|
||||
if (TZ_MAX_TIMES <= sp->timecnt) {
|
||||
sp->goahead = false;
|
||||
break;
|
||||
}
|
||||
if (TZ_MAX_TIMES <= sp->timecnt)
|
||||
return EOVERFLOW;
|
||||
sp->ats[sp->timecnt] = t;
|
||||
sp->types[sp->timecnt] = (sp->typecnt
|
||||
+ ts->types[i]);
|
||||
@@ -1334,10 +1322,6 @@ static const int mon_lengths[2][MONSPERYEAR] = {
|
||||
{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
|
||||
};
|
||||
|
||||
static const int year_lengths[2] = {
|
||||
DAYSPERNYEAR, DAYSPERLYEAR
|
||||
};
|
||||
|
||||
/* Is C an ASCII digit? */
|
||||
static bool
|
||||
is_digit(char c)
|
||||
@@ -1537,40 +1521,26 @@ getrule(const char *strp, register struct rule *const rulep)
|
||||
*/
|
||||
|
||||
static int_fast32_t
|
||||
transtime(const int year, register const struct rule *const rulep,
|
||||
transtime(time_t year, register const struct rule *const rulep,
|
||||
const int_fast32_t offset)
|
||||
{
|
||||
int d; /* Day of year (zero-origin). */
|
||||
register bool leapyear;
|
||||
register int_fast32_t value;
|
||||
register int i;
|
||||
int d, m1, yy0, yy1, yy2, dow;
|
||||
|
||||
leapyear = isleap(year);
|
||||
switch (rulep->r_type) {
|
||||
|
||||
case JULIAN_DAY:
|
||||
if (rulep->r_type <= DAY_OF_YEAR) {
|
||||
/*
|
||||
** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
|
||||
** years.
|
||||
** In non-leap years, or if the day number is 59 or less, just
|
||||
** add SECSPERDAY times the day number-1 to the time of
|
||||
** January 1, midnight, to get the day.
|
||||
*/
|
||||
value = (rulep->r_day - 1) * SECSPERDAY;
|
||||
if (leapyear && rulep->r_day >= 60)
|
||||
value += SECSPERDAY;
|
||||
break;
|
||||
|
||||
case DAY_OF_YEAR:
|
||||
/*
|
||||
** use the day number - 1.
|
||||
**
|
||||
** n - day of year.
|
||||
** Just add SECSPERDAY times the day number to the time of
|
||||
** January 1, midnight, to get the day.
|
||||
*/
|
||||
value = rulep->r_day * SECSPERDAY;
|
||||
break;
|
||||
|
||||
case MONTH_NTH_DAY_OF_WEEK:
|
||||
d = rulep->r_day - ((rulep->r_type < DAY_OF_YEAR)
|
||||
& (!leapyear | (rulep->r_day <= 59)));
|
||||
} else {
|
||||
/*
|
||||
** Mm.n.d - nth "dth day" of month m.
|
||||
*/
|
||||
@@ -1579,14 +1549,16 @@ transtime(const int year, register const struct rule *const rulep,
|
||||
** Use Zeller's Congruence to get day-of-week of first day of
|
||||
** month.
|
||||
*/
|
||||
m1 = (rulep->r_mon + 9) % 12 + 1;
|
||||
yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
|
||||
yy1 = yy0 / 100;
|
||||
yy2 = yy0 % 100;
|
||||
dow = ((26 * m1 - 2) / 10 +
|
||||
1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
|
||||
if (dow < 0)
|
||||
dow += DAYSPERWEEK;
|
||||
int i;
|
||||
bool janfeb = rulep->r_mon <= 2;
|
||||
int month = (rulep->r_mon
|
||||
+ (janfeb ? MONSPERYEAR : 0)); /* 3..14 */
|
||||
int adjustment = (TYPE_SIGNED(time_t) ? 0 : 400) - janfeb;
|
||||
int ay_rem = (year + adjustment) % YEARSPERREPEAT;
|
||||
int y = ay_rem + (ay_rem < 0 ? YEARSPERREPEAT : 0);
|
||||
int dow = (((13 * (month + 1)) / 5
|
||||
+ y + y / 4 - y / 100 + y / 400)
|
||||
% DAYSPERWEEK);
|
||||
|
||||
/*
|
||||
** "dow" is the day-of-week of the first day of the month. Get
|
||||
@@ -1594,33 +1566,24 @@ transtime(const int year, register const struct rule *const rulep,
|
||||
** month.
|
||||
*/
|
||||
d = rulep->r_day - dow;
|
||||
if (d < 0)
|
||||
d += DAYSPERWEEK;
|
||||
for (i = 1; i < rulep->r_week; ++i) {
|
||||
if (d + DAYSPERWEEK >=
|
||||
mon_lengths[leapyear][rulep->r_mon - 1])
|
||||
break;
|
||||
d += DAYSPERWEEK;
|
||||
}
|
||||
d += (rulep->r_week - (0 <= d)) * DAYSPERWEEK;
|
||||
if (mon_lengths[leapyear][rulep->r_mon - 1] <= d)
|
||||
d -= DAYSPERWEEK;
|
||||
|
||||
/*
|
||||
** "d" is the day-of-month (zero-origin) of the day we want.
|
||||
*/
|
||||
value = d * SECSPERDAY;
|
||||
for (i = 0; i < rulep->r_mon - 1; ++i)
|
||||
value += mon_lengths[leapyear][i] * SECSPERDAY;
|
||||
break;
|
||||
|
||||
default: unreachable();
|
||||
d += mon_lengths[leapyear][i];
|
||||
}
|
||||
|
||||
/*
|
||||
** "value" is the year-relative time of 00:00:00 UT on the day in
|
||||
** d is the origin-0 year-relative day in
|
||||
** question. To get the year-relative time of the specified local
|
||||
** time on that day, add the transition time and the current offset
|
||||
** from UT.
|
||||
** from UT to d * SECSPERDAY.
|
||||
*/
|
||||
return value + rulep->r_time + offset;
|
||||
return d * SECSPERDAY + rulep->r_time + offset;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1670,11 +1633,11 @@ tzparse(const char *name, struct state *sp, struct state const *basep)
|
||||
}
|
||||
} else
|
||||
set_leapcount(sp, 0); /* So, we're off a little. */
|
||||
sp->goback = sp->goahead = false;
|
||||
sp->goahead = false;
|
||||
if (*name != '\0') {
|
||||
struct rule start, end;
|
||||
int year, yearbeg, yearlim, timecnt;
|
||||
time_t janfirst;
|
||||
int timecnt;
|
||||
time_t janfirst, repeatbeg, year, yearbeg, yearlim;
|
||||
int_fast32_t janoffset = 0;
|
||||
|
||||
if (*name == '<') {
|
||||
@@ -1712,18 +1675,20 @@ tzparse(const char *name, struct state *sp, struct state const *basep)
|
||||
if (!name || *name)
|
||||
return false;
|
||||
sp->typecnt = 2; /* standard time and DST */
|
||||
/*
|
||||
** Two transitions per year, from EPOCH_YEAR forward.
|
||||
*/
|
||||
|
||||
/* Two transitions per year, from atlo forward, and going on
|
||||
for years_of_observations past max(atlo, leaplo). */
|
||||
init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
|
||||
init_ttinfo(&sp->ttis[1], -dstoffset, true, stdlen + 1);
|
||||
timecnt = 0;
|
||||
janfirst = 0;
|
||||
yearbeg = EPOCH_YEAR;
|
||||
repeatbeg = (atlo / SECSPERREPEAT
|
||||
+ (atlo < 0 && 0 < atlo % SECSPERREPEAT));
|
||||
yearbeg = repeatbeg * YEARSPERREPEAT + EPOCH_YEAR;
|
||||
janfirst = repeatbeg * SECSPERREPEAT;
|
||||
|
||||
do {
|
||||
int_fast32_t yearsecs
|
||||
= year_lengths[isleap(yearbeg - 1)] * SECSPERDAY;
|
||||
= year_days(yearbeg - 1) * SECSPERDAY;
|
||||
time_t janfirst1 = janfirst;
|
||||
yearbeg--;
|
||||
if (increment_overflow_time(&janfirst1, -yearsecs)) {
|
||||
@@ -1731,30 +1696,25 @@ tzparse(const char *name, struct state *sp, struct state const *basep)
|
||||
break;
|
||||
}
|
||||
janfirst = janfirst1;
|
||||
} while (atlo < janfirst
|
||||
&& EPOCH_YEAR - YEARSPERREPEAT / 2 < yearbeg);
|
||||
} while (atlo < janfirst);
|
||||
|
||||
while (true) {
|
||||
int_fast32_t yearsecs
|
||||
= year_lengths[isleap(yearbeg)] * SECSPERDAY;
|
||||
int yearbeg1 = yearbeg;
|
||||
= year_days(yearbeg) * SECSPERDAY;
|
||||
time_t janfirst1 = janfirst;
|
||||
if (increment_overflow_time(&janfirst1, yearsecs)
|
||||
|| increment_overflow(&yearbeg1, 1)
|
||||
|| atlo <= janfirst1)
|
||||
break;
|
||||
yearbeg = yearbeg1;
|
||||
yearbeg++;
|
||||
janfirst = janfirst1;
|
||||
}
|
||||
|
||||
yearlim = yearbeg;
|
||||
if (increment_overflow(&yearlim, years_of_observations))
|
||||
yearlim = INT_MAX;
|
||||
yearlim = yearbeg + years_of_observations;
|
||||
for (year = yearbeg; year < yearlim; year++) {
|
||||
int_fast32_t
|
||||
starttime = transtime(year, &start, stdoffset),
|
||||
endtime = transtime(year, &end, dstoffset),
|
||||
yearsecs = year_lengths[isleap(year)] * SECSPERDAY;
|
||||
yearsecs = year_days(year) * SECSPERDAY;
|
||||
bool reversed = endtime < starttime;
|
||||
if (reversed) {
|
||||
int_fast32_t swap = starttime;
|
||||
@@ -1764,24 +1724,25 @@ tzparse(const char *name, struct state *sp, struct state const *basep)
|
||||
if (reversed
|
||||
|| (starttime < endtime
|
||||
&& endtime - starttime < yearsecs)) {
|
||||
if (TZ_MAX_TIMES - 2 < timecnt)
|
||||
break;
|
||||
sp->ats[timecnt] = janfirst;
|
||||
if (! increment_overflow_time(&sp->ats[timecnt],
|
||||
janoffset + starttime)
|
||||
&& atlo <= sp->ats[timecnt])
|
||||
time_t at_added = TIME_T_MAX;
|
||||
time_t at = janfirst;
|
||||
if (! increment_overflow_time(&at, janoffset + starttime)
|
||||
&& atlo <= at) {
|
||||
if (TZ_MAX_TIMES <= timecnt)
|
||||
return false;
|
||||
sp->ats[timecnt] = at_added = at;
|
||||
sp->types[timecnt++] = !reversed;
|
||||
sp->ats[timecnt] = janfirst;
|
||||
if (! increment_overflow_time(&sp->ats[timecnt],
|
||||
janoffset + endtime)
|
||||
&& atlo <= sp->ats[timecnt]) {
|
||||
}
|
||||
at = janfirst;
|
||||
if (! increment_overflow_time(&at, janoffset + endtime)
|
||||
&& atlo <= at) {
|
||||
if (TZ_MAX_TIMES <= timecnt)
|
||||
return false;
|
||||
sp->ats[timecnt] = at_added = at;
|
||||
sp->types[timecnt++] = reversed;
|
||||
}
|
||||
}
|
||||
if (endtime < leaplo) {
|
||||
yearlim = year;
|
||||
if (increment_overflow(&yearlim, years_of_observations))
|
||||
yearlim = INT_MAX;
|
||||
if (at_added < leaplo)
|
||||
yearlim = year + years_of_observations;
|
||||
}
|
||||
if (increment_overflow_time(&janfirst, janoffset + yearsecs))
|
||||
break;
|
||||
@@ -1792,7 +1753,7 @@ tzparse(const char *name, struct state *sp, struct state const *basep)
|
||||
sp->ttis[0] = sp->ttis[1];
|
||||
sp->typecnt = 1; /* Perpetual DST. */
|
||||
} else if (years_of_observations <= year - yearbeg)
|
||||
sp->goback = sp->goahead = true;
|
||||
sp->goahead = true;
|
||||
} else {
|
||||
dstlen = 0;
|
||||
sp->typecnt = 1; /* only standard time */
|
||||
@@ -1849,7 +1810,7 @@ zoneinit(struct state *sp, char const *name, char tzloadflags)
|
||||
sp->timecnt = 0;
|
||||
sp->typecnt = 0;
|
||||
sp->charcnt = 0;
|
||||
sp->goback = sp->goahead = false;
|
||||
sp->goahead = false;
|
||||
init_ttinfo(&sp->ttis[0], 0, false, 0);
|
||||
strcpy(sp->chars, utc);
|
||||
return 0;
|
||||
@@ -2069,12 +2030,15 @@ tzfree(timezone_t sp)
|
||||
** since in that case tzset should have already done this step correctly.
|
||||
** SETNAME's type is int_fast32_t for compatibility with gmtsub,
|
||||
** but it is actually a boolean and its value should be 0 or 1.
|
||||
**
|
||||
** If LTM_YEAR, store the resulting year-1900 into *LTM_YEAR rather
|
||||
** than into the default TMP->tm_year; this prevents year overflow.
|
||||
*/
|
||||
|
||||
/*ARGSUSED*/
|
||||
static struct tm *
|
||||
localsub(struct state const *sp, time_t const *timep, int_fast32_t setname,
|
||||
struct tm *const tmp)
|
||||
struct tm *tmp, time_t *ltm_year)
|
||||
{
|
||||
register const struct ttinfo * ttisp;
|
||||
register int i;
|
||||
@@ -2083,52 +2047,39 @@ localsub(struct state const *sp, time_t const *timep, int_fast32_t setname,
|
||||
|
||||
if (sp == NULL) {
|
||||
/* Don't bother to set tzname etc.; tzset has already done it. */
|
||||
return gmtsub(gmtptr, timep, 0, tmp);
|
||||
return gmtsub(gmtptr, timep, 0, tmp, ltm_year);
|
||||
}
|
||||
if ((sp->goback && t < sp->ats[0]) ||
|
||||
(sp->goahead && t > sp->ats[sp->timecnt - 1])) {
|
||||
time_t newt;
|
||||
register time_t seconds;
|
||||
register time_t years;
|
||||
if (sp->goahead && sp->ats[sp->timecnt - 1] < t) {
|
||||
/* Avoid integer overflow when time_t is signed, by
|
||||
using secs_div_2 twice; the full value would
|
||||
always be even, so halving does not round. */
|
||||
time_t
|
||||
tlo = sp->ats[sp->timecnt - 1],
|
||||
diffyears = ((t / 2 - tlo / 2
|
||||
+ ((t % 2 - tlo % 2 + 2) / 2 - 1))
|
||||
/ (SECSPERREPEAT / 2)
|
||||
* YEARSPERREPEAT),
|
||||
years = diffyears + YEARSPERREPEAT,
|
||||
secs_div_2 = (diffyears * (AVGSECSPERYEAR / 2)
|
||||
+ SECSPERREPEAT / 2),
|
||||
newt = t - secs_div_2 - secs_div_2,
|
||||
ryear;
|
||||
|
||||
if (t < sp->ats[0])
|
||||
seconds = sp->ats[0] - t;
|
||||
else seconds = t - sp->ats[sp->timecnt - 1];
|
||||
--seconds;
|
||||
|
||||
/* Beware integer overflow, as SECONDS might
|
||||
be close to the maximum time_t. */
|
||||
years = seconds / SECSPERREPEAT * YEARSPERREPEAT;
|
||||
seconds = years * AVGSECSPERYEAR;
|
||||
years += YEARSPERREPEAT;
|
||||
if (t < sp->ats[0])
|
||||
newt = t + seconds + SECSPERREPEAT;
|
||||
else
|
||||
newt = t - seconds - SECSPERREPEAT;
|
||||
|
||||
if (newt < sp->ats[0] ||
|
||||
newt > sp->ats[sp->timecnt - 1])
|
||||
return NULL; /* "cannot happen" */
|
||||
result = localsub(sp, &newt, setname, tmp);
|
||||
result = localsub(sp, &newt, setname, tmp, &ryear);
|
||||
if (result) {
|
||||
# if defined ckd_add && defined ckd_sub
|
||||
if (t < sp->ats[0]
|
||||
? ckd_sub(&result->tm_year,
|
||||
result->tm_year, years)
|
||||
: ckd_add(&result->tm_year,
|
||||
result->tm_year, years))
|
||||
if (ltm_year)
|
||||
*ltm_year = ryear + years;
|
||||
else {
|
||||
# ifdef ckd_add
|
||||
if (ckd_add(&result->tm_year, ryear, years))
|
||||
return NULL;
|
||||
# else
|
||||
register int_fast64_t newy;
|
||||
|
||||
newy = result->tm_year;
|
||||
if (t < sp->ats[0])
|
||||
newy -= years;
|
||||
else newy += years;
|
||||
time_t newy = ryear + years;
|
||||
if (! (INT_MIN <= newy && newy <= INT_MAX))
|
||||
return NULL;
|
||||
result->tm_year = newy;
|
||||
# endif
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -2152,9 +2103,9 @@ localsub(struct state const *sp, time_t const *timep, int_fast32_t setname,
|
||||
** To get (wrong) behavior that's compatible with System V Release 2.0
|
||||
** you'd replace the statement below with
|
||||
** t += ttisp->tt_utoff;
|
||||
** timesub(&t, 0, sp, tmp);
|
||||
** timesub(&t, 0, sp, tmp, ltm_year);
|
||||
*/
|
||||
result = timesub(&t, ttisp->tt_utoff, sp, tmp);
|
||||
result = timesub(&t, ttisp->tt_utoff, sp, tmp, ltm_year);
|
||||
if (result) {
|
||||
result->tm_isdst = ttisp->tt_isdst;
|
||||
# ifdef TM_ZONE
|
||||
@@ -2204,7 +2155,7 @@ struct tm *
|
||||
localtime_rz(struct state *restrict sp, time_t const *restrict timep,
|
||||
struct tm *restrict tmp)
|
||||
{
|
||||
return localsub(sp, timep, 0, tmp);
|
||||
return localsub(sp, timep, 0, tmp, NULL);
|
||||
}
|
||||
# endif
|
||||
|
||||
@@ -2219,7 +2170,7 @@ localtime_tzset(time_t const *timep, struct tm *tmp, bool setname)
|
||||
}
|
||||
if (0 <= tz_change_interval || setname || !lcl_is_set)
|
||||
tzset_unlocked(!err, false, now);
|
||||
tmp = localsub(lclptr, timep, setname, tmp);
|
||||
tmp = localsub(lclptr, timep, setname, tmp, NULL);
|
||||
unlock(!err);
|
||||
return tmp;
|
||||
}
|
||||
@@ -2246,11 +2197,11 @@ localtime_r(const time_t *restrict timep, struct tm *restrict tmp)
|
||||
|
||||
static struct tm *
|
||||
gmtsub(ATTRIBUTE_MAYBE_UNUSED struct state const *sp, time_t const *timep,
|
||||
int_fast32_t offset, struct tm *tmp)
|
||||
int_fast32_t offset, struct tm *tmp, time_t *ltm_year)
|
||||
{
|
||||
register struct tm * result;
|
||||
|
||||
result = timesub(timep, offset, gmtptr, tmp);
|
||||
result = timesub(timep, offset, gmtptr, tmp, ltm_year);
|
||||
#ifdef TM_ZONE
|
||||
/*
|
||||
** Could get fancy here and deliver something such as
|
||||
@@ -2273,7 +2224,7 @@ struct tm *
|
||||
gmtime_r(time_t const *restrict timep, struct tm *restrict tmp)
|
||||
{
|
||||
gmtcheck();
|
||||
return gmtsub(gmtptr, timep, 0, tmp);
|
||||
return gmtsub(gmtptr, timep, 0, tmp, NULL);
|
||||
}
|
||||
|
||||
struct tm *
|
||||
@@ -2294,7 +2245,7 @@ struct tm *
|
||||
offtime_r(time_t const *restrict timep, long offset, struct tm *restrict tmp)
|
||||
{
|
||||
gmtcheck();
|
||||
return gmtsub(gmtptr, timep, offset, tmp);
|
||||
return gmtsub(gmtptr, timep, offset, tmp, NULL);
|
||||
}
|
||||
|
||||
struct tm *
|
||||
@@ -2330,7 +2281,7 @@ leaps_thru_end_of(time_t y)
|
||||
|
||||
static struct tm *
|
||||
timesub(const time_t *timep, int_fast32_t offset,
|
||||
const struct state *sp, struct tm *tmp)
|
||||
const struct state *sp, struct tm *tmp, time_t *ltm_year)
|
||||
{
|
||||
register time_t tdays;
|
||||
register const int * ip;
|
||||
@@ -2380,7 +2331,7 @@ timesub(const time_t *timep, int_fast32_t offset,
|
||||
idays += dayoff % DAYSPERREPEAT + 2 * DAYSPERREPEAT;
|
||||
idays %= DAYSPERREPEAT;
|
||||
/* Increase Y and decrease IDAYS until IDAYS is in range for Y. */
|
||||
while (year_lengths[isleap(y)] <= idays) {
|
||||
while (year_days(y) <= idays) {
|
||||
int tdelta = idays / DAYSPERLYEAR;
|
||||
int_fast32_t ydelta = tdelta + !tdelta;
|
||||
time_t newy = y + ydelta;
|
||||
@@ -2392,29 +2343,34 @@ timesub(const time_t *timep, int_fast32_t offset,
|
||||
y = newy;
|
||||
}
|
||||
|
||||
if (ltm_year) {
|
||||
*ltm_year = y - TM_YEAR_BASE;
|
||||
} else {
|
||||
#ifdef ckd_add
|
||||
if (ckd_add(&tmp->tm_year, y, -TM_YEAR_BASE)) {
|
||||
errno = EOVERFLOW;
|
||||
return NULL;
|
||||
}
|
||||
if (ckd_add(&tmp->tm_year, y, -TM_YEAR_BASE)) {
|
||||
errno = EOVERFLOW;
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
if (!TYPE_SIGNED(time_t) && y < TM_YEAR_BASE) {
|
||||
int signed_y = y;
|
||||
tmp->tm_year = signed_y - TM_YEAR_BASE;
|
||||
} else if ((!TYPE_SIGNED(time_t) || INT_MIN + TM_YEAR_BASE <= y)
|
||||
&& y - TM_YEAR_BASE <= INT_MAX)
|
||||
tmp->tm_year = y - TM_YEAR_BASE;
|
||||
else {
|
||||
errno = EOVERFLOW;
|
||||
return NULL;
|
||||
}
|
||||
if (!TYPE_SIGNED(time_t) && y < TM_YEAR_BASE) {
|
||||
int signed_y = y;
|
||||
tmp->tm_year = signed_y - TM_YEAR_BASE;
|
||||
} else if ((!TYPE_SIGNED(time_t) || INT_MIN + TM_YEAR_BASE <= y)
|
||||
&& y - TM_YEAR_BASE <= INT_MAX)
|
||||
tmp->tm_year = y - TM_YEAR_BASE;
|
||||
else {
|
||||
errno = EOVERFLOW;
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
tmp->tm_yday = idays;
|
||||
/*
|
||||
** The "extra" mods below avoid overflow problems.
|
||||
*/
|
||||
tmp->tm_wday = (TM_WDAY_BASE
|
||||
+ ((tmp->tm_year % DAYSPERWEEK)
|
||||
+ ((y % DAYSPERWEEK - TM_YEAR_BASE % DAYSPERWEEK)
|
||||
% DAYSPERWEEK
|
||||
* (DAYSPERNYEAR % DAYSPERWEEK))
|
||||
+ leaps_thru_end_of(y - 1)
|
||||
- leaps_thru_end_of(TM_YEAR_BASE - 1)
|
||||
@@ -2459,27 +2415,6 @@ timesub(const time_t *timep, int_fast32_t offset,
|
||||
** Normalize logic courtesy Paul Eggert.
|
||||
*/
|
||||
|
||||
static bool
|
||||
increment_overflow(int *ip, int j)
|
||||
{
|
||||
#ifdef ckd_add
|
||||
return ckd_add(ip, *ip, j);
|
||||
#else
|
||||
register int const i = *ip;
|
||||
|
||||
/*
|
||||
** If i >= 0 there can only be overflow if i + j > INT_MAX
|
||||
** or if j > INT_MAX - i; given i >= 0, INT_MAX - i cannot overflow.
|
||||
** If i < 0 there can only be overflow if i + j < INT_MIN
|
||||
** or if j < INT_MIN - i; given i < 0, INT_MIN - i cannot overflow.
|
||||
*/
|
||||
if ((i >= 0) ? (j > INT_MAX - i) : (j < INT_MIN - i))
|
||||
return true;
|
||||
*ip += j;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool
|
||||
increment_overflow_64(int *ip, int_fast64_t j)
|
||||
{
|
||||
@@ -2588,7 +2523,7 @@ mktmcpy(struct tm *dest, struct tm const *src)
|
||||
static time_t
|
||||
time2sub(struct tm *const tmp,
|
||||
struct tm *funcp(struct state const *, time_t const *,
|
||||
int_fast32_t, struct tm *),
|
||||
int_fast32_t, struct tm *, time_t *),
|
||||
struct state const *sp,
|
||||
const int_fast32_t offset,
|
||||
bool *okayp,
|
||||
@@ -2648,12 +2583,12 @@ time2sub(struct tm *const tmp,
|
||||
|
||||
while (mday <= 0) {
|
||||
iinntt li = y - (yourtm.tm_mon <= 1);
|
||||
mday += year_lengths[isleap(li)];
|
||||
mday += year_days(li);
|
||||
y--;
|
||||
}
|
||||
while (DAYSPERLYEAR < mday) {
|
||||
iinntt li = y + (1 < yourtm.tm_mon);
|
||||
mday -= year_lengths[isleap(li)];
|
||||
mday -= year_days(li);
|
||||
y++;
|
||||
}
|
||||
yourtm.tm_mday = mday;
|
||||
@@ -2705,7 +2640,7 @@ time2sub(struct tm *const tmp,
|
||||
t = lo;
|
||||
else if (t > hi)
|
||||
t = hi;
|
||||
if (! funcp(sp, &t, offset, &mytm)) {
|
||||
if (! funcp(sp, &t, offset, &mytm, NULL)) {
|
||||
/*
|
||||
** Assume that t is too extreme to be represented in
|
||||
** a struct tm; arrange things so that it is less
|
||||
@@ -2761,7 +2696,7 @@ time2sub(struct tm *const tmp,
|
||||
# endif
|
||||
if (!v && !increment_overflow_time_64(&altt, offdiff)) {
|
||||
struct tm alttm;
|
||||
if (funcp(sp, &altt, offset, &alttm)
|
||||
if (funcp(sp, &altt, offset, &alttm, NULL)
|
||||
&& alttm.tm_isdst == mytm.tm_isdst
|
||||
&& alttm.TM_GMTOFF == yourtm.TM_GMTOFF
|
||||
&& tmcomp(&alttm, &yourtm) == 0) {
|
||||
@@ -2795,7 +2730,7 @@ time2sub(struct tm *const tmp,
|
||||
utoff_diff(sp->ttis[j].tt_utoff,
|
||||
sp->ttis[i].tt_utoff)))
|
||||
continue;
|
||||
if (! funcp(sp, &newt, offset, &mytm))
|
||||
if (! funcp(sp, &newt, offset, &mytm, NULL))
|
||||
continue;
|
||||
if (tmcomp(&mytm, &yourtm) != 0)
|
||||
continue;
|
||||
@@ -2813,7 +2748,7 @@ time2sub(struct tm *const tmp,
|
||||
label:
|
||||
if (increment_overflow_time_iinntt(&t, saved_seconds))
|
||||
return WRONG;
|
||||
if (funcp(sp, &t, offset, tmp))
|
||||
if (funcp(sp, &t, offset, tmp, NULL))
|
||||
*okayp = true;
|
||||
return t;
|
||||
}
|
||||
@@ -2821,7 +2756,7 @@ label:
|
||||
static time_t
|
||||
time2(struct tm * const tmp,
|
||||
struct tm *funcp(struct state const *, time_t const *,
|
||||
int_fast32_t, struct tm *),
|
||||
int_fast32_t, struct tm *, time_t *),
|
||||
struct state const *sp,
|
||||
const int_fast32_t offset,
|
||||
bool *okayp)
|
||||
@@ -2840,7 +2775,7 @@ time2(struct tm * const tmp,
|
||||
static time_t
|
||||
time1(struct tm *const tmp,
|
||||
struct tm *funcp(struct state const *, time_t const *,
|
||||
int_fast32_t, struct tm *),
|
||||
int_fast32_t, struct tm *, time_t *),
|
||||
struct state const *sp,
|
||||
const int_fast32_t offset)
|
||||
{
|
||||
|
||||
@@ -255,6 +255,9 @@ strnlen (char const *s, size_t maxlen)
|
||||
#ifndef ENOMEM
|
||||
# define ENOMEM EINVAL
|
||||
#endif
|
||||
#ifndef ENOSYS
|
||||
# define ENOSYS EINVAL
|
||||
#endif
|
||||
#ifndef ENOTCAPABLE
|
||||
# define ENOTCAPABLE EINVAL
|
||||
#endif
|
||||
@@ -264,6 +267,9 @@ strnlen (char const *s, size_t maxlen)
|
||||
#ifndef EOVERFLOW
|
||||
# define EOVERFLOW EINVAL
|
||||
#endif
|
||||
#ifndef EPERM
|
||||
# define EPERM EINVAL
|
||||
#endif
|
||||
|
||||
#if HAVE_GETTEXT
|
||||
# include <libintl.h>
|
||||
@@ -305,6 +311,7 @@ extern int optind;
|
||||
|
||||
#ifndef HAVE_ISSETUGID
|
||||
# if (defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ \
|
||||
|| defined __DragonFly__ \
|
||||
|| (defined __linux__ && !defined __GLIBC__) /* Android, musl, etc. */ \
|
||||
|| (defined __APPLE__ && defined __MACH__) || defined __sun)
|
||||
# define HAVE_ISSETUGID 1
|
||||
@@ -813,6 +820,7 @@ void tzset(void);
|
||||
# if (202311 <= __STDC_VERSION__ \
|
||||
|| defined __GLIBC__ || defined __tm_zone /* musl */ \
|
||||
|| defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ \
|
||||
|| defined __DragonFly__ || defined __HAIKU__ \
|
||||
|| (defined __APPLE__ && defined __MACH__))
|
||||
# define HAVE_DECL_TIMEGM 1
|
||||
# else
|
||||
@@ -841,7 +849,8 @@ extern char **environ;
|
||||
|
||||
#ifndef HAVE_MEMPCPY
|
||||
# if (defined mempcpy \
|
||||
|| defined __FreeBSD__ || defined __NetBSD__ || defined __linux__)
|
||||
|| defined __FreeBSD__ || defined __NetBSD__ || defined __DragonFly__ \
|
||||
|| defined __linux__)
|
||||
# define HAVE_MEMPCPY 1
|
||||
# else
|
||||
# define HAVE_MEMPCPY 0
|
||||
@@ -906,6 +915,7 @@ time_t posix2time(time_t);
|
||||
|| defined __GLIBC__ \
|
||||
|| defined __tm_zone /* musl */ \
|
||||
|| defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ \
|
||||
|| defined __DragonFly__ || defined __HAIKU__ \
|
||||
|| (defined __APPLE__ && defined __MACH__))
|
||||
# if !defined TM_GMTOFF && !defined NO_TM_GMTOFF
|
||||
# define TM_GMTOFF tm_gmtoff
|
||||
@@ -1170,6 +1180,7 @@ enum {
|
||||
};
|
||||
|
||||
#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
|
||||
#define year_days(y) (DAYSPERNYEAR + isleap(y))
|
||||
|
||||
/*
|
||||
** Since everything in isleap is modulo 400 (or a factor of 400), we know that
|
||||
@@ -1183,6 +1194,6 @@ enum {
|
||||
** We use this to avoid addition overflow problems.
|
||||
*/
|
||||
|
||||
#define isleap_sum(a, b) isleap((a) % 400 + (b) % 400)
|
||||
#define year_sum_days(a, b) (DAYSPERNYEAR + isleap((a) % 400 + (b) % 400))
|
||||
|
||||
#endif /* !defined PRIVATE_H */
|
||||
+3
-6
@@ -464,9 +464,7 @@ label:
|
||||
int bot;
|
||||
int top;
|
||||
|
||||
len = isleap_sum(year, base) ?
|
||||
DAYSPERLYEAR :
|
||||
DAYSPERNYEAR;
|
||||
len = year_sum_days(year, base);
|
||||
/*
|
||||
** What yday (-3 ... 3) does
|
||||
** the ISO year begin on?
|
||||
@@ -493,9 +491,8 @@ label:
|
||||
break;
|
||||
}
|
||||
--base;
|
||||
yday += isleap_sum(year, base) ?
|
||||
DAYSPERLYEAR :
|
||||
DAYSPERNYEAR;
|
||||
yday += year_sum_days(year,
|
||||
base);
|
||||
}
|
||||
#ifdef XPG4_1994_04_09
|
||||
if ((w == 52 &&
|
||||
|
||||
+32
-31
@@ -12,6 +12,7 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<main>
|
||||
<h1>Theory and pragmatics of the <code><abbr>tz</abbr></code> code and data</h1>
|
||||
<nav>
|
||||
<ul>
|
||||
@@ -26,10 +27,10 @@
|
||||
<li><a href="#leapsec">Leap seconds</a></li>
|
||||
<li><a href="#calendar">Calendrical issues</a></li>
|
||||
<li><a href="#planets">Time and time zones off earth</a></li>
|
||||
<li><a href="#see-also">See also</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<section>
|
||||
<h2 id="scope">Scope of the <code><abbr>tz</abbr></code> database</h2>
|
||||
<p>
|
||||
The <a
|
||||
@@ -112,9 +113,6 @@ It does not always make sense to talk about a timezone’s
|
||||
“base offset”, which is not necessarily a single number.
|
||||
</p>
|
||||
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 id="naming">Timezone identifiers</h2>
|
||||
<p>
|
||||
Each timezone has a name that uniquely identifies the timezone.
|
||||
@@ -345,8 +343,7 @@ These legacy names are mostly defined in the file
|
||||
"<code>etcetera</code>".
|
||||
Also, the file "<code>backward</code>" defines the legacy names
|
||||
<code>Etc/GMT0</code>, <code>Etc/GMT-0</code>, <code>Etc/GMT+0</code>,
|
||||
<code>GMT0</code>, <code>GMT-0</code> and <code>GMT+0</code>,
|
||||
and the file "<code>northamerica</code>" defines the legacy names
|
||||
<code>GMT0</code>, <code>GMT-0</code>, <code>GMT+0</code>,
|
||||
<code>EST5EDT</code>, <code>CST6CDT</code>,
|
||||
<code>MST7MDT</code>, and <code>PST8PDT</code>.
|
||||
</li>
|
||||
@@ -387,11 +384,11 @@ and <code>zone.tab</code>.
|
||||
|
||||
<p>
|
||||
The database defines each timezone name to be a zone, or a link to a zone.
|
||||
The source file <code>backward</code> defines links for backward
|
||||
compatibility; it does not define zones.
|
||||
The source file <code>backward</code> defines links
|
||||
and a few zones for backward compatibility.
|
||||
Although <code>backward</code> was originally designed to be optional,
|
||||
nowadays distributions typically use it
|
||||
and no great weight should be attached to whether a link
|
||||
and no great weight should be attached to whether a link or zone
|
||||
is defined in <code>backward</code> or in some other file.
|
||||
The source file <code>etcetera</code> defines names that may be useful
|
||||
on platforms that do not support proleptic <code>TZ</code> strings
|
||||
@@ -404,9 +401,7 @@ second information on platforms that support leap seconds.
|
||||
Another <code>etcetera</code> name, <code>GMT</code>,
|
||||
is used by older code releases.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 id="abbreviations">Time zone abbreviations</h2>
|
||||
<p>
|
||||
When this package is installed, it generates time zone abbreviations
|
||||
@@ -610,9 +605,7 @@ Israel.
|
||||
To avoid ambiguity, use numeric <abbr>UT</abbr> offsets like
|
||||
<code>-</code>0600 instead of time zone abbreviations like CST.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 id="accuracy">Accuracy of the <code><abbr>tz</abbr></code> database</h2>
|
||||
<p>
|
||||
The <code><abbr>tz</abbr></code> database is not authoritative, and it
|
||||
@@ -876,9 +869,7 @@ merely because two locations
|
||||
differ in <abbr>LMT</abbr> or transitioned to standard time at
|
||||
different dates.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 id="functions">Time and date functions</h2>
|
||||
<p>
|
||||
The <code><abbr>tz</abbr></code> code contains time and date functions
|
||||
@@ -1284,9 +1275,7 @@ The vestigial <abbr>API</abbr>s are:
|
||||
much the better.
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 id="stability">Interface stability</h2>
|
||||
<p>
|
||||
The <code><abbr>tz</abbr></code> code and data supply the following interfaces:
|
||||
@@ -1353,9 +1342,7 @@ than Bangkok by putting <samp>Asia/Bangkok</samp> in the event’s record,
|
||||
the application should be robust in the presence of timezone splits
|
||||
between now and the future time.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 id="leapsec">Leap seconds</h2>
|
||||
<p>
|
||||
Leap seconds were introduced in 1972 to accommodate the
|
||||
@@ -1430,9 +1417,7 @@ Alternatively, you can install just one set of <abbr>TZif</abbr> files
|
||||
in the first place; see the <code>REDO</code> variable in this package’s
|
||||
<a href="https://en.wikipedia.org/wiki/Makefile">makefile</a>.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 id="calendar">Calendrical issues</h2>
|
||||
<p>
|
||||
Calendrical issues are a bit out of scope for a time zone database,
|
||||
@@ -1446,22 +1431,30 @@ Other information and sources are given in the file "<code>calendars</code>"
|
||||
in the <code><abbr>tz</abbr></code> distribution.
|
||||
They sometimes disagree.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 id="planets">Time and time zones off Earth</h2>
|
||||
<p>
|
||||
The European Space Agency is <a
|
||||
href="https://www.esa.int/Applications/Satellite_navigation/Telling_time_on_the_Moon">considering</a>
|
||||
the establishment of a reference timescale for the Moon, which has
|
||||
Efforts are underway to establish a reference timescale for the Moon, which has
|
||||
days roughly equivalent to 29.5 Earth days, and where relativistic
|
||||
effects cause clocks to tick slightly faster than on Earth.
|
||||
Also, <abbr title="National Aeronautics and Space Administration">NASA</abbr>
|
||||
has been <a
|
||||
The European Space Agency <a
|
||||
href="https://www.esa.int/Applications/Satellite_navigation/Telling_time_on_the_Moon">began
|
||||
considering</a> the problem in 2023, and in 2024
|
||||
<abbr title="National Aeronautics and Space Administration">NASA</abbr>
|
||||
was <a
|
||||
href="https://bidenwhitehouse.archives.gov/wp-content/uploads/2024/04/Celestial-Time-Standardization-Policy.pdf">ordered</a>
|
||||
to consider the establishment of Coordinated Lunar Time (<abbr>LTC</abbr>).
|
||||
It is not yet known whether the US and European efforts will result in
|
||||
multiple timescales on the Moon.
|
||||
In 2025 a team at China’s
|
||||
<a href="https://en.wikipedia.org/wiki/Purple_Mountain_Observatory">Purple
|
||||
Mountain Observatory</a> published
|
||||
<a href="https://doi.org/10.1051/0004-6361/202557345">Lunar Time Ephemeris
|
||||
440</a>, the first formal proposal for a standard
|
||||
for Temps Coordonné Lunaire (<abbr>TCL</abbr>).
|
||||
A <a href="https://www.bipm.org/documents/20126/284836054/CGPM-2026-Draft-Resolutions.pdf">draft
|
||||
resolution of the 13–15 October 2026 General Conference on Weights
|
||||
and Measures</a> recommends that the <a href="https://www.bipm.org/en/">Bureau
|
||||
International des Poids et Mesures</a> collaborate with space agencies
|
||||
and other organizations on this matter.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -1583,7 +1576,15 @@ Sources for time on other planets:
|
||||
(2016-01-20).
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<aside>
|
||||
<h2 id="see-also">See also</h2>
|
||||
<ul>
|
||||
<li><a href="tz-link.html">Time zone and daylight saving time data</a></li>
|
||||
<li><a href="tz-art.html">Time and the arts</a></li>
|
||||
</ul>
|
||||
</aside>
|
||||
|
||||
<footer>
|
||||
<hr>
|
||||
|
||||
+11
-3
@@ -9,6 +9,7 @@ ul {padding-left: 1.3rem;}
|
||||
<title>Time and the arts</title>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<h1>Time and the arts</h1>
|
||||
<h2>Documentaries</h2>
|
||||
<ul>
|
||||
@@ -466,8 +467,10 @@ Unlike minimalism, it does not assume that the listener has plenty of time.
|
||||
<li>
|
||||
The webcomic <em>xkcd</em> has the strips
|
||||
“<a href="https://xkcd.com/673/">The Sun</a>” (2009-12-09),
|
||||
“<a href="https://xkcd.com/1655/">Doomsday Clock</a>” (2016-03-14) and
|
||||
“<a href="https://xkcd.com/1655/">Doomsday Clock</a>” (2016-03-14),
|
||||
“<a href="https://xkcd.com/2549/">Edge Cake</a>” (2021-12-01),
|
||||
“<a href="https://xkcd.com/2867/">DateTime</a>” (2023-12-13),
|
||||
and “<a href="https://xkcd.com/3272/">Time Change</a>” (2026-07-15),
|
||||
along with the panels
|
||||
“<a href="https://xkcd.com/448/">Good Morning</a>” (2008-07-11),
|
||||
“<a href="https://xkcd.com/1017/">Backward in Time</a>” (2012-02-14),
|
||||
@@ -482,8 +485,7 @@ along with the panels
|
||||
“<a href="https://xkcd.com/2266/">Leap Smearing</a>” (2020-02-10),
|
||||
“<a href="https://xkcd.com/2594/">Consensus Time</a>” (2022-03-16),
|
||||
“<a href="https://xkcd.com/2846/">Daylight Saving Choice</a>” (2023-10-25),
|
||||
“<a href="https://xkcd.com/2854/">Date Line</a>” (2023-11-13),
|
||||
and “<a href="https://xkcd.com/2867/">DateTime</a>” (2023-12-13).
|
||||
and “<a href="https://xkcd.com/2854/">Date Line</a>” (2023-11-13).
|
||||
The related book <em>What If?</em> has an entry
|
||||
“<a href="https://what-if.xkcd.com/26/">Leap Seconds</a>” (2012-12-31).
|
||||
</li>
|
||||
@@ -611,10 +613,16 @@ but maybe in your time zone I haven’t finished yet. So stay tuned!”
|
||||
(Goldie Hawn, <em>Rowan & Martin’s Laugh-In</em> No. 65, 1970-03-09)
|
||||
</li>
|
||||
</ul>
|
||||
</main>
|
||||
|
||||
<aside>
|
||||
<h2>See also</h2>
|
||||
<ul>
|
||||
<li><a href="tz-link.html">Time zone and daylight saving time data</a></li>
|
||||
<li><a href="theory.html">Theory and pragmatics of the
|
||||
<code><abbr>tz</abbr></code> code and data</a></li>
|
||||
</ul>
|
||||
</aside>
|
||||
|
||||
<footer>
|
||||
<hr>
|
||||
|
||||
+11
-7
@@ -15,6 +15,7 @@ ul {padding-left: 1.3rem;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<h1>How to Read the <a href="https://en.wikipedia.org/wiki/Tz_database">tz
|
||||
Database</a> Source Files</h1>
|
||||
<h2>by Bill Seymour</h2>
|
||||
@@ -415,17 +416,19 @@ Line. For example:</p>
|
||||
|
||||
<pre>
|
||||
#Zone NAME STDOFF RULES FORMAT [UNTIL]
|
||||
Zone America/Juneau 15:02:19 - LMT 1867 Oct 18
|
||||
Zone America/Juneau 15:02:19 - LMT 1867 Oct 19 0:31:13u
|
||||
-8:57:41 - LMT ...
|
||||
</pre>
|
||||
|
||||
<p>When Alaska was purchased from Russia in 1867, the Date Line moved
|
||||
from the Alaska/Canada border to the Bering Strait; and the time in
|
||||
Alaska was then 24 hours earlier than it had
|
||||
been. <code><aside></code>(6 October in the Julian calendar,
|
||||
which Russia was still using then for religious reasons, was followed
|
||||
by <i>a second instance of the same day with a different name</i>, 18
|
||||
October in the Gregorian calendar. Isn’t civil time
|
||||
been. <code><aside></code>(This also means that, although the sun had set
|
||||
on Friday 6 October and risen on Saturday 7 October in the Julian calendar,
|
||||
which Russia was still using then for religious reasons, upon the transfer
|
||||
Saturday afternoon became Friday afternoon, and then the sun set and rose once
|
||||
more on <i>second instances of the same days with different names</i>,
|
||||
Friday 18 and Saturday 19 October in the Gregorian calendar. Isn’t civil time
|
||||
wonderful? <code>8-)</code>)<code></aside></code></p>
|
||||
|
||||
<p>The abbreviation, “LMT” stands for “local mean
|
||||
@@ -660,14 +663,15 @@ Zone Pacific/Honolulu -10:31:26 - LMT 1896 Jan 13 12:00
|
||||
</table>
|
||||
|
||||
<p>There will be a short quiz later. <code>8-)</code></p>
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<hr>
|
||||
<address>
|
||||
This web page is in the public domain, so clarified as of
|
||||
2015-10-20 by Bill Seymour.
|
||||
<br>
|
||||
All suggestions and corrections will be welcome; all flames will be amusing.
|
||||
Mail to was at pobox dot com.
|
||||
</address>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
+60
-58
@@ -11,6 +11,7 @@ ul {padding-left: 1.3rem;}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<h1>Time zone and daylight saving time data</h1>
|
||||
<p>
|
||||
<a href="https://en.wikipedia.org/wiki/Time_zone">Time zone</a> and
|
||||
@@ -61,7 +62,6 @@ area.
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<section>
|
||||
<h2 id="tzdb">The <code><abbr title="time zone">tz</abbr></code> database</h2>
|
||||
<p>
|
||||
The <a href="https://en.wikipedia.org/wiki/Public_domain">public-domain</a>
|
||||
@@ -84,6 +84,7 @@ title="Berkeley Software Distribution">BSD</abbr></a>,
|
||||
<a href="https://netbsd.org">Net<abbr>BSD</abbr></a>,
|
||||
<a href="https://www.openbsd.org">Open<abbr>BSD</abbr></a>,
|
||||
<a href="https://www.chromium.org/chromium-os/">ChromiumOS</a>,
|
||||
<a href="https://en.wikipedia.org/wiki/OpenHarmony">OpenHarmony</a>,
|
||||
<a href="https://cygwin.com">Cygwin</a>,
|
||||
<a href="https://mariadb.org">MariaDB</a>,
|
||||
<a href="https://musl.libc.org">musl libc</a>,
|
||||
@@ -133,9 +134,7 @@ Universal Time</a> (<abbr>UTC</abbr>).
|
||||
The database also records when daylight saving time was in use,
|
||||
along with some time zone abbreviations such as <abbr>EST</abbr>
|
||||
for Eastern Standard Time in the <abbr>US</abbr>.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 id="download">Downloading the <code><abbr>tz</abbr></code> database</h2>
|
||||
<p>
|
||||
The following <a
|
||||
@@ -145,15 +144,15 @@ the latest release’s two
|
||||
to a <abbr>GNU</abbr>/Linux or similar host.</p>
|
||||
<pre><code>mkdir tzdb
|
||||
cd tzdb
|
||||
<a href="https://www.gnu.org/software/wget/">wget</a> https://www.iana.org/time-zones/repository/tzcode-latest.tar.gz
|
||||
wget https://www.iana.org/time-zones/repository/tzdata-latest.tar.gz
|
||||
<a href="https://www.gnu.org/software/wget/">wget</a> https://data.iana.org/time-zones/tzcode-latest.tar.gz
|
||||
wget https://data.iana.org/time-zones/tzdata-latest.tar.gz
|
||||
<a href="https://www.gnu.org/software/gzip/">gzip</a> -dc tzcode-latest.tar.gz | <a href="https://www.gnu.org/software/tar/">tar</a> -xf -
|
||||
gzip -dc tzdata-latest.tar.gz | tar -xf -
|
||||
</code></pre>
|
||||
<p>Alternatively, the following shell commands download the same
|
||||
release in a single-tarball format containing extra data
|
||||
useful for regression testing:</p>
|
||||
<pre><code>wget <a href="https://www.iana.org/time-zones/repository/tzdb-latest.tar.lz">https://www.iana.org/time-zones/repository/tzdb-latest.tar.lz</a>
|
||||
<pre><code>wget <a href="https://data.iana.org/time-zones/tzdb-latest.tar.lz">https://data.iana.org/time-zones/tzdb-latest.tar.lz</a>
|
||||
<a href="https://www.nongnu.org/lzip/">lzip</a> -dc tzdb-latest.tar.lz | tar -xf -
|
||||
</code></pre>
|
||||
<p>These commands use convenience links to the latest release
|
||||
@@ -183,7 +182,7 @@ title="Hypertext Transfer Protocol Secure">HTTPS</abbr></a>,
|
||||
<a href="https://en.wikipedia.org/wiki/Rsync"><abbr
|
||||
title="remote sync">rsync</abbr></a>, and
|
||||
<a href="https://en.wikipedia.org/wiki/FTP"><abbr
|
||||
title="File Transfer Protocol">FTP</abbr></a>.
|
||||
title="File Transfer Protocol">FTP</abbr></a>.</p>
|
||||
<p>Alternatively, a development repository of code and data can be
|
||||
retrieved from <a href="https://github.com">GitHub</a> via the shell
|
||||
command:</p>
|
||||
@@ -205,9 +204,7 @@ Time Zone Information Format (<abbr>TZif</abbr>)</a>
|
||||
The code also lets
|
||||
you read a <abbr>TZif</abbr> file and interpret timestamps for that
|
||||
location.</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 id="changes">Changes to the <code><abbr>tz</abbr></code> database</h2>
|
||||
<p>
|
||||
The <code><abbr>tz</abbr></code> code and data
|
||||
@@ -234,7 +231,10 @@ the process by tailoring the generic instructions in
|
||||
the <code><abbr>tz</abbr> README</code> file and installing the latest
|
||||
data yourself. System-specific instructions for installing the
|
||||
latest <code><abbr>tz</abbr></code> data have also been published
|
||||
for <a href="https://www.ibm.com/support/pages/aix-time-zone-olson-tzdata-updates"><abbr>AIX</abbr></a>,
|
||||
for <a href="https://community.ibm.com/community/user/blogs/ravindra-shinde/2024/12/13/time-zone-update-tool-tz"><abbr>AIX</abbr></a>
|
||||
(and
|
||||
<a href="https://www.ibm.com/support/pages/aix-time-zone-olson-tzdata-updates">older
|
||||
<abbr>AIX</abbr></a>),
|
||||
<a
|
||||
href="https://source.android.com/docs/core/permissions/timezone-rules">Android</a>,
|
||||
<a
|
||||
@@ -276,16 +276,14 @@ found in <a href="theory.html">Theory and pragmatics of the
|
||||
<a href="https://a0.github.io/a0-tzmigration/">A0 TimeZone Migration</a>
|
||||
displays changes between recent <code><abbr>tzdb</abbr></code> versions.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 id="coordinating">Coordinating with governments and distributors</h2>
|
||||
<p>
|
||||
As discussed in
|
||||
“<a href="https://www.icann.org/en/blogs/details/how-time-zones-are-coordinated-13-03-2023-en">How
|
||||
Time Zones Are Coordinated</a>”, the time zone database relies on
|
||||
collaboration among governments, the time zone database volunteer
|
||||
community, and data distributors downstream.
|
||||
community, and data distributors downstream.</p>
|
||||
<p>
|
||||
If your government plans to change its time zone boundaries or
|
||||
daylight saving rules, please send email as described in
|
||||
@@ -326,9 +324,7 @@ The shorter the notice, the more likely clock problems will arise; see “<a
|
||||
href="https://codeofmatt.com/on-the-timing-of-time-zone-changes/">On
|
||||
the Timing of Time Zone Changes</a>” for examples.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 id="commentary">Commentary on the <code><abbr>tz</abbr></code> database</h2>
|
||||
<ul>
|
||||
<li>The article
|
||||
@@ -344,9 +340,7 @@ database’s style.</li>
|
||||
<li><a href="https://doi.org/10.1145/3340301.3341125">What time is it:
|
||||
managing time in the internet</a> analyzes the database longitudinally.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 id="web">Web sites using recent versions of the
|
||||
<code><abbr>tz</abbr></code> database</h2>
|
||||
<p>
|
||||
@@ -380,9 +374,7 @@ calculates the current time difference between locations.</li>
|
||||
<li><a href="https://www.wx-now.com">Weather Now</a> and
|
||||
<a href="https://www.thetimenow.com">The Time Now</a> list the weather too.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 id="protocols">Network protocols for <code><abbr>tz</abbr></code> data</h2>
|
||||
<ul>
|
||||
<li><a href="https://www.rfc-editor.org/info/rfc7808/">Time Zone
|
||||
@@ -405,9 +397,7 @@ title="Extensible Markup Language">XML</abbr></a> format, and a variant
|
||||
uses <a href="https://www.json.org/json-en.html"><abbr
|
||||
title="JavaScript Object Notation">JSON</abbr></a> format.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 id="compilers">Other <code><abbr>tz</abbr></code> compilers</h2>
|
||||
<p>Although some of these do not fully support
|
||||
<code><abbr>tz</abbr></code> data, in recent <code><abbr>tzdb</abbr></code>
|
||||
@@ -416,7 +406,7 @@ running the command <code>make rearguard_tarballs</code> and compiling
|
||||
from the resulting tarballs instead.</p>
|
||||
<ul>
|
||||
<li><a href="https://github.com/libical">Libical</a>
|
||||
contains <code>vzic</code>, <a
|
||||
contains <code>vzic</code>, a <a
|
||||
href="https://en.wikipedia.org/wiki/C_(programming_language)">C</a>
|
||||
program that compiles
|
||||
<code><abbr>tz</abbr></code> source into iCalendar-compatible VTIMEZONE files.
|
||||
@@ -425,6 +415,23 @@ available under the <a
|
||||
href="https://www.gnu.org/copyleft/gpl.html"><abbr>GNU</abbr>
|
||||
General Public License (<abbr
|
||||
title="General Public License">GPL</abbr>)</a>.</li>
|
||||
<li>The <a id="TZDP"
|
||||
href="https://howardhinnant.github.io/date/tz.html">Time Zone
|
||||
Database Parser</a> contains a
|
||||
<a href="https://en.wikipedia.org/wiki/C++">C++</a> runtime parser
|
||||
supporting the <a
|
||||
href="https://en.cppreference.com/cpp/chrono#Time_zone"><code>std::chrono::time_zone</code> API</a>
|
||||
that is standardized in
|
||||
<a href="https://en.wikipedia.org/wiki/C%2B%2B20">C++20</a> and later.
|
||||
It is freely available under the
|
||||
<a href="https://en.wikipedia.org/wiki/MIT_License"><abbr
|
||||
title="Massachusetts Institute of Technology">MIT</abbr> license</a>.
|
||||
This approach is used by the <code>std::chrono::time_zone</code> implementation
|
||||
of <a href="https://gcc.gnu.org/"><abbr
|
||||
title="the GNU Compiler Collection">GCC</abbr></a>
|
||||
<code>libstdc++</code>, which is available under the GPL combined
|
||||
with the <a href="https://www.gnu.org/licenses/gcc-exception.html">GCC
|
||||
Runtime Library Exception</a>.</li>
|
||||
<li><a
|
||||
href="https://metacpan.org/release/DateTime-TimeZone">DateTime::TimeZone</a>
|
||||
contains a script <code>parse_olson</code> that compiles
|
||||
@@ -436,14 +443,6 @@ available under both the <abbr>GPL</abbr> and the Perl Artistic
|
||||
License. DateTime::TimeZone also contains a script
|
||||
<code>tests_from_zdump</code> that generates test cases for each clock
|
||||
transition in the <code><abbr>tz</abbr></code> database.</li>
|
||||
<li>The <a href="https://howardhinnant.github.io/date/tz.html">Time Zone
|
||||
Database Parser</a> is a
|
||||
<a href="https://en.wikipedia.org/wiki/C++">C++</a> parser and
|
||||
runtime library with a <a
|
||||
href="https://en.cppreference.com/cpp/chrono"><code>std::chrono</code> API</a>
|
||||
that is a standard part of C++.
|
||||
It is freely available under the
|
||||
<abbr title="Massachusetts Institute of Technology">MIT</abbr> license.</li>
|
||||
<li><a id="ICU" href="https://icu.unicode.org">International Components for
|
||||
Unicode (<abbr>ICU</abbr>)</a> contains C/C++ and <a
|
||||
href="https://en.wikipedia.org/wiki/Java_(programming_language)">Java</a>
|
||||
@@ -498,6 +497,7 @@ License">LGPL</abbr>)</a>.</li>
|
||||
<li><abbr>ICU</abbr> (mentioned <a href="#ICU">above</a>) contains compilers and
|
||||
Java-based libraries.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="https://nodatime.org">Noda Time – Date and
|
||||
time <abbr>API</abbr> for .NET</a>
|
||||
is like Joda-Time and Time4J, but for the .NET framework instead of Java.
|
||||
@@ -549,6 +549,7 @@ objects</a> let programs access an abstract view of
|
||||
<code><abbr>tzdb</abbr></code> data, and are designed to replace <a
|
||||
href="https://codeofmatt.com/javascript-date-type-is-horribly-broken/">JavaScript’s
|
||||
problematic <code>Date</code> objects</a> when working with dates and times.
|
||||
</li>
|
||||
<li><a href="https://github.com/JuliaTime">JuliaTime</a> contains a
|
||||
compiler from <code><abbr>tz</abbr></code> source into
|
||||
<a href="https://julialang.org">Julia</a>. It is freely available
|
||||
@@ -587,9 +588,7 @@ source into text files, along with a runtime that can read those
|
||||
files. Tcl is freely available under a <abbr>BSD</abbr>-style
|
||||
license.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 id="TZif">Other <abbr>TZif</abbr> readers</h2>
|
||||
<ul>
|
||||
<li>The <a
|
||||
@@ -604,6 +603,17 @@ a <abbr>TZif</abbr> file reader written in C that
|
||||
creates a <code>GTimeZone</code> object representing sets
|
||||
of <abbr>UT</abbr> offsets.
|
||||
It is freely available under the <abbr>LGPL</abbr>.</li>
|
||||
<li>The <a href="https://en.wikipedia.org/wiki/Musl">musl</a> C library
|
||||
also has an <abbr>TZif</abbr> reader.
|
||||
It is freely available under the <abbr>MIT</abbr> license.</li>
|
||||
<li>The Time Zone Database Parser for C++, mentioned <a href="#TZDP">above,</a>
|
||||
can be configured to read TZif binary files.
|
||||
A similar approach is taken in
|
||||
<a href="https://www.llvm.org/"><abbr>LLVM</abbr></a>
|
||||
<code>std::chrono::time_zone</code>, which is available
|
||||
under the Apache License with
|
||||
<a href="https://llvm.org/docs/DeveloperPolicy.html#open-source-licensing-terms">LLVM
|
||||
Exceptions</a>.</li>
|
||||
<li>The
|
||||
<a href="https://github.com/bloomberg/bde/wiki">BDE Standard Library</a>’s
|
||||
<code>baltzo::TimeZoneUtil</code> component contains a C++
|
||||
@@ -659,15 +669,20 @@ converts <abbr>TZif</abbr> data into
|
||||
<abbr>JSON</abbr>-format data suitable for use
|
||||
in its JavaScript library for time zone conversion. Dates before 1970
|
||||
are not supported.</li>
|
||||
<li>The <a href="https://crates.io/crates/jiff">jiff</a> datetime library
|
||||
for <a href="https://rust-lang.org/">Rust</a> either compiles
|
||||
<code><abbr>tz</abbr></code> source into Rust,
|
||||
or consults <abbr>TZif</abbr> data at runtime.
|
||||
It is in the public domain.
|
||||
It intends to supplant the soft-deprecated
|
||||
<a href="https://crates.io/crates/chrono-tz">Chrono-TZ</a>.</li>
|
||||
<li>The <a
|
||||
href="https://hackage.haskell.org/package/timezone-olson">timezone-olson</a>
|
||||
package contains <a href="https://www.haskell.org">Haskell</a> code that
|
||||
parses and uses <abbr>TZif</abbr> data. It is freely
|
||||
available under a <abbr>BSD</abbr>-style license.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 id="software">Other <code><abbr>tz</abbr></code>-based time zone software</h2>
|
||||
<ul>
|
||||
<li><a href="https://foxclocks.org">FoxClocks</a>
|
||||
@@ -684,7 +699,10 @@ data (mentioned <a href="#CLDR">below</a>) used by the
|
||||
<a href="https://en.wikipedia.org/wiki/Windows_Runtime">Windows Runtime</a> /
|
||||
<a href="https://en.wikipedia.org/wiki/Universal_Windows_Platform">Universal Windows Platform</a> classes
|
||||
<a href="https://learn.microsoft.com/en-us/uwp/api/Windows.Globalization.DateTimeFormatting.DateTimeFormatter"><code>DateTimeFormatter</code></a> and
|
||||
<a href="https://learn.microsoft.com/en-us/uwp/api/windows.globalization.calendar"><code>Calendar</code></a>.
|
||||
<a href="https://learn.microsoft.com/en-us/uwp/api/windows.globalization.calendar"><code>Calendar</code></a>,
|
||||
and with updates discussed in the
|
||||
<a href="https://techcommunity.microsoft.com/category/windows/blog/dstblog">Daylight
|
||||
Saving Time & Time Zone Blog</a>.
|
||||
<a id="System.TimeZoneInfo"
|
||||
href="https://learn.microsoft.com/en-us/archive/blogs/bclteam/exploring-windows-time-zones-with-system-timezoneinfo-josh-free">Exploring
|
||||
Windows Time Zones with <code>System.TimeZoneInfo</code></a> describes
|
||||
@@ -700,16 +718,14 @@ to <code><abbr>tz</abbr></code> names.
|
||||
These mappings can be performed programmatically via the
|
||||
<a href="https://github.com/mattjohnsonpint/TimeZoneConverter">TimeZoneConverter</a>
|
||||
.NET library,
|
||||
or the ICU Java and C++ libraries mentioned <a href="#ICU">above</a>.
|
||||
or the ICU Java and C++ libraries mentioned <a href="#ICU">above</a>.</li>
|
||||
<li><a
|
||||
href="https://www.oracle.com/java/">Oracle
|
||||
Java</a> contains a copy of a subset of a recent
|
||||
<code><abbr>tz</abbr></code> database in a
|
||||
Java-specific format.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 id="other-dbs">Other time zone databases</h2>
|
||||
<ul>
|
||||
<li><a href="https://www.astro.com/atlas">Time-zone Atlas</a>
|
||||
@@ -733,9 +749,7 @@ Schedules Information Manual</a> of the
|
||||
International Air Transport Association
|
||||
gives current time zone rules for airports served by commercial aviation.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 id="maps">Maps</h2>
|
||||
<ul>
|
||||
<li><a href="https://www.worldtimezone.com">World Time Zone Map
|
||||
@@ -757,9 +771,7 @@ World Factbook</em></a>, formerly published by the
|
||||
Although the maps’ pictorial quality is good,
|
||||
the maps do not indicate daylight saving time.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 id="boundaries">Time zone boundaries</h2>
|
||||
<p>Geographical boundaries between timezones are available
|
||||
from several <a
|
||||
@@ -810,9 +822,7 @@ for land and territorial waters only). A captain can change ship’s
|
||||
clocks any time after entering a new time zone; midnight changes are
|
||||
common.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 id="civil">Civil time concepts and history</h2>
|
||||
<ul>
|
||||
<li><a href="https://www.nist.gov/pml/time-and-frequency-division/popular-links/walk-through-time">A
|
||||
@@ -835,9 +845,7 @@ time zone boundary.</li>
|
||||
<li><a href="https://statoids.com/tconcept.html">Basic Time
|
||||
Zone Concepts</a> discusses terminological issues behind time zones.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 id="national">National histories of legal time</h2>
|
||||
<dl>
|
||||
<dt>Australia</dt>
|
||||
@@ -935,9 +943,7 @@ Navy (SOHMA) publishes an annual <a
|
||||
href="https://sohma.armada.mil.uy/index.php/servicios/datos-astronomicos" hreflang="es">almanac
|
||||
(in Spanish)</a>.</dd>
|
||||
</dl>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 id="costs">Costs and benefits of time shifts</h2>
|
||||
<p>Various sources argue for and against daylight saving time and time
|
||||
zone shifts, and many scientific studies have been conducted. This
|
||||
@@ -1016,9 +1022,7 @@ opposes <abbr>DST</abbr> changes and permanent <abbr>DST</abbr>,
|
||||
and advocates that governments adopt
|
||||
“permanent Standard Time for the health and safety of their citizens”.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 id="precision">Precision timekeeping</h2>
|
||||
<ul>
|
||||
<li><a
|
||||
@@ -1053,7 +1057,7 @@ a client’s time zone and daylight saving settings automatically.</li>
|
||||
Scales</a> describes astronomical time scales like
|
||||
<abbr title="Terrestrial Dynamic Time">TDT</abbr>,
|
||||
<abbr title="Geocentric Coordinate Time">TCG</abbr>, and
|
||||
<abbr title="Barycentric Dynamic Time">TDB</abbr>.
|
||||
<abbr title="Barycentric Dynamic Time">TDB</abbr>.</li>
|
||||
<li>The <a href="https://www.iau.org"><abbr
|
||||
title="International Astronomical Union">IAU</abbr></a>’s <a
|
||||
href="https://www.iausofa.org"><abbr
|
||||
@@ -1170,9 +1174,7 @@ However, there is still no consensus on whether this is the best way
|
||||
to replace leap seconds.
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 id="notation">Time notation</h2>
|
||||
<ul>
|
||||
<li>The <a id="CLDR" href="https://cldr.unicode.org">Unicode Common Locale Data
|
||||
@@ -1183,7 +1185,7 @@ contains French translations for “Eastern European Summer Time”,
|
||||
<a href="https://unicode.org/cldr/charts/latest/by_type/">by-type
|
||||
charts</a> show these values for many locales. Data values are available in
|
||||
both <abbr title="Locale Data Markup Language">LDML</abbr>
|
||||
(an <abbr>XML</abbr> format) and <abbr>JSON</abbr>.
|
||||
(an <abbr>XML</abbr> format) and <abbr>JSON</abbr>.</li>
|
||||
<li>
|
||||
<a href="https://www.cl.cam.ac.uk/~mgk25/iso-time.html">A summary of
|
||||
the international standard date and time notation</a> covers
|
||||
@@ -1209,7 +1211,7 @@ An extension, <a href="https://www.rfc-editor.org/info/rfc9557/">Date
|
||||
and Time on the Internet: Timestamps with Additional Information</a>
|
||||
(Internet <abbr>RFC</abbr> 9557) extends this profile
|
||||
to let you specify the <code><abbr>tzdb</abbr></code> timezone of a timestamp
|
||||
via suffixes like <code>[Asia/Tokyo]</code>.
|
||||
via suffixes like <code>[Asia/Tokyo]</code>.</li>
|
||||
<li>
|
||||
<a href="https://web.archive.org/web/20190130042457/https://www.hackcraft.net/web/datetime/">Date & Time
|
||||
Formats on the Web</a> surveys web- and Internet-oriented date and time
|
||||
@@ -1243,16 +1245,16 @@ any future changes to the rules. One should never set
|
||||
local time is nine hours ahead of <abbr>UT</abbr> and the time zone
|
||||
is called “<abbr>GMT</abbr>”.</li>
|
||||
</ul>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<section>
|
||||
<aside>
|
||||
<h2 id="see-also">See also</h2>
|
||||
<ul>
|
||||
<li><a href="theory.html">Theory and pragmatics of the
|
||||
<code><abbr>tz</abbr></code> code and data</a></li>
|
||||
<li><a href="tz-art.html">Time and the arts</a></li>
|
||||
</ul>
|
||||
</section>
|
||||
</aside>
|
||||
|
||||
<footer>
|
||||
<hr>
|
||||
|
||||
+1
-2
@@ -402,7 +402,6 @@ SEE ALSO
|
||||
time(2), localtime(3), tzset(3), tzselect(8), zdump(8), zic(8).
|
||||
|
||||
Olson A, Eggert P, Murchison K. The Time Zone Information Format
|
||||
(TZif). October 2024. Internet RFC 9636 ⟨https://www.rfc-editor.org/
|
||||
rfc/rfc9636⟩ doi:10.17487/RFC9636 ⟨https://doi.org/10.17487/RFC9636⟩.
|
||||
(TZif). October 2024. Internet RFC 9636 doi:10.17487/RFC9636.
|
||||
|
||||
Time Zone Database tzfile(5)
|
||||
@@ -719,7 +719,7 @@ delta_nonneg(struct tm *newp, struct tm *oldp)
|
||||
intmax_t sec = SECSPERREPEAT, result = cycles * sec;
|
||||
int tmy = oldp->tm_year + cycles * YEARSPERREPEAT;
|
||||
for ( ; tmy < newp->tm_year; ++tmy)
|
||||
result += DAYSPERNYEAR + isleap_sum(tmy, TM_YEAR_BASE);
|
||||
result += year_sum_days(tmy, TM_YEAR_BASE);
|
||||
result += newp->tm_yday - oldp->tm_yday;
|
||||
result *= HOURSPERDAY;
|
||||
result += newp->tm_hour - oldp->tm_hour;
|
||||
@@ -746,7 +746,7 @@ adjusted_yday(struct tm const *a, struct tm const *b)
|
||||
{
|
||||
int yday = a->tm_yday;
|
||||
if (b->tm_year < a->tm_year)
|
||||
yday += 365 + isleap_sum(b->tm_year, TM_YEAR_BASE);
|
||||
yday += year_sum_days(b->tm_year, TM_YEAR_BASE);
|
||||
return yday;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -330,12 +330,8 @@ for the
|
||||
POSIX Portable Character Set (PPCS)
|
||||
.UE
|
||||
and the encoding's non-unibyte characters should consist entirely of
|
||||
non-PPCS bytes. Non-PPCS characters typically occur only in comments:
|
||||
although output file names and time zone abbreviations can contain
|
||||
nearly any character, other software will work better if these are
|
||||
limited to the restricted syntax described under the
|
||||
.B \-v
|
||||
option.
|
||||
non-PPCS bytes.
|
||||
Non-PPCS characters typically occur only in comments.
|
||||
.PP
|
||||
Input lines are made up of fields.
|
||||
Fields are separated from one another by one or more white space characters.
|
||||
@@ -350,15 +346,16 @@ Any line that is blank (after comment stripping) is ignored.
|
||||
Nonblank lines are expected to be of one of three types:
|
||||
rule lines, zone lines, and link lines.
|
||||
.PP
|
||||
Names must be in English and are case insensitive.
|
||||
Keywords are in English and are case insensitive.
|
||||
They are not reserved words.
|
||||
They appear in several contexts, and include month and weekday names
|
||||
and keywords such as
|
||||
and other words such as
|
||||
.BR "maximum" ,
|
||||
.BR "only" ,
|
||||
.BR "Rolling" ,
|
||||
and
|
||||
.BR "Zone" .
|
||||
A name can be abbreviated by omitting all but an initial prefix; any
|
||||
A keyword can be abbreviated by omitting all but an initial prefix; any
|
||||
abbreviation must be unambiguous in context.
|
||||
.PP
|
||||
A rule line has the form
|
||||
@@ -586,11 +583,26 @@ The name of the timezone.
|
||||
This is the name used in creating the time conversion information file for the
|
||||
timezone.
|
||||
It should not contain a file name component
|
||||
that is empty or is
|
||||
.q ".\&"
|
||||
or
|
||||
.q ".." ;
|
||||
a file name component is a maximal substring that does not contain
|
||||
.q "/" .
|
||||
Names can be further restricted by the operating system or file system.
|
||||
Most systems reject a name
|
||||
.IB A / B
|
||||
if there is another name
|
||||
.IR A ,
|
||||
some reject names differing only in case,
|
||||
and some reject names containing special characters like
|
||||
.q ":"
|
||||
and
|
||||
.q "\e" .
|
||||
Other software will work better if names are
|
||||
limited to the restricted syntax described under the
|
||||
.B \-v
|
||||
option.
|
||||
.TP
|
||||
.B STDOFF
|
||||
The amount of time to add to UT to get standard time,
|
||||
@@ -737,8 +749,16 @@ A link line has the form
|
||||
.ta \w'Link\0\0'u +\w'Europe/Istanbul\0\0'u
|
||||
Link TARGET LINK-NAME
|
||||
.sp
|
||||
.fi
|
||||
where
|
||||
.B TARGET
|
||||
and
|
||||
.B LINK-NAME
|
||||
both have the same syntax as a zone line's
|
||||
.BR NAME .
|
||||
For example:
|
||||
.sp
|
||||
.nf
|
||||
.ti +2
|
||||
Link Europe/Istanbul Asia/Istanbul
|
||||
.sp
|
||||
@@ -752,10 +772,7 @@ field in some zone line or as the
|
||||
field in some link line.
|
||||
The
|
||||
.B LINK-NAME
|
||||
field is used as an alternative name for that zone;
|
||||
it has the same syntax as a zone line's
|
||||
.B NAME
|
||||
field.
|
||||
field is an alternative name for that zone.
|
||||
Links can chain together, although the behavior is unspecified if a
|
||||
chain of one or more links does not terminate in a Zone name.
|
||||
A link line can appear before the line that defines the link target.
|
||||
|
||||
@@ -186,13 +186,9 @@ FILES
|
||||
zero or more lines, each ending in a newline byte and containing at
|
||||
most 2048 bytes counting the newline, and without any NUL bytes. The
|
||||
input text's encoding is typically UTF-8 or ASCII; it should have a
|
||||
unibyte representation for the POSIX Portable Character Set (PPCS)
|
||||
⟨https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap06
|
||||
.html⟩ and the encoding's non-unibyte characters should consist
|
||||
entirely of non-PPCS bytes. Non-PPCS characters typically occur only
|
||||
in comments: although output file names and time zone abbreviations can
|
||||
contain nearly any character, other software will work better if these
|
||||
are limited to the restricted syntax described under the -v option.
|
||||
unibyte representation for the POSIX Portable Character Set (PPCS) and
|
||||
the encoding's non-unibyte characters should consist entirely of non-
|
||||
PPCS bytes. Non-PPCS characters typically occur only in comments.
|
||||
|
||||
Input lines are made up of fields. Fields are separated from one
|
||||
another by one or more white space characters. The white space
|
||||
@@ -206,11 +202,11 @@ FILES
|
||||
lines are expected to be of one of three types: rule lines, zone lines,
|
||||
and link lines.
|
||||
|
||||
Names must be in English and are case insensitive. They appear in
|
||||
several contexts, and include month and weekday names and keywords such
|
||||
as maximum, only, Rolling, and Zone. A name can be abbreviated by
|
||||
omitting all but an initial prefix; any abbreviation must be
|
||||
unambiguous in context.
|
||||
Keywords are in English and are case insensitive. They are not
|
||||
reserved words. They appear in several contexts, and include month and
|
||||
weekday names and other words such as maximum, only, Rolling, and Zone.
|
||||
A keyword can be abbreviated by omitting all but an initial prefix; any
|
||||
abbreviation must be unambiguous in context.
|
||||
|
||||
A rule line has the form
|
||||
|
||||
@@ -330,8 +326,14 @@ FILES
|
||||
|
||||
NAME The name of the timezone. This is the name used in creating the
|
||||
time conversion information file for the timezone. It should
|
||||
not contain a file name component “.” or “..”; a file name
|
||||
component is a maximal substring that does not contain “/”.
|
||||
not contain a file name component that is empty or is “.” or
|
||||
“..”; a file name component is a maximal substring that does not
|
||||
contain “/”. Names can be further restricted by the operating
|
||||
system or file system. Most systems reject a name A/B if there
|
||||
is another name A, some reject names differing only in case, and
|
||||
some reject names containing special characters like “:” and
|
||||
“\”. Other software will work better if names are limited to
|
||||
the restricted syntax described under the -v option.
|
||||
|
||||
STDOFF The amount of time to add to UT to get standard time, without
|
||||
any adjustment for daylight saving. This field has the same
|
||||
@@ -418,17 +420,17 @@ FILES
|
||||
|
||||
Link TARGET LINK-NAME
|
||||
|
||||
For example:
|
||||
where TARGET and LINK-NAME both have the same syntax as a zone line's
|
||||
NAME. For example:
|
||||
|
||||
Link Europe/Istanbul Asia/Istanbul
|
||||
|
||||
The TARGET field should appear as the NAME field in some zone line or
|
||||
as the LINK-NAME field in some link line. The LINK-NAME field is used
|
||||
as an alternative name for that zone; it has the same syntax as a zone
|
||||
line's NAME field. Links can chain together, although the behavior is
|
||||
unspecified if a chain of one or more links does not terminate in a
|
||||
Zone name. A link line can appear before the line that defines the
|
||||
link target. For example:
|
||||
as the LINK-NAME field in some link line. The LINK-NAME field is an
|
||||
alternative name for that zone. Links can chain together, although the
|
||||
behavior is unspecified if a chain of one or more links does not
|
||||
terminate in a Zone name. A link line can appear before the line that
|
||||
defines the link target. For example:
|
||||
|
||||
Link Greenwich G_M_T
|
||||
Link Etc/GMT Greenwich
|
||||
|
||||
@@ -528,10 +528,6 @@ static const int len_months[2][MONSPERYEAR] = {
|
||||
{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
|
||||
};
|
||||
|
||||
static const int len_years[2] = {
|
||||
DAYSPERNYEAR, DAYSPERLYEAR
|
||||
};
|
||||
|
||||
static struct attype {
|
||||
zic_t at;
|
||||
bool dontmerge;
|
||||
@@ -783,6 +779,7 @@ arg2num(char const *arg, int base, unsigned long maxval, char const *msgid)
|
||||
|
||||
#ifndef HAVE_SETMODE
|
||||
# if (defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ \
|
||||
|| defined __DragonFly__ \
|
||||
|| (defined __APPLE__ && defined __MACH__))
|
||||
# define HAVE_SETMODE 1
|
||||
# else
|
||||
@@ -1467,6 +1464,12 @@ namecheck(const char *name)
|
||||
register char const *component = name;
|
||||
for (cp = name; *cp; cp++) {
|
||||
unsigned char c = *cp;
|
||||
#if defined _WIN32 || defined __CYGWIN__
|
||||
if (c == ':' || c == '\\') {
|
||||
error(N_("file name '%s' contains '%c'"), name, c);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
if (noise && !strchr(benign, c)) {
|
||||
warning((strchr(printable_and_not_benign, c)
|
||||
? N_("file name '%s' contains byte '%c'")
|
||||
@@ -1781,8 +1784,20 @@ dolink(char const *target, char const *linkname, bool staysymlink)
|
||||
break;
|
||||
}
|
||||
link_errno = errno;
|
||||
/* When hard links are not supported, some MS-Windows file system
|
||||
drivers fail with EINVAL, contrary to the intent of
|
||||
MS-FSA 42.0 (2025) section 2.1.5.15.7. */
|
||||
if (link_errno == EINVAL)
|
||||
link_errno = ENOTSUP;
|
||||
}
|
||||
#endif
|
||||
/* On platforms like AIX, the Linux kernel, macOS, and Solaris,
|
||||
link/linkat can fail with ENOSYS or EPERM if the file system
|
||||
does not support hard links, or if other problems occur.
|
||||
It is too much trouble to suss out the other problems. */
|
||||
if (link_errno == ENOSYS || link_errno == EPERM)
|
||||
link_errno = ENOTSUP;
|
||||
|
||||
if (link_errno == EXDEV || link_errno == ENOTSUP)
|
||||
break;
|
||||
|
||||
@@ -1849,7 +1864,8 @@ dolink(char const *target, char const *linkname, bool staysymlink)
|
||||
strerror(link_errno));
|
||||
else if (symlink_errno < 0)
|
||||
warning(N_("copy used because symbolic link not obvious"));
|
||||
else if (symlink_errno != ENOTSUP)
|
||||
else if (symlink_errno != ENOSYS && symlink_errno != ENOTSUP
|
||||
&& symlink_errno != EPERM)
|
||||
warning(N_("copy used because symbolic link failed: %s"),
|
||||
strerror(symlink_errno));
|
||||
}
|
||||
@@ -2307,18 +2323,13 @@ inzsub(char **fields, int nfields, bool iscont)
|
||||
static zic_t
|
||||
getleapdatetime(char **fields, bool expire_line)
|
||||
{
|
||||
register const char * cp;
|
||||
register const struct lookup * lp;
|
||||
register zic_t i, j;
|
||||
zic_t year;
|
||||
int month, day;
|
||||
zic_t dayoff, tod;
|
||||
zic_t t;
|
||||
char xs;
|
||||
struct rule r;
|
||||
|
||||
dayoff = 0;
|
||||
cp = fields[LP_YEAR];
|
||||
if (sscanf(cp, "%"SCNdZIC"%c", &year, &xs) != 1) {
|
||||
if (sscanf(fields[LP_YEAR], "%"SCNdZIC"%c", &year, &xs) != 1) {
|
||||
/*
|
||||
** Leapin' Lizards!
|
||||
*/
|
||||
@@ -2332,38 +2343,20 @@ getleapdatetime(char **fields, bool expire_line)
|
||||
leapminyear = year;
|
||||
leapseen = true;
|
||||
}
|
||||
j = EPOCH_YEAR;
|
||||
while (j != year) {
|
||||
if (year > j) {
|
||||
i = len_years[isleap(j)];
|
||||
++j;
|
||||
} else {
|
||||
--j;
|
||||
i = -len_years[isleap(j)];
|
||||
}
|
||||
dayoff = oadd(dayoff, i);
|
||||
}
|
||||
if ((lp = byword(fields[LP_MONTH], mon_names)) == NULL) {
|
||||
error(N_("invalid month name"));
|
||||
return -1;
|
||||
}
|
||||
month = lp->l_value;
|
||||
j = TM_JANUARY;
|
||||
while (j != month) {
|
||||
i = len_months[isleap(year)][j];
|
||||
dayoff = oadd(dayoff, i);
|
||||
++j;
|
||||
}
|
||||
cp = fields[LP_DAY];
|
||||
if (sscanf(cp, "%d%c", &day, &xs) != 1 ||
|
||||
day <= 0 || day > len_months[isleap(year)][month]) {
|
||||
r.r_month = lp->l_value;
|
||||
if (! (sscanf(fields[LP_DAY], "%d%c", &r.r_dayofmonth, &xs) == 1
|
||||
&& 0 < r.r_dayofmonth
|
||||
&& r.r_dayofmonth <= len_months[isleap(year)][r.r_month])) {
|
||||
error(N_("invalid day of month"));
|
||||
return -1;
|
||||
}
|
||||
dayoff = oadd(dayoff, day - 1);
|
||||
t = omul(dayoff, SECSPERDAY);
|
||||
tod = gethms(fields[LP_TIME], N_("invalid time of day"));
|
||||
t = tadd(t, tod);
|
||||
r.r_dycode = DC_DOM;
|
||||
r.r_tod = gethms(fields[LP_TIME], N_("invalid time of day"));
|
||||
t = rpytime(&r, year);
|
||||
if (t < 0)
|
||||
error(N_("leap second precedes Epoch"));
|
||||
return t;
|
||||
@@ -2419,6 +2412,8 @@ inlink(char **fields, int nfields)
|
||||
error(N_("blank TARGET field on Link line"));
|
||||
return;
|
||||
}
|
||||
if (! namecheck(fields[LF_TARGET]))
|
||||
return;
|
||||
if (! namecheck(fields[LF_LINKNAME]))
|
||||
return;
|
||||
l.l_filenum = filenum;
|
||||
@@ -3552,10 +3547,13 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
|
||||
} else
|
||||
defaulttype = type;
|
||||
} else {
|
||||
zic_t year;
|
||||
for (year = min_year; year <= max_year; ++year) {
|
||||
zic_t year, next_year;
|
||||
bool try_next_year = true;
|
||||
for (year = min_year; try_next_year; year = next_year) {
|
||||
if (useuntil && year > zp->z_untilrule.r_hiyear)
|
||||
break;
|
||||
try_next_year = false;
|
||||
next_year = max_year;
|
||||
/*
|
||||
** Mark which rules to do in the current year.
|
||||
** For those to do, calculate rpytime(rp, year);
|
||||
@@ -3567,6 +3565,17 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
|
||||
struct rule *rp = &zp->z_rules[j];
|
||||
eats(zp->z_filenum, zp->z_linenum,
|
||||
rp->r_filenum, rp->r_linenum);
|
||||
|
||||
/* Keep track of the earliest year after YEAR
|
||||
in which some rule <= J applies. */
|
||||
if (year < rp->r_hiyear) {
|
||||
zic_t next = max(year + 1, rp->r_loyear);
|
||||
if (next <= next_year) {
|
||||
next_year = next;
|
||||
try_next_year = true;
|
||||
}
|
||||
}
|
||||
|
||||
rp->r_todo = year >= rp->r_loyear &&
|
||||
year <= rp->r_hiyear;
|
||||
if (rp->r_todo) {
|
||||
@@ -4147,7 +4156,7 @@ rpytime(const struct rule *rp, zic_t wantedy)
|
||||
wantedy = y + (yrem + 2 * YEARSPERREPEAT) % YEARSPERREPEAT;
|
||||
|
||||
while (wantedy != y) {
|
||||
i = len_years[isleap(y)];
|
||||
i = year_days(y);
|
||||
dayoff = oadd(dayoff, i);
|
||||
y++;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user