Home | History | Annotate | Download | only in time
History log of /src/lib/libc/time/README
RevisionDateAuthorComments
 1.18  18-Dec-2025  christos Release 2025c - 2025-12-10 14:42:37 -0800

Briefly:
Several code changes for compatibility with FreeBSD.

Changes to code

An unset TZ is no longer invalid when /etc/localtime is missing,
and is abbreviated "UTC" not "-00". This reverts to 2024b behavior.
(Problem and patch reported by Dag-Erling Smørgrav.)

New function offtime_r, short for fixed-offset localtime_rz.
It is defined if STD_INSPIRED is defined.
(Patch from Dag-Erling Smørgrav.)

tzset etc. are now more cautious about questionable TZ settings.
Privileged programs now reject TZ settings that start with '/',
unless they are TZDEFAULT (default "/etc/localtime") or
start with TZDIR then '/' (default "/usr/share/zoneinfo/").
Unprivileged programs now require files to be regular files
and reject relative names containing ".." directory components;
formerly, only privileged programs did those two things.
These changes were inspired by similar behavior in FreeBSD.
On NetBSD, unprivileged programs now use O_REGULAR to check
whether a TZ setting starting with '/' names a regular file,
avoiding a minor security race still present elsewhere.
TZ strings taken from tzalloc arguments are now treated with
no less caution than TZ strings taken from the environment, as
the old undocumented behavior would have been hard to explain.
tzset etc. no longer use the 'access' system call to check access;
instead they now use the system calls issetugid, getauxval,
getresuid/getresgid, and geteuid/getegid/getuid/getgid (whichever
first works) to test whether a program is privileged.
Compile with -DHAVE_SYS_AUXV_H=[01] to enable or disable
<sys/auxv.h> which (if it defines AT_SECURE) enables getauxval,
and compile with -DHAVE_ISSETUGID=[01], -DHAVE_GETRESUID=[01], and
-DHAVE_GETEUID=[01] to enable or disable the other calls' use.

The new CFLAGS option -DTZ_CHANGE_INTERVAL=N makes tzset etc.
check for TZif file changes if the in-memory data are N seconds
old or more, and are derived from the TZ environment variable.
This is intended for platforms that want tzset etc. to reflect
changes to whatever file TZ selects (including changes to
/etc/localtime if TZ is unset). If N is negative (the default)
these checks are omitted; this is the traditional behavior.

The new CFLAGS options -DHAVE_STRUCT_STAT_ST_CTIM=0 and
-DHAVE_STRUCT_TIMESPEC=0 port to non-POSIX.1-2008 platforms
that lack st_ctim and struct timespec, respectively.

tzset etc. now treat ' ' like '_' in time zone abbreviations,
just as they treat other invalid bytes. This continues the
transition begun in release 96k, which removed spaces in tzdata
because the spaces break time string parsers.

The new CFLAGS option -DTHREAD_PREFER_SINGLE causes tzcode
in single-threaded processes to avoid locks, as FreeBSD does.
This can save time in single-threaded apps. The threadedness
testing costs CPU time and energy in multi-threaded apps.
New options -DHAVE___ISTHREADED and -DHAVE_SYS_SINGLE_THREADED_H
can help configure how to test for single-threadedness.

The new CFLAGS option -DTHREAD_RWLOCK uses read-write locks, as
macOS does, instead of mutexes. This saves real time when TZ is
rarely changing and many threads call tzcode simultaneously.
It costs more CPU time and energy.

The new CFLAGS option -TTHREAD_TM_MULTI causes localtime to return
a pointer to thread-specific memory, as FreeBSD does, instead of
to the same memory in all threads. This supports unportable
programs that incorrectly use localtime instead of localtime_r.
This option affects gmtime and offtime similarly to localtime.
Because the corresponding storage is freed on thread exit, this
option is incompatible with POSIX.1-2024 and earlier. It also
costs CPU time and memory.

tzfree now preserves errno, consistently with POSIX.1-2024 'free'.

tzcode now uses mempcpy if available, guessing its availability.
Compile with -DHAVE_MEMPCPY=1 or 0 to override the guess.

tzcode now uses strnlen to improve asymptotic performance a bit.
Compile with -DHAVE_STRNLEN=0 if your platform lacks it.

tzcode now hand-declares unistd.h-provided symbols like getopt
if HAVE_UNISTD_H=0, not if HAVE_POSIX_DECLS=0.

tzset etc. now have an experimental OPENAT_TZDIR option;
see Makefile and localtime.c for details.

On platforms like GNU/Hurd that do not define PATH_MAX,
exceedingly long TZ strings no longer fail merely because they
exceed an arbitrary file name length limit imposed by tzcode.

zic has new options inspired by FreeBSD. '-D' skips creation of
output ancestor directories, '-m MODE' sets output files' mode,
and '-u OWNER[:GROUP]' sets output files' owner and group.

zic now uses the fdopen function, which was standardized by
POSIX.1-1988 and is now safe to use in portable code.
This replaces its use of the older umask function, which
complicated maintenance.
 1.17  23-Dec-2023  christos Import tzcode 2023d:

localtime.c no longer mishandles TZif files that contain a single
transition into a DST regime. Previously, it incorrectly assumed
DST was in effect before the transition too. (Thanks to Alois
Treindl for debugging help.)

localtime.c's timeoff no longer collides with OpenBSD 7.4.

The C code now uses _Generic only if __STDC_VERSION__ says the
compiler is C11 or later.

tzselect now optionally reads zonenow.tab, to simplify when
configuring only for timestamps dated from now on.

tzselect no longer creates temporary files.

tzselect no longer mishandles the following:

Spaces and most other special characters in BUGEMAIL, PACKAGE,
TZDIR, and VERSION.

TZ strings when using mawk 1.4.3, which mishandles regular
expressions of the form /X{2,}/.

ISO 6709 coordinates when using an awk that lacks the GNU
extension of newlines in -v option-arguments.

Non UTF-8 locales when using an iconv command that lacks the GNU
//TRANSLIT extension.

zic no longer mishandles data for Palestine after the year 2075.
Previously, it incorrectly omitted post-2075 transitions that are
predicted for just before and just after Ramadan. (Thanks to Ken
Murchison for debugging help.)

zic now works again on Linux 2.6.16 and 2.6.17 (2006).
 1.16  09-Oct-2020  christos Merge tzcode2020b (except we keep tzsetwall(3) for now for compatibility,
and we were "slim" already)

Support for zic's long-obsolete '-y YEARISTYPE' option has been
removed and, with it, so has support for the TYPE field in Rule
lines, which is now reserved for compatibility with earlier zic.
These features were previously deprecated in release 2015f.
(Thanks to Tim Parenti.)

zic now defaults to '-b slim' instead of to '-b fat'.

zic's new '-l -' and '-p -' options uninstall any existing
localtime and posixrules files, respectively.

The undocumented and ineffective tzsetwall function has been
removed.
 1.15  04-Apr-2019  christos merge 2019a

Changes to code

zic now has an -r option to limit the time range of output data.
For example, 'zic -r @1000000000' limits the output data to
timestamps starting 1000000000 seconds after the Epoch.
This helps shrink output size and can be useful for applications
not needing the full timestamp history, such as TZDIST truncation;
see Internet RFC 8536 section 5.1. (Inspired by a feature request
from Christopher Wong, helped along by bug reports from Wong and
from Tim Parenti.)

Changes to documentation

Mention Internet RFC 8536 (February 2019), which documents TZif.

tz-link.html now cites tzdata-meta
<https://tzdata-meta.timtimeonline.com/>.
 1.14  19-Oct-2018  christos Update to 2018f:

Changes to code

zic now always generates TZif files where time type 0 is used for
timestamps before the first transition. This simplifies the
reading of TZif files and should not affect behavior of existing
TZif readers because the same set of time types is used; only
their internal indexes may have changed. This affects only the
legacy zones EST5EDT, CST6CDT, MST7MDT, PST8PDT, CET, MET, and
EET, which previously used nonzero types for these timestamps.

Because of the type 0 change, zic no longer outputs a dummy
transition at time -2**59 (before the Big Bang), as clients should
no longer need this to handle historical timestamps correctly.
This reverts a change introduced in 2013d and shrinks most TZif
files by a few bytes.

zic now supports negative time-of-day in Rule and Leap lines, e.g.,
"Rule X min max - Apr lastSun -6:00 1:00 -" means the transition
occurs at 18:00 on the Saturday before the last Sunday in April.
This behavior was documented in 2018a but the code did not
entirely match the documentation.

localtime.c no longer requires at least one time type in TZif
files that lack transitions or have a POSIX-style TZ string. This
future-proofs the code against possible future extensions to the
format that would allow TZif files with POSIX-style TZ strings and
without transitions or time types.

A read-access subscript error in localtime.c has been fixed.
It could occur only in TZif files with timecnt == 0, something that
does not happen in practice now but could happen in future versions.

localtime.c no longer ignores TZif POSIX-style TZ strings that
specify only standard time. Instead, these TZ strings now
override the default time type for timestamps after the last
transition (or for all time stamps if there are no transitions),
just as DST strings specifying DST have always done.

leapseconds.awk now outputs "#updated" and "#expires" comments,
and supports leap seconds at the ends of months other than June
and December. (Inspired by suggestions from Chris Woodbury.)

Changes to documentation

New restrictions: A Rule name must start with a character that
is neither an ASCII digit nor "-" nor "+", and an unquoted name
should not use characters in the set "!$%&'()*,/:;<=>?@[\]^`{|}~".
The latter restriction makes room for future extensions (a
possibility noted by Tom Lane).

tzfile.5 now documents what time types apply before the first and
after the last transition, if any.

Documentation now uses the spelling "timezone" for a TZ setting
that determines timestamp history, and "time zone" for a
geographic region currently sharing the same standard time.

The name "TZif" is now used for the tz binary data format.

tz-link.htm now mentions the A0 TimeZone Migration utilities.
(Thanks to Aldrin Martoq for the link.)
 1.13  25-Jan-2018  christos branches: 1.13.2; 1.13.4;
Merge tzcode2018c [ changelog with changes to tzdata sections removed ]

Release 2018c - 2018-01-22 23:00:44 -0800

Changes to build procedure

The build procedure now works around mawk 1.3.3's lack of support
for character class expressions. (Problem reported by Ohyama.)


Release 2018b - 2018-01-17 23:24:48 -0800

Changes to build procedure

The distribution now contains the file 'pacificnew' again.
This file was inadvertantly omitted in the 2018a distribution.
(Problem reported by Matias Fonzo.)


Release 2018a - 2018-01-12 22:29:21 -0800

Changes to build procedure

The default installation locations have been changed to mostly
match Debian circa 2017, instead of being designed as an add-on to
4.3BSD circa 1986. This affects the Makefile macros TOPDIR,
TZDIR, MANDIR, and LIBDIR. New Makefile macros TZDEFAULT, USRDIR,
USRSHAREDIR, BINDIR, ZDUMPDIR, and ZICDIR let installers tailor
locations more precisely. (This responds to suggestions from
Brian Inglis and from Steve Summit.)

The default installation procedure no longer creates the
backward-compatibility link US/Pacific-New, which causes
confusion during user setup (e.g., see Debian bug 815200).
Use 'make BACKWARD="backward pacificnew"' to create the link
anyway, for now. Eventually we plan to remove the link entirely.

tzdata.zi now contains a version-number comment.
(Suggested by Tom Lane.)

The Makefile now quotes values like BACKWARD more carefully when
passing them to the shell. (Problem reported by Zefram.)

Builders no longer need to specify -DHAVE_SNPRINTF on platforms
that have snprintf and use pre-C99 compilers. (Problem reported
by Jon Skeet.)

Changes to code

zic has a new option -t FILE that specifies the location of the
file that determines local time when TZ is unset. The default for
this location can be configured via the new TZDEFAULT makefile
macro, which defaults to /etc/localtime.

Diagnostics and commentary now distinguish UT from UTC more
carefully; see theory.html for more information about UT vs UTC.

zic has been ported to GCC 8's -Wstringop-truncation option.
(Problem reported by Martin Sebor.)

Changes to documentation and commentary

The zic man page now documents the longstanding behavior that
times and years can be out of the usual range, with negative times
counting backwards from midnight and with year 0 preceding year 1.
(Problem reported by Michael Deckers.)

The theory.html file now mentions the POSIX limit of six chars
per abbreviation, and lists alphabetic abbreviations used.

The files tz-art.htm and tz-link.htm have been renamed to
tz-art.html and tz-link.html, respectively, for consistency with
other file names and to simplify web server configuration.
 1.12  11-Mar-2017  christos merge 2017a
 1.11  07-Oct-2016  christos branches: 1.11.2;
merge tzcode2016g
 1.10  15-Mar-2016  christos branches: 1.10.2;
Sync with 2016b
 1.9  07-Oct-2014  christos Sync with tzcode2014h
 1.8  26-Dec-2013  christos branches: 1.8.4;
update from tzcode 2013e to tzcode2013i
i:
The compile-time flag NOSOLAR has been removed, as nowadays the
benefit of slightly shrinking runtime table size is outweighed by the
cost of disallowing potential future updates that exceed old limits.
h:
Fix localtime overflow bugs with 32-bit unsigned time_t.

zdump no longer assumes sscanf returns maximal values on overflow.
g:
'zic' now runs on platforms that lack both hard links and symlinks.
(Thanks to Theo Veenker for reporting the problem, for MinGW.)
Also, fix some bugs on platforms that lack hard links but have symlinks.

'zic -v' again warns that Asia/Tehran has no POSIX environment variable
to predict the far future, fixing a bug introduced in 2013e.
f:
The types of the global variables 'timezone' and 'altzone' (if present)
have been changed back to 'long'. This is required for 'timezone'
by POSIX, and for 'altzone' by common practice, e.g., Solaris 11.
These variables were originally 'long' in the tz code, but were
mistakenly changed to 'time_t' in 1987; nobody reported the
incompatibility until now. The difference matters on x32, where
'long' is 32 bits and 'time_t' is 64. (Thanks to Elliott Hughes.)
 1.7  09-Aug-2012  christos branches: 1.7.2;
merge 2012e
 1.6  31-Dec-2009  mlelstv branches: 1.6.6;
Import tzcode2009k.
- now understands 64bit time_t and 64bit data in timezone files.
- localtime(), gmtime(), asctime() and ctime() may now fail with
a NULL result if time_t cannot be represented by struct tm.
 1.5  29-Jan-2002  kleink Merge tzcode2002b.
 1.4  22-Jan-1998  jtc branches: 1.4.12;
sync with tzcode1998b
 1.3  22-Jan-1998  jtc sync with tzcode1998a
 1.2  09-Jan-1998  perry RCS Id Police.
 1.1  10-Mar-1995  jtc branches: 1.1.1;
Initial revision
 1.1.1.7  25-Oct-2009  mlelstv import tzcode2009k
 1.1.1.6  29-Jan-2002  kleink Import tzcode2002b.
 1.1.1.5  22-Jan-1998  jtc import tzcode1998b
 1.1.1.4  22-Jan-1998  jtc import tzcode1998a
 1.1.1.3  05-Sep-1997  jtc import tzcode1997g
 1.1.1.2  18-Jun-1997  jtc import tzcode1997e
 1.1.1.1  10-Mar-1995  jtc branches: 1.1.1.1.2;
Strictly speaking, these files probably don't belong in the libc sources.
On the other hand, it makes it easier to track the master tzcode sources
if we try to keep the distribution together as much as possible.

The zic and zdump commands will access the files the need with make's
.PATH facility.
 1.1.1.1.2.2  10-Mar-1995  jtc Strictly speaking, these files probably don't belong in the libc sources.
On the other hand, it makes it easier to track the master tzcode sources
if we try to keep the distribution together as much as possible.

The zic and zdump commands will access the files the need with make's
.PATH facility.
 1.1.1.1.2.1  10-Mar-1995  jtc file README was added on branch ivory_soap on 1995-03-10 07:08:15 +0000
 1.4.12.1  08-Mar-2002  nathanw Catch up to -current.
 1.6.6.2  22-May-2014  yamt sync with head.

for a reference, the tree before this commit was tagged
as yamt-pagecache-tag8.

this commit was splitted into small chunks to avoid
a limitation of cvs. ("Protocol error: too many arguments")
 1.6.6.1  30-Oct-2012  yamt sync with head
 1.7.2.1  20-Aug-2014  tls Rebase to HEAD as of a few days ago.
 1.8.4.1  25-Jan-2015  martin Pull up the following revisions via patch, requested by apb in ticket #453:

doc/3RDPARTY up to 1.1195
usr.sbin/zdump/Makefile up to 1.9
usr.sbin/zic/Makefile up to 1.15
lib/libc/time/Makefile up to 1.25
lib/libc/time/Makefile.inc up to 1.21
lib/libc/time/NEWS up to 1.8
lib/libc/time/README up to 1.9
lib/libc/time/Theory up to 1.16
lib/libc/time/asctime.c up to 1.20
lib/libc/time/checktab.awk up to 1.8
lib/libc/time/ctime.3 up to 1.51
lib/libc/time/getdate.c up to 1.3
lib/libc/time/localtime.c up to 1.92
lib/libc/time/private.h up to 1.38
lib/libc/time/strftime.c up to 1.33
lib/libc/time/time2posix.3 up to 1.19
lib/libc/time/tz-art.htm up to 1.8
lib/libc/time/tz-link.htm up to 1.20
lib/libc/time/tzfile.5 up to 1.22
lib/libc/time/tzfile.h up to 1.16
lib/libc/time/tzselect.8 up to 1.6
lib/libc/time/tzselect.ksh up to 1.12
lib/libc/time/tzset.3 up to 1.31
lib/libc/time/zdump.8 up to 1.14
lib/libc/time/zdump.c up to 1.40
lib/libc/time/zic.8 up to 1.24
lib/libc/time/zic.c up to 1.52

Update tzcode from 2014e to 2014j.
 1.10.2.2  20-Mar-2017  pgoyette Sync with HEAD
 1.10.2.1  04-Nov-2016  pgoyette Sync with HEAD
 1.11.2.1  21-Apr-2017  bouyer Sync with HEAD
 1.13.4.1  10-Jun-2019  christos Sync with HEAD
 1.13.2.1  20-Oct-2018  pgoyette Sync with head

RSS XML Feed