aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Paeps <philip@FreeBSD.org>2022-08-16 08:09:47 +0000
committerPhilip Paeps <philip@FreeBSD.org>2022-08-16 08:09:47 +0000
commita24d752d3e77a28c877a5319face8d00aa1b558c (patch)
tree5ae147d3bedd850833ec5c783ea54fa4b00e6aba
parent9b5369d383baf54651be0922591eeb6263ce029d (diff)
downloadsrc-vendor/tzcode.tar.gz
src-vendor/tzcode.zip
-rw-r--r--CONTRIBUTING97
-rw-r--r--LICENSE5
-rw-r--r--Makefile1316
-rw-r--r--NEWS5671
-rw-r--r--README92
-rw-r--r--SECURITY15
-rw-r--r--Theory568
-rw-r--r--asctime.c69
-rw-r--r--calendars173
-rw-r--r--checktab.awk159
-rw-r--r--date.190
-rw-r--r--date.1.txt202
-rw-r--r--date.c951
-rw-r--r--difftime.c79
-rw-r--r--ialloc.c86
-rw-r--r--itca.jpgbin55948 -> 0 bytes
-rw-r--r--localtime.c2347
-rw-r--r--newctime.3285
-rw-r--r--newctime.3.txt277
-rw-r--r--newstrftime.3182
-rw-r--r--newstrftime.3.txt220
-rw-r--r--newtzset.3227
-rw-r--r--newtzset.3.txt330
-rw-r--r--private.h824
-rw-r--r--scheck.c63
-rw-r--r--strftime.c409
-rw-r--r--theory.html1479
-rw-r--r--time2posix.356
-rw-r--r--time2posix.3.txt139
-rw-r--r--tz-art.htm472
-rw-r--r--tz-art.html636
-rw-r--r--tz-how-to.html719
-rw-r--r--tz-link.htm678
-rw-r--r--tz-link.html1175
-rw-r--r--tzfile.5554
-rw-r--r--tzfile.5.txt463
-rw-r--r--tzfile.h125
-rw-r--r--tzselect.8102
-rw-r--r--tzselect.8.txt84
-rw-r--r--tzselect.ksh548
-rw-r--r--usno1988111
-rw-r--r--usno1989452
-rw-r--r--usno1989a452
-rw-r--r--usno1995326
-rw-r--r--usno1997327
-rw-r--r--usno1998327
-rw-r--r--version1
-rw-r--r--workman.sh23
-rw-r--r--zdump.8248
-rw-r--r--zdump.8.txt159
-rw-r--r--zdump.c1486
-rw-r--r--zic.8813
-rw-r--r--zic.8.txt796
-rw-r--r--zic.c3709
-rwxr-xr-xzoneinfo2tdf.pl54
55 files changed, 20750 insertions, 10501 deletions
diff --git a/CONTRIBUTING b/CONTRIBUTING
new file mode 100644
index 000000000000..4c0f56a50265
--- /dev/null
+++ b/CONTRIBUTING
@@ -0,0 +1,97 @@
+# Contributing to the tz code and data
+
+Please do not create issues or pull requests on GitHub, as the
+proper procedure for proposing and distributing patches is via
+email as described below.
+
+The time zone database is by no means authoritative: governments
+change timekeeping rules erratically and sometimes with little
+warning, the data entries do not cover all of civil time before
+1970, and undoubtedly errors remain in the code and data. Feel
+free to fill gaps or fix mistakes, and please email improvements
+to <tz@iana.org> for use in the future. In your email, please give
+reliable sources that reviewers can check.
+
+## Contributing technical changes
+
+To email small changes, please run a POSIX shell command like
+'diff -u old/europe new/europe >myfix.patch', and attach
+'myfix.patch' to the email.
+
+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>.
+It is also good to browse the mailing list archives
+<https://mm.icann.org/pipermail/tz/> for examples of patches that tend
+to work well. Additions to data should contain commentary citing
+reliable sources as justification. Citations should use "https:" URLs
+if available.
+
+For changes that fix sensitive security-related bugs, please see the
+distribution's 'SECURITY' file.
+
+Please submit changes against either the latest release
+<https://www.iana.org/time-zones> or the main branch of the development
+repository. The latter is preferred.
+
+## Sample Git workflow for developing contributions
+
+If you use Git the following workflow may be helpful:
+
+ * Copy the development repository.
+
+ git clone https://github.com/eggert/tz.git
+ cd tz
+
+ * Get current with the main branch.
+
+ git checkout main
+ git pull
+
+ * Switch to a new branch for the changes. Choose a different
+ branch name for each change set.
+
+ git checkout -b mybranch
+
+ * Sleuth by using 'git blame'. For example, when fixing data for
+ Africa/Sao_Tome, if the command 'git blame africa' outputs a line
+ '2951fa3b (Paul Eggert 2018-01-08 09:03:13 -0800 1068) Zone
+ Africa/Sao_Tome 0:26:56 - LMT 1884', commit 2951fa3b should
+ provide some justification for the 'Zone Africa/Sao_Tome' line.
+
+ * Edit source files. Include commentary that justifies the
+ changes by citing reliable sources.
+
+ * Debug the changes, e.g.:
+
+ make check
+ make install
+ ./zdump -v America/Los_Angeles
+
+ * For each separable change, commit it in the new branch, e.g.:
+
+ git add northamerica
+ git commit
+
+ See recent 'git log' output for the commit-message style.
+
+ * Create patch files 0001-..., 0002-..., ...
+
+ git format-patch main
+
+ * After reviewing the patch files, send the patches to <tz@iana.org>
+ for others to review.
+
+ git send-email main
+
+ For an archived example of such an email, see
+ "[PROPOSED] Fix off-by-1 error for Jamaica and T&C before 1913"
+ <https://mm.icann.org/pipermail/tz/2018-February/026122.html>.
+
+ * Start anew by getting current with the main branch again
+ (the second step above).
+
+-----
+
+This file is in the public domain.
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 000000000000..8ba4399c622d
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,5 @@
+Unless specified below, all files in the tz code and data (including
+this LICENSE file) are in the public domain.
+
+If the files date.c, newstrftime.3, and strftime.c are present, they
+contain material derived from BSD and use the BSD 3-clause license.
diff --git a/Makefile b/Makefile
index 892d11619b58..b68f843d08ee 100644
--- a/Makefile
+++ b/Makefile
@@ -1,72 +1,137 @@
-# <pre>
-# @(#)Makefile 8.9
+# Make and install tzdb code and data.
+
# This file is in the public domain, so clarified as of
# 2009-05-17 by Arthur David Olson.
-# Change the line below for your time zone (after finding the zone you want in
-# the time zone files, or adding it to a time zone file).
-# Alternately, if you discover you've got the wrong time zone, you can just
-# zic -l rightzone
-# to correct things.
+# Package name for the code distribution.
+PACKAGE= tzcode
+
+# Version number for the distribution, overridden in the 'tarballs' rule below.
+VERSION= unknown
+
+# Email address for bug reports.
+BUGEMAIL= tz@iana.org
+
+# DATAFORM selects the data format.
+# Available formats represent essentially the same data, albeit
+# possibly with minor discrepancies that users are not likely to notice.
+# To get new features and the best data right away, use:
+# DATAFORM= vanguard
+# To wait a while before using new features, to give downstream users
+# time to upgrade zic (the default), use:
+# DATAFORM= main
+# To wait even longer for new features, use:
+# DATAFORM= rearguard
+# Rearguard users might also want "ZFLAGS = -b fat"; see below.
+DATAFORM= main
+
+# Change the line below for your timezone (after finding the one you want in
+# one of the $(TDATA) source files, or adding it to a source file).
+# Alternatively, if you discover you've got the wrong timezone, you can just
+# 'zic -l -' to remove it, or 'zic -l rightzone' to change it.
# Use the command
# make zonenames
# to get a list of the values you can use for LOCALTIME.
-LOCALTIME= GMT
-
-# If you want something other than Eastern United States time as a template
-# for handling POSIX-style time zone environment variables,
-# change the line below (after finding the zone you want in the
-# time zone files, or adding it to a time zone file).
-# (When a POSIX-style environment variable is handled, the rules in the
-# template file are used to determine "spring forward" and "fall back" days and
-# times; the environment variable itself specifies UTC offsets of standard and
-# summer time.)
-# Alternately, if you discover you've got the wrong time zone, you can just
-# zic -p rightzone
-# to correct things.
+LOCALTIME= Factory
+
+# The POSIXRULES macro controls interpretation of nonstandard and obsolete
+# POSIX-like TZ settings like TZ='EET-2EEST' that lack DST transition rules.
+# Such a setting uses the rules in a template file to determine
+# "spring forward" and "fall back" days and times; the environment
+# variable itself specifies UT offsets of standard and daylight saving time.
+#
+# If POSIXRULES is '-', no template is installed; this is the default.
+#
+# Any other value for POSIXRULES is obsolete and should not be relied on, as:
+# * It does not work correctly in popular implementations such as GNU/Linux.
+# * It does not work even in tzcode, except for historical timestamps
+# that precede the last explicit transition in the POSIXRULES file.
+# Hence it typically does not work for current and future timestamps.
+# In short, software should avoid ruleless settings like TZ='EET-2EEST'
+# and so should not depend on the value of POSIXRULES.
+#
+# If, despite the above, you want a template for handling these settings,
+# you can change the line below (after finding the timezone you want in the
+# one of the $(TDATA) source files, or adding it to a source file).
+# Alternatively, if you discover you've got the wrong timezone, you can just
+# 'zic -p -' to remove it, or 'zic -p rightzone' to change it.
# Use the command
# make zonenames
# to get a list of the values you can use for POSIXRULES.
-# If you want POSIX compatibility, use "America/New_York".
-POSIXRULES= America/New_York
+POSIXRULES= -
# Also see TZDEFRULESTRING below, which takes effect only
# if the time zone files cannot be accessed.
-# Everything gets put in subdirectories of. . .
-TOPDIR= /usr/local
+# Installation locations.
+#
+# The defaults are suitable for Debian, except that if REDO is
+# posix_right or right_posix then files that Debian puts under
+# /usr/share/zoneinfo/posix and /usr/share/zoneinfo/right are instead
+# put under /usr/share/zoneinfo-posix and /usr/share/zoneinfo-leaps,
+# respectively. Problems with the Debian approach are discussed in
+# the commentary for the right_posix rule (below).
-# "Compiled" time zone information is placed in the "TZDIR" directory
-# (and subdirectories).
-# Use an absolute path name for TZDIR unless you're just testing the software.
+# Destination directory, which can be used for staging.
+# 'make DESTDIR=/stage install' installs under /stage (e.g., to
+# /stage/etc/localtime instead of to /etc/localtime). Files under
+# /stage are not intended to work as-is, but can be copied by hand to
+# the root directory later. If DESTDIR is empty, 'make install' does
+# not stage, but installs directly into production locations.
+DESTDIR =
-TZDIR= $(TOPDIR)/etc/zoneinfo
+# Everything is installed into subdirectories of TOPDIR, and used there.
+# TOPDIR should be empty (meaning the root directory),
+# or a directory name that does not end in "/".
+# TOPDIR should be empty or an absolute name unless you're just testing.
+TOPDIR =
-# The "tzselect", "zic", and "zdump" commands get installed in. . .
+# The default local timezone is taken from the file TZDEFAULT.
+TZDEFAULT = $(TOPDIR)/etc/localtime
-ETCDIR= $(TOPDIR)/etc
+# The subdirectory containing installed program and data files, and
+# likewise for installed files that can be shared among architectures.
+# These should be relative file names.
+USRDIR = usr
+USRSHAREDIR = $(USRDIR)/share
-# If you "make INSTALL", the "date" command gets installed in. . .
+# "Compiled" timezone information is placed in the "TZDIR" directory
+# (and subdirectories).
+# TZDIR_BASENAME should not contain "/" and should not be ".", ".." or empty.
+TZDIR_BASENAME= zoneinfo
+TZDIR = $(TOPDIR)/$(USRSHAREDIR)/$(TZDIR_BASENAME)
-BINDIR= $(TOPDIR)/bin
+# The "tzselect" and (if you do "make INSTALL") "date" commands go in:
+BINDIR = $(TOPDIR)/$(USRDIR)/bin
-# Manual pages go in subdirectories of. . .
+# The "zdump" command goes in:
+ZDUMPDIR = $(BINDIR)
-MANDIR= $(TOPDIR)/man
+# The "zic" command goes in:
+ZICDIR = $(TOPDIR)/$(USRDIR)/sbin
+
+# Manual pages go in subdirectories of. . .
+MANDIR = $(TOPDIR)/$(USRSHAREDIR)/man
# Library functions are put in an archive in LIBDIR.
+LIBDIR = $(TOPDIR)/$(USRDIR)/lib
-LIBDIR= $(TOPDIR)/lib
-TZLIB= $(LIBDIR)/libtz.a
-# If you always want time values interpreted as "seconds since the epoch
-# (not counting leap seconds)", use
+# Types to try, as an alternative to time_t.
+TIME_T_ALTERNATIVES = $(TIME_T_ALTERNATIVES_HEAD) $(TIME_T_ALTERNATIVES_TAIL)
+TIME_T_ALTERNATIVES_HEAD = int_least64_t
+TIME_T_ALTERNATIVES_TAIL = int_least32_t uint_least32_t uint_least64_t
+
+# What kind of TZif data files to generate. (TZif is the binary time
+# zone data format that zic generates; see Internet RFC 8536.)
+# If you want only POSIX time, with time values interpreted as
+# seconds since the epoch (not counting leap seconds), use
# REDO= posix_only
-# below. If you always want right time values interpreted as "seconds since
-# the epoch" (counting leap seconds)", use
+# below. If you want only "right" time, with values interpreted
+# as seconds since the epoch (counting leap seconds), use
# REDO= right_only
# below. If you want both sets of data available, with leap seconds not
# counted normally, use
@@ -74,131 +139,232 @@ TZLIB= $(LIBDIR)/libtz.a
# below. If you want both sets of data available, with leap seconds counted
# normally, use
# REDO= right_posix
-# below.
-# POSIX mandates that leap seconds not be counted; for compatibility with it,
-# use either "posix_only" or "posix_right".
+# below. POSIX mandates that leap seconds not be counted; for compatibility
+# with it, use "posix_only" or "posix_right". Use POSIX time on systems with
+# leap smearing; this can work better than unsmeared "right" time with
+# applications that are not leap second aware, and is closer to unsmeared
+# "right" time than unsmeared POSIX time is (e.g., 0.5 vs 1.0 s max error).
REDO= posix_right
-# Since "." may not be in PATH...
+# Whether to put an "Expires" line in the leapseconds file.
+# Use EXPIRES_LINE=1 to put the line in, 0 to omit it.
+# The EXPIRES_LINE value matters only if REDO's value contains "right".
+# If you change EXPIRES_LINE, remove the leapseconds file before running "make".
+# zic's support for the Expires line was introduced in tzdb 2020a,
+# and was modified in tzdb 2021b to generate version 4 TZif files.
+# EXPIRES_LINE defaults to 0 for now so that the leapseconds file
+# can be given to pre-2020a zic implementations and so that TZif files
+# built by newer zic implementations can be read by pre-2021b libraries.
+EXPIRES_LINE= 0
+
+# To install data in text form that has all the information of the TZif data,
+# (optionally incorporating leap second information), use
+# TZDATA_TEXT= tzdata.zi leapseconds
+# To install text data without leap second information (e.g., because
+# REDO='posix_only'), use
+# TZDATA_TEXT= tzdata.zi
+# To avoid installing text data, use
+# TZDATA_TEXT=
+
+TZDATA_TEXT= leapseconds tzdata.zi
+
+# For backward-compatibility links for old zone names, use
+# BACKWARD= backward
+# To omit these links, use
+# BACKWARD=
+
+BACKWARD= backward
-YEARISTYPE= ./yearistype
+# If you want out-of-scope and often-wrong data from the file 'backzone',
+# but only for entries listed in the backward-compatibility file zone.tab, use
+# PACKRATDATA= backzone
+# PACKRATLIST= zone.tab
+# If you want all the 'backzone' data, use
+# PACKRATDATA= backzone
+# PACKRATLIST=
+# To omit this data, use
+# PACKRATDATA=
+# PACKRATLIST=
+
+PACKRATDATA=
+PACKRATLIST=
+
+# The name of a locale using the UTF-8 encoding, used during self-tests.
+# The tests are skipped if the name does not appear to work on this system.
+
+UTF8_LOCALE= en_US.utf8
# Non-default libraries needed to link.
-# Add -lintl if you want to use `gettext' on Solaris.
LDLIBS=
-# Add the following to the end of the "CFLAGS=" line as needed.
-# -DHAVE_ADJTIME=0 if `adjtime' does not exist (SVR0?)
-# -DHAVE_GETTEXT=1 if `gettext' works (GNU, Linux, Solaris); also see LDLIBS
-# -DHAVE_INCOMPATIBLE_CTIME_R=1 if your system's time.h declares
-# ctime_r and asctime_r incompatibly with the POSIX standard (Solaris 8).
-# -DHAVE_SETTIMEOFDAY=0 if settimeofday does not exist (SVR0?)
-# -DHAVE_SETTIMEOFDAY=1 if settimeofday has just 1 arg (SVR4)
-# -DHAVE_SETTIMEOFDAY=2 if settimeofday uses 2nd arg (4.3BSD)
-# -DHAVE_SETTIMEOFDAY=3 if settimeofday ignores 2nd arg (4.4BSD)
-# -DHAVE_STDINT_H=1 if you have a pre-C99 compiler with "stdint.h"
+# Add the following to the end of the "CFLAGS=" line as needed to override
+# defaults specified in the source code. "-DFOO" is equivalent to "-DFOO=1".
+# -DDEPRECATE_TWO_DIGIT_YEARS for optional runtime warnings about strftime
+# formats that generate only the last two digits of year numbers
+# -DEPOCH_LOCAL if the 'time' function returns local time not UT
+# -DEPOCH_OFFSET=N if the 'time' function returns a value N greater
+# than what POSIX specifies, assuming local time is UT.
+# For example, N is 252460800 on AmigaOS.
+# -DHAVE_DECL_ASCTIME_R=0 if <time.h> does not declare asctime_r
+# -DHAVE_DECL_ENVIRON if <unistd.h> declares 'environ'
+# -DHAVE_DIRECT_H if mkdir needs <direct.h> (MS-Windows)
+# -DHAVE_GENERIC=0 if _Generic does not work
+# -DHAVE_GETTEXT if 'gettext' works (e.g., GNU/Linux, FreeBSD, Solaris)
+# -DHAVE_INCOMPATIBLE_CTIME_R if your system's time.h declares
+# ctime_r and asctime_r incompatibly with the POSIX standard
+# (Solaris when _POSIX_PTHREAD_SEMANTICS is not defined).
+# -DHAVE_INTTYPES_H if you have a non-C99 compiler with <inttypes.h>
+# -DHAVE_LINK=0 if your system lacks a link function
+# -DHAVE_LOCALTIME_R=0 if your system lacks a localtime_r function
+# -DHAVE_LOCALTIME_RZ=0 if you do not want zdump to use localtime_rz
+# localtime_rz can make zdump significantly faster, but is nonstandard.
+# -DHAVE_MALLOC_ERRNO=0 if malloc etc. do not set errno on failure.
+# -DHAVE_POSIX_DECLS=0 if your system's include files do not declare
+# functions like 'link' or variables like 'tzname' required by POSIX
+# -DHAVE_SNPRINTF=0 if your system lacks the snprintf function
+# -DHAVE_STDBOOL_H if you have a non-C99 compiler with <stdbool.h>
+# -DHAVE_STDINT_H if you have a non-C99 compiler with <stdint.h>
+# -DHAVE_STRFTIME_L if <time.h> declares locale_t and strftime_l
+# -DHAVE_STRDUP=0 if your system lacks the strdup function
+# -DHAVE_STRTOLL=0 if your system lacks the strtoll function
# -DHAVE_SYMLINK=0 if your system lacks the symlink function
-# -DHAVE_SYS_STAT_H=0 if your compiler lacks a "sys/stat.h"
-# -DHAVE_SYS_WAIT_H=0 if your compiler lacks a "sys/wait.h"
-# -DLOCALE_HOME=\"path\" if locales are in "path", not "/usr/lib/locale"
-# -DHAVE_UNISTD_H=0 if your compiler lacks a "unistd.h" (Microsoft C++ 7?)
-# -DHAVE_UTMPX_H=1 if your compiler has a "utmpx.h"
-# -DTZDEFRULESTRING=\",date/time,date/time\" to default to the specified
-# DST transitions if the time zone files cannot be accessed
+# -DHAVE_SYS_STAT_H=0 if your compiler lacks a <sys/stat.h>
+# -DHAVE_TZSET=0 if your system lacks a tzset function
+# -DHAVE_UNISTD_H=0 if your compiler lacks a <unistd.h>
+# -Dlocale_t=XXX if your system uses XXX instead of locale_t
+# -DRESERVE_STD_EXT_IDS if your platform reserves standard identifiers
+# with external linkage, e.g., applications cannot define 'localtime'.
+# -Dssize_t=long on hosts like MS-Windows that lack ssize_t
+# -DSUPPRESS_TZDIR to not prepend TZDIR to file names; this has
+# security implications and is not recommended for general use
+# -DTHREAD_SAFE to make localtime.c thread-safe, as POSIX requires;
+# not needed by the main-program tz code, which is single-threaded.
+# Append other compiler flags as needed, e.g., -pthread on GNU/Linux.
+# -Dtime_tz=\"T\" to use T as the time_t type, rather than the system time_t
+# This is intended for internal use only; it mangles external names.
# -DTZ_DOMAIN=\"foo\" to use "foo" for gettext domain name; default is "tz"
-# -TTZ_DOMAINDIR=\"/path\" to use "/path" for gettext directory;
+# -DTZ_DOMAINDIR=\"/path\" to use "/path" for gettext directory;
# the default is system-supplied, typically "/usr/lib/locale"
-# $(GCC_DEBUG_FLAGS) if you are using GCC and want lots of checking
-# -DNO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU=1
-# if you do not want run time warnings about formats that may cause
-# year 2000 grief
+# -DTZDEFRULESTRING=\",date/time,date/time\" to default to the specified
+# DST transitions if the time zone files cannot be accessed
+# -DUNINIT_TRAP if reading uninitialized storage can cause problems
+# other than simply getting garbage data
+# -DUSE_LTZ=0 to build zdump with the system time zone library
+# Also set TZDOBJS=zdump.o and CHECK_TIME_T_ALTERNATIVES= below.
+# -DZIC_BLOAT_DEFAULT=\"fat\" to default zic's -b option to "fat", and
+# similarly for "slim". Fat TZif files work around incompatibilities
+# and bugs in some TZif readers, notably readers that mishandle 64-bit
+# data in TZif files. Slim TZif files are more efficient and do not
+# work around these incompatibilities and bugs. If not given, the
+# default is "slim".
# -DZIC_MAX_ABBR_LEN_WO_WARN=3
# (or some other number) to set the maximum time zone abbreviation length
# that zic will accept without a warning (the default is 6)
-GCC_DEBUG_FLAGS = -Dlint -g -O -fno-common \
- -Wall -Wcast-qual -Wconversion -Wmissing-prototypes \
- -Wnested-externs -Wpointer-arith -Wshadow \
- -Wtraditional # -Wstrict-prototypes -Wwrite-strings
-#
-# If you want to use System V compatibility code, add
-# -DUSG_COMPAT
-# to the end of the "CFLAGS=" line. This arrange for "timezone" and "daylight"
-# variables to be kept up-to-date by the time conversion functions. Neither
-# "timezone" nor "daylight" is described in X3J11's work.
+# $(GCC_DEBUG_FLAGS) if you are using recent GCC and want lots of checking
+# Select instrumentation via "make GCC_INSTRUMENT='whatever'".
+GCC_INSTRUMENT = \
+ -fsanitize=undefined -fsanitize-address-use-after-scope \
+ -fsanitize-undefined-trap-on-error -fstack-protector
+# Omit -fanalyzer from GCC_DEBUG_FLAGS, as it makes GCC too slow.
+GCC_DEBUG_FLAGS = -DGCC_LINT -g3 -O3 -fno-common \
+ $(GCC_INSTRUMENT) \
+ -Wall -Wextra \
+ -Walloc-size-larger-than=100000 -Warray-bounds=2 \
+ -Wbad-function-cast -Wbidi-chars=any,ucn -Wcast-align=strict -Wdate-time \
+ -Wdeclaration-after-statement -Wdouble-promotion \
+ -Wduplicated-branches -Wduplicated-cond \
+ -Wformat=2 -Wformat-overflow=2 -Wformat-signedness -Wformat-truncation \
+ -Winit-self -Wlogical-op \
+ -Wmissing-declarations -Wmissing-prototypes -Wnested-externs \
+ -Wnull-dereference \
+ -Wold-style-definition -Woverlength-strings -Wpointer-arith \
+ -Wshadow -Wshift-overflow=2 -Wstrict-overflow \
+ -Wstrict-prototypes -Wstringop-overflow=4 \
+ -Wstringop-truncation -Wsuggest-attribute=cold \
+ -Wsuggest-attribute=const -Wsuggest-attribute=format \
+ -Wsuggest-attribute=malloc \
+ -Wsuggest-attribute=noreturn -Wsuggest-attribute=pure \
+ -Wtrampolines -Wundef -Wuninitialized -Wunused-macros -Wuse-after-free=3 \
+ -Wvariadic-macros -Wvla -Wwrite-strings \
+ -Wno-address -Wno-format-nonliteral -Wno-sign-compare \
+ -Wno-type-limits -Wno-unused-parameter
#
# If your system has a "GMT offset" field in its "struct tm"s
# (or if you decide to add such a field in your system's "time.h" file),
# add the name to a define such as
# -DTM_GMTOFF=tm_gmtoff
-# or
-# -DTM_GMTOFF=_tm_gmtoff
-# to the end of the "CFLAGS=" line.
-# Neither tm_gmtoff nor _tm_gmtoff is described in X3J11's work;
-# in its work, use of "tm_gmtoff" is described as non-conforming.
-# Both Linux and BSD have done the equivalent of defining TM_GMTOFF in
-# their recent releases.
-#
-# If your system has a "zone abbreviation" field in its "struct tm"s
-# (or if you decide to add such a field in your system's "time.h" file),
-# add the name to a define such as
+# to the end of the "CFLAGS=" line. If not defined, the code attempts to
+# guess TM_GMTOFF from other macros; define NO_TM_GMTOFF to suppress this.
+# Similarly, if your system has a "zone abbreviation" field, define
# -DTM_ZONE=tm_zone
-# or
-# -DTM_ZONE=_tm_zone
-# to the end of the "CFLAGS=" line.
-# Neither tm_zone nor _tm_zone is described in X3J11's work;
-# in its work, use of "tm_zone" is described as non-conforming.
-# Both UCB and Sun have done the equivalent of defining TM_ZONE in
-# their recent releases.
+# and define NO_TM_ZONE to suppress any guessing. Although these two fields
+# not required by POSIX, a future version of POSIX is planned to require them
+# and they are widely available on GNU/Linux and BSD systems.
+#
+# The next batch of options control support for external variables
+# exported by tzcode. In practice these variables are less useful
+# than TM_GMTOFF and TM_ZONE. However, most of them are standardized.
+# #
+# # To omit or support the external variable "tzname", add one of:
+# # -DHAVE_TZNAME=0 # do not support "tzname"
+# # -DHAVE_TZNAME=1 # support "tzname", which is defined by system library
+# # -DHAVE_TZNAME=2 # support and define "tzname"
+# # to the "CFLAGS=" line. "tzname" is required by POSIX 1988 and later.
+# # If not defined, the code attempts to guess HAVE_TZNAME from other macros.
+# # Warning: unless time_tz is also defined, HAVE_TZNAME=1 can cause
+# # crashes when combined with some platforms' standard libraries,
+# # presumably due to memory allocation issues.
+# #
+# # To omit or support the external variables "timezone" and "daylight", add
+# # -DUSG_COMPAT=0 # do not support
+# # -DUSG_COMPAT=1 # support, and variables are defined by system library
+# # -DUSG_COMPAT=2 # support and define variables
+# # to the "CFLAGS=" line; "timezone" and "daylight" are inspired by
+# # Unix Systems Group code and are required by POSIX 2008 (with XSI) and later.
+# # If not defined, the code attempts to guess USG_COMPAT from other macros.
+# #
+# # To support the external variable "altzone", add
+# # -DALTZONE=0 # do not support
+# # -DALTZONE=1 # support "altzone", which is defined by system library
+# # -DALTZONE=2 # support and define "altzone"
+# # to the end of the "CFLAGS=" line; although "altzone" appeared in
+# # System V Release 3.1 it has not been standardized.
+# # If not defined, the code attempts to guess ALTZONE from other macros.
#
# If you want functions that were inspired by early versions of X3J11's work,
# add
# -DSTD_INSPIRED
# to the end of the "CFLAGS=" line. This arranges for the functions
-# "tzsetwall", "offtime", "timelocal", "timegm", "timeoff",
+# "offtime", "timelocal", "timegm", "timeoff",
# "posix2time", and "time2posix" to be added to the time conversion library.
-# "tzsetwall" is like "tzset" except that it arranges for local wall clock
-# time (rather than the time specified in the TZ environment variable)
-# to be used.
# "offtime" is like "gmtime" except that it accepts a second (long) argument
# that gives an offset to add to the time_t when converting it.
# "timelocal" is equivalent to "mktime".
# "timegm" is like "timelocal" except that it turns a struct tm into
-# a time_t using UTC (rather than local time as "timelocal" does).
+# a time_t using UT (rather than local time as "timelocal" does).
# "timeoff" is like "timegm" except that it accepts a second (long) argument
# that gives an offset to use when converting to a time_t.
# "posix2time" and "time2posix" are described in an included manual page.
# X3J11's work does not describe any of these functions.
-# Sun has provided "tzsetwall", "timelocal", and "timegm" in SunOS 4.0.
# These functions may well disappear in future releases of the time
# conversion package.
#
-# If you want Source Code Control System ID's left out of object modules, add
-# -DNOID
-# to the end of the "CFLAGS=" line.
-#
-# If you'll never want to handle solar-time-based time zones, add
-# -DNOSOLAR
-# to the end of the "CFLAGS=" line
-# (and comment out the "SDATA=" line below).
-# This reduces (slightly) the run-time data-space requirements of
-# the time conversion functions; it may reduce the acceptability of your system
-# to folks in oil- and cash-rich places.
+# If you don't want functions that were inspired by NetBSD, add
+# -DNETBSD_INSPIRED=0
+# to the end of the "CFLAGS=" line. Otherwise, the functions
+# "localtime_rz", "mktime_z", "tzalloc", and "tzfree" are added to the
+# time library, and if STD_INSPIRED is also defined the functions
+# "posix2time_z" and "time2posix_z" are added as well.
+# The functions ending in "_z" (or "_rz") are like their unsuffixed
+# (or suffixed-by-"_r") counterparts, except with an extra first
+# argument of opaque type timezone_t that specifies the timezone.
+# "tzalloc" allocates a timezone_t value, and "tzfree" frees it.
#
# If you want to allocate state structures in localtime, add
# -DALL_STATE
# to the end of the "CFLAGS=" line. Storage is obtained by calling malloc.
#
-# If you want an "altzone" variable (a la System V Release 3.1), add
-# -DALTZONE
-# to the end of the "CFLAGS=" line.
-# This variable is not described in X3J11's work.
-#
-# If you want a "gtime" function (a la MACH), add
-# -DCMUCS
-# to the end of the "CFLAGS=" line
-# This function is not described in X3J11's work.
-#
# NIST-PCTS:151-2, Version 1.4, (1993-12-03) is a test suite put
# out by the National Institute of Standards and Technology
# which claims to test C and Posix conformance. If you want to pass PCTS, add
@@ -208,122 +374,318 @@ GCC_DEBUG_FLAGS = -Dlint -g -O -fno-common \
# If you want strict compliance with XPG4 as of 1994-04-09, add
# -DXPG4_1994_04_09
# to the end of the "CFLAGS=" line. This causes "strftime" to always return
-# 53 as a week number (rather than 52 or 53) for those days in January that
-# before the first Monday in January when a "%V" format is used and January 1
+# 53 as a week number (rather than 52 or 53) for January days before
+# January's first Monday when a "%V" format is used and January 1
# falls on a Friday, Saturday, or Sunday.
CFLAGS=
-# If you want zic's -s option used when installing, uncomment the next line
-# ZFLAGS= -s
+# Linker flags. Default to $(LFLAGS) for backwards compatibility
+# to release 2012h and earlier.
+
+LDFLAGS= $(LFLAGS)
+
+# For leap seconds, this Makefile uses LEAPSECONDS='-L leapseconds' in
+# submake command lines. The default is no leap seconds.
+
+LEAPSECONDS=
+
+# The zic command and its arguments.
zic= ./zic
ZIC= $(zic) $(ZFLAGS)
-# The name of a Posix-compliant `awk' on your system.
-AWK= nawk
+# To shrink the size of installed TZif files,
+# append "-r @N" to omit data before N-seconds-after-the-Epoch.
+# To grow the files and work around older application bugs, append "-b fat";
+# see ZIC_BLOAT_DEFAULT above.
+# See the zic man page for more about -b and -r.
+ZFLAGS=
+
+# How to use zic to install TZif files.
+
+ZIC_INSTALL= $(ZIC) -d '$(DESTDIR)$(TZDIR)' $(LEAPSECONDS)
+
+# The name of a Posix-compliant 'awk' on your system.
+# mawk 1.3.3 and Solaris 10 /usr/bin/awk do not work.
+# Also, it is better (though not essential) if 'awk' supports UTF-8,
+# and unfortunately mawk and busybox awk do not support UTF-8.
+# Try AWK=gawk or AWK=nawk if your awk has the abovementioned problems.
+AWK= awk
+
+# The full path name of a Posix-compliant shell, preferably one that supports
+# the Korn shell's 'select' statement as an extension.
+# These days, Bash is the most popular.
+# It should be OK to set this to /bin/sh, on platforms where /bin/sh
+# lacks 'select' or doesn't completely conform to Posix, but /bin/bash
+# is typically nicer if it works.
+KSHELL= /bin/bash
+
+# Name of curl <https://curl.haxx.se/>, used for HTML validation.
+CURL= curl
+
+# Name of GNU Privacy Guard <https://gnupg.org/>, used to sign distributions.
+GPG= gpg
+
+# This expensive test requires USE_LTZ.
+# To suppress it, define this macro to be empty.
+CHECK_TIME_T_ALTERNATIVES = check_time_t_alternatives
+
+# SAFE_CHAR is a regular expression that matches a safe character.
+# Some parts of this distribution are limited to safe characters;
+# others can use any UTF-8 character.
+# For now, the safe characters are a safe subset of ASCII.
+# The caller must set the shell variable 'sharp' to the character '#',
+# since Makefile macros cannot contain '#'.
+# TAB_CHAR is a single tab character, in single quotes.
+TAB_CHAR= ' '
+SAFE_CHARSET1= $(TAB_CHAR)' !\"'$$sharp'$$%&'\''()*+,./0123456789:;<=>?@'
+SAFE_CHARSET2= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\^_`'
+SAFE_CHARSET3= 'abcdefghijklmnopqrstuvwxyz{|}~'
+SAFE_CHARSET= $(SAFE_CHARSET1)$(SAFE_CHARSET2)$(SAFE_CHARSET3)
+SAFE_CHAR= '[]'$(SAFE_CHARSET)'-]'
+
+# These characters are Latin-1, and so are likely to be displayable
+# even in editors with limited character sets.
+UNUSUAL_OK_LATIN_1 = «°±»½¾×
+# This IPA symbol is represented in Unicode as the composition of
+# U+0075 and U+032F, and U+032F is not considered alphabetic by some
+# grep implementations that do not grok composition.
+UNUSUAL_OK_IPA = u̯
+# Non-ASCII non-letters that OK_CHAR allows, as these characters are
+# useful in commentary.
+UNUSUAL_OK_CHARSET= $(UNUSUAL_OK_LATIN_1)$(UNUSUAL_OK_IPA)
-# The path where SGML DTDs are kept.
-SGML_SEARCH_PATH= $(TOPDIR)/share/doc/sgml-lib/REC-html401-19991224/
+# Put this in a bracket expression to match spaces.
+s = [:space:]
-# The catalog file(s) to use when validating.
-SGML_CATALOG_FILES= HTML4.cat
+# OK_CHAR matches any character allowed in the distributed files.
+# This is the same as SAFE_CHAR, except that UNUSUAL_OK_CHARSET and
+# multibyte letters are also allowed so that commentary can contain a
+# few safe symbols and people's names and can quote non-English sources.
+# Other non-letters are limited to ASCII renderings for the
+# convenience of maintainers using XEmacs 21.5.34, which by default
+# mishandles Unicode characters U+0100 and greater.
+OK_CHAR= '[][:alpha:]$(UNUSUAL_OK_CHARSET)'$(SAFE_CHARSET)'-]'
-# The name, arguments and environment of a program to validate your web pages.
-# See <http://www.jclark.com/sp/> for a validator, and
-# <http://validator.w3.org/source/> for a validation library.
-VALIDATE = nsgmls
-VALIDATE_FLAGS = -s -B -wall -wno-unused-param
-VALIDATE_ENV = \
- SGML_CATALOG_FILES=$(SGML_CATALOG_FILES) \
- SGML_SEARCH_PATH=$(SGML_SEARCH_PATH) \
- SP_CHARSET_FIXED=YES \
- SP_ENCODING=UTF-8
+# SAFE_LINE matches a line of safe characters.
+# SAFE_SHARP_LINE is similar, except any OK character can follow '#';
+# this is so that comments can contain non-ASCII characters.
+# OK_LINE matches a line of OK characters.
+SAFE_LINE= '^'$(SAFE_CHAR)'*$$'
+SAFE_SHARP_LINE='^'$(SAFE_CHAR)'*('$$sharp$(OK_CHAR)'*)?$$'
+OK_LINE= '^'$(OK_CHAR)'*$$'
+
+# Flags to give 'tar' when making a distribution.
+# Try to use flags appropriate for GNU tar.
+GNUTARFLAGS= --format=pax --pax-option='delete=atime,delete=ctime' \
+ --numeric-owner --owner=0 --group=0 \
+ --mode=go+u,go-w --sort=name
+TARFLAGS= `if tar $(GNUTARFLAGS) --version >/dev/null 2>&1; \
+ then echo $(GNUTARFLAGS); \
+ else :; \
+ fi`
+
+# Flags to give 'gzip' when making a distribution.
+GZIPFLAGS= -9n
###############################################################################
+#MAKE= make
+
cc= cc
-CC= $(cc) -DTZDIR=\"$(TZDIR)\"
+CC= $(cc) -DTZDIR='"$(TZDIR)"'
+
+AR= ar
-TZCSRCS= zic.c localtime.c asctime.c scheck.c ialloc.c
-TZCOBJS= zic.o localtime.o asctime.o scheck.o ialloc.o
-TZDSRCS= zdump.c localtime.c ialloc.c
-TZDOBJS= zdump.o localtime.o ialloc.o
-DATESRCS= date.c localtime.c strftime.c asctime.c
+# ':' on typical hosts; 'ranlib' on the ancient hosts that still need ranlib.
+RANLIB= :
+
+TZCOBJS= zic.o
+TZDOBJS= zdump.o localtime.o asctime.o strftime.o
DATEOBJS= date.o localtime.o strftime.o asctime.o
-LIBSRCS= localtime.c asctime.c difftime.c
-LIBOBJS= localtime.o asctime.o difftime.o
+LIBSRCS= localtime.c asctime.c difftime.c strftime.c
+LIBOBJS= localtime.o asctime.o difftime.o strftime.o
HEADERS= tzfile.h private.h
-NONLIBSRCS= zic.c zdump.c scheck.c ialloc.c
-NEWUCBSRCS= date.c strftime.c
-SOURCES= $(HEADERS) $(LIBSRCS) $(NONLIBSRCS) $(NEWUCBSRCS) tzselect.ksh
+NONLIBSRCS= zic.c zdump.c
+NEWUCBSRCS= date.c
+SOURCES= $(HEADERS) $(LIBSRCS) $(NONLIBSRCS) $(NEWUCBSRCS) \
+ tzselect.ksh workman.sh
MANS= newctime.3 newstrftime.3 newtzset.3 time2posix.3 \
tzfile.5 tzselect.8 zic.8 zdump.8
-DOCS= README Theory $(MANS) date.1 Makefile
+MANTXTS= newctime.3.txt newstrftime.3.txt newtzset.3.txt \
+ time2posix.3.txt \
+ tzfile.5.txt tzselect.8.txt zic.8.txt zdump.8.txt \
+ date.1.txt
+COMMON= calendars CONTRIBUTING LICENSE Makefile \
+ NEWS README SECURITY theory.html version
+WEB_PAGES= tz-art.html tz-how-to.html tz-link.html
+CHECK_WEB_PAGES=check_theory.html check_tz-art.html \
+ check_tz-how-to.html check_tz-link.html
+DOCS= $(MANS) date.1 $(MANTXTS) $(WEB_PAGES)
PRIMARY_YDATA= africa antarctica asia australasia \
europe northamerica southamerica
-YDATA= $(PRIMARY_YDATA) pacificnew etcetera backward
-NDATA= systemv factory
-SDATA= solar87 solar88 solar89
-TDATA= $(YDATA) $(NDATA) $(SDATA)
-TABDATA= iso3166.tab zone.tab
-DATA= $(YDATA) $(NDATA) $(SDATA) $(TABDATA) leapseconds yearistype.sh
-WEB_PAGES= tz-art.htm tz-link.htm
-MISC= usno1988 usno1989 usno1989a usno1995 usno1997 usno1998 \
- itca.jpg $(WEB_PAGES) checktab.awk workman.sh \
- zoneinfo2tdf.pl
-ENCHILADA= $(DOCS) $(SOURCES) $(DATA) $(MISC)
+YDATA= $(PRIMARY_YDATA) etcetera
+NDATA= factory
+TDATA_TO_CHECK= $(YDATA) $(NDATA) backward
+TDATA= $(YDATA) $(NDATA) $(BACKWARD)
+ZONETABLES= zone1970.tab zone.tab
+TABDATA= iso3166.tab $(TZDATA_TEXT) $(ZONETABLES)
+LEAP_DEPS= leapseconds.awk leap-seconds.list
+TZDATA_ZI_DEPS= ziguard.awk zishrink.awk version $(TDATA) \
+ $(PACKRATDATA) $(PACKRATLIST)
+DSTDATA_ZI_DEPS= ziguard.awk $(TDATA) $(PACKRATDATA) $(PACKRATLIST)
+DATA= $(TDATA_TO_CHECK) backzone iso3166.tab leap-seconds.list \
+ leapseconds $(ZONETABLES)
+AWK_SCRIPTS= checklinks.awk checktab.awk leapseconds.awk \
+ ziguard.awk zishrink.awk
+MISC= $(AWK_SCRIPTS)
+TZS_YEAR= 2050
+TZS_CUTOFF_FLAG= -c $(TZS_YEAR)
+TZS= to$(TZS_YEAR).tzs
+TZS_NEW= to$(TZS_YEAR)new.tzs
+TZS_DEPS= $(YDATA) asctime.c localtime.c \
+ private.h tzfile.h zdump.c zic.c
+TZDATA_DIST = $(COMMON) $(DATA) $(MISC)
+# EIGHT_YARDS is just a yard short of the whole ENCHILADA.
+EIGHT_YARDS = $(TZDATA_DIST) $(DOCS) $(SOURCES) tzdata.zi
+ENCHILADA = $(EIGHT_YARDS) $(TZS)
+
+# Consult these files when deciding whether to rebuild the 'version' file.
+# This list is not the same as the output of 'git ls-files', since
+# .gitignore is not distributed.
+VERSION_DEPS= \
+ calendars CONTRIBUTING LICENSE Makefile NEWS README SECURITY \
+ africa antarctica asctime.c asia australasia \
+ backward backzone \
+ checklinks.awk checktab.awk \
+ date.1 date.c difftime.c \
+ etcetera europe factory iso3166.tab \
+ leap-seconds.list leapseconds.awk localtime.c \
+ newctime.3 newstrftime.3 newtzset.3 northamerica \
+ private.h southamerica strftime.c theory.html \
+ time2posix.3 tz-art.html tz-how-to.html tz-link.html \
+ tzfile.5 tzfile.h tzselect.8 tzselect.ksh \
+ workman.sh zdump.8 zdump.c zic.8 zic.c \
+ ziguard.awk zishrink.awk \
+ zone.tab zone1970.tab
# And for the benefit of csh users on systems that assume the user
# shell should be used to handle commands in Makefiles. . .
SHELL= /bin/sh
-all: tzselect zic zdump $(LIBOBJS)
-
-ALL: all date
-
-install: all $(DATA) $(REDO) $(TZLIB) $(MANS) $(TABDATA)
- $(ZIC) -y $(YEARISTYPE) \
- -d $(TZDIR) -l $(LOCALTIME) -p $(POSIXRULES)
- -rm -f $(TZDIR)/iso3166.tab $(TZDIR)/zone.tab
- cp iso3166.tab zone.tab $(TZDIR)/.
- -mkdir $(TOPDIR) $(ETCDIR)
- cp tzselect zic zdump $(ETCDIR)/.
- -mkdir $(TOPDIR) $(MANDIR) \
- $(MANDIR)/man3 $(MANDIR)/man5 $(MANDIR)/man8
- -rm -f $(MANDIR)/man3/newctime.3 \
- $(MANDIR)/man3/newtzset.3 \
- $(MANDIR)/man5/tzfile.5 \
- $(MANDIR)/man8/tzselect.8 \
- $(MANDIR)/man8/zdump.8 \
- $(MANDIR)/man8/zic.8
- cp newctime.3 newtzset.3 $(MANDIR)/man3/.
- cp tzfile.5 $(MANDIR)/man5/.
- cp tzselect.8 zdump.8 zic.8 $(MANDIR)/man8/.
+all: tzselect zic zdump libtz.a $(TABDATA) \
+ vanguard.zi main.zi rearguard.zi
+
+ALL: all date $(ENCHILADA)
+
+install: all $(DATA) $(REDO) $(MANS)
+ mkdir -p '$(DESTDIR)$(BINDIR)' \
+ '$(DESTDIR)$(ZDUMPDIR)' '$(DESTDIR)$(ZICDIR)' \
+ '$(DESTDIR)$(LIBDIR)' \
+ '$(DESTDIR)$(MANDIR)/man3' '$(DESTDIR)$(MANDIR)/man5' \
+ '$(DESTDIR)$(MANDIR)/man8'
+ $(ZIC_INSTALL) -l $(LOCALTIME) \
+ `case '$(POSIXRULES)' in ?*) echo '-p';; esac \
+ ` $(POSIXRULES) \
+ -t '$(DESTDIR)$(TZDEFAULT)'
+ cp -f $(TABDATA) '$(DESTDIR)$(TZDIR)/.'
+ cp tzselect '$(DESTDIR)$(BINDIR)/.'
+ cp zdump '$(DESTDIR)$(ZDUMPDIR)/.'
+ cp zic '$(DESTDIR)$(ZICDIR)/.'
+ cp libtz.a '$(DESTDIR)$(LIBDIR)/.'
+ $(RANLIB) '$(DESTDIR)$(LIBDIR)/libtz.a'
+ cp -f newctime.3 newtzset.3 '$(DESTDIR)$(MANDIR)/man3/.'
+ cp -f tzfile.5 '$(DESTDIR)$(MANDIR)/man5/.'
+ cp -f tzselect.8 zdump.8 zic.8 '$(DESTDIR)$(MANDIR)/man8/.'
INSTALL: ALL install date.1
- -mkdir $(TOPDIR) $(BINDIR)
- cp date $(BINDIR)/.
- -mkdir $(TOPDIR) $(MANDIR) $(MANDIR)/man1
- -rm -f $(MANDIR)/man1/date.1
- cp date.1 $(MANDIR)/man1/.
+ mkdir -p '$(DESTDIR)$(BINDIR)' '$(DESTDIR)$(MANDIR)/man1'
+ cp date '$(DESTDIR)$(BINDIR)/.'
+ cp -f date.1 '$(DESTDIR)$(MANDIR)/man1/.'
+
+# Calculate version number from git, if available.
+# Otherwise, use $(VERSION) unless it is "unknown" and there is already
+# a 'version' file, in which case reuse the existing 'version' contents
+# and append "-dirty" if the contents do not already end in "-dirty".
+version: $(VERSION_DEPS)
+ { (type git) >/dev/null 2>&1 && \
+ V=`git describe --match '[0-9][0-9][0-9][0-9][a-z]*' \
+ --abbrev=7 --dirty` || \
+ if test '$(VERSION)' = unknown && V=`cat $@`; then \
+ case $$V in *-dirty);; *) V=$$V-dirty;; esac; \
+ else \
+ V='$(VERSION)'; \
+ fi; } && \
+ printf '%s\n' "$$V" >$@.out
+ mv $@.out $@
+
+# These files can be tailored by setting BACKWARD, PACKRATDATA, PACKRATLIST.
+vanguard.zi main.zi rearguard.zi: $(DSTDATA_ZI_DEPS)
+ $(AWK) \
+ -v DATAFORM=`expr $@ : '\(.*\).zi'` \
+ -v PACKRATDATA='$(PACKRATDATA)' \
+ -v PACKRATLIST='$(PACKRATLIST)' \
+ -f ziguard.awk \
+ $(TDATA) $(PACKRATDATA) >$@.out
+ mv $@.out $@
+# This file has a version comment that attempts to capture any tailoring
+# via BACKWARD, DATAFORM, PACKRATDATA, PACKRATLIST, and REDO.
+tzdata.zi: $(DATAFORM).zi version zishrink.awk
+ version=`sed 1q version` && \
+ LC_ALL=C $(AWK) \
+ -v dataform='$(DATAFORM)' \
+ -v deps='$(DSTDATA_ZI_DEPS) zishrink.awk' \
+ -v redo='$(REDO)' \
+ -v version="$$version" \
+ -f zishrink.awk \
+ $(DATAFORM).zi >$@.out
+ mv $@.out $@
+
+version.h: version
+ VERSION=`cat version` && printf '%s\n' \
+ 'static char const PKGVERSION[]="($(PACKAGE)) ";' \
+ "static char const TZVERSION[]=\"$$VERSION\";" \
+ 'static char const REPORT_BUGS_TO[]="$(BUGEMAIL)";' \
+ >$@.out
+ mv $@.out $@
zdump: $(TZDOBJS)
- $(CC) $(CFLAGS) $(LFLAGS) $(TZDOBJS) $(LDLIBS) -o $@
+ $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $(TZDOBJS) $(LDLIBS)
+
+zic: $(TZCOBJS)
+ $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $(TZCOBJS) $(LDLIBS)
+
+leapseconds: $(LEAP_DEPS)
+ $(AWK) -v EXPIRES_LINE=$(EXPIRES_LINE) \
+ -f leapseconds.awk leap-seconds.list >$@.out
+ mv $@.out $@
-zic: $(TZCOBJS) yearistype
- $(CC) $(CFLAGS) $(LFLAGS) $(TZCOBJS) $(LDLIBS) -o $@
+# Arguments to pass to submakes of install_data.
+# They can be overridden by later submake arguments.
+INSTALLARGS = \
+ BACKWARD='$(BACKWARD)' \
+ DESTDIR='$(DESTDIR)' \
+ LEAPSECONDS='$(LEAPSECONDS)' \
+ PACKRATDATA='$(PACKRATDATA)' \
+ PACKRATLIST='$(PACKRATLIST)' \
+ TZDEFAULT='$(TZDEFAULT)' \
+ TZDIR='$(TZDIR)' \
+ ZIC='$(ZIC)'
-yearistype: yearistype.sh
- cp yearistype.sh yearistype
- chmod +x yearistype
+INSTALL_DATA_DEPS = zic leapseconds tzdata.zi
-posix_only: zic $(TDATA)
- $(ZIC) -y $(YEARISTYPE) -d $(TZDIR) -L /dev/null $(TDATA)
+# 'make install_data' installs one set of TZif files.
+install_data: $(INSTALL_DATA_DEPS)
+ $(ZIC_INSTALL) tzdata.zi
-right_only: zic leapseconds $(TDATA)
- $(ZIC) -y $(YEARISTYPE) -d $(TZDIR) -L leapseconds $(TDATA)
+posix_only: $(INSTALL_DATA_DEPS)
+ $(MAKE) $(INSTALLARGS) LEAPSECONDS= install_data
+
+right_only: $(INSTALL_DATA_DEPS)
+ $(MAKE) $(INSTALLARGS) LEAPSECONDS='-L leapseconds' \
+ install_data
# In earlier versions of this makefile, the other two directories were
# subdirectories of $(TZDIR). However, this led to configuration errors.
@@ -334,88 +696,530 @@ right_only: zic leapseconds $(TDATA)
# Therefore, the other two directories are now siblings of $(TZDIR).
# You must replace all of $(TZDIR) to switch from not using leap seconds
# to using them, or vice versa.
-other_two: zic leapseconds $(TDATA)
- $(ZIC) -y $(YEARISTYPE) -d $(TZDIR)-posix -L /dev/null $(TDATA)
- $(ZIC) -y $(YEARISTYPE) \
- -d $(TZDIR)-leaps -L leapseconds $(TDATA)
-
-posix_right: posix_only other_two
+right_posix: right_only
+ rm -fr '$(DESTDIR)$(TZDIR)-leaps'
+ ln -s '$(TZDIR_BASENAME)' '$(DESTDIR)$(TZDIR)-leaps' || \
+ $(MAKE) $(INSTALLARGS) TZDIR='$(TZDIR)-leaps' right_only
+ $(MAKE) $(INSTALLARGS) TZDIR='$(TZDIR)-posix' posix_only
-right_posix: right_only other_two
+posix_right: posix_only
+ rm -fr '$(DESTDIR)$(TZDIR)-posix'
+ ln -s '$(TZDIR_BASENAME)' '$(DESTDIR)$(TZDIR)-posix' || \
+ $(MAKE) $(INSTALLARGS) TZDIR='$(TZDIR)-posix' posix_only
+ $(MAKE) $(INSTALLARGS) TZDIR='$(TZDIR)-leaps' right_only
zones: $(REDO)
-$(TZLIB): $(LIBOBJS)
- -mkdir $(TOPDIR) $(LIBDIR)
- ar ru $@ $(LIBOBJS)
- if [ -x /usr/ucb/ranlib -o -x /usr/bin/ranlib ] ; \
- then ranlib $@ ; fi
+# dummy.zd is not a real file; it is mentioned here only so that the
+# top-level 'make' does not have a syntax error.
+ZDS = dummy.zd
+# Rule used only by submakes invoked by the $(TZS_NEW) rule.
+# It is separate so that GNU 'make -j' can run instances in parallel.
+$(ZDS): zdump
+ ./zdump -i $(TZS_CUTOFF_FLAG) '$(wd)/'$$(expr $@ : '\(.*\).zd') \
+ >$@
+
+TZS_NEW_DEPS = tzdata.zi zdump zic
+$(TZS_NEW): $(TZS_NEW_DEPS)
+ rm -fr tzs$(TZS_YEAR).dir
+ mkdir tzs$(TZS_YEAR).dir
+ $(zic) -d tzs$(TZS_YEAR).dir tzdata.zi
+ $(AWK) '/^L/{print "Link\t" $$2 "\t" $$3}' \
+ tzdata.zi | LC_ALL=C sort >$@.out
+ wd=`pwd` && \
+ x=`$(AWK) '/^Z/{print "tzs$(TZS_YEAR).dir/" $$2 ".zd"}' \
+ tzdata.zi \
+ | LC_ALL=C sort -t . -k 2,2` && \
+ set x $$x && \
+ shift && \
+ ZDS=$$* && \
+ $(MAKE) wd="$$wd" TZS_CUTOFF_FLAG="$(TZS_CUTOFF_FLAG)" \
+ ZDS="$$ZDS" $$ZDS && \
+ sed 's,^TZ=".*\.dir/,TZ=",' $$ZDS >>$@.out
+ rm -fr tzs$(TZS_YEAR).dir
+ mv $@.out $@
+
+# If $(TZS) exists but 'make check_tzs' fails, a maintainer should inspect the
+# failed output and fix the inconsistency, perhaps by running 'make force_tzs'.
+$(TZS):
+ touch $@
+
+force_tzs: $(TZS_NEW)
+ cp $(TZS_NEW) $(TZS)
+
+libtz.a: $(LIBOBJS)
+ rm -f $@
+ $(AR) -rc $@ $(LIBOBJS)
+ $(RANLIB) $@
date: $(DATEOBJS)
- $(CC) $(CFLAGS) date.o localtime.o asctime.o strftime.o \
- $(LDLIBS) -lc -o $@
+ $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $(DATEOBJS) $(LDLIBS)
-tzselect: tzselect.ksh
- sed \
- -e 's|AWK=[^}]*|AWK=$(AWK)|g' \
+tzselect: tzselect.ksh version
+ VERSION=`cat version` && sed \
+ -e 's|#!/bin/bash|#!$(KSHELL)|g' \
+ -e 's|AWK=[^}]*|AWK='\''$(AWK)'\''|g' \
+ -e 's|\(PKGVERSION\)=.*|\1='\''($(PACKAGE)) '\''|' \
+ -e 's|\(REPORT_BUGS_TO\)=.*|\1=$(BUGEMAIL)|' \
-e 's|TZDIR=[^}]*|TZDIR=$(TZDIR)|' \
- <$? >$@
- chmod +x $@
+ -e 's|\(TZVERSION\)=.*|\1='"$$VERSION"'|' \
+ <$@.ksh >$@.out
+ chmod +x $@.out
+ mv $@.out $@
+
+check: check_character_set check_white_space check_links \
+ check_name_lengths check_slashed_abbrs check_sorted \
+ check_tables check_web check_ziguard check_zishrink check_tzs
+
+check_character_set: $(ENCHILADA)
+ test ! '$(UTF8_LOCALE)' || \
+ ! printf 'A\304\200B\n' | \
+ LC_ALL='$(UTF8_LOCALE)' grep -q '^A.B$$' >/dev/null 2>&1 || { \
+ LC_ALL='$(UTF8_LOCALE)' && export LC_ALL && \
+ sharp='#' && \
+ ! grep -Env $(SAFE_LINE) $(MANS) date.1 $(MANTXTS) \
+ $(MISC) $(SOURCES) $(WEB_PAGES) \
+ CONTRIBUTING LICENSE README SECURITY \
+ version tzdata.zi && \
+ ! grep -Env $(SAFE_LINE)'|^UNUSUAL_OK_'$(OK_CHAR)'*$$' \
+ Makefile && \
+ ! grep -Env $(SAFE_SHARP_LINE) $(TDATA_TO_CHECK) backzone \
+ leapseconds zone.tab && \
+ ! grep -Env $(OK_LINE) $(ENCHILADA); \
+ }
+ touch $@
+
+check_white_space: $(ENCHILADA)
+ patfmt=' \t|[\f\r\v]' && pat=`printf "$$patfmt\\n"` && \
+ ! grep -En "$$pat" \
+ $$(ls $(ENCHILADA) | grep -Fvx leap-seconds.list)
+ ! grep -n '[$s]$$' \
+ $$(ls $(ENCHILADA) | grep -Fvx leap-seconds.list)
+ touch $@
+
+PRECEDES_FILE_NAME = ^(Zone|Link[$s]+[^$s]+)[$s]+
+FILE_NAME_COMPONENT_TOO_LONG = $(PRECEDES_FILE_NAME)[^$s]*[^/$s]{15}
+
+check_name_lengths: $(TDATA_TO_CHECK) backzone
+ ! grep -En '$(FILE_NAME_COMPONENT_TOO_LONG)' \
+ $(TDATA_TO_CHECK) backzone
+ touch $@
+
+PRECEDES_STDOFF = ^(Zone[$s]+[^$s]+)?[$s]+
+STDOFF = [-+]?[0-9:.]+
+RULELESS_SAVE = (-|$(STDOFF)[sd]?)
+RULELESS_SLASHED_ABBRS = \
+ $(PRECEDES_STDOFF)$(STDOFF)[$s]+$(RULELESS_SAVE)[$s]+[^$s]*/
+
+check_slashed_abbrs: $(TDATA_TO_CHECK)
+ ! grep -En '$(RULELESS_SLASHED_ABBRS)' $(TDATA_TO_CHECK)
+ touch $@
-check: check_tables check_web
+CHECK_CC_LIST = { n = split($$1,a,/,/); for (i=2; i<=n; i++) print a[1], a[i]; }
-check_tables: checktab.awk $(PRIMARY_YDATA)
- $(AWK) -f checktab.awk $(PRIMARY_YDATA)
+check_sorted: backward backzone iso3166.tab zone.tab zone1970.tab
+ $(AWK) '/^Link/ {print $$3}' backward | LC_ALL=C sort -cu
+ $(AWK) '/^Zone/ {print $$2}' backzone | LC_ALL=C sort -cu
+ touch $@
-check_web: $(WEB_PAGES)
- $(VALIDATE_ENV) $(VALIDATE) $(VALIDATE_FLAGS) $(WEB_PAGES)
+check_links: checklinks.awk $(TDATA_TO_CHECK) tzdata.zi
+ $(AWK) -f checklinks.awk $(TDATA_TO_CHECK)
+ $(AWK) -f checklinks.awk tzdata.zi
+ touch $@
-clean:
- rm -f core *.o *.out tzselect zdump zic yearistype date
+check_tables: checktab.awk $(YDATA) backward $(ZONETABLES)
+ for tab in $(ZONETABLES); do \
+ test "$$tab" = zone.tab && links='$(BACKWARD)' || links=''; \
+ $(AWK) -f checktab.awk -v zone_table=$$tab $(YDATA) $$links \
+ || exit; \
+ done
+ touch $@
+
+check_tzs: $(TZS) $(TZS_NEW)
+ if test -s $(TZS); then \
+ diff -u $(TZS) $(TZS_NEW); \
+ else \
+ cp $(TZS_NEW) $(TZS); \
+ fi
+ touch $@
+
+check_web: $(CHECK_WEB_PAGES)
+check_theory.html: theory.html
+check_tz-art.html: tz-art.html
+check_tz-how-to.html: tz-how-to.html
+check_tz-link.html: tz-link.html
+check_theory.html check_tz-art.html check_tz-how-to.html check_tz-link.html:
+ $(CURL) -sS --url https://validator.w3.org/nu/ -F out=gnu \
+ -F file=@$$(expr $@ : 'check_\(.*\)') -o $@.out && \
+ test ! -s $@.out || { cat $@.out; exit 1; }
+ mv $@.out $@
+
+check_ziguard: rearguard.zi vanguard.zi ziguard.awk
+ $(AWK) -v DATAFORM=rearguard -f ziguard.awk vanguard.zi | \
+ diff -u rearguard.zi -
+ $(AWK) -v DATAFORM=vanguard -f ziguard.awk rearguard.zi | \
+ diff -u vanguard.zi -
+ touch $@
+
+# Check that zishrink.awk does not alter the data, and that ziguard.awk
+# preserves main-format data.
+check_zishrink: check_zishrink_posix check_zishrink_right
+check_zishrink_posix check_zishrink_right: \
+ zic leapseconds $(PACKRATDATA) $(PACKRATLIST) \
+ $(TDATA) $(DATAFORM).zi tzdata.zi
+ rm -fr $@.dir $@-t.dir $@-shrunk.dir
+ mkdir $@.dir $@-t.dir $@-shrunk.dir
+ case $@ in \
+ *_right) leap='-L leapseconds';; \
+ *) leap=;; \
+ esac && \
+ $(ZIC) $$leap -d $@.dir $(DATAFORM).zi && \
+ $(ZIC) $$leap -d $@-shrunk.dir tzdata.zi && \
+ case $(DATAFORM),$(PACKRATLIST) in \
+ main,) \
+ $(ZIC) $$leap -d $@-t.dir $(TDATA) && \
+ $(AWK) '/^Rule/' $(TDATA) | \
+ $(ZIC) $$leap -d $@-t.dir - $(PACKRATDATA) && \
+ diff -r $@.dir $@-t.dir;; \
+ esac
+ diff -r $@.dir $@-shrunk.dir
+ rm -fr $@.dir $@-t.dir $@-shrunk.dir
+ touch $@
+
+clean_misc:
+ rm -fr check_*.dir
+ rm -f *.o *.out $(TIME_T_ALTERNATIVES) \
+ check_* core typecheck_* \
+ date tzselect version.h zdump zic libtz.a
+clean: clean_misc
+ rm -fr *.dir tzdb-*/
+ rm -f *.zi $(TZS_NEW)
maintainer-clean: clean
@echo 'This command is intended for maintainers to use; it'
@echo 'deletes files that may need special tools to rebuild.'
- rm -f *.[1-8].txt tzcode.tar.gz tzdata.tar.gz
+ rm -f leapseconds version $(MANTXTS) $(TZS) *.asc *.tar.*
names:
@echo $(ENCHILADA)
+public: check check_public $(CHECK_TIME_T_ALTERNATIVES) \
+ tarballs signatures
+
+date.1.txt: date.1
+newctime.3.txt: newctime.3
+newstrftime.3.txt: newstrftime.3
+newtzset.3.txt: newtzset.3
+time2posix.3.txt: time2posix.3
+tzfile.5.txt: tzfile.5
+tzselect.8.txt: tzselect.8
+zdump.8.txt: zdump.8
+zic.8.txt: zic.8
+
+$(MANTXTS): workman.sh
+ LC_ALL=C sh workman.sh `expr $@ : '\(.*\)\.txt$$'` >$@.out
+ mv $@.out $@
+
+# Set file timestamps deterministically if possible,
+# so that tarballs containing the timestamps are reproducible.
+#
+# '$(SET_TIMESTAMP_N) N DEST A B C ...' sets the timestamp of the
+# file DEST to the maximum of the timestamps of the files A B C ...,
+# plus N if GNU ls and touch are available.
+SET_TIMESTAMP_N = sh -c '\
+ n=$$0 dest=$$1; shift; \
+ touch -cmr `ls -t "$$@" | sed 1q` "$$dest" && \
+ if test $$n != 0 && \
+ lsout=`ls -n --time-style="+%s" "$$dest" 2>/dev/null`; then \
+ set x $$lsout && \
+ touch -cmd @`expr $$7 + $$n` "$$dest"; \
+ else :; fi'
+# If DEST depends on A B C ... in this Makefile, callers should use
+# $(SET_TIMESTAMP_DEP) DEST A B C ..., for the benefit of any
+# downstream 'make' that considers equal timestamps to be out of date.
+# POSIX allows this 'make' behavior, and HP-UX 'make' does it.
+# If all that matters is that the timestamp be reproducible
+# and plausible, use $(SET_TIMESTAMP).
+SET_TIMESTAMP = $(SET_TIMESTAMP_N) 0
+SET_TIMESTAMP_DEP = $(SET_TIMESTAMP_N) 1
+
+# Set the timestamps to those of the git repository, if available,
+# and if the files have not changed since then.
+# This uses GNU 'ls --time-style=+%s', which outputs the seconds count,
+# and GNU 'touch -d@N FILE', where N is the number of seconds since 1970.
+# If git or GNU is absent, don't bother to sync with git timestamps.
+# Also, set the timestamp of each prebuilt file like 'leapseconds'
+# to be the maximum of the files it depends on.
+set-timestamps.out: $(EIGHT_YARDS)
+ rm -f $@
+ if (type git) >/dev/null 2>&1 && \
+ files=`git ls-files $(EIGHT_YARDS)` && \
+ touch -md @1 test.out; then \
+ rm -f test.out && \
+ for file in $$files; do \
+ if git diff --quiet $$file; then \
+ time=`git log -1 --format='tformat:%ct' $$file` && \
+ touch -cmd @$$time $$file; \
+ else \
+ echo >&2 "$$file: warning: does not match repository"; \
+ fi || exit; \
+ done; \
+ fi
+ $(SET_TIMESTAMP_DEP) leapseconds $(LEAP_DEPS)
+ for file in `ls $(MANTXTS) | sed 's/\.txt$$//'`; do \
+ $(SET_TIMESTAMP_DEP) $$file.txt $$file workman.sh || \
+ exit; \
+ done
+ $(SET_TIMESTAMP_DEP) version $(VERSION_DEPS)
+ $(SET_TIMESTAMP_DEP) tzdata.zi $(TZDATA_ZI_DEPS)
+ touch $@
+set-tzs-timestamp.out: $(TZS)
+ $(SET_TIMESTAMP_DEP) $(TZS) $(TZS_DEPS)
+ touch $@
+
# The zics below ensure that each data file can stand on its own.
# We also do an all-files run to catch links to links.
-public: $(ENCHILADA)
- make maintainer-clean
- make "CFLAGS=$(GCC_DEBUG_FLAGS)"
- -mkdir /tmp/,tzpublic
- -for i in $(TDATA) ; do zic -v -d /tmp/,tzpublic $$i 2>&1 | grep -v "starting year" ; done
- for i in $(TDATA) ; do zic -d /tmp/,tzpublic $$i || exit; done
- zic -v -d /tmp/,tzpublic $(TDATA) || exit
- rm -f -r /tmp/,tzpublic
- for i in *.[1-8] ; do sh workman.sh $$i > $$i.txt || exit; done
- $(AWK) -f checktab.awk $(PRIMARY_YDATA)
- tar cf - $(DOCS) $(SOURCES) $(MISC) *.[1-8].txt | gzip -9 > tzcode.tar.gz
- tar cf - $(DATA) | gzip -9 > tzdata.tar.gz
-
-typecheck:
- make clean
- for i in "long long" unsigned double; \
+check_public: $(VERSION_DEPS)
+ rm -fr public.dir
+ mkdir public.dir
+ ln $(VERSION_DEPS) public.dir
+ cd public.dir && $(MAKE) CFLAGS='$(GCC_DEBUG_FLAGS)' ALL
+ for i in $(TDATA_TO_CHECK) public.dir/tzdata.zi \
+ public.dir/vanguard.zi public.dir/main.zi \
+ public.dir/rearguard.zi; \
do \
- make CFLAGS="-DTYPECHECK -D_TIME_T \"-Dtime_t=$$i\"" ; \
- ./zdump -v Europe/Rome ; \
- make clean ; \
+ public.dir/zic -v -d public.dir/zoneinfo $$i 2>&1 || exit; \
done
+ public.dir/zic -v -d public.dir/zoneinfo-all $(TDATA_TO_CHECK)
+ :
+ : Also check 'backzone' syntax.
+ rm public.dir/main.zi
+ cd public.dir && $(MAKE) PACKRATDATA=backzone main.zi
+ public.dir/zic -d public.dir/zoneinfo main.zi
+ rm public.dir/main.zi
+ cd public.dir && \
+ $(MAKE) PACKRATDATA=backzone PACKRATLIST=zone.tab main.zi
+ public.dir/zic -d public.dir/zoneinfo main.zi
+ :
+ rm -fr public.dir
+ touch $@
+
+# Check that the code works under various alternative
+# implementations of time_t.
+check_time_t_alternatives: $(TIME_T_ALTERNATIVES)
+$(TIME_T_ALTERNATIVES_TAIL): $(TIME_T_ALTERNATIVES_HEAD)
+$(TIME_T_ALTERNATIVES): $(VERSION_DEPS)
+ rm -fr $@.dir
+ mkdir $@.dir
+ ln $(VERSION_DEPS) $@.dir
+ case $@ in \
+ int*32_t) range=-2147483648,2147483648;; \
+ u*) range=0,4294967296;; \
+ *) range=-4294967296,4294967296;; \
+ esac && \
+ wd=`pwd` && \
+ zones=`$(AWK) '/^[^#]/ { print $$3 }' <zone1970.tab` && \
+ if test $@ = $(TIME_T_ALTERNATIVES_HEAD); then \
+ range_target=; \
+ else \
+ range_target=to$$range.tzs; \
+ fi && \
+ (cd $@.dir && \
+ $(MAKE) TOPDIR="$$wd/$@.dir" \
+ CFLAGS='$(CFLAGS) -Dtime_tz='"'$@'" \
+ REDO='$(REDO)' \
+ D=$$wd/$@.dir \
+ TZS_YEAR="$$range" TZS_CUTOFF_FLAG="-t $$range" \
+ install $$range_target) && \
+ test $@ = $(TIME_T_ALTERNATIVES_HEAD) || { \
+ (cd $(TIME_T_ALTERNATIVES_HEAD).dir && \
+ $(MAKE) TOPDIR="$$wd/$@.dir" \
+ TZS_YEAR="$$range" TZS_CUTOFF_FLAG="-t $$range" \
+ D=$$wd/$@.dir \
+ to$$range.tzs) && \
+ diff -u $(TIME_T_ALTERNATIVES_HEAD).dir/to$$range.tzs \
+ $@.dir/to$$range.tzs && \
+ if diff -q Makefile Makefile 2>/dev/null; then \
+ quiet_option='-q'; \
+ else \
+ quiet_option=''; \
+ fi && \
+ diff $$quiet_option -r $(TIME_T_ALTERNATIVES_HEAD).dir/etc \
+ $@.dir/etc && \
+ diff $$quiet_option -r \
+ $(TIME_T_ALTERNATIVES_HEAD).dir/usr/share \
+ $@.dir/usr/share; \
+ }
+ touch $@
+
+TRADITIONAL_ASC = \
+ tzcode$(VERSION).tar.gz.asc \
+ tzdata$(VERSION).tar.gz.asc
+REARGUARD_ASC = \
+ tzdata$(VERSION)-rearguard.tar.gz.asc
+ALL_ASC = $(TRADITIONAL_ASC) $(REARGUARD_ASC) \
+ tzdb-$(VERSION).tar.lz.asc
+
+tarballs rearguard_tarballs tailored_tarballs traditional_tarballs \
+signatures rearguard_signatures traditional_signatures: \
+ version set-timestamps.out rearguard.zi vanguard.zi
+ VERSION=`cat version` && \
+ $(MAKE) AWK='$(AWK)' VERSION="$$VERSION" $@_version
+
+# These *_version rules are intended for use if VERSION is set by some
+# other means. Ordinarily these rules are used only by the above
+# non-_version rules, which set VERSION on the 'make' command line.
+tarballs_version: traditional_tarballs_version rearguard_tarballs_version \
+ tzdb-$(VERSION).tar.lz
+rearguard_tarballs_version: \
+ tzdata$(VERSION)-rearguard.tar.gz
+traditional_tarballs_version: \
+ tzcode$(VERSION).tar.gz tzdata$(VERSION).tar.gz
+tailored_tarballs_version: \
+ tzdata$(VERSION)-tailored.tar.gz
+signatures_version: $(ALL_ASC)
+rearguard_signatures_version: $(REARGUARD_ASC)
+traditional_signatures_version: $(TRADITIONAL_ASC)
+
+tzcode$(VERSION).tar.gz: set-timestamps.out
+ LC_ALL=C && export LC_ALL && \
+ tar $(TARFLAGS) -cf - \
+ $(COMMON) $(DOCS) $(SOURCES) | \
+ gzip $(GZIPFLAGS) >$@.out
+ mv $@.out $@
+
+tzdata$(VERSION).tar.gz: set-timestamps.out
+ LC_ALL=C && export LC_ALL && \
+ tar $(TARFLAGS) -cf - $(TZDATA_DIST) | \
+ gzip $(GZIPFLAGS) >$@.out
+ mv $@.out $@
+
+# Create empty files with a reproducible timestamp.
+CREATE_EMPTY = TZ=UTC0 touch -mt 202010122253.00
+
+# The obsolescent *rearguard* targets and related macros are present
+# for backwards compatibility with tz releases 2018e through 2022a.
+# They should go away eventually. To build rearguard tarballs you
+# can instead use 'make DATAFORM=rearguard tailored_tarballs'.
+tzdata$(VERSION)-rearguard.tar.gz: rearguard.zi set-timestamps.out
+ rm -fr $@.dir
+ mkdir $@.dir
+ ln $(TZDATA_DIST) $@.dir
+ cd $@.dir && rm -f $(TDATA) $(PACKRATDATA) version
+ for f in $(TDATA) $(PACKRATDATA); do \
+ rearf=$@.dir/$$f; \
+ $(AWK) -v DATAFORM=rearguard -f ziguard.awk $$f >$$rearf && \
+ $(SET_TIMESTAMP_DEP) $$rearf ziguard.awk $$f || exit; \
+ done
+ sed '1s/$$/-rearguard/' <version >$@.dir/version
+ : The dummy pacificnew pacifies TZUpdater 2.3.1 and earlier.
+ $(CREATE_EMPTY) $@.dir/pacificnew
+ touch -cmr version $@.dir/version
+ LC_ALL=C && export LC_ALL && \
+ (cd $@.dir && \
+ tar $(TARFLAGS) -cf - \
+ $(TZDATA_DIST) pacificnew | \
+ gzip $(GZIPFLAGS)) >$@.out
+ mv $@.out $@
+
+# Create a tailored tarball suitable for TZUpdater and compatible tools.
+# For example, 'make DATAFORM=vanguard tailored_tarballs' makes a tarball
+# useful for testing whether TZUpdater supports vanguard form.
+# The generated tarball is not byte-for-byte equivalent to a hand-tailored
+# traditional tarball, as data entries are put into 'etcetera' even if they
+# came from some other source file. However, the effect should be the same
+# for ordinary use, which reads all the source files.
+tzdata$(VERSION)-tailored.tar.gz: set-timestamps.out
+ rm -fr $@.dir
+ mkdir $@.dir
+ : The dummy pacificnew pacifies TZUpdater 2.3.1 and earlier.
+ cd $@.dir && \
+ $(CREATE_EMPTY) $(PRIMARY_YDATA) $(NDATA) backward \
+ `test $(DATAFORM) = vanguard || echo pacificnew`
+ (grep '^#' tzdata.zi && echo && cat $(DATAFORM).zi) \
+ >$@.dir/etcetera
+ touch -cmr tzdata.zi $@.dir/etcetera
+ sed -n \
+ -e '/^# *version *\(.*\)/h' \
+ -e '/^# *ddeps */H' \
+ -e '$$!d' \
+ -e 'g' \
+ -e 's/^# *version *//' \
+ -e 's/\n# *ddeps */-/' \
+ -e 's/ /-/g' \
+ -e 'p' \
+ <tzdata.zi >$@.dir/version
+ touch -cmr version $@.dir/version
+ links= && \
+ for file in $(TZDATA_DIST); do \
+ test -f $@.dir/$$file || links="$$links $$file"; \
+ done && \
+ ln $$links $@.dir
+ LC_ALL=C && export LC_ALL && \
+ (cd $@.dir && \
+ tar $(TARFLAGS) -cf - * | gzip $(GZIPFLAGS)) >$@.out
+ mv $@.out $@
+
+tzdb-$(VERSION).tar.lz: set-timestamps.out set-tzs-timestamp.out
+ rm -fr tzdb-$(VERSION)
+ mkdir tzdb-$(VERSION)
+ ln $(ENCHILADA) tzdb-$(VERSION)
+ $(SET_TIMESTAMP) tzdb-$(VERSION) tzdb-$(VERSION)/*
+ LC_ALL=C && export LC_ALL && \
+ tar $(TARFLAGS) -cf - tzdb-$(VERSION) | lzip -9 >$@.out
+ mv $@.out $@
+
+tzcode$(VERSION).tar.gz.asc: tzcode$(VERSION).tar.gz
+tzdata$(VERSION).tar.gz.asc: tzdata$(VERSION).tar.gz
+tzdata$(VERSION)-rearguard.tar.gz.asc: tzdata$(VERSION)-rearguard.tar.gz
+tzdb-$(VERSION).tar.lz.asc: tzdb-$(VERSION).tar.lz
+$(ALL_ASC):
+ $(GPG) --armor --detach-sign $?
+
+TYPECHECK_CFLAGS = $(CFLAGS) -DTYPECHECK -D__time_t_defined -D_TIME_T
+typecheck: typecheck_long_long typecheck_unsigned
+typecheck_long_long typecheck_unsigned: $(VERSION_DEPS)
+ rm -fr $@.dir
+ mkdir $@.dir
+ ln $(VERSION_DEPS) $@.dir
+ cd $@.dir && \
+ case $@ in \
+ *_long_long) i="long long";; \
+ *_unsigned ) i="unsigned" ;; \
+ esac && \
+ typecheck_cflags='' && \
+ $(MAKE) \
+ CFLAGS="$(TYPECHECK_CFLAGS) \"-Dtime_t=$$i\"" \
+ TOPDIR="`pwd`" \
+ install
+ $@.dir/zdump -i -c 1970,1971 Europe/Rome
+ touch $@
-zonenames: $(TDATA)
- @$(AWK) '/^Zone/ { print $$2 } /^Link/ { print $$3 }' $(TDATA)
+zonenames: tzdata.zi
+ @$(AWK) '/^Z/ { print $$2 } /^L/ { print $$3 }' tzdata.zi
asctime.o: private.h tzfile.h
date.o: private.h
difftime.o: private.h
-ialloc.o: private.h
localtime.o: private.h tzfile.h
-scheck.o: private.h
-strftime.o: tzfile.h
-zic.o: private.h tzfile.h
+strftime.o: private.h tzfile.h
+zdump.o: version.h
+zic.o: private.h tzfile.h version.h
-.KEEP_STATE:
+.PHONY: ALL INSTALL all
+.PHONY: check check_time_t_alternatives
+.PHONY: check_web check_zishrink
+.PHONY: clean clean_misc dummy.zd force_tzs
+.PHONY: install install_data maintainer-clean names
+.PHONY: posix_only posix_right public
+.PHONY: rearguard_signatures rearguard_signatures_version
+.PHONY: rearguard_tarballs rearguard_tarballs_version
+.PHONY: right_only right_posix signatures signatures_version
+.PHONY: tarballs tarballs_version
+.PHONY: traditional_signatures traditional_signatures_version
+.PHONY: traditional_tarballs traditional_tarballs_version
+.PHONY: tailored_tarballs tailored_tarballs_version
+.PHONY: typecheck
+.PHONY: zonenames zones
+.PHONY: $(ZDS)
diff --git a/NEWS b/NEWS
new file mode 100644
index 000000000000..c4abb32cd4dc
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,5671 @@
+News for the tz database
+
+Release 2022c - 2022-08-15 17:47:18 -0700
+
+ Briefly:
+ Work around awk bug in FreeBSD, macOS, etc.
+ Improve tzselect on intercontinental Zones.
+
+ Changes to code
+
+ Work around a bug in onetrueawk that broke commands like
+ 'make traditional_tarballs' on FreeBSD, macOS, etc.
+ (Problem reported by Deborah Goldsmith.)
+
+ Add code to tzselect that uses experimental structured comments in
+ zone1970.tab to clarify whether Zones like Africa/Abidjan and
+ Europe/Istanbul cross continent or ocean boundaries.
+ (Inspired by a problem reported by Peter Krefting.)
+
+ Fix bug with 'zic -d /a/b/c' when /a is unwritable but the
+ directory /a/b already exists.
+
+ Remove zoneinfo2tdf.pl, as it was unused and triggered false
+ malware alarms on some email servers.
+
+
+Release 2022b - 2022-08-10 15:38:32 -0700
+
+ Briefly:
+ Chile's DST is delayed by a week in September 2022.
+ Iran no longer observes DST after 2022.
+ Rename Europe/Kiev to Europe/Kyiv.
+ New zic -R option
+ Vanguard form now uses %z.
+ Finish moving duplicate-since-1970 zones to 'backzone'.
+ New build option PACKRATLIST
+ New tailored_tarballs target, replacing rearguard_tarballs
+
+ Changes to future timestamps
+
+ Chile's 2022 DST start is delayed from September 4 to September 11.
+ (Thanks to Juan Correa.)
+
+ Iran plans to stop observing DST permanently, after it falls back
+ on 2022-09-21. (Thanks to Ali Mirjamali.)
+
+ Changes to past timestamps
+
+ Finish moving to 'backzone' the location-based zones whose
+ timestamps since 1970 are duplicates; adjust links accordingly.
+ This change ordinarily affects only pre-1970 timestamps, and with
+ the new PACKRATLIST option it does not affect any timestamps.
+ In this round the affected zones are Antarctica/Vostok,
+ Asia/Brunei, Asia/Kuala_Lumpur, Atlantic/Reykjavik,
+ Europe/Amsterdam, Europe/Copenhagen, Europe/Luxembourg,
+ Europe/Monaco, Europe/Oslo, Europe/Stockholm, Indian/Christmas,
+ Indian/Cocos, Indian/Kerguelen, Indian/Mahe, Indian/Reunion,
+ Pacific/Chuuk, Pacific/Funafuti, Pacific/Majuro, Pacific/Pohnpei,
+ Pacific/Wake and Pacific/Wallis, and the affected links are
+ Arctic/Longyearbyen, Atlantic/Jan_Mayen, Iceland, Pacific/Ponape,
+ Pacific/Truk, and Pacific/Yap.
+
+ From fall 1994 through fall 1995, Shanks wrote that Crimea's
+ DST transitions were at 02:00 standard time, not at 00:00.
+ (Thanks to Michael Deckers.)
+
+ Iran adopted standard time in 1935, not 1946. In 1977 it observed
+ DST from 03-21 23:00 to 10-20 24:00; its 1978 transitions were on
+ 03-24 and 08-05, not 03-20 and 10-20; and its spring 1979
+ transition was on 05-27, not 03-21.
+ (Thanks to Roozbeh Pournader and Francis Santoni.)
+
+ Chile's observance of -04 from 1946-08-29 through 1947-03-31 was
+ considered DST, not standard time. Santiago and environs had moved
+ their clocks back to rejoin the rest of mainland Chile; put this
+ change at the end of 1946-08-28. (Thanks to Michael Deckers.)
+
+ Some old, small clock transitions have been removed, as people at
+ the time did not change their clocks. This affects Asia/Hong_Kong
+ in 1904, Asia/Ho_Chi_Minh in 1906, and Europe/Dublin in 1880.
+
+ Changes to zone name
+
+ Rename Europe/Kiev to Europe/Kyiv, as "Kyiv" is more common in
+ English now. Spelling of other names in Ukraine has not yet
+ demonstrably changed in common English practice so for now these
+ names retain old spellings, as in other countries (e.g.,
+ Europe/Prague not "Praha", and Europe/Sofia not "Sofiya").
+
+ Changes to code
+
+ zic has a new option '-R @N' to output explicit transitions < N.
+ (Need suggested by Almaz Mingaleev.)
+
+ 'zic -r @N' no longer outputs bad data when N < first transition.
+ (Problem introduced in 2021d and reported by Peter Krefting.)
+
+ zic now checks its input for NUL bytes and unterminated lines, and
+ now supports input line lengths up to 2048 (not 512) bytes.
+
+ gmtime and related code now use the abbreviation "UTC" not "GMT".
+ POSIX is being revised to require this.
+
+ When tzset and related functions set vestigial static variables
+ like tzname, they now prefer specified timestamps to unspecified ones.
+ (Problem reported by Almaz Mingaleev.)
+
+ zic no longer complains "can't determine time zone abbreviation to
+ use just after until time" when a transition to a new standard
+ time occurs simultaneously with the first DST fallback transition.
+
+ Changes to build procedure
+
+ Source data in vanguard form now uses the %z notation, introduced
+ in release 2015f. For example, for America/Sao_Paulo vanguard
+ form contains the zone continuation line "-3:00 Brazil %z", which
+ is simpler and more reliable than the line "-3:00 Brazil -03/-02"
+ used in main and rearguard forms. The plan is for the main form
+ to use %z eventually; in the meantime maintainers of zi parsers
+ are encouraged to test the parsers on vanguard.zi.
+
+ The Makefile has a new PACKRATLIST option to select a subset of
+ 'backzone'. For example, 'make PACKRATDATA=backzone
+ PACKRATLIST=zone.tab' now generates TZif files identical to those
+ of the global-tz project.
+
+ The Makefile has a new tailored_tarballs target for generating
+ special-purpose tarballs. It generalizes and replaces the
+ rearguard_tarballs target and related targets and macros, which
+ are now obsolescent.
+
+ 'make install' now defaults LOCALTIME to Factory not GMT,
+ which means the default abbreviation is now "-00" not "GMT".
+
+ Remove the posix_packrat target, marked obsolescent in 2016a.
+
+
+Release 2022a - 2022-03-15 23:02:01 -0700
+
+ Briefly:
+ Palestine will spring forward on 2022-03-27, not -03-26.
+ zdump -v now outputs better failure indications.
+ Bug fixes for code that reads corrupted TZif data.
+
+ Changes to future timestamps
+
+ Palestine will spring forward on 2022-03-27, not 2022-03-26.
+ (Thanks to Heba Hamad.) Predict future transitions for first
+ Sunday >= March 25. Additionally, predict fallbacks to be the first
+ Friday on or after October 23, not October's last Friday, to be more
+ consistent with recent practice. The first differing fallback
+ prediction is on 2025-10-24, not 2025-10-31.
+
+ Changes to past timestamps
+
+ From 1992 through spring 1996, Ukraine's DST transitions were at
+ 02:00 standard time, not at 01:00 UTC. (Thanks to Alois Treindl.)
+
+ Chile's Santiago Mean Time and its LMT precursor have been adjusted
+ eastward by 1 second to align with past and present law.
+
+ Changes to commentary
+
+ Add several references for Chile's 1946/1947 transitions, some of
+ which only affected portions of the country.
+
+ Changes to code
+
+ Fix bug when mktime gets confused by truncated TZif files with
+ unspecified local time. (Problem reported by Almaz Mingaleev.)
+
+ Fix bug when 32-bit time_t code reads malformed 64-bit TZif data.
+ (Problem reported by Christos Zoulas.)
+
+ When reading a version 2 or later TZif file, the TZif reader now
+ validates the version 1 header and data block only enough to skip
+ over them, as recommended by RFC 8536 section 4. Also, the TZif
+ reader no longer mistakenly attempts to parse a version 1 TZIf
+ file header as a TZ string.
+
+ zdump -v now outputs "(localtime failed)" and "(gmtime failed)"
+ when local time and UT cannot be determined for a timestamp.
+
+ Changes to build procedure
+
+ Distribution tarballs now use standard POSIX.1-1988 ustar format
+ instead of GNU format. Although the formats are almost identical
+ for these tarballs, ustar headers' magic fields contain "ustar"
+ instead of "ustar ", and their version fields contain "00" instead
+ of " ". The two formats are planned to diverge more significantly
+ for tzdb releases after 2242-03-16 12:56:31 UTC, when the ustar
+ format becomes obsolete and the tarballs switch to pax format, an
+ extension of ustar. For details about these formats, please see
+ "pax - portable archive interchange", IEEE Std 1003.1-2017,
+ <https://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html#tag_20_92_13>.
+
+
+Release 2021e - 2021-10-21 18:41:00 -0700
+
+ Changes to future timestamps
+
+ Palestine will fall back 10-29 (not 10-30) at 01:00.
+ (Thanks to P Chan and Heba Hemad.)
+
+
+Release 2021d - 2021-10-15 13:48:18 -0700
+
+ Briefly:
+ Fiji suspends DST for the 2021/2022 season.
+ 'zic -r' marks unspecified timestamps with "-00".
+
+ Changes to future timestamps
+
+ Fiji will suspend observance of DST for the 2021/2022 season.
+ Assume for now that it will return next year. (Thanks to Jashneel
+ Kumar and P Chan.)
+
+ Changes to code
+
+ 'zic -r' now uses "-00" time zone abbreviations for intervals
+ with UT offsets that are unspecified due to -r truncation.
+ This implements a change in draft Internet RFC 8536bis.
+
+
+Release 2021c - 2021-10-01 14:21:49 -0700
+
+ Briefly:
+ Revert most 2021b changes to 'backward'.
+ Fix 'zic -b fat' bug in pre-1970 32-bit data.
+ Fix two Link line typos.
+ Distribute SECURITY file.
+
+ This release is intended as a bugfix release, to fix compatibility
+ problems and typos reported since 2021b was released.
+
+ Changes to Link directives
+
+ Revert almost all of 2021b's changes to the 'backward' file,
+ by moving Link directives back to where they were in 2021a.
+ Although 'zic' doesn't care which source file contains a Link
+ directive, some downstream uses ran into trouble with the move.
+ (Problem reported by Stephen Colebourne for Joda-Time.)
+
+ Fix typo that linked Atlantic/Jan_Mayen to the wrong location
+ (problem reported by Chris Walton).
+
+ Fix 'backzone' typo that linked America/Virgin to the wrong
+ location (problem reported by Michael Deckers).
+
+ Changes to code
+
+ Fix a bug in 'zic -b fat' that caused old timestamps to be
+ mishandled in 32-bit-only readers (problem reported by Daniel
+ Fischer).
+
+ Changes to documentation
+
+ Distribute the SECURITY file (problem reported by Andreas Radke).
+
+
+Release 2021b - 2021-09-24 16:23:00 -0700
+
+ Briefly:
+ Jordan now starts DST on February's last Thursday.
+ Samoa no longer observes DST.
+ Merge more location-based Zones whose timestamps agree since 1970.
+ Move some backward-compatibility links to 'backward'.
+ Rename Pacific/Enderbury to Pacific/Kanton.
+ Correct many pre-1993 transitions in Malawi, Portugal, etc.
+ zic now creates each output file or link atomically.
+ zic -L no longer omits the POSIX TZ string in its output.
+ zic fixes for truncation and leap second table expiration.
+ zic now follows POSIX for TZ strings using all-year DST.
+ Fix some localtime crashes and bugs in obscure cases.
+ zdump -v now outputs more-useful boundary cases.
+ tzfile.5 better matches a draft successor to RFC 8536.
+ A new file SECURITY.
+
+ This release is prompted by recent announcements by Jordan and Samoa.
+ It incorporates many other changes that had accumulated since 2021a.
+ However, it omits most proposed changes that merged all Zones
+ agreeing since 1970, as concerns were raised about doing too many of
+ these changes at once. It does keeps some of these changes in the
+ interest of making tzdb more equitable one step at a time; see
+ "Merge more location-based Zones" below.
+
+ Changes to future timestamps
+
+ Jordan now starts DST on February's last Thursday.
+ (Thanks to Steffen Thorsen.)
+
+ Samoa no longer observes DST. (Thanks to Geoffrey D. Bennett.)
+
+ Changes to zone name
+
+ Rename Pacific/Enderbury to Pacific/Kanton. When we added
+ Enderbury in 1993, we did not know that it is uninhabited and that
+ Kanton (population two dozen) is the only inhabited location in
+ that timezone. The old name is now a backward-compatibility link.
+
+ Changes to past timestamps
+
+ Correct many pre-1993 transitions, fixing entries originally
+ derived from Shanks, Whitman, and Mundell. The fixes include:
+ - Barbados: standard time was introduced in 1911, not 1932; and
+ DST was observed in 1942-1944
+ - Cook Islands: In 1899 they switched from east to west of GMT,
+ celebrating Christmas for two days. They (and Niue) switched
+ to standard time in 1952, not 1901.
+ - Guyana: corrected LMT for Georgetown; the introduction of
+ standard time in 1911, not 1915; and corrections to 1975 and
+ 1992 transitions
+ - Kanton: uninhabited before 1937-08-31
+ - Niue: only observed -11:20 from 1952 through 1964, then went to
+ -11 instead of -11:30
+ - Portugal: DST was observed in 1950
+ - Tonga: corrected LMT; the introduction of standard time in 1945,
+ not 1901; and corrections to the transition from +12:20 to +13
+ in 1961, not 1941
+ Additional fixes to entries in the 'backzone' file include:
+ - Enderbury: inhabited only 1860/1885 and 1938-03-06/1942-02-09
+ - The Gambia: 1933 and 1942 transitions
+ - Malawi: several 1911 through 1925 transitions
+ - Sierra Leone: several 1913 through 1941 transitions, and DST
+ was NOT observed in 1957 through 1962
+ (Thanks to P Chan, Michael Deckers, Alexander Krivenyshev and
+ Alois Treindl.)
+
+ Merge more location-based Zones whose timestamps agree since 1970,
+ as pre-1970 timestamps are out of scope. This is part of a
+ process that has been ongoing since 2013. This does not affect
+ post-1970 timestamps, and timezone historians who build with 'make
+ PACKRATDATA=backzone' should see no changes to pre-1970 timestamps.
+ When merging, keep the most-populous location's data, and move
+ data for other locations to 'backzone' with a backward
+ link in 'backward'. For example, move America/Creston data to
+ 'backzone' with a link in 'backward' from America/Phoenix because
+ the two timezones' timestamps agree since 1970; this change
+ affects some pre-1968 timestamps in America/Creston because
+ Creston and Phoenix disagreed before 1968. The affected Zones
+ are Africa/Accra, America/Atikokan, America/Blanc-Sablon,
+ America/Creston, America/Curacao, America/Nassau,
+ America/Port_of_Spain, Antarctica/DumontDUrville, and
+ Antarctica/Syowa.
+
+ Changes to maintenance procedure
+
+ The new file SECURITY covers how to report security-related bugs.
+
+ Several backward-compatibility links have been moved to the
+ 'backward' file. These links, which range from Africa/Addis_Ababa
+ to Pacific/Saipan, are only for compatibility with now-obsolete
+ guidelines suggesting an entry for every ISO 3166 code.
+ The intercontinental convenience links Asia/Istanbul and
+ Europe/Nicosia have also been moved to 'backward'.
+
+ Changes to code
+
+ zic now creates each output file or link atomically,
+ possibly by creating a temporary file and then renaming it.
+ This avoids races where a TZ setting would temporarily stop
+ working while zic was installing a replacement file or link.
+
+ zic -L no longer omits the POSIX TZ string in its output.
+ Starting with 2020a, zic -L truncated its output according to the
+ "Expires" directive or "#expires" comment in the leapseconds file.
+ The resulting TZif files omitted daylight saving transitions after
+ the leap second table expired, which led to far less-accurate
+ predictions of times after the expiry. Although future timestamps
+ cannot be converted accurately in the presence of leap seconds, it
+ is more accurate to convert near-future timestamps with a few
+ seconds error than with an hour error, so zic -L no longer
+ truncates output in this way.
+
+ Instead, when zic -L is given the "Expires" directive, it now
+ outputs the expiration by appending a no-change entry to the leap
+ second table. Although this should work well with most TZif
+ readers, it does not conform to Internet RFC 8536 and some pickier
+ clients (including tzdb 2017c through 2021a) reject it, so
+ "Expires" directives are currently disabled by default. To enable
+ them, set the EXPIRES_LINE Makefile variable. If a TZif file uses
+ this new feature it is marked with a new TZif version number 4,
+ a format intended to be documented in a successor to RFC 8536.
+
+ zic -L LEAPFILE -r @LO no longer generates an invalid TZif file
+ that omits leap second information for the range LO..B when LO
+ falls between two leap seconds A and B. Instead, it generates a
+ TZif version 4 file that represents the previously-missing
+ information.
+
+ The TZif reader now allows the leap second table to begin with a
+ correction other than -1 or +1, and to contain adjacent
+ transitions with equal corrections. This supports TZif version 4.
+
+ The TZif reader now lets leap seconds occur less than 28 days
+ apart. This supports possible future TZif extensions.
+
+ Fix bug that caused 'localtime' etc. to crash when TZ was
+ set to a all-year DST string like "EST5EDT4,0/0,J365/25" that does
+ not conform to POSIX but does conform to Internet RFC 8536.
+
+ Fix another bug that caused 'localtime' etc. to crash when TZ was
+ set to a POSIX-conforming but unusual TZ string like
+ "EST5EDT4,0/0,J365/0", where almost all the year is DST.
+
+ Fix yet another bug that caused 'localtime' etc. to mishandle slim
+ TZif files containing leap seconds after the last explicit
+ transition in the table, or when handling far-future timestamps
+ in slim TZif files lacking leap seconds.
+
+ Fix localtime misbehavior involving positive leap seconds.
+ This change affects only behavior for "right" system time,
+ which contains leap seconds, and only if the UT offset is
+ not a multiple of 60 seconds when a positive leap second occurs.
+ (No such timezone exists in tzdb, luckily.) Without the fix,
+ the timestamp was ambiguous during a positive leap second.
+ With the fix, any seconds occurring after a positive leap second
+ and within the same localtime minute are counted through 60, not
+ through 59; their UT offset (tm_gmtoff) is the same as before.
+ Here is how the fix affects timestamps in a timezone with UT
+ offset +01:23:45 (5025 seconds) and with a positive leap second at
+ 1972-06-30 23:59:60 UTC (78796800):
+
+ time_t without the fix with the fix
+ 78796800 1972-07-01 01:23:45 1972-07-01 01:23:45 (leap second)
+ 78796801 1972-07-01 01:23:45 1972-07-01 01:23:46
+ ...
+ 78796815 1972-07-01 01:23:59 1972-07-01 01:23:60
+ 78796816 1972-07-01 01:24:00 1972-07-01 01:24:00
+
+ Fix an unlikely bug that caused 'localtime' etc. to misbehave if
+ civil time changes a few seconds before time_t wraps around, when
+ leap seconds are enabled.
+
+ Fix bug in zic -r; in some cases, the dummy time type after the
+ last time transition disagreed with the TZ string, contrary to
+ Internet RFC 8563 section 3.3.
+
+ Fix a bug with 'zic -r @X' when X is a negative leap second that
+ has a nonnegative correction. Without the fix, the output file
+ was truncated so that X appeared to be a positive leap second.
+ Fix a similar, even-less-likely bug when truncating at a positive
+ leap second that has a nonpositive correction.
+
+ zic -r now reports an error if given rolling leap seconds, as this
+ usage has never generally worked and is evidently unused.
+
+ zic now generates a POSIX-conforming TZ string for TZif files
+ where all-year DST is predicted for the indefinite future.
+ For example, for all-year Eastern Daylight Time, zic now generates
+ "XXX3EDT4,0/0,J365/23" where it previously generated
+ "EST5EDT,0/0,J365/25" or "". (Thanks to Michael Deckers for
+ noting the possibility of POSIX conformance.)
+
+ zic.c no longer requires sys/wait.h (thanks to spazmodius for
+ noting it wasn't needed).
+
+ When reading slim TZif files, zdump no longer mishandles leap
+ seconds on the rare platforms where time_t counts leap seconds,
+ fixing a bug introduced in 2014g.
+
+ zdump -v now outputs timestamps at boundaries of what localtime
+ and gmtime can represent, instead of the less-useful timestamps
+ one day after the minimum and one day before the maximum.
+ (Thanks to Arthur David Olson for prototype code, and to Manuela
+ Friedrich for debugging help.)
+
+ zdump's -c and -t options are now consistently inclusive for the
+ lower time bound and exclusive for the upper. Formerly they were
+ inconsistent. (Confusion noted by Martin Burnicki.)
+
+ Changes to build procedure
+
+ You can now compile with -DHAVE_MALLOC_ERRNO=0 to port to
+ non-POSIX hosts where malloc doesn't set errno.
+ (Problem reported by Jan Engelhardt.)
+
+ Changes to documentation
+
+ tzfile.5 better matches a draft successor to RFC 8536
+ <https://datatracker.ietf.org/doc/draft-murchison-rfc8536bis/01/>.
+
+
+Release 2021a - 2021-01-24 10:54:57 -0800
+
+ Changes to future timestamps
+
+ South Sudan changes from +03 to +02 on 2021-02-01 at 00:00.
+ (Thanks to Steffen Thorsen.)
+
+
+Release 2020f - 2020-12-29 00:17:46 -0800
+
+ Change to build procedure
+
+ 'make rearguard_tarballs' no longer generates a bad rearguard.zi,
+ fixing a 2020e bug. (Problem reported by Deborah Goldsmith.)
+
+
+Release 2020e - 2020-12-22 15:14:34 -0800
+
+ Briefly:
+ Volgograd switches to Moscow time on 2020-12-27 at 02:00.
+
+ Changes to future timestamps
+
+ Volgograd changes time zone from +04 to +03 on 2020-12-27 at 02:00.
+ (Thanks to Alexander Krivenyshev and Stepan Golosunov.)
+
+ Changes to past timestamps
+
+ Correct many pre-1986 transitions, fixing entries originally
+ derived from Shanks. The fixes include:
+ - Australia: several 1917 through 1971 transitions
+ - The Bahamas: several 1941 through 1945 transitions
+ - Bermuda: several 1917 through 1956 transitions
+ - Belize: several 1942 through 1968 transitions
+ - Ghana: several 1915 through 1956 transitions
+ - Israel and Palestine: several 1940 through 1985 transitions
+ - Kenya and adjacent: several 1908 through 1960 transitions
+ - Nigeria and adjacent: correcting LMT in Lagos, and several 1905
+ through 1919 transitions
+ - Seychelles: the introduction of standard time in 1907, not 1906
+ - Vanuatu: DST in 1973-1974, and a corrected 1984 transition
+ (Thanks to P Chan.)
+
+ Because of the Australia change, Australia/Currie (King Island) is
+ no longer needed, as it is identical to Australia/Hobart for all
+ timestamps since 1970 and was therefore created by mistake.
+ Australia/Currie has been moved to the 'backward' file and its
+ corrected data moved to the 'backzone' file.
+
+ Changes to past time zone abbreviations and DST flags
+
+ To better match legislation in Turks and Caicos, the 2015 shift to
+ year-round observance of -04 is now modeled as AST throughout before
+ returning to Eastern Time with US DST in 2018, rather than as
+ maintaining EDT until 2015-11-01. (Thanks to P Chan.)
+
+ Changes to documentation
+
+ The zic man page now documents zic's coalescing of transitions
+ when a zone falls back just before DST springs forward.
+
+
+Release 2020d - 2020-10-21 11:24:13 -0700
+
+ Briefly:
+ Palestine ends DST earlier than predicted, on 2020-10-24.
+
+ Changes to past and future timestamps
+
+ Palestine ends DST on 2020-10-24 at 01:00, instead of 2020-10-31
+ as previously predicted (thanks to Sharef Mustafa.) Its
+ 2019-10-26 fall-back was at 00:00, not 01:00 (thanks to Steffen
+ Thorsen.) Its 2015-10-23 transition was at 01:00 not 00:00, and
+ its spring 2020 transition was on March 28 at 00:00, not March 27
+ (thanks to Pierre Cashon.) This affects Asia/Gaza and
+ Asia/Hebron. Assume future spring and fall transitions will be on
+ the Saturday preceding the last Sunday of March and October,
+ respectively.
+
+
+Release 2020c - 2020-10-16 11:15:53 -0700
+
+ Briefly:
+ Fiji starts DST later than usual, on 2020-12-20.
+
+ Changes to future timestamps
+
+ Fiji will start DST on 2020-12-20, instead of 2020-11-08 as
+ previously predicted. DST will still end on 2021-01-17.
+ (Thanks to Raymond Kumar and Alan Mintz.) Assume for now that
+ the later-than-usual start date is a one-time departure from the
+ recent pattern.
+
+ Changes to build procedure
+
+ Rearguard tarballs now contain an empty file pacificnew.
+ Some older downstream software expects this file to exist.
+ (Problem reported by Mike Cullinan.)
+
+
+Release 2020b - 2020-10-06 18:35:04 -0700
+
+ Briefly:
+ Revised predictions for Morocco's changes starting in 2023.
+ Canada's Yukon changes to -07 on 2020-11-01, not 2020-03-08.
+ Macquarie Island has stayed in sync with Tasmania since 2011.
+ Casey, Antarctica is at +08 in winter and +11 in summer.
+ zic no longer supports -y, nor the TYPE field of Rules.
+
+ Changes to future timestamps
+
+ Morocco's spring-forward after Ramadan is now predicted to occur
+ no sooner than two days after Ramadan, instead of one day.
+ (Thanks to Milamber.) The first altered prediction is for 2023,
+ now predicted to spring-forward on April 30 instead of April 23.
+
+ Changes to past and future timestamps
+
+ Casey Station, Antarctica has been using +08 in winter and +11 in
+ summer since 2018. The most recent transition from +08 to +11 was
+ 2020-10-04 00:01. Also, Macquarie Island has been staying in
+ sync with Tasmania since 2011. (Thanks to Steffen Thorsen.)
+
+ Changes to past and future time zone abbreviations and DST flags
+
+ Canada's Yukon, represented by America/Whitehorse and
+ America/Dawson, changes its time zone rules from -08/-07 to
+ permanent -07 on 2020-11-01, not on 2020-03-08 as 2020a had it.
+ This change affects only the time zone abbreviation (MST vs PDT)
+ and daylight saving flag for the period between the two dates.
+ (Thanks to Andrew G. Smith.)
+
+ Changes to past timestamps
+
+ Correct several transitions for Hungary for 1918/1983.
+ For example, the 1983-09-25 fall-back was at 01:00, not 03:00.
+ (Thanks to Géza Nyáry.) Also, the 1890 transition to standard
+ time was on 11-01, not 10-01 (thanks to Michael Deckers).
+
+ The 1891 French transition was on March 16, not March 15. The
+ 1911-03-11 French transition was at midnight, not a minute later.
+ Monaco's transitions were on 1892-06-01 and 1911-03-29, not
+ 1891-03-15 and 1911-03-11. (Thanks to Michael Deckers.)
+
+ Changes to code
+
+ 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.
+
+ Changes to build procedure
+
+ The Makefile now defaults POSIXRULES to '-', so the posixrules
+ feature (obsolete as of 2019b) is no longer installed by default.
+
+ Changes to documentation and commentary
+
+ The long-obsolete files pacificnew, systemv, and yearistype.sh have
+ been removed from the distribution. (Thanks to Tim Parenti.)
+
+
+Release 2020a - 2020-04-23 16:03:47 -0700
+
+ Briefly:
+ Morocco springs forward on 2020-05-31, not 2020-05-24.
+ Canada's Yukon advanced to -07 year-round on 2020-03-08.
+ America/Nuuk renamed from America/Godthab.
+ zic now supports expiration dates for leap second lists.
+
+ Changes to future timestamps
+
+ Morocco's second spring-forward transition in 2020 will be May 31,
+ not May 24 as predicted earlier. (Thanks to Semlali Naoufal.)
+ Adjust future-year predictions to use the first Sunday after the
+ day after Ramadan, not the first Sunday after Ramadan.
+
+ Canada's Yukon, represented by America/Whitehorse and
+ America/Dawson, advanced to -07 year-round, beginning with its
+ spring-forward transition on 2020-03-08, and will not fall back on
+ 2020-11-01. Although a government press release calls this
+ "permanent Pacific Daylight Saving Time", we prefer MST for
+ consistency with nearby Dawson Creek, Creston, and Fort Nelson.
+ (Thanks to Tim Parenti.)
+
+ Changes to past timestamps
+
+ Shanghai observed DST in 1919. (Thanks to Phake Nick.)
+
+ Changes to timezone identifiers
+
+ To reflect current usage in English better, America/Godthab has
+ been renamed to America/Nuuk. A backwards-compatibility link
+ remains for the old name.
+
+ Changes to code
+
+ localtime.c no longer mishandles timestamps after the last
+ transition in a TZif file with leap seconds and with daylight
+ saving time transitions projected into the indefinite future.
+ For example, with TZ='America/Los_Angeles' with leap seconds,
+ zdump formerly reported a DST transition on 2038-03-14
+ from 01:59:32.999... to 02:59:33 instead of the correct transition
+ from 01:59:59.999... to 03:00:00.
+
+ zic -L now supports an Expires line in the leapseconds file, and
+ truncates the TZif output accordingly. This propagates leap
+ second expiration information into the TZif file, and avoids the
+ abovementioned localtime.c bug as well as similar bugs present in
+ many client implementations. If no Expires line is present, zic
+ -L instead truncates the TZif output based on the #expires comment
+ present in leapseconds files distributed by tzdb 2018f and later;
+ however, this usage is obsolescent. For now, the distributed
+ leapseconds file has an Expires line that is commented out, so
+ that the file can be fed to older versions of zic which ignore the
+ commented-out line. Future tzdb distributions are planned to
+ contain a leapseconds file with an Expires line.
+
+ The configuration macros HAVE_TZNAME and USG_COMPAT should now be
+ set to 1 if the system library supports the feature, and 2 if not.
+ As before, these macros are nonzero if tzcode should support the
+ feature, zero otherwise.
+
+ The configuration macro ALTZONE now has the same values with the
+ same meaning as HAVE_TZNAME and USG_COMPAT.
+
+ The code's defense against CRLF in leap-seconds.list is now
+ portable to POSIX awk. (Problem reported by Deborah Goldsmith.)
+
+ Although the undocumented tzsetwall function is not changed in
+ this release, it is now deprecated in preparation for removal in
+ future releases. Due to POSIX requirements, tzsetwall has not
+ worked for some time. Any code that uses it should instead use
+ tzalloc(NULL) or, if portability trumps thread-safety, should
+ unset the TZ environment variable.
+
+ Changes to commentary
+
+ The Îles-de-la-Madeleine and the Listuguj reserve are noted as
+ following America/Halifax, and comments about Yukon's "south" and
+ "north" have been corrected to say "east" and "west". (Thanks to
+ Jeffery Nichols.)
+
+
+Release 2019c - 2019-09-11 08:59:48 -0700
+
+ Briefly:
+ Fiji observes DST from 2019-11-10 to 2020-01-12.
+ Norfolk Island starts observing Australian-style DST.
+
+ Changes to future timestamps
+
+ Fiji's next DST transitions will be 2019-11-10 and 2020-01-12
+ instead of 2019-11-03 and 2020-01-19. (Thanks to Raymond Kumar.)
+ Adjust future guesses accordingly.
+
+ Norfolk Island will observe Australian-style DST starting in
+ spring 2019. The first transition is on 2019-10-06. (Thanks to
+ Kyle Czech and Michael Deckers.)
+
+ Changes to past timestamps
+
+ Many corrections to time in Turkey from 1940 through 1985.
+ (Thanks to Oya Vulaş via Alois Treindl, and to Kıvanç Yazan.)
+
+ The Norfolk Island 1975-03-02 transition was at 02:00 standard
+ time, not 02:00 DST. (Thanks to Michael Deckers.)
+
+ South Korea observed DST from 1948 through 1951. Although this
+ info was supposed to appear in release 2014j, a typo inadvertently
+ suppressed the change. (Thanks to Alois Treindl.)
+
+ Detroit observed DST in 1967 and 1968 following the US DST rules,
+ except that its 1967 DST began on June 14 at 00:01. (Thanks to
+ Alois Treindl for pointing out that the old data entries were
+ probably wrong.)
+
+ Fix several errors in pre-1970 transitions in Perry County, IN.
+ (Thanks to Alois Treindl for pointing out the 1967/9 errors.)
+
+ Edmonton did not observe DST in 1967 or 1969. In 1946 Vancouver
+ ended DST on 09-29 not 10-13, and Vienna ended DST on 10-07 not
+ 10-06. In 1945 Königsberg (now Kaliningrad) switched from +01/+02
+ to +02/+03 on 04-10 not 01-01, and its +02/+03 is abbreviated
+ EET/EEST, not CET/CEST. (Thanks to Alois Treindl.) In 1946
+ Königsberg switched to +03 on 04-07 not 01-01.
+
+ In 1946 Louisville switched from CST to CDT on 04-28 at 00:01, not
+ 01-01 at 00:00. (Thanks to Alois Treindl and Michael Deckers.)
+ Also, it switched from CST to CDT on 1950-04-30, not 1947-04-27.
+
+ The 1892-05-01 transition in Brussels was at 00:17:30, not at noon.
+ (Thanks to Michael Deckers.)
+
+ Changes to past time zone abbreviations and DST flags
+
+ Hong Kong Winter Time, observed from 1941-10-01 to 1941-12-25,
+ is now flagged as DST and is abbreviated HKWT not HKT.
+
+ Changes to code
+
+ leapseconds.awk now relies only on its input data, rather than
+ also relying on its comments. (Inspired by code from Dennis
+ Ferguson and Chris Woodbury.)
+
+ The code now defends against CRLFs in leap-seconds.list.
+ (Thanks to Brian Inglis and Chris Woodbury.)
+
+ Changes to documentation and commentary
+
+ theory.html discusses leap seconds. (Thanks to Steve Summit.)
+
+ Nashville's newspapers dueled about the time of day in the 1950s.
+ (Thanks to John Seigenthaler.)
+
+ Liechtenstein observed Swiss DST in 1941/2.
+ (Thanks to Alois Treindl.)
+
+
+Release 2019b - 2019-07-01 00:09:53 -0700
+
+ Briefly:
+ Brazil no longer observes DST.
+ 'zic -b slim' outputs smaller TZif files; please try it out.
+ Palestine's 2019 spring-forward transition was on 03-29, not 03-30.
+
+ Changes to future timestamps
+
+ Brazil has canceled DST and will stay on standard time indefinitely.
+ (Thanks to Steffen Thorsen, Marcus Diniz, and Daniel Soares de
+ Oliveira.)
+
+ Predictions for Morocco now go through 2087 instead of 2037, to
+ work around a problem on newlib when using TZif files output by
+ zic 2019a or earlier. (Problem reported by David Gauchard.)
+
+ Changes to past and future timestamps
+
+ Palestine's 2019 spring transition was 03-29 at 00:00, not 03-30
+ at 01:00. (Thanks to Sharef Mustafa and Even Scharning.) Guess
+ future transitions to be March's last Friday at 00:00.
+
+ Changes to past timestamps
+
+ Hong Kong's 1941-06-15 spring-forward transition was at 03:00, not
+ 03:30. Its 1945 transition from JST to HKT was on 11-18 at 02:00,
+ not 09-15 at 00:00. In 1946 its spring-forward transition was on
+ 04-21 at 00:00, not the previous day at 03:30. From 1946 through
+ 1952 its fall-back transitions occurred at 04:30, not at 03:30.
+ In 1947 its fall-back transition was on 11-30, not 12-30.
+ (Thanks to P Chan.)
+
+ Changes to past time zone abbreviations
+
+ Italy's 1866 transition to Rome Mean Time was on December 12, not
+ September 22. This affects only the time zone abbreviation for
+ Europe/Rome between those dates. (Thanks to Stephen Trainor and
+ Luigi Rosa.)
+
+ Changes affecting metadata only
+
+ Add info about the Crimea situation in zone1970.tab and zone.tab.
+ (Problem reported by Serhii Demediuk.)
+
+ Changes to code
+
+ zic's new -b option supports a way to control data bloat and to
+ test for year-2038 bugs in software that reads TZif files.
+ 'zic -b fat' and 'zic -b slim' generate larger and smaller output;
+ for example, changing from fat to slim shrinks the Europe/London
+ file from 3648 to 1599 bytes, saving about 56%. Fat and slim
+ files represent the same set of timestamps and use the same TZif
+ format as documented in tzfile(5) and in Internet RFC 8536.
+ Fat format attempts to work around bugs or incompatibilities in
+ older software, notably software that mishandles 64-bit TZif data
+ or uses obsolete TZ strings like "EET-2EEST" that lack DST rules.
+ Slim format is more efficient and does not work around 64-bit bugs
+ or obsolete TZ strings. Currently zic defaults to fat format
+ unless you compile with -DZIC_BLOAT_DEFAULT=\"slim\"; this
+ out-of-the-box default is intended to change in future releases
+ as the buggy software often mishandles timestamps anyway.
+
+ zic no longer treats a set of rules ending in 2037 specially.
+ Previously, zic assumed that such a ruleset meant that future
+ timestamps could not be predicted, and therefore omitted a
+ POSIX-like TZ string in the TZif output. The old behavior is no
+ longer needed for current tzdata, and caused problems with newlib
+ when used with older tzdata (reported by David Gauchard).
+
+ zic no longer generates some artifact transitions. For example,
+ Europe/London no longer has a no-op transition in January 1996.
+
+ Changes to build procedure
+
+ tzdata.zi now assumes zic 2017c or later. This shrinks tzdata.zi
+ by a percent or so.
+
+ Changes to documentation and commentary
+
+ The Makefile now documents the POSIXRULES macro as being obsolete,
+ and similarly, zic's -p POSIXRULES option is now documented as
+ being obsolete. Although the POSIXRULES feature still exists and
+ works as before, in practice it is rarely used for its intended
+ purpose, and it does not work either in the default reference
+ implementation (for timestamps after 2037) or in common
+ implementations such as GNU/Linux (for contemporary timestamps).
+ Since POSIXRULES was designed primarily as a temporary transition
+ facility for System V platforms that died off decades ago, it is
+ being decommissioned rather than institutionalized.
+
+ New info on Bonin Islands and Marcus (thanks to Wakaba and Phake Nick).
+
+
+Release 2019a - 2019-03-25 22:01:33 -0700
+
+ Briefly:
+ Palestine "springs forward" on 2019-03-30 instead of 2019-03-23.
+ Metlakatla "fell back" to rejoin Alaska Time on 2019-01-20 at 02:00.
+
+ Changes to past and future timestamps
+
+ Palestine will not start DST until 2019-03-30, instead of 2019-03-23 as
+ previously predicted. Adjust our prediction by guessing that spring
+ transitions will be between 24 and 30 March, which matches recent practice
+ since 2016. (Thanks to Even Scharning and Tim Parenti.)
+
+ Metlakatla ended its observance of Pacific standard time,
+ rejoining Alaska Time, on 2019-01-20 at 02:00. (Thanks to Ryan
+ Stanley and Tim Parenti.)
+
+ Changes to past timestamps
+
+ Israel observed DST in 1980 (08-02/09-13) and 1984 (05-05/08-25).
+ (Thanks to Alois Treindl and Isaac Starkman.)
+
+ Changes to time zone abbreviations
+
+ Etc/UCT is now a backward-compatibility link to Etc/UTC, instead
+ of being a separate zone that generates the abbreviation "UCT",
+ which nowadays is typically a typo. (Problem reported by Isiah
+ Meadows.)
+
+ 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/>.
+
+
+Release 2018i - 2018-12-30 11:05:43 -0800
+
+ Briefly:
+ São Tomé and Príncipe switches from +01 to +00 on 2019-01-01.
+
+ Changes to future timestamps
+
+ Due to a change in government, São Tomé and Príncipe switches back
+ from +01 to +00 on 2019-01-01 at 02:00. (Thanks to Vadim
+ Nasardinov and Michael Deckers.)
+
+
+Release 2018h - 2018-12-23 17:59:32 -0800
+
+ Briefly:
+ Qyzylorda, Kazakhstan moved from +06 to +05 on 2018-12-21.
+ New zone Asia/Qostanay because Qostanay, Kazakhstan didn't move.
+ Metlakatla, Alaska observes PST this winter only.
+ Guess Morocco will continue to adjust clocks around Ramadan.
+ Add predictions for Iran from 2038 through 2090.
+
+ Changes to future timestamps
+
+ Guess that Morocco will continue to fall back just before and
+ spring forward just after Ramadan, the practice since 2012.
+ (Thanks to Maamar Abdelkader.) This means Morocco will observe
+ negative DST during Ramadan in main and vanguard formats, and in
+ rearguard format it stays in the +00 timezone and observes
+ ordinary DST in all months other than Ramadan. As before, extend
+ this guesswork to the year 2037. As a consequence, Morocco is
+ scheduled to observe three DST transitions in some Gregorian years
+ (e.g., 2033) due to the mismatch between the Gregorian and Islamic
+ calendars.
+
+ The table of exact transitions for Iranian DST has been extended.
+ It formerly cut off before the year 2038 in a nod to 32-bit time_t.
+ It now cuts off before 2091 as there is doubt about how the Persian
+ calendar will treat 2091. This change predicts DST transitions in
+ 2038-9, 2042-3, and 2046-7 to occur one day later than previously
+ predicted. As before, post-cutoff transitions are approximated.
+
+ Changes to past and future timestamps
+
+ Qyzylorda (aka Kyzylorda) oblast in Kazakhstan moved from +06 to
+ +05 on 2018-12-21. This is a zone split as Qostanay (aka
+ Kostanay) did not switch, so create a zone Asia/Qostanay.
+
+ Metlakatla moved from Alaska to Pacific standard time on 2018-11-04.
+ It did not change clocks that day and remains on -08 this winter.
+ (Thanks to Ryan Stanley.) It will revert to the usual Alaska
+ rules next spring, so this change affects only timestamps
+ from 2018-11-04 through 2019-03-10.
+
+ Change to past timestamps
+
+ Kwajalein's 1993-08-20 transition from -12 to +12 was at 24:00,
+ not 00:00. I transcribed the time incorrectly from Shanks.
+ (Thanks to Phake Nick.)
+
+ Nauru's 1979 transition was on 02-10 at 02:00, not 05-01 at 00:00.
+ (Thanks to Phake Nick.)
+
+ Guam observed DST irregularly from 1959 through 1977.
+ (Thanks to Phake Nick.)
+
+ Hong Kong observed DST in 1941 starting 06-15 (not 04-01), then on
+ 10-01 changed standard time to +08:30 (not +08). Its transition
+ back to +08 after WWII was on 1945-09-15, not the previous day.
+ Its 1904-10-30 change took effect at 01:00 +08 (not 00:00 LMT).
+ (Thanks to Phake Nick, Steve Allen, and Joseph Myers.) Also,
+ its 1952 fallback was on 11-02 (not 10-25).
+
+ This release contains many changes to timestamps before 1946 due
+ to Japanese possession or occupation of Pacific/Chuuk,
+ Pacific/Guam, Pacific/Kosrae, Pacific/Kwajalein, Pacific/Majuro,
+ Pacific/Nauru, Pacific/Palau, and Pacific/Pohnpei.
+ (Thanks to Phake Nick.)
+
+ Assume that the Spanish East Indies was like the Philippines and
+ observed American time until the end of 1844. This affects
+ Pacific/Chuuk, Pacific/Kosrae, Pacific/Palau, and Pacific/Pohnpei.
+
+ Changes to past tm_isdst flags
+
+ For the recent Morocco change, the tm_isdst flag should be 1 from
+ 2018-10-27 00:00 to 2018-10-28 03:00. (Thanks to Michael Deckers.)
+ Give a URL to the official decree. (Thanks to Matt Johnson.)
+
+
+Release 2018g - 2018-10-26 22:22:45 -0700
+
+ Briefly:
+ Morocco switches to permanent +01 on 2018-10-28.
+
+ Changes to future timestamps
+
+ Morocco switches from +00/+01 to permanent +01 effective 2018-10-28,
+ so its clocks will not fall back as previously scheduled.
+ (Thanks to Mohamed Essedik Najd and Brian Inglis.)
+
+ Changes to code
+
+ When generating TZif files with leap seconds, zic no longer uses a
+ format that trips up older 32-bit clients, fixing a bug introduced
+ in 2018f. (Reported by Daniel Fischer.) Also, the zic workaround
+ for QTBUG-53071 now also works for TZif files with leap seconds.
+
+ The translator to rearguard format now rewrites the line
+ "Rule Japan 1948 1951 - Sep Sat>=8 25:00 0 S" to
+ "Rule Japan 1948 1951 - Sep Sun>=9 1:00 0 S".
+ This caters to zic before 2007 and to Oracle TZUpdater 2.2.0
+ and earlier. (Reported by Christos Zoulas.)
+
+ Changes to past time zone abbreviations
+
+ Change HDT to HWT/HPT for WWII-era abbreviations in Hawaii.
+ This reverts to 2011h, as the abbreviation change in 2011i was
+ likely inadvertent.
+
+ Changes to documentation
+
+ tzfile.5 has new sections on interoperability issues.
+
+
+Release 2018f - 2018-10-18 00:14:18 -0700
+
+ Briefly:
+ Volgograd moves from +03 to +04 on 2018-10-28.
+ Fiji ends DST 2019-01-13, not 2019-01-20.
+ Most of Chile changes DST dates, effective 2019-04-06.
+
+ Changes to future timestamps
+
+ Volgograd moves from +03 to +04 on 2018-10-28 at 02:00.
+ (Thanks to Alexander Fetisov and Stepan Golosunov.)
+
+ Fiji ends DST 2019-01-13 instead of the 2019-01-20 previously
+ predicted. (Thanks to Raymond Kumar.) Adjust future predictions
+ accordingly.
+
+ Most of Chile will end DST on the first Saturday in April at 24:00 mainland
+ time, and resume DST on the first Saturday in September at 24:00 mainland
+ time. The changes are effective from 2019-04-06, and do not affect the
+ Magallanes region modeled by America/Punta_Arenas. (Thanks to Juan Correa
+ and Tim Parenti.) Adjust future predictions accordingly.
+
+ Changes to past timestamps
+
+ The 2018-05-05 North Korea 30-minute time zone change took place
+ at 23:30 the previous day, not at 00:00 that day.
+
+ China's 1988 spring-forward transition was on April 17, not
+ April 10. Its DST transitions in 1986/91 were at 02:00, not 00:00.
+ (Thanks to P Chan.)
+
+ Fix several issues for Macau before 1992. Macau's pre-1904 LMT
+ was off by 10 s. Macau switched to +08 in 1904 not 1912, and
+ temporarily switched to +09/+10 during World War II. Macau
+ observed DST in 1942/79, not 1961/80, and there were several
+ errors for transition times and dates. (Thanks to P Chan.)
+
+ The 1948-1951 fallback transitions in Japan were at 25:00 on
+ September's second Saturday, not at 24:00. (Thanks to Phake Nick.)
+ zic turns this into 01:00 on the day after September's second
+ Saturday, which is the best that POSIX or C platforms can do.
+
+ Incorporate 1940-1949 Asia/Shanghai DST transitions from a 2014
+ paper by Li Yu, replacing more-questionable data from Shanks.
+
+ Changes to time zone abbreviations
+
+ Use "PST" and "PDT" for Philippine time. (Thanks to Paul Goyette.)
+
+ 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 timestamps 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.)
+
+ Changes to build procedure
+
+ New 'make' target 'rearguard_tarballs' to build the rearguard
+ tarball only. This is a convenience on platforms that lack lzip
+ if you want to build the rearguard tarball. (Problem reported by
+ Deborah Goldsmith.)
+
+ tzdata.zi is now more stable from release to release. (Problem
+ noted by Tom Lane.) It is also a bit shorter.
+
+ tzdata.zi now can contain comment lines documenting configuration
+ information, such as which data format was selected, which input
+ files were used, and how leap seconds are treated. (Problems
+ noted by Lester Caine and Brian Inglis.) If the Makefile defaults
+ are used these comment lines are absent, for backward
+ compatibility. A redistributor intending to alter its copy of the
+ files should also append "-LABEL" to the 'version' file's first
+ line, where "LABEL" identifies the redistributor's change.
+
+
+Release 2018e - 2018-05-01 23:42:51 -0700
+
+ Briefly:
+
+ North Korea switches back to +09 on 2018-05-05.
+ The main format uses negative DST again, for Ireland etc.
+ 'make tarballs' now also builds a rearguard tarball.
+ New 's' and 'd' suffixes in SAVE columns of Rule and Zone lines.
+
+ Changes to past and future timestamps
+
+ North Korea switches back from +0830 to +09 on 2018-05-05.
+ (Thanks to Kang Seonghoon, Arthur David Olson, Seo Sanghyeon,
+ and Tim Parenti.)
+
+ Bring back the negative-DST changes of 2018a, except be more
+ compatible with data parsers that do not support negative DST.
+ Also, this now affects historical timestamps in Namibia and the
+ former Czechoslovakia, not just Ireland. The main format now uses
+ negative DST to model timestamps in Europe/Dublin (from 1971 on),
+ Europe/Prague (1946/7), and Africa/Windhoek (1994/2017). This
+ does not affect UT offsets, only time zone abbreviations and the
+ tm_isdst flag. Also, this does not affect rearguard or vanguard
+ formats; effectively the main format now uses vanguard instead of
+ rearguard format. Data parsers that do not support negative DST
+ can still use data from the rearguard tarball described below.
+
+ Changes to build procedure
+
+ The command 'make tarballs' now also builds the tarball
+ tzdataVERSION-rearguard.tar.gz, which is like tzdataVERSION.tar.gz
+ except that it uses rearguard format intended for trailing-edge
+ data parsers.
+
+ Changes to data format and to code
+
+ The SAVE column of Rule and Zone lines can now have an 's' or 'd'
+ suffix, which specifies whether the adjusted time is standard time
+ or daylight saving time. If no suffix is given, daylight saving
+ time is used if and only if the SAVE column is nonzero; this is
+ the longstanding behavior. Although this new feature is not used
+ in tzdata, it could be used to specify the legal time in Namibia
+ 1994-2017, as opposed to the popular time (see below).
+
+ Changes to past timestamps
+
+ From 1994 through 2017 Namibia observed DST in winter, not summer.
+ That is, it used negative DST, as Ireland still does. This change
+ does not affect UTC offsets; it affects only the tm_isdst flag and
+ the abbreviation used during summer, which is now CAT, not WAST.
+ Although (as noted by Michael Deckers) summer and winter time were
+ both simply called "standard time" in Namibian law, in common
+ practice winter time was considered to be DST (as noted by Stephen
+ Colebourne). The full effect of this change is only in vanguard
+ and main format; in rearguard format, the tm_isdst flag is still
+ zero in winter and nonzero in summer.
+
+ In 1946/7 Czechoslovakia also observed negative DST in winter.
+ The full effect of this change is only in vanguard and main
+ formats; in rearguard format, it is modeled as plain GMT without
+ daylight saving. Also, the dates of some 1944/5 DST transitions
+ in Czechoslovakia have been changed.
+
+
+Release 2018d - 2018-03-22 07:05:46 -0700
+
+ Briefly:
+
+ Palestine starts DST a week earlier in 2018.
+ Add support for vanguard and rearguard data consumers.
+ Add subsecond precision to source data format, though not to data.
+
+ Changes to future timestamps
+
+ In 2018, Palestine starts DST on March 24, not March 31.
+ Adjust future predictions accordingly. (Thanks to Sharef Mustafa.)
+
+ Changes to past and future timestamps
+
+ Casey Station in Antarctica changed from +11 to +08 on 2018-03-11
+ at 04:00. (Thanks to Steffen Thorsen.)
+
+ Changes to past timestamps
+
+ Historical transitions for Uruguay, represented by
+ America/Montevideo, have been updated per official legal documents,
+ replacing previous data mainly originating from the inventions of
+ Shanks & Pottenger. This has resulted in adjustments ranging from
+ 30 to 90 minutes in either direction over at least two dozen
+ distinct periods ranging from one day to several years in length.
+ A mere handful of pre-1991 transitions are unaffected; data since
+ then has come from more reliable contemporaneous reporting. These
+ changes affect various timestamps in 1920-1923, 1936, 1939,
+ 1942-1943, 1959, 1966-1970, 1972, 1974-1980, and 1988-1990.
+ Additionally, Uruguay's pre-standard-time UT offset has been
+ adjusted westward by 7 seconds, from UT-03:44:44 to UT-03:44:51, to
+ match the location of the Observatory of the National Meteorological
+ Institute in Montevideo.
+ (Thanks to Jeremie Bonjour, Tim Parenti, and Michael Deckers.)
+
+ East Kiribati skipped New Year's Eve 1994, not New Year's Day 1995.
+ (Thanks to Kerry Shetline.)
+
+ Fix the 1912-01-01 transition for Portugal and its colonies.
+ This transition was at 00:00 according to the new UT offset, not
+ according to the old one. Also assume that Cape Verde switched on
+ the same date as the rest, not in 1907. This affects
+ Africa/Bissau, Africa/Sao_Tome, Asia/Macau, Atlantic/Azores,
+ Atlantic/Cape_Verde, Atlantic/Madeira, and Europe/Lisbon.
+ (Thanks to Michael Deckers.)
+
+ Fix an off-by-1 error for pre-1913 timestamps in Jamaica and in
+ Turks & Caicos.
+
+ Changes to past time zone abbreviations
+
+ MMT took effect in Uruguay from 1908-06-10, not 1898-06-28. There
+ is no clock change associated with the transition.
+
+ Changes to build procedure
+
+ The new DATAFORM macro in the Makefile lets the installer choose
+ among three source data formats. The idea is to lessen downstream
+ disruption when data formats are improved.
+
+ * DATAFORM=vanguard installs from the latest, bleeding-edge
+ format. DATAFORM=main (the default) installs from the format
+ used in the 'africa' etc. files. DATAFORM=rearguard installs
+ from a trailing-edge format. Eventually, elements of today's
+ vanguard format should move to the main format, and similarly
+ the main format's features should eventually move to the
+ rearguard format.
+
+ * In the current version, the main and rearguard formats are
+ identical and match that of 2018c, so this change does not
+ affect default behavior. The vanguard format currently contains
+ one feature not in the main format: negative SAVE values. This
+ improves support for Ireland, which uses Irish Standard Time
+ (IST, UTC+01) in summer and GMT (UTC) in winter. tzcode has
+ supported negative SAVE values for decades, and this feature
+ should move to the main format soon. However, it will not move
+ to the rearguard format for quite some time because some
+ downstream parsers do not support it.
+
+ * The build procedure constructs three files vanguard.zi, main.zi,
+ and rearguard.zi, one for each format. Although the files
+ represent essentially the same data, they may have minor
+ discrepancies that users are not likely to notice. The files
+ are intended for downstream data consumers and are not
+ installed. Zoneinfo parsers that do not support negative SAVE values
+ should start using rearguard.zi, so that they will be unaffected
+ when the negative-DST feature moves from vanguard to main.
+ Bleeding-edge Zoneinfo parsers that support the new features
+ already can use vanguard.zi; in this respect, current tzcode is
+ bleeding-edge.
+
+ The Makefile should now be safe for parallelized builds, and 'make
+ -j to2050new.tzs' is now much faster on a multiprocessor host
+ with GNU Make.
+
+ When built with -DSUPPRESS_TZDIR, the tzcode library no longer
+ prepends TZDIR/ to file names that do not begin with '/'. This is
+ not recommended for general use, due to its security implications.
+ (From a suggestion by Manuela Friedrich.)
+
+ Changes to code
+
+ zic now accepts subsecond precision in expressions like
+ 00:19:32.13, which is approximately the legal time of the
+ Netherlands from 1835 to 1937. However, because it is
+ questionable whether the few recorded uses of non-integer offsets
+ had subsecond precision in practice, there are no plans for tzdata
+ to use this feature. (Thanks to Steve Allen for pointing out
+ the limitations of historical data in this area.)
+
+ The code is a bit more portable to MS-Windows. Installers can
+ compile with -DRESERVE_STD_EXT_IDS on MS-Windows platforms that
+ reserve identifiers like 'localtime'. (Thanks to Manuela
+ Friedrich.)
+
+ Changes to documentation and commentary
+
+ theory.html now outlines tzdb's extensions to POSIX's model for
+ civil time, and has a section "POSIX features no longer needed"
+ that lists POSIX API components that are now vestigial.
+ (From suggestions by Steve Summit.) It also better distinguishes
+ time zones from tz regions. (From a suggestion by Guy Harris.)
+
+ Commentary is now more consistent about using the phrase "daylight
+ saving time", to match the C name tm_isdst. Daylight saving time
+ need not occur in summer, and need not have a positive offset from
+ standard time.
+
+ Commentary about historical transitions in Uruguay has been expanded
+ with links to many relevant legal documents.
+ (Thanks to Tim Parenti.)
+
+ Commentary now uses some non-ASCII characters with Unicode value
+ less than U+0100, as they can be useful and should work even with
+ older editors such as XEmacs.
+
+
+Release 2018c - 2018-01-22 23:00:44 -0800
+
+ Briefly:
+ Revert Irish changes that relied on negative SAVE values.
+
+ Changes to tm_isdst
+
+ Revert the 2018a change to Europe/Dublin. As before, this change
+ does not affect UT offsets or abbreviations; it affects only
+ whether timestamps are considered to be standard time or
+ daylight-saving time, as expressed in the tm_isdst flag of C's
+ struct tm type. This reversion is intended to be a temporary
+ workaround for problems discovered with downstream uses of
+ releases 2018a and 2018b, which implemented Irish time by using
+ negative SAVE values in the Eire rules of the 'europe' file.
+ Although negative SAVE values have been part of tzcode for many
+ years and are supported by many platforms, they were not
+ documented before 2018a and ICU and OpenJDK do not currently
+ support them. A mechanism to export data to platforms lacking
+ support for negative DST is planned to be developed before the
+ change is reapplied. (Problems reported by Deborah Goldsmith and
+ Stephen Colebourne.)
+
+ Changes to past timestamps
+
+ Japanese DST transitions (1948-1951) were Sundays at 00:00, not
+ Saturdays or Sundays at 02:00. (Thanks to Takayuki Nikai.)
+
+ 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
+
+ Briefly:
+ Fix a packaging problem in tz2018a, which was missing 'pacificnew'.
+
+ Changes to build procedure
+
+ The distribution now contains the file 'pacificnew' again.
+ This file was inadvertently omitted in the 2018a distribution.
+ (Problem reported by Matias Fonzo.)
+
+
+Release 2018a - 2018-01-12 22:29:21 -0800
+
+ Briefly:
+ São Tomé and Príncipe switched from +00 to +01.
+ Brazil's DST will now start on November's first Sunday.
+ Ireland's standard time is now in the summer, not the winter.
+ Use Debian-style installation locations, instead of 4.3BSD-style.
+ New zic option -t.
+
+ Changes to past and future timestamps
+
+ São Tomé and Príncipe switched from +00 to +01 on 2018-01-01 at
+ 01:00. (Thanks to Steffen Thorsen and Michael Deckers.)
+
+ Changes to future timestamps
+
+ Starting in 2018 southern Brazil will begin DST on November's
+ first Sunday instead of October's third Sunday. (Thanks to
+ Steffen Thorsen.)
+
+ Changes to past timestamps
+
+ A discrepancy of 4 s in timestamps before 1931 in South Sudan has
+ been corrected. The 'backzone' and 'zone.tab' files did not agree
+ with the 'africa' and 'zone1970.tab' files. (Problem reported by
+ Michael Deckers.)
+
+ The abbreviation invented for Bolivia Summer Time (1931-2) is now
+ BST instead of BOST, to be more consistent with the convention
+ used for Latvian Summer Time (1918-9) and for British Summer Time.
+
+ Changes to tm_isdst
+
+ Change Europe/Dublin so that it observes Irish Standard Time (UT
+ +01) in summer and GMT (as negative daylight-saving) in winter,
+ instead of observing standard time (GMT) in winter and Irish
+ Summer Time (UT +01) in summer. This change does not affect UT
+ offsets or abbreviations; it affects only whether timestamps are
+ considered to be standard time or daylight-saving time, as
+ expressed in the tm_isdst flag of C's struct tm type.
+ (Discrepancy noted by Derick Rethans.)
+
+ 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.
+
+
+Release 2017c - 2017-10-20 14:49:34 -0700
+
+ Briefly:
+ Northern Cyprus switches from +03 to +02/+03 on 2017-10-29.
+ Fiji ends DST 2018-01-14, not 2018-01-21.
+ Namibia switches from +01/+02 to +02 on 2018-04-01.
+ Sudan switches from +03 to +02 on 2017-11-01.
+ Tonga likely switches from +13/+14 to +13 on 2017-11-05.
+ Turks & Caicos switches from -04 to -05/-04 on 2018-11-04.
+ A new file tzdata.zi now holds a small text copy of all data.
+ The zic input format has been regularized slightly.
+
+ Changes to future timestamps
+
+ Northern Cyprus has decided to resume EU rules starting
+ 2017-10-29, thus reinstituting winter time.
+
+ Fiji ends DST 2018-01-14 instead of the 2018-01-21 previously
+ predicted. (Thanks to Dominic Fok.) Adjust future predictions
+ accordingly.
+
+ Namibia will switch from +01 with DST to +02 all year on
+ 2017-09-03 at 02:00. This affects UT offsets starting 2018-04-01
+ at 02:00. (Thanks to Steffen Thorsen.)
+
+ Sudan will switch from +03 to +02 on 2017-11-01. (Thanks to Ahmed
+ Atyya and Yahia Abdalla.) South Sudan is not switching, so
+ Africa/Juba is no longer a link to Africa/Khartoum.
+
+ Tonga has likely ended its experiment with DST, and will not
+ adjust its clocks on 2017-11-05. Although Tonga has not announced
+ whether it will continue to observe DST, the IATA is assuming that
+ it will not. (Thanks to David Wade.)
+
+ Turks & Caicos will switch from -04 all year to -05 with US DST on
+ 2018-03-11 at 03:00. This affects UT offsets starting 2018-11-04
+ at 02:00. (Thanks to Steffen Thorsen.)
+
+ Changes to past timestamps
+
+ Namibia switched from +02 to +01 on 1994-03-21, not 1994-04-03.
+ (Thanks to Arthur David Olson.)
+
+ Detroit did not observe DST in 1967.
+
+ Use railway time for Asia/Kolkata before 1941, by switching to
+ Madras local time (UT +052110) in 1870, then to IST (UT +0530) in
+ 1906. Also, treat 1941-2's +0630 as DST, like 1942-5.
+
+ Europe/Dublin's 1946 and 1947 fallback transitions occurred at
+ 02:00 standard time, not 02:00 DST. (Thanks to Michael Deckers.)
+
+ Pacific/Apia and Pacific/Pago_Pago switched from Antipodean to
+ American time in 1892, not 1879. (Thanks to Michael Deckers.)
+
+ Adjust the 1867 transition in Alaska to better reflect the
+ historical record, by changing it to occur on 1867-10-18 at 15:30
+ Sitka time rather than at the start of 1867-10-17 local time.
+ Although strictly speaking this is accurate only for Sitka,
+ the rest of Alaska's blanks need to be filled in somehow.
+
+ Fix off-by-one errors in UT offsets for Adak and Nome before 1867.
+ (Thanks to Michael Deckers.)
+
+ Add 7 s to the UT offset in Asia/Yangon before 1920.
+
+ Changes to zone names
+
+ Remove Canada/East-Saskatchewan from the 'backward' file, as it
+ exceeded the 14-character limit and was an unused misnomer anyway.
+
+ Changes to build procedure
+
+ To support applications that prefer to read time zone data in text
+ form, two zic input files tzdata.zi and leapseconds are now
+ installed by default. The commands 'zic tzdata.zi' and 'zic -L
+ leapseconds tzdata.zi' can reproduce the tzdata binary files
+ without and with leap seconds, respectively. To prevent these two
+ new files from being installed, use 'make TZDATA_TEXT=', and to
+ suppress leap seconds from the tzdata text installation, use 'make
+ TZDATA_TEXT=tzdata.zi'.
+
+ 'make BACKWARD=' now suppresses backward-compatibility names
+ like 'US/Pacific' that are defined in the 'backward' and
+ 'pacificnew' files.
+
+ 'make check' now works on systems that lack a UTF-8 locale,
+ or that lack the nsgmls program. Set UTF8_LOCALE to configure
+ the name of a UTF-8 locale, if you have one.
+
+ Y2K runtime checks are no longer enabled by default. Add
+ -DDEPRECATE_TWO_DIGIT_YEARS to CFLAGS to enable them, instead of
+ adding -DNO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU
+ to disable them. (New name suggested by Brian Inglis.)
+
+ The build procedure for zdump now works on AIX 7.1.
+ (Problem reported by Kees Dekker.)
+
+ Changes to code
+
+ zic and the reference runtime now reject multiple leap seconds
+ within 28 days of each other, or leap seconds before the Epoch.
+ As a result, support for double leap seconds, which was
+ obsolescent and undocumented, has been removed. Double leap
+ seconds were an error in the C89 standard; they have never existed
+ in civil timekeeping. (Thanks to Robert Elz and Bradley White for
+ noticing glitches in the code that uncovered this problem.)
+
+ zic now warns about use of the obsolescent and undocumented -y
+ option, and about use of the obsolescent TYPE field of Rule lines.
+
+ zic now allows unambiguous abbreviations like "Sa" and "Su" for
+ weekdays; formerly it rejected them due to a bug. Conversely, zic
+ no longer considers non-prefixes to be abbreviations; for example,
+ it no longer accepts "lF" as an abbreviation for "lastFriday".
+ Also, zic warns about the undocumented usage with a "last-"
+ prefix, e.g., "last-Fri".
+
+ Similarly, zic now accepts the unambiguous abbreviation "L" for
+ "Link" in ordinary context and for "Leap" in leap-second context.
+ Conversely, zic no longer accepts non-prefixes such as "La" as
+ abbreviations for words like "Leap".
+
+ zic no longer accepts leap second lines in ordinary input, or
+ ordinary lines in leap second input. Formerly, zic sometimes
+ warned about this undocumented usage and handled it incorrectly.
+
+ The new macro HAVE_TZNAME governs whether the tzname external
+ variable is exported, instead of USG_COMPAT. USG_COMPAT now
+ governs only the external variables "timezone" and "daylight".
+ This change is needed because the three variables are not in the
+ same category: although POSIX requires tzname, it specifies the
+ other two variables as optional. Also, USG_COMPAT is now 1 or 0:
+ if not defined, the code attempts to guess it from other macros.
+
+ localtime.c and difftime.c no longer require stdio.h, and .c files
+ other than zic.c no longer require sys/wait.h.
+
+ zdump.c no longer assumes snprintf. (Reported by Jonathan Leffler.)
+
+ Calculation of time_t extrema works around a bug in GCC 4.8.4
+ (Reported by Stan Shebs and Joseph Myers.)
+
+ zic.c no longer mistranslates formats of line numbers in non-English
+ locales. (Problem reported by Benno Schulenberg.)
+
+ Several minor changes have been made to the code to make it a
+ bit easier to port to MS-Windows and Solaris. (Thanks to Kees
+ Dekker for reporting the problems.)
+
+ Changes to documentation and commentary
+
+ The two new files 'theory.html' and 'calendars' contain the
+ contents of the removed file 'Theory'. The goal is to document
+ tzdb theory more accessibly.
+
+ The zic man page now documents abbreviation rules.
+
+ tz-link.htm now covers how to apply tzdata changes to clients.
+ (Thanks to Jorge Fábregas for the AIX link.) It also mentions MySQL.
+
+ The leap-seconds.list URL has been updated to something that is
+ more reliable for tzdb. (Thanks to Tim Parenti and Brian Inglis.)
+
+Release 2017b - 2017-03-17 07:30:38 -0700
+
+ Briefly: Haiti has resumed DST.
+
+ Changes to past and future timestamps
+
+ Haiti resumed observance of DST in 2017. (Thanks to Steffen Thorsen.)
+
+ Changes to past timestamps
+
+ Liberia changed from -004430 to +00 on 1972-01-07, not 1972-05-01.
+
+ Use "MMT" to abbreviate Liberia's time zone before 1972, as "-004430"
+ is one byte over the POSIX limit. (Problem reported by Derick Rethans.)
+
+ Changes to code
+
+ The reference localtime implementation now falls back on the
+ current US daylight-saving transition rules rather than the
+ 1987-2006 rules. This fallback occurs only when (1) the TZ
+ environment variable has a value like "AST4ADT" that asks
+ for daylight saving time but does not specify the rules, (2) there
+ is no file by that name, and (3) the TZDEFRULES file cannot be
+ loaded. (Thanks to Tom Lane.)
+
+
+Release 2017a - 2017-02-28 00:05:36 -0800
+
+ Briefly: Southern Chile moves from -04/-03 to -03, and Mongolia
+ discontinues DST.
+
+ Changes to future timestamps
+
+ Mongolia no longer observes DST. (Thanks to Ganbold Tsagaankhuu.)
+
+ Chile's Region of Magallanes moves from -04/-03 to -03 year-round.
+ Its clocks diverge from America/Santiago starting 2017-05-13 at
+ 23:00, hiving off a new zone America/Punta_Arenas. Although the
+ Chilean government says this change expires in May 2019, for now
+ assume it's permanent. (Thanks to Juan Correa and Deborah
+ Goldsmith.) This also affects Antarctica/Palmer.
+
+ Changes to past timestamps
+
+ Fix many entries for historical timestamps for Europe/Madrid
+ before 1979, to agree with tables compiled by Pere Planesas of the
+ National Astronomical Observatory of Spain. As a side effect,
+ this changes some timestamps for Africa/Ceuta before 1929, which
+ are probably guesswork anyway. (Thanks to Steve Allen and
+ Pierpaolo Bernardi for the heads-ups, and to Michael Deckers for
+ correcting the 1901 transition.)
+
+ Ecuador observed DST from 1992-11-28 to 1993-02-05.
+ (Thanks to Alois Treindl.)
+
+ Asia/Atyrau and Asia/Oral were at +03 (not +04) before 1930-06-21.
+ (Thanks to Stepan Golosunov.)
+
+ Changes to past and future time zone abbreviations
+
+ Switch to numeric time zone abbreviations for South America, as
+ part of the ongoing project of removing invented abbreviations.
+ This avoids the need to invent an abbreviation for the new Chilean
+ new zone. Similarly, switch from invented to numeric time zone
+ abbreviations for Afghanistan, American Samoa, the Azores,
+ Bangladesh, Bhutan, the British Indian Ocean Territory, Brunei,
+ Cape Verde, Chatham Is, Christmas I, Cocos (Keeling) Is, Cook Is,
+ Dubai, East Timor, Eucla, Fiji, French Polynesia, Greenland,
+ Indochina, Iran, Iraq, Kiribati, Lord Howe, Macquarie, Malaysia,
+ the Maldives, Marshall Is, Mauritius, Micronesia, Mongolia,
+ Myanmar, Nauru, Nepal, New Caledonia, Niue, Norfolk I, Palau,
+ Papua New Guinea, the Philippines, Pitcairn, Qatar, Réunion, St
+ Pierre & Miquelon, Samoa, Saudi Arabia, Seychelles, Singapore,
+ Solomon Is, Tokelau, Tuvalu, Wake, Vanuatu, Wallis & Futuna, and
+ Xinjiang; for 20-minute daylight saving time in Ghana before 1943;
+ for half-hour daylight saving time in Belize before 1944 and in
+ the Dominican Republic before 1975; and for Canary Islands before
+ 1946, for Guinea-Bissau before 1975, for Iceland before 1969, for
+ Indian Summer Time before 1942, for Indonesia before around 1964,
+ for Kenya before 1960, for Liberia before 1973, for Madeira before
+ 1967, for Namibia before 1943, for the Netherlands in 1937-9, for
+ Pakistan before 1971, for Western Sahara before 1977, and for
+ Zaporozhye in 1880-1924.
+
+ For Alaska time from 1900 through 1967, instead of "CAT" use the
+ abbreviation "AST", the abbreviation commonly used at the time
+ (Atlantic Standard Time had not been standardized yet). Use "AWT"
+ and "APT" instead of the invented abbreviations "CAWT" and "CAPT".
+
+ Use "CST" and "CDT" instead of invented abbreviations for Macau
+ before 1999 and Taiwan before 1938, and use "JST" instead of the
+ invented abbreviation "JCST" for Japan and Korea before 1938.
+
+ Change to database entry category
+
+ Move the Pacific/Johnston link from 'australasia' to 'backward',
+ since Johnston is now uninhabited.
+
+ Changes to code
+
+ zic no longer mishandles some transitions in January 2038 when it
+ attempts to work around Qt bug 53071. This fixes a bug affecting
+ Pacific/Tongatapu that was introduced in zic 2016e. localtime.c
+ now contains a workaround, useful when loading a file generated by
+ a buggy zic. (Problem and localtime.c fix reported by Bradley
+ White.)
+
+ zdump -i now outputs non-hour numeric time zone abbreviations
+ without a colon, e.g., "+0530" rather than "+05:30". This agrees
+ with zic %z and with common practice, and simplifies auditing of
+ zdump output.
+
+ zdump is now buildable again with -DUSE_LTZ=0.
+ (Problem reported by Joseph Myers.)
+
+ zdump.c now always includes private.h, to avoid code duplication
+ with private.h. (Problem reported by Kees Dekker.)
+
+ localtime.c no longer mishandles early or late timestamps
+ when TZ is set to a POSIX-style string that specifies DST.
+ (Problem reported by Kees Dekker.)
+
+ date and strftime now cause %z to generate "-0000" instead of
+ "+0000" when the UT offset is zero and the time zone abbreviation
+ begins with "-".
+
+ Changes to documentation and commentary
+
+ The 'Theory' file now better documents choice of historical time
+ zone abbreviations. (Problems reported by Michael Deckers.)
+
+ tz-link.htm now covers leap smearing, which is popular in clouds.
+
+
+Release 2016j - 2016-11-22 23:17:13 -0800
+
+ Briefly: Saratov, Russia moves from +03 to +04 on 2016-12-04.
+
+ Changes to future timestamps
+
+ Saratov, Russia switches from +03 to +04 on 2016-12-04 at 02:00.
+ This hives off a new zone Europe/Saratov from Europe/Volgograd.
+ (Thanks to Yuri Konotopov and Stepan Golosunov.)
+
+ Changes to past timestamps
+
+ The new zone Asia/Atyrau for Atyraū Region, Kazakhstan, is like
+ Asia/Aqtau except it switched from +05/+06 to +04/+05 in spring
+ 1999, not fall 1994. (Thanks to Stepan Golosunov.)
+
+ Changes to past time zone abbreviations
+
+ Asia/Gaza and Asia/Hebron now use "EEST", not "EET", to denote
+ summer time before 1948. The old use of "EET" was a typo.
+
+ Changes to code
+
+ zic no longer mishandles file systems that lack hard links, fixing
+ bugs introduced in 2016g. (Problems reported by Tom Lane.)
+ Also, when the destination already contains symbolic links, zic
+ should now work better on systems where the 'link' system call
+ does not follow symbolic links.
+
+ Changes to documentation and commentary
+
+ tz-link.htm now documents the relationship between release version
+ numbers and development-repository commit tags. (Suggested by
+ Paul Koning.)
+
+ The 'Theory' file now documents UT.
+
+ iso3166.tab now accents "Curaçao", and commentary now mentions
+ the names "Cabo Verde" and "Czechia". (Thanks to Jiří Boháč.)
+
+
+Release 2016i - 2016-11-01 23:19:52 -0700
+
+ Briefly: Cyprus split into two time zones on 2016-10-30, and Tonga
+ reintroduces DST on 2016-11-06.
+
+ Changes to future timestamps
+
+ Pacific/Tongatapu begins DST on 2016-11-06 at 02:00, ending on
+ 2017-01-15 at 03:00. Assume future observances in Tonga will be
+ from the first Sunday in November through the third Sunday in
+ January, like Fiji. (Thanks to Pulu ʻAnau.) Switch to numeric
+ time zone abbreviations for this zone.
+
+ Changes to past and future timestamps
+
+ Northern Cyprus is now +03 year round, causing a split in Cyprus
+ time zones starting 2016-10-30 at 04:00. This creates a zone
+ Asia/Famagusta. (Thanks to Even Scharning and Matt Johnson.)
+
+ Antarctica/Casey switched from +08 to +11 on 2016-10-22.
+ (Thanks to Steffen Thorsen.)
+
+ Changes to past timestamps
+
+ Several corrections were made for pre-1975 timestamps in Italy.
+ These affect Europe/Malta, Europe/Rome, Europe/San_Marino, and
+ Europe/Vatican.
+
+ First, the 1893-11-01 00:00 transition in Italy used the new UT
+ offset (+01), not the old (+00:49:56). (Thanks to Michael
+ Deckers.)
+
+ Second, rules for daylight saving in Italy were changed to agree
+ with Italy's National Institute of Metrological Research (INRiM)
+ except for 1944, as follows (thanks to Pierpaolo Bernardi, Brian
+ Inglis, and Michael Deckers):
+
+ The 1916-06-03 transition was at 24:00, not 00:00.
+
+ The 1916-10-01, 1919-10-05, and 1920-09-19 transitions were at
+ 00:00, not 01:00.
+
+ The 1917-09-30 and 1918-10-06 transitions were at 24:00, not
+ 01:00.
+
+ The 1944-09-17 transition was at 03:00, not 01:00. This
+ particular change is taken from Italian law as INRiM's table,
+ (which says 02:00) appears to have a typo here. Also, keep the
+ 1944-04-03 transition for Europe/Rome, as Rome was controlled by
+ Germany then.
+
+ The 1967-1970 and 1972-1974 fallback transitions were at 01:00,
+ not 00:00.
+
+ Changes to code
+
+ The code should now be buildable on AmigaOS merely by setting the
+ appropriate Makefile variables. (From a patch by Carsten Larsen.)
+
+
+Release 2016h - 2016-10-19 23:17:57 -0700
+
+ Changes to future timestamps
+
+ Asia/Gaza and Asia/Hebron end DST on 2016-10-29 at 01:00, not
+ 2016-10-21 at 00:00. (Thanks to Sharef Mustafa.) Predict that
+ future fall transitions will be on the last Saturday of October
+ at 01:00, which is consistent with predicted spring transitions
+ on the last Saturday of March. (Thanks to Tim Parenti.)
+
+ Changes to past timestamps
+
+ In Turkey, transitions in 1986-1990 were at 01:00 standard time
+ not at 02:00, and the spring 1994 transition was on March 20, not
+ March 27. (Thanks to Kıvanç Yazan.)
+
+ Changes to past and future time zone abbreviations
+
+ Asia/Colombo now uses numeric time zone abbreviations like "+0530"
+ instead of alphabetic ones like "IST" and "LKT". Various
+ English-language sources use "IST", "LKT" and "SLST", with no
+ working consensus. (Usage of "SLST" mentioned by Sadika
+ Sumanapala.)
+
+ Changes to code
+
+ zic no longer mishandles relativizing file names when creating
+ symbolic links like /etc/localtime, when these symbolic links
+ are outside the usual directory hierarchy. This fixes a bug
+ introduced in 2016g. (Problem reported by Andreas Stieger.)
+
+ Changes to build procedure
+
+ New rules 'traditional_tarballs' and 'traditional_signatures' for
+ building just the traditional-format distribution. (Requested by
+ Deborah Goldsmith.)
+
+ The file 'version' is now put into the tzdata tarball too.
+ (Requested by Howard Hinnant.)
+
+ Changes to documentation and commentary
+
+ The 'Theory' file now has a section on interface stability.
+ (Requested by Paul Koning.) It also mentions features like
+ tm_zone and localtime_rz that have long been supported by the
+ reference code.
+
+ tz-link.htm has improved coverage of time zone boundaries suitable
+ for geolocation. (Thanks to heads-ups from Evan Siroky and Matt
+ Johnson.)
+
+ The US commentary now mentions Allen and the "day of two noons".
+
+ The Fiji commentary mentions the government's 2016-10-03 press
+ release. (Thanks to Raymond Kumar.)
+
+
+Release 2016g - 2016-09-13 08:56:38 -0700
+
+ Changes to future timestamps
+
+ Turkey switched from EET/EEST (+02/+03) to permanent +03,
+ effective 2016-09-07. (Thanks to Burak AYDIN.) Use "+03" rather
+ than an invented abbreviation for the new time.
+
+ New leap second 2016-12-31 23:59:60 UTC as per IERS Bulletin C 52.
+ (Thanks to Tim Parenti.)
+
+ Changes to past timestamps
+
+ For America/Los_Angeles, spring-forward transition times have been
+ corrected from 02:00 to 02:01 in 1948, and from 02:00 to 01:00 in
+ 1950-1966.
+
+ For zones using Soviet time on 1919-07-01, transitions to UT-based
+ time were at 00:00 UT, not at 02:00 local time. The affected
+ zones are Europe/Kirov, Europe/Moscow, Europe/Samara, and
+ Europe/Ulyanovsk. (Thanks to Alexander Belopolsky.)
+
+ Changes to past and future time zone abbreviations
+
+ The Factory zone now uses the time zone abbreviation -00 instead
+ of a long English-language string, as -00 is now the normal way to
+ represent an undefined time zone.
+
+ Several zones in Antarctica and the former Soviet Union, along
+ with zones intended for ships at sea that cannot use POSIX TZ
+ strings, now use numeric time zone abbreviations instead of
+ invented or obsolete alphanumeric abbreviations. The affected
+ zones are Antarctica/Casey, Antarctica/Davis,
+ Antarctica/DumontDUrville, Antarctica/Mawson, Antarctica/Rothera,
+ Antarctica/Syowa, Antarctica/Troll, Antarctica/Vostok,
+ Asia/Anadyr, Asia/Ashgabat, Asia/Baku, Asia/Bishkek, Asia/Chita,
+ Asia/Dushanbe, Asia/Irkutsk, Asia/Kamchatka, Asia/Khandyga,
+ Asia/Krasnoyarsk, Asia/Magadan, Asia/Omsk, Asia/Sakhalin,
+ Asia/Samarkand, Asia/Srednekolymsk, Asia/Tashkent, Asia/Tbilisi,
+ Asia/Ust-Nera, Asia/Vladivostok, Asia/Yakutsk, Asia/Yekaterinburg,
+ Asia/Yerevan, Etc/GMT-14, Etc/GMT-13, Etc/GMT-12, Etc/GMT-11,
+ Etc/GMT-10, Etc/GMT-9, Etc/GMT-8, Etc/GMT-7, Etc/GMT-6, Etc/GMT-5,
+ Etc/GMT-4, Etc/GMT-3, Etc/GMT-2, Etc/GMT-1, Etc/GMT+1, Etc/GMT+2,
+ Etc/GMT+3, Etc/GMT+4, Etc/GMT+5, Etc/GMT+6, Etc/GMT+7, Etc/GMT+8,
+ Etc/GMT+9, Etc/GMT+10, Etc/GMT+11, Etc/GMT+12, Europe/Kaliningrad,
+ Europe/Minsk, Europe/Samara, Europe/Volgograd, and
+ Indian/Kerguelen. For Europe/Moscow the invented abbreviation MSM
+ was replaced by +05, whereas MSK and MSD were kept as they are not
+ our invention and are widely used.
+
+ Changes to zone names
+
+ Rename Asia/Rangoon to Asia/Yangon, with a backward compatibility link.
+ (Thanks to David Massoud.)
+
+ Changes to code
+
+ zic no longer generates binary files containing POSIX TZ-like
+ strings that disagree with the local time type after the last
+ explicit transition in the data. This fixes a bug with
+ Africa/Casablanca and Africa/El_Aaiun in some year-2037 timestamps
+ on the reference platform. (Thanks to Alexander Belopolsky for
+ reporting the bug and suggesting a way forward.)
+
+ If the installed localtime and/or posixrules files are symbolic
+ links, zic now keeps them symbolic links when updating them, for
+ compatibility with platforms like OpenSUSE where other programs
+ configure these files as symlinks.
+
+ zic now avoids hard linking to symbolic links, avoids some
+ unnecessary mkdir and stat system calls, and uses shorter file
+ names internally.
+
+ zdump has a new -i option to generate transitions in a
+ more-compact but still human-readable format. This option is
+ experimental, and the output format may change in future versions.
+ (Thanks to Jon Skeet for suggesting that an option was needed,
+ and thanks to Tim Parenti and Chris Rovick for further comments.)
+
+ Changes to build procedure
+
+ An experimental distribution format is available, in addition
+ to the traditional format which will continue to be distributed.
+ The new format is a tarball tzdb-VERSION.tar.lz with signature
+ file tzdb-VERSION.tar.lz.asc. It unpacks to a top-level directory
+ tzdb-VERSION containing the code and data of the traditional
+ two-tarball format, along with extra data that may be useful.
+ (Thanks to Antonio Diaz Diaz, Oscar van Vlijmen, and many others
+ for comments about the experimental format.)
+
+ The release version number is now more accurate in the usual case
+ where releases are built from a Git repository. For example, if
+ 23 commits and some working-file changes have been made since
+ release 2016g, the version number is now something like
+ '2016g-23-g50556e3-dirty' instead of the misleading '2016g'.
+ Tagged releases use the same version number format as before,
+ e.g., '2016g'. To support the more-accurate version number, its
+ specification has moved from a line in the Makefile to a new
+ source file 'version'.
+
+ The experimental distribution contains a file to2050.tzs that
+ contains what should be the output of 'zdump -i -c 2050' on
+ primary zones. If this file is available, 'make check' now checks
+ that zdump generates this output.
+
+ 'make check_web' now works on Fedora-like distributions.
+
+ Changes to documentation and commentary
+
+ tzfile.5 now documents the new restriction on POSIX TZ-like
+ strings that is now implemented by zic.
+
+ Comments now cite URLs for some 1917-1921 Russian DST decrees.
+ (Thanks to Alexander Belopolsky.)
+
+ tz-link.htm mentions JuliaTime (thanks to Curtis Vogt) and Time4J
+ (thanks to Meno Hochschild) and ThreeTen-Extra, and its
+ description of Java 8 has been brought up to date (thanks to
+ Stephen Colebourne). Its description of local time on Mars has
+ been updated to match current practice, and URLs have been updated
+ and some obsolete ones removed.
+
+
+Release 2016f - 2016-07-05 16:26:51 +0200
+
+ Changes affecting future timestamps
+
+ The Egyptian government changed its mind on short notice, and
+ Africa/Cairo will not introduce DST starting 2016-07-07 after all.
+ (Thanks to Mina Samuel.)
+
+ Asia/Novosibirsk switches from +06 to +07 on 2016-07-24 at 02:00.
+ (Thanks to Stepan Golosunov.)
+
+ Changes to past and future timestamps
+
+ Asia/Novokuznetsk and Asia/Novosibirsk now use numeric time zone
+ abbreviations instead of invented ones.
+
+ Changes affecting past timestamps
+
+ Europe/Minsk's 1992-03-29 spring-forward transition was at 02:00 not 00:00.
+ (Thanks to Stepan Golosunov.)
+
+
+Release 2016e - 2016-06-14 08:46:16 -0700
+
+ Changes affecting future timestamps
+
+ Africa/Cairo observes DST in 2016 from July 7 to the end of October.
+ Guess October 27 and 24:00 transitions. (Thanks to Steffen Thorsen.)
+ For future years, guess April's last Thursday to October's last
+ Thursday except for Ramadan.
+
+ Changes affecting past timestamps
+
+ Locations while uninhabited now use '-00', not 'zzz', as a
+ placeholder time zone abbreviation. This is inspired by Internet
+ RFC 3339 and is more consistent with numeric time zone
+ abbreviations already used elsewhere. The change affects several
+ arctic and antarctic locations, e.g., America/Cambridge_Bay before
+ 1920 and Antarctica/Troll before 2005.
+
+ Asia/Baku's 1992-09-27 transition from +04 (DST) to +04 (non-DST) was
+ at 03:00, not 23:00 the previous day. (Thanks to Michael Deckers.)
+
+ Changes to code
+
+ zic now outputs a dummy transition at time 2**31 - 1 in zones
+ whose POSIX-style TZ strings contain a '<'. This mostly works
+ around Qt bug 53071 <https://bugreports.qt.io/browse/QTBUG-53071>.
+ (Thanks to Zhanibek Adilbekov for reporting the Qt bug.)
+
+ Changes affecting documentation and commentary
+
+ tz-link.htm says why governments should give plenty of notice for
+ time zone or DST changes, and refers to Matt Johnson's blog post.
+
+ tz-link.htm mentions Tzdata for Elixir. (Thanks to Matt Johnson.)
+
+
+Release 2016d - 2016-04-17 22:50:29 -0700
+
+ Changes affecting future timestamps
+
+ America/Caracas switches from -0430 to -04 on 2016-05-01 at 02:30.
+ (Thanks to Alexander Krivenyshev for the heads-up.)
+
+ Asia/Magadan switches from +10 to +11 on 2016-04-24 at 02:00.
+ (Thanks to Alexander Krivenyshev and Matt Johnson.)
+
+ New zone Asia/Tomsk, split off from Asia/Novosibirsk. It covers
+ Tomsk Oblast, Russia, which switches from +06 to +07 on 2016-05-29
+ at 02:00. (Thanks to Stepan Golosunov.)
+
+ Changes affecting past timestamps
+
+ New zone Europe/Kirov, split off from Europe/Volgograd. It covers
+ Kirov Oblast, Russia, which switched from +04/+05 to +03/+04 on
+ 1989-03-26 at 02:00, roughly a year after Europe/Volgograd made
+ the same change. (Thanks to Stepan Golosunov.)
+
+ Russia and nearby locations had daylight-saving transitions on
+ 1992-03-29 at 02:00 and 1992-09-27 at 03:00, instead of on
+ 1992-03-28 at 23:00 and 1992-09-26 at 23:00. (Thanks to Stepan
+ Golosunov.)
+
+ Many corrections to historical time in Kazakhstan from 1991
+ through 2005. (Thanks to Stepan Golosunov.) Replace Kazakhstan's
+ invented time zone abbreviations with numeric abbreviations.
+
+ Changes to commentary
+
+ Mention Internet RFCs 7808 (TZDIST) and 7809 (CalDAV time zone references).
+
+
+Release 2016c - 2016-03-23 00:51:27 -0700
+
+ Changes affecting future timestamps
+
+ Azerbaijan no longer observes DST. (Thanks to Steffen Thorsen.)
+
+ Chile reverts from permanent to seasonal DST. (Thanks to Juan
+ Correa for the heads-up, and to Tim Parenti for corrections.)
+ Guess that future transitions are August's and May's second
+ Saturdays at 24:00 mainland time. Also, call the period from
+ 2014-09-07 through 2016-05-14 daylight saving time instead of
+ standard time, as that seems more appropriate now.
+
+ Changes affecting past timestamps
+
+ Europe/Kaliningrad and Europe/Vilnius changed from +03/+04 to
+ +02/+03 on 1989-03-26, not 1991-03-31. Europe/Volgograd changed
+ from +04/+05 to +03/+04 on 1988-03-27, not 1989-03-26.
+ (Thanks to Stepan Golosunov.)
+
+ Changes to commentary
+
+ Several updates and URLs for historical and proposed Russian changes.
+ (Thanks to Stepan Golosunov, Matt Johnson, and Alexander Krivenyshev.)
+
+
+Release 2016b - 2016-03-12 17:30:14 -0800
+
+ Compatibility note
+
+ Starting with release 2016b, some data entries cause zic implementations
+ derived from tz releases 2005j through 2015e to issue warnings like
+ "time zone abbreviation differs from POSIX standard (+03)".
+ These warnings should not otherwise affect zic's output and can safely be
+ ignored on today's platforms, as the warnings refer to a restriction in
+ POSIX.1-1988 that was removed in POSIX.1-2001. One way to suppress the
+ warnings is to upgrade to zic derived from tz releases 2015f and later.
+
+ Changes affecting future timestamps
+
+ New zones Europe/Astrakhan and Europe/Ulyanovsk for Astrakhan and
+ Ulyanovsk Oblasts, Russia, both of which will switch from +03 to +04 on
+ 2016-03-27 at 02:00 local time. They need distinct zones since their
+ post-1970 histories disagree. New zone Asia/Barnaul for Altai Krai and
+ Altai Republic, Russia, which will switch from +06 to +07 on the same date
+ and local time. The Astrakhan change is already official; the others have
+ passed the first reading in the State Duma and are extremely likely.
+ Also, Asia/Sakhalin moves from +10 to +11 on 2016-03-27 at 02:00.
+ (Thanks to Alexander Krivenyshev for the heads-up, and to Matt Johnson
+ and Stepan Golosunov for followup.)
+
+ As a trial of a new system that needs less information to be made up,
+ the new zones use numeric time zone abbreviations like "+04"
+ instead of invented abbreviations like "ASTT".
+
+ Haiti will not observe DST in 2016. (Thanks to Jean Antoine via
+ Steffen Thorsen.)
+
+ Palestine's spring-forward transition on 2016-03-26 is at 01:00, not 00:00.
+ (Thanks to Hannah Kreitem.) Guess future transitions will be March's last
+ Saturday at 01:00, not March's last Friday at 24:00.
+
+ Changes affecting past timestamps
+
+ Europe/Chisinau observed DST during 1990, and switched from +04 to
+ +03 at 1990-05-06 02:00, instead of switching from +03 to +02.
+ (Thanks to Stepan Golosunov.)
+
+ 1991 abbreviations in Europe/Samara should be SAMT/SAMST, not
+ KUYT/KUYST. (Thanks to Stepan Golosunov.)
+
+ Changes to code
+
+ tzselect's diagnostics and checking, and checktab.awk's checking,
+ have been improved. (Thanks to J William Piggott.)
+
+ tzcode now builds under MinGW. (Thanks to Ian Abbott and Esben Haabendal.)
+
+ tzselect now tests Julian-date TZ settings more accurately.
+ (Thanks to J William Piggott.)
+
+ Changes to commentary
+
+ Comments in zone tables have been improved. (Thanks to J William Piggott.)
+
+ tzselect again limits its menu comments so that menus fit on a
+ 24×80 alphanumeric display.
+
+ A new web page tz-how-to.html. (Thanks to Bill Seymour.)
+
+ In the Theory file, the description of possible time zone abbreviations in
+ tzdata has been cleaned up, as the old description was unclear and
+ inconsistent. (Thanks to Alain Mouette for reporting the problem.)
+
+
+Release 2016a - 2016-01-26 23:28:02 -0800
+
+ Changes affecting future timestamps
+
+ America/Cayman will not observe daylight saving this year after all.
+ Revert our guess that it would. (Thanks to Matt Johnson.)
+
+ Asia/Chita switches from +0800 to +0900 on 2016-03-27 at 02:00.
+ (Thanks to Alexander Krivenyshev.)
+
+ Asia/Tehran now has DST predictions for the year 2038 and later,
+ to be March 21 00:00 to September 21 00:00. This is likely better
+ than predicting no DST, albeit off by a day every now and then.
+
+ Changes affecting past and future timestamps
+
+ America/Metlakatla switched from PST all year to AKST/AKDT on
+ 2015-11-01 at 02:00. (Thanks to Steffen Thorsen.)
+
+ America/Santa_Isabel has been removed, and replaced with a
+ backward compatibility link to America/Tijuana. Its contents were
+ apparently based on a misreading of Mexican legislation.
+
+ Changes affecting past timestamps
+
+ Asia/Karachi's two transition times in 2002 were off by a minute.
+ (Thanks to Matt Johnson.)
+
+ Changes affecting build procedure
+
+ An installer can now combine leap seconds with use of the backzone file,
+ e.g., with 'make PACKRATDATA=backzone REDO=posix_right zones'.
+ The old 'make posix_packrat' rule is now marked as obsolescent.
+ (Thanks to Ian Abbott for an initial implementation.)
+
+ Changes affecting documentation and commentary
+
+ A new file LICENSE makes it easier to see that the code and data
+ are mostly public-domain. (Thanks to James Knight.) The three
+ non-public-domain files now use the current (3-clause) BSD license
+ instead of older versions of that license.
+
+ tz-link.htm mentions the BDE library (thanks to Andrew Paprocki),
+ CCTZ (thanks to Tim Parenti), TimeJones.com, and has a new section
+ on editing tz source files (with a mention of Sublime zoneinfo,
+ thanks to Gilmore Davidson).
+
+ The Theory and asia files now mention the 2015 book "The Global
+ Transformation of Time, 1870-1950", and cite a couple of reviews.
+
+ The America/Chicago entry now documents the informal use of US
+ central time in Fort Pierre, South Dakota. (Thanks to Rick
+ McDermid, Matt Johnson, and Steve Jones.)
+
+
+Release 2015g - 2015-10-01 00:39:51 -0700
+
+ Changes affecting future timestamps
+
+ Turkey's 2015 fall-back transition is scheduled for Nov. 8, not Oct. 25.
+ (Thanks to Fatih.)
+
+ Norfolk moves from +1130 to +1100 on 2015-10-04 at 02:00 local time.
+ (Thanks to Alexander Krivenyshev.)
+
+ Fiji's 2016 fall-back transition is scheduled for January 17, not 24.
+ (Thanks to Ken Rylander.)
+
+ Fort Nelson, British Columbia will not fall back on 2015-11-01. It has
+ effectively been on MST (-0700) since it advanced its clocks on 2015-03-08.
+ New zone America/Fort_Nelson. (Thanks to Matt Johnson.)
+
+ Changes affecting past timestamps
+
+ Norfolk observed DST from 1974-10-27 02:00 to 1975-03-02 02:00.
+
+ Changes affecting code
+
+ localtime no longer mishandles America/Anchorage after 2037.
+ (Thanks to Bradley White for reporting the bug.)
+
+ On hosts with signed 32-bit time_t, localtime no longer mishandles
+ Pacific/Fiji after 2038-01-16 14:00 UTC.
+
+ The localtime module allows the variables 'timezone', 'daylight',
+ and 'altzone' to be in common storage shared with other modules,
+ and declares them in case the system <time.h> does not.
+ (Problems reported by Kees Dekker.)
+
+ On platforms with tm_zone, strftime.c now assumes it is not NULL.
+ This simplifies the code and is consistent with zdump.c.
+ (Problem reported by Christos Zoulas.)
+
+ Changes affecting documentation
+
+ The tzfile man page now documents that transition times denote the
+ starts (not the ends) of the corresponding time periods.
+ (Ambiguity reported by Bill Seymour.)
+
+
+Release 2015f - 2015-08-10 18:06:56 -0700
+
+ Changes affecting future timestamps
+
+ North Korea switches to +0830 on 2015-08-15. (Thanks to Steffen Thorsen.)
+ The abbreviation remains "KST". (Thanks to Robert Elz.)
+
+ Uruguay no longer observes DST. (Thanks to Steffen Thorsen
+ and Pablo Camargo.)
+
+ Changes affecting past and future timestamps
+
+ Moldova starts and ends DST at 00:00 UTC, not at 01:00 UTC.
+ (Thanks to Roman Tudos.)
+
+ Changes affecting data format and code
+
+ zic's '-y YEARISTYPE' option is no longer documented. The TYPE
+ field of a Rule line should now be '-'; the old values 'even',
+ 'odd', 'uspres', 'nonpres', 'nonuspres' were already undocumented.
+ Although the implementation has not changed, these features do not
+ work in the default installation, they are not used in the data,
+ and they are now considered obsolescent.
+
+ zic now checks that two rules don't take effect at the same time.
+ (Thanks to Jon Skeet and Arthur David Olson.) Constraints on
+ simultaneity are now documented.
+
+ The two characters '%z' in a zone format now stand for the UT
+ offset, e.g., '-07' for seven hours behind UT and '+0530' for
+ five hours and thirty minutes ahead. This better supports time
+ zone abbreviations conforming to POSIX.1-2001 and later.
+
+ Changes affecting installed data files
+
+ Comments for America/Halifax and America/Glace_Bay have been improved.
+ (Thanks to Brian Inglis.)
+
+ Data entries have been simplified for Atlantic/Canary, Europe/Simferopol,
+ Europe/Sofia, and Europe/Tallinn. This yields slightly smaller
+ installed data files for Europe/Simferopol and Europe/Tallinn.
+ It does not affect timestamps. (Thanks to Howard Hinnant.)
+
+ Changes affecting code
+
+ zdump and zic no longer warn about valid time zone abbreviations
+ like '-05'.
+
+ Some Visual Studio 2013 warnings have been suppressed.
+ (Thanks to Kees Dekker.)
+
+ 'date' no longer sets the time of day and its -a, -d, -n and -t
+ options have been removed. Long obsolescent, the implementation
+ of these features had porting problems. Builders no longer need
+ to configure HAVE_ADJTIME, HAVE_SETTIMEOFDAY, or HAVE_UTMPX_H.
+ (Thanks to Kees Dekker for pointing out the problem.)
+
+ Changes affecting documentation
+
+ The Theory file mentions naming issues earlier, as these seem to be
+ poorly publicized (thanks to Gilmore Davidson for reporting the problem).
+
+ tz-link.htm mentions Time Zone Database Parser (thanks to Howard Hinnant).
+
+ Mention that Herbert Samuel introduced the term "Summer Time".
+
+
+Release 2015e - 2015-06-13 10:56:02 -0700
+
+ Changes affecting future timestamps
+
+ Morocco will suspend DST from 2015-06-14 03:00 through 2015-07-19 02:00,
+ not 06-13 and 07-18 as we had guessed. (Thanks to Milamber.)
+
+ Assume Cayman Islands will observe DST starting next year, using US rules.
+ Although it isn't guaranteed, it is the most likely.
+
+ Changes affecting data format
+
+ The file 'iso3166.tab' now uses UTF-8, so that its entries can better
+ spell the names of Åland Islands, Côte d'Ivoire, and Réunion.
+
+ Changes affecting code
+
+ When displaying data, tzselect converts it to the current locale's
+ encoding if the iconv command works. (Problem reported by random832.)
+
+ tzselect no longer mishandles Dominica, fixing a bug introduced
+ in Release 2014f. (Problem reported by Owen Leibman.)
+
+ zic -l no longer fails when compiled with -DTZDEFAULT=\"/etc/localtime\".
+ This fixes a bug introduced in Release 2014f.
+ (Problem reported by Leonardo Chiquitto.)
+
+
+Release 2015d - 2015-04-24 08:09:46 -0700
+
+ Changes affecting future timestamps
+
+ Egypt will not observe DST in 2015 and will consider canceling it
+ permanently. For now, assume no DST indefinitely.
+ (Thanks to Ahmed Nazmy and Tim Parenti.)
+
+ Changes affecting past timestamps
+
+ America/Whitehorse switched from UT -09 to -08 on 1967-05-28, not
+ 1966-07-01. Also, Yukon's time zone history is documented better.
+ (Thanks to Brian Inglis and Dennis Ferguson.)
+
+ Change affecting past and future time zone abbreviations
+
+ The abbreviations for Hawaii-Aleutian standard and daylight times
+ have been changed from HAST/HADT to HST/HDT, as per US Government
+ Printing Office style. This affects only America/Adak since 1983,
+ as America/Honolulu was already using the new style.
+
+ Changes affecting code
+
+ zic has some minor performance improvements.
+
+
+Release 2015c - 2015-04-11 08:55:55 -0700
+
+ Changes affecting future timestamps
+
+ Egypt's spring-forward transition is at 24:00 on April's last Thursday,
+ not 00:00 on April's last Friday. 2015's transition will therefore be on
+ Thursday, April 30 at 24:00, not Friday, April 24 at 00:00. Similar fixes
+ apply to 2026, 2037, 2043, etc. (Thanks to Steffen Thorsen.)
+
+ Changes affecting past timestamps
+
+ The following changes affect some pre-1991 Chile-related timestamps
+ in America/Santiago, Antarctica/Palmer, and Pacific/Easter.
+
+ The 1910 transition was January 10, not January 1.
+
+ The 1918 transition was September 10, not September 1.
+
+ The UT -04 time observed from 1932 to 1942 is now considered to
+ be standard time, not year-round DST.
+
+ Santiago observed DST (UT -03) from 1946-07-15 through
+ 1946-08-31, then reverted to standard time, then switched to -05
+ on 1947-04-01.
+
+ Assume transitions before 1968 were at 00:00, since we have no data
+ saying otherwise.
+
+ The spring 1988 transition was 1988-10-09, not 1988-10-02.
+ The fall 1990 transition was 1990-03-11, not 1990-03-18.
+
+ Assume no UT offset change for Pacific/Easter on 1890-01-01,
+ and omit all transitions on Pacific/Easter from 1942 through 1946
+ since we have no data suggesting that they existed.
+
+ One more zone has been turned into a link, as it differed
+ from an existing zone only for older timestamps. As usual,
+ this change affects UT offsets in pre-1970 timestamps only.
+ The zone's old contents have been moved to the 'backzone' file.
+ The affected zone is America/Montreal.
+
+ Changes affecting commentary
+
+ Mention the TZUpdater tool.
+
+ Mention "The Time Now". (Thanks to Brandon Ramsey.)
+
+
+Release 2015b - 2015-03-19 23:28:11 -0700
+
+ Changes affecting future timestamps
+
+ Mongolia will start observing DST again this year, from the last
+ Saturday in March at 02:00 to the last Saturday in September at 00:00.
+ (Thanks to Ganbold Tsagaankhuu.)
+
+ Palestine will start DST on March 28, not March 27. Also,
+ correct the fall 2014 transition from September 26 to October 24.
+ Adjust future predictions accordingly. (Thanks to Steffen Thorsen.)
+
+ Changes affecting past timestamps
+
+ The 1982 zone shift in Pacific/Easter has been corrected, fixing a 2015a
+ regression. (Thanks to Stuart Bishop for reporting the problem.)
+
+ Some more zones have been turned into links, when they differed
+ from existing zones only for older timestamps. As usual,
+ these changes affect UT offsets in pre-1970 timestamps only.
+ Their old contents have been moved to the 'backzone' file.
+ The affected zones are: America/Antigua, America/Cayman,
+ Pacific/Midway, and Pacific/Saipan.
+
+ Changes affecting time zone abbreviations
+
+ Correct the 1992-2010 DST abbreviation in Volgograd from "MSK" to "MSD".
+ (Thanks to Hank W.)
+
+ Changes affecting code
+
+ Fix integer overflow bug in reference 'mktime' implementation.
+ (Problem reported by Jörg Richter.)
+
+ Allow -Dtime_tz=time_t compilations, and allow -Dtime_tz=... libraries
+ to be used in the same executable as standard-library time_t functions.
+ (Problems reported by Bradley White.)
+
+ Changes affecting commentary
+
+ Cite the recent Mexican decree changing Quintana Roo's time zone.
+ (Thanks to Carlos Raúl Perasso.)
+
+ Likewise for the recent Chilean decree. (Thanks to Eduardo Romero Urra.)
+
+ Update info about Mars time.
+
+
+Release 2015a - 2015-01-29 22:35:20 -0800
+
+ Changes affecting future timestamps
+
+ The Mexican state of Quintana Roo, represented by America/Cancun,
+ will shift from Central Time with DST to Eastern Time without DST
+ on 2015-02-01 at 02:00. (Thanks to Steffen Thorsen and Gwillim Law.)
+
+ Chile will not change clocks in April or thereafter; its new standard time
+ will be its old daylight saving time. This affects America/Santiago,
+ Pacific/Easter, and Antarctica/Palmer. (Thanks to Juan Correa.)
+
+ New leap second 2015-06-30 23:59:60 UTC as per IERS Bulletin C 49.
+ (Thanks to Tim Parenti.)
+
+ Changes affecting past timestamps
+
+ Iceland observed DST in 1919 and 1921, and its 1939 fallback
+ transition was Oct. 29, not Nov. 29. Remove incorrect data from
+ Shanks about time in Iceland between 1837 and 1908.
+
+ Some more zones have been turned into links, when they differed
+ from existing zones only for older timestamps. As usual,
+ these changes affect UT offsets in pre-1970 timestamps only.
+ Their old contents have been moved to the 'backzone' file.
+ The affected zones are: Asia/Aden, Asia/Bahrain, Asia/Kuwait,
+ and Asia/Muscat.
+
+ Changes affecting code
+
+ tzalloc now scrubs time zone abbreviations compatibly with the way
+ that tzset always has, by replacing invalid bytes with '_' and by
+ shortening too-long abbreviations.
+
+ tzselect ports to POSIX awk implementations, no longer mishandles
+ POSIX TZ settings when GNU awk is used, and reports POSIX TZ
+ settings to the user. (Thanks to Stefan Kuhn.)
+
+ Changes affecting build procedure
+
+ 'make check' now checks for links to links in the data.
+ One such link (for Africa/Asmera) has been fixed.
+ (Thanks to Stephen Colebourne for pointing out the problem.)
+
+ Changes affecting commentary
+
+ The leapseconds file commentary now mentions the expiration date.
+ (Problem reported by Martin Burnicki.)
+
+ Update Mexican Library of Congress URL.
+
+
+Release 2014j - 2014-11-10 17:37:11 -0800
+
+ Changes affecting current and future timestamps
+
+ Turks & Caicos' switch from US eastern time to UT -04 year-round
+ did not occur on 2014-11-02 at 02:00. It's currently scheduled
+ for 2015-11-01 at 02:00. (Thanks to Chris Walton.)
+
+ Changes affecting past timestamps
+
+ Many pre-1989 timestamps have been corrected for Asia/Seoul and
+ Asia/Pyongyang, based on sources for the Korean-language Wikipedia
+ entry for time in Korea. (Thanks to Sanghyuk Jung.) Also, no
+ longer guess that Pyongyang mimicked Seoul time after World War II,
+ as this is politically implausible.
+
+ Some more zones have been turned into links, when they differed
+ from existing zones only for older timestamps. As usual,
+ these changes affect UT offsets in pre-1970 timestamps only.
+ Their old contents have been moved to the 'backzone' file.
+ The affected zones are: Africa/Addis_Ababa, Africa/Asmara,
+ Africa/Dar_es_Salaam, Africa/Djibouti, Africa/Kampala,
+ Africa/Mogadishu, Indian/Antananarivo, Indian/Comoro, and
+ Indian/Mayotte.
+
+ Changes affecting commentary
+
+ The commentary is less enthusiastic about Shanks as a source,
+ and is more careful to distinguish UT from UTC.
+
+
+Release 2014i - 2014-10-21 22:04:57 -0700
+
+ Changes affecting future timestamps
+
+ Pacific/Fiji will observe DST from 2014-11-02 02:00 to 2015-01-18 03:00.
+ (Thanks to Ken Rylander for the heads-up.) Guess that future
+ years will use a similar pattern.
+
+ A new Zone Pacific/Bougainville, for the part of Papua New Guinea
+ that plans to switch from UT +10 to +11 on 2014-12-28 at 02:00.
+ (Thanks to Kiley Walbom for the heads-up.)
+
+ Changes affecting time zone abbreviations
+
+ Since Belarus is not changing its clocks even though Moscow is,
+ the time zone abbreviation in Europe/Minsk is changing from FET
+ to its more-traditional value MSK on 2014-10-26 at 01:00.
+ (Thanks to Alexander Bokovoy for the heads-up about Belarus.)
+
+ The new abbreviation IDT stands for the pre-1976 use of UT +08 in
+ Indochina, to distinguish it better from ICT (+07).
+
+ Changes affecting past timestamps
+
+ Many timestamps have been corrected for Asia/Ho_Chi_Minh before 1976
+ (thanks to Trần Ngọc Quân for an indirect pointer to Trần Tiến Bình's
+ authoritative book). Asia/Ho_Chi_Minh has been added to
+ zone1970.tab, to give tzselect users in Vietnam two choices,
+ since north and south Vietnam disagreed after our 1970 cutoff.
+
+ Asia/Phnom_Penh and Asia/Vientiane have been turned into links, as
+ they differed from existing zones only for older timestamps. As
+ usual, these changes affect pre-1970 timestamps only. Their old
+ contents have been moved to the 'backzone' file.
+
+ Changes affecting code
+
+ The time-related library functions now set errno on failure, and
+ some crashes in the new tzalloc-related library functions have
+ been fixed. (Thanks to Christos Zoulas for reporting most of
+ these problems and for suggesting fixes.)
+
+ If USG_COMPAT is defined and the requested timestamp is standard time,
+ the tz library's localtime and mktime functions now set the extern
+ variable timezone to a value appropriate for that timestamp; and
+ similarly for ALTZONE, daylight saving time, and the altzone variable.
+ This change is a companion to the tzname change in 2014h, and is
+ designed to make timezone and altzone more compatible with tzname.
+
+ The tz library's functions now set errno to EOVERFLOW if they fail
+ because the result cannot be represented. ctime and ctime_r now
+ return NULL and set errno when a timestamp is out of range, rather
+ than having undefined behavior.
+
+ Some bugs associated with the new 2014g functions have been fixed.
+ This includes a bug that largely incapacitated the new functions
+ time2posix_z and posix2time_z. (Thanks to Christos Zoulas.)
+ It also includes some uses of uninitialized variables after tzalloc.
+ The new code uses the standard type 'ssize_t', which the Makefile
+ now gives porting advice about.
+
+ Changes affecting commentary
+
+ Updated URLs for NRC Canada (thanks to Matt Johnson and Brian Inglis).
+
+
+Release 2014h - 2014-09-25 18:59:03 -0700
+
+ Changes affecting past timestamps
+
+ America/Jamaica's 1974 spring-forward transition was Jan. 6, not Apr. 28.
+
+ Shanks says Asia/Novokuznetsk switched from LMT (not "NMT") on 1924-05-01,
+ not 1920-01-06. The old entry was based on a misinterpretation of Shanks.
+
+ Some more zones have been turned into links, when they differed
+ from existing zones only for older timestamps. As usual,
+ these changes affect UT offsets in pre-1970 timestamps only.
+ Their old contents have been moved to the 'backzone' file.
+ The affected zones are: Africa/Blantyre, Africa/Bujumbura,
+ Africa/Gaborone, Africa/Harare, Africa/Kigali, Africa/Lubumbashi,
+ Africa/Lusaka, Africa/Maseru, and Africa/Mbabane.
+
+ Changes affecting code
+
+ zdump -V and -v now output gmtoff= values on all platforms,
+ not merely on platforms defining TM_GMTOFF.
+
+ The tz library's localtime and mktime functions now set tzname to a value
+ appropriate for the requested timestamp, and zdump now uses this
+ on platforms not defining TM_ZONE, fixing a 2014g regression.
+ (Thanks to Tim Parenti for reporting the problem.)
+
+ The tz library no longer sets tzname if localtime or mktime fails.
+
+ zdump -c no longer mishandles transitions near year boundaries.
+ (Thanks to Tim Parenti for reporting the problem.)
+
+ An access to uninitialized data has been fixed.
+ (Thanks to Jörg Richter for reporting the problem.)
+
+ When THREAD_SAFE is defined, the code ports to the C11 memory model.
+ A memory leak has been fixed if ALL_STATE and THREAD_SAFE are defined
+ and two threads race to initialize data used by gmtime-like functions.
+ (Thanks to Andy Heninger for reporting the problems.)
+
+ Changes affecting build procedure
+
+ 'make check' now checks better for properly-sorted data.
+
+ Changes affecting documentation and commentary
+
+ zdump's gmtoff=N output is now documented, and its isdst=D output
+ is now documented to possibly output D values other than 0 or 1.
+
+ zdump -c's treatment of years is now documented to use the
+ Gregorian calendar and Universal Time without leap seconds,
+ and its behavior at cutoff boundaries is now documented better.
+ (Thanks to Arthur David Olson and Tim Parenti for reporting the problems.)
+
+ Programs are now documented to use the proleptic Gregorian calendar.
+ (Thanks to Alan Barrett for the suggestion.)
+
+ Fractional-second GMT offsets have been documented for civil time
+ in 19th-century Chennai, Jakarta, and New York.
+
+
+Release 2014g - 2014-08-28 12:31:23 -0700
+
+ Changes affecting future timestamps
+
+ Turks & Caicos is switching from US eastern time to UT -04
+ year-round, modeled as a switch on 2014-11-02 at 02:00.
+ [As noted in 2014j, this switch was later delayed.]
+
+ Changes affecting past timestamps
+
+ Time in Russia or the USSR before 1926 or so has been corrected by
+ a few seconds in the following zones: Asia/Irkutsk,
+ Asia/Krasnoyarsk, Asia/Omsk, Asia/Samarkand, Asia/Tbilisi,
+ Asia/Vladivostok, Asia/Yakutsk, Europe/Riga, Europe/Samara. For
+ Asia/Yekaterinburg the correction is a few minutes. (Thanks to
+ Vladimir Karpinsky.)
+
+ The Portuguese decree of 1911-05-26 took effect on 1912-01-01.
+ This affects 1911 timestamps in Africa/Bissau, Africa/Luanda,
+ Atlantic/Azores, and Atlantic/Madeira. Also, Lisbon's pre-1912
+ GMT offset was -0:36:45 (rounded from -0:36:44.68), not -0:36:32.
+ (Thanks to Stephen Colebourne for pointing to the decree.)
+
+ Asia/Dhaka ended DST on 2009-12-31 at 24:00, not 23:59.
+
+ A new file 'backzone' contains data which may appeal to
+ connoisseurs of old timestamps, although it is out of scope for
+ the tz database, is often poorly sourced, and contains some data
+ that is known to be incorrect. The new file is not recommended
+ for ordinary use and its entries are not installed by default.
+ (Thanks to Lester Caine for the high-quality Jersey, Guernsey, and
+ Isle of Man entries.)
+
+ Some more zones have been turned into links, when they differed
+ from existing zones only for older timestamps. As usual,
+ these changes affect UT offsets in pre-1970 timestamps only.
+ Their old contents have been moved to the 'backzone' file.
+ The affected zones are: Africa/Bangui, Africa/Brazzaville,
+ Africa/Douala, Africa/Kinshasa, Africa/Libreville, Africa/Luanda,
+ Africa/Malabo, Africa/Niamey, and Africa/Porto-Novo.
+
+ Changes affecting code
+
+ Unless NETBSD_INSPIRED is defined to 0, the tz library now
+ supplies functions for creating and using objects that represent
+ timezones. The new functions are tzalloc, tzfree, localtime_rz,
+ mktime_z, and (if STD_INSPIRED is also defined) posix2time_z and
+ time2posix_z. They are intended for performance: for example,
+ localtime_rz (unlike localtime_r) is trivially thread-safe without
+ locking. (Thanks to Christos Zoulas for proposing NetBSD-inspired
+ functions, and to Alan Barrett and Jonathan Lennox for helping to
+ debug the change.)
+
+ zdump now builds with the tz library unless USE_LTZ is defined to 0,
+ This lets zdump use tz features even if the system library lacks them.
+ To build zdump with the system library, use 'make CFLAGS=-DUSE_LTZ=0
+ TZDOBJS=zdump.o CHECK_TIME_T_ALTERNATIVES='.
+
+ zdump now uses localtime_rz if available, as it's significantly faster,
+ and it can help zdump better diagnose invalid timezone names.
+ Define HAVE_LOCALTIME_RZ to 0 to suppress this. HAVE_LOCALTIME_RZ
+ defaults to 1 if NETBSD_INSPIRED && USE_LTZ. When localtime_rz is
+ not available, zdump now uses localtime_r and tzset if available,
+ as this is a bit cleaner and faster than plain localtime. Compile
+ with -DHAVE_LOCALTIME_R=0 and/or -DHAVE_TZSET=0 if your system
+ lacks these two functions.
+
+ If THREAD_SAFE is defined to 1, the tz library is now thread-safe.
+ Although not needed for tz's own applications, which are single-threaded,
+ this supports POSIX better if the tz library is used in multithreaded apps.
+
+ Some crashes have been fixed when zdump or the tz library is given
+ invalid or outlandish input.
+
+ The tz library no longer mishandles leap seconds on platforms with
+ unsigned time_t in timezones that lack ordinary transitions after 1970.
+
+ The tz code now attempts to infer TM_GMTOFF and TM_ZONE if not
+ already defined, to make it easier to configure on common platforms.
+ Define NO_TM_GMTOFF and NO_TM_ZONE to suppress this.
+
+ Unless the new macro UNINIT_TRAP is defined to 1, the tz code now
+ assumes that reading uninitialized memory yields garbage values
+ but does not cause other problems such as traps.
+
+ If TM_GMTOFF is defined and UNINIT_TRAP is 0, mktime is now
+ more likely to guess right for ambiguous timestamps near
+ transitions where tm_isdst does not change.
+
+ If HAVE_STRFTIME_L is defined to 1, the tz library now defines
+ strftime_l for compatibility with recent versions of POSIX.
+ Only the C locale is supported, though. HAVE_STRFTIME_L defaults
+ to 1 on recent POSIX versions, and to 0 otherwise.
+
+ tzselect -c now uses a hybrid distance measure that works better
+ in Africa. (Thanks to Alan Barrett for noting the problem.)
+
+ The C source code now ports to NetBSD when GCC_DEBUG_FLAGS is used,
+ or when time_tz is defined.
+
+ When HAVE_UTMPX_H is set the 'date' command now builds on systems
+ whose <utmpx.h> file does not define WTMPX_FILE, and when setting
+ the date it updates the wtmpx file if _PATH_WTMPX is defined.
+ This affects GNU/Linux and similar systems.
+
+ For easier maintenance later, some C code has been simplified,
+ some lint has been removed, and the code has been tweaked so that
+ plain 'make' is more likely to work.
+
+ The C type 'bool' is now used for boolean values, instead of 'int'.
+
+ The long-obsolete LOCALE_HOME code has been removed.
+
+ The long-obsolete 'gtime' function has been removed.
+
+ Changes affecting build procedure
+
+ 'zdump' no longer links in ialloc.o, as it's not needed.
+
+ 'make check_time_t_alternatives' no longer assumes GNU diff.
+
+ Changes affecting distribution tarballs
+
+ The files checktab.awk and zoneinfo2tdf.pl are now distributed in
+ the tzdata tarball instead of the tzcode tarball, since they help
+ maintain the data. The NEWS and Theory files are now also
+ distributed in the tzdata tarball, as they're relevant for data.
+ (Thanks to Alan Barrett for pointing this out.) Also, the
+ leapseconds.awk file is no longer distributed in the tzcode
+ tarball, since it belongs in the tzdata tarball (where 2014f
+ inadvertently also distributed it).
+
+ Changes affecting documentation and commentary
+
+ A new file CONTRIBUTING is distributed. (Thanks to Tim Parenti for
+ suggesting a CONTRIBUTING file, and to Tony Finch and Walter Harms
+ for debugging it.)
+
+ The man pages have been updated to use function prototypes,
+ to document thread-safe variants like localtime_r, and to document
+ the NetBSD-inspired functions tzalloc, tzfree, localtime_rz, and
+ mktime_z.
+
+ The fields in Link lines have been renamed to be more descriptive
+ and more like the parameters of 'ln'. LINK-FROM has become TARGET,
+ and LINK-TO has become LINK-NAME.
+
+ tz-link.htm mentions the IETF's tzdist working group; Windows
+ Runtime etc. (thanks to Matt Johnson); and HP-UX's tztab.
+
+ Some broken URLs have been fixed in the commentary. (Thanks to
+ Lester Caine.)
+
+ Commentary about Philippines DST has been updated, and commentary
+ on pre-1970 time in India has been added.
+
+
+Release 2014f - 2014-08-05 17:42:36 -0700
+
+ Changes affecting future timestamps
+
+ Russia will subtract an hour from most of its time zones on 2014-10-26
+ at 02:00 local time. (Thanks to Alexander Krivenyshev.)
+ There are a few exceptions: Magadan Oblast (Asia/Magadan) and Zabaykalsky
+ Krai are subtracting two hours; conversely, Chukotka Autonomous Okrug
+ (Asia/Anadyr), Kamchatka Krai (Asia/Kamchatka), Kemerovo Oblast
+ (Asia/Novokuznetsk), and the Samara Oblast and the Udmurt Republic
+ (Europe/Samara) are not changing their clocks. The changed zones are
+ Europe/Kaliningrad, Europe/Moscow, Europe/Simferopol, Europe/Volgograd,
+ Asia/Yekaterinburg, Asia/Omsk, Asia/Novosibirsk, Asia/Krasnoyarsk,
+ Asia/Irkutsk, Asia/Yakutsk, Asia/Vladivostok, Asia/Khandyga,
+ Asia/Sakhalin, and Asia/Ust-Nera; Asia/Magadan will have two hours
+ subtracted; and Asia/Novokuznetsk's time zone abbreviation is affected,
+ but not its UTC offset. Two zones are added: Asia/Chita (split
+ from Asia/Yakutsk, and also with two hours subtracted) and
+ Asia/Srednekolymsk (split from Asia/Magadan, but with only one hour
+ subtracted). (Thanks to Tim Parenti for much of the above.)
+
+ Changes affecting time zone abbreviations
+
+ Australian eastern time zone abbreviations are now AEST/AEDT not EST,
+ and similarly for the other Australian zones. That is, for eastern
+ standard and daylight saving time the abbreviations are AEST and AEDT
+ instead of the former EST for both; similarly, ACST/ACDT, ACWST/ACWDT,
+ and AWST/AWDT are now used instead of the former CST, CWST, and WST.
+ This change does not affect UT offsets, only time zone abbreviations.
+ (Thanks to Rich Tibbett and many others.)
+
+ Asia/Novokuznetsk shifts from NOVT to KRAT (remaining on UT +07)
+ effective 2014-10-26 at 02:00 local time.
+
+ The time zone abbreviation for Xinjiang Time (observed in Ürümqi)
+ has been changed from URUT to XJT. (Thanks to Luther Ma.)
+
+ Prefer MSK/MSD for Moscow time in Russia, even in other cities.
+ Similarly, prefer EET/EEST for eastern European time in Russia.
+
+ Change time zone abbreviations in (western) Samoa to use "ST" and
+ "DT" suffixes, as this is more likely to match common practice.
+ Prefix "W" to (western) Samoa time when its standard-time offset
+ disagrees with that of American Samoa.
+
+ America/Metlakatla now uses PST, not MeST, to abbreviate its time zone.
+
+ Time zone abbreviations have been updated for Japan's two time
+ zones used 1896-1937. JWST now stands for Western Standard
+ Time, and JCST for Central Standard Time (formerly this was CJT).
+ These abbreviations are now used for time in Korea, Taiwan,
+ and Sakhalin while controlled by Japan.
+
+ Changes affecting past timestamps
+
+ China's five zones have been simplified to two, since the post-1970
+ differences in the other three seem to have been imaginary. The
+ zones Asia/Harbin, Asia/Chongqing, and Asia/Kashgar have been
+ removed; backwards-compatibility links still work, albeit with
+ different behaviors for timestamps before May 1980. Asia/Urumqi's
+ 1980 transition to UT +08 has been removed, so that it is now at
+ +06 and not +08. (Thanks to Luther Ma and to Alois Treindl;
+ Treindl sent helpful translations of two papers by Guo Qingsheng.)
+
+ Some zones have been turned into links, when they differed from existing
+ zones only for older UT offsets where data entries were likely invented.
+ These changes affect UT offsets in pre-1970 timestamps only. This is
+ similar to the change in release 2013e, except this time for western
+ Africa. The affected zones are: Africa/Bamako, Africa/Banjul,
+ Africa/Conakry, Africa/Dakar, Africa/Freetown, Africa/Lome,
+ Africa/Nouakchott, Africa/Ouagadougou, Africa/Sao_Tome, and
+ Atlantic/St_Helena. This also affects the backwards-compatibility
+ link Africa/Timbuktu. (Thanks to Alan Barrett, Stephen Colebourne,
+ Tim Parenti, and David Patte for reporting problems in earlier
+ versions of this change.)
+
+ Asia/Shanghai's pre-standard-time UT offset has been changed from
+ 8:05:57 to 8:05:43, the location of Xujiahui Observatory. Its
+ transition to standard time has been changed from 1928 to 1901.
+
+ Asia/Taipei switched to JWST on 1896-01-01, then to JST on 1937-10-01,
+ then to CST on 1945-09-21 at 01:00, and did not observe DST in 1945.
+ In 1946 it observed DST from 05-15 through 09-30; in 1947
+ from 04-15 through 10-31; and in 1979 from 07-01 through 09-30.
+ (Thanks to Yu-Cheng Chuang.)
+
+ Asia/Riyadh's transition to standard time is now 1947-03-14, not 1950.
+
+ Europe/Helsinki's 1942 fall-back transition was 10-04 at 01:00, not
+ 10-03 at 00:00. (Thanks to Konstantin Hyppönen.)
+
+ Pacific/Pago_Pago has been changed from UT -11:30 to -11 for the
+ period from 1911 to 1950.
+
+ Pacific/Chatham has been changed to New Zealand standard time plus
+ 45 minutes for the period before 1957, reflecting a 1956 remark in
+ the New Zealand parliament.
+
+ Europe/Budapest has several pre-1946 corrections: in 1918 the transition
+ out of DST was on 09-16, not 09-29; in 1919 it was on 11-24, not 09-15; in
+ 1945 it was on 11-01, not 11-03; in 1941 the transition to DST was 04-08
+ not 04-06 at 02:00; and there was no DST in 1920.
+
+ Africa/Accra is now assumed to have observed DST from 1920 through 1935.
+
+ Time in Russia before 1927 or so has been corrected by a few seconds in
+ the following zones: Europe/Moscow, Asia/Irkutsk, Asia/Tbilisi,
+ Asia/Tashkent, Asia/Vladivostok, Asia/Yekaterinburg, Europe/Helsinki, and
+ Europe/Riga. Also, Moscow's location has been changed to its Kilometer 0
+ point. (Thanks to Vladimir Karpinsky for the Moscow changes.)
+
+ Changes affecting data format
+
+ A new file 'zone1970.tab' supersedes 'zone.tab' in the installed data.
+ The new file's extended format allows multiple country codes per zone.
+ The older file is still installed but is deprecated; its format is
+ not changing and it will still be distributed for a while, but new
+ applications should use the new file.
+
+ The new file format simplifies maintenance of obscure locations.
+ To test this, it adds coverage for the Crozet Islands and the
+ Scattered Islands. (Thanks to Tobias Conradi and Antoine Leca.)
+
+ The file 'iso3166.tab' is planned to switch from ASCII to UTF-8.
+ It is still ASCII now, but commentary about the switch has been added.
+ The new file 'zone1970.tab' already uses UTF-8.
+
+ Changes affecting code
+
+ 'localtime', 'mktime', etc. now use much less stack space if ALL_STATE
+ is defined. (Thanks to Elliott Hughes for reporting the problem.)
+
+ 'zic' no longer mishandles input when ignoring case in locales that
+ are not compatible with English, e.g., unibyte Turkish locales when
+ compiled with HAVE_GETTEXT.
+
+ Error diagnostics of 'zic' and 'yearistype' have been reworded so that
+ they no longer use ASCII '-' as if it were a dash.
+
+ 'zic' now rejects output file names that contain '.' or '..' components.
+ (Thanks to Tim Parenti for reporting the problem.)
+
+ 'zic -v' now warns about output file names that do not follow
+ POSIX rules, or that contain a digit or '.'. (Thanks to Arthur
+ David Olson for starting the ball rolling on this.)
+
+ Some lint has been removed when using GCC_DEBUG_FLAGS with GCC 4.9.0.
+
+ Changes affecting build procedure
+
+ 'zic' no longer links in localtime.o and asctime.o, as they're not needed.
+ (Thanks to John Cochran.)
+
+ Changes affecting documentation and commentary
+
+ The 'Theory' file documents legacy names, the longstanding
+ exceptions to the POSIX-inspired file name rules.
+
+ The 'zic' documentation clarifies the role of time types when
+ interpreting dates. (Thanks to Arthur David Olson.)
+
+ Documentation and commentary now prefer UTF-8 to US-ASCII,
+ allowing the use of proper accents in foreign words and names.
+ Code and data have not changed because of this. (Thanks to
+ Garrett Wollman, Ian Abbott, and Guy Harris for helping to debug
+ this.)
+
+ Non-HTML documentation and commentary now use plain-text URLs instead of
+ HTML insertions, and are more consistent about bracketing URLs when they
+ are not already surrounded by white space. (Thanks to suggestions by
+ Steffen Nurpmeso.)
+
+ There is new commentary about Xujiahui Observatory, the five time-zone
+ project in China from 1918 to 1949, timekeeping in Japanese-occupied
+ Shanghai, and Tibet Time in the 1950s. The sharp-eyed can spot the
+ warlord Jin Shuren in the data.
+
+ Commentary about the coverage of each Russian zone has been standardized.
+ (Thanks to Tim Parenti.)
+
+ There is new commentary about contemporary timekeeping in Ethiopia.
+
+ Obsolete comments about a 2007 proposal for DST in Kuwait has been removed.
+
+ There is new commentary about time in Poland in 1919.
+
+ Proper credit has been given to DST inventor George Vernon Hudson.
+
+ Commentary about time in Metlakatla, AK and Resolute, NU has been
+ improved, with a new source for the former.
+
+ In zone.tab, Pacific/Easter no longer mentions Salas y Gómez, as it
+ is uninhabited.
+
+ Commentary about permanent Antarctic bases has been updated.
+
+ Several typos have been corrected. (Thanks to Tim Parenti for
+ contributing some of these fixes.)
+
+ tz-link.htm now mentions the JavaScript libraries Moment Timezone,
+ TimezoneJS.Date, Walltime-js, and Timezone. (Thanks to a heads-up
+ from Matt Johnson.) Also, it mentions the Go 'latlong' package.
+ (Thanks to a heads-up from Dirkjan Ochtman.)
+
+ The files usno1988, usno1989, usno1989a, usno1995, usno1997, and usno1998
+ have been removed. These obsolescent US Naval Observatory entries were no
+ longer helpful for maintenance. (Thanks to Tim Parenti for the suggestion.)
+
+
+Release 2014e - 2014-06-12 21:53:52 -0700
+
+ Changes affecting near-future timestamps
+
+ Egypt's 2014 Ramadan-based transitions are June 26 and July 31 at 24:00.
+ (Thanks to Imed Chihi.) Guess that from 2015 on Egypt will temporarily
+ switch to standard time at 24:00 the last Thursday before Ramadan, and
+ back to DST at 00:00 the first Friday after Ramadan.
+
+ Similarly, Morocco's are June 28 at 03:00 and August 2 at 02:00. (Thanks
+ to Milamber Space Network.) Guess that from 2015 on Morocco will
+ temporarily switch to standard time at 03:00 the last Saturday before
+ Ramadan, and back to DST at 02:00 the first Saturday after Ramadan.
+
+ Changes affecting past timestamps
+
+ The abbreviation "MSM" (Moscow Midsummer Time) is now used instead of
+ "MSD" for Moscow's double daylight time in summer 1921. Also, a typo
+ "VLASST" has been repaired to be "VLAST" for Vladivostok summer time
+ in 1991. (Thanks to Hank W. for reporting the problems.)
+
+ Changes affecting commentary
+
+ tz-link.htm now cites RFC 7265 for jCal, mentions PTP and the
+ draft CalDAV extension, updates URLs for TSP, TZInfo, IATA, and
+ removes stale pointers to World Time Explorer and WORLDTIME.
+
+
+Release 2014d - 2014-05-27 21:34:40 -0700
+
+ Changes affecting code
+
+ zic no longer generates files containing timestamps before the Big Bang.
+ This works around GNOME glib bug 878
+ <https://gitlab.gnome.org/GNOME/glib/issues/878>
+ (Thanks to Leonardo Chiquitto for reporting the bug, and to
+ Arthur David Olson and James Cloos for suggesting improvements to the fix.)
+
+ Changes affecting documentation
+
+ tz-link.htm now mentions GNOME.
+
+
+Release 2014c - 2014-05-13 07:44:13 -0700
+
+ Changes affecting near-future timestamps
+
+ Egypt observes DST starting 2014-05-15 at 24:00.
+ (Thanks to Ahmad El-Dardiry and Gunther Vermier.)
+ Details have not been announced, except that DST will not be observed
+ during Ramadan. Guess that DST will stop during the same Ramadan dates as
+ Morocco, and that Egypt's future spring and fall transitions will be the
+ same as 2010 when it last observed DST, namely April's last Friday at
+ 00:00 to September's last Thursday at 23:00 standard time. Also, guess
+ that Ramadan transitions will be at 00:00 standard time.
+
+ Changes affecting code
+
+ zic now generates transitions for minimum time values, eliminating guesswork
+ when handling low-valued timestamps. (Thanks to Arthur David Olson.)
+
+ Port to Cygwin sans glibc. (Thanks to Arthur David Olson.)
+
+ Changes affecting commentary and documentation
+
+ Remove now-confusing comment about Jordan. (Thanks to Oleksii Nochovnyi.)
+
+
+Release 2014b - 2014-03-24 21:28:50 -0700
+
+ Changes affecting near-future timestamps
+
+ Crimea switches to Moscow time on 2014-03-30 at 02:00 local time.
+ (Thanks to Alexander Krivenyshev.) Move its zone.tab entry from UA to RU.
+
+ New entry for Troll station, Antarctica. (Thanks to Paul-Inge Flakstad and
+ Bengt-Inge Larsson.) This is currently an approximation; a better version
+ will require the zic and localtime fixes mentioned below, and the plan is
+ to wait for a while until at least the zic fixes propagate.
+
+ Changes affecting code
+
+ 'zic' and 'localtime' no longer reject locations needing four transitions
+ per year for the foreseeable future. (Thanks to Andrew Main (Zefram).)
+ Also, 'zic' avoids some unlikely failures due to integer overflow.
+
+ Changes affecting build procedure
+
+ 'make check' now detects Rule lines defined but never used.
+ The NZAQ rules, an instance of this problem, have been removed.
+
+ Changes affecting commentary and documentation
+
+ Fix Tuesday/Thursday typo in description of time in Israel.
+ (Thanks to Bert Katz via Pavel Kharitonov and Mike Frysinger.)
+
+ Microsoft Windows 8.1 doesn't support tz database names. (Thanks
+ to Donald MacQueen.) Instead, the Microsoft Windows Store app
+ library supports them.
+
+ Add comments about Johnston Island time in the 1960s.
+ (Thanks to Lyle McElhaney.)
+
+ Morocco's 2014 DST start will be as predicted.
+ (Thanks to Sebastien Willemijns.)
+
+
+Release 2014a - 2014-03-07 23:30:29 -0800
+
+ Changes affecting near-future timestamps
+
+ Turkey begins DST on 2014-03-31, not 03-30. (Thanks to Faruk Pasin for
+ the heads-up, and to Tim Parenti for simplifying the update.)
+
+ Changes affecting past timestamps
+
+ Fiji ended DST on 2014-01-19 at 02:00, not the previously-scheduled 03:00.
+ (Thanks to Steffen Thorsen.)
+
+ Ukraine switched from Moscow to Eastern European time on 1990-07-01
+ (not 1992-01-01), and observed DST during the entire next winter.
+ (Thanks to Vladimir in Moscow via Alois Treindl.)
+
+ In 1988 Israel observed DST from 04-10 to 09-04, not 04-09 to 09-03.
+ (Thanks to Avigdor Finkelstein.)
+
+ Changes affecting code
+
+ A uninitialized-storage bug in 'localtime' has been fixed.
+ (Thanks to Logan Chien.)
+
+ Changes affecting the build procedure
+
+ The settings for 'make check_web' now default to Ubuntu 13.10.
+
+ Changes affecting commentary and documentation
+
+ The boundary of the US Pacific time zone is given more accurately.
+ (Thanks to Alan Mintz.)
+
+ Chile's 2014 DST will be as predicted. (Thanks to José Miguel Garrido.)
+
+ Paraguay's 2014 DST will be as predicted. (Thanks to Carlos Raúl Perasso.)
+
+ Better descriptions of countries with same time zone history as
+ Trinidad and Tobago since 1970. (Thanks to Alan Barrett for suggestion.)
+
+ Several changes affect tz-link.htm, the main web page.
+
+ Mention Time.is (thanks to Even Scharning) and WX-now (thanks to
+ David Braverman).
+
+ Mention xCal (Internet RFC 6321) and jCal.
+
+ Microsoft has some support for tz database names.
+
+ CLDR data formats include both XML and JSON.
+
+ Mention Maggiolo's map of solar vs standard time.
+ (Thanks to Arthur David Olson.)
+
+ Mention TZ4Net. (Thanks to Matt Johnson.)
+
+ Mention the timezone-olson Haskell package.
+
+ Mention zeitverschiebung.net. (Thanks to Martin Jäger.)
+
+ Remove moribund links to daylight-savings-time.info and to
+ Simple Timer + Clocks.
+
+ Update two links. (Thanks to Oscar van Vlijmen.)
+
+ Fix some formatting glitches, e.g., remove random newlines from
+ abbr elements' title attributes.
+
+
+Release 2013i - 2013-12-17 07:25:23 -0800
+
+ Changes affecting near-future timestamps:
+
+ Jordan switches back to standard time at 00:00 on December 20, 2013.
+ The 2006-2011 transition schedule is planned to resume in 2014.
+ (Thanks to Steffen Thorsen.)
+
+ Changes affecting past timestamps:
+
+ In 2004, Cuba began DST on March 28, not April 4.
+ (Thanks to Steffen Thorsen.)
+
+ Changes affecting code
+
+ 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.
+
+ Changes affecting documentation and commentary
+
+ The files solar87, solar88, and solar89 are no longer distributed.
+ They were a negative experiment - that is, a demonstration that
+ tz data can represent solar time only with some difficulty and error.
+ Their presence in the distribution caused confusion, as Riyadh
+ civil time was generally not solar time in those years.
+
+ tz-link.htm now mentions Noda Time. (Thanks to Matt Johnson.)
+
+
+Release 2013h - 2013-10-25 15:32:32 -0700
+
+ Changes affecting current and future timestamps:
+
+ Libya has switched its UT offset back to +02 without DST, instead
+ of +01 with DST. (Thanks to Even Scharning.)
+
+ Western Sahara (Africa/El_Aaiun) uses Morocco's DST rules.
+ (Thanks to Gwillim Law.)
+
+ Changes affecting future timestamps:
+
+ Acre and (we guess) western Amazonas will switch from UT -04 to -05
+ on 2013-11-10. This affects America/Rio_Branco and America/Eirunepe.
+ (Thanks to Steffen Thorsen.)
+
+ Add entries for DST transitions in Morocco in the year 2038.
+ This avoids some year-2038 glitches introduced in 2013g.
+ (Thanks to Yoshito Umaoka for reporting the problem.)
+
+ Changes affecting API
+
+ The 'tzselect' command no longer requires the 'select' command,
+ and should now work with /bin/sh on more platforms. It also works
+ around a bug in BusyBox awk before version 1.21.0. (Thanks to
+ Patrick 'P. J.' McDermott and Alan Barrett.)
+
+ Changes affecting code
+
+ Fix localtime overflow bugs with 32-bit unsigned time_t.
+
+ zdump no longer assumes sscanf returns maximal values on overflow.
+
+ Changes affecting the build procedure
+
+ The builder can specify which programs to use, if any, instead of
+ 'ar' and 'ranlib', and libtz.a is now built locally before being
+ installed. (Thanks to Michael Forney.)
+
+ A dependency typo in the 'zdump' rule has been fixed.
+ (Thanks to Andrew Paprocki.)
+
+ The Makefile has been simplified by assuming that 'mkdir -p' and 'cp -f'
+ work as specified by POSIX.2-1992 or later; this is portable nowadays.
+
+ 'make clean' no longer removes 'leapseconds', since it's
+ host-independent and is part of the distribution.
+
+ The unused makefile macros TZCSRCS, TZDSRCS, DATESRCS have been removed.
+
+ Changes affecting documentation and commentary
+
+ tz-link.htm now mentions TC TIMEZONE's draft time zone service protocol
+ (thanks to Mike Douglass) and TimezoneJS.Date (thanks to Jim Fehrle).
+
+ Update URLs in tz-link page. Add URLs for Microsoft Windows, since
+ 8.1 introduces tz support. Remove URLs for Tru64 and UnixWare (no
+ longer maintained) and for old advisories. SOFA now does C.
+
+Release 2013g - 2013-09-30 21:08:26 -0700
+
+ Changes affecting current and near-future timestamps
+
+ Morocco now observes DST from the last Sunday in March to the last
+ Sunday in October, not April to September respectively. (Thanks
+ to Steffen Thorsen.)
+
+ Changes affecting 'zic'
+
+ '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.
+
+ Changes affecting the build procedure
+
+ The 'leapseconds' file is again put into the tzdata tarball.
+ Also, 'leapseconds.awk', so tzdata is self-contained. (Thanks to
+ Matt Burgess and Ian Abbott.) The timestamps of these and other
+ dependent files in tarballs are adjusted more consistently.
+
+ Changes affecting documentation and commentary
+
+ The README file is now part of the data tarball as well as the code.
+ It now states that files are public domain unless otherwise specified.
+ (Thanks to Andrew Main (Zefram) for asking for clarifications.)
+ Its details about the 1989 release moved to a place of honor near
+ the end of NEWS.
+
+
+Release 2013f - 2013-09-24 23:37:36 -0700
+
+ Changes affecting near-future timestamps
+
+ Tocantins will very likely not observe DST starting this spring.
+ (Thanks to Steffen Thorsen.)
+
+ Jordan will likely stay at UT +03 indefinitely, and will not fall
+ back this fall.
+
+ Palestine will fall back at 00:00, not 01:00. (Thanks to Steffen Thorsen.)
+
+ Changes affecting API
+
+ 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.)
+
+ Changes affecting the build procedure
+
+ Avoid long strings in leapseconds.awk to work around a mawk bug.
+ (Thanks to Cyril Baurand.)
+
+ Changes affecting documentation and commentary
+
+ New file 'NEWS' that contains release notes like this one.
+
+ Paraguay's law does not specify DST transition time; 00:00 is customary.
+ (Thanks to Waldemar Villamayor-Venialbo.)
+
+ Minor capitalization fixes.
+
+ Changes affecting version-control only
+
+ The experimental GitHub repository now contains annotated and
+ signed tags for recent releases, e.g., '2013e' for Release 2013e.
+ Releases are tagged starting with 2012e; earlier releases were
+ done differently, and tags would either not have a simple name or
+ not exactly match what was released.
+
+ 'make set-timestamps' is now simpler and a bit more portable.
+
+
+Release 2013e - 2013-09-19 23:50:04 -0700
+
+ Changes affecting near-future timestamps
+
+ This year Fiji will start DST on October 27, not October 20.
+ (Thanks to David Wheeler for the heads-up.) For now, guess that
+ Fiji will continue to spring forward the Sunday before the fourth
+ Monday in October.
+
+ Changes affecting current and future time zone abbreviations
+
+ Use WIB/WITA/WIT rather than WIT/CIT/EIT for alphabetic Indonesian
+ time zone abbreviations since 1932. (Thanks to George Ziegler,
+ Priyadi Iman Nurcahyo, Zakaria, Jason Grimes, Martin Pitt, and
+ Benny Lin.) This affects Asia/Dili, Asia/Jakarta, Asia/Jayapura,
+ Asia/Makassar, and Asia/Pontianak.
+
+ Use ART (UT -03, standard time), rather than WARST (also -03, but
+ daylight saving time) for San Luis, Argentina since 2009.
+
+ Changes affecting Godthåb timestamps after 2037 if version mismatch
+
+ Allow POSIX-like TZ strings where the transition time's hour can
+ range from -167 through 167, instead of the POSIX-required 0
+ through 24. E.g., TZ='FJT-12FJST,M10.3.1/146,M1.3.4/75' for the
+ new Fiji rules. This is a more-compact way to represent
+ far-future timestamps for America/Godthab, America/Santiago,
+ Antarctica/Palmer, Asia/Gaza, Asia/Hebron, Asia/Jerusalem,
+ Pacific/Easter, and Pacific/Fiji. Other zones are unaffected by
+ this change. (Derived from a suggestion by Arthur David Olson.)
+
+ Allow POSIX-like TZ strings where daylight saving time is in
+ effect all year. E.g., TZ='WART4WARST,J1/0,J365/25' for Western
+ Argentina Summer Time all year. This supports a more-compact way
+ to represent the 2013d data for America/Argentina/San_Luis.
+ Because of the change for San Luis noted above this change does not
+ affect the current data. (Thanks to Andrew Main (Zefram) for
+ suggestions that improved this change.)
+
+ Where these two TZ changes take effect, there is a minor extension
+ to the tz file format in that it allows new values for the
+ embedded TZ-format string, and the tz file format version number
+ has therefore been increased from 2 to 3 as a precaution.
+ Version-2-based client code should continue to work as before for
+ all timestamps before 2038. Existing version-2-based client code
+ (tzcode, GNU/Linux, Solaris) has been tested on version-3-format
+ files, and typically works in practice even for timestamps after
+ 2037; the only known exception is America/Godthab.
+
+ Changes affecting timestamps before 1970
+
+ Pacific/Johnston is now a link to Pacific/Honolulu. This corrects
+ some errors before 1947.
+
+ Some zones have been turned into links, when they differ from existing
+ zones only in older data entries that were likely invented or that
+ differ only in LMT or transitions from LMT. These changes affect
+ only timestamps before 1943. The affected zones are:
+ Africa/Juba, America/Anguilla, America/Aruba, America/Dominica,
+ America/Grenada, America/Guadeloupe, America/Marigot,
+ America/Montserrat, America/St_Barthelemy, America/St_Kitts,
+ America/St_Lucia, America/St_Thomas, America/St_Vincent,
+ America/Tortola, and Europe/Vaduz. (Thanks to Alois Treindl for
+ confirming that the old Europe/Vaduz zone was wrong and the new
+ link is better for WWII-era times.)
+
+ Change Kingston Mean Time from -5:07:12 to -5:07:11. This affects
+ America/Cayman, America/Jamaica and America/Grand_Turk timestamps
+ from 1890 to 1912.
+
+ Change the UT offset of Bern Mean Time from 0:29:44 to 0:29:46.
+ This affects Europe/Zurich timestamps from 1853 to 1894. (Thanks
+ to Alois Treindl.)
+
+ Change the date of the circa-1850 Zurich transition from 1849-09-12
+ to 1853-07-16, overriding Shanks with data from Messerli about
+ postal and telegraph time in Switzerland.
+
+ Changes affecting time zone abbreviations before 1970
+
+ For Asia/Jakarta, use BMT (not JMT) for mean time from 1923 to 1932,
+ as Jakarta was called Batavia back then.
+
+ Changes affecting API
+
+ The 'zic' command now outputs a dummy transition when far-future
+ data can't be summarized using a TZ string, and uses a 402-year
+ window rather than a 400-year window. For the current data, this
+ affects only the Asia/Tehran file. It does not affect any of the
+ timestamps that this file represents, so zdump outputs the same
+ information as before. (Thanks to Andrew Main (Zefram).)
+
+ The 'date' command has a new '-r' option, which lets you specify
+ the integer time to display, a la FreeBSD.
+
+ The 'tzselect' command has two new options '-c' and '-n', which lets you
+ select a zone based on latitude and longitude.
+
+ The 'zic' command's '-v' option now warns about constructs that
+ require the new version-3 binary file format. (Thanks to Arthur
+ David Olson for the suggestion.)
+
+ Support for floating-point time_t has been removed.
+ It was always dicey, and POSIX no longer requires it.
+ (Thanks to Eric Blake for suggesting to the POSIX committee to
+ remove it, and thanks to Alan Barrett, Clive D.W. Feather, Andy
+ Heninger, Arthur David Olson, and Alois Treindl, for reporting
+ bugs and elucidating some of the corners of the old floating-point
+ implementation.)
+
+ The signatures of 'offtime', 'timeoff', and 'gtime' have been
+ changed back to the old practice of using 'long' to represent UT
+ offsets. This had been inadvertently and mistakenly changed to
+ 'int_fast32_t'. (Thanks to Christos Zoulas.)
+
+ The code avoids undefined behavior on integer overflow in some
+ more places, including gmtime, localtime, mktime and zdump.
+
+ Changes affecting the zdump utility
+
+ zdump now outputs "UT" when referring to Universal Time, not "UTC".
+ "UTC" does not make sense for timestamps that predate the introduction
+ of UTC, whereas "UT", a more-generic term, does. (Thanks to Steve Allen
+ for clarifying UT vs UTC.)
+
+ Data changes affecting behavior of tzselect and similar programs
+
+ Country code BQ is now called the more-common name "Caribbean Netherlands"
+ rather than the more-official "Bonaire, St Eustatius & Saba".
+
+ Remove from zone.tab the names America/Montreal, America/Shiprock,
+ and Antarctica/South_Pole, as they are equivalent to existing
+ same-country-code zones for post-1970 timestamps. The data entries for
+ these names are unchanged, so the names continue to work as before.
+
+ Changes affecting code internals
+
+ zic -c now runs way faster on 64-bit hosts when given large numbers.
+
+ zic now uses vfprintf to avoid allocating and freeing some memory.
+
+ tzselect now computes the list of continents from the data,
+ rather than have it hard-coded.
+
+ Minor changes pacify GCC 4.7.3 and GCC 4.8.1.
+
+ Changes affecting the build procedure
+
+ The 'leapseconds' file is now generated automatically from a
+ new file 'leap-seconds.list', which is a copy of
+ <ftp://ftp.nist.gov/pub/time/leap-seconds.list>
+ A new source file 'leapseconds.awk' implements this.
+ The goal is simplification of the future maintenance of 'leapseconds'.
+
+ When building the 'posix' or 'right' subdirectories, if the
+ subdirectory would be a copy of the default subdirectory, it is
+ now made a symbolic link if that is supported. This saves about
+ 2 MB of file system space.
+
+ The links America/Shiprock and Antarctica/South_Pole have been
+ moved to the 'backward' file. This affects only nondefault builds
+ that omit 'backward'.
+
+ Changes affecting version-control only
+
+ .gitignore now ignores 'date'.
+
+ Changes affecting documentation and commentary
+
+ Changes to the 'tzfile' man page
+
+ It now mentions that the binary file format may be extended in
+ future versions by appending data.
+
+ It now refers to the 'zdump' and 'zic' man pages.
+
+ Changes to the 'zic' man page
+
+ It lists conditions that elicit a warning with '-v'.
+
+ It says that the behavior is unspecified when duplicate names
+ are given, or if the source of one link is the target of another.
+
+ Its examples are updated to match the latest data.
+
+ The definition of white space has been clarified slightly.
+ (Thanks to Michael Deckers.)
+
+ Changes to the 'Theory' file
+
+ There is a new section about the accuracy of the tz database,
+ describing the many ways that errors can creep in, and
+ explaining why so many of the pre-1970 timestamps are wrong or
+ misleading (thanks to Steve Allen, Lester Caine, and Garrett
+ Wollman for discussions that contributed to this).
+
+ The 'Theory' file describes LMT better (this follows a
+ suggestion by Guy Harris).
+
+ It refers to the 2013 edition of POSIX rather than the 2004 edition.
+
+ It's mentioned that excluding 'backward' should not affect the
+ other data, and it suggests at least one zone.tab name per
+ inhabited country (thanks to Stephen Colebourne).
+
+ Some longstanding restrictions on names are documented, e.g.,
+ 'America/New_York' precludes 'America/New_York/Bronx'.
+
+ It gives more reasons for the 1970 cutoff.
+
+ It now mentions which time_t variants are supported, such as
+ signed integer time_t. (Thanks to Paul Goyette for reporting
+ typos in an experimental version of this change.)
+
+ (Thanks to Philip Newton for correcting typos in these changes.)
+
+ Documentation and commentary is more careful to distinguish UT in
+ general from UTC in particular. (Thanks to Steve Allen.)
+
+ Add a better source for the Zurich 1894 transition.
+ (Thanks to Pierre-Yves Berger.)
+
+ Update shapefile citations in tz-link.htm. (Thanks to Guy Harris.)
+
+
+Release 2013d - 2013-07-05 07:38:01 -0700
+
+ Changes affecting future timestamps:
+
+ Morocco's midsummer transitions this year are July 7 and August 10,
+ not July 9 and August 8. (Thanks to Andrew Paprocki.)
+
+ Israel now falls back on the last Sunday of October.
+ (Thanks to Ephraim Silverberg.)
+
+ Changes affecting past timestamps:
+
+ Specify Jerusalem's location more precisely; this changes the pre-1880
+ times by 2 s.
+
+ Changing affecting metadata only:
+
+ Fix typos in the entries for country codes BQ and SX.
+
+ Changes affecting code:
+
+ Rework the code to fix a bug with handling Australia/Macquarie on
+ 32-bit hosts (thanks to Arthur David Olson).
+
+ Port to platforms like NetBSD, where time_t can be wider than long.
+
+ Add support for testing time_t types other than the system's.
+ Run 'make check_time_t_alternatives' to try this out.
+ Currently, the tests fail for unsigned time_t;
+ this should get fixed at some point.
+
+ Changes affecting documentation and commentary:
+
+ Deemphasize the significance of national borders.
+
+ Update the zdump man page.
+
+ Remove obsolete NOID comment (thanks to Denis Excoffier).
+
+ Update several URLs and comments in the web pages.
+
+ Spelling fixes (thanks to Kevin Lyda and Jonathan Leffler).
+
+ Update URL for CLDR Zone->Tzid table (thanks to Yoshito Umaoka).
+
+
+Release 2013c - 2013-04-19 16:17:40 -0700
+
+ Changes affecting current and future timestamps:
+
+ Palestine observed DST starting March 29, 2013. (Thanks to
+ Steffen Thorsen.) From 2013 on, Gaza and Hebron both observe DST,
+ with the predicted rules being the last Thursday in March at 24:00
+ to the first Friday on or after September 21 at 01:00.
+
+ Assume that the recent change to Paraguay's DST rules is permanent,
+ by moving the end of DST to the 4th Sunday in March every year.
+ (Thanks to Carlos Raúl Perasso.)
+
+ Changes affecting past timestamps:
+
+ Fix some historical data for Palestine to agree with that of
+ timeanddate.com, as follows:
+
+ The spring 2008 change in Gaza and Hebron was on 00:00 Mar 28, not
+ 00:00 Apr 1.
+
+ The fall 2009 change in Gaza and Hebron on Sep 4 was at 01:00, not
+ 02:00.
+
+ The spring 2010 change in Hebron was 00:00 Mar 26, not 00:01 Mar 27.
+
+ The spring 2011 change in Gaza was 00:01 Apr 1, not 12:01 Apr 2.
+
+ The spring 2011 change in Hebron on Apr 1 was at 00:01, not 12:01.
+
+ The fall 2011 change in Hebron on Sep 30 was at 00:00, not 03:00.
+
+ Fix times of habitation for Macquarie to agree with the Tasmania
+ Parks & Wildlife Service history, which indicates that permanent
+ habitation was 1899-1919 and 1948 on.
+
+ Changing affecting metadata only:
+
+ Macquarie Island is politically part of Australia, not Antarctica.
+ (Thanks to Tobias Conradi.)
+
+ Sort Macquarie more-consistently with other parts of Australia.
+ (Thanks to Tim Parenti.)
+
+
+Release 2013b - 2013-03-10 22:33:40 -0700
+
+ Changes affecting current and future timestamps:
+
+ Haiti uses US daylight-saving rules this year, and presumably future years.
+ This changes timestamps starting today. (Thanks to Steffen Thorsen.)
+
+ Paraguay will end DST on March 24 this year.
+ (Thanks to Steffen Thorsen.) For now, assume it's just this year.
+
+ Morocco does not observe DST during Ramadan;
+ try to predict Ramadan in Morocco as best we can.
+ (Thanks to Erik Homoet for the heads-up.)
+
+ Changes affecting commentary:
+
+ Update URLs in tz-link page. Add URLs for webOS, BB10, iOS.
+ Update URL for Solaris. Mention Internet RFC 6557.
+ Update Internet RFCs 2445->5545, 2822->5322.
+ Switch from FTP to HTTP for Internet RFCs.
+
+
+Release 2013a - 2013-02-27 09:20:35 -0800
+
+ Change affecting binary data format:
+
+ The zone offset at the end of version-2-format zone files is now
+ allowed to be 24:00, as per POSIX.1-2008. (Thanks to Arthur David Olson.)
+
+ Changes affecting current and future timestamps:
+
+ Chile's 2013 rules, and we guess rules for 2014 and later, will be
+ the same as 2012, namely Apr Sun>=23 03:00 UTC to Sep Sun>=2 04:00 UTC.
+ (Thanks to Steffen Thorsen and Robert Elz.)
+
+ New Zones Asia/Khandyga, Asia/Ust-Nera, Europe/Busingen.
+ (Thanks to Tobias Conradi and Arthur David Olson.)
+
+ Many changes affect historical timestamps before 1940.
+ These were deduced from: Milne J. Civil time. Geogr J. 1899
+ Feb;13(2):173-94 <https://www.jstor.org/stable/1774359>.
+
+ Changes affecting the code:
+
+ Fix zic bug that mishandled Egypt's 2010 changes (this also affected
+ the data). (Thanks to Arthur David Olson.)
+
+ Fix localtime bug when time_t is unsigned and data files were generated
+ by a signed time_t system. (Thanks to Doug Bailey for reporting and
+ to Arthur David Olson for fixing.)
+
+ Allow the email address for bug reports to be set by the packager.
+ The default is tz@iana.org, as before. (Thanks to Joseph S. Myers.)
+
+ Update HTML checking to be compatible with Ubuntu 12.10.
+
+ Check that files are a safe subset of ASCII. At some point we may
+ relax this requirement to a safe subset of UTF-8. Without the
+ check, some non-UTF-8 encodings were leaking into the distribution.
+
+ Commentary changes:
+
+ Restore a comment about copyright notices that was inadvertently deleted.
+ (Thanks to Arthur David Olson.)
+
+ Improve the commentary about which districts observe what times
+ in Russia. (Thanks to Oscar van Vlijmen and Arthur David Olson.)
+
+ Add web page links to tz.js.
+
+ Add "Run by the Monkeys" to tz-art. (Thanks to Arthur David Olson.)
+
+
+Release 2012j - 2012-11-12 18:34:49 -0800
+
+ Libya moved to CET this weekend, but with DST planned next year.
+ (Thanks to Even Scharning, Steffen Thorsen, and Tim Parenti.)
+
+ Signatures now have the extension .asc, not .sign, as that's more
+ standard. (Thanks to Phil Pennock.)
+
+ The output of 'zdump --version', and of 'zic --version', now
+ uses a format that is more typical for --version.
+ (Thanks to Joseph S. Myers.)
+
+ The output of 'tzselect --help', 'zdump --help', and 'zic --help'
+ now uses tz@iana.org rather than the old elsie address.
+
+ zic -v now complains about abbreviations that are less than 3
+ or more than 6 characters, as per Posix. Formerly, it checked
+ for abbreviations that were more than 3.
+
+ 'make public' no longer puts its temporary directory under /tmp,
+ and uses the just-built zic rather than the system zic.
+
+ Various fixes to documentation and commentary.
+
+
+Release 2012i - 2012-11-03 12:57:09 -0700
+
+ Cuba switches from DST tomorrow at 01:00. (Thanks to Steffen Thorsen.)
+
+ Linker flags can now be specified via LDFLAGS.
+ AWK now defaults to 'awk', not 'nawk'.
+ The shell in tzselect now defaults to /bin/bash, but this can
+ be overridden by specifying KSHELL.
+ The main web page now mentions the unofficial GitHub repository.
+ (Thanks to Mike Frysinger.)
+
+ Tarball signatures can now be built by running 'make signatures'.
+ There are also new makefile rules 'tarballs', 'check_public', and
+ separate makefile rules for each tarball and signature file.
+ A few makefile rules are now more portable to strict POSIX.
+
+ The main web page now lists the canonical IANA URL.
+
+
+Release 2012h - 2012-10-26 22:49:10 -0700
+
+ Bahia no longer has DST. (Thanks to Kelley Cook.)
+
+ Tocantins has DST. (Thanks to Rodrigo Severo.)
+
+ Israel has new DST rules next year. (Thanks to Ephraim Silverberg.)
+
+ Jordan stays on DST this winter. (Thanks to Steffen Thorsen.)
+
+ Web page updates.
+
+ More C modernization, except that at Arthur David Olson's suggestion
+ the instances of 'register' were kept.
+
+
+Release 2012g - 2012-10-17 20:59:45 -0700
+
+ Samoa fall 2012 and later. (Thanks to Nicholas Pereira and Robert Elz.)
+
+ Palestine fall 2012. (Thanks to Steffen Thorsen.)
+
+ Assume C89.
+
+ To attack the version-number problem, this release ships the file
+ 'Makefile' (which contains the release number) in both the tzcode and
+ the tzdata tarballs. The two Makefiles are identical, and should be
+ identical in any matching pair of tarballs, so it shouldn't matter
+ which order you extract the tarballs. Perhaps we can come up with a
+ better version-number scheme at some point; this scheme does have the
+ virtue of not adding more files.
+
+
+Release 2012f - 2012-09-12 23:17:03 -0700
+
+ * australasia (Pacific/Fiji): Fiji DST is October 21 through January
+ 20 this year. (Thanks to Steffen Thorsen.)
+
+
+Release 2012e - 2012-08-02 20:44:55 -0700
+
+ * australasia (Pacific/Fakaofo): Tokelau is UT +13, not +14.
+ (Thanks to Steffen Thorsen.)
+
+ * Use a single version number for both code and data.
+
+ * .gitignore: New file.
+
+ * Remove trailing white space.
+
+
+Release code2012c-data2012d - 2012-07-19 16:35:33 -0700
+
+ Changes for Morocco's timestamps, which take effect in a couple of
+ hours, along with infrastructure changes to accommodate how the tz
+ code and data are released on IANA.
+
+
+Release data2012c - 2012-03-27 12:17:25 -0400
+
+ africa
+ Summer time changes for Morocco (to start late April 2012)
+
+ asia
+ Changes for 2012 for Gaza & the West Bank (Hebron) and Syria
+
+ northamerica
+ Haiti following US/Canada rules for 2012 (and we're assuming,
+ for now anyway, for the future).
+
+
+Release 2012b - 2012-03-02 12:29:15 +0700
+
+ There is just one change to tzcode2012b (compared with 2012a):
+ the Makefile that was accidentally included with 2012a has been
+ replaced with the version that should have been there, which is
+ identical with the previous version (from tzcode2011i).
+
+ There are just two changes in tzdata2012b compared with 2012a.
+
+ Most significantly, summer time in Cuba has been delayed 3 weeks
+ (now starts April 1 rather than March 11). Since Mar 11 (the old start
+ date, as listed in 2012a) is just a little over a week away, this
+ change is urgent.
+
+ Less importantly, an excess tab in one of the changes in zone.tab
+ in 2012a has been removed.
+
+
+Release 2012a - 2012-03-01 18:28:10 +0700
+
+ The changes in tzcode2012a (compared to the previous version, 2011i)
+ are entirely to the README and tz-art.htm and tz-link.htm files, if
+ none of those concern you, you can ignore the code update. The changes
+ reflect the changed addresses for the mailing list and the code and
+ data distribution points & methods (and a link to DateTime::TimeZone::Tzfile
+ has been added to tz-link.htm).
+
+ In tzdata2012a (compared to the previous release, which was 2011n)
+ the major changes are:
+ Chile 2011/2012 and 2012/2013 summer time date adjustments.
+ Falkland Islands onto permanent summer time (we're assuming for the
+ foreseeable future, though 2012 is all we're fairly certain of.)
+ Armenia has abolished Summer Time.
+ Tokelau jumped the International Date Line back last December
+ (just the same as their near neighbour, Samoa).
+ America/Creston is a new zone for a small area of British Columbia
+ There will be a leapsecond 2012-06-30 23:59:60 UTC.
+
+ Other minor changes are:
+ Corrections to 1918 Canadian summer time end dates.
+ Updated URL for UK time zone history (in comments)
+ A few typos in Le Corre's list of free French place names (comments)
+
+
+Release data2011n - 2011-10-30 14:57:54 +0700
+
+ There are three changes of note - most urgently, Cuba (America/Havana)
+ has extended summer time by two weeks, now to end on Nov 13, rather than
+ the (already past) Oct 30. Second, the Pridnestrovian Moldavian Republic
+ (Europe/Tiraspol) decided not to split from the rest of Moldova after
+ all, and consequently that zone has been removed (again) and reinstated
+ in the "backward" file as a link to Europe/Chisinau. And third, the
+ end date for Fiji's summer time this summer was moved forward from the
+ earlier planned Feb 26, to Jan 22.
+
+ Apart from that, Moldova (MD) returns to a single entry in zone.tab
+ (and the incorrect syntax that was in the 2011m version of that file
+ is so fixed - it would have been fixed in a different way had this
+ change not happened - that's the "missing" sccs version id).
+
+
+Release data2011m - 2011-10-24 21:42:16 +0700
+
+ In particular, the typos in comments in the data (2011-11-17 should have
+ been 2011-10-17 as Alan Barrett noted, and spelling of Tiraspol that
+ Tim Parenti noted) have been fixed, and the change for Ukraine has been
+ made in all 4 Ukrainian zones, rather than just Kiev (again, thanks to
+ Tim Parenti, and also Denys Gavrysh)
+
+ In addition, I added Europe/Tiraspol to zone.tab.
+
+ This time, all the files have new version numbers... (including the files
+ otherwise unchanged in 2011m that were changed in 2011l but didn't get new
+ version numbers there...)
+
+
+Release data2011l - 2011-10-10 11:15:43 +0700
+
+ There are just 2 changes that cause different generated tzdata files from
+ zic, to Asia/Hebron and Pacific/Fiji - the possible change for Bahia, Brazil
+ is included, but commented out. Compared with the diff I sent out last week,
+ this version also includes attributions for the sources for the changes
+ (in much the same format as ado used, but the html tags have not been
+ checked, verified, or used in any way at all, so if there are errors there,
+ please let me know.)
+
+
+Release data2011k - 2011-09-20 17:54:03 -0400
+
+ [not summarized]
+
+
+Release data2011j - 2011-09-12 09:22:49 -0400
+
+ (contemporary changes for Samoa; past changes for Kenya, Uganda, and
+ Tanzania); there are also two spelling corrections to comments in
+ the australasia file (with thanks to Christos Zoulas).
+
+
+Release 2011i - 2011-08-29 05:56:32 -0400
+
+ [not summarized]
+
+
+Release data2011h - 2011-06-15 18:41:48 -0400
+
+ Russia and Curaçao changes
+
+
+Release 2011g - 2011-04-25 09:07:22 -0400
+
+ update the rules for Egypt to reflect its abandonment of DST this year
+
+
+Release 2011f - 2011-04-06 17:14:53 -0400
+
+ [not summarized]
+
+
+Release 2011e - 2011-03-31 16:04:38 -0400
+
+ Morocco, Chile, and tz-link changes
+
+
+Release 2011d - 2011-03-14 09:18:01 -0400
+
+ changes that impact present-day timestamps in Cuba, Samoa, and Turkey
+
+
+Release 2011c - 2011-03-07 09:30:09 -0500
+
+ These do affect current timestamps in Chile and Annette Island, Canada.
+
+
+Release 2011b - 2011-02-07 08:44:50 -0500
+
+ [not summarized]
+
+
+Release 2011a - 2011-01-24 10:30:16 -0500
+
+ [not summarized]
+
+
+Release data2010o - 2010-11-01 09:18:23 -0400
+
+ change to the end of DST in Fiji in 2011
+
+
+Release 2010n - 2010-10-25 08:19:17 -0400
+
+ [not summarized]
+
+
+Release 2010m - 2010-09-27 09:24:48 -0400
+
+ Hong Kong, Vostok, and zic.c changes
+
+
+Release 2010l - 2010-08-16 06:57:25 -0400
+
+ [not summarized]
+
+
+Release 2010k - 2010-07-26 10:42:27 -0400
+
+ [not summarized]
+
+
+Release 2010j - 2010-05-10 09:07:48 -0400
+
+ changes for Bahía de Banderas and for version naming
+
+
+Release data2010i - 2010-04-16 18:50:45 -0400
+
+ the end of DST in Morocco on 2010-08-08
+
+
+Release data2010h - 2010-04-05 09:58:56 -0400
+
+ [not summarized]
+
+
+Release data2010g - 2010-03-24 11:14:53 -0400
+
+ [not summarized]
+
+
+Release 2010f - 2010-03-22 09:45:46 -0400
+
+ [not summarized]
+
+
+Release data2010e - 2010-03-08 14:24:27 -0500
+
+ corrects the Dhaka bug found by Danvin Ruangchan
+
+
+Release data2010d - 2010-03-06 07:26:01 -0500
+
+ [not summarized]
+
+
+Release 2010c - 2010-03-01 09:20:58 -0500
+
+ changes including KRE's suggestion for earlier initialization of
+ "goahead" and "goback" structure elements
+
+
+Release code2010a - 2010-02-16 10:40:04 -0500
+
+ [not summarized]
+
+
+Release data2010b - 2010-01-20 12:37:01 -0500
+
+ Mexico changes
+
+
+Release data2010a - 2010-01-18 08:30:04 -0500
+
+ changes to Dhaka
+
+
+Release data2009u - 2009-12-26 08:32:28 -0500
+
+ changes to DST in Bangladesh
+
+
+Release 2009t - 2009-12-21 13:24:27 -0500
+
+ [not summarized]
+
+
+Release data2009s - 2009-11-14 10:26:32 -0500
+
+ (cosmetic) Antarctica change and the DST-in-Fiji-in-2009-and-2010 change
+
+
+Release 2009r - 2009-11-09 10:10:31 -0500
+
+ "antarctica" and "tz-link.htm" changes
+
+
+Release 2009q - 2009-11-02 09:12:40 -0500
+
+ with two corrections as reported by Eric Muller and Philip Newton
+
+
+Release data2009p - 2009-10-23 15:05:27 -0400
+
+ Argentina (including San Luis) changes (with the correction from
+ Mariano Absatz)
+
+
+Release data2009o - 2009-10-14 16:49:38 -0400
+
+ Samoa (commentary only), Pakistan, and Bangladesh changes
+
+
+Release data2009n - 2009-09-22 15:13:38 -0400
+
+ added commentary for Argentina and a change to the end of DST in
+ 2009 in Pakistan
+
+
+Release data2009m - 2009-09-03 10:23:43 -0400
+
+ Samoa and Palestine changes
+
+
+Release data2009l - 2009-08-14 09:13:07 -0400
+
+ Samoa (comments only) and Egypt
+
+
+Release 2009k - 2009-07-20 09:46:08 -0400
+
+ [not summarized]
+
+
+Release data2009j - 2009-06-15 06:43:59 -0400
+
+ Bangladesh change (with a short turnaround since the DST change is
+ impending)
+
+
+Release 2009i - 2009-06-08 09:21:22 -0400
+
+ updating for DST in Bangladesh this year
+
+
+Release 2009h - 2009-05-26 09:19:14 -0400
+
+ [not summarized]
+
+
+Release data2009g - 2009-04-20 16:34:07 -0400
+
+ Cairo
+
+
+Release data2009f - 2009-04-10 11:00:52 -0400
+
+ correct DST in Pakistan
+
+
+Release 2009e - 2009-04-06 09:08:11 -0400
+
+ [not summarized]
+
+
+Release 2009d - 2009-03-23 09:38:12 -0400
+
+ Morocco, Tunisia, Argentina, and American Astronomical Society changes
+
+
+Release data2009c - 2009-03-16 09:47:51 -0400
+
+ change to the start of Cuban DST
+
+
+Release 2009b - 2009-02-09 11:15:22 -0500
+
+ [not summarized]
+
+
+Release 2009a - 2009-01-21 10:09:39 -0500
+
+ [not summarized]
+
+
+Release data2008i - 2008-10-21 12:10:25 -0400
+
+ southamerica and zone.tab files, with Argentina DST rule changes and
+ United States zone reordering and recommenting
+
+
+Release 2008h - 2008-10-13 07:33:56 -0400
+
+ [not summarized]
+
+
+Release 2008g - 2008-10-06 09:03:18 -0400
+
+ Fix a broken HTML anchor and update Brazil's DST transitions;
+ there's also a slight reordering of information in tz-art.htm.
+
+
+Release data2008f - 2008-09-09 22:33:26 -0400
+
+ [not summarized]
+
+
+Release 2008e - 2008-07-28 14:11:17 -0400
+
+ changes by Arthur David Olson and Jesper Nørgaard Welen
+
+
+Release data2008d - 2008-07-07 09:51:38 -0400
+
+ changes by Arthur David Olson, Paul Eggert, and Rodrigo Severo
+
+
+Release data2008c - 2008-05-19 17:48:03 -0400
+
+ Pakistan, Morocco, and Mongolia
+
+
+Release data2008b - 2008-03-24 08:30:59 -0400
+
+ including renaming Asia/Calcutta to Asia/Kolkata, with a backward
+ link provided
+
+
+Release 2008a - 2008-03-08 05:42:16 -0500
+
+ [not summarized]
+
+
+Release 2007k - 2007-12-31 10:25:22 -0500
+
+ most importantly, changes to the "southamerica" file based on
+ Argentina's readoption of daylight saving time
+
+
+Release 2007j - 2007-12-03 09:51:01 -0500
+
+ 1. eliminate the "P" (parameter) macro;
+
+ 2. the "noncontroversial" changes circulated on the time zone
+ mailing list (less the changes to "logwtmp.c");
+
+ 3. eliminate "too many transition" errors when "min" is used in time
+ zone rules;
+
+ 4. changes by Paul Eggert (including updated information for Venezuela).
+
+
+Release data2007i - 2007-10-30 10:28:11 -0400
+
+ changes for Cuba and Syria
+
+
+Release 2007h - 2007-10-01 10:05:51 -0400
+
+ changes by Paul Eggert, as well as an updated link to the ICU
+ project in tz-link.htm
+
+
+Release 2007g - 2007-08-20 10:47:59 -0400
+
+ changes by Paul Eggert
+
+ The "leapseconds" file has been updated to incorporate the most
+ recent International Earth Rotation and Reference Systems Service
+ (IERS) bulletin.
+
+ There's an addition to tz-art.htm regarding the television show "Medium".
+
+
+Release 2007f - 2007-05-07 10:46:46 -0400
+
+ changes by Paul Eggert (including Haiti, Turks and Caicos, and New
+ Zealand)
+
+ changes to zic.c to allow hour values greater than 24 (along with
+ Paul's improved time value overflow checking)
+
+
+Release 2007e - 2007-04-02 10:11:52 -0400
+
+ Syria and Honduras changes by Paul Eggert
+
+ zic.c variable renaming changes by Arthur David Olson
+
+
+Release 2007d - 2007-03-20 08:48:30 -0400
+
+ changes by Paul Eggert
+
+ the elimination of white space at the ends of lines
+
+
+Release 2007c - 2007-02-26 09:09:37 -0500
+
+ changes by Paul Eggert
+
+
+Release 2007b - 2007-02-12 09:34:20 -0500
+
+ Paul Eggert's proposed change to the quotation handling logic in zic.c.
+
+ changes to the commentary in "leapseconds" reflecting the IERS
+ announcement that there is to be no positive leap second at the end
+ of June 2007.
+
+
+Release 2007a - 2007-01-08 12:28:29 -0500
+
+ changes by Paul Eggert
+
+ Derick Rethans's Asmara change
+
+ Oscar van Vlijmen's Easter Island local mean time change
+
+ symbolic link changes
+
+
+Release 2006p - 2006-11-27 08:54:27 -0500
+
+ changes by Paul Eggert
+
+
+Release 2006o - 2006-11-06 09:18:07 -0500
+
+ changes by Paul Eggert
+
+
+Release 2006n - 2006-10-10 11:32:06 -0400
+
+ changes by Paul Eggert
+
+
+Release 2006m - 2006-10-02 15:32:35 -0400
+
+ changes for Uruguay, Palestine, and Egypt by Paul Eggert
+
+ (minimalist) changes to zic.8 to clarify "until" information
+
+
+Release data2006l - 2006-09-18 12:58:11 -0400
+
+ Paul's best-effort work on this coming weekend's Egypt time change
+
+
+Release 2006k - 2006-08-28 12:19:09 -0400
+
+ changes by Paul Eggert
+
+
+Release 2006j - 2006-08-21 09:56:32 -0400
+
+ changes by Paul Eggert
+
+
+Release code2006i - 2006-08-07 12:30:55 -0400
+
+ localtime.c fixes
+
+ Ken Pizzini's conversion script
+
+
+Release code2006h - 2006-07-24 09:19:37 -0400
+
+ adds public domain notices to four files
+
+ includes a fix for transition times being off by a second
+
+ adds a new recording to the "arts" file (information courtesy Colin Bowern)
+
+
+Release 2006g - 2006-05-08 17:18:09 -0400
+
+ northamerica changes by Paul Eggert
+
+
+Release 2006f - 2006-05-01 11:46:00 -0400
+
+ a missing version number problem is fixed (with thanks to Bradley
+ White for catching the problem)
+
+
+Release 2006d - 2006-04-17 14:33:43 -0400
+
+ changes by Paul Eggert
+
+ added new items to tz-arts.htm that were found by Paul
+
+
+Release 2006c - 2006-04-03 10:09:32 -0400
+
+ two sets of data changes by Paul Eggert
+
+ a fencepost error fix in zic.c
+
+ changes to zic.c and the "europe" file to minimize differences
+ between output produced by the old 32-bit zic and the new 64-bit
+ version
+
+
+Release 2006b - 2006-02-20 10:08:18 -0500
+ [tz32code2006b + tz64code2006b + tzdata2006b]
+
+ 64-bit code
+
+ All SCCS IDs were bumped to "8.1" for this release.
+
+
+Release 2006a - 2006-01-30 08:59:31 -0500
+
+ changes by Paul Eggert (in particular, Indiana time zone moves)
+
+ an addition to the zic manual page to describe how special-case
+ transitions are handled
+
+
+Release 2005r - 2005-12-27 09:27:13 -0500
+
+ Canadian changes by Paul Eggert
+
+ They also add "<pre>" directives to time zone data files and reflect
+ changes to warning message logic in "zdump.c" (but with calls to
+ "gettext" kept unbundled at the suggestion of Ken Pizzini).
+
+
+Release 2005q - 2005-12-13 09:17:09 -0500
+
+ Nothing earth-shaking here:
+ 1. Electronic mail addresses have been removed.
+ 2. Casts of the return value of exit have been removed.
+ 3. Casts of the argument of is.* macros have been added.
+ 4. Indentation in one section of zic.c has been fixed.
+ 5. References to dead URLs in the data files have been dealt with.
+
+
+Release 2005p - 2005-12-05 10:30:53 -0500
+
+ "systemv", "tz-link.htm", and "zdump.c" changes
+ (less the casts of arguments to the is* macros)
+
+
+Release 2005o - 2005-11-28 10:55:26 -0500
+
+ Georgia, Cuba, Nicaragua, and Jordan changes by Paul Eggert
+
+ zdump.c lint fixes by Arthur David Olson
+
+
+Release 2005n - 2005-10-03 09:44:09 -0400
+
+ changes by Paul Eggert (both the Uruguay changes and the Kyrgyzstan
+ et al. changes)
+
+
+Release 2005m - 2005-08-29 12:15:40 -0400
+
+ changes by Paul Eggert (with a small tweak to the tz-art change)
+
+ a declaration of an unused variable has been removed from zdump.c
+
+
+Release 2005l - 2005-08-22 12:06:39 -0400
+
+ changes by Paul Eggert
+
+ overflow/underflow checks by Arthur David Olson, minus changes to
+ the "Theory" file about the pending addition of 64-bit data (I grow
+ less confident of the changes being accepted with each passing day,
+ and the changes no longer increase the data files nine-fold--there's
+ less than a doubling in size by my local Sun's reckoning)
+
+
+Release 2005k - 2005-07-14 14:14:24 -0400
+
+ The "leapseconds" file has been edited to reflect the recently
+ announced leap second at the end of 2005.
+
+ I've also deleted electronic mail addresses from the files as an
+ anti-spam measure.
+
+
+Release 2005j - 2005-06-13 14:34:13 -0400
+
+ These reflect changes to limit the length of time zone abbreviations
+ and the characters used in those abbreviations.
+
+ There are also changes to handle POSIX-style "quoted" timezone
+ environment variables.
+
+ The changes were circulated on the time zone mailing list; the only
+ change since then was the removal of a couple of minimum-length of
+ abbreviation checks.
+
+
+Release data2005i - 2005-04-21 15:04:16 -0400
+
+ changes (most importantly to Nicaragua and Haiti) by Paul Eggert
+
+
+Release 2005h - 2005-04-04 11:24:47 -0400
+
+ changes by Paul Eggert
+
+ minor changes to Makefile and zdump.c to produce more useful output
+ when doing a "make typecheck"
+
+
+Release 2005g - 2005-03-14 10:11:21 -0500
+
+ changes by Paul Eggert (a change to current DST rules in Uruguay and
+ an update to a link to time zone software)
+
+
+Release 2005f - 2005-03-01 08:45:32 -0500
+
+ data and documentation changes by Paul Eggert
+
+
+Release 2005e - 2005-02-10 15:59:44 -0500
+
+ [not summarized]
+
+
+Release code2005d - 2005-01-31 09:21:47 -0500
+
+ make zic complain about links to links if the -v flag is used
+
+ have "make public" do more code checking
+
+ add an include to "localtime.c" for the benefit of gcc systems
+
+
+Release 2005c - 2005-01-17 18:36:29 -0500
+
+ get better results when mktime runs on a system where time_t is double
+
+ changes to the data files (most importantly to Paraguay)
+
+
+Release 2005b - 2005-01-10 09:19:54 -0500
+
+ Get localtime and gmtime working on systems with exotic time_t types.
+
+ Update the leap second commentary in the "leapseconds" file.
+
+
+Release 2005a - 2005-01-01 13:13:44 -0500
+
+ [not summarized]
+
+
+Release code2004i - 2004-12-14 13:42:58 -0500
+
+ Deal with systems where time_t is unsigned.
+
+
+Release code2004h - 2004-12-07 11:40:18 -0500
+
+ 64-bit-time_t changes
+
+
+Release 2004g - 2004-11-02 09:06:01 -0500
+
+ update to Cuba (taking effect this weekend)
+
+ other changes by Paul Eggert
+
+ correction of the spelling of Oslo
+
+ changed versions of difftime.c and private.h
+
+
+Release code2004f - 2004-10-21 10:25:22 -0400
+
+ Cope with wide-ranging tm_year values.
+
+
+Release 2004e - 2004-10-11 14:47:21 -0400
+
+ Brazil/Argentina/Israel changes by Paul Eggert
+
+ changes to tz-link.htm by Paul
+
+ one small fix to Makefile
+
+
+Release 2004d - 2004-09-22 08:27:29 -0400
+
+ Avoid overflow problems when TM_YEAR_BASE is added to an integer.
+
+
+Release 2004c - 2004-08-11 12:06:26 -0400
+
+ asctime-related changes
+
+ (variants of) some of the documentation changes suggested by Paul Eggert
+
+
+Release 2004b - 2004-07-19 14:33:35 -0400
+
+ data changes by Paul Eggert - most importantly, updates for Argentina
+
+
+Release 2004a - 2004-05-27 12:00:47 -0400
+
+ changes by Paul Eggert
+
+ Handle DST transitions that occur at the end of a month in some
+ years but at the start of the following month in other years.
+
+ Add a copy of the correspondence that's the basis for claims about
+ DST in the Navajo Nation.
+
+
+Release 2003e - 2003-12-15 09:36:47 -0500
+
+ changes by Arthur David Olson (primarily code changes)
+
+ changes by Paul Eggert (primarily data changes)
+
+ minor changes to "Makefile" and "northamerica" (in the latter case,
+ optimization of the "Toronto" rules)
+
+
+Release 2003d - 2003-10-06 09:34:44 -0400
+
+ changes by Paul Eggert
+
+
+Release 2003c - 2003-09-16 10:47:05 -0400
+
+ Fix bad returns in zic.c's inleap function.
+ Thanks to Bradley White for catching the problem!
+
+
+Release 2003b - 2003-09-16 07:13:44 -0400
+
+ Add a "--version" option (and documentation) to the zic and zdump commands.
+
+ changes to overflow/underflow checking in zic
+
+ a localtime typo fix.
+
+ Update the leapseconds and tz-art.htm files.
+
+
+Release 2003a - 2003-03-24 09:30:54 -0500
+
+ changes by Paul Eggert
+
+ a few additions and modifications to the tz-art.htm file
+
+
+Release 2002d - 2002-10-15 13:12:42 -0400
+
+ changes by Paul Eggert, less the "Britain (UK)" change in iso3166.tab
+
+ There's also a new time zone quote in "tz-art.htm".
+
+
+Release 2002c - 2002-04-04 11:55:20 -0500
+
+ changes by Paul Eggert
+
+ Change zic.c to avoid creating symlinks to files that don't exist.
+
+
+Release 2002b - 2002-01-28 12:56:03 -0500
+
+ [These change notes are for Release 2002a, which was corrupted.
+ 2002b was a corrected version of 2002a.]
+
+ changes by Paul Eggert
+
+ Update the "leapseconds" file to note that there'll be no leap
+ second at the end of June, 2002.
+
+ Change "zic.c" to deal with a problem in handling the "Asia/Bishkek" zone.
+
+ Change to "difftime.c" to avoid sizeof problems.
+
+
+Release 2001d - 2001-10-09 13:31:32 -0400
+
+ changes by Paul Eggert
+
+
+Release 2001c - 2001-06-05 13:59:55 -0400
+
+ changes by Paul Eggert and Andrew Brown
+
+
+Release 2001b - 2001-04-05 16:44:38 -0400
+
+ changes by Paul Eggert (modulo jnorgard's typo fix)
+
+ tz-art.htm has been HTMLified.
+
+
+Release 2001a - 2001-03-13 12:57:44 -0500
+
+ changes by Paul Eggert
+
+ An addition to the "leapseconds" file: comments with the text of the
+ latest IERS leap second notice.
+
+ Trailing white space has been removed from data file lines, and
+ repeated spaces in "Rule Jordan" lines in the "asia" file have been
+ converted to tabs.
+
+
+Release 2000h - 2000-12-14 15:33:38 -0500
+
+ changes by Paul Eggert
+
+ one typo fix in the "art" file
+
+ With providence, this is the last update of the millennium.
+
+
+Release 2000g - 2000-10-10 11:35:22 -0400
+
+ changes by Paul Eggert
+
+ correction of John Mackin's name submitted by Robert Elz
+
+ Garry Shandling's Daylight Saving Time joke (!?!) from the recent
+ Emmy Awards broadcast.
+
+
+Release 2000f - 2000-08-10 09:31:58 -0400
+
+ changes by Paul Eggert
+
+ Added information in "tz-art.htm" on a Seinfeld reference to DST.
+
+ Error checking and messages in the "yearistype" script have been
+ improved.
+
+
+Release 2000e - 2000-07-31 09:27:54 -0400
+
+ data changes by Paul Eggert
+
+ a change to the default value of the defined constant HAVE_STRERROR
+
+ the addition of a Dave Barry quote on DST to the tz-arts file
+
+
+Release 2000d - 2000-04-20 15:43:04 -0400
+
+ changes to the documentation and code of strftime for C99 conformance
+
+ a bug fix for date.c
+
+ These are based on (though modified from) changes by Paul Eggert.
+
+
+Release 2000c - 2000-03-04 10:31:43 -0500
+
+ changes by Paul Eggert
+
+
+Release 2000b - 2000-02-21 12:16:29 -0500
+
+ changes by Paul Eggert and Joseph Myers
+
+ modest tweaks to the tz-art.htm and tz-link.htm files
+
+
+Release 2000a - 2000-01-18 09:21:26 -0500
+
+ changes by Paul Eggert
+
+ The two hypertext documents have also been renamed.
+
+
+Release code1999i-data1999j - 1999-11-15 18:43:22 -0500
+
+ Paul Eggert's changes
+
+ additions to the "zic" manual page and the "Arts.htm" file
+
+
+Release code1999h-data1999i - 1999-11-08 14:55:21 -0500
+
+ [not summarized]
+
+
+Release data1999h - 1999-10-07 03:50:29 -0400
+
+ changes by Paul Eggert to "europe" (most importantly, fixing
+ Lithuania and Estonia)
+
+
+Release 1999g - 1999-09-28 11:06:18 -0400
+
+ data changes by Paul Eggert (most importantly, the change for
+ Lebanon that buys correctness for this coming Sunday)
+
+ The "code" file contains changes to "Makefile" and "checktab.awk" to
+ allow better checking of time zone files before they are published.
+
+
+Release 1999f - 1999-09-23 09:48:14 -0400
+
+ changes by Arthur David Olson and Paul Eggert
+
+
+Release 1999e - 1999-08-17 15:20:54 -0400
+
+ changes circulated by Paul Eggert, although the change to handling
+ of DST-specifying timezone names has been commented out for now
+ (search for "XXX" in "localtime.c" for details). These files also
+ do not make any changes to the start of DST in Brazil.
+
+ In addition to Paul's changes, there are updates to "Arts.htm" and
+ cleanups of URLs.
+
+
+Release 1999d - 1999-03-30 11:31:07 -0500
+
+ changes by Paul Eggert
+
+ The Makefile's "make public" rule has also been changed to do a test
+ compile of each individual time zone data file (which should help
+ avoid problems such as the one we had with Nicosia).
+
+
+Release 1999c - 1999-03-25 09:47:47 -0500
+
+ changes by Paul Eggert, most importantly the change for Chile.
+
+
+Release 1999b - 1999-02-01 17:51:44 -0500
+
+ changes by Paul Eggert
+
+ code changes (suggested by Mani Varadarajan, mani at be.com) for
+ correct handling of symbolic links when building using a relative directory
+
+ code changes to generate correct messages for failed links
+
+ updates to the URLs in Arts.htm
+
+
+Release 1999a - 1999-01-19 16:20:29 -0500
+
+ error message internationalizations and corrections in zic.c and
+ zdump.c (as suggested by Vladimir Michl, vladimir.michl at upol.cz,
+ to whom thanks!)
+
+
+Release code1998h-data1998i - 1998-10-01 09:56:10 -0400
+
+ changes for Brazil, Chile, and Germany
+
+ support for use of "24:00" in the input files for the time zone compiler
+
+
+Release code1998g-data1998h - 1998-09-24 10:50:28 -0400
+
+ changes by Paul Eggert
+
+ correction to a define in the "private.h" file
+
+
+Release data1998g - 1998-08-11 03:28:35 -0000
+ [tzdata1998g.tar.gz is missing!]
+
+ Lithuanian change provided by mgedmin at pub.osf.it
+
+ Move creation of the GMT link with Etc/GMT to "etcetera" (from
+ "backward") to ensure that the GMT file is created even where folks
+ don't want the "backward" links (as suggested by Paul Eggert).
+
+
+Release data1998f - 1998-07-20 13:50:00 -0000
+ [tzdata1998f.tar.gz is missing!]
+
+ Update the "leapseconds" file to include the newly-announced
+ insertion at the end of 1998.
+
+
+Release code1998f - 1998-06-01 10:18:31 -0400
+
+ addition to localtime.c by Guy Harris
+
+
+Release 1998e - 1998-05-28 09:56:26 -0400
+
+ The Makefile is changed to produce zoneinfo-posix rather than
+ zoneinfo/posix, and to produce zoneinfo-leaps rather than
+ zoneinfo/right.
+
+ data changes by Paul Eggert
+
+ changes from Guy Harris to provide asctime_r and ctime_r
+
+ A usno1998 file (substantially identical to usno1997) has been added.
+
+
+Release 1998d - 1998-05-14 11:58:34 -0400
+
+ changes to comments (in particular, elimination of references to CIA maps).
+ "Arts.htm", "WWW.htm", "asia", and "australasia" are the only places
+ where changes occur.
+
+
+Release 1998c - 1998-02-28 12:32:26 -0500
+
+ changes by Paul Eggert (save the "French correction," on which I'll
+ wait for the dust to settle)
+
+ symlink changes
+
+ changes and additions to Arts.htm
+
+
+Release 1998b - 1998-01-17 14:31:51 -0500
+
+ URL cleanups and additions
+
+
+Release 1998a - 1998-01-13 12:37:35 -0500
+
+ changes by Paul Eggert
+
+
+Release code1997i-data1997k - 1997-12-29 09:53:41 -0500
+
+ changes by Paul Eggert, with minor modifications from Arthur David
+ Olson to make the files more browser friendly
+
+
+Release code1997h-data1997j - 1997-12-18 17:47:35 -0500
+
+ minor changes to put "TZif" at the start of each timezone information file
+
+ a rule has also been added to the Makefile so you can
+ make zones
+ to just recompile the zone information files (rather than doing a
+ full "make install" with its other effects).
+
+
+Release data1997i - 1997-10-07 08:45:38 -0400
+
+ changes to Africa by Paul Eggert
+
+
+Release code1997g-data1997h - 1997-09-04 16:56:54 -0400
+
+ corrections for Uruguay (and other locations)
+
+ Arthur David Olson's simple-minded fix allowing mktime to both
+ correctly handle leap seconds and correctly handle tm_sec values
+ upon which arithmetic has been performed.
+
+
+Release code1997f-data1997g - 1997-07-19 13:15:02 -0400
+
+ Paul Eggert's updates
+
+ a small change to a function prototype;
+
+ "Music" has been renamed "Arts.htm", HTMLified, and augmented to
+ include information on Around the World in Eighty Days.
+
+
+Release code1997e-data1997f - 1997-05-03 18:52:34 -0400
+
+ fixes to zic's error handling
+
+ changes inspired by the item circulated on Slovenia
+
+ The description of Web resources has been HTMLified for browsing
+ convenience.
+
+ A new piece of tz-related music has been added to the "Music" file.
+
+
+Release code1997d-data1997e - 1997-03-29 12:48:52 -0500
+
+ Paul Eggert's latest suggestions
+
+
+Release code1997c-data1997d - 1997-03-07 20:37:54 -0500
+
+ changes to "zic.c" to correct performance of the "-s" option
+
+ a new file "usno1997"
+
+
+Release data1997c - 1997-03-04 09:58:18 -0500
+
+ changes in Israel
+
+
+Release 1997b - 1997-02-27 18:34:19 -0500
+
+ The data file incorporates the 1997 leap second.
+
+ The code file incorporates Arthur David Olson's take on the
+ zic/multiprocessor/directory-creation situation.
+
+
+Release 1997a - 1997-01-21 09:11:10 -0500
+
+ Paul Eggert's Antarctica (and other changes)
+
+ Arthur David Olson finessed the "getopt" issue by checking against
+ both -1 and EOF (regardless of POSIX, SunOS 4.1.1's manual says -1
+ is returned while SunOS 5.5's manual says EOF is returned).
+
+
+Release code1996o-data1996n - 1996-12-27 21:42:05 -0500
+
+ Paul Eggert's latest changes
+
+
+Release code1996n - 1996-12-16 09:42:02 -0500
+
+ link snapping fix from Bruce Evans (via Garrett Wollman)
+
+
+Release data1996m - 1996-11-24 02:37:34 -0000
+ [tzdata1996m.tar.gz is missing!]
+
+ Paul Eggert's batch of changes
+
+
+Release code1996m-data1996l - 1996-11-05 14:00:12 -0500
+
+ No functional changes here; the files have simply been changed to
+ make more use of ISO style dates in comments. The names of the above
+ files now include the year in full.
+
+
+Release code96l - 1996-09-08 17:12:20 -0400
+
+ tzcode96k was missing a couple of pieces.
+
+
+Release 96k - 1996-09-08 16:06:22 -0400
+
+ the latest round of changes from Paul Eggert
+
+ the recent Year 2000 material
+
+
+Release code96j - 1996-07-30 13:18:53 -0400
+
+ Set sp->typecnt as suggested by Timothy Patrick Murphy.
+
+
+Release code96i - 1996-07-27 20:11:35 -0400
+
+ Paul's suggested patch for strftime %V week numbers
+
+
+Release data96i - 1996-07-01 18:13:04 -0400
+
+ "northamerica" and "europe" changes by Paul Eggert
+
+
+Release code96h - 1996-06-05 08:02:21 -0400
+
+ fix for handling transitions specified in Universal Time
+
+ Some "public domain" notices have also been added.
+
+
+Release code96g - 1996-05-16 14:00:26 -0400
+
+ fix for the simultaneous-DST-and-zone-change challenge
+
+
+Release data96h - 1996-05-09 17:40:51 -0400
+
+ changes by Paul Eggert
+
+
+Release code96f-data96g - 1996-05-03 03:09:59 -0000
+ [tzcode96f.tar.gz + tzdata96g.tar.gz are both missing!]
+
+ The changes get us some of the way to fixing the problems noted in Paul
+ Eggert's letter yesterday (in addition to a few others). The approach
+ has been to make zic a bit smarter about figuring out what time zone
+ abbreviations apply just after the time specified in the "UNTIL" part
+ of a zone line. Putting the smarts in zic means avoiding having
+ transition times show up in both "Zone" lines and "Rule" lines, which
+ in turn avoids multiple transition time entries in time zone files.
+ (This also makes the zic input files such as "europe" a bit shorter and
+ should ease maintenance.)
+
+
+Release data96f - 1996-04-19 19:20:03 -0000
+ [tzdata96f.tar.gz is missing!]
+
+ The only changes are to the "northamerica" file; the time zone
+ abbreviation for Denver is corrected to MST (and MDT), and the
+ comments for Mexico have been updated.
+
+
+Release data96e - 1996-03-19 17:37:26 -0500
+
+ Proposals by Paul Eggert, in particular the Portugal change that
+ comes into play at the end of this month.
+
+
+Release data96d - 1996-03-18 20:49:39 -0500
+
+ [not summarized]
+
+
+Release code96e - 1996-02-29 15:43:27 -0000
+ [tzcode96e.tar.gz is missing!]
+
+ internationalization changes and the fix to the documentation for strftime
+
+
+Release code96d-data96c - 1996-02-12 11:05:27 -0500
+
+ The "code" file simply updates Bob Kridle's electronic address.
+
+ The "data" file updates rules for Mexico.
+
+
+Release data96b - 1996-01-27 15:44:42 -0500
+
+ Kiribati change
+
+
+Release code96c - 1996-01-16 16:58:15 -0500
+
+ leap-year streamlining and binary-search changes
+
+ fix to newctime.3
+
+
+Release code96b - 1996-01-10 20:42:39 -0500
+
+ fixes and enhancements from Paul Eggert, including code that
+ emulates the behavior of recent versions of the SunOS "date"
+ command.
+
+
+Release 96a - 1996-01-06 09:08:24 -0500
+
+ Israel updates
+
+ fixes to strftime.c for correct ISO 8601 week number generation,
+ plus support for two new formats ('G' and 'g') to give ISO 8601 year
+ numbers (which are not necessarily the same as calendar year numbers)
+
+
+Release code95i-data95m - 1995-12-21 12:46:47 -0500
+
+ The latest revisions from Paul Eggert are included, the usno1995
+ file has been updated, and a new file ("WWW") covering useful URLs
+ has been added.
+
+
+Release code95h-data95l - 1995-12-19 18:10:12 -0500
+
+ A simplification of a macro definition, a change to data for Sudan,
+ and (for last minute shoppers) notes in the "Music" file on the CD
+ "Old Man Time".
+
+
+Release code95g-data95k - 1995-10-30 10:32:47 -0500
+
+ (slightly reformatted) 8-bit-clean proposed patch
+
+ minor patch: US/Eastern -> America/New_York
+
+ snapshot of the USNO's latest data ("usno1995")
+
+ some other minor cleanups
+
+
+Release code95f-data95j - 1995-10-28 21:01:34 -0000
+ [tzcode95f.tar.gz + tzdata95j.tar.gz are both missing!]
+
+ European cleanups
+
+ support for 64-bit time_t's
+
+ optimization in localtime.c
+
+
+Release code95e - 1995-10-13 13:23:57 -0400
+
+ the mktime change to scan from future to past when trying to find time zone
+ offsets
+
+
+Release data95i - 1995-09-26 10:43:26 -0400
+
+ For Canada/Central, guess that the Sun customer's "one week too
+ early" was just a approximation, and the true error is one month
+ too early. This is consistent with the rest of Canada.
+
+
+Release data95h - 1995-09-21 11:26:48 -0400
+
+ latest changes from Paul Eggert
+
+
+Release code95d - 1995-09-14 11:14:45 -0400
+
+ the addition of a "Music" file, which documents four recorded
+ versions of the tune "Save That Time".
+
+
+Release data95g - 1995-09-01 17:21:36 -0400
+
+ "yearistype" correction
+
+
+Release data95f - 1995-08-28 20:46:56 -0400
+
+ Paul Eggert's change to the australasia file
+
+
+Release data95e - 1995-07-08 18:02:34 -0400
+
+ The only change is a leap second at the end of this year.
+ Thanks to Bradley White for forwarding news on the leap second.
+
+
+Release data95d - 1995-07-03 13:26:22 -0400
+
+ Paul Eggert's changes
+
+
+Release data95c - 1995-07-02 19:19:28 -0400
+
+ changes to "asia", "backward", "europe", and "southamerica"
+ (read: northamericacentrics need not apply)
+
+
+Release code95c - 1995-03-13 14:00:46 -0500
+
+ one-line fix for sign extension problems in detzcode
+
+
+Release 95b - 1995-03-04 11:22:38 -0500
+
+ Minor changes in both:
+
+ The "code" file contains a workaround for the lack of "unistd.h" in
+ Microsoft C++ version 7.
+
+ The "data" file contains a fixed "Link" for America/Shiprock.
+
+
+Release 94h - 1994-12-10 12:51:14 -0500
+
+ The files:
+
+ * incorporate the changes to "zdump" and "date" to make changes to
+ the "TZ" environment variable permanent;
+
+ * incorporate the table changes by Paul Eggert;
+
+ * include (and document) support for universal time specifications in
+ data files - but do not (yet) include use of this feature in the
+ data files.
+
+ Think of this as "TZ Classic" - the software has been set up not to break if
+ universal time shows up in its input, and data entries have been
+ left as is so as not to break existing implementations.
+
+
+Release data94f - 1994-08-20 12:56:09 -0400
+
+ (with thanks!) the latest data updates from Paul Eggert
+
+
+Release data94e - 1994-06-04 13:13:53 -0400
+
+ [not summarized]
+
+
+Release code94g - 1994-05-05 12:14:07 -0400
+
+ fix missing "optind.c" and a reference to it in the Makefile
+
+
+Release code94f - 1994-05-05 13:00:33 -0000
+ [tzcode94f.tar.gz is missing!]
+
+ changes to avoid overflow in difftime, as well as changes to cope
+ with the 52/53 challenge in strftime
+
+
+Release code94e - 1994-03-30 23:32:59 -0500
+
+ change for the benefit of PCTS
+
+
+Release 94d - 1994-02-24 15:42:25 -0500
+
+ Avoid clashes with POSIX semantics for zones such as GMT+4.
+
+ Some other very minor housekeeping is also present.
+
+
+Release code94c - 1994-02-10 08:52:40 -0500
+
+ Fix bug where mkdirs was broken unless you compile with
+ -fwritable-strings (which is generally losing to do).
+
+
+Release 94b - 1994-02-07 10:04:33 -0500
+
+ work by Paul Eggert who notes:
+
+ I found another book of time zone histories by E W Whitman; it's not
+ as extensive as Shanks but has a few goodies of its own. I used it
+ to update the tables. I also fixed some more as a result of
+ correspondence with Adam David and Peter Ilieve, and move some stray
+ links from 'europe' to 'backward'. I corrected some scanning errors
+ in usno1989.
+
+ As far as the code goes, I fixed zic to allow years in the range
+ INT_MIN to INT_MAX; this fixed a few boundary conditions around 1900.
+ And I cleaned up the zic documentation a little bit.
+
+
+Release data94a - 1994-02-03 08:58:54 -0500
+
+ It simply incorporates the recently announced leap second into the
+ "leapseconds" file.
+
+
+Release 93g - 1993-11-22 17:28:27 -0500
+
+ Paul Eggert has provided a good deal of historic information (based
+ on Shanks), and there are some code changes to deal with the buglets
+ that crawled out in dealing with the new information.
+
+
+Release 93f - 1993-10-15 12:27:46 -0400
+
+ Paul Eggert's changes
+
+
+Release 93e - 1993-09-05 21:21:44 -0400
+
+ This has updated data for Israel, England, and Kwajalein. There's
+ also an update to "zdump" to cope with Kwajalein's 24-hour jump.
+ Thanks to Paul Eggert and Peter Ilieve for the changes.
+
+
+Release 93d - 1993-06-17 23:34:17 -0400
+
+ new fix and new data on Israel
+
+
+Release 93c - 1993-06-06 19:31:55 -0400
+
+ [not summarized]
+
+
+Release 93b - 1993-02-02 14:53:58 -0500
+
+ updated "leapseconds" file
+
+
+Release 93 - 1993-01-08 07:01:06 -0500
+
+ At kre's suggestion, the package has been split in two - a code piece
+ (which also includes documentation) that's only of use to folks who
+ want to recompile things and a data piece useful to anyone who can
+ run "zic".
+
+ The new version has a few changes to the data files, a few
+ portability changes, and an off-by-one fix (with thanks to
+ Tom Karzes at deshaw.com for providing a description and a
+ solution).
+
+
+Release 92c - 1992-11-21 17:35:36 -0000
+ [tz92c.tar.Z is missing!]
+
+ The fallout from the latest round of DST transitions.
+
+ There are changes for Portugal, Saskatchewan, and "Pacific-New";
+ there's also a change to "zic.c" that makes it portable to more systems.
+
+
+Release 92 - 1992-04-25 18:17:03 -0000
+ [tz92.tar.Z is missing!]
+
+ By popular demand (well, at any rate, following a request by kre at munnari)
+
+
+The 1989 update of the time zone package featured:
+
+ * POSIXization (including interpretation of POSIX-style TZ environment
+ variables, provided by Guy Harris),
+ * ANSIfication (including versions of "mktime" and "difftime"),
+ * SVIDulation (an "altzone" variable)
+ * MACHination (the "gtime" function)
+ * corrections to some time zone data (including corrections to the rules
+ for Great Britain and New Zealand)
+ * reference data from the United States Naval Observatory for folks who
+ want to do additional time zones
+ * and the 1989 data for Saudi Arabia.
+
+ (Since this code will be treated as "part of the implementation" in some
+ places and as "part of the application" in others, there's no good way to
+ name functions, such as timegm, that are not part of the proposed ANSI C
+ standard; such functions have kept their old, underscore-free names in this
+ update.)
+
+ And the "dysize" function has disappeared; it was present to allow
+ compilation of the "date" command on old BSD systems, and a version of "date"
+ is now provided in the package. The "date" command is not created when you
+ "make all" since it may lack options provided by the version distributed with
+ your operating system, or may not interact with the system in the same way
+ the native version does.
+
+ Since POSIX frowns on correct leap second handling, the default behavior of
+ the "zic" command (in the absence of a "-L" option) has been changed to omit
+ leap second information from its output files.
+
+
+-----
+Notes
+
+This file contains copies of the part of each release announcement
+that talks about the changes in that release. The text has been
+adapted and reformatted for the purposes of this file.
+
+Traditionally a release R consists of a pair of tarball files,
+tzcodeR.tar.gz and tzdataR.tar.gz. However, some releases (e.g.,
+code2010a, data2012c) consist of just one or the other tarball, and a
+few (e.g., code2012c-data2012d) have tarballs with mixed version
+numbers. Recent releases also come in an experimental format
+consisting of a single tarball tzdb-R.tar.lz with extra data.
+
+Release timestamps are taken from the release's commit (for newer,
+Git-based releases), from the newest file in the tarball (for older
+releases, where this info is available) or from the email announcing
+the release (if all else fails; these are marked with a time zone
+abbreviation of -0000 and an "is missing!" comment).
+
+Earlier versions of the code and data were not announced on the tz
+list and are not summarized here.
+
+This file is in the public domain.
+
+Local Variables:
+coding: utf-8
+End:
diff --git a/README b/README
index 427b6a015195..145aacd495b7 100644
--- a/README
+++ b/README
@@ -1,86 +1,52 @@
-@(#)README 8.3
-This file is in the public domain, so clarified as of
-2009-05-17 by Arthur David Olson.
+README for the tz distribution
-"What time is it?" -- Richard Deacon as The King
-"Any time you want it to be." -- Frank Baxter as The Scientist
+"Where do I set the hands of the clock?" -- Les Tremayne as The King
+"Oh that--you can set them any place you want." -- Frank Baxter as The Scientist
(from the Bell System film "About Time")
-The 1989 update of the time zone package featured
+The Time Zone Database (called tz, tzdb or zoneinfo) contains code and
+data that represent the history of local time for many representative
+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.
-* POSIXization (including interpretation of POSIX-style TZ environment
- variables, provided by Guy Harris),
-* ANSIfication (including versions of "mktime" and "difftime"),
-* SVIDulation (an "altzone" variable)
-* MACHination (the "gtime" function)
-* corrections to some time zone data (including corrections to the rules
- for Great Britain and New Zealand)
-* reference data from the United States Naval Observatory for folks who
- want to do additional time zones
-* and the 1989 data for Saudi Arabia.
-
-(Since this code will be treated as "part of the implementation" in some places
-and as "part of the application" in others, there's no good way to name
-functions, such as timegm, that are not part of the proposed ANSI C standard;
-such functions have kept their old, underscore-free names in this update.)
-
-And the "dysize" function has disappeared; it was present to allow compilation
-of the "date" command on old BSD systems, and a version of "date" is now
-provided in the package. The "date" command is not created when you "make all"
-since it may lack options provided by the version distributed with your
-operating system, or may not interact with the system in the same way the
-native version does.
-
-Since POSIX frowns on correct leap second handling, the default behavior of
-the "zic" command (in the absence of a "-L" option) has been changed to omit
-leap second information from its output files.
-
-Here is a recipe for acquiring, building, installing, and testing the
-tz distribution on a GNU/Linux or similar host.
-
- mkdir tz
- cd tz
- wget 'ftp://elsie.nci.nih.gov/pub/tz*.tar.gz'
- gzip -dc tzcode*.tar.gz | tar -xf -
- gzip -dc tzdata*.tar.gz | tar -xf -
-
-Be sure to read the comments in "Makefile" and make any changes needed
+See <https://www.iana.org/time-zones/repository/tz-link.html> or the
+file tz-link.html for how to acquire the code and data. Once acquired,
+read the comments in the file 'Makefile' and make any changes needed
to make things right for your system, especially if you are using some
platform other than GNU/Linux. Then run the following commands,
substituting your desired installation directory for "$HOME/tzdir":
make TOPDIR=$HOME/tzdir install
- $HOME/tzdir/etc/zdump -v America/Los_Angeles
+ $HOME/tzdir/usr/bin/zdump -v America/Los_Angeles
-To use the new functions, use a "-ltz" option when compiling or linking.
+See the file tz-how-to.html for examples of how to read the data files.
-Historical local time information has been included here to:
+This database of historical local time information has several goals:
-* provide a compendium of data about the history of civil time
- that is useful even if the data are not 100% accurate;
+ * Provide a compendium of data about the history of civil time that
+ is useful even if not 100% accurate.
-* give an idea of the variety of local time rules that have
- existed in the past and thus an idea of the variety that may be
- expected in the future;
+ * Give an idea of the variety of local time rules that have existed
+ in the past and thus may be expected in the future.
-* provide a test of the generality of the local time rule description
- system.
+ * Test the generality of the local time rule description system.
The information in the time zone data files is by no means authoritative;
-the files currently do not even attempt to cover all time stamps before
-1970, and there are undoubtedly errors even for time stamps since 1970.
-If you know that the rules are different from those in a file, by all means
-feel free to change file (and please send the changed version to
-tz@elsie.nci.nih.gov for use in the future). Europeans take note!
+fixes and enhancements are welcome. Please see the file CONTRIBUTING
+for details.
-Thanks to these Timezone Caballeros who've made major contributions to the
-time conversion package: Keith Bostic; Bob Devine; Paul Eggert; Robert Elz;
+Thanks to these Time Zone Caballeros who've made major contributions to the
+time conversion package: Keith Bostic; Bob Devine; Paul Eggert; Robert Elz;
Guy Harris; Mark Horton; John Mackin; and Bradley White. Thanks also to
Michael Bloom, Art Neilson, Stephen Prince, John Sovereign, and Frank Wales
for testing work, and to Gwillim Law for checking local mean time data.
+Thanks in particular to Arthur David Olson, the project's founder and first
+maintainer, to whom the time zone community owes the greatest debt of all.
None of them are responsible for remaining errors.
-Look in the ~ftp/pub directory of elsie.nci.nih.gov
-for updated versions of these files.
+-----
-Please send comments or information to tz@elsie.nci.nih.gov.
+This file is in the public domain, so clarified as of 2009-05-17 by
+Arthur David Olson. The other files in this distribution are either
+public domain or BSD licensed; see the file LICENSE for details.
diff --git a/SECURITY b/SECURITY
new file mode 100644
index 000000000000..40128bc86dd2
--- /dev/null
+++ b/SECURITY
@@ -0,0 +1,15 @@
+Please report any sensitive security-related bugs via email to the
+tzdb designated coordinators, currently Paul Eggert
+<eggert@cs.ucla.edu> and Tim Parenti <tim@timtimeonline.com>.
+Put "tzdb security" at the start of your email's subject line.
+We prefer communications to be in English.
+
+You should receive a response within a week. If not, please follow up
+via email to make sure we received your original message.
+
+If we confirm the bug, we plan to notify affected third-party services
+or software that we know about, prepare an advisory, commit fixes to
+the main development branch as quickly as is practical, and finally
+publish the advisory on tz@iana.org. As with all tzdb contributions,
+we give credit to security contributors unless they wish to remain
+anonymous.
diff --git a/Theory b/Theory
deleted file mode 100644
index b1e6bd5c9d5d..000000000000
--- a/Theory
+++ /dev/null
@@ -1,568 +0,0 @@
-@(#)Theory 8.5
-This file is in the public domain, so clarified as of
-2009-05-17 by Arthur David Olson.
-
------ Outline -----
-
- Time and date functions
- Names of time zone regions
- Time zone abbreviations
- Calendrical issues
- Time and time zones on Mars
-
------ Time and date functions -----
-
-These time and date functions are upwards compatible with POSIX,
-an international standard for UNIX-like systems.
-As of this writing, the current edition of POSIX is:
-
- Standard for Information technology
- -- Portable Operating System Interface (POSIX (R))
- -- System Interfaces
- IEEE Std 1003.1, 2004 Edition
- <http://www.opengroup.org/online-pubs?DOC=7999959899>
- <http://www.opengroup.org/pubs/catalog/t041.htm>
-
-POSIX has the following properties and limitations.
-
-* In POSIX, time display in a process is controlled by the
- environment variable TZ. Unfortunately, the POSIX TZ string takes
- a form that is hard to describe and is error-prone in practice.
- Also, POSIX TZ strings can't deal with other (for example, Israeli)
- daylight saving time rules, or situations where more than two
- time zone abbreviations are used in an area.
-
- The POSIX TZ string takes the following form:
-
- stdoffset[dst[offset],date[/time],date[/time]]
-
- where:
-
- std and dst
- are 3 or more characters specifying the standard
- and daylight saving time (DST) zone names.
- Starting with POSIX.1-2001, std and dst may also be
- in a quoted form like "<UTC+10>"; this allows
- "+" and "-" in the names.
- offset
- is of the form `[-]hh:[mm[:ss]]' and specifies the
- offset west of UTC. The default DST offset is one hour
- ahead of standard time.
- date[/time],date[/time]
- specifies the beginning and end of DST. If this is absent,
- the system supplies its own rules for DST, and these can
- differ from year to year; typically US DST rules are used.
- time
- takes the form `hh:[mm[:ss]]' and defaults to 02:00.
- date
- takes one of the following forms:
- Jn (1<=n<=365)
- origin-1 day number not counting February 29
- n (0<=n<=365)
- origin-0 day number counting February 29 if present
- Mm.n.d (0[Sunday]<=d<=6[Saturday], 1<=n<=5, 1<=m<=12)
- for the dth day of week n of month m of the year,
- where week 1 is the first week in which day d appears,
- and `5' stands for the last week in which day d appears
- (which may be either the 4th or 5th week).
-
- Here is an example POSIX TZ string, for US Pacific time using rules
- appropriate from 1987 through 2006:
-
- TZ='PST8PDT,M4.1.0/02:00,M10.5.0/02:00'
-
- This POSIX TZ string is hard to remember, and mishandles time stamps
- before 1987 and after 2006. With this package you can use this
- instead:
-
- TZ='America/Los_Angeles'
-
-* POSIX does not define the exact meaning of TZ values like "EST5EDT".
- Typically the current US DST rules are used to interpret such values,
- but this means that the US DST rules are compiled into each program
- that does time conversion. This means that when US time conversion
- rules change (as in the United States in 1987), all programs that
- do time conversion must be recompiled to ensure proper results.
-
-* In POSIX, there's no tamper-proof way for a process to learn the
- system's best idea of local wall clock. (This is important for
- applications that an administrator wants used only at certain times--
- without regard to whether the user has fiddled the "TZ" environment
- variable. While an administrator can "do everything in UTC" to get
- around the problem, doing so is inconvenient and precludes handling
- daylight saving time shifts--as might be required to limit phone
- calls to off-peak hours.)
-
-* POSIX requires that systems ignore leap seconds.
-
-These are the extensions that have been made to the POSIX functions:
-
-* The "TZ" environment variable is used in generating the name of a file
- from which time zone information is read (or is interpreted a la
- POSIX); "TZ" is no longer constrained to be a three-letter time zone
- name followed by a number of hours and an optional three-letter
- daylight time zone name. The daylight saving time rules to be used
- for a particular time zone are encoded in the time zone file;
- the format of the file allows U.S., Australian, and other rules to be
- encoded, and allows for situations where more than two time zone
- abbreviations are used.
-
- It was recognized that allowing the "TZ" environment variable to
- take on values such as "America/New_York" might cause "old" programs
- (that expect "TZ" to have a certain form) to operate incorrectly;
- consideration was given to using some other environment variable
- (for example, "TIMEZONE") to hold the string used to generate the
- time zone information file name. In the end, however, it was decided
- to continue using "TZ": it is widely used for time zone purposes;
- separately maintaining both "TZ" and "TIMEZONE" seemed a nuisance;
- and systems where "new" forms of "TZ" might cause problems can simply
- use TZ values such as "EST5EDT" which can be used both by
- "new" programs (a la POSIX) and "old" programs (as zone names and
- offsets).
-
-* To handle places where more than two time zone abbreviations are used,
- the functions "localtime" and "gmtime" set tzname[tmp->tm_isdst]
- (where "tmp" is the value the function returns) to the time zone
- abbreviation to be used. This differs from POSIX, where the elements
- of tzname are only changed as a result of calls to tzset.
-
-* Since the "TZ" environment variable can now be used to control time
- conversion, the "daylight" and "timezone" variables are no longer
- needed. (These variables are defined and set by "tzset"; however, their
- values will not be used by "localtime.")
-
-* The "localtime" function has been set up to deliver correct results
- for near-minimum or near-maximum time_t values. (A comment in the
- source code tells how to get compatibly wrong results).
-
-* A function "tzsetwall" has been added to arrange for the system's
- best approximation to local wall clock time to be delivered by
- subsequent calls to "localtime." Source code for portable
- applications that "must" run on local wall clock time should call
- "tzsetwall();" if such code is moved to "old" systems that don't
- provide tzsetwall, you won't be able to generate an executable program.
- (These time zone functions also arrange for local wall clock time to be
- used if tzset is called--directly or indirectly--and there's no "TZ"
- environment variable; portable applications should not, however, rely
- on this behavior since it's not the way SVR2 systems behave.)
-
-* These functions can account for leap seconds, thanks to Bradley White.
-
-Points of interest to folks with other systems:
-
-* This package is already part of many POSIX-compliant hosts,
- including BSD, HP, Linux, Network Appliance, SCO, SGI, and Sun.
- On such hosts, the primary use of this package
- is to update obsolete time zone rule tables.
- To do this, you may need to compile the time zone compiler
- `zic' supplied with this package instead of using the system `zic',
- since the format of zic's input changed slightly in late 1994,
- and many vendors still do not support the new input format.
-
-* The UNIX Version 7 "timezone" function is not present in this package;
- it's impossible to reliably map timezone's arguments (a "minutes west
- of GMT" value and a "daylight saving time in effect" flag) to a
- time zone abbreviation, and we refuse to guess.
- Programs that in the past used the timezone function may now examine
- tzname[localtime(&clock)->tm_isdst] to learn the correct time
- zone abbreviation to use. Alternatively, use
- localtime(&clock)->tm_zone if this has been enabled.
-
-* The 4.2BSD gettimeofday function is not used in this package.
- This formerly let users obtain the current UTC offset and DST flag,
- but this functionality was removed in later versions of BSD.
-
-* In SVR2, time conversion fails for near-minimum or near-maximum
- time_t values when doing conversions for places that don't use UTC.
- This package takes care to do these conversions correctly.
-
-The functions that are conditionally compiled if STD_INSPIRED is defined
-should, at this point, be looked on primarily as food for thought. They are
-not in any sense "standard compatible"--some are not, in fact, specified in
-*any* standard. They do, however, represent responses of various authors to
-standardization proposals.
-
-Other time conversion proposals, in particular the one developed by folks at
-Hewlett Packard, offer a wider selection of functions that provide capabilities
-beyond those provided here. The absence of such functions from this package
-is not meant to discourage the development, standardization, or use of such
-functions. Rather, their absence reflects the decision to make this package
-contain valid extensions to POSIX, to ensure its broad acceptability. If
-more powerful time conversion functions can be standardized, so much the
-better.
-
-
------ Names of time zone rule files -----
-
-The time zone rule file naming conventions attempt to strike a balance
-among the following goals:
-
- * Uniquely identify every national region where clocks have all
- agreed since 1970. This is essential for the intended use: static
- clocks keeping local civil time.
-
- * Indicate to humans as to where that region is. This simplifes use.
-
- * Be robust in the presence of political changes. This reduces the
- number of updates and backward-compatibility hacks. For example,
- names of countries are ordinarily not used, to avoid
- incompatibilities when countries change their name
- (e.g. Zaire->Congo) or when locations change countries
- (e.g. Hong Kong from UK colony to China).
-
- * Be portable to a wide variety of implementations.
- This promotes use of the technology.
-
- * Use a consistent naming convention over the entire world.
- This simplifies both use and maintenance.
-
-This naming convention is not intended for use by inexperienced users
-to select TZ values by themselves (though they can of course examine
-and reuse existing settings). Distributors should provide
-documentation and/or a simple selection interface that explains the
-names; see the 'tzselect' program supplied with this distribution for
-one example.
-
-Names normally have the form AREA/LOCATION, where AREA is the name
-of a continent or ocean, and LOCATION is the name of a specific
-location within that region. North and South America share the same
-area, `America'. Typical names are `Africa/Cairo', `America/New_York',
-and `Pacific/Honolulu'.
-
-Here are the general rules used for choosing location names,
-in decreasing order of importance:
-
- Use only valid POSIX file name components (i.e., the parts of
- names other than `/'). Within a file name component,
- use only ASCII letters, `.', `-' and `_'. Do not use
- digits, as that might create an ambiguity with POSIX
- TZ strings. A file name component must not exceed 14
- characters or start with `-'. E.g., prefer `Brunei'
- to `Bandar_Seri_Begawan'.
- Include at least one location per time zone rule set per country.
- One such location is enough. Use ISO 3166 (see the file
- iso3166.tab) to help decide whether something is a country.
- However, uninhabited ISO 3166 regions like Bouvet Island
- do not need locations, since local time is not defined there.
- If all the clocks in a country's region have agreed since 1970,
- don't bother to include more than one location
- even if subregions' clocks disagreed before 1970.
- Otherwise these tables would become annoyingly large.
- If a name is ambiguous, use a less ambiguous alternative;
- e.g. many cities are named San Jose and Georgetown, so
- prefer `Costa_Rica' to `San_Jose' and `Guyana' to `Georgetown'.
- Keep locations compact. Use cities or small islands, not countries
- or regions, so that any future time zone changes do not split
- locations into different time zones. E.g. prefer `Paris'
- to `France', since France has had multiple time zones.
- Use mainstream English spelling, e.g. prefer `Rome' to `Roma', and
- prefer `Athens' to the true name (which uses Greek letters).
- The POSIX file name restrictions encourage this rule.
- Use the most populous among locations in a country's time zone,
- e.g. prefer `Shanghai' to `Beijing'. Among locations with
- similar populations, pick the best-known location,
- e.g. prefer `Rome' to `Milan'.
- Use the singular form, e.g. prefer `Canary' to `Canaries'.
- Omit common suffixes like `_Islands' and `_City', unless that
- would lead to ambiguity. E.g. prefer `Cayman' to
- `Cayman_Islands' and `Guatemala' to `Guatemala_City',
- but prefer `Mexico_City' to `Mexico' because the country
- of Mexico has several time zones.
- Use `_' to represent a space.
- Omit `.' from abbreviations in names, e.g. prefer `St_Helena'
- to `St._Helena'.
- Do not change established names if they only marginally
- violate the above rules. For example, don't change
- the existing name `Rome' to `Milan' merely because
- Milan's population has grown to be somewhat greater
- than Rome's.
- If a name is changed, put its old spelling in the `backward' file.
-
-The file `zone.tab' lists the geographical locations used to name
-time zone rule files. It is intended to be an exhaustive list
-of canonical names for geographic regions.
-
-Older versions of this package used a different naming scheme,
-and these older names are still supported.
-See the file `backward' for most of these older names
-(e.g. `US/Eastern' instead of `America/New_York').
-The other old-fashioned names still supported are
-`WET', `CET', `MET', and `EET' (see the file `europe').
-
-
------ Time zone abbreviations -----
-
-When this package is installed, it generates time zone abbreviations
-like `EST' to be compatible with human tradition and POSIX.
-Here are the general rules used for choosing time zone abbreviations,
-in decreasing order of importance:
-
- Use abbreviations that consist of three or more ASCII letters.
- Previous editions of this database also used characters like
- ' ' and '?', but these characters have a special meaning to
- the shell and cause commands like
- set `date`
- to have unexpected effects.
- Previous editions of this rule required upper-case letters,
- but the Congressman who introduced Chamorro Standard Time
- preferred "ChST", so the rule has been relaxed.
-
- This rule guarantees that all abbreviations could have
- been specified by a POSIX TZ string. POSIX
- requires at least three characters for an
- abbreviation. POSIX through 2000 says that an abbreviation
- cannot start with ':', and cannot contain ',', '-',
- '+', NUL, or a digit. POSIX from 2001 on changes this
- rule to say that an abbreviation can contain only '-', '+',
- and alphanumeric characters from the portable character set
- in the current locale. To be portable to both sets of
- rules, an abbreviation must therefore use only ASCII
- letters.
-
- Use abbreviations that are in common use among English-speakers,
- e.g. `EST' for Eastern Standard Time in North America.
- We assume that applications translate them to other languages
- as part of the normal localization process; for example,
- a French application might translate `EST' to `HNE'.
-
- For zones whose times are taken from a city's longitude, use the
- traditional xMT notation, e.g. `PMT' for Paris Mean Time.
- The only name like this in current use is `GMT'.
-
- If there is no common English abbreviation, abbreviate the English
- translation of the usual phrase used by native speakers.
- If this is not available or is a phrase mentioning the country
- (e.g. ``Cape Verde Time''), then:
-
- When a country has a single or principal time zone region,
- append `T' to the country's ISO code, e.g. `CVT' for
- Cape Verde Time. For summer time append `ST';
- for double summer time append `DST'; etc.
- When a country has multiple time zones, take the first three
- letters of an English place name identifying each zone
- and then append `T', `ST', etc. as before;
- e.g. `VLAST' for VLAdivostok Summer Time.
-
- Use UTC (with time zone abbreviation "zzz") for locations while
- uninhabited. The "zzz" mnemonic is that these locations are,
- in some sense, asleep.
-
-Application writers should note that these abbreviations are ambiguous
-in practice: e.g. `EST' has a different meaning in Australia than
-it does in the United States. In new applications, it's often better
-to use numeric UTC offsets like `-0500' instead of time zone
-abbreviations like `EST'; this avoids the ambiguity.
-
-
------ Calendrical issues -----
-
-Calendrical issues are a bit out of scope for a time zone database,
-but they indicate the sort of problems that we would run into if we
-extended the time zone database further into the past. An excellent
-resource in this area is Nachum Dershowitz and Edward M. Reingold,
-<a href="http://emr.cs.iit.edu/home/reingold/calendar-book/third-edition/">
-Calendrical Calculations: Third Edition
-</a>, Cambridge University Press (2008). Other information and
-sources are given below. They sometimes disagree.
-
-
-France
-
-Gregorian calendar adopted 1582-12-20.
-French Revolutionary calendar used 1793-11-24 through 1805-12-31,
-and (in Paris only) 1871-05-06 through 1871-05-23.
-
-
-Russia
-
-From Chris Carrier (1996-12-02):
-On 1929-10-01 the Soviet Union instituted an ``Eternal Calendar''
-with 30-day months plus 5 holidays, with a 5-day week.
-On 1931-12-01 it changed to a 6-day week; in 1934 it reverted to the
-Gregorian calendar while retaining the 6-day week; on 1940-06-27 it
-reverted to the 7-day week. With the 6-day week the usual days
-off were the 6th, 12th, 18th, 24th and 30th of the month.
-(Source: Evitiar Zerubavel, _The Seven Day Circle_)
-
-
-Mark Brader reported a similar story in "The Book of Calendars", edited
-by Frank Parise (1982, Facts on File, ISBN 0-8719-6467-8), page 377. But:
-
-From: Petteri Sulonen (via Usenet)
-Date: 14 Jan 1999 00:00:00 GMT
-...
-
-If your source is correct, how come documents between 1929 -- 1940 were
-still dated using the conventional, Gregorian calendar?
-
-I can post a scan of a document dated December 1, 1934, signed by
-Yenukidze, the secretary, on behalf of Kalinin, the President of the
-Executive Committee of the Supreme Soviet, if you like.
-
-
-
-Sweden (and Finland)
-
-From: Mark Brader
-<a href="news:1996Jul6.012937.29190@sq.com">
-Subject: Re: Gregorian reform -- a part of locale?
-</a>
-Date: 1996-07-06
-
-In 1700, Denmark made the transition from Julian to Gregorian. Sweden
-decided to *start* a transition in 1700 as well, but rather than have one of
-those unsightly calendar gaps :-), they simply decreed that the next leap
-year after 1696 would be in 1744 -- putting the whole country on a calendar
-different from both Julian and Gregorian for a period of 40 years.
-
-However, in 1704 something went wrong and the plan was not carried through;
-they did, after all, have a leap year that year. And one in 1708. In 1712
-they gave it up and went back to Julian, putting 30 days in February that
-year!...
-
-Then in 1753, Sweden made the transition to Gregorian in the usual manner,
-getting there only 13 years behind the original schedule.
-
-(A previous posting of this story was challenged, and Swedish readers
-produced the following references to support it: "Tiderakning och historia"
-by Natanael Beckman (1924) and "Tid, en bok om tiderakning och
-kalendervasen" by Lars-Olof Lode'n (no date was given).)
-
-
-Grotefend's data
-
-From: "Michael Palmer" [with one obvious typo fixed]
-Subject: Re: Gregorian Calendar (was Re: Another FHC related question
-Newsgroups: soc.genealogy.german
-Date: Tue, 9 Feb 1999 02:32:48 -800
-...
-
-The following is a(n incomplete) listing, arranged chronologically, of
-European states, with the date they converted from the Julian to the
-Gregorian calendar:
-
-04/15 Oct 1582 - Italy (with exceptions), Spain, Portugal, Poland (Roman
- Catholics and Danzig only)
-09/20 Dec 1582 - France, Lorraine
-
-21 Dec 1582/
- 01 Jan 1583 - Holland, Brabant, Flanders, Hennegau
-10/21 Feb 1583 - bishopric of Liege (L"uttich)
-13/24 Feb 1583 - bishopric of Augsburg
-04/15 Oct 1583 - electorate of Trier
-05/16 Oct 1583 - Bavaria, bishoprics of Freising, Eichstedt, Regensburg,
- Salzburg, Brixen
-13/24 Oct 1583 - Austrian Oberelsass and Breisgau
-20/31 Oct 1583 - bishopric of Basel
-02/13 Nov 1583 - duchy of J"ulich-Berg
-02/13 Nov 1583 - electorate and city of K"oln
-04/15 Nov 1583 - bishopric of W"urzburg
-11/22 Nov 1583 - electorate of Mainz
-16/27 Nov 1583 - bishopric of Strassburg and the margraviate of Baden
-17/28 Nov 1583 - bishopric of M"unster and duchy of Cleve
-14/25 Dec 1583 - Steiermark
-
-06/17 Jan 1584 - Austria and Bohemia
-11/22 Jan 1584 - Luzern, Uri, Schwyz, Zug, Freiburg, Solothurn
-12/23 Jan 1584 - Silesia and the Lausitz
-22 Jan/
- 02 Feb 1584 - Hungary (legally on 21 Oct 1587)
- Jun 1584 - Unterwalden
-01/12 Jul 1584 - duchy of Westfalen
-
-16/27 Jun 1585 - bishopric of Paderborn
-
-14/25 Dec 1590 - Transylvania
-
-22 Aug/
- 02 Sep 1612 - duchy of Prussia
-
-13/24 Dec 1614 - Pfalz-Neuburg
-
- 1617 - duchy of Kurland (reverted to the Julian calendar in
- 1796)
-
- 1624 - bishopric of Osnabr"uck
-
- 1630 - bishopric of Minden
-
-15/26 Mar 1631 - bishopric of Hildesheim
-
- 1655 - Kanton Wallis
-
-05/16 Feb 1682 - city of Strassburg
-
-18 Feb/
- 01 Mar 1700 - Protestant Germany (including Swedish possessions in
- Germany), Denmark, Norway
-30 Jun/
- 12 Jul 1700 - Gelderland, Zutphen
-10 Nov/
- 12 Dec 1700 - Utrecht, Overijssel
-
-31 Dec 1700/
- 12 Jan 1701 - Friesland, Groningen, Z"urich, Bern, Basel, Geneva,
- Turgau, and Schaffhausen
-
- 1724 - Glarus, Appenzell, and the city of St. Gallen
-
-01 Jan 1750 - Pisa and Florence
-
-02/14 Sep 1752 - Great Britain
-
-17 Feb/
- 01 Mar 1753 - Sweden
-
-1760-1812 - Graub"unden
-
-The Russian empire (including Finland and the Baltic states) did not
-convert to the Gregorian calendar until the Soviet revolution of 1917.
-
-Source: H. Grotefend, _Taschenbuch der Zeitrechnung des deutschen
-Mittelalters und der Neuzeit_, herausgegeben von Dr. O. Grotefend
-(Hannover: Hahnsche Buchhandlung, 1941), pp. 26-28.
-
-
------ Time and time zones on Mars -----
-
-Some people have adjusted their work schedules to fit Mars time.
-Dozens of special Mars watches were built for Jet Propulsion
-Laboratory workers who kept Mars time during the Mars Exploration
-Rovers mission (2004). These timepieces look like normal Seikos and
-Citizens but use Mars seconds rather than terrestrial seconds.
-
-A Mars solar day is called a "sol" and has a mean period equal to
-about 24 hours 39 minutes 35.244 seconds in terrestrial time. It is
-divided into a conventional 24-hour clock, so each Mars second equals
-about 1.02749125 terrestrial seconds.
-
-The prime meridian of Mars goes through the center of the crater
-Airy-0, named in honor of the British astronomer who built the
-Greenwich telescope that defines Earth's prime meridian. Mean solar
-time on the Mars prime meridian is called Mars Coordinated Time (MTC).
-
-Each landed mission on Mars has adopted a different reference for
-solar time keeping, so there is no real standard for Mars time zones.
-For example, the Mars Exploration Rover project (2004) defined two
-time zones "Local Solar Time A" and "Local Solar Time B" for its two
-missions, each zone designed so that its time equals local true solar
-time at approximately the middle of the nominal mission. Such a "time
-zone" is not particularly suited for any application other than the
-mission itself.
-
-Many calendars have been proposed for Mars, but none have achieved
-wide acceptance. Astronomers often use Mars Sol Date (MSD) which is a
-sequential count of Mars solar days elapsed since about 1873-12-29
-12:00 GMT.
-
-The tz database does not currently support Mars time, but it is
-documented here in the hopes that support will be added eventually.
-
-Sources:
-
-Michael Allison and Robert Schmunk,
-"Technical Notes on Mars Solar Time as Adopted by the Mars24 Sunclock"
-<http://www.giss.nasa.gov/tools/mars24/help/notes.html> (2004-07-30).
-
-Jia-Rui Chong, "Workdays Fit for a Martian", Los Angeles Times
-(2004-01-14), pp A1, A20-A21.
diff --git a/asctime.c b/asctime.c
index 52586c6aedf2..f0159f8324fa 100644
--- a/asctime.c
+++ b/asctime.c
@@ -1,3 +1,5 @@
+/* asctime and asctime_r a la POSIX and ISO C, except pad years before 1000. */
+
/*
** This file is in the public domain, so clarified as of
** 1996-06-05 by Arthur David Olson.
@@ -9,24 +11,12 @@
** whereas the output of asctime is supposed to be constant.
*/
-#ifndef lint
-#ifndef NOID
-static char elsieid[] = "@(#)asctime.c 8.5";
-#endif /* !defined NOID */
-#endif /* !defined lint */
-
/*LINTLIBRARY*/
#include "private.h"
-#include "tzfile.h"
+#include <stdio.h>
/*
-** Some systems only handle "%.2d"; others only handle "%02d";
-** "%02.2d" makes (most) everybody happy.
-** At least some versions of gcc warn about the %02.2d;
-** we conditionalize below to avoid the warning.
-*/
-/*
** All years associated with 32-bit time_t values are exactly four digits long;
** some years associated with 64-bit time_t values are not.
** Vintage programs are coded for years that are always four digits long
@@ -35,61 +25,45 @@ static char elsieid[] = "@(#)asctime.c 8.5";
** leading zeroes to get the newline in the traditional place.
** The -4 ensures that we get four characters of output even if
** we call a strftime variant that produces fewer characters for some years.
-** The ISO C 1999 and POSIX 1003.1-2004 standards prohibit padding the year,
+** The ISO C and POSIX standards prohibit padding the year,
** but many implementations pad anyway; most likely the standards are buggy.
*/
-#ifdef __GNUC__
-#define ASCTIME_FMT "%.3s %.3s%3d %2.2d:%2.2d:%2.2d %-4s\n"
-#else /* !defined __GNUC__ */
-#define ASCTIME_FMT "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %-4s\n"
-#endif /* !defined __GNUC__ */
+static char const ASCTIME_FMT[] = "%s %s%3d %.2d:%.2d:%.2d %-4s\n";
/*
** For years that are more than four digits we put extra spaces before the year
** so that code trying to overwrite the newline won't end up overwriting
** a digit within a year and truncating the year (operating on the assumption
** that no output is better than wrong output).
*/
-#ifdef __GNUC__
-#define ASCTIME_FMT_B "%.3s %.3s%3d %2.2d:%2.2d:%2.2d %s\n"
-#else /* !defined __GNUC__ */
-#define ASCTIME_FMT_B "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %s\n"
-#endif /* !defined __GNUC__ */
+static char const ASCTIME_FMT_B[] = "%s %s%3d %.2d:%.2d:%.2d %s\n";
-#define STD_ASCTIME_BUF_SIZE 26
+enum { STD_ASCTIME_BUF_SIZE = 26 };
/*
** Big enough for something such as
** ??? ???-2147483648 -2147483648:-2147483648:-2147483648 -2147483648\n
** (two three-character abbreviations, five strings denoting integers,
** seven explicit spaces, two explicit colons, a newline,
-** and a trailing ASCII nul).
+** and a trailing NUL byte).
** The values above are for systems where an int is 32 bits and are provided
-** as an example; the define below calculates the maximum for the system at
+** as an example; the size expression below is a bound for the system at
** hand.
*/
-#define MAX_ASCTIME_BUF_SIZE (2*3+5*INT_STRLEN_MAXIMUM(int)+7+2+1+1)
-
-static char buf_asctime[MAX_ASCTIME_BUF_SIZE];
-
-/*
-** A la ISO/IEC 9945-1, ANSI/IEEE Std 1003.1, 2004 Edition.
-*/
+static char buf_asctime[2*3 + 5*INT_STRLEN_MAXIMUM(int) + 7 + 2 + 1 + 1];
char *
-asctime_r(timeptr, buf)
-register const struct tm * timeptr;
-char * buf;
+asctime_r(register const struct tm *timeptr, char *buf)
{
- static const char wday_name[][3] = {
+ static const char wday_name[][4] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
- static const char mon_name[][3] = {
+ static const char mon_name[][4] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
register const char * wn;
register const char * mn;
char year[INT_STRLEN_MAXIMUM(int) + 2];
- char result[MAX_ASCTIME_BUF_SIZE];
+ char result[sizeof buf_asctime];
if (timeptr == NULL) {
errno = EINVAL;
@@ -107,11 +81,11 @@ char * buf;
** Assume that strftime is unaffected by other out-of-range members
** (e.g., timeptr->tm_mday) when processing "%Y".
*/
- (void) strftime(year, sizeof year, "%Y", timeptr);
+ strftime(year, sizeof year, "%Y", timeptr);
/*
** We avoid using snprintf since it's not available on all systems.
*/
- (void) sprintf(result,
+ sprintf(result,
((strlen(year) <= 4) ? ASCTIME_FMT : ASCTIME_FMT_B),
wn, mn,
timeptr->tm_mday, timeptr->tm_hour,
@@ -120,22 +94,13 @@ char * buf;
if (strlen(result) < STD_ASCTIME_BUF_SIZE || buf == buf_asctime)
return strcpy(buf, result);
else {
-#ifdef EOVERFLOW
errno = EOVERFLOW;
-#else /* !defined EOVERFLOW */
- errno = EINVAL;
-#endif /* !defined EOVERFLOW */
return NULL;
}
}
-/*
-** A la ISO/IEC 9945-1, ANSI/IEEE Std 1003.1, 2004 Edition.
-*/
-
char *
-asctime(timeptr)
-register const struct tm * timeptr;
+asctime(register const struct tm *timeptr)
{
return asctime_r(timeptr, buf_asctime);
}
diff --git a/calendars b/calendars
new file mode 100644
index 000000000000..f4ed9e434e50
--- /dev/null
+++ b/calendars
@@ -0,0 +1,173 @@
+----- Calendrical issues -----
+
+As mentioned in Theory.html, although calendrical issues are out of
+scope for tzdb, they indicate the sort of problems that we would run
+into if we extended tzdb further into the past. The following
+information and sources go beyond Theory.html's brief discussion.
+They sometimes disagree.
+
+
+France
+
+Gregorian calendar adopted 1582-12-20.
+French Revolutionary calendar used 1793-11-24 through 1805-12-31,
+and (in Paris only) 1871-05-06 through 1871-05-23.
+
+
+Russia
+
+From Chris Carrier (1996-12-02):
+On 1929-10-01 the Soviet Union instituted an "Eternal Calendar"
+with 30-day months plus 5 holidays, with a 5-day week.
+On 1931-12-01 it changed to a 6-day week; in 1934 it reverted to the
+Gregorian calendar while retaining the 6-day week; on 1940-06-27 it
+reverted to the 7-day week. With the 6-day week the usual days
+off were the 6th, 12th, 18th, 24th and 30th of the month.
+(Source: Evitiar Zerubavel, _The Seven Day Circle_)
+
+
+Mark Brader reported a similar story in "The Book of Calendars", edited
+by Frank Parise (1982, Facts on File, ISBN 0-8719-6467-8), page 377. But:
+
+From: Petteri Sulonen (via Usenet)
+Date: 14 Jan 1999 00:00:00 GMT
+...
+
+If your source is correct, how come documents between 1929 and 1940 were
+still dated using the conventional, Gregorian calendar?
+
+I can post a scan of a document dated December 1, 1934, signed by
+Yenukidze, the secretary, on behalf of Kalinin, the President of the
+Executive Committee of the Supreme Soviet, if you like.
+
+
+
+Sweden (and Finland)
+
+From: Mark Brader
+Subject: Re: Gregorian reform - a part of locale?
+<news:1996Jul6.012937.29190@sq.com>
+Date: 1996-07-06
+
+In 1700, Denmark made the transition from Julian to Gregorian. Sweden
+decided to *start* a transition in 1700 as well, but rather than have one of
+those unsightly calendar gaps :-), they simply decreed that the next leap
+year after 1696 would be in 1744 - putting the whole country on a calendar
+different from both Julian and Gregorian for a period of 40 years.
+
+However, in 1704 something went wrong and the plan was not carried through;
+they did, after all, have a leap year that year. And one in 1708. In 1712
+they gave it up and went back to Julian, putting 30 days in February that
+year!...
+
+Then in 1753, Sweden made the transition to Gregorian in the usual manner,
+getting there only 13 years behind the original schedule.
+
+(A previous posting of this story was challenged, and Swedish readers
+produced the following references to support it: "Tideräkning och historia"
+by Natanael Beckman (1924) and "Tid, en bok om tideräkning och
+kalenderväsen" by Lars-Olof Lodén (1968).
+
+
+Grotefend's data
+
+From: "Michael Palmer" [with two obvious typos fixed]
+Subject: Re: Gregorian Calendar (was Re: Another FHC related question
+Newsgroups: soc.genealogy.german
+Date: Tue, 9 Feb 1999 02:32:48 -800
+...
+
+The following is a(n incomplete) listing, arranged chronologically, of
+European states, with the date they converted from the Julian to the
+Gregorian calendar:
+
+04/15 Oct 1582 - Italy (with exceptions), Spain, Portugal, Poland (Roman
+ Catholics and Danzig only)
+09/20 Dec 1582 - France, Lorraine
+
+21 Dec 1582/
+ 01 Jan 1583 - Holland, Brabant, Flanders, Hennegau
+10/21 Feb 1583 - bishopric of Liege (Lüttich)
+13/24 Feb 1583 - bishopric of Augsburg
+04/15 Oct 1583 - electorate of Trier
+05/16 Oct 1583 - Bavaria, bishoprics of Freising, Eichstedt, Regensburg,
+ Salzburg, Brixen
+13/24 Oct 1583 - Austrian Oberelsaß and Breisgau
+20/31 Oct 1583 - bishopric of Basel
+02/13 Nov 1583 - duchy of Jülich-Berg
+02/13 Nov 1583 - electorate and city of Köln
+04/15 Nov 1583 - bishopric of Würzburg
+11/22 Nov 1583 - electorate of Mainz
+16/27 Nov 1583 - bishopric of Strassburg and the margraviate of Baden
+17/28 Nov 1583 - bishopric of Münster and duchy of Cleve
+14/25 Dec 1583 - Steiermark
+
+06/17 Jan 1584 - Austria and Bohemia
+11/22 Jan 1584 - Lucerne, Uri, Schwyz, Zug, Freiburg, Solothurn
+12/23 Jan 1584 - Silesia and the Lausitz
+22 Jan/
+ 02 Feb 1584 - Hungary (legally on 21 Oct 1587)
+ Jun 1584 - Unterwalden
+01/12 Jul 1584 - duchy of Westfalen
+
+16/27 Jun 1585 - bishopric of Paderborn
+
+14/25 Dec 1590 - Transylvania
+
+22 Aug/
+ 02 Sep 1612 - duchy of Prussia
+
+13/24 Dec 1614 - Pfalz-Neuburg
+
+ 1617 - duchy of Kurland (reverted to the Julian calendar in
+ 1796)
+
+ 1624 - bishopric of Osnabrück
+
+ 1630 - bishopric of Minden
+
+15/26 Mar 1631 - bishopric of Hildesheim
+
+ 1655 - Kanton Wallis
+
+05/16 Feb 1682 - city of Strassburg
+
+18 Feb/
+ 01 Mar 1700 - Protestant Germany (including Swedish possessions in
+ Germany), Denmark, Norway
+30 Jun/
+ 12 Jul 1700 - Gelderland, Zutphen
+10 Nov/
+ 12 Dec 1700 - Utrecht, Overijssel
+
+31 Dec 1700/
+ 12 Jan 1701 - Friesland, Groningen, Zürich, Bern, Basel, Geneva,
+ Thurgau, and Schaffhausen
+
+ 1724 - Glarus, Appenzell, and the city of St. Gallen
+
+01 Jan 1750 - Pisa and Florence
+
+02/14 Sep 1752 - Great Britain
+
+17 Feb/
+ 01 Mar 1753 - Sweden
+
+1760-1812 - Graubünden
+
+The Russian empire (including Finland and the Baltic states) did not
+convert to the Gregorian calendar until the Soviet revolution of 1917.
+
+Source: H. Grotefend, _Taschenbuch der Zeitrechnung des deutschen
+Mittelalters und der Neuzeit_, herausgegeben von Dr. O. Grotefend
+(Hannover: Hahnsche Buchhandlung, 1941), pp. 26-28.
+
+-----
+
+This file is in the public domain, so clarified as of 2009-05-17 by
+Arthur David Olson.
+
+-----
+Local Variables:
+coding: utf-8
+End:
diff --git a/checktab.awk b/checktab.awk
deleted file mode 100644
index 80ad7d570158..000000000000
--- a/checktab.awk
+++ /dev/null
@@ -1,159 +0,0 @@
-# Check tz tables for consistency.
-
-# @(#)checktab.awk 8.1
-
-# Contributed by Paul Eggert.
-
-BEGIN {
- FS = "\t"
-
- if (!iso_table) iso_table = "iso3166.tab"
- if (!zone_table) zone_table = "zone.tab"
- if (!want_warnings) want_warnings = -1
-
- while (getline <iso_table) {
- iso_NR++
- if ($0 ~ /^#/) continue
- if (NF != 2) {
- printf "%s:%d: wrong number of columns\n", \
- iso_table, iso_NR >>"/dev/stderr"
- status = 1
- }
- cc = $1
- name = $2
- if (cc !~ /^[A-Z][A-Z]$/) {
- printf "%s:%d: invalid country code `%s'\n", \
- iso_table, iso_NR, cc >>"/dev/stderr"
- status = 1
- }
- if (cc <= cc0) {
- if (cc == cc0) {
- s = "duplicate";
- } else {
- s = "out of order";
- }
-
- printf "%s:%d: country code `%s' is %s\n", \
- iso_table, iso_NR, cc, s \
- >>"/dev/stderr"
- status = 1
- }
- cc0 = cc
- if (name2cc[name]) {
- printf "%s:%d: `%s' and `%s' have the sname name\n", \
- iso_table, iso_NR, name2cc[name], cc \
- >>"/dev/stderr"
- status = 1
- }
- name2cc[name] = cc
- cc2name[cc] = name
- cc2NR[cc] = iso_NR
- }
-
- zone_table = "zone.tab"
- cc0 = ""
-
- while (getline <zone_table) {
- zone_NR++
- if ($0 ~ /^#/) continue
- if (NF != 3 && NF != 4) {
- printf "%s:%d: wrong number of columns\n", \
- zone_table, zone_NR >>"/dev/stderr"
- status = 1
- }
- cc = $1
- coordinates = $2
- tz = $3
- comments = $4
- if (cc < cc0) {
- printf "%s:%d: country code `%s' is out of order\n", \
- zone_table, zone_NR, cc >>"/dev/stderr"
- status = 1
- }
- cc0 = cc
- if (tz2cc[tz]) {
- printf "%s:%d: %s: duplicate TZ column\n", \
- zone_table, zone_NR, tz >>"/dev/stderr"
- status = 1
- }
- tz2cc[tz] = cc
- tz2comments[tz] = comments
- tz2NR[tz] = zone_NR
- if (cc2name[cc]) {
- cc_used[cc]++
- } else {
- printf "%s:%d: %s: unknown country code\n", \
- zone_table, zone_NR, cc >>"/dev/stderr"
- status = 1
- }
- if (coordinates !~ /^[-+][0-9][0-9][0-5][0-9][-+][01][0-9][0-9][0-5][0-9]$/ \
- && coordinates !~ /^[-+][0-9][0-9][0-5][0-9][0-5][0-9][-+][01][0-9][0-9][0-5][0-9][0-5][0-9]$/) {
- printf "%s:%d: %s: invalid coordinates\n", \
- zone_table, zone_NR, coordinates >>"/dev/stderr"
- status = 1
- }
- }
-
- for (tz in tz2cc) {
- if (cc_used[tz2cc[tz]] == 1) {
- if (tz2comments[tz]) {
- printf "%s:%d: unnecessary comment `%s'\n", \
- zone_table, tz2NR[tz], tz2comments[tz] \
- >>"/dev/stderr"
- status = 1
- }
- } else {
- if (!tz2comments[tz]) {
- printf "%s:%d: missing comment\n", \
- zone_table, tz2NR[tz] >>"/dev/stderr"
- status = 1
- }
- }
- }
-
- FS = " "
-}
-
-{
- tz = ""
- if ($1 == "Zone") tz = $2
- if ($1 == "Link") {
- # Ignore Link commands if source and destination basenames
- # are identical, e.g. Europe/Istanbul versus Asia/Istanbul.
- src = $2
- dst = $3
- while ((i = index(src, "/"))) src = substr(src, i+1)
- while ((i = index(dst, "/"))) dst = substr(dst, i+1)
- if (src != dst) tz = $3
- }
- if (tz && tz ~ /\//) {
- if (!tz2cc[tz]) {
- printf "%s: no data for `%s'\n", zone_table, tz \
- >>"/dev/stderr"
- status = 1
- }
- zoneSeen[tz] = 1
- }
-}
-
-END {
- for (tz in tz2cc) {
- if (!zoneSeen[tz]) {
- printf "%s:%d: no Zone table for `%s'\n", \
- zone_table, tz2NR[tz], tz >>"/dev/stderr"
- status = 1
- }
- }
-
- if (0 < want_warnings) {
- for (cc in cc2name) {
- if (!cc_used[cc]) {
- printf "%s:%d: warning: " \
- "no Zone entries for %s (%s)\n", \
- iso_table, cc2NR[cc], cc, cc2name[cc]
- }
- }
- }
-
- exit status
-}
diff --git a/date.1 b/date.1
index a3e00731f955..1ecd63a3d90c 100644
--- a/date.1
+++ b/date.1
@@ -4,28 +4,32 @@ date \- show and set date and time
.SH SYNOPSIS
.if n .nh
.if n .na
+.ie \n(.g .ds - \f(CW-\fP
+.el .ds - \-
.B date
[
-.B \-u
+.B \*-u
] [
-.B \-c
+.B \*-c
] [
-.B \-n
-] [
-.B \-d
-dsttype
-] [
-.B \-t
-minutes-west
-] [
-\fB\-a \fR[\fB+\fR|\fB-]\fIsss\fB.\fIfff\fR
+.B \*-r
+.I seconds
] [
.BI + format
] [
\fR[\fIyyyy\fR]\fImmddhhmm\fR[\fIyy\fR][\fB.\fIss\fR]
]
.SH DESCRIPTION
-.I Date
+.ie '\(lq'' .ds lq \&"\"
+.el .ds lq \(lq\"
+.ie '\(rq'' .ds rq \&"\"
+.el .ds rq \(rq\"
+.de q
+\\$3\*(lq\\$1\*(rq\\$2
+..
+The
+.B date
+command
without arguments writes the date and time to the standard output in
the form
.ce 1
@@ -39,13 +43,13 @@ replaced by the local time zone's abbreviation
environment variable if set).
The exact output format depends on the locale.
.PP
-If a command-line argument starts with a plus sign
-.RB (` + '),
+If a command-line argument starts with a plus sign (\c
+.q "\fB+\fP" ),
the rest of the argument is used as a
.I format
that controls what appears in the output.
-In the format, when a percent sign
-.RB (` % ')
+In the format, when a percent sign (\c
+.q "\fB%\fP"
appears,
it and the character after it are not output,
but rather identify part of the date or time
@@ -88,6 +92,7 @@ to be output in a particular way
%X 14:54:40 Time*
%y 89 Last two digits of year
%Y 1989 Year in full
+%z -0500 Numeric time zone
%Z EST Time zone abbreviation
%+ Wed Mar 8 14:54:40 EST 1989 Default output format*
.if t .in -.5i
@@ -103,7 +108,8 @@ a newline character is always added at the end of the output.
.PP
In Sunday-based week numbering,
the first Sunday of the year begins week 1;
-days preceding it are part of ``week 0.''
+days preceding it are part of
+.q "week 0" .
In Monday-based week numbering,
the first Monday of the year begins week 1.
.PP
@@ -130,48 +136,32 @@ the seconds part of the new time; if no seconds are given, zero is assumed.
.PP
These options are available:
.TP
-.BR \-u " or " \-c
-Use UTC when setting and showing the date and time.
-.TP
-.B \-n
-Do not notify other networked systems of the time change.
+.BR \*-u " or " \*-c
+Use Universal Time when setting and showing the date and time.
.TP
-.BI "\-d " dsttype
-Set the kernel-stored Daylight Saving Time type to the given value.
-(The kernel-stored DST type is used mostly by ``old'' binaries.)
-.TP
-.BI "\-t " minutes-west
-Set the kernel-stored ``minutes west of UTC'' value to the one given on the
-command line.
-(The kernel-stored DST type is used mostly by ``old'' binaries.)
-.TP
-.BI "\-a " adjustment
-Change the time forward (or backward) by the number of seconds
-(and fractions thereof) specified in the
-.I adjustment\^
-argument.
-Either the seconds part or the fractions part of the argument (but not both)
-may be omitted.
-On BSD-based systems,
-the adjustment is made by changing the rate at which time advances;
-on System-V-based systems, the adjustment is made by changing the time.
+.BI "\*-r " seconds
+Output the date that corresponds to
+.I seconds
+past the epoch of 1970-01-01 00:00:00 UTC, where
+.I seconds
+should be an integer, either decimal, octal (leading 0), or
+hexadecimal (leading 0x), preceded by an optional sign.
.SH FILES
-.ta \w'/usr/local/etc/zoneinfo/posixrules\0\0'u
-/usr/lib/locale/\f2L\fP/LC_TIME description of time locale \f2L\fP
+.ta \w'/usr/share/zoneinfo/posixrules\0\0'u
+/etc/localtime local timezone file
.br
-/usr/local/etc/zoneinfo time zone information directory
+/usr/lib/locale/\f2L\fP/LC_TIME description of time locale \f2L\fP
.br
-/usr/local/etc/zoneinfo/localtime local time zone file
+/usr/share/zoneinfo timezone information directory
.br
-/usr/local/etc/zoneinfo/posixrules used with POSIX-style TZ's
+/usr/share/zoneinfo/posixrules used with POSIX-style TZ's
.br
-/usr/local/etc/zoneinfo/GMT for UTC leap seconds
+/usr/share/zoneinfo/GMT for UTC leap seconds
.sp
If
-.B /usr/local/etc/zoneinfo/GMT
+.B /usr/share/zoneinfo/GMT
is absent,
UTC leap seconds are loaded from
-.BR /usr/local/etc/zoneinfo/posixrules .
-.\" @(#)date.1 8.2
+.BR /usr/share/zoneinfo/posixrules .
.\" This file is in the public domain, so clarified as of
.\" 2009-05-17 by Arthur David Olson.
diff --git a/date.1.txt b/date.1.txt
index 2910aaac370c..5affca23b2f0 100644
--- a/date.1.txt
+++ b/date.1.txt
@@ -1,127 +1,107 @@
-NAME
+DATE(1) General Commands Manual DATE(1)
- date - show and set date and time
+NAME
+ date - show and set date and time
SYNOPSIS
- date [ -u ] [ -c ] [ -n ] [ -d dsttype ] [ -t minutes-west ]
- [ -a [+|-]sss.fff ] [ +format ] [ [yyyy]mmddhhmm[yy][.ss] ]
+ date [ -u ] [ -c ] [ -r seconds ] [ +format ] [ [yyyy]mmddhhmm[yy][.ss]
+ ]
DESCRIPTION
- Date without arguments writes the date and time to the
- standard output in the form
- Wed Mar 8 14:54:40 EST 1989
- with EST replaced by the local time zone's abbreviation (or
- by the abbreviation for the time zone specified in the TZ
- environment variable if set). The exact output format
- depends on the locale.
-
- If a command-line argument starts with a plus sign (`+'),
- the rest of the argument is used as a format that controls
- what appears in the output. In the format, when a percent
- sign (`%') appears, it and the character after it are not
- output, but rather identify part of the date or time to be
- output in a particular way (or identify a special character
- to output):
+ The date command without arguments writes the date and time to the
+ standard output in the form
+ Wed Mar 8 14:54:40 EST 1989
+ with EST replaced by the local time zone's abbreviation (or by the
+ abbreviation for the time zone specified in the TZ environment variable
+ if set). The exact output format depends on the locale.
- Sample output Explanation
- %a Wed Abbreviated weekday name*
- %A Wednesday Full weekday name*
- %b Mar Abbreviated month name*
- %B March Full month name*
- %c Wed Mar 08 14:54:40 1989 Date and time*
- %C 19 Century
- %d 08 Day of month (always two digits)
- %D 03/08/89 Month/day/year (eight characters)
- %e 8 Day of month (leading zero blanked)
- %h Mar Abbreviated month name*
- %H 14 24-hour-clock hour (two digits)
- %I 02 12-hour-clock hour (two digits)
- %j 067 Julian day number (three digits)
- %k 2 12-hour-clock hour (leading zero blanked)
- %l 14 24-hour-clock hour (leading zero blanked)
- %m 03 Month number (two digits)
- %M 54 Minute (two digits)
- %n \n newline character
- %p PM AM/PM designation
- %r 02:54:40 PM Hour:minute:second AM/PM designation
- %R 14:54 Hour:minute
- %S 40 Second (two digits)
- %t \t tab character
- %T 14:54:40 Hour:minute:second
- %U 10 Sunday-based week number (two digits)
- %w 3 Day number (one digit, Sunday is 0)
- %W 10 Monday-based week number (two digits)
- %x 03/08/89 Date*
- %X 14:54:40 Time*
- %y 89 Last two digits of year
- %Y 1989 Year in full
- %Z EST Time zone abbreviation
- %+ Wed Mar 8 14:54:40 EST 1989 Default output format*
- * The exact output depends on the locale.
+ If a command-line argument starts with a plus sign ("+"), the rest of
+ the argument is used as a format that controls what appears in the
+ output. In the format, when a percent sign ("%" appears, it and the
+ character after it are not output, but rather identify part of the date
+ or time to be output in a particular way (or identify a special
+ character to output):
- If a character other than one of those shown above appears
- after a percent sign in the format, that following character
- is output. All other characters in the format are copied
- unchanged to the output; a newline character is always added
- at the end of the output.
- In Sunday-based week numbering, the first Sunday of the year
- begins week 1; days preceding it are part of ``week 0.'' In
- Monday-based week numbering, the first Monday of the year
- begins week 1.
+ Sample output Explanation
+ %a Wed Abbreviated weekday name*
+ %A Wednesday Full weekday name*
+ %b Mar Abbreviated month name*
+ %B March Full month name*
+ %c Wed Mar 08 14:54:40 1989 Date and time*
+ %C 19 Century
+ %d 08 Day of month (always two digits)
+ %D 03/08/89 Month/day/year (eight characters)
+ %e 8 Day of month (leading zero blanked)
+ %h Mar Abbreviated month name*
+ %H 14 24-hour-clock hour (two digits)
+ %I 02 12-hour-clock hour (two digits)
+ %j 067 Julian day number (three digits)
+ %k 2 12-hour-clock hour (leading zero blanked)
+ %l 14 24-hour-clock hour (leading zero blanked)
+ %m 03 Month number (two digits)
+ %M 54 Minute (two digits)
+ %n \n newline character
+ %p PM AM/PM designation
+ %r 02:54:40 PM Hour:minute:second AM/PM designation
+ %R 14:54 Hour:minute
+ %S 40 Second (two digits)
+ %t \t tab character
+ %T 14:54:40 Hour:minute:second
+ %U 10 Sunday-based week number (two digits)
+ %w 3 Day number (one digit, Sunday is 0)
+ %W 10 Monday-based week number (two digits)
+ %x 03/08/89 Date*
+ %X 14:54:40 Time*
+ %y 89 Last two digits of year
+ %Y 1989 Year in full
+ %z -0500 Numeric time zone
+ %Z EST Time zone abbreviation
+ %+ Wed Mar 8 14:54:40 EST 1989 Default output format*
+ * The exact output depends on the locale.
- To set the date, use a command line argument with one of the
- following forms:
- 1454 24-hour-clock hours (first two digits) and minutes
- 081454 Month day (first two digits), hours, and minutes
- 03081454 Month (two digits, January is 01), month day, hours, minutes
- 8903081454 Year, month, month day, hours, minutes
- 0308145489 Month, month day, hours, minutes, year
- (on System V-compatible systems)
- 030814541989 Month, month day, hours, minutes, four-digit year
- 198903081454 Four-digit year, month, month day, hours, minutes
- If the century, year, month, or month day is not given, the
- current value is used. Any of the above forms may be
- followed by a period and two digits that give the seconds
- part of the new time; if no seconds are given, zero is
- assumed.
+ If a character other than one of those shown above appears after a
+ percent sign in the format, that following character is output. All
+ other characters in the format are copied unchanged to the output; a
+ newline character is always added at the end of the output.
- These options are available:
+ In Sunday-based week numbering, the first Sunday of the year begins
+ week 1; days preceding it are part of "week 0". In Monday-based week
+ numbering, the first Monday of the year begins week 1.
- -u or -c
- Use UTC when setting and showing the date and time.
+ To set the date, use a command line argument with one of the following
+ forms:
+ 1454 24-hour-clock hours (first two digits) and minutes
+ 081454 Month day (first two digits), hours, and minutes
+ 03081454 Month (two digits, January is 01), month day, hours, minutes
+ 8903081454 Year, month, month day, hours, minutes
+ 0308145489 Month, month day, hours, minutes, year
+ (on System V-compatible systems)
+ 030814541989 Month, month day, hours, minutes, four-digit year
+ 198903081454 Four-digit year, month, month day, hours, minutes
+ If the century, year, month, or month day is not given, the current
+ value is used. Any of the above forms may be followed by a period and
+ two digits that give the seconds part of the new time; if no seconds
+ are given, zero is assumed.
- -n Do not notify other networked systems of the time
- change.
+ These options are available:
- -d dsttype
- Set the kernel-stored Daylight Saving Time type to the
- given value. (The kernel-stored DST type is used
- mostly by ``old'' binaries.)
+ -u or -c
+ Use Universal Time when setting and showing the date and time.
- -t minutes-west
- Set the kernel-stored ``minutes west of UTC'' value to
- the one given on the command line. (The kernel-stored
- DST type is used mostly by ``old'' binaries.)
-
- -a adjustment
- Change the time forward (or backward) by the number of
- seconds (and fractions thereof) specified in the
- adjustment argument. Either the seconds part or the
- fractions part of the argument (but not both) may be
- omitted. On BSD-based systems, the adjustment is made
- by changing the rate at which time advances; on System-
- V-based systems, the adjustment is made by changing the
- time.
+ -r seconds
+ Output the date that corresponds to seconds past the epoch of
+ 1970-01-01 00:00:00 UTC, where seconds should be an integer,
+ either decimal, octal (leading 0), or hexadecimal (leading 0x),
+ preceded by an optional sign.
FILES
- /usr/lib/locale/L/LC_TIME description of time
- locale L
- /usr/local/etc/zoneinfo time zone information
- directory
- /usr/local/etc/zoneinfo/localtime local time zone file
- /usr/local/etc/zoneinfo/posixrules used with POSIX-style
- TZ's
- /usr/local/etc/zoneinfo/GMT for UTC leap seconds
+ /etc/localtime local timezone file
+ /usr/lib/locale/L/LC_TIME description of time locale L
+ /usr/share/zoneinfo timezone information directory
+ /usr/share/zoneinfo/posixrules used with POSIX-style TZ's
+ /usr/share/zoneinfo/GMT for UTC leap seconds
+
+ If /usr/share/zoneinfo/GMT is absent, UTC leap seconds are loaded from
+ /usr/share/zoneinfo/posixrules.
- If /usr/local/etc/zoneinfo/GMT is absent, UTC leap seconds
- are loaded from /usr/local/etc/zoneinfo/posixrules.
+ DATE(1)
diff --git a/date.c b/date.c
index 6a6d2cdaffcd..4e4b355af03f 100644
--- a/date.c
+++ b/date.c
@@ -1,313 +1,114 @@
-#ifndef lint
-#ifndef NOID
-static char elsieid[] = "@(#)date.c 8.4";
-/*
-** Modified from the UCB version with the SCCS ID appearing below.
-*/
-#endif /* !defined NOID */
-#endif /* !defined lint */
-
-/*
- * Copyright (c) 1985, 1987, 1988 The Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANT[A]BILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifndef lint
-char copyright[] =
-"@(#) Copyright (c) 1985, 1987, 1988 The Regents of the University of California.\n\
- All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-static char sccsid[] = "@(#)date.c 4.23 (Berkeley) 9/20/88";
-#endif /* not lint */
+/* Display or set the current time and date. */
+
+/* Copyright 1985, 1987, 1988 The Regents of the University of California.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the University nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE. */
#include "private.h"
-#if HAVE_ADJTIME || HAVE_SETTIMEOFDAY
-#include "sys/time.h" /* for struct timeval, struct timezone */
-#endif /* HAVE_ADJTIME || HAVE_SETTIMEOFDAY */
-#include "locale.h"
-#include "utmp.h" /* for OLD_TIME (or its absence) */
-#if HAVE_UTMPX_H
-#include "utmpx.h"
-#endif
-
-#ifndef OTIME_MSG
-#define OTIME_MSG "old time"
-#endif
-#ifndef NTIME_MSG
-#define NTIME_MSG "new time"
-#endif
-
-/*
-** The two things date knows about time are. . .
-*/
-
-#ifndef TM_YEAR_BASE
-#define TM_YEAR_BASE 1900
-#endif /* !defined TM_YEAR_BASE */
+#include <locale.h>
+#include <stdio.h>
-#ifndef SECSPERMIN
-#define SECSPERMIN 60
-#endif /* !defined SECSPERMIN */
-
-extern double atof();
-extern char ** environ;
-extern char * getlogin();
-extern time_t mktime();
+#if !HAVE_POSIX_DECLS
extern char * optarg;
extern int optind;
-extern char * strchr();
-extern time_t time();
-extern char * tzname[2];
+#endif
static int retval = EXIT_SUCCESS;
-static void checkfinal(const char *, int, time_t, time_t);
-static int comptm(const struct tm *, const struct tm *);
-static time_t convert(const char *, int, time_t);
-static void display(const char *);
+static void display(const char *, time_t);
static void dogmt(void);
static void errensure(void);
-static void iffy(time_t, time_t, const char *, const char *);
-int main(int, char**);
-static const char * nondigit(const char *);
-static void oops(const char *);
-static void reset(time_t, int);
static void timeout(FILE *, const char *, const struct tm *);
-static void usage(void);
-static void wildinput(const char *, const char *,
- const char *);
+static _Noreturn void usage(void);
int
-main(argc, argv)
-const int argc;
-char * argv[];
+main(const int argc, char *argv[])
{
- register const char * format;
- register const char * value;
- register const char * cp;
+ register const char * format = "+%+";
register int ch;
- register int dousg;
- register int aflag = 0;
- register int dflag = 0;
- register int nflag = 0;
- register int tflag = 0;
- register int minuteswest;
- register int dsttime;
- register double adjust;
- time_t now;
+ register bool rflag = false;
time_t t;
+ intmax_t secs;
+ char * endarg;
- INITIALIZE(dousg);
- INITIALIZE(minuteswest);
- INITIALIZE(dsttime);
- INITIALIZE(adjust);
- INITIALIZE(t);
#ifdef LC_ALL
- (void) setlocale(LC_ALL, "");
+ setlocale(LC_ALL, "");
#endif /* defined(LC_ALL) */
#if HAVE_GETTEXT
-#ifdef TZ_DOMAINDIR
- (void) bindtextdomain(TZ_DOMAIN, TZ_DOMAINDIR);
-#endif /* defined(TEXTDOMAINDIR) */
- (void) textdomain(TZ_DOMAIN);
+# ifdef TZ_DOMAINDIR
+ bindtextdomain(TZ_DOMAIN, TZ_DOMAINDIR);
+# endif /* defined(TEXTDOMAINDIR) */
+ textdomain(TZ_DOMAIN);
#endif /* HAVE_GETTEXT */
- (void) time(&now);
- format = value = NULL;
- while ((ch = getopt(argc, argv, "ucnd:t:a:")) != EOF && ch != -1) {
+ t = time(NULL);
+ while ((ch = getopt(argc, argv, "ucr:")) != EOF && ch != -1) {
switch (ch) {
default:
usage();
- case 'u': /* do it in UTC */
+ case 'u': /* do it in UT */
case 'c':
dogmt();
break;
- case 'n': /* don't set network */
- nflag = 1;
- break;
- case 'd': /* daylight saving time */
- if (dflag) {
- (void) fprintf(stderr,
- _("date: error: multiple -d's used"));
+ case 'r': /* seconds since 1970 */
+ if (rflag) {
+ fprintf(stderr,
+ _("date: error: multiple -r's used"));
usage();
}
- dflag = 1;
- cp = optarg;
- dsttime = atoi(cp);
- if (*cp == '\0' || *nondigit(cp) != '\0')
- wildinput(_("-t value"), optarg,
- _("must be a non-negative number"));
- break;
- case 't': /* minutes west of UTC */
- if (tflag) {
- (void) fprintf(stderr,
- _("date: error: multiple -t's used"));
- usage();
+ rflag = true;
+ errno = 0;
+ secs = strtoimax(optarg, &endarg, 0);
+ if (*endarg || optarg == endarg)
+ errno = EINVAL;
+ else if (! (TIME_T_MIN <= secs && secs <= TIME_T_MAX))
+ errno = ERANGE;
+ if (errno) {
+ perror(optarg);
+ errensure();
+ exit(retval);
}
- tflag = 1;
- cp = optarg;
- minuteswest = atoi(cp);
- if (*cp == '+' || *cp == '-')
- ++cp;
- if (*cp == '\0' || *nondigit(cp) != '\0')
- wildinput(_("-d value"), optarg,
- _("must be a number"));
+ t = secs;
break;
- case 'a': /* adjustment */
- if (aflag) {
- (void) fprintf(stderr,
- _("date: error: multiple -a's used"));
- usage();
- }
- aflag = 1;
- cp = optarg;
- adjust = atof(cp);
- if (*cp == '+' || *cp == '-')
- ++cp;
- if (*cp == '\0' || strcmp(cp, ".") == 0)
- wildinput(_("-a value"), optarg,
- _("must be a number"));
- cp = nondigit(cp);
- if (*cp == '.')
- ++cp;
- if (*nondigit(cp) != '\0')
- wildinput(_("-a value"), optarg,
- _("must be a number"));
- break;
- }
- }
- while (optind < argc) {
- cp = argv[optind++];
- if (*cp == '+')
- if (format == NULL)
- format = cp + 1;
- else {
- (void) fprintf(stderr,
-_("date: error: multiple formats in command line\n"));
- usage();
- }
- else if (value == NULL)
- value = cp;
- else {
- (void) fprintf(stderr,
-_("date: error: multiple values in command line\n"));
- usage();
- }
- }
- if (value != NULL) {
- /*
- ** This order ensures that "reasonable" twelve-digit inputs
- ** (such as 120203042006) won't be misinterpreted
- ** even if time_t's range all the way back to the thirteenth
- ** century. Do not change the order.
- */
- t = convert(value, (dousg = TRUE), now);
- if (t == -1)
- t = convert(value, (dousg = FALSE), now);
- if (t == -1) {
- /*
- ** Out of range values,
- ** or time that falls in a DST transition hole?
- */
- if ((cp = strchr(value, '.')) != NULL) {
- /*
- ** Ensure that the failure of
- ** TZ=America/New_York date 8712312359.60
- ** doesn't get misdiagnosed. (It was
- ** TZ=America/New_York date 8712311859.60
- ** when the leap second was inserted.)
- ** The normal check won't work since
- ** the given time is valid in UTC.
- */
- if (atoi(cp + 1) >= SECSPERMIN)
- wildinput(_("time"), value,
- _("out of range seconds given"));
- }
- dogmt();
- t = convert(value, FALSE, now);
- if (t == -1)
- t = convert(value, TRUE, now);
- wildinput(_("time"), value,
- (t == -1) ?
- _("out of range value given") :
- _("time skipped when clock springs forward"));
}
}
- /*
- ** Entire command line has now been checked.
- */
- if (aflag) {
-#if HAVE_ADJTIME
- struct timeval tv;
-
- tv.tv_sec = (int) adjust;
- tv.tv_usec = (int) ((adjust - tv.tv_sec) * 1000000L);
- if (adjtime(&tv, (struct timeval *) NULL) != 0)
- oops("adjtime");
-#endif /* HAVE_ADJTIME */
-#if !HAVE_ADJTIME
- reset((time_t) (now + adjust), nflag);
-#endif /* !HAVE_ADJTIME */
- /*
- ** Sun silently ignores everything else; we follow suit.
- */
- exit(retval);
- }
- if (dflag || tflag) {
-#if HAVE_SETTIMEOFDAY == 2
- struct timezone tz;
-
- if (!dflag || !tflag)
- if (gettimeofday((struct timeval *) NULL, &tz) != 0)
- oops("gettimeofday");
- if (dflag)
- tz.tz_dsttime = dsttime;
- if (tflag)
- tz.tz_minuteswest = minuteswest;
- if (settimeofday((struct timeval *) NULL, &tz) != 0)
- oops("settimeofday");
-#endif /* HAVE_SETTIMEOFDAY == 2 */
-#if HAVE_SETTIMEOFDAY != 2
- (void) fprintf(stderr,
-_("date: warning: kernel doesn't keep -d/-t information, option ignored\n"));
-#endif /* HAVE_SETTIMEOFDAY != 2 */
+ if (optind < argc) {
+ if (argc - optind != 1) {
+ fprintf(stderr,
+ _("date: error: multiple operands in command line\n"));
+ usage();
+ }
+ format = argv[optind];
+ if (*format != '+') {
+ fprintf(stderr, _("date: unknown operand: %s\n"), format);
+ usage();
+ }
}
- if (value == NULL)
- display(format);
-
- reset(t, nflag);
-
- checkfinal(value, dousg, t, now);
-
-#ifdef EBUG
- {
- struct tm tm;
-
- tm = *localtime(&t);
- timeout(stdout, "%c\n", &tm);
- exit(retval);
- }
-#endif /* defined EBUG */
-
- display(format);
-
- /* gcc -Wall pacifier */
- for ( ; ; )
- continue;
+ display(format, t);
+ return retval;
}
static void
@@ -319,18 +120,18 @@ dogmt(void)
register int from;
register int to;
register int n;
- static char tzegmt0[] = "TZ=GMT0";
+ static char tzeutc0[] = "TZ=UTC0";
for (n = 0; environ[n] != NULL; ++n)
continue;
- fakeenv = (char **) malloc((size_t) (n + 2) * sizeof *fakeenv);
+ fakeenv = malloc((n + 2) * sizeof *fakeenv);
if (fakeenv == NULL) {
- (void) perror(_("Memory exhausted"));
+ fprintf(stderr, _("date: Memory exhausted\n"));
errensure();
exit(retval);
}
to = 0;
- fakeenv[to++] = tzegmt0;
+ fakeenv[to++] = tzeutc0;
for (from = 1; environ[from] != NULL; ++from)
if (strncmp(environ[from], "TZ=", 3) != 0)
fakeenv[to++] = environ[from];
@@ -339,165 +140,6 @@ dogmt(void)
}
}
-#ifdef OLD_TIME
-
-/*
-** We assume we're on a System-V-based system,
-** should use stime,
-** should write System-V-format utmp entries,
-** and don't have network notification to worry about.
-*/
-
-#include "fcntl.h" /* for O_WRONLY, O_APPEND */
-
-/*ARGSUSED*/
-static void
-reset(const time_t newt, const int nflag)
-{
- register int fid;
- time_t oldt;
- static struct {
- struct utmp before;
- struct utmp after;
- } s;
-#if HAVE_UTMPX_H
- static struct {
- struct utmpx before;
- struct utmpx after;
- } sx;
-#endif
-
- /*
- ** Wouldn't it be great if stime returned the old time?
- */
- (void) time(&oldt);
- if (stime(&newt) != 0)
- oops("stime");
- s.before.ut_type = OLD_TIME;
- s.before.ut_time = oldt;
- (void) strcpy(s.before.ut_line, OTIME_MSG);
- s.after.ut_type = NEW_TIME;
- s.after.ut_time = newt;
- (void) strcpy(s.after.ut_line, NTIME_MSG);
- fid = open(WTMP_FILE, O_WRONLY | O_APPEND);
- if (fid < 0)
- oops(_("log file open"));
- if (write(fid, (char *) &s, sizeof s) != sizeof s)
- oops(_("log file write"));
- if (close(fid) != 0)
- oops(_("log file close"));
-#if !HAVE_UTMPX_H
- pututline(&s.before);
- pututline(&s.after);
-#endif /* !HAVE_UTMPX_H */
-#if HAVE_UTMPX_H
- sx.before.ut_type = OLD_TIME;
- sx.before.ut_tv.tv_sec = oldt;
- (void) strcpy(sx.before.ut_line, OTIME_MSG);
- sx.after.ut_type = NEW_TIME;
- sx.after.ut_tv.tv_sec = newt;
- (void) strcpy(sx.after.ut_line, NTIME_MSG);
-#if !SUPPRESS_WTMPX_FILE_UPDATE
- /* In Solaris 2.5 (and presumably other systems),
- `date' does not update /var/adm/wtmpx.
- This must be a bug. If you'd like to reproduce the bug,
- define SUPPRESS_WTMPX_FILE_UPDATE to be nonzero. */
- fid = open(WTMPX_FILE, O_WRONLY | O_APPEND);
- if (fid < 0)
- oops(_("log file open"));
- if (write(fid, (char *) &sx, sizeof sx) != sizeof sx)
- oops(_("log file write"));
- if (close(fid) != 0)
- oops(_("log file close"));
-#endif /* !SUPPRESS_WTMPX_FILE_UPDATE */
- pututxline(&sx.before);
- pututxline(&sx.after);
-#endif /* HAVE_UTMPX_H */
-}
-
-#endif /* defined OLD_TIME */
-#ifndef OLD_TIME
-
-/*
-** We assume we're on a BSD-based system,
-** should use settimeofday,
-** should write BSD-format utmp entries (using logwtmp),
-** and may get to worry about network notification.
-** The "time name" changes between 4.3-tahoe and 4.4;
-** we include sys/param.h to determine which we should use.
-*/
-
-#ifndef TIME_NAME
-#include "sys/param.h"
-#ifdef BSD4_4
-#define TIME_NAME "date"
-#endif /* defined BSD4_4 */
-#ifndef BSD4_4
-#define TIME_NAME ""
-#endif /* !defined BSD4_4 */
-#endif /* !defined TIME_NAME */
-
-#include "syslog.h"
-#include "sys/socket.h"
-#include "netinet/in.h"
-#include "netdb.h"
-#define TSPTYPES
-#include "protocols/timed.h"
-
-extern int logwtmp();
-
-#if HAVE_SETTIMEOFDAY == 1
-#define settimeofday(t, tz) (settimeofday)(t)
-#endif /* HAVE_SETTIMEOFDAY == 1 */
-
-#ifndef TSP_SETDATE
-/*ARGSUSED*/
-#endif /* !defined TSP_SETDATE */
-static void
-reset(newt, nflag)
-const time_t newt;
-const int nflag;
-{
- register const char * username;
- static struct timeval tv; /* static so tv_usec is 0 */
-
-#ifdef EBUG
- return;
-#endif /* defined EBUG */
- username = getlogin();
- if (username == NULL || *username == '\0') /* single-user or no tty */
- username = "root";
- tv.tv_sec = newt;
-#ifdef TSP_SETDATE
- if (nflag || !netsettime(tv))
-#endif /* defined TSP_SETDATE */
- {
- /*
- ** "old" entry is always written, for compatibility.
- */
- logwtmp("|", TIME_NAME, "");
- if (settimeofday(&tv, (struct timezone *) NULL) == 0) {
- logwtmp("{", TIME_NAME, ""); /* } */
- syslog(LOG_AUTH | LOG_NOTICE, _("date set by %s"),
- username);
- } else oops("settimeofday");
- }
-}
-
-#endif /* !defined OLD_TIME */
-
-static void
-wildinput(item, value, reason)
-const char * const item;
-const char * const value;
-const char * const reason;
-{
- (void) fprintf(stderr,
- _("date: error: bad command line %s \"%s\", %s\n"),
- item, value, reason);
- usage();
-}
-
static void
errensure(void)
{
@@ -505,441 +147,70 @@ errensure(void)
retval = EXIT_FAILURE;
}
-static const char *
-nondigit(cp)
-register const char * cp;
-{
- while (is_digit(*cp))
- ++cp;
- return cp;
-}
-
static void
usage(void)
{
- (void) fprintf(stderr, _("date: usage is date [-u] [-c] [-n] [-d dst] \
-[-t min-west] [-a sss.fff] [[yyyy]mmddhhmm[yyyy][.ss]] [+format]\n"));
+ fprintf(stderr,
+ _("date: usage: date [-u] [-c] [-r seconds]"
+ " [+format]\n"));
errensure();
exit(retval);
}
static void
-oops(string)
-const char * const string;
+display(char const *format, time_t now)
{
- int e = errno;
-
- (void) fprintf(stderr, _("date: error: "));
- errno = e;
- (void) perror(string);
- errensure();
- display((char *) NULL);
-}
+ struct tm *tmp;
-static void
-display(format)
-const char * const format;
-{
- struct tm tm;
- time_t now;
-
- (void) time(&now);
- tm = *localtime(&now);
- timeout(stdout, format ? format : "%+", &tm);
- (void) putchar('\n');
- (void) fflush(stdout);
- (void) fflush(stderr);
+ tmp = localtime(&now);
+ if (!tmp) {
+ fprintf(stderr,
+ _("date: error: time out of range\n"));
+ errensure();
+ return;
+ }
+ timeout(stdout, format, tmp);
+ putchar('\n');
+ fflush(stdout);
+ fflush(stderr);
if (ferror(stdout) || ferror(stderr)) {
- (void) fprintf(stderr,
+ fprintf(stderr,
_("date: error: couldn't write results\n"));
errensure();
}
- exit(retval);
}
-extern size_t strftime();
-
-#define INCR 1024
-
static void
-timeout(fp, format, tmp)
-FILE * const fp;
-const char * const format;
-const struct tm * const tmp;
+timeout(FILE *fp, char const *format, struct tm const *tmp)
{
char * cp;
size_t result;
size_t size;
+ struct tm tm;
+ int INCR = 1024;
- if (*format == '\0')
+ if (!tmp) {
+ fprintf(stderr, _("date: error: time out of range\n"));
+ errensure();
return;
+ }
+ tm = *tmp;
+ tmp = &tm;
size = INCR;
- cp = malloc((size_t) size);
+ cp = malloc(size);
for ( ; ; ) {
if (cp == NULL) {
- (void) fprintf(stderr,
+ fprintf(stderr,
_("date: error: can't get memory\n"));
errensure();
exit(retval);
}
- cp[0] = '\1';
result = strftime(cp, size, format, tmp);
- if (result != 0 || cp[0] == '\0')
+ if (result != 0)
break;
size += INCR;
- cp = realloc(cp, (size_t) size);
+ cp = realloc(cp, size);
}
- (void) fwrite(cp, 1, result, fp);
+ fwrite(cp + 1, 1, result - 1, fp);
free(cp);
}
-
-static int
-comptm(atmp, btmp)
-register const struct tm * const atmp;
-register const struct tm * const btmp;
-{
- register int result;
-
- if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
- (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
- (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
- (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
- (result = (atmp->tm_min - btmp->tm_min)) == 0)
- result = atmp->tm_sec - btmp->tm_sec;
- return result;
-}
-
-/*
-** convert --
-** convert user's input into a time_t.
-*/
-
-#define ATOI2(ar) (ar[0] - '0') * 10 + (ar[1] - '0'); ar += 2;
-
-static time_t
-convert(register const char * const value, const int dousg, const time_t t)
-{
- register const char * cp;
- register const char * dotp;
- register int cent, year_in_cent, month, hour, day, mins, secs;
- struct tm tm, outtm;
- time_t outt;
-
- tm = *localtime(&t);
-#define DIVISOR 100
- year_in_cent = tm.tm_year % DIVISOR + TM_YEAR_BASE % DIVISOR;
- cent = tm.tm_year / DIVISOR + TM_YEAR_BASE / DIVISOR +
- year_in_cent / DIVISOR;
- year_in_cent %= DIVISOR;
- if (year_in_cent < 0) {
- year_in_cent += DIVISOR;
- --cent;
- }
- month = tm.tm_mon + 1;
- day = tm.tm_mday;
- hour = tm.tm_hour;
- mins = tm.tm_min;
- secs = 0;
-
- dotp = strchr(value, '.');
- for (cp = value; *cp != '\0'; ++cp)
- if (!is_digit(*cp) && cp != dotp)
- wildinput(_("time"), value, _("contains a nondigit"));
-
- if (dotp == NULL)
- dotp = strchr(value, '\0');
- else {
- cp = dotp + 1;
- if (strlen(cp) != 2)
- wildinput(_("time"), value,
- _("seconds part is not two digits"));
- secs = ATOI2(cp);
- }
-
- cp = value;
- switch (dotp - cp) {
- default:
- wildinput(_("time"), value,
- _("main part is wrong length"));
- case 12:
- if (!dousg) {
- cent = ATOI2(cp);
- year_in_cent = ATOI2(cp);
- }
- month = ATOI2(cp);
- day = ATOI2(cp);
- hour = ATOI2(cp);
- mins = ATOI2(cp);
- if (dousg) {
- cent = ATOI2(cp);
- year_in_cent = ATOI2(cp);
- }
- break;
- case 8: /* mmddhhmm */
- month = ATOI2(cp);
- /* fall through to. . . */
- case 6: /* ddhhmm */
- day = ATOI2(cp);
- /* fall through to. . . */
- case 4: /* hhmm */
- hour = ATOI2(cp);
- mins = ATOI2(cp);
- break;
- case 10:
- if (!dousg) {
- year_in_cent = ATOI2(cp);
- }
- month = ATOI2(cp);
- day = ATOI2(cp);
- hour = ATOI2(cp);
- mins = ATOI2(cp);
- if (dousg) {
- year_in_cent = ATOI2(cp);
- }
- break;
- }
-
- tm.tm_year = cent * 100 + year_in_cent - TM_YEAR_BASE;
- tm.tm_mon = month - 1;
- tm.tm_mday = day;
- tm.tm_hour = hour;
- tm.tm_min = mins;
- tm.tm_sec = secs;
- tm.tm_isdst = -1;
- outtm = tm;
- outt = mktime(&outtm);
- return (comptm(&tm, &outtm) == 0) ? outt : -1;
-}
-
-/*
-** Code from here on out is either based on code provided by UCB
-** or is only called just before the program exits.
-*/
-
-/*
-** Check for iffy input.
-*/
-
-static void
-checkfinal(const char * const value,
- const int didusg,
- const time_t t,
- const time_t oldnow)
-{
- time_t othert;
- struct tm tm;
- struct tm othertm;
- register int pass;
- register long offset;
-
- /*
- ** See if there's both a USG and a BSD interpretation.
- */
- othert = convert(value, !didusg, oldnow);
- if (othert != -1 && othert != t)
- iffy(t, othert, value, _("year could be at start or end"));
- /*
- ** See if there's both a DST and a STD version.
- */
- tm = *localtime(&t);
- othertm = tm;
- othertm.tm_isdst = !tm.tm_isdst;
- othert = mktime(&othertm);
- if (othert != -1 && othertm.tm_isdst != tm.tm_isdst &&
- comptm(&tm, &othertm) == 0)
- iffy(t, othert, value,
- _("both standard and summer time versions exist"));
-/*
-** Final check.
-**
-** If a jurisdiction shifts time *without* shifting whether time is
-** summer or standard (as Hawaii, the United Kingdom, and Saudi Arabia
-** have done), routine checks for iffy times may not work.
-** So we perform this final check, deferring it until after the time has
-** been set--it may take a while, and we don't want to introduce an unnecessary
-** lag between the time the user enters their command and the time that
-** stime/settimeofday is called.
-**
-** We just check nearby times to see if any have the same representation
-** as the time that convert returned. We work our way out from the center
-** for quick response in solar time situations. We only handle common cases--
-** offsets of at most a minute, and offsets of exact numbers of minutes
-** and at most an hour.
-*/
- for (offset = 1; offset <= 60; ++offset)
- for (pass = 1; pass <= 4; ++pass) {
- if (pass == 1)
- othert = t + offset;
- else if (pass == 2)
- othert = t - offset;
- else if (pass == 3)
- othert = t + 60 * offset;
- else othert = t - 60 * offset;
- othertm = *localtime(&othert);
- if (comptm(&tm, &othertm) == 0)
- iffy(t, othert, value,
- _("multiple matching times exist"));
- }
-}
-
-static void
-iffy(const time_t thist, const time_t thatt,
- const char * const value, const char * const reason)
-{
- struct tm tm;
-
- (void) fprintf(stderr, _("date: warning: ambiguous time \"%s\", %s.\n"),
- value, reason);
- tm = *gmtime(&thist);
- /*
- ** Avoid running afoul of SCCS!
- */
- timeout(stderr, _("Time was set as if you used\n\tdate -u %m%d%H\
-%M\
-%Y.%S\n"), &tm);
- tm = *localtime(&thist);
- timeout(stderr, _("to get %c"), &tm);
- (void) fprintf(stderr, _(" (%s). Use\n"),
- tm.tm_isdst ? _("summer time") : _("standard time"));
- tm = *gmtime(&thatt);
- timeout(stderr, _("\tdate -u %m%d%H\
-%M\
-%Y.%S\n"), &tm);
- tm = *localtime(&thatt);
- timeout(stderr, _("to get %c"), &tm);
- (void) fprintf(stderr, _(" (%s).\n"),
- tm.tm_isdst ? _("summer time") : _("standard time"));
- errensure();
- exit(retval);
-}
-
-#ifdef TSP_SETDATE
-#define WAITACK 2 /* seconds */
-#define WAITDATEACK 5 /* seconds */
-
-/*
- * Set the date in the machines controlled by timedaemons
- * by communicating the new date to the local timedaemon.
- * If the timedaemon is in the master state, it performs the
- * correction on all slaves. If it is in the slave state, it
- * notifies the master that a correction is needed.
- * Returns 1 on success, 0 on failure.
- */
-netsettime(ntv)
- struct timeval ntv;
-{
- int s, length, port, timed_ack, found, err;
- long waittime;
- fd_set ready;
- char hostname[MAXHOSTNAMELEN];
- struct timeval tout;
- struct servent *sp;
- struct tsp msg;
- struct sockaddr_in sin, dest, from;
-
- sp = getservbyname("timed", "udp");
- if (sp == 0) {
- fputs(_("udp/timed: unknown service\n"), stderr);
- retval = 2;
- return (0);
- }
- dest.sin_port = sp->s_port;
- dest.sin_family = AF_INET;
- dest.sin_addr.s_addr = htonl((u_long)INADDR_ANY);
- s = socket(AF_INET, SOCK_DGRAM, 0);
- if (s < 0) {
- if (errno != EPROTONOSUPPORT)
- perror("date: socket");
- goto bad;
- }
- bzero((char *)&sin, sizeof (sin));
- sin.sin_family = AF_INET;
- for (port = IPPORT_RESERVED - 1; port > IPPORT_RESERVED / 2; port--) {
- sin.sin_port = htons((u_short)port);
- if (bind(s, (struct sockaddr *)&sin, sizeof (sin)) >= 0)
- break;
- if (errno != EADDRINUSE) {
- if (errno != EADDRNOTAVAIL)
- perror("date: bind");
- goto bad;
- }
- }
- if (port == IPPORT_RESERVED / 2) {
- fputs(_("date: All ports in use\n"), stderr);
- goto bad;
- }
- msg.tsp_type = TSP_SETDATE;
- msg.tsp_vers = TSPVERSION;
- if (gethostname(hostname, sizeof (hostname))) {
- perror("gethostname");
- goto bad;
- }
- (void) strncpy(msg.tsp_name, hostname, sizeof (hostname));
- msg.tsp_seq = htons((u_short)0);
- msg.tsp_time.tv_sec = htonl((u_long)ntv.tv_sec);
- msg.tsp_time.tv_usec = htonl((u_long)ntv.tv_usec);
- length = sizeof (struct sockaddr_in);
- if (connect(s, &dest, length) < 0) {
- perror("date: connect");
- goto bad;
- }
- if (send(s, (char *)&msg, sizeof (struct tsp), 0) < 0) {
- if (errno != ECONNREFUSED)
- perror("date: send");
- goto bad;
- }
- timed_ack = -1;
- waittime = WAITACK;
-loop:
- tout.tv_sec = waittime;
- tout.tv_usec = 0;
- FD_ZERO(&ready);
- FD_SET(s, &ready);
- found = select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout);
- length = sizeof err;
- if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char *)&err, &length) == 0
- && err) {
- errno = err;
- if (errno != ECONNREFUSED)
- perror(_("date: send (delayed error)"));
- goto bad;
- }
- if (found > 0 && FD_ISSET(s, &ready)) {
- length = sizeof (struct sockaddr_in);
- if (recvfrom(s, (char *)&msg, sizeof (struct tsp), 0, &from,
- &length) < 0) {
- if (errno != ECONNREFUSED)
- perror("date: recvfrom");
- goto bad;
- }
- msg.tsp_seq = ntohs(msg.tsp_seq);
- msg.tsp_time.tv_sec = ntohl(msg.tsp_time.tv_sec);
- msg.tsp_time.tv_usec = ntohl(msg.tsp_time.tv_usec);
- switch (msg.tsp_type) {
-
- case TSP_ACK:
- timed_ack = TSP_ACK;
- waittime = WAITDATEACK;
- goto loop;
-
- case TSP_DATEACK:
- (void)close(s);
- return (1);
-
- default:
- fprintf(stderr,
- _("date: Wrong ack received from timed: %s\n"),
- tsptype[msg.tsp_type]);
- timed_ack = -1;
- break;
- }
- }
- if (timed_ack == -1)
- fputs(_("date: Can't reach time daemon, time set locally.\n"),
- stderr);
-bad:
- (void)close(s);
- retval = 2;
- return (0);
-}
-#endif /* defined TSP_SETDATE */
diff --git a/difftime.c b/difftime.c
index da779773bfdd..ff78f03c5705 100644
--- a/difftime.c
+++ b/difftime.c
@@ -1,65 +1,60 @@
+/* Return the difference between two timestamps. */
+
/*
** This file is in the public domain, so clarified as of
** 1996-06-05 by Arthur David Olson.
*/
-#ifndef lint
-#ifndef NOID
-static char elsieid[] = "@(#)difftime.c 8.1";
-#endif /* !defined NOID */
-#endif /* !defined lint */
-
/*LINTLIBRARY*/
-#include "private.h" /* for time_t, TYPE_INTEGRAL, and TYPE_SIGNED */
+#include "private.h" /* for time_t and TYPE_SIGNED */
+
+/* Return -X as a double. Using this avoids casting to 'double'. */
+static double
+dminus(double x)
+{
+ return -x;
+}
double
-difftime(time1, time0)
-const time_t time1;
-const time_t time0;
+difftime(time_t time1, time_t time0)
{
/*
- ** If (sizeof (double) > sizeof (time_t)) simply convert and subtract
+ ** If double is large enough, simply convert and subtract
** (assuming that the larger type has more precision).
- ** This is the common real-world case circa 2004.
*/
- if (sizeof (double) > sizeof (time_t))
- return (double) time1 - (double) time0;
- if (!TYPE_INTEGRAL(time_t)) {
- /*
- ** time_t is floating.
- */
- return time1 - time0;
+ if (sizeof(time_t) < sizeof(double)) {
+ double t1 = time1, t0 = time0;
+ return t1 - t0;
}
- if (!TYPE_SIGNED(time_t)) {
- /*
- ** time_t is integral and unsigned.
- ** The difference of two unsigned values can't overflow
- ** if the minuend is greater than or equal to the subtrahend.
- */
- if (time1 >= time0)
- return time1 - time0;
- else return -((double) (time0 - time1));
+
+ /*
+ ** The difference of two unsigned values can't overflow
+ ** if the minuend is greater than or equal to the subtrahend.
+ */
+ if (!TYPE_SIGNED(time_t))
+ return time0 <= time1 ? time1 - time0 : dminus(time0 - time1);
+
+ /* Use uintmax_t if wide enough. */
+ if (sizeof(time_t) <= sizeof(uintmax_t)) {
+ uintmax_t t1 = time1, t0 = time0;
+ return time0 <= time1 ? t1 - t0 : dminus(t0 - t1);
}
+
/*
- ** time_t is integral and signed.
** Handle cases where both time1 and time0 have the same sign
** (meaning that their difference cannot overflow).
*/
if ((time1 < 0) == (time0 < 0))
- return time1 - time0;
- /*
- ** time1 and time0 have opposite signs.
- ** Punt if unsigned long is too narrow.
- */
- if (sizeof (unsigned long) < sizeof (time_t))
- return (double) time1 - (double) time0;
+ return time1 - time0;
+
/*
- ** Stay calm...decent optimizers will eliminate the complexity below.
+ ** The values have opposite signs and uintmax_t is too narrow.
+ ** This suffers from double rounding; attempt to lessen that
+ ** by using long double temporaries.
*/
- if (time1 >= 0 /* && time0 < 0 */)
- return (unsigned long) time1 +
- (unsigned long) (-(time0 + 1)) + 1;
- return -(double) ((unsigned long) time0 +
- (unsigned long) (-(time1 + 1)) + 1);
+ {
+ long double t1 = time1, t0 = time0;
+ return t1 - t0;
+ }
}
diff --git a/ialloc.c b/ialloc.c
deleted file mode 100644
index 1fc2035f4529..000000000000
--- a/ialloc.c
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
-** This file is in the public domain, so clarified as of
-** 2006-07-17 by Arthur David Olson.
-*/
-
-#ifndef lint
-#ifndef NOID
-static char elsieid[] = "@(#)ialloc.c 8.30";
-#endif /* !defined NOID */
-#endif /* !defined lint */
-
-/*LINTLIBRARY*/
-
-#include "private.h"
-
-#define nonzero(n) (((n) == 0) ? 1 : (n))
-
-char *
-imalloc(n)
-const int n;
-{
- return malloc((size_t) nonzero(n));
-}
-
-char *
-icalloc(nelem, elsize)
-int nelem;
-int elsize;
-{
- if (nelem == 0 || elsize == 0)
- nelem = elsize = 1;
- return calloc((size_t) nelem, (size_t) elsize);
-}
-
-void *
-irealloc(pointer, size)
-void * const pointer;
-const int size;
-{
- if (pointer == NULL)
- return imalloc(size);
- return realloc((void *) pointer, (size_t) nonzero(size));
-}
-
-char *
-icatalloc(old, new)
-char * const old;
-const char * const new;
-{
- register char * result;
- register int oldsize, newsize;
-
- newsize = (new == NULL) ? 0 : strlen(new);
- if (old == NULL)
- oldsize = 0;
- else if (newsize == 0)
- return old;
- else oldsize = strlen(old);
- if ((result = irealloc(old, oldsize + newsize + 1)) != NULL)
- if (new != NULL)
- (void) strcpy(result + oldsize, new);
- return result;
-}
-
-char *
-icpyalloc(string)
-const char * const string;
-{
- return icatalloc((char *) NULL, string);
-}
-
-void
-ifree(p)
-char * const p;
-{
- if (p != NULL)
- (void) free(p);
-}
-
-void
-icfree(p)
-char * const p;
-{
- if (p != NULL)
- (void) free(p);
-}
diff --git a/itca.jpg b/itca.jpg
deleted file mode 100644
index 89a7119c0ccc..000000000000
--- a/itca.jpg
+++ /dev/null
Binary files differ
diff --git a/localtime.c b/localtime.c
index 13c11aa928df..073b09669648 100644
--- a/localtime.c
+++ b/localtime.c
@@ -1,14 +1,10 @@
+/* Convert timestamp from time_t to struct tm. */
+
/*
** This file is in the public domain, so clarified as of
** 1996-06-05 by Arthur David Olson.
*/
-#ifndef lint
-#ifndef NOID
-static char elsieid[] = "@(#)localtime.c 8.15";
-#endif /* !defined NOID */
-#endif /* !defined lint */
-
/*
** Leap second handling from Bradley White.
** POSIX-style TZ environment variable handling from Guy Harris.
@@ -16,34 +12,42 @@ static char elsieid[] = "@(#)localtime.c 8.15";
/*LINTLIBRARY*/
+#define LOCALTIME_IMPLEMENTATION
#include "private.h"
+
#include "tzfile.h"
-#include "fcntl.h"
-#include "float.h" /* for FLT_MAX and DBL_MAX */
+#include <fcntl.h>
+
+#if defined THREAD_SAFE && THREAD_SAFE
+# include <pthread.h>
+static pthread_mutex_t locallock = PTHREAD_MUTEX_INITIALIZER;
+static int lock(void) { return pthread_mutex_lock(&locallock); }
+static void unlock(void) { pthread_mutex_unlock(&locallock); }
+#else
+static int lock(void) { return 0; }
+static void unlock(void) { }
+#endif
#ifndef TZ_ABBR_MAX_LEN
-#define TZ_ABBR_MAX_LEN 16
+# define TZ_ABBR_MAX_LEN 16
#endif /* !defined TZ_ABBR_MAX_LEN */
#ifndef TZ_ABBR_CHAR_SET
-#define TZ_ABBR_CHAR_SET \
+# define TZ_ABBR_CHAR_SET \
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"
#endif /* !defined TZ_ABBR_CHAR_SET */
#ifndef TZ_ABBR_ERR_CHAR
-#define TZ_ABBR_ERR_CHAR '_'
+# define TZ_ABBR_ERR_CHAR '_'
#endif /* !defined TZ_ABBR_ERR_CHAR */
/*
-** SunOS 4.1.1 headers lack O_BINARY.
+** Support non-POSIX platforms that distinguish between text and binary files.
*/
-#ifdef O_BINARY
-#define OPEN_MODE (O_RDONLY | O_BINARY)
-#endif /* defined O_BINARY */
#ifndef O_BINARY
-#define OPEN_MODE O_RDONLY
-#endif /* !defined O_BINARY */
+# define O_BINARY 0
+#endif
#ifndef WILDABBR
/*
@@ -65,44 +69,51 @@ static char elsieid[] = "@(#)localtime.c 8.15";
** manual page of what this "time zone abbreviation" means (doing this so
** that tzname[0] has the "normal" length of three characters).
*/
-#define WILDABBR " "
+# define WILDABBR " "
#endif /* !defined WILDABBR */
-static char wildabbr[] = WILDABBR;
+static const char wildabbr[] = WILDABBR;
-static const char gmt[] = "GMT";
+static char const etc_utc[] = "Etc/UTC";
+static char const *utc = etc_utc + sizeof "Etc/" - 1;
/*
** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
-** We default to US rules as of 1999-08-17.
-** POSIX 1003.1 section 8.1.1 says that the default DST rules are
-** implementation dependent; for historical reasons, US rules are a
-** common default.
+** Default to US rules as of 2017-05-07.
+** POSIX does not specify the default DST rules;
+** for historical reasons, US rules are a common default.
*/
#ifndef TZDEFRULESTRING
-#define TZDEFRULESTRING ",M4.1.0,M10.5.0"
-#endif /* !defined TZDEFDST */
+# define TZDEFRULESTRING ",M3.2.0,M11.1.0"
+#endif
struct ttinfo { /* time type information */
- long tt_gmtoff; /* UTC offset in seconds */
- int tt_isdst; /* used to set tm_isdst */
- int tt_abbrind; /* abbreviation list index */
- int tt_ttisstd; /* TRUE if transition is std time */
- int tt_ttisgmt; /* TRUE if transition is UTC */
+ int_fast32_t tt_utoff; /* UT offset in seconds */
+ bool tt_isdst; /* used to set tm_isdst */
+ int tt_desigidx; /* abbreviation list index */
+ bool tt_ttisstd; /* transition is std time */
+ bool tt_ttisut; /* transition is UT */
};
struct lsinfo { /* leap second information */
time_t ls_trans; /* transition time */
- long ls_corr; /* correction to apply */
+ int_fast32_t ls_corr; /* correction to apply */
};
-#define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
+/* This abbreviation means local time is unspecified. */
+static char const UNSPEC[] = "-00";
+
+/* How many extra bytes are needed at the end of struct state's chars array.
+ This needs to be at least 1 for null termination in case the input
+ data isn't properly terminated, and it also needs to be big enough
+ for ttunspecified to work without crashing. */
+enum { CHARS_EXTRA = max(sizeof UNSPEC, 2) - 1 };
#ifdef TZNAME_MAX
-#define MY_TZNAME_MAX TZNAME_MAX
+# define MY_TZNAME_MAX TZNAME_MAX
#endif /* defined TZNAME_MAX */
#ifndef TZNAME_MAX
-#define MY_TZNAME_MAX 255
+# define MY_TZNAME_MAX 255
#endif /* !defined TZNAME_MAX */
struct state {
@@ -110,78 +121,45 @@ struct state {
int timecnt;
int typecnt;
int charcnt;
- int goback;
- int goahead;
+ bool goback;
+ bool goahead;
time_t ats[TZ_MAX_TIMES];
unsigned char types[TZ_MAX_TIMES];
struct ttinfo ttis[TZ_MAX_TYPES];
- char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt),
- (2 * (MY_TZNAME_MAX + 1)))];
+ char chars[max(max(TZ_MAX_CHARS + CHARS_EXTRA, sizeof "UTC"),
+ 2 * (MY_TZNAME_MAX + 1))];
struct lsinfo lsis[TZ_MAX_LEAPS];
+
+ /* The time type to use for early times or if no transitions.
+ It is always zero for recent tzdb releases.
+ It might be nonzero for data from tzdb 2018e or earlier. */
+ int defaulttype;
+};
+
+enum r_type {
+ JULIAN_DAY, /* Jn = Julian day */
+ DAY_OF_YEAR, /* n = day of year */
+ MONTH_NTH_DAY_OF_WEEK /* Mm.n.d = month, week, day of week */
};
struct rule {
- int r_type; /* type of rule--see below */
+ enum r_type r_type; /* type of rule */
int r_day; /* day number of rule */
int r_week; /* week number of rule */
int r_mon; /* month number of rule */
- long r_time; /* transition time of rule */
+ int_fast32_t r_time; /* transition time of rule */
};
-#define JULIAN_DAY 0 /* Jn - Julian day */
-#define DAY_OF_YEAR 1 /* n - day of year */
-#define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */
-
-/*
-** Prototypes for static functions.
-*/
-
-static long detzcode(const char * codep);
-static time_t detzcode64(const char * codep);
-static int differ_by_repeat(time_t t1, time_t t0);
-static const char * getzname(const char * strp);
-static const char * getqzname(const char * strp, const int delim);
-static const char * getnum(const char * strp, int * nump, int min,
- int max);
-static const char * getsecs(const char * strp, long * secsp);
-static const char * getoffset(const char * strp, long * offsetp);
-static const char * getrule(const char * strp, struct rule * rulep);
-static void gmtload(struct state * sp);
-static struct tm * gmtsub(const time_t * timep, long offset,
- struct tm * tmp);
-static struct tm * localsub(const time_t * timep, long offset,
- struct tm * tmp);
-static int increment_overflow(int * number, int delta);
-static int leaps_thru_end_of(int y);
-static int long_increment_overflow(long * number, int delta);
-static int long_normalize_overflow(long * tensptr,
- int * unitsptr, int base);
-static int normalize_overflow(int * tensptr, int * unitsptr,
- int base);
-static void settzname(void);
-static time_t time1(struct tm * tmp,
- struct tm * (*funcp)(const time_t *,
- long, struct tm *),
- long offset);
-static time_t time2(struct tm *tmp,
- struct tm * (*funcp)(const time_t *,
- long, struct tm*),
- long offset, int * okayp);
-static time_t time2sub(struct tm *tmp,
- struct tm * (*funcp)(const time_t *,
- long, struct tm*),
- long offset, int * okayp, int do_norm_secs);
-static struct tm * timesub(const time_t * timep, long offset,
- const struct state * sp, struct tm * tmp);
-static int tmcomp(const struct tm * atmp,
- const struct tm * btmp);
-static time_t transtime(time_t janfirst, int year,
- const struct rule * rulep, long offset);
-static int typesequiv(const struct state * sp, int a, int b);
-static int tzload(const char * name, struct state * sp,
- int doextend);
-static int tzparse(const char * name, struct state * sp,
- int lastditch);
+static struct tm *gmtsub(struct state const *, time_t const *, int_fast32_t,
+ struct tm *);
+static bool increment_overflow(int *, int);
+static bool increment_overflow_time(time_t *, int_fast32_t);
+static int_fast32_t leapcorr(struct state const *, time_t);
+static bool normalize_overflow32(int_fast32_t *, int *, int);
+static struct tm *timesub(time_t const *, int_fast32_t, struct state const *,
+ struct tm *);
+static bool typesequiv(struct state const *, int, int);
+static bool tzparse(char const *, struct state *, struct state *);
#ifdef ALL_STATE
static struct state * lclptr;
@@ -191,22 +169,16 @@ static struct state * gmtptr;
#ifndef ALL_STATE
static struct state lclmem;
static struct state gmtmem;
-#define lclptr (&lclmem)
-#define gmtptr (&gmtmem)
+static struct state *const lclptr = &lclmem;
+static struct state *const gmtptr = &gmtmem;
#endif /* State Farm */
#ifndef TZ_STRLEN_MAX
-#define TZ_STRLEN_MAX 255
+# define TZ_STRLEN_MAX 255
#endif /* !defined TZ_STRLEN_MAX */
static char lcl_TZname[TZ_STRLEN_MAX + 1];
static int lcl_is_set;
-static int gmt_is_set;
-
-char * tzname[2] = {
- wildabbr,
- wildabbr
-};
/*
** Section 4.12.3 of X3.159-1989 requires that
@@ -218,85 +190,161 @@ char * tzname[2] = {
static struct tm tm;
-#ifdef USG_COMPAT
-time_t timezone = 0;
-int daylight = 0;
-#endif /* defined USG_COMPAT */
-
-#ifdef ALTZONE
-time_t altzone = 0;
-#endif /* defined ALTZONE */
+#if 2 <= HAVE_TZNAME + TZ_TIME_T
+char * tzname[2] = {
+ (char *) wildabbr,
+ (char *) wildabbr
+};
+#endif
+#if 2 <= USG_COMPAT + TZ_TIME_T
+long timezone;
+int daylight;
+#endif
+#if 2 <= ALTZONE + TZ_TIME_T
+long altzone;
+#endif
+
+/* Initialize *S to a value based on UTOFF, ISDST, and DESIGIDX. */
+static void
+init_ttinfo(struct ttinfo *s, int_fast32_t utoff, bool isdst, int desigidx)
+{
+ s->tt_utoff = utoff;
+ s->tt_isdst = isdst;
+ s->tt_desigidx = desigidx;
+ s->tt_ttisstd = false;
+ s->tt_ttisut = false;
+}
-static long
-detzcode(codep)
-const char * const codep;
+/* Return true if SP's time type I does not specify local time. */
+static bool
+ttunspecified(struct state const *sp, int i)
{
- register long result;
- register int i;
+ char const *abbr = &sp->chars[sp->ttis[i].tt_desigidx];
+ /* memcmp is likely faster than strcmp, and is safe due to CHARS_EXTRA. */
+ return memcmp(abbr, UNSPEC, sizeof UNSPEC) == 0;
+}
- result = (codep[0] & 0x80) ? ~0L : 0;
- for (i = 0; i < 4; ++i)
+static int_fast32_t
+detzcode(const char *const codep)
+{
+ register int_fast32_t result;
+ register int i;
+ int_fast32_t one = 1;
+ int_fast32_t halfmaxval = one << (32 - 2);
+ int_fast32_t maxval = halfmaxval - 1 + halfmaxval;
+ int_fast32_t minval = -1 - maxval;
+
+ result = codep[0] & 0x7f;
+ for (i = 1; i < 4; ++i)
result = (result << 8) | (codep[i] & 0xff);
+
+ if (codep[0] & 0x80) {
+ /* Do two's-complement negation even on non-two's-complement machines.
+ If the result would be minval - 1, return minval. */
+ result -= !TWOS_COMPLEMENT(int_fast32_t) && result != 0;
+ result += minval;
+ }
return result;
}
-static time_t
-detzcode64(codep)
-const char * const codep;
+static int_fast64_t
+detzcode64(const char *const codep)
{
- register time_t result;
+ register int_fast64_t result;
register int i;
+ int_fast64_t one = 1;
+ int_fast64_t halfmaxval = one << (64 - 2);
+ int_fast64_t maxval = halfmaxval - 1 + halfmaxval;
+ int_fast64_t minval = -TWOS_COMPLEMENT(int_fast64_t) - maxval;
- result = (codep[0] & 0x80) ? (~(int_fast64_t) 0) : 0;
- for (i = 0; i < 8; ++i)
- result = result * 256 + (codep[i] & 0xff);
+ result = codep[0] & 0x7f;
+ for (i = 1; i < 8; ++i)
+ result = (result << 8) | (codep[i] & 0xff);
+
+ if (codep[0] & 0x80) {
+ /* Do two's-complement negation even on non-two's-complement machines.
+ If the result would be minval - 1, return minval. */
+ result -= !TWOS_COMPLEMENT(int_fast64_t) && result != 0;
+ result += minval;
+ }
return result;
}
static void
+update_tzname_etc(struct state const *sp, struct ttinfo const *ttisp)
+{
+#if HAVE_TZNAME
+ tzname[ttisp->tt_isdst] = (char *) &sp->chars[ttisp->tt_desigidx];
+#endif
+#if USG_COMPAT
+ if (!ttisp->tt_isdst)
+ timezone = - ttisp->tt_utoff;
+#endif
+#if ALTZONE
+ if (ttisp->tt_isdst)
+ altzone = - ttisp->tt_utoff;
+#endif
+}
+
+/* If STDDST_MASK indicates that SP's TYPE provides useful info,
+ update tzname, timezone, and/or altzone and return STDDST_MASK,
+ diminished by the provided info if it is a specified local time.
+ Otherwise, return STDDST_MASK. See settzname for STDDST_MASK. */
+static int
+may_update_tzname_etc(int stddst_mask, struct state *sp, int type)
+{
+ struct ttinfo *ttisp = &sp->ttis[type];
+ int this_bit = 1 << ttisp->tt_isdst;
+ if (stddst_mask & this_bit) {
+ update_tzname_etc(sp, ttisp);
+ if (!ttunspecified(sp, type))
+ return stddst_mask & ~this_bit;
+ }
+ return stddst_mask;
+}
+
+static void
settzname(void)
{
register struct state * const sp = lclptr;
register int i;
- tzname[0] = wildabbr;
- tzname[1] = wildabbr;
-#ifdef USG_COMPAT
- daylight = 0;
+ /* If STDDST_MASK & 1 we need info about a standard time.
+ If STDDST_MASK & 2 we need info about a daylight saving time.
+ When STDDST_MASK becomes zero we can stop looking. */
+ int stddst_mask = 0;
+
+#if HAVE_TZNAME
+ tzname[0] = tzname[1] = (char *) (sp ? wildabbr : utc);
+ stddst_mask = 3;
+#endif
+#if USG_COMPAT
timezone = 0;
-#endif /* defined USG_COMPAT */
-#ifdef ALTZONE
+ stddst_mask = 3;
+#endif
+#if ALTZONE
altzone = 0;
-#endif /* defined ALTZONE */
-#ifdef ALL_STATE
- if (sp == NULL) {
- tzname[0] = tzname[1] = gmt;
- return;
- }
-#endif /* defined ALL_STATE */
+ stddst_mask |= 2;
+#endif
/*
- ** And to get the latest zone names into tzname. . .
+ ** And to get the latest time zone abbreviations into tzname. . .
*/
- for (i = 0; i < sp->timecnt; ++i) {
- register const struct ttinfo * const ttisp =
- &sp->ttis[
- sp->types[i]];
-
- tzname[ttisp->tt_isdst] =
- &sp->chars[ttisp->tt_abbrind];
-#ifdef USG_COMPAT
- if (ttisp->tt_isdst)
- daylight = 1;
- if (!ttisp->tt_isdst)
- timezone = -(ttisp->tt_gmtoff);
-#endif /* defined USG_COMPAT */
-#ifdef ALTZONE
- if (ttisp->tt_isdst)
- altzone = -(ttisp->tt_gmtoff);
-#endif /* defined ALTZONE */
+ if (sp) {
+ for (i = sp->timecnt - 1; stddst_mask && 0 <= i; i--)
+ stddst_mask = may_update_tzname_etc(stddst_mask, sp, sp->types[i]);
+ for (i = sp->typecnt - 1; stddst_mask && 0 <= i; i--)
+ stddst_mask = may_update_tzname_etc(stddst_mask, sp, i);
}
+#if USG_COMPAT
+ daylight = stddst_mask >> 1 ^ 1;
+#endif
+}
+
+static void
+scrub_abbrs(struct state *sp)
+{
+ int i;
/*
- ** Finally, scrub the abbreviations.
** First, replace bogus characters.
*/
for (i = 0; i < sp->charcnt; ++i)
@@ -307,7 +355,7 @@ settzname(void)
*/
for (i = 0; i < sp->typecnt; ++i) {
register const struct ttinfo * const ttisp = &sp->ttis[i];
- register char * cp = &sp->chars[ttisp->tt_abbrind];
+ char *cp = &sp->chars[ttisp->tt_desigidx];
if (strlen(cp) > TZ_ABBR_MAX_LEN &&
strcmp(cp, GRANDPARENTED) != 0)
@@ -315,281 +363,454 @@ settzname(void)
}
}
-static int
-differ_by_repeat(t1, t0)
-const time_t t1;
-const time_t t0;
-{
- if (TYPE_INTEGRAL(time_t) &&
- TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
- return 0;
- return t1 - t0 == SECSPERREPEAT;
-}
+/* Input buffer for data read from a compiled tz file. */
+union input_buffer {
+ /* The first part of the buffer, interpreted as a header. */
+ struct tzhead tzhead;
+
+ /* The entire buffer. */
+ char buf[2 * sizeof(struct tzhead) + 2 * sizeof(struct state)
+ + 4 * TZ_MAX_TIMES];
+};
+
+/* TZDIR with a trailing '/' rather than a trailing '\0'. */
+static char const tzdirslash[sizeof TZDIR] = TZDIR "/";
+
+/* Local storage needed for 'tzloadbody'. */
+union local_storage {
+ /* The results of analyzing the file's contents after it is opened. */
+ struct file_analysis {
+ /* The input buffer. */
+ union input_buffer u;
+ /* A temporary state used for parsing a TZ string in the file. */
+ struct state st;
+ } u;
+
+ /* The file name to be opened. */
+ char fullname[max(sizeof(struct file_analysis), sizeof tzdirslash + 1024)];
+};
+
+/* Load tz data from the file named NAME into *SP. Read extended
+ format if DOEXTEND. Use *LSP for temporary storage. Return 0 on
+ success, an errno value on failure. */
static int
-tzload(name, sp, doextend)
-register const char * name;
-register struct state * const sp;
-register const int doextend;
+tzloadbody(char const *name, struct state *sp, bool doextend,
+ union local_storage *lsp)
{
- register const char * p;
register int i;
register int fid;
register int stored;
- register int nread;
- union {
- struct tzhead tzhead;
- char buf[2 * sizeof(struct tzhead) +
- 2 * sizeof *sp +
- 4 * TZ_MAX_TIMES];
- } u;
-
- sp->goback = sp->goahead = FALSE;
- if (name == NULL && (name = TZDEFAULT) == NULL)
- return -1;
- {
- register int doaccess;
- /*
- ** Section 4.9.1 of the C standard says that
- ** "FILENAME_MAX expands to an integral constant expression
- ** that is the size needed for an array of char large enough
- ** to hold the longest file name string that the implementation
- ** guarantees can be opened."
- */
- char fullname[FILENAME_MAX + 1];
+ register ssize_t nread;
+ register bool doaccess;
+ register union input_buffer *up = &lsp->u.u;
+ register int tzheadsize = sizeof(struct tzhead);
- if (name[0] == ':')
- ++name;
- doaccess = name[0] == '/';
- if (!doaccess) {
- if ((p = TZDIR) == NULL)
- return -1;
- if ((strlen(p) + strlen(name) + 1) >= sizeof fullname)
- return -1;
- (void) strcpy(fullname, p);
- (void) strcat(fullname, "/");
- (void) strcat(fullname, name);
- /*
- ** Set doaccess if '.' (as in "../") shows up in name.
- */
- if (strchr(name, '.') != NULL)
- doaccess = TRUE;
- name = fullname;
- }
- if (doaccess && access(name, R_OK) != 0)
- return -1;
- if ((fid = open(name, OPEN_MODE)) == -1)
- return -1;
+ sp->goback = sp->goahead = false;
+
+ if (! name) {
+ name = TZDEFAULT;
+ if (! name)
+ return EINVAL;
}
- nread = read(fid, u.buf, sizeof u.buf);
- if (close(fid) < 0 || nread <= 0)
- return -1;
+
+ if (name[0] == ':')
+ ++name;
+#ifdef SUPPRESS_TZDIR
+ /* Do not prepend TZDIR. This is intended for specialized
+ applications only, due to its security implications. */
+ doaccess = true;
+#else
+ doaccess = name[0] == '/';
+#endif
+ if (!doaccess) {
+ char const *dot;
+ size_t namelen = strlen(name);
+ if (sizeof lsp->fullname - sizeof tzdirslash <= namelen)
+ return ENAMETOOLONG;
+
+ /* Create a string "TZDIR/NAME". Using sprintf here
+ would pull in stdio (and would fail if the
+ resulting string length exceeded INT_MAX!). */
+ memcpy(lsp->fullname, tzdirslash, sizeof tzdirslash);
+ strcpy(lsp->fullname + sizeof tzdirslash, name);
+
+ /* Set doaccess if NAME contains a ".." file name
+ component, as such a name could read a file outside
+ the TZDIR virtual subtree. */
+ for (dot = name; (dot = strchr(dot, '.')); dot++)
+ if ((dot == name || dot[-1] == '/') && dot[1] == '.'
+ && (dot[2] == '/' || !dot[2])) {
+ doaccess = true;
+ break;
+ }
+
+ name = lsp->fullname;
+ }
+ if (doaccess && access(name, R_OK) != 0)
+ return errno;
+ fid = open(name, O_RDONLY | O_BINARY);
+ if (fid < 0)
+ return errno;
+
+ nread = read(fid, up->buf, sizeof up->buf);
+ if (nread < tzheadsize) {
+ int err = nread < 0 ? errno : EINVAL;
+ close(fid);
+ return err;
+ }
+ if (close(fid) < 0)
+ return errno;
for (stored = 4; stored <= 8; stored *= 2) {
- int ttisstdcnt;
- int ttisgmtcnt;
-
- ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt);
- ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt);
- sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt);
- sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt);
- sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt);
- sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt);
- p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt;
- if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
- sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
- sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
- sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
- (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
- (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
- return -1;
- if (nread - (p - u.buf) <
- sp->timecnt * stored + /* ats */
- sp->timecnt + /* types */
- sp->typecnt * 6 + /* ttinfos */
- sp->charcnt + /* chars */
- sp->leapcnt * (stored + 4) + /* lsinfos */
- ttisstdcnt + /* ttisstds */
- ttisgmtcnt) /* ttisgmts */
- return -1;
+ char version = up->tzhead.tzh_version[0];
+ bool skip_datablock = stored == 4 && version;
+ int_fast32_t datablock_size;
+ int_fast32_t ttisstdcnt = detzcode(up->tzhead.tzh_ttisstdcnt);
+ int_fast32_t ttisutcnt = detzcode(up->tzhead.tzh_ttisutcnt);
+ int_fast64_t prevtr = -1;
+ int_fast32_t prevcorr;
+ int_fast32_t leapcnt = detzcode(up->tzhead.tzh_leapcnt);
+ int_fast32_t timecnt = detzcode(up->tzhead.tzh_timecnt);
+ int_fast32_t typecnt = detzcode(up->tzhead.tzh_typecnt);
+ int_fast32_t charcnt = detzcode(up->tzhead.tzh_charcnt);
+ char const *p = up->buf + tzheadsize;
+ /* Although tzfile(5) currently requires typecnt to be nonzero,
+ support future formats that may allow zero typecnt
+ in files that have a TZ string and no transitions. */
+ if (! (0 <= leapcnt && leapcnt < TZ_MAX_LEAPS
+ && 0 <= typecnt && typecnt < TZ_MAX_TYPES
+ && 0 <= timecnt && timecnt < TZ_MAX_TIMES
+ && 0 <= charcnt && charcnt < TZ_MAX_CHARS
+ && 0 <= ttisstdcnt && ttisstdcnt < TZ_MAX_TYPES
+ && 0 <= ttisutcnt && ttisutcnt < TZ_MAX_TYPES))
+ return EINVAL;
+ datablock_size
+ = (timecnt * stored /* ats */
+ + timecnt /* types */
+ + typecnt * 6 /* ttinfos */
+ + charcnt /* chars */
+ + leapcnt * (stored + 4) /* lsinfos */
+ + ttisstdcnt /* ttisstds */
+ + ttisutcnt); /* ttisuts */
+ if (nread < tzheadsize + datablock_size)
+ return EINVAL;
+ if (skip_datablock)
+ p += datablock_size;
+ else {
+ if (! ((ttisstdcnt == typecnt || ttisstdcnt == 0)
+ && (ttisutcnt == typecnt || ttisutcnt == 0)))
+ return EINVAL;
+
+ sp->leapcnt = leapcnt;
+ sp->timecnt = timecnt;
+ sp->typecnt = typecnt;
+ sp->charcnt = charcnt;
+
+ /* Read transitions, discarding those out of time_t range.
+ But pretend the last transition before TIME_T_MIN
+ occurred at TIME_T_MIN. */
+ timecnt = 0;
for (i = 0; i < sp->timecnt; ++i) {
- sp->ats[i] = (stored == 4) ?
- detzcode(p) : detzcode64(p);
+ int_fast64_t at
+ = stored == 4 ? detzcode(p) : detzcode64(p);
+ sp->types[i] = at <= TIME_T_MAX;
+ if (sp->types[i]) {
+ time_t attime
+ = ((TYPE_SIGNED(time_t) ? at < TIME_T_MIN : at < 0)
+ ? TIME_T_MIN : at);
+ if (timecnt && attime <= sp->ats[timecnt - 1]) {
+ if (attime < sp->ats[timecnt - 1])
+ return EINVAL;
+ sp->types[i - 1] = 0;
+ timecnt--;
+ }
+ sp->ats[timecnt++] = attime;
+ }
p += stored;
}
+
+ timecnt = 0;
for (i = 0; i < sp->timecnt; ++i) {
- sp->types[i] = (unsigned char) *p++;
- if (sp->types[i] >= sp->typecnt)
- return -1;
+ unsigned char typ = *p++;
+ if (sp->typecnt <= typ)
+ return EINVAL;
+ if (sp->types[i])
+ sp->types[timecnt++] = typ;
}
+ sp->timecnt = timecnt;
for (i = 0; i < sp->typecnt; ++i) {
register struct ttinfo * ttisp;
+ unsigned char isdst, desigidx;
ttisp = &sp->ttis[i];
- ttisp->tt_gmtoff = detzcode(p);
+ ttisp->tt_utoff = detzcode(p);
p += 4;
- ttisp->tt_isdst = (unsigned char) *p++;
- if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
- return -1;
- ttisp->tt_abbrind = (unsigned char) *p++;
- if (ttisp->tt_abbrind < 0 ||
- ttisp->tt_abbrind > sp->charcnt)
- return -1;
+ isdst = *p++;
+ if (! (isdst < 2))
+ return EINVAL;
+ ttisp->tt_isdst = isdst;
+ desigidx = *p++;
+ if (! (desigidx < sp->charcnt))
+ return EINVAL;
+ ttisp->tt_desigidx = desigidx;
}
for (i = 0; i < sp->charcnt; ++i)
sp->chars[i] = *p++;
- sp->chars[i] = '\0'; /* ensure '\0' at end */
- for (i = 0; i < sp->leapcnt; ++i) {
- register struct lsinfo * lsisp;
+ /* Ensure '\0'-terminated, and make it safe to call
+ ttunspecified later. */
+ memset(&sp->chars[i], 0, CHARS_EXTRA);
- lsisp = &sp->lsis[i];
- lsisp->ls_trans = (stored == 4) ?
- detzcode(p) : detzcode64(p);
- p += stored;
- lsisp->ls_corr = detzcode(p);
- p += 4;
+ /* Read leap seconds, discarding those out of time_t range. */
+ leapcnt = 0;
+ for (i = 0; i < sp->leapcnt; ++i) {
+ int_fast64_t tr = stored == 4 ? detzcode(p) : detzcode64(p);
+ int_fast32_t corr = detzcode(p + stored);
+ p += stored + 4;
+
+ /* Leap seconds cannot occur before the Epoch,
+ or out of order. */
+ if (tr <= prevtr)
+ return EINVAL;
+
+ /* To avoid other botches in this code, each leap second's
+ correction must differ from the previous one's by 1
+ second or less, except that the first correction can be
+ any value; these requirements are more generous than
+ RFC 8536, to allow future RFC extensions. */
+ if (! (i == 0
+ || (prevcorr < corr
+ ? corr == prevcorr + 1
+ : (corr == prevcorr
+ || corr == prevcorr - 1))))
+ return EINVAL;
+ prevtr = tr;
+ prevcorr = corr;
+
+ if (tr <= TIME_T_MAX) {
+ sp->lsis[leapcnt].ls_trans = tr;
+ sp->lsis[leapcnt].ls_corr = corr;
+ leapcnt++;
+ }
}
+ sp->leapcnt = leapcnt;
+
for (i = 0; i < sp->typecnt; ++i) {
register struct ttinfo * ttisp;
ttisp = &sp->ttis[i];
if (ttisstdcnt == 0)
- ttisp->tt_ttisstd = FALSE;
+ ttisp->tt_ttisstd = false;
else {
+ if (*p != true && *p != false)
+ return EINVAL;
ttisp->tt_ttisstd = *p++;
- if (ttisp->tt_ttisstd != TRUE &&
- ttisp->tt_ttisstd != FALSE)
- return -1;
}
}
for (i = 0; i < sp->typecnt; ++i) {
register struct ttinfo * ttisp;
ttisp = &sp->ttis[i];
- if (ttisgmtcnt == 0)
- ttisp->tt_ttisgmt = FALSE;
+ if (ttisutcnt == 0)
+ ttisp->tt_ttisut = false;
else {
- ttisp->tt_ttisgmt = *p++;
- if (ttisp->tt_ttisgmt != TRUE &&
- ttisp->tt_ttisgmt != FALSE)
- return -1;
+ if (*p != true && *p != false)
+ return EINVAL;
+ ttisp->tt_ttisut = *p++;
}
}
- /*
- ** Out-of-sort ats should mean we're running on a
- ** signed time_t system but using a data file with
- ** unsigned values (or vice versa).
- */
- for (i = 0; i < sp->timecnt - 2; ++i)
- if (sp->ats[i] > sp->ats[i + 1]) {
- ++i;
- if (TYPE_SIGNED(time_t)) {
- /*
- ** Ignore the end (easy).
- */
- sp->timecnt = i;
- } else {
- /*
- ** Ignore the beginning (harder).
- */
- register int j;
+ }
- for (j = 0; j + i < sp->timecnt; ++j) {
- sp->ats[j] = sp->ats[j + i];
- sp->types[j] = sp->types[j + i];
- }
- sp->timecnt = j;
- }
- break;
- }
- /*
- ** If this is an old file, we're done.
- */
- if (u.tzhead.tzh_version[0] == '\0')
- break;
- nread -= p - u.buf;
- for (i = 0; i < nread; ++i)
- u.buf[i] = p[i];
- /*
- ** If this is a narrow integer time_t system, we're done.
- */
- if (stored >= (int) sizeof(time_t) && TYPE_INTEGRAL(time_t))
- break;
+ nread -= p - up->buf;
+ memmove(up->buf, p, nread);
+
+ /* If this is an old file, we're done. */
+ if (!version)
+ break;
}
if (doextend && nread > 2 &&
- u.buf[0] == '\n' && u.buf[nread - 1] == '\n' &&
+ up->buf[0] == '\n' && up->buf[nread - 1] == '\n' &&
sp->typecnt + 2 <= TZ_MAX_TYPES) {
- struct state ts;
- register int result;
-
- u.buf[nread - 1] = '\0';
- result = tzparse(&u.buf[1], &ts, FALSE);
- if (result == 0 && ts.typecnt == 2 &&
- sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) {
- for (i = 0; i < 2; ++i)
- ts.ttis[i].tt_abbrind +=
- sp->charcnt;
- for (i = 0; i < ts.charcnt; ++i)
- sp->chars[sp->charcnt++] =
- ts.chars[i];
- i = 0;
- while (i < ts.timecnt &&
- ts.ats[i] <=
- sp->ats[sp->timecnt - 1])
- ++i;
- while (i < ts.timecnt &&
- sp->timecnt < TZ_MAX_TIMES) {
- sp->ats[sp->timecnt] =
- ts.ats[i];
- sp->types[sp->timecnt] =
- sp->typecnt +
- ts.types[i];
- ++sp->timecnt;
- ++i;
- }
- sp->ttis[sp->typecnt++] = ts.ttis[0];
- sp->ttis[sp->typecnt++] = ts.ttis[1];
+ struct state *ts = &lsp->u.st;
+
+ up->buf[nread - 1] = '\0';
+ if (tzparse(&up->buf[1], ts, sp)) {
+
+ /* Attempt to reuse existing abbreviations.
+ Without this, America/Anchorage would be right on
+ the edge after 2037 when TZ_MAX_CHARS is 50, as
+ sp->charcnt equals 40 (for LMT AST AWT APT AHST
+ 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;
+ int j;
+ 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 = strlen(tsabbr);
+ if (j + tsabbrlen < TZ_MAX_CHARS) {
+ strcpy(sp->chars + j, tsabbr);
+ charcnt = j + tsabbrlen + 1;
+ ts->ttis[i].tt_desigidx = j;
+ gotabbr++;
+ }
+ }
+ }
+ if (gotabbr == ts->typecnt) {
+ sp->charcnt = charcnt;
+
+ /* Ignore any trailing, no-op transitions generated
+ by zic as they don't help here and can run afoul
+ of bugs in zic 2016j or earlier. */
+ while (1 < sp->timecnt
+ && (sp->types[sp->timecnt - 1]
+ == sp->types[sp->timecnt - 2]))
+ sp->timecnt--;
+
+ for (i = 0;
+ i < ts->timecnt && sp->timecnt < TZ_MAX_TIMES;
+ i++) {
+ time_t t = ts->ats[i];
+ if (increment_overflow_time(&t, leapcorr(sp, t))
+ || (0 < sp->timecnt
+ && t <= sp->ats[sp->timecnt - 1]))
+ continue;
+ sp->ats[sp->timecnt] = t;
+ sp->types[sp->timecnt] = (sp->typecnt
+ + ts->types[i]);
+ sp->timecnt++;
+ }
+ for (i = 0; i < ts->typecnt; i++)
+ sp->ttis[sp->typecnt++] = ts->ttis[i];
+ }
}
}
+ if (sp->typecnt == 0)
+ return EINVAL;
if (sp->timecnt > 1) {
+ if (sp->ats[0] <= TIME_T_MAX - SECSPERREPEAT) {
+ time_t repeatat = sp->ats[0] + SECSPERREPEAT;
+ int repeattype = sp->types[0];
for (i = 1; i < sp->timecnt; ++i)
- if (typesequiv(sp, sp->types[i], sp->types[0]) &&
- differ_by_repeat(sp->ats[i], sp->ats[0])) {
- sp->goback = TRUE;
+ if (sp->ats[i] == repeatat
+ && typesequiv(sp, sp->types[i], repeattype)) {
+ sp->goback = true;
break;
- }
+ }
+ }
+ if (TIME_T_MIN + SECSPERREPEAT <= sp->ats[sp->timecnt - 1]) {
+ time_t repeatat = sp->ats[sp->timecnt - 1] - SECSPERREPEAT;
+ int repeattype = sp->types[sp->timecnt - 1];
for (i = sp->timecnt - 2; i >= 0; --i)
- if (typesequiv(sp, sp->types[sp->timecnt - 1],
- sp->types[i]) &&
- differ_by_repeat(sp->ats[sp->timecnt - 1],
- sp->ats[i])) {
- sp->goahead = TRUE;
+ if (sp->ats[i] == repeatat
+ && typesequiv(sp, sp->types[i], repeattype)) {
+ sp->goahead = true;
break;
- }
+ }
+ }
+ }
+
+ /* Infer sp->defaulttype from the data. Although this default
+ type is always zero for data from recent tzdb releases,
+ things are trickier for data from tzdb 2018e or earlier.
+
+ The first set of heuristics work around bugs in 32-bit data
+ generated by tzdb 2013c or earlier. The workaround is for
+ zones like Australia/Macquarie where timestamps before the
+ first transition have a time type that is not the earliest
+ standard-time type. See:
+ https://mm.icann.org/pipermail/tz/2013-May/019368.html */
+ /*
+ ** If type 0 does not specify local time, or is unused in transitions,
+ ** it's the type to use for early times.
+ */
+ for (i = 0; i < sp->timecnt; ++i)
+ if (sp->types[i] == 0)
+ break;
+ i = i < sp->timecnt && ! ttunspecified(sp, 0) ? -1 : 0;
+ /*
+ ** Absent the above,
+ ** if there are transition times
+ ** and the first transition is to a daylight time
+ ** find the standard type less than and closest to
+ ** the type of the first transition.
+ */
+ if (i < 0 && sp->timecnt > 0 && sp->ttis[sp->types[0]].tt_isdst) {
+ i = sp->types[0];
+ while (--i >= 0)
+ if (!sp->ttis[i].tt_isdst)
+ break;
}
+ /* The next heuristics are for data generated by tzdb 2018e or
+ earlier, for zones like EST5EDT where the first transition
+ is to DST. */
+ /*
+ ** If no result yet, find the first standard type.
+ ** If there is none, punt to type zero.
+ */
+ if (i < 0) {
+ i = 0;
+ while (sp->ttis[i].tt_isdst)
+ if (++i >= sp->typecnt) {
+ i = 0;
+ break;
+ }
+ }
+ /* A simple 'sp->defaulttype = 0;' would suffice here if we
+ didn't have to worry about 2018e-or-earlier data. Even
+ simpler would be to remove the defaulttype member and just
+ use 0 in its place. */
+ sp->defaulttype = i;
+
return 0;
}
+/* Load tz data from the file named NAME into *SP. Read extended
+ format if DOEXTEND. Return 0 on success, an errno value on failure. */
static int
-typesequiv(sp, a, b)
-const struct state * const sp;
-const int a;
-const int b;
+tzload(char const *name, struct state *sp, bool doextend)
{
- register int result;
+#ifdef ALL_STATE
+ union local_storage *lsp = malloc(sizeof *lsp);
+ if (!lsp) {
+ return HAVE_MALLOC_ERRNO ? errno : ENOMEM;
+ } else {
+ int err = tzloadbody(name, sp, doextend, lsp);
+ free(lsp);
+ return err;
+ }
+#else
+ union local_storage ls;
+ return tzloadbody(name, sp, doextend, &ls);
+#endif
+}
+
+static bool
+typesequiv(const struct state *sp, int a, int b)
+{
+ register bool result;
if (sp == NULL ||
a < 0 || a >= sp->typecnt ||
b < 0 || b >= sp->typecnt)
- result = FALSE;
+ result = false;
else {
register const struct ttinfo * ap = &sp->ttis[a];
register const struct ttinfo * bp = &sp->ttis[b];
- result = ap->tt_gmtoff == bp->tt_gmtoff &&
- ap->tt_isdst == bp->tt_isdst &&
- ap->tt_ttisstd == bp->tt_ttisstd &&
- ap->tt_ttisgmt == bp->tt_ttisgmt &&
- strcmp(&sp->chars[ap->tt_abbrind],
- &sp->chars[bp->tt_abbrind]) == 0;
+ result = (ap->tt_utoff == bp->tt_utoff
+ && ap->tt_isdst == bp->tt_isdst
+ && ap->tt_ttisstd == bp->tt_ttisstd
+ && ap->tt_ttisut == bp->tt_ttisut
+ && (strcmp(&sp->chars[ap->tt_desigidx],
+ &sp->chars[bp->tt_desigidx])
+ == 0));
}
return result;
}
@@ -603,15 +824,21 @@ static const int year_lengths[2] = {
DAYSPERNYEAR, DAYSPERLYEAR
};
+/* Is C an ASCII digit? */
+static bool
+is_digit(char c)
+{
+ return '0' <= c && c <= '9';
+}
+
/*
-** Given a pointer into a time zone string, scan until a character that is not
-** a valid character in a zone name is found. Return a pointer to that
-** character.
+** Given a pointer into a timezone string, scan until a character that is not
+** a valid character in a time zone abbreviation is found.
+** Return a pointer to that character.
*/
-static const char *
-getzname(strp)
-register const char * strp;
+static ATTRIBUTE_PURE const char *
+getzname(register const char *strp)
{
register char c;
@@ -622,15 +849,16 @@ register const char * strp;
}
/*
-** Given a pointer into an extended time zone string, scan until the ending
-** delimiter of the zone name is located. Return a pointer to the delimiter.
+** Given a pointer into an extended timezone string, scan until the ending
+** delimiter of the time zone abbreviation is located.
+** Return a pointer to the delimiter.
**
** As with getzname above, the legal character set is actually quite
** restricted, with other characters producing undefined results.
** We don't do any checking here; checking is done later in common-case code.
*/
-static const char *
+static ATTRIBUTE_PURE const char *
getqzname(register const char *strp, const int delim)
{
register int c;
@@ -641,18 +869,14 @@ getqzname(register const char *strp, const int delim)
}
/*
-** Given a pointer into a time zone string, extract a number from that string.
+** Given a pointer into a timezone string, extract a number from that string.
** Check that the number is within a specified range; if it is not, return
** NULL.
** Otherwise, return a pointer to the first character not part of the number.
*/
static const char *
-getnum(strp, nump, min, max)
-register const char * strp;
-int * const nump;
-const int min;
-const int max;
+getnum(register const char *strp, int *const nump, const int min, const int max)
{
register char c;
register int num;
@@ -673,7 +897,7 @@ const int max;
}
/*
-** Given a pointer into a time zone string, extract a number of seconds,
+** Given a pointer into a timezone string, extract a number of seconds,
** in hh[:mm[:ss]] form, from the string.
** If any error occurs, return NULL.
** Otherwise, return a pointer to the first character not part of the number
@@ -681,22 +905,21 @@ const int max;
*/
static const char *
-getsecs(strp, secsp)
-register const char * strp;
-long * const secsp;
+getsecs(register const char *strp, int_fast32_t *const secsp)
{
int num;
+ int_fast32_t secsperhour = SECSPERHOUR;
/*
- ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
+ ** 'HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
** "M10.4.6/26", which does not conform to Posix,
** but which specifies the equivalent of
- ** ``02:00 on the first Sunday on or after 23 Oct''.
+ ** "02:00 on the first Sunday on or after 23 Oct".
*/
strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
if (strp == NULL)
return NULL;
- *secsp = num * (long) SECSPERHOUR;
+ *secsp = num * secsperhour;
if (*strp == ':') {
++strp;
strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
@@ -705,7 +928,7 @@ long * const secsp;
*secsp += num * SECSPERMIN;
if (*strp == ':') {
++strp;
- /* `SECSPERMIN' allows for leap seconds. */
+ /* 'SECSPERMIN' allows for leap seconds. */
strp = getnum(strp, &num, 0, SECSPERMIN);
if (strp == NULL)
return NULL;
@@ -716,21 +939,19 @@ long * const secsp;
}
/*
-** Given a pointer into a time zone string, extract an offset, in
+** Given a pointer into a timezone string, extract an offset, in
** [+-]hh[:mm[:ss]] form, from the string.
** If any error occurs, return NULL.
** Otherwise, return a pointer to the first character not part of the time.
*/
static const char *
-getoffset(strp, offsetp)
-register const char * strp;
-long * const offsetp;
+getoffset(register const char *strp, int_fast32_t *const offsetp)
{
- register int neg = 0;
+ register bool neg = false;
if (*strp == '-') {
- neg = 1;
+ neg = true;
++strp;
} else if (*strp == '+')
++strp;
@@ -743,16 +964,14 @@ long * const offsetp;
}
/*
-** Given a pointer into a time zone string, extract a rule in the form
+** Given a pointer into a timezone string, extract a rule in the form
** date[/time]. See POSIX section 8 for the format of "date" and "time".
** If a valid rule is not found, return NULL.
** Otherwise, return a pointer to the first character not part of the rule.
*/
static const char *
-getrule(strp, rulep)
-const char * strp;
-register struct rule * const rulep;
+getrule(const char *strp, register struct rule *const rulep)
{
if (*strp == 'J') {
/*
@@ -792,30 +1011,25 @@ register struct rule * const rulep;
** Time specified.
*/
++strp;
- strp = getsecs(strp, &rulep->r_time);
+ strp = getoffset(strp, &rulep->r_time);
} else rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
return strp;
}
/*
-** Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the
-** year, a rule, and the offset from UTC at the time that rule takes effect,
-** calculate the Epoch-relative time that rule takes effect.
+** Given a year, a rule, and the offset from UT at the time that rule takes
+** effect, calculate the year-relative time that rule takes effect.
*/
-static time_t
-transtime(janfirst, year, rulep, offset)
-const time_t janfirst;
-const int year;
-register const struct rule * const rulep;
-const long offset;
+static int_fast32_t
+transtime(const int year, register const struct rule *const rulep,
+ const int_fast32_t offset)
{
- register int leapyear;
- register time_t value;
+ register bool leapyear;
+ register int_fast32_t value;
register int i;
int d, m1, yy0, yy1, yy2, dow;
- INITIALIZE(value);
leapyear = isleap(year);
switch (rulep->r_type) {
@@ -827,7 +1041,7 @@ const long offset;
** add SECSPERDAY times the day number-1 to the time of
** January 1, midnight, to get the day.
*/
- value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
+ value = (rulep->r_day - 1) * SECSPERDAY;
if (leapyear && rulep->r_day >= 60)
value += SECSPERDAY;
break;
@@ -838,16 +1052,13 @@ const long offset;
** Just add SECSPERDAY times the day number to the time of
** January 1, midnight, to get the day.
*/
- value = janfirst + rulep->r_day * SECSPERDAY;
+ value = rulep->r_day * SECSPERDAY;
break;
case MONTH_NTH_DAY_OF_WEEK:
/*
** Mm.n.d - nth "dth day" of month m.
*/
- value = janfirst;
- for (i = 0; i < rulep->r_mon - 1; ++i)
- value += mon_lengths[leapyear][i] * SECSPERDAY;
/*
** Use Zeller's Congruence to get day-of-week of first day of
@@ -880,15 +1091,19 @@ const long offset;
/*
** "d" is the day-of-month (zero-origin) of the day we want.
*/
- value += d * SECSPERDAY;
+ value = d * SECSPERDAY;
+ for (i = 0; i < rulep->r_mon - 1; ++i)
+ value += mon_lengths[leapyear][i] * SECSPERDAY;
break;
+
+ default: UNREACHABLE();
}
/*
- ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in
- ** question. To get the Epoch-relative time of the specified local
+ ** "value" is the year-relative time of 00:00:00 UT on the 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 UTC.
+ ** from UT.
*/
return value + rulep->r_time + offset;
}
@@ -898,144 +1113,194 @@ const long offset;
** appropriate.
*/
-static int
-tzparse(name, sp, lastditch)
-const char * name;
-register struct state * const sp;
-const int lastditch;
+static bool
+tzparse(const char *name, struct state *sp, struct state *basep)
{
const char * stdname;
const char * dstname;
size_t stdlen;
size_t dstlen;
- long stdoffset;
- long dstoffset;
- register time_t * atp;
- register unsigned char * typep;
+ size_t charcnt;
+ int_fast32_t stdoffset;
+ int_fast32_t dstoffset;
register char * cp;
- register int load_result;
- static struct ttinfo zttinfo;
+ register bool load_ok;
+ time_t atlo = TIME_T_MIN, leaplo = TIME_T_MIN;
- INITIALIZE(dstname);
stdname = name;
- if (lastditch) {
- stdlen = strlen(name); /* length of standard zone name */
- name += stdlen;
- if (stdlen >= sizeof sp->chars)
- stdlen = (sizeof sp->chars) - 1;
- stdoffset = 0;
+ if (*name == '<') {
+ name++;
+ stdname = name;
+ name = getqzname(name, '>');
+ if (*name != '>')
+ return false;
+ stdlen = name - stdname;
+ name++;
} else {
- if (*name == '<') {
- name++;
- stdname = name;
- name = getqzname(name, '>');
- if (*name != '>')
- return (-1);
- stdlen = name - stdname;
- name++;
- } else {
- name = getzname(name);
- stdlen = name - stdname;
- }
- if (*name == '\0')
- return -1;
- name = getoffset(name, &stdoffset);
- if (name == NULL)
- return -1;
+ name = getzname(name);
+ stdlen = name - stdname;
+ }
+ if (!stdlen)
+ return false;
+ name = getoffset(name, &stdoffset);
+ if (name == NULL)
+ return false;
+ charcnt = stdlen + 1;
+ if (sizeof sp->chars < charcnt)
+ return false;
+ if (basep) {
+ if (0 < basep->timecnt)
+ atlo = basep->ats[basep->timecnt - 1];
+ load_ok = false;
+ sp->leapcnt = basep->leapcnt;
+ memcpy(sp->lsis, basep->lsis, sp->leapcnt * sizeof *sp->lsis);
+ } else {
+ load_ok = tzload(TZDEFRULES, sp, false) == 0;
+ if (!load_ok)
+ sp->leapcnt = 0; /* So, we're off a little. */
}
- load_result = tzload(TZDEFRULES, sp, FALSE);
- if (load_result != 0)
- sp->leapcnt = 0; /* so, we're off a little */
+ if (0 < sp->leapcnt)
+ leaplo = sp->lsis[sp->leapcnt - 1].ls_trans;
if (*name != '\0') {
if (*name == '<') {
dstname = ++name;
name = getqzname(name, '>');
if (*name != '>')
- return -1;
+ return false;
dstlen = name - dstname;
name++;
} else {
dstname = name;
name = getzname(name);
- dstlen = name - dstname; /* length of DST zone name */
+ dstlen = name - dstname; /* length of DST abbr. */
}
+ if (!dstlen)
+ return false;
+ charcnt += dstlen + 1;
+ if (sizeof sp->chars < charcnt)
+ return false;
if (*name != '\0' && *name != ',' && *name != ';') {
name = getoffset(name, &dstoffset);
if (name == NULL)
- return -1;
+ return false;
} else dstoffset = stdoffset - SECSPERHOUR;
- if (*name == '\0' && load_result != 0)
+ if (*name == '\0' && !load_ok)
name = TZDEFRULESTRING;
if (*name == ',' || *name == ';') {
struct rule start;
struct rule end;
register int year;
- register time_t janfirst;
- time_t starttime;
- time_t endtime;
+ register int timecnt;
+ time_t janfirst;
+ int_fast32_t janoffset = 0;
+ int yearbeg, yearlim;
++name;
if ((name = getrule(name, &start)) == NULL)
- return -1;
+ return false;
if (*name++ != ',')
- return -1;
+ return false;
if ((name = getrule(name, &end)) == NULL)
- return -1;
+ return false;
if (*name != '\0')
- return -1;
+ return false;
sp->typecnt = 2; /* standard time and DST */
/*
** Two transitions per year, from EPOCH_YEAR forward.
*/
- sp->ttis[0] = sp->ttis[1] = zttinfo;
- sp->ttis[0].tt_gmtoff = -dstoffset;
- sp->ttis[0].tt_isdst = 1;
- sp->ttis[0].tt_abbrind = stdlen + 1;
- sp->ttis[1].tt_gmtoff = -stdoffset;
- sp->ttis[1].tt_isdst = 0;
- sp->ttis[1].tt_abbrind = 0;
- atp = sp->ats;
- typep = sp->types;
+ init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
+ init_ttinfo(&sp->ttis[1], -dstoffset, true, stdlen + 1);
+ sp->defaulttype = 0;
+ timecnt = 0;
janfirst = 0;
- sp->timecnt = 0;
- for (year = EPOCH_YEAR;
- sp->timecnt + 2 <= TZ_MAX_TIMES;
- ++year) {
- time_t newfirst;
-
- starttime = transtime(janfirst, year, &start,
- stdoffset);
- endtime = transtime(janfirst, year, &end,
- dstoffset);
- if (starttime > endtime) {
- *atp++ = endtime;
- *typep++ = 1; /* DST ends */
- *atp++ = starttime;
- *typep++ = 0; /* DST begins */
- } else {
- *atp++ = starttime;
- *typep++ = 0; /* DST begins */
- *atp++ = endtime;
- *typep++ = 1; /* DST ends */
+ yearbeg = EPOCH_YEAR;
+
+ do {
+ int_fast32_t yearsecs
+ = year_lengths[isleap(yearbeg - 1)] * SECSPERDAY;
+ yearbeg--;
+ if (increment_overflow_time(&janfirst, -yearsecs)) {
+ janoffset = -yearsecs;
+ break;
+ }
+ } while (atlo < janfirst
+ && EPOCH_YEAR - YEARSPERREPEAT / 2 < yearbeg);
+
+ while (true) {
+ int_fast32_t yearsecs
+ = year_lengths[isleap(yearbeg)] * SECSPERDAY;
+ int yearbeg1 = yearbeg;
+ time_t janfirst1 = janfirst;
+ if (increment_overflow_time(&janfirst1, yearsecs)
+ || increment_overflow(&yearbeg1, 1)
+ || atlo <= janfirst1)
+ break;
+ yearbeg = yearbeg1;
+ janfirst = janfirst1;
+ }
+
+ yearlim = yearbeg;
+ if (increment_overflow(&yearlim, YEARSPERREPEAT + 1))
+ yearlim = INT_MAX;
+ for (year = yearbeg; year < yearlim; year++) {
+ int_fast32_t
+ starttime = transtime(year, &start, stdoffset),
+ endtime = transtime(year, &end, dstoffset);
+ int_fast32_t
+ yearsecs = (year_lengths[isleap(year)]
+ * SECSPERDAY);
+ bool reversed = endtime < starttime;
+ if (reversed) {
+ int_fast32_t swap = starttime;
+ starttime = endtime;
+ endtime = swap;
+ }
+ 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])
+ sp->types[timecnt++] = !reversed;
+ sp->ats[timecnt] = janfirst;
+ if (! increment_overflow_time
+ (&sp->ats[timecnt],
+ janoffset + endtime)
+ && atlo <= sp->ats[timecnt]) {
+ sp->types[timecnt++] = reversed;
+ }
}
- sp->timecnt += 2;
- newfirst = janfirst;
- newfirst += year_lengths[isleap(year)] *
- SECSPERDAY;
- if (newfirst <= janfirst)
+ if (endtime < leaplo) {
+ yearlim = year;
+ if (increment_overflow(&yearlim,
+ YEARSPERREPEAT + 1))
+ yearlim = INT_MAX;
+ }
+ if (increment_overflow_time
+ (&janfirst, janoffset + yearsecs))
break;
- janfirst = newfirst;
+ janoffset = 0;
}
+ sp->timecnt = timecnt;
+ if (! timecnt) {
+ sp->ttis[0] = sp->ttis[1];
+ sp->typecnt = 1; /* Perpetual DST. */
+ } else if (YEARSPERREPEAT < year - yearbeg)
+ sp->goback = sp->goahead = true;
} else {
- register long theirstdoffset;
- register long theirdstoffset;
- register long theiroffset;
- register int isdst;
- register int i;
- register int j;
+ register int_fast32_t theirstdoffset;
+ register int_fast32_t theirdstoffset;
+ register int_fast32_t theiroffset;
+ register bool isdst;
+ register int i;
+ register int j;
if (*name != '\0')
- return -1;
+ return false;
/*
** Initial values of theirstdoffset and theirdstoffset.
*/
@@ -1044,7 +1309,7 @@ const int lastditch;
j = sp->types[i];
if (!sp->ttis[j].tt_isdst) {
theirstdoffset =
- -sp->ttis[j].tt_gmtoff;
+ - sp->ttis[j].tt_utoff;
break;
}
}
@@ -1053,15 +1318,14 @@ const int lastditch;
j = sp->types[i];
if (sp->ttis[j].tt_isdst) {
theirdstoffset =
- -sp->ttis[j].tt_gmtoff;
+ - sp->ttis[j].tt_utoff;
break;
}
}
/*
** Initially we're assumed to be in standard time.
*/
- isdst = FALSE;
- theiroffset = theirstdoffset;
+ isdst = false;
/*
** Now juggle transition times and types
** tracking offsets as you do.
@@ -1069,16 +1333,17 @@ const int lastditch;
for (i = 0; i < sp->timecnt; ++i) {
j = sp->types[i];
sp->types[i] = sp->ttis[j].tt_isdst;
- if (sp->ttis[j].tt_ttisgmt) {
+ if (sp->ttis[j].tt_ttisut) {
/* No adjustment to transition time */
} else {
/*
- ** If summer time is in effect, and the
- ** transition time was not specified as
- ** standard time, add the summer time
- ** offset to the transition time;
- ** otherwise, add the standard time
- ** offset to the transition time.
+ ** If daylight saving time is in
+ ** effect, and the transition time was
+ ** not specified as standard time, add
+ ** the daylight saving time offset to
+ ** the transition time; otherwise, add
+ ** the standard time offset to the
+ ** transition time.
*/
/*
** Transitions from DST to DDST
@@ -1094,7 +1359,7 @@ const int lastditch;
theirstdoffset;
}
}
- theiroffset = -sp->ttis[j].tt_gmtoff;
+ theiroffset = -sp->ttis[j].tt_utoff;
if (sp->ttis[j].tt_isdst)
theirdstoffset = theiroffset;
else theirstdoffset = theiroffset;
@@ -1102,192 +1367,219 @@ const int lastditch;
/*
** Finally, fill in ttis.
*/
- sp->ttis[0] = sp->ttis[1] = zttinfo;
- sp->ttis[0].tt_gmtoff = -stdoffset;
- sp->ttis[0].tt_isdst = FALSE;
- sp->ttis[0].tt_abbrind = 0;
- sp->ttis[1].tt_gmtoff = -dstoffset;
- sp->ttis[1].tt_isdst = TRUE;
- sp->ttis[1].tt_abbrind = stdlen + 1;
+ init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
+ init_ttinfo(&sp->ttis[1], -dstoffset, true, stdlen + 1);
sp->typecnt = 2;
+ sp->defaulttype = 0;
}
} else {
dstlen = 0;
sp->typecnt = 1; /* only standard time */
sp->timecnt = 0;
- sp->ttis[0] = zttinfo;
- sp->ttis[0].tt_gmtoff = -stdoffset;
- sp->ttis[0].tt_isdst = 0;
- sp->ttis[0].tt_abbrind = 0;
+ init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
+ sp->defaulttype = 0;
}
- sp->charcnt = stdlen + 1;
- if (dstlen != 0)
- sp->charcnt += dstlen + 1;
- if ((size_t) sp->charcnt > sizeof sp->chars)
- return -1;
+ sp->charcnt = charcnt;
cp = sp->chars;
- (void) strncpy(cp, stdname, stdlen);
+ memcpy(cp, stdname, stdlen);
cp += stdlen;
*cp++ = '\0';
if (dstlen != 0) {
- (void) strncpy(cp, dstname, dstlen);
+ memcpy(cp, dstname, dstlen);
*(cp + dstlen) = '\0';
}
- return 0;
+ return true;
}
static void
-gmtload(sp)
-struct state * const sp;
+gmtload(struct state *const sp)
{
- if (tzload(gmt, sp, TRUE) != 0)
- (void) tzparse(gmt, sp, TRUE);
+ if (tzload(etc_utc, sp, true) != 0)
+ tzparse("UTC0", sp, NULL);
}
-#ifndef STD_INSPIRED
-/*
-** A non-static declaration of tzsetwall in a system header file
-** may cause a warning about this upcoming static declaration...
-*/
-static
-#endif /* !defined STD_INSPIRED */
-void
-tzsetwall(void)
+/* Initialize *SP to a value appropriate for the TZ setting NAME.
+ Return 0 on success, an errno value on failure. */
+static int
+zoneinit(struct state *sp, char const *name)
{
- if (lcl_is_set < 0)
- return;
- lcl_is_set = -1;
+ if (name && ! name[0]) {
+ /*
+ ** User wants it fast rather than right.
+ */
+ sp->leapcnt = 0; /* so, we're off a little */
+ sp->timecnt = 0;
+ sp->typecnt = 0;
+ sp->charcnt = 0;
+ sp->goback = sp->goahead = false;
+ init_ttinfo(&sp->ttis[0], 0, false, 0);
+ strcpy(sp->chars, utc);
+ sp->defaulttype = 0;
+ return 0;
+ } else {
+ int err = tzload(name, sp, true);
+ if (err != 0 && name && name[0] != ':' && tzparse(name, sp, NULL))
+ err = 0;
+ if (err == 0)
+ scrub_abbrs(sp);
+ return err;
+ }
+}
+static void
+tzset_unlocked(void)
+{
+ char const *name = getenv("TZ");
+ struct state *sp = lclptr;
+ int lcl = name ? strlen(name) < sizeof lcl_TZname : -1;
+ if (lcl < 0
+ ? lcl_is_set < 0
+ : 0 < lcl_is_set && strcmp(lcl_TZname, name) == 0)
+ return;
#ifdef ALL_STATE
- if (lclptr == NULL) {
- lclptr = (struct state *) calloc(1, sizeof *lclptr);
- if (lclptr == NULL) {
- settzname(); /* all we can do */
- return;
- }
- }
+ if (! sp)
+ lclptr = sp = malloc(sizeof *lclptr);
#endif /* defined ALL_STATE */
- if (tzload((char *) NULL, lclptr, TRUE) != 0)
- gmtload(lclptr);
- settzname();
+ if (sp) {
+ if (zoneinit(sp, name) != 0)
+ zoneinit(sp, "");
+ if (0 < lcl)
+ strcpy(lcl_TZname, name);
+ }
+ settzname();
+ lcl_is_set = lcl;
}
void
tzset(void)
{
- register const char * name;
+ if (lock() != 0)
+ return;
+ tzset_unlocked();
+ unlock();
+}
- name = getenv("TZ");
- if (name == NULL) {
- tzsetwall();
- return;
- }
+static void
+gmtcheck(void)
+{
+ static bool gmt_is_set;
+ if (lock() != 0)
+ return;
+ if (! gmt_is_set) {
+#ifdef ALL_STATE
+ gmtptr = malloc(sizeof *gmtptr);
+#endif
+ if (gmtptr)
+ gmtload(gmtptr);
+ gmt_is_set = true;
+ }
+ unlock();
+}
- if (lcl_is_set > 0 && strcmp(lcl_TZname, name) == 0)
- return;
- lcl_is_set = strlen(name) < sizeof lcl_TZname;
- if (lcl_is_set)
- (void) strcpy(lcl_TZname, name);
+#if NETBSD_INSPIRED
-#ifdef ALL_STATE
- if (lclptr == NULL) {
- lclptr = (struct state *) calloc(1, sizeof *lclptr);
- if (lclptr == NULL) {
- settzname(); /* all we can do */
- return;
- }
- }
-#endif /* defined ALL_STATE */
- if (*name == '\0') {
- /*
- ** User wants it fast rather than right.
- */
- lclptr->leapcnt = 0; /* so, we're off a little */
- lclptr->timecnt = 0;
- lclptr->typecnt = 0;
- lclptr->ttis[0].tt_isdst = 0;
- lclptr->ttis[0].tt_gmtoff = 0;
- lclptr->ttis[0].tt_abbrind = 0;
- (void) strcpy(lclptr->chars, gmt);
- } else if (tzload(name, lclptr, TRUE) != 0)
- if (name[0] == ':' || tzparse(name, lclptr, FALSE) != 0)
- (void) gmtload(lclptr);
- settzname();
+timezone_t
+tzalloc(char const *name)
+{
+ timezone_t sp = malloc(sizeof *sp);
+ if (sp) {
+ int err = zoneinit(sp, name);
+ if (err != 0) {
+ free(sp);
+ errno = err;
+ return NULL;
+ }
+ } else if (!HAVE_MALLOC_ERRNO)
+ errno = ENOMEM;
+ return sp;
+}
+
+void
+tzfree(timezone_t sp)
+{
+ free(sp);
}
/*
+** NetBSD 6.1.4 has ctime_rz, but omit it because POSIX says ctime and
+** ctime_r are obsolescent and have potential security problems that
+** ctime_rz would share. Callers can instead use localtime_rz + strftime.
+**
+** NetBSD 6.1.4 has tzgetname, but omit it because it doesn't work
+** in zones with three or more time zone abbreviations.
+** Callers can instead use localtime_rz + strftime.
+*/
+
+#endif
+
+/*
** The easy way to behave "as if no library function calls" localtime
-** is to not call it--so we drop its guts into "localsub", which can be
-** freely called. (And no, the PANS doesn't require the above behavior--
+** is to not call it, so we drop its guts into "localsub", which can be
+** freely called. (And no, the PANS doesn't require the above behavior,
** but it *is* desirable.)
**
-** The unused offset argument is for the benefit of mktime variants.
+** If successful and SETNAME is nonzero,
+** set the applicable parts of tzname, timezone and altzone;
+** however, it's OK to omit this step if the timezone is POSIX-compatible,
+** 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.
*/
/*ARGSUSED*/
static struct tm *
-localsub(timep, offset, tmp)
-const time_t * const timep;
-const long offset;
-struct tm * const tmp;
+localsub(struct state const *sp, time_t const *timep, int_fast32_t setname,
+ struct tm *const tmp)
{
- register struct state * sp;
register const struct ttinfo * ttisp;
register int i;
register struct tm * result;
const time_t t = *timep;
- sp = lclptr;
-#ifdef ALL_STATE
- if (sp == NULL)
- return gmtsub(timep, offset, tmp);
-#endif /* defined ALL_STATE */
+ if (sp == NULL) {
+ /* Don't bother to set tzname etc.; tzset has already done it. */
+ return gmtsub(gmtptr, timep, 0, tmp);
+ }
if ((sp->goback && t < sp->ats[0]) ||
(sp->goahead && t > sp->ats[sp->timecnt - 1])) {
- time_t newt = t;
+ time_t newt;
register time_t seconds;
- register time_t tcycles;
- register int_fast64_t icycles;
+ register time_t years;
if (t < sp->ats[0])
seconds = sp->ats[0] - t;
else seconds = t - sp->ats[sp->timecnt - 1];
--seconds;
- tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
- ++tcycles;
- icycles = tcycles;
- if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
- return NULL;
- seconds = icycles;
- seconds *= YEARSPERREPEAT;
- seconds *= AVGSECSPERYEAR;
+
+ /* 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 += seconds;
- else newt -= seconds;
+ 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(&newt, offset, tmp);
- if (result == tmp) {
- register time_t newy;
+ result = localsub(sp, &newt, setname, tmp);
+ if (result) {
+ register int_fast64_t newy;
- newy = tmp->tm_year;
+ newy = result->tm_year;
if (t < sp->ats[0])
- newy -= icycles * YEARSPERREPEAT;
- else newy += icycles * YEARSPERREPEAT;
- tmp->tm_year = newy;
- if (tmp->tm_year != newy)
+ newy -= years;
+ else newy += years;
+ if (! (INT_MIN <= newy && newy <= INT_MAX))
return NULL;
+ result->tm_year = newy;
}
return result;
}
if (sp->timecnt == 0 || t < sp->ats[0]) {
- i = 0;
- while (sp->ttis[i].tt_isdst)
- if (++i >= sp->typecnt) {
- i = 0;
- break;
- }
+ i = sp->defaulttype;
} else {
register int lo = 1;
register int hi = sp->timecnt;
@@ -1299,42 +1591,62 @@ struct tm * const tmp;
hi = mid;
else lo = mid + 1;
}
- i = (int) sp->types[lo - 1];
+ i = sp->types[lo - 1];
}
ttisp = &sp->ttis[i];
/*
** To get (wrong) behavior that's compatible with System V Release 2.0
** you'd replace the statement below with
- ** t += ttisp->tt_gmtoff;
+ ** t += ttisp->tt_utoff;
** timesub(&t, 0L, sp, tmp);
*/
- result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
- tmp->tm_isdst = ttisp->tt_isdst;
- tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind];
+ result = timesub(&t, ttisp->tt_utoff, sp, tmp);
+ if (result) {
+ result->tm_isdst = ttisp->tt_isdst;
#ifdef TM_ZONE
- tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];
+ result->TM_ZONE = (char *) &sp->chars[ttisp->tt_desigidx];
#endif /* defined TM_ZONE */
+ if (setname)
+ update_tzname_etc(sp, ttisp);
+ }
return result;
}
+#if NETBSD_INSPIRED
+
struct tm *
-localtime(timep)
-const time_t * const timep;
+localtime_rz(struct state *sp, time_t const *timep, struct tm *tmp)
{
- tzset();
- return localsub(timep, 0L, &tm);
+ return localsub(sp, timep, 0, tmp);
}
-/*
-** Re-entrant version of localtime.
-*/
+#endif
+
+static struct tm *
+localtime_tzset(time_t const *timep, struct tm *tmp, bool setname)
+{
+ int err = lock();
+ if (err) {
+ errno = err;
+ return NULL;
+ }
+ if (setname || !lcl_is_set)
+ tzset_unlocked();
+ tmp = localsub(lclptr, timep, setname, tmp);
+ unlock();
+ return tmp;
+}
+
+struct tm *
+localtime(const time_t *timep)
+{
+ return localtime_tzset(timep, &tm, true);
+}
struct tm *
-localtime_r(timep, tmp)
-const time_t * const timep;
-struct tm * tmp;
+localtime_r(const time_t *timep, struct tm *tmp)
{
- return localsub(timep, 0L, tmp);
+ return localtime_tzset(timep, tmp, false);
}
/*
@@ -1342,71 +1654,48 @@ struct tm * tmp;
*/
static struct tm *
-gmtsub(timep, offset, tmp)
-const time_t * const timep;
-const long offset;
-struct tm * const tmp;
+gmtsub(struct state const *sp, time_t const *timep, int_fast32_t offset,
+ struct tm *tmp)
{
register struct tm * result;
- if (!gmt_is_set) {
- gmt_is_set = TRUE;
-#ifdef ALL_STATE
- gmtptr = (struct state *) calloc(1, sizeof *gmtptr);
- if (gmtptr != NULL)
-#endif /* defined ALL_STATE */
- gmtload(gmtptr);
- }
result = timesub(timep, offset, gmtptr, tmp);
#ifdef TM_ZONE
/*
** Could get fancy here and deliver something such as
- ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero,
+ ** "+xx" or "-xx" if offset is non-zero,
** but this is no time for a treasure hunt.
*/
- if (offset != 0)
- tmp->TM_ZONE = wildabbr;
- else {
-#ifdef ALL_STATE
- if (gmtptr == NULL)
- tmp->TM_ZONE = gmt;
- else tmp->TM_ZONE = gmtptr->chars;
-#endif /* defined ALL_STATE */
-#ifndef ALL_STATE
- tmp->TM_ZONE = gmtptr->chars;
-#endif /* State Farm */
- }
+ tmp->TM_ZONE = ((char *)
+ (offset ? wildabbr : gmtptr ? gmtptr->chars : utc));
#endif /* defined TM_ZONE */
return result;
}
-struct tm *
-gmtime(timep)
-const time_t * const timep;
-{
- return gmtsub(timep, 0L, &tm);
-}
-
/*
* Re-entrant version of gmtime.
*/
struct tm *
-gmtime_r(timep, tmp)
-const time_t * const timep;
-struct tm * tmp;
+gmtime_r(const time_t *timep, struct tm *tmp)
{
- return gmtsub(timep, 0L, tmp);
+ gmtcheck();
+ return gmtsub(gmtptr, timep, 0, tmp);
+}
+
+struct tm *
+gmtime(const time_t *timep)
+{
+ return gmtime_r(timep, &tm);
}
#ifdef STD_INSPIRED
struct tm *
-offtime(timep, offset)
-const time_t * const timep;
-const long offset;
+offtime(const time_t *timep, long offset)
{
- return gmtsub(timep, offset, &tm);
+ gmtcheck();
+ return gmtsub(gmtptr, timep, offset, &tm);
}
#endif /* defined STD_INSPIRED */
@@ -1416,141 +1705,121 @@ const long offset;
** where, to make the math easy, the answer for year zero is defined as zero.
*/
-static int
-leaps_thru_end_of(y)
-register const int y;
+static time_t
+leaps_thru_end_of_nonneg(time_t y)
+{
+ return y / 4 - y / 100 + y / 400;
+}
+
+static time_t
+leaps_thru_end_of(time_t y)
{
- return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
- -(leaps_thru_end_of(-(y + 1)) + 1);
+ return (y < 0
+ ? -1 - leaps_thru_end_of_nonneg(-1 - y)
+ : leaps_thru_end_of_nonneg(y));
}
static struct tm *
-timesub(timep, offset, sp, tmp)
-const time_t * const timep;
-const long offset;
-register const struct state * const sp;
-register struct tm * const tmp;
+timesub(const time_t *timep, int_fast32_t offset,
+ const struct state *sp, struct tm *tmp)
{
register const struct lsinfo * lp;
register time_t tdays;
- register int idays; /* unsigned would be so 2003 */
- register long rem;
- int y;
register const int * ip;
- register long corr;
- register int hit;
+ register int_fast32_t corr;
register int i;
+ int_fast32_t idays, rem, dayoff, dayrem;
+ time_t y;
+
+ /* If less than SECSPERMIN, the number of seconds since the
+ most recent positive leap second; otherwise, do not add 1
+ to localtime tm_sec because of leap seconds. */
+ time_t secs_since_posleap = SECSPERMIN;
corr = 0;
- hit = 0;
-#ifdef ALL_STATE
i = (sp == NULL) ? 0 : sp->leapcnt;
-#endif /* defined ALL_STATE */
-#ifndef ALL_STATE
- i = sp->leapcnt;
-#endif /* State Farm */
while (--i >= 0) {
lp = &sp->lsis[i];
if (*timep >= lp->ls_trans) {
- if (*timep == lp->ls_trans) {
- hit = ((i == 0 && lp->ls_corr > 0) ||
- lp->ls_corr > sp->lsis[i - 1].ls_corr);
- if (hit)
- while (i > 0 &&
- sp->lsis[i].ls_trans ==
- sp->lsis[i - 1].ls_trans + 1 &&
- sp->lsis[i].ls_corr ==
- sp->lsis[i - 1].ls_corr + 1) {
- ++hit;
- --i;
- }
- }
corr = lp->ls_corr;
+ if ((i == 0 ? 0 : lp[-1].ls_corr) < corr)
+ secs_since_posleap = *timep - lp->ls_trans;
break;
}
}
- y = EPOCH_YEAR;
+
+ /* Calculate the year, avoiding integer overflow even if
+ time_t is unsigned. */
tdays = *timep / SECSPERDAY;
- rem = *timep - tdays * SECSPERDAY;
- while (tdays < 0 || tdays >= year_lengths[isleap(y)]) {
- int newy;
- register time_t tdelta;
- register int idelta;
+ rem = *timep % SECSPERDAY;
+ rem += offset % SECSPERDAY - corr % SECSPERDAY + 3 * SECSPERDAY;
+ dayoff = offset / SECSPERDAY - corr / SECSPERDAY + rem / SECSPERDAY - 3;
+ rem %= SECSPERDAY;
+ /* y = (EPOCH_YEAR
+ + floor((tdays + dayoff) / DAYSPERREPEAT) * YEARSPERREPEAT),
+ sans overflow. But calculate against 1570 (EPOCH_YEAR -
+ YEARSPERREPEAT) instead of against 1970 so that things work
+ for localtime values before 1970 when time_t is unsigned. */
+ dayrem = tdays % DAYSPERREPEAT;
+ dayrem += dayoff % DAYSPERREPEAT;
+ y = (EPOCH_YEAR - YEARSPERREPEAT
+ + ((1 + dayoff / DAYSPERREPEAT + dayrem / DAYSPERREPEAT
+ - ((dayrem % DAYSPERREPEAT) < 0)
+ + tdays / DAYSPERREPEAT)
+ * YEARSPERREPEAT));
+ /* idays = (tdays + dayoff) mod DAYSPERREPEAT, sans overflow. */
+ idays = tdays % DAYSPERREPEAT;
+ 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) {
+ int tdelta = idays / DAYSPERLYEAR;
+ int_fast32_t ydelta = tdelta + !tdelta;
+ time_t newy = y + ydelta;
register int leapdays;
-
- tdelta = tdays / DAYSPERLYEAR;
- idelta = tdelta;
- if (tdelta - idelta >= 1 || idelta - tdelta >= 1)
- return NULL;
- if (idelta == 0)
- idelta = (tdays < 0) ? -1 : 1;
- newy = y;
- if (increment_overflow(&newy, idelta))
- return NULL;
leapdays = leaps_thru_end_of(newy - 1) -
leaps_thru_end_of(y - 1);
- tdays -= ((time_t) newy - y) * DAYSPERNYEAR;
- tdays -= leapdays;
+ idays -= ydelta * DAYSPERNYEAR;
+ idays -= leapdays;
y = newy;
}
- {
- register long seconds;
- seconds = tdays * SECSPERDAY + 0.5;
- tdays = seconds / SECSPERDAY;
- rem += seconds - tdays * SECSPERDAY;
- }
- /*
- ** Given the range, we can now fearlessly cast...
- */
- idays = tdays;
- rem += offset - corr;
- while (rem < 0) {
- rem += SECSPERDAY;
- --idays;
- }
- while (rem >= SECSPERDAY) {
- rem -= SECSPERDAY;
- ++idays;
- }
- while (idays < 0) {
- if (increment_overflow(&y, -1))
- return NULL;
- idays += year_lengths[isleap(y)];
- }
- while (idays >= year_lengths[isleap(y)]) {
- idays -= year_lengths[isleap(y)];
- if (increment_overflow(&y, 1))
- 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;
}
- tmp->tm_year = y;
- if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE))
- return NULL;
tmp->tm_yday = idays;
/*
** The "extra" mods below avoid overflow problems.
*/
- tmp->tm_wday = EPOCH_WDAY +
- ((y - EPOCH_YEAR) % DAYSPERWEEK) *
- (DAYSPERNYEAR % DAYSPERWEEK) +
- leaps_thru_end_of(y - 1) -
- leaps_thru_end_of(EPOCH_YEAR - 1) +
- idays;
+ tmp->tm_wday = (TM_WDAY_BASE
+ + ((tmp->tm_year % DAYSPERWEEK)
+ * (DAYSPERNYEAR % DAYSPERWEEK))
+ + leaps_thru_end_of(y - 1)
+ - leaps_thru_end_of(TM_YEAR_BASE - 1)
+ + idays);
tmp->tm_wday %= DAYSPERWEEK;
if (tmp->tm_wday < 0)
tmp->tm_wday += DAYSPERWEEK;
- tmp->tm_hour = (int) (rem / SECSPERHOUR);
+ tmp->tm_hour = rem / SECSPERHOUR;
rem %= SECSPERHOUR;
- tmp->tm_min = (int) (rem / SECSPERMIN);
- /*
- ** A positive leap second requires a special
- ** representation. This uses "... ??:59:60" et seq.
- */
- tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
+ tmp->tm_min = rem / SECSPERMIN;
+ tmp->tm_sec = rem % SECSPERMIN;
+
+ /* Use "... ??:??:60" at the end of the localtime minute containing
+ the second just before the positive leap second. */
+ tmp->tm_sec += secs_since_posleap <= tmp->tm_sec;
+
ip = mon_lengths[isleap(y)];
for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
idays -= ip[tmp->tm_mon];
- tmp->tm_mday = (int) (idays + 1);
+ tmp->tm_mday = idays + 1;
tmp->tm_isdst = 0;
#ifdef TM_GMTOFF
tmp->TM_GMTOFF = offset;
@@ -1559,8 +1828,7 @@ register struct tm * const tmp;
}
char *
-ctime(timep)
-const time_t * const timep;
+ctime(const time_t *timep)
{
/*
** Section 4.12.3.2 of X3.159-1989 requires that
@@ -1568,17 +1836,16 @@ const time_t * const timep;
** to local time in the form of a string. It is equivalent to
** asctime(localtime(timer))
*/
- return asctime(localtime(timep));
+ struct tm *tmp = localtime(timep);
+ return tmp ? asctime(tmp) : NULL;
}
char *
-ctime_r(timep, buf)
-const time_t * const timep;
-char * buf;
+ctime_r(const time_t *timep, char *buf)
{
- struct tm mytm;
-
- return asctime_r(localtime_r(timep, &mytm), buf);
+ struct tm mytm;
+ struct tm *tmp = localtime_r(timep, &mytm);
+ return tmp ? asctime_r(tmp, buf) : NULL;
}
/*
@@ -1591,42 +1858,59 @@ char * buf;
*/
#ifndef WRONG
-#define WRONG (-1)
+# define WRONG (-1)
#endif /* !defined WRONG */
/*
-** Simplified normalize logic courtesy Paul Eggert.
+** Normalize logic courtesy Paul Eggert.
*/
-static int
-increment_overflow(number, delta)
-int * number;
-int delta;
+static bool
+increment_overflow(int *ip, int j)
{
- int number0;
+ register int const i = *ip;
- number0 = *number;
- *number += delta;
- return (*number < number0) != (delta < 0);
+ /*
+ ** 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;
}
-static int
-long_increment_overflow(number, delta)
-long * number;
-int delta;
+static bool
+increment_overflow32(int_fast32_t *const lp, int const m)
{
- long number0;
+ register int_fast32_t const l = *lp;
- number0 = *number;
- *number += delta;
- return (*number < number0) != (delta < 0);
+ if ((l >= 0) ? (m > INT_FAST32_MAX - l) : (m < INT_FAST32_MIN - l))
+ return true;
+ *lp += m;
+ return false;
}
-static int
-normalize_overflow(tensptr, unitsptr, base)
-int * const tensptr;
-int * const unitsptr;
-const int base;
+static bool
+increment_overflow_time(time_t *tp, int_fast32_t j)
+{
+ /*
+ ** This is like
+ ** 'if (! (TIME_T_MIN <= *tp + j && *tp + j <= TIME_T_MAX)) ...',
+ ** except that it does the right thing even if *tp + j would overflow.
+ */
+ if (! (j < 0
+ ? (TYPE_SIGNED(time_t) ? TIME_T_MIN - j <= *tp : -1 - j < *tp)
+ : *tp <= TIME_T_MAX - j))
+ return true;
+ *tp += j;
+ return false;
+}
+
+static bool
+normalize_overflow(int *const tensptr, int *const unitsptr, const int base)
{
register int tensdelta;
@@ -1637,11 +1921,8 @@ const int base;
return increment_overflow(tensptr, tensdelta);
}
-static int
-long_normalize_overflow(tensptr, unitsptr, base)
-long * const tensptr;
-int * const unitsptr;
-const int base;
+static bool
+normalize_overflow32(int_fast32_t *tensptr, int *unitsptr, int base)
{
register int tensdelta;
@@ -1649,18 +1930,18 @@ const int base;
(*unitsptr / base) :
(-1 - (-1 - *unitsptr) / base);
*unitsptr -= tensdelta * base;
- return long_increment_overflow(tensptr, tensdelta);
+ return increment_overflow32(tensptr, tensdelta);
}
static int
-tmcomp(atmp, btmp)
-register const struct tm * const atmp;
-register const struct tm * const btmp;
+tmcomp(register const struct tm *const atmp,
+ register const struct tm *const btmp)
{
register int result;
- if ((result = (atmp->tm_year - btmp->tm_year)) == 0 &&
- (result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
+ if (atmp->tm_year != btmp->tm_year)
+ return atmp->tm_year < btmp->tm_year ? -1 : 1;
+ if ((result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
(result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
(result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
(result = (atmp->tm_min - btmp->tm_min)) == 0)
@@ -1669,26 +1950,26 @@ register const struct tm * const btmp;
}
static time_t
-time2sub(tmp, funcp, offset, okayp, do_norm_secs)
-struct tm * const tmp;
-struct tm * (* const funcp)(const time_t*, long, struct tm*);
-const long offset;
-int * const okayp;
-const int do_norm_secs;
+time2sub(struct tm *const tmp,
+ struct tm *(*funcp)(struct state const *, time_t const *,
+ int_fast32_t, struct tm *),
+ struct state const *sp,
+ const int_fast32_t offset,
+ bool *okayp,
+ bool do_norm_secs)
{
- register const struct state * sp;
register int dir;
register int i, j;
register int saved_seconds;
- register long li;
+ register int_fast32_t li;
register time_t lo;
register time_t hi;
- long y;
+ int_fast32_t y;
time_t newt;
time_t t;
struct tm yourtm, mytm;
- *okayp = FALSE;
+ *okayp = false;
yourtm = *tmp;
if (do_norm_secs) {
if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,
@@ -1700,16 +1981,16 @@ const int do_norm_secs;
if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
return WRONG;
y = yourtm.tm_year;
- if (long_normalize_overflow(&y, &yourtm.tm_mon, MONSPERYEAR))
+ if (normalize_overflow32(&y, &yourtm.tm_mon, MONSPERYEAR))
return WRONG;
/*
** Turn y into an actual year number for now.
** It is converted back to an offset from TM_YEAR_BASE later.
*/
- if (long_increment_overflow(&y, TM_YEAR_BASE))
+ if (increment_overflow32(&y, TM_YEAR_BASE))
return WRONG;
while (yourtm.tm_mday <= 0) {
- if (long_increment_overflow(&y, -1))
+ if (increment_overflow32(&y, -1))
return WRONG;
li = y + (1 < yourtm.tm_mon);
yourtm.tm_mday += year_lengths[isleap(li)];
@@ -1717,7 +1998,7 @@ const int do_norm_secs;
while (yourtm.tm_mday > DAYSPERLYEAR) {
li = y + (1 < yourtm.tm_mon);
yourtm.tm_mday -= year_lengths[isleap(li)];
- if (long_increment_overflow(&y, 1))
+ if (increment_overflow32(&y, 1))
return WRONG;
}
for ( ; ; ) {
@@ -1727,15 +2008,15 @@ const int do_norm_secs;
yourtm.tm_mday -= i;
if (++yourtm.tm_mon >= MONSPERYEAR) {
yourtm.tm_mon = 0;
- if (long_increment_overflow(&y, 1))
+ if (increment_overflow32(&y, 1))
return WRONG;
}
}
- if (long_increment_overflow(&y, -TM_YEAR_BASE))
+ if (increment_overflow32(&y, -TM_YEAR_BASE))
return WRONG;
- yourtm.tm_year = y;
- if (yourtm.tm_year != y)
+ if (! (INT_MIN <= y && y <= INT_MAX))
return WRONG;
+ yourtm.tm_year = y;
if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)
saved_seconds = 0;
else if (y + TM_YEAR_BASE < EPOCH_YEAR) {
@@ -1758,27 +2039,15 @@ const int do_norm_secs;
/*
** Do a binary search (this works whatever time_t's type is).
*/
- if (!TYPE_SIGNED(time_t)) {
- lo = 0;
- hi = lo - 1;
- } else if (!TYPE_INTEGRAL(time_t)) {
- if (sizeof(time_t) > sizeof(float))
- hi = (time_t) DBL_MAX;
- else hi = (time_t) FLT_MAX;
- lo = -hi;
- } else {
- lo = 1;
- for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i)
- lo *= 2;
- hi = -(lo + 1);
- }
+ lo = TIME_T_MIN;
+ hi = TIME_T_MAX;
for ( ; ; ) {
t = lo / 2 + hi / 2;
if (t < lo)
t = lo;
else if (t > hi)
t = hi;
- if ((*funcp)(&t, offset, &mytm) == NULL) {
+ if (! funcp(sp, &t, offset, &mytm)) {
/*
** Assume that t is too extreme to be represented in
** a struct tm; arrange things so that it is less
@@ -1788,14 +2057,14 @@ const int do_norm_secs;
} else dir = tmcomp(&mytm, &yourtm);
if (dir != 0) {
if (t == lo) {
- ++t;
- if (t <= lo)
+ if (t == TIME_T_MAX)
return WRONG;
+ ++t;
++lo;
} else if (t == hi) {
- --t;
- if (t >= hi)
+ if (t == TIME_T_MIN)
return WRONG;
+ --t;
--hi;
}
if (lo > hi)
@@ -1805,6 +2074,35 @@ const int do_norm_secs;
else lo = t;
continue;
}
+#if defined TM_GMTOFF && ! UNINIT_TRAP
+ if (mytm.TM_GMTOFF != yourtm.TM_GMTOFF
+ && (yourtm.TM_GMTOFF < 0
+ ? (-SECSPERDAY <= yourtm.TM_GMTOFF
+ && (mytm.TM_GMTOFF <=
+ (min(INT_FAST32_MAX, LONG_MAX)
+ + yourtm.TM_GMTOFF)))
+ : (yourtm.TM_GMTOFF <= SECSPERDAY
+ && ((max(INT_FAST32_MIN, LONG_MIN)
+ + yourtm.TM_GMTOFF)
+ <= mytm.TM_GMTOFF)))) {
+ /* MYTM matches YOURTM except with the wrong UT offset.
+ YOURTM.TM_GMTOFF is plausible, so try it instead.
+ It's OK if YOURTM.TM_GMTOFF contains uninitialized data,
+ since the guess gets checked. */
+ time_t altt = t;
+ int_fast32_t diff = mytm.TM_GMTOFF - yourtm.TM_GMTOFF;
+ if (!increment_overflow_time(&altt, diff)) {
+ struct tm alttm;
+ if (funcp(sp, &altt, offset, &alttm)
+ && alttm.tm_isdst == mytm.tm_isdst
+ && alttm.TM_GMTOFF == yourtm.TM_GMTOFF
+ && tmcomp(&alttm, &yourtm) == 0) {
+ t = altt;
+ mytm = alttm;
+ }
+ }
+ }
+#endif
if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
break;
/*
@@ -1813,21 +2111,19 @@ const int do_norm_secs;
** It's okay to guess wrong since the guess
** gets checked.
*/
- sp = (const struct state *)
- ((funcp == localsub) ? lclptr : gmtptr);
-#ifdef ALL_STATE
if (sp == NULL)
return WRONG;
-#endif /* defined ALL_STATE */
for (i = sp->typecnt - 1; i >= 0; --i) {
if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
continue;
for (j = sp->typecnt - 1; j >= 0; --j) {
if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
continue;
- newt = t + sp->ttis[j].tt_gmtoff -
- sp->ttis[i].tt_gmtoff;
- if ((*funcp)(&newt, offset, &mytm) == NULL)
+ if (ttunspecified(sp, j))
+ continue;
+ newt = (t + sp->ttis[j].tt_utoff
+ - sp->ttis[i].tt_utoff);
+ if (! funcp(sp, &newt, offset, &mytm))
continue;
if (tmcomp(&mytm, &yourtm) != 0)
continue;
@@ -1847,17 +2143,18 @@ label:
if ((newt < t) != (saved_seconds < 0))
return WRONG;
t = newt;
- if ((*funcp)(&t, offset, tmp))
- *okayp = TRUE;
+ if (funcp(sp, &t, offset, tmp))
+ *okayp = true;
return t;
}
static time_t
-time2(tmp, funcp, offset, okayp)
-struct tm * const tmp;
-struct tm * (* const funcp)(const time_t*, long, struct tm*);
-const long offset;
-int * const okayp;
+time2(struct tm * const tmp,
+ struct tm *(*funcp)(struct state const *, time_t const *,
+ int_fast32_t, struct tm *),
+ struct state const *sp,
+ const int_fast32_t offset,
+ bool *okayp)
{
time_t t;
@@ -1866,25 +2163,25 @@ int * const okayp;
** (in case tm_sec contains a value associated with a leap second).
** If that fails, try with normalization of seconds.
*/
- t = time2sub(tmp, funcp, offset, okayp, FALSE);
- return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE);
+ t = time2sub(tmp, funcp, sp, offset, okayp, false);
+ return *okayp ? t : time2sub(tmp, funcp, sp, offset, okayp, true);
}
static time_t
-time1(tmp, funcp, offset)
-struct tm * const tmp;
-struct tm * (* const funcp)(const time_t *, long, struct tm *);
-const long offset;
+time1(struct tm *const tmp,
+ struct tm *(*funcp)(struct state const *, time_t const *,
+ int_fast32_t, struct tm *),
+ struct state const *sp,
+ const int_fast32_t offset)
{
register time_t t;
- register const struct state * sp;
register int samei, otheri;
register int sameind, otherind;
register int i;
register int nseen;
- int seen[TZ_MAX_TYPES];
- int types[TZ_MAX_TYPES];
- int okay;
+ char seen[TZ_MAX_TYPES];
+ unsigned char types[TZ_MAX_TYPES];
+ bool okay;
if (tmp == NULL) {
errno = EINVAL;
@@ -1892,18 +2189,16 @@ const long offset;
}
if (tmp->tm_isdst > 1)
tmp->tm_isdst = 1;
- t = time2(tmp, funcp, offset, &okay);
-#ifdef PCTS
- /*
- ** PCTS code courtesy Grant Sullivan.
- */
+ t = time2(tmp, funcp, sp, offset, &okay);
if (okay)
return t;
if (tmp->tm_isdst < 0)
+#ifdef PCTS
+ /*
+ ** POSIX Conformance Test Suite code courtesy Grant Sullivan.
+ */
tmp->tm_isdst = 0; /* reset to std and try again */
-#endif /* defined PCTS */
-#ifndef PCTS
- if (okay || tmp->tm_isdst < 0)
+#else
return t;
#endif /* !defined PCTS */
/*
@@ -1912,17 +2207,14 @@ const long offset;
** We try to divine the type they started from and adjust to the
** type they need.
*/
- sp = (const struct state *) ((funcp == localsub) ? lclptr : gmtptr);
-#ifdef ALL_STATE
if (sp == NULL)
return WRONG;
-#endif /* defined ALL_STATE */
for (i = 0; i < sp->typecnt; ++i)
- seen[i] = FALSE;
+ seen[i] = false;
nseen = 0;
for (i = sp->timecnt - 1; i >= 0; --i)
- if (!seen[sp->types[i]]) {
- seen[sp->types[i]] = TRUE;
+ if (!seen[sp->types[i]] && !ttunspecified(sp, sp->types[i])) {
+ seen[sp->types[i]] = true;
types[nseen++] = sp->types[i];
}
for (sameind = 0; sameind < nseen; ++sameind) {
@@ -1933,33 +2225,60 @@ const long offset;
otheri = types[otherind];
if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
continue;
- tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
- sp->ttis[samei].tt_gmtoff;
+ tmp->tm_sec += (sp->ttis[otheri].tt_utoff
+ - sp->ttis[samei].tt_utoff);
tmp->tm_isdst = !tmp->tm_isdst;
- t = time2(tmp, funcp, offset, &okay);
+ t = time2(tmp, funcp, sp, offset, &okay);
if (okay)
return t;
- tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff -
- sp->ttis[samei].tt_gmtoff;
+ tmp->tm_sec -= (sp->ttis[otheri].tt_utoff
+ - sp->ttis[samei].tt_utoff);
tmp->tm_isdst = !tmp->tm_isdst;
}
}
return WRONG;
}
+static time_t
+mktime_tzname(struct state *sp, struct tm *tmp, bool setname)
+{
+ if (sp)
+ return time1(tmp, localsub, sp, setname);
+ else {
+ gmtcheck();
+ return time1(tmp, gmtsub, gmtptr, 0);
+ }
+}
+
+#if NETBSD_INSPIRED
+
time_t
-mktime(tmp)
-struct tm * const tmp;
+mktime_z(struct state *sp, struct tm *tmp)
{
- tzset();
- return time1(tmp, localsub, 0L);
+ return mktime_tzname(sp, tmp, false);
+}
+
+#endif
+
+time_t
+mktime(struct tm *tmp)
+{
+ time_t t;
+ int err = lock();
+ if (err) {
+ errno = err;
+ return -1;
+ }
+ tzset_unlocked();
+ t = mktime_tzname(lclptr, tmp, true);
+ unlock();
+ return t;
}
#ifdef STD_INSPIRED
time_t
-timelocal(tmp)
-struct tm * const tmp;
+timelocal(struct tm *tmp)
{
if (tmp != NULL)
tmp->tm_isdst = -1; /* in case it wasn't initialized */
@@ -1967,118 +2286,164 @@ struct tm * const tmp;
}
time_t
-timegm(tmp)
-struct tm * const tmp;
+timegm(struct tm *tmp)
{
- if (tmp != NULL)
- tmp->tm_isdst = 0;
- return time1(tmp, gmtsub, 0L);
+ return timeoff(tmp, 0);
}
time_t
-timeoff(tmp, offset)
-struct tm * const tmp;
-const long offset;
+timeoff(struct tm *tmp, long offset)
{
- if (tmp != NULL)
- tmp->tm_isdst = 0;
- return time1(tmp, gmtsub, offset);
+ if (tmp)
+ tmp->tm_isdst = 0;
+ gmtcheck();
+ return time1(tmp, gmtsub, gmtptr, offset);
}
#endif /* defined STD_INSPIRED */
-#ifdef CMUCS
-
-/*
-** The following is supplied for compatibility with
-** previous versions of the CMUCS runtime library.
-*/
-
-long
-gtime(tmp)
-struct tm * const tmp;
+static int_fast32_t
+leapcorr(struct state const *sp, time_t t)
{
- const time_t t = mktime(tmp);
+ register struct lsinfo const * lp;
+ register int i;
- if (t == WRONG)
- return -1;
- return t;
+ i = sp->leapcnt;
+ while (--i >= 0) {
+ lp = &sp->lsis[i];
+ if (t >= lp->ls_trans)
+ return lp->ls_corr;
+ }
+ return 0;
}
-#endif /* defined CMUCS */
-
/*
** XXX--is the below the right way to conditionalize??
*/
#ifdef STD_INSPIRED
+/* NETBSD_INSPIRED_EXTERN functions are exported to callers if
+ NETBSD_INSPIRED is defined, and are private otherwise. */
+# if NETBSD_INSPIRED
+# define NETBSD_INSPIRED_EXTERN
+# else
+# define NETBSD_INSPIRED_EXTERN static
+# endif
+
/*
-** IEEE Std 1003.1-1988 (POSIX) legislates that 536457599
+** IEEE Std 1003.1 (POSIX) says that 536457599
** shall correspond to "Wed Dec 31 23:59:59 UTC 1986", which
** is not the case if we are accounting for leap seconds.
** So, we provide the following conversion routines for use
** when exchanging timestamps with POSIX conforming systems.
*/
-static long
-leapcorr(timep)
-time_t * timep;
+NETBSD_INSPIRED_EXTERN time_t
+time2posix_z(struct state *sp, time_t t)
{
- register struct state * sp;
- register struct lsinfo * lp;
- register int i;
-
- sp = lclptr;
- i = sp->leapcnt;
- while (--i >= 0) {
- lp = &sp->lsis[i];
- if (*timep >= lp->ls_trans)
- return lp->ls_corr;
- }
- return 0;
+ return t - leapcorr(sp, t);
}
time_t
-time2posix(t)
-time_t t;
+time2posix(time_t t)
{
- tzset();
- return t - leapcorr(&t);
+ int err = lock();
+ if (err) {
+ errno = err;
+ return -1;
+ }
+ if (!lcl_is_set)
+ tzset_unlocked();
+ if (lclptr)
+ t = time2posix_z(lclptr, t);
+ unlock();
+ return t;
}
-time_t
-posix2time(t)
-time_t t;
+NETBSD_INSPIRED_EXTERN time_t
+posix2time_z(struct state *sp, time_t t)
{
time_t x;
time_t y;
-
- tzset();
/*
** For a positive leap second hit, the result
** is not unique. For a negative leap second
** hit, the corresponding time doesn't exist,
** so we return an adjacent second.
*/
- x = t + leapcorr(&t);
- y = x - leapcorr(&x);
+ x = t + leapcorr(sp, t);
+ y = x - leapcorr(sp, x);
if (y < t) {
do {
x++;
- y = x - leapcorr(&x);
+ y = x - leapcorr(sp, x);
} while (y < t);
- if (t != y)
- return x - 1;
+ x -= y != t;
} else if (y > t) {
do {
--x;
- y = x - leapcorr(&x);
+ y = x - leapcorr(sp, x);
} while (y > t);
- if (t != y)
- return x + 1;
+ x += y != t;
}
return x;
}
+time_t
+posix2time(time_t t)
+{
+ int err = lock();
+ if (err) {
+ errno = err;
+ return -1;
+ }
+ if (!lcl_is_set)
+ tzset_unlocked();
+ if (lclptr)
+ t = posix2time_z(lclptr, t);
+ unlock();
+ return t;
+}
+
#endif /* defined STD_INSPIRED */
+
+#if TZ_TIME_T
+
+# if !USG_COMPAT
+# define daylight 0
+# define timezone 0
+# endif
+# if !ALTZONE
+# define altzone 0
+# endif
+
+/* Convert from the underlying system's time_t to the ersatz time_tz,
+ which is called 'time_t' in this file. Typically, this merely
+ converts the time's integer width. On some platforms, the system
+ time is local time not UT, or uses some epoch other than the POSIX
+ epoch.
+
+ Although this code appears to define a function named 'time' that
+ returns time_t, the macros in private.h cause this code to actually
+ define a function named 'tz_time' that returns tz_time_t. The call
+ to sys_time invokes the underlying system's 'time' function. */
+
+time_t
+time(time_t *p)
+{
+ time_t r = sys_time(0);
+ if (r != (time_t) -1) {
+ int_fast32_t offset = EPOCH_LOCAL ? (daylight ? timezone : altzone) : 0;
+ if (increment_overflow32(&offset, -EPOCH_OFFSET)
+ || increment_overflow_time(&r, offset)) {
+ errno = EOVERFLOW;
+ r = -1;
+ }
+ }
+ if (p)
+ *p = r;
+ return r;
+}
+
+#endif
diff --git a/newctime.3 b/newctime.3
index a0239de5c0a4..866154986dab 100644
--- a/newctime.3
+++ b/newctime.3
@@ -1,43 +1,61 @@
.TH NEWCTIME 3
.SH NAME
-asctime, ctime, difftime, gmtime, localtime, mktime \- convert date and time to ASCII
+asctime, ctime, difftime, gmtime, localtime, mktime \- convert date and time
.SH SYNOPSIS
.nf
-.B extern char *tzname[2];
+.ie \n(.g .ds - \f(CW-\fP
+.el .ds - \-
+.B #include <time.h>
.PP
-.B void tzset()
+.BR "extern char *tzname[];" " /\(** (optional) \(**/"
.PP
-.B #include <sys/types.h>
+.B char *ctime(time_t const *clock);
.PP
-.B char *ctime(clock)
-.B const time_t *clock;
+.B char *ctime_r(time_t const *clock, char *buf);
.PP
-.B double difftime(time1, time0)
-.B time_t time1;
-.B time_t time0;
+.B double difftime(time_t time1, time_t time0);
.PP
-.B #include <time.h>
+.B char *asctime(struct tm const *tm);
+.PP
+.B "char *asctime_r(struct tm const *restrict tm,"
+.B " char *restrict result);"
+.PP
+.B struct tm *localtime(time_t const *clock);
+.PP
+.B "struct tm *localtime_r(time_t const *restrict clock,"
+.B " struct tm *restrict result);"
+.PP
+.B "struct tm *localtime_rz(timezone_t restrict zone,"
+.B " time_t const *restrict clock,"
+.B " struct tm *restrict result);"
.PP
-.B char *asctime(tm)
-.B const struct tm *tm;
+.B struct tm *gmtime(time_t const *clock);
.PP
-.B struct tm *localtime(clock)
-.B const time_t *clock;
+.B "struct tm *gmtime_r(time_t const *restrict clock,"
+.B " struct tm *restrict result);"
.PP
-.B struct tm *gmtime(clock)
-.B const time_t *clock;
+.B time_t mktime(struct tm *tm);
.PP
-.B time_t mktime(tm)
-.B struct tm *tm;
+.B "time_t mktime_z(timezone_t restrict zone,"
+.B " struct tm *restrict tm);"
.PP
-.B cc ... -ltz
+.B cc ... \*-ltz
.fi
.SH DESCRIPTION
-.I Ctime\^
+.ie '\(en'' .ds en \-
+.el .ds en \(en
+.ie '\(lq'' .ds lq \&"\"
+.el .ds lq \(lq\"
+.ie '\(rq'' .ds rq \&"\"
+.el .ds rq \(rq\"
+.de q
+\\$3\*(lq\\$1\*(rq\\$2
+..
+The
+.B ctime
+function
converts a long integer, pointed to by
.IR clock ,
-representing the time in seconds since
-00:00:00 UTC, 1970-01-01,
and returns a pointer to a
string of the form
.br
@@ -59,41 +77,66 @@ These unusual formats are designed to make it less likely that older
software that expects exactly 26 bytes of output will mistakenly output
misleading values for out-of-range years.
.PP
-.I Localtime\^
+The
+.BI * clock
+timestamp represents the time in seconds since 1970-01-01 00:00:00
+Coordinated Universal Time (UTC).
+The POSIX standard says that timestamps must be nonnegative
+and must ignore leap seconds.
+Many implementations extend POSIX by allowing negative timestamps,
+and can therefore represent timestamps that predate the
+introduction of UTC and are some other flavor of Universal Time (UT).
+Some implementations support leap seconds, in contradiction to POSIX.
+.PP
+The
+.B localtime
and
-.I gmtime\^
-return pointers to ``tm'' structures, described below.
-.I Localtime\^
+.B gmtime
+functions
+return pointers to
+.q "tm"
+structures, described below.
+The
+.B localtime
+function
corrects for the time zone and any time zone adjustments
(such as Daylight Saving Time in the United States).
-After filling in the ``tm'' structure,
-.I localtime
+After filling in the
+.q "tm"
+structure,
+.B localtime
sets the
.BR tm_isdst 'th
element of
.B tzname
-to a pointer to an
-ASCII string that's the time zone abbreviation to be used with
-.IR localtime 's
+to a pointer to a string that's the time zone abbreviation to be used with
+.BR localtime 's
return value.
.PP
-.I Gmtime\^
+The
+.B gmtime
+function
converts to Coordinated Universal Time.
.PP
-.I Asctime\^
+The
+.B asctime
+function
converts a time value contained in a
-``tm'' structure to a string,
+.q "tm"
+structure to a string,
as shown in the above example,
and returns a pointer to the string.
.PP
-.I Mktime\^
+The
+.B mktime
+function
converts the broken-down time,
expressed as local time,
in the structure pointed to by
.I tm
into a calendar time value with the same encoding as that of the values
returned by the
-.I time
+.B time
function.
The original values of the
.B tm_wday
@@ -105,16 +148,15 @@ to their normal ranges.
(A positive or zero value for
.B tm_isdst
causes
-.I mktime
-to presume initially that summer time (for example, Daylight Saving Time
-in the U.S.A.)
+.B mktime
+to presume initially that daylight saving time
respectively,
is or is not in effect for the specified time.
A negative value for
.B tm_isdst
causes the
-.I mktime
-function to attempt to divine whether summer time is in effect
+.B mktime
+function to attempt to divine whether daylight saving time is in effect
for the specified time; in this case it does not use a consistent
rule and may give a different answer when later
presented with the same argument.)
@@ -131,22 +173,58 @@ is not set until
and
.B tm_year
are determined.
-.I Mktime\^
+The
+.B mktime
+function
returns the specified calendar time;
If the calendar time cannot be represented,
-it returns
-.BR -1 .
+it returns \-1.
.PP
-.I Difftime\^
+The
+.B difftime
+function
returns the difference between two calendar times,
.RI ( time1
--
+\-
.IR time0 ),
expressed in seconds.
.PP
-Declarations of all the functions and externals, and the ``tm'' structure,
+The
+.BR ctime_r ,
+.BR localtime_r ,
+.BR gmtime_r ,
+and
+.B asctime_r
+functions
+are like their unsuffixed counterparts, except that they accept an
+additional argument specifying where to store the result if successful.
+.PP
+The
+.B localtime_rz
+and
+.B mktime_z
+functions
+are like their unsuffixed counterparts, except that they accept an
+extra initial
+.B zone
+argument specifying the timezone to be used for conversion.
+If
+.B zone
+is null, UT is used; otherwise,
+.B zone
+should be have been allocated by
+.B tzalloc
+and should not be freed until after all uses (e.g., by calls to
+.BR strftime )
+of the filled-in
+.B tm_zone
+fields.
+.PP
+Declarations of all the functions and externals, and the
+.q "tm"
+structure,
are in the
-.B <time.h>\^
+.B <time.h>
header file.
The structure (of type)
.B struct tm
@@ -154,53 +232,64 @@ includes the following fields:
.RS
.PP
.nf
-.ta .5i +\w'long tm_gmtoff;\0\0'u
- int tm_sec; /\(** seconds (0 - 60) \(**/
- int tm_min; /\(** minutes (0 - 59) \(**/
- int tm_hour; /\(** hours (0 - 23) \(**/
- int tm_mday; /\(** day of month (1 - 31) \(**/
- int tm_mon; /\(** month of year (0 - 11) \(**/
+.ta 2n +\w'long tm_gmtoff;nn'u
+ int tm_sec; /\(** seconds (0\*(en60) \(**/
+ int tm_min; /\(** minutes (0\*(en59) \(**/
+ int tm_hour; /\(** hours (0\*(en23) \(**/
+ int tm_mday; /\(** day of month (1\*(en31) \(**/
+ int tm_mon; /\(** month of year (0\*(en11) \(**/
int tm_year; /\(** year \- 1900 \(**/
int tm_wday; /\(** day of week (Sunday = 0) \(**/
- int tm_yday; /\(** day of year (0 - 365) \(**/
- int tm_isdst; /\(** is summer time in effect? \(**/
- char \(**tm_zone; /\(** abbreviation of timezone name \(**/
- long tm_gmtoff; /\(** offset from UTC in seconds \(**/
+ int tm_yday; /\(** day of year (0\*(en365) \(**/
+ int tm_isdst; /\(** is daylight saving time in effect? \(**/
+ char \(**tm_zone; /\(** time zone abbreviation (optional) \(**/
+ long tm_gmtoff; /\(** offset from UT in seconds (optional) \(**/
.fi
.RE
.PP
The
-.I tm_zone
+.B tm_isdst
+field
+is non-zero if daylight saving time is in effect.
+.PP
+The
+.B tm_gmtoff
+field
+is the offset (in seconds) of the time represented
+from UT, with positive values indicating east
+of the Prime Meridian.
+The field's name is derived from Greenwich Mean Time, a precursor of UT.
+.PP
+In
+.B "struct tm"
+the
+.B tm_zone
and
-.I tm_gmtoff
+.B tm_gmtoff
fields exist, and are filled in, only if arrangements to do
so were made when the library containing these functions was
created.
-There is no guarantee that these fields will continue to exist
-in this form in future releases of this code.
-.PP
-.I Tm_isdst\^
-is non-zero if summer time is in effect.
-.PP
-.I Tm_gmtoff
-is the offset (in seconds) of the time represented
-from UTC, with positive values indicating east
-of the Prime Meridian.
+Similarly, the
+.B tzname
+variable is optional; also, there is no guarantee that
+.B tzname
+will
+continue to exist in this form in future releases of this code.
.SH FILES
-.ta \w'/usr/local/etc/zoneinfo/posixrules\0\0'u
-/usr/local/etc/zoneinfo time zone information directory
+.ta \w'/usr/share/zoneinfo/posixrules\0\0'u
+/usr/share/zoneinfo timezone information directory
.br
-/usr/local/etc/zoneinfo/localtime local time zone file
+/usr/share/zoneinfo/localtime local timezone file
.br
-/usr/local/etc/zoneinfo/posixrules used with POSIX-style TZ's
+/usr/share/zoneinfo/posixrules used with POSIX-style TZ's
.br
-/usr/local/etc/zoneinfo/GMT for UTC leap seconds
+/usr/share/zoneinfo/GMT for UTC leap seconds
.sp
If
-.B /usr/local/etc/zoneinfo/GMT
+.B /usr/share/zoneinfo/GMT
is absent,
UTC leap seconds are loaded from
-.BR /usr/local/etc/zoneinfo/posixrules .
+.BR /usr/share/zoneinfo/posixrules .
.SH SEE ALSO
getenv(3),
newstrftime(3),
@@ -208,34 +297,48 @@ newtzset(3),
time(2),
tzfile(5)
.SH NOTES
-The return values point to static data;
-the data is overwritten by each call.
+The return values of
+.BR asctime ,
+.BR ctime ,
+.BR gmtime ,
+and
+.B localtime
+point to static data
+overwritten by each call.
The
+.B tzname
+variable (once set) and the
.B tm_zone
field of a returned
.B "struct tm"
-points to a static array of characters, which
-will also be overwritten at the next call
-(and by calls to
-.IR tzset ).
+both point to an array of characters that
+can be freed or overwritten by later calls to the functions
+.BR localtime ,
+.BR tzfree ,
+and
+.BR tzset ,
+if these functions affect the timezone information that specifies the
+abbreviation in question.
+The remaining functions and data are thread-safe.
.PP
-.I Asctime\^
+The
+.BR asctime ,
+.BR asctime_r ,
+.BR ctime ,
and
-.I ctime\^
+.B ctime_r
+functions
behave strangely for years before 1000 or after 9999.
The 1989 and 1999 editions of the C Standard say
that years from \-99 through 999 are converted without
extra spaces, but this conflicts with longstanding
tradition and with this implementation.
+The 2011 edition says that the behavior
+is undefined if the year is before 1000 or after 9999.
Traditional implementations of these two functions are
restricted to years in the range 1900 through 2099.
To avoid this portability mess, new programs should use
-.I strftime\^
+.B strftime
instead.
-.PP
-Avoid using out-of-range values with
-.I mktime
-when setting up lunch with promptness sticklers in Riyadh.
-.\" @(#)newctime.3 8.3
.\" This file is in the public domain, so clarified as of
.\" 2009-05-17 by Arthur David Olson.
diff --git a/newctime.3.txt b/newctime.3.txt
index ba311400474a..2076491d925e 100644
--- a/newctime.3.txt
+++ b/newctime.3.txt
@@ -1,149 +1,172 @@
-NAME
+NEWCTIME(3) Library Functions Manual NEWCTIME(3)
- asctime, ctime, difftime, gmtime, localtime, mktime -
- convert date and time to ASCII
+NAME
+ asctime, ctime, difftime, gmtime, localtime, mktime - convert date and
+ time
SYNOPSIS
- extern char *tzname[2];
+ #include <time.h>
+
+ extern char *tzname[]; /* (optional) */
+
+ char *ctime(time_t const *clock);
+
+ char *ctime_r(time_t const *clock, char *buf);
+
+ double difftime(time_t time1, time_t time0);
- void tzset()
+ char *asctime(struct tm const *tm);
- #include <sys/types.h>
+ char *asctime_r(struct tm const *restrict tm,
+ char *restrict result);
- char *ctime(clock)
- const time_t *clock;
+ struct tm *localtime(time_t const *clock);
- double difftime(time1, time0)
- time_t time1;
- time_t time0;
+ struct tm *localtime_r(time_t const *restrict clock,
+ struct tm *restrict result);
- #include <time.h>
+ struct tm *localtime_rz(timezone_t restrict zone,
+ time_t const *restrict clock,
+ struct tm *restrict result);
- char *asctime(tm)
- const struct tm *tm;
+ struct tm *gmtime(time_t const *clock);
- struct tm *localtime(clock)
- const time_t *clock;
+ struct tm *gmtime_r(time_t const *restrict clock,
+ struct tm *restrict result);
- struct tm *gmtime(clock)
- const time_t *clock;
+ time_t mktime(struct tm *tm);
- time_t mktime(tm)
- struct tm *tm;
+ time_t mktime_z(timezone_t restrict zone,
+ struct tm *restrict tm);
- cc ... -ltz
+ cc ... -ltz
DESCRIPTION
- Ctime converts a long integer, pointed to by clock,
- representing the time in seconds since 00:00:00 UTC,
- 1970-01-01, and returns a pointer to a string of the form
- Thu Nov 24 18:22:48 1986\n\0
- Years requiring fewer than four characters are padded with
- leading zeroes. For years longer than four characters, the
- string is of the form
- Thu Nov 24 18:22:48 81986\n\0
- with five spaces before the year. These unusual formats are
- designed to make it less likely that older software that
- expects exactly 26 bytes of output will mistakenly output
- misleading values for out-of-range years.
-
- Localtime and gmtime return pointers to ``tm'' structures,
- described below. Localtime corrects for the time zone and
- any time zone adjustments (such as Daylight Saving Time in
- the United States). After filling in the ``tm'' structure,
- localtime sets the tm_isdst'th element of tzname to a
- pointer to an ASCII string that's the time zone abbreviation
- to be used with localtime's return value.
-
- Gmtime converts to Coordinated Universal Time.
-
- Asctime converts a time value contained in a ``tm''
- structure to a string, as shown in the above example, and
- returns a pointer to the string.
-
- Mktime converts the broken-down time, expressed as local
- time, in the structure pointed to by tm into a calendar time
- value with the same encoding as that of the values returned
- by the time function. The original values of the tm_wday
- and tm_yday components of the structure are ignored, and the
- original values of the other components are not restricted
- to their normal ranges. (A positive or zero value for
- tm_isdst causes mktime to presume initially that summer time
- (for example, Daylight Saving Time in the U.S.A.)
- respectively, is or is not in effect for the specified time.
- A negative value for tm_isdst causes the mktime function to
- attempt to divine whether summer time is in effect for the
- specified time; in this case it does not use a consistent
- rule and may give a different answer when later presented
- with the same argument.) On successful completion, the
- values of the tm_wday and tm_yday components of the
- structure are set appropriately, and the other components
- are set to represent the specified calendar time, but with
- their values forced to their normal ranges; the final value
- of tm_mday is not set until tm_mon and tm_year are
- determined. Mktime returns the specified calendar time; If
- the calendar time cannot be represented, it returns -1.
-
- Difftime returns the difference between two calendar times,
- (time1 - time0), expressed in seconds.
-
- Declarations of all the functions and externals, and the
- ``tm'' structure, are in the <time.h> header file. The
- structure (of type) struct tm includes the following fields:
-
- int tm_sec; /* seconds (0 - 60) */
- int tm_min; /* minutes (0 - 59) */
- int tm_hour; /* hours (0 - 23) */
- int tm_mday; /* day of month (1 - 31) */
- int tm_mon; /* month of year (0 - 11) */
- int tm_year; /* year - 1900 */
- int tm_wday; /* day of week (Sunday = 0) */
- int tm_yday; /* day of year (0 - 365) */
- int tm_isdst; /* is summer time in effect? */
- char *tm_zone; /* abbreviation of timezone name */
- long tm_gmtoff; /* offset from UTC in seconds */
-
- The tm_zone and tm_gmtoff fields exist, and are filled in,
- only if arrangements to do so were made when the library
- containing these functions was created. There is no
- guarantee that these fields will continue to exist in this
- form in future releases of this code.
-
- Tm_isdst is non-zero if summer time is in effect.
-
- Tm_gmtoff is the offset (in seconds) of the time represented
- from UTC, with positive values indicating east of the Prime
- Meridian.
+ The ctime function converts a long integer, pointed to by clock, and
+ returns a pointer to a string of the form
+ Thu Nov 24 18:22:48 1986\n\0
+ Years requiring fewer than four characters are padded with leading
+ zeroes. For years longer than four characters, the string is of the
+ form
+ Thu Nov 24 18:22:48 81986\n\0
+ with five spaces before the year. These unusual formats are designed
+ to make it less likely that older software that expects exactly 26
+ bytes of output will mistakenly output misleading values for out-of-
+ range years.
+
+ The *clock timestamp represents the time in seconds since 1970-01-01
+ 00:00:00 Coordinated Universal Time (UTC). The POSIX standard says
+ that timestamps must be nonnegative and must ignore leap seconds. Many
+ implementations extend POSIX by allowing negative timestamps, and can
+ therefore represent timestamps that predate the introduction of UTC and
+ are some other flavor of Universal Time (UT). Some implementations
+ support leap seconds, in contradiction to POSIX.
+
+ The localtime and gmtime functions return pointers to "tm" structures,
+ described below. The localtime function corrects for the time zone and
+ any time zone adjustments (such as Daylight Saving Time in the United
+ States). After filling in the "tm" structure, localtime sets the
+ tm_isdst'th element of tzname to a pointer to a string that's the time
+ zone abbreviation to be used with localtime's return value.
+
+ The gmtime function converts to Coordinated Universal Time.
+
+ The asctime function converts a time value contained in a "tm"
+ structure to a string, as shown in the above example, and returns a
+ pointer to the string.
+
+ The mktime function converts the broken-down time, expressed as local
+ time, in the structure pointed to by tm into a calendar time value with
+ the same encoding as that of the values returned by the time function.
+ The original values of the tm_wday and tm_yday components of the
+ structure are ignored, and the original values of the other components
+ are not restricted to their normal ranges. (A positive or zero value
+ for tm_isdst causes mktime to presume initially that daylight saving
+ time respectively, is or is not in effect for the specified time. A
+ negative value for tm_isdst causes the mktime function to attempt to
+ divine whether daylight saving time is in effect for the specified
+ time; in this case it does not use a consistent rule and may give a
+ different answer when later presented with the same argument.) On
+ successful completion, the values of the tm_wday and tm_yday components
+ of the structure are set appropriately, and the other components are
+ set to represent the specified calendar time, but with their values
+ forced to their normal ranges; the final value of tm_mday is not set
+ until tm_mon and tm_year are determined. The mktime function returns
+ the specified calendar time; If the calendar time cannot be
+ represented, it returns -1.
+
+ The difftime function returns the difference between two calendar
+ times, (time1 - time0), expressed in seconds.
+
+ The ctime_r, localtime_r, gmtime_r, and asctime_r functions are like
+ their unsuffixed counterparts, except that they accept an additional
+ argument specifying where to store the result if successful.
+
+ The localtime_rz and mktime_z functions are like their unsuffixed
+ counterparts, except that they accept an extra initial zone argument
+ specifying the timezone to be used for conversion. If zone is null, UT
+ is used; otherwise, zone should be have been allocated by tzalloc and
+ should not be freed until after all uses (e.g., by calls to strftime)
+ of the filled-in tm_zone fields.
+
+ Declarations of all the functions and externals, and the "tm"
+ structure, are in the <time.h> header file. The structure (of type)
+ struct tm includes the following fields:
+
+ int tm_sec; /* seconds (0-60) */
+ int tm_min; /* minutes (0-59) */
+ int tm_hour; /* hours (0-23) */
+ int tm_mday; /* day of month (1-31) */
+ int tm_mon; /* month of year (0-11) */
+ int tm_year; /* year - 1900 */
+ int tm_wday; /* day of week (Sunday = 0) */
+ int tm_yday; /* day of year (0-365) */
+ int tm_isdst; /* is daylight saving time in effect? */
+ char *tm_zone; /* time zone abbreviation (optional) */
+ long tm_gmtoff; /* offset from UT in seconds (optional) */
+
+ The tm_isdst field is non-zero if daylight saving time is in effect.
+
+ The tm_gmtoff field is the offset (in seconds) of the time represented
+ from UT, with positive values indicating east of the Prime Meridian.
+ The field's name is derived from Greenwich Mean Time, a precursor of
+ UT.
+
+ In struct tm the tm_zone and tm_gmtoff fields exist, and are filled in,
+ only if arrangements to do so were made when the library containing
+ these functions was created. Similarly, the tzname variable is
+ optional; also, there is no guarantee that tzname will continue to
+ exist in this form in future releases of this code.
FILES
- /usr/local/etc/zoneinfo time zone information
- directory
- /usr/local/etc/zoneinfo/localtime local time zone file
- /usr/local/etc/zoneinfo/posixrules used with POSIX-style
- TZ's
- /usr/local/etc/zoneinfo/GMT for UTC leap seconds
+ /usr/share/zoneinfo timezone information directory
+ /usr/share/zoneinfo/localtime local timezone file
+ /usr/share/zoneinfo/posixrules used with POSIX-style TZ's
+ /usr/share/zoneinfo/GMT for UTC leap seconds
- If /usr/local/etc/zoneinfo/GMT is absent, UTC leap seconds
- are loaded from /usr/local/etc/zoneinfo/posixrules.
+ If /usr/share/zoneinfo/GMT is absent, UTC leap seconds are loaded from
+ /usr/share/zoneinfo/posixrules.
SEE ALSO
- getenv(3), newstrftime(3), newtzset(3), time(2), tzfile(5)
+ getenv(3), newstrftime(3), newtzset(3), time(2), tzfile(5)
NOTES
- The return values point to static data; the data is
- overwritten by each call. The tm_zone field of a returned
- struct tm points to a static array of characters, which will
- also be overwritten at the next call (and by calls to
- tzset).
-
- Asctime and ctime behave strangely for years before 1000 or
- after 9999. The 1989 and 1999 editions of the C Standard
- say that years from -99 through 999 are converted without
- extra spaces, but this conflicts with longstanding tradition
- and with this implementation. Traditional implementations
- of these two functions are restricted to years in the range
- 1900 through 2099. To avoid this portability mess, new
- programs should use strftime instead.
-
- Avoid using out-of-range values with mktime when setting up
- lunch with promptness sticklers in Riyadh.
+ The return values of asctime, ctime, gmtime, and localtime point to
+ static data overwritten by each call. The tzname variable (once set)
+ and the tm_zone field of a returned struct tm both point to an array of
+ characters that can be freed or overwritten by later calls to the
+ functions localtime, tzfree, and tzset, if these functions affect the
+ timezone information that specifies the abbreviation in question. The
+ remaining functions and data are thread-safe.
+
+ The asctime, asctime_r, ctime, and ctime_r functions behave strangely
+ for years before 1000 or after 9999. The 1989 and 1999 editions of the
+ C Standard say that years from -99 through 999 are converted without
+ extra spaces, but this conflicts with longstanding tradition and with
+ this implementation. The 2011 edition says that the behavior is
+ undefined if the year is before 1000 or after 9999. Traditional
+ implementations of these two functions are restricted to years in the
+ range 1900 through 2099. To avoid this portability mess, new programs
+ should use strftime instead.
+
+ NEWCTIME(3)
diff --git a/newstrftime.3 b/newstrftime.3
index cd70974b8e15..d68bc33783a1 100644
--- a/newstrftime.3
+++ b/newstrftime.3
@@ -1,5 +1,7 @@
-.\" Based on the UCB file whose copyright information appears below.
-.\" Copyright (c) 1989, 1991 The Regents of the University of California.
+.\" strftime man page
+.\"
+.\" Based on the UCB file whose corrected copyright information appears below.
+.\" Copyright 1989, 1991 The Regents of the University of California.
.\" All rights reserved.
.\"
.\" This code is derived from software contributed to Berkeley by
@@ -14,15 +16,11 @@
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\" must display the following acknowledgement:
-.\" This product includes software developed by the University of
-.\" California, Berkeley and its contributors.
-.\" 4. Neither the name of the University nor the names of its contributors
+.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
@@ -42,49 +40,51 @@
strftime \- format date and time
.SH SYNOPSIS
.nf
-.B #include <sys/types.h>
+.ie \n(.g .ds - \f(CW-\fP
+.el .ds - \-
.B #include <time.h>
.PP
-.B size_t strftime(buf, maxsize, format, timeptr)
-.B char *buf;
-.B size_t maxsize;
-.B const char *format;
-.B const struct tm *timeptr
+.B "size_t strftime(char *restrict buf, size_t maxsize,"
+.B " char const *restrict format, struct tm const *restrict timeptr);"
.PP
-.B cc ... -ltz
+.B cc ... \-ltz
.fi
.SH DESCRIPTION
+.ie '\(lq'' .ds lq \&"\"
+.el .ds lq \(lq\"
+.ie '\(rq'' .ds rq \&"\"
+.el .ds rq \(rq\"
+.de c
+.ie \n(.g \f(CW\\$1\fP\\$2
+.el \\$1\\$2
+..
+.de q
+\\$3\*(lq\\$1\*(rq\\$2
+..
The
-.I strftime\^
+.B strftime
function formats the information from
-.I timeptr\^
-into the buffer
-.I buf\^
+.I timeptr
+into the array pointed to by
+.I buf
according to the string pointed to by
-.IR format\^ .
+.IR format .
.PP
The
-.I format\^
+.I format
string consists of zero or more conversion specifications and
ordinary characters.
-All ordinary characters are copied directly into the buffer.
+All ordinary characters are copied directly into the array.
A conversion specification consists of a percent sign
.Ql %
and one other character.
.PP
No more than
-.I maxsize\^
-characters are be placed into the array.
-If the total number of resulting characters, including the terminating
-null character, is not more than
-.IR maxsize\^ ,
-.I strftime\^
-returns the number of characters in the array, not counting the
-terminating null.
-Otherwise, zero is returned.
+.I maxsize
+bytes are placed into the array.
.PP
Each conversion specification is replaced by the characters as
-follows which are then copied into the buffer.
+follows which are then copied into the array.
.TP
%A
is replaced by the locale's full weekday name.
@@ -100,99 +100,122 @@ is replaced by the locale's abbreviated month name.
.TP
%C
is replaced by the century (a year divided by 100 and truncated to an integer)
-as a decimal number (00-99).
+as a decimal number [00,99].
.TP
%c
is replaced by the locale's appropriate date and time representation.
.TP
%D
-is replaced by the date in the format %m/%d/%y.
+is equivalent to
+.c %m/%d/%y .
.TP
%d
-is replaced by the day of the month as a decimal number (01-31).
+is replaced by the day of the month as a decimal number [01,31].
.TP
%e
-is replaced by the day of month as a decimal number (1-31);
+is replaced by the day of month as a decimal number [1,31];
single digits are preceded by a blank.
.TP
%F
-is replaced by the date in the format %Y-%m-%d.
+is equivalent to
+.c %Y-%m-%d
+(the ISO 8601 date format).
.TP
%G
is replaced by the ISO 8601 year with century as a decimal number.
+See also the
+.c %V
+conversion specification.
.TP
%g
-is replaced by the ISO 8601 year without century as a decimal number (00-99).
+is replaced by the ISO 8601 year without century as a decimal number [00,99].
+This is the year that includes the greater part of the week.
+(Monday as the first day of a week).
+See also the
+.c %V
+conversion specification.
.TP
%H
-is replaced by the hour (24-hour clock) as a decimal number (00-23).
+is replaced by the hour (24-hour clock) as a decimal number [00,23].
.TP
%I
-is replaced by the hour (12-hour clock) as a decimal number (01-12).
+is replaced by the hour (12-hour clock) as a decimal number [01,12].
.TP
%j
-is replaced by the day of the year as a decimal number (001-366).
+is replaced by the day of the year as a decimal number [001,366].
.TP
%k
-is replaced by the hour (24-hour clock) as a decimal number (0-23);
+is replaced by the hour (24-hour clock) as a decimal number [0,23];
single digits are preceded by a blank.
.TP
%l
-is replaced by the hour (12-hour clock) as a decimal number (1-12);
+is replaced by the hour (12-hour clock) as a decimal number [1,12];
single digits are preceded by a blank.
.TP
%M
-is replaced by the minute as a decimal number (00-59).
+is replaced by the minute as a decimal number [00,59].
.TP
%m
-is replaced by the month as a decimal number (01-12).
+is replaced by the month as a decimal number [01,12].
.TP
%n
is replaced by a newline.
.TP
%p
-is replaced by the locale's equivalent of either AM or PM.
+is replaced by the locale's equivalent of either
+.q AM
+or
+.q PM .
.TP
%R
-is replaced by the time in the format %H:%M.
+is replaced by the time in the format
+.c %H:%M .
.TP
%r
is replaced by the locale's representation of 12-hour clock time
using AM/PM notation.
.TP
%S
-is replaced by the second as a decimal number (00-60).
+is replaced by the second as a decimal number [00,60].
+The range of
+seconds is [00,60] instead of [00,59] to allow for the periodic occurrence
+of leap seconds.
.TP
%s
-is replaced by the number of seconds since the Epoch, UTC (see mktime(3)).
+is replaced by the number of seconds since the Epoch (see
+.BR ctime (3)).
.TP
%T
-is replaced by the time in the format %H:%M:%S.
+is replaced by the time in the format
+.c %H:%M:%S .
.TP
%t
is replaced by a tab.
.TP
%U
is replaced by the week number of the year (Sunday as the first day of
-the week) as a decimal number (00-53).
+the week) as a decimal number [00,53].
.TP
%u
is replaced by the weekday (Monday as the first day of the week)
-as a decimal number (1-7).
+as a decimal number [1,7].
.TP
%V
is replaced by the week number of the year (Monday as the first day of
-the week) as a decimal number (01-53). If the week containing January
+the week) as a decimal number [01,53]. If the week containing January
1 has four or more days in the new year, then it is week 1; otherwise
it is week 53 of the previous year, and the next week is week 1.
+The year is given by the
+.c %G
+conversion specification.
.TP
%W
is replaced by the week number of the year (Monday as the first day of
-the week) as a decimal number (00-53).
+the week) as a decimal number [00,53].
.TP
%w
is replaced by the weekday (Sunday as the first day of the week)
-as a decimal number (0-6).
+as a decimal number [0,6].
.TP
%X
is replaced by the locale's appropriate time representation.
@@ -204,22 +227,58 @@ is replaced by the locale's appropriate date representation.
is replaced by the year with century as a decimal number.
.TP
%y
-is replaced by the year without century as a decimal number (00-99).
+is replaced by the year without century as a decimal number [00,99].
.TP
%Z
-is replaced by the time zone name,
+is replaced by the time zone abbreviation,
or by the empty string if this is not determinable.
.TP
%z
-is replaced by the offset from UTC in the format +HHMM or -HHMM as appropriate,
+is replaced by the offset from the Prime Meridian
+in the format +HHMM or \*-HHMM (ISO 8601) as appropriate,
with positive values representing locations east of Greenwich,
or by the empty string if this is not determinable.
+The numeric time zone abbreviation \*-0000 is used when the time is
+Universal Time
+but local time is indeterminate; by convention this is used for
+locations while uninhabited, and corresponds to a zero offset when the
+time zone abbreviation begins with
+.q "\*-" .
.TP
%%
is replaced by a single %.
.TP
%+
-is replaced by the date and time in date(1) format.
+is replaced by the locale's date and time in
+.BR date (1)
+format.
+.SH "RETURN VALUE"
+If the conversion is successful,
+.B strftime
+returns the number of bytes placed into the array, not counting the
+terminating NUL;
+.B errno
+is unchanged if the returned value is zero.
+Otherwise,
+.B errno
+is set to indicate the error, zero is returned,
+and the array contents are unspecified.
+.SH ERRORS
+This function fails if:
+.TP
+[ERANGE]
+The total number of resulting bytes, including the terminating
+NUL character, is more than
+.IR maxsize .
+.PP
+This function may fail if:
+.TP
+[EOVERFLOW]
+The format includes an
+.c %s
+conversion and the number of seconds since the Epoch cannot be represented
+in a
+.c time_t .
.SH SEE ALSO
date(1),
getenv(3),
@@ -227,6 +286,5 @@ newctime(3),
newtzset(3),
time(2),
tzfile(5)
-.\" @(#)newstrftime.3 8.2
-.\" This file is in the public domain, so clarified as of
-.\" 2009-05-17 by Arthur David Olson.
+.SH BUGS
+There is no conversion specification for the phase of the moon.
diff --git a/newstrftime.3.txt b/newstrftime.3.txt
index ea210a869f4a..37329d91dbc6 100644
--- a/newstrftime.3.txt
+++ b/newstrftime.3.txt
@@ -1,149 +1,169 @@
-NAME
+NEWSTRFTIME(3) Library Functions Manual NEWSTRFTIME(3)
- strftime - format date and time
+NAME
+ strftime - format date and time
SYNOPSIS
- #include <sys/types.h>
- #include <time.h>
+ #include <time.h>
- size_t strftime(buf, maxsize, format, timeptr)
- char *buf;
- size_t maxsize;
- const char *format;
- const struct tm *timeptr
+ size_t strftime(char *restrict buf, size_t maxsize,
+ char const *restrict format, struct tm const *restrict timeptr);
- cc ... -ltz
+ cc ... -ltz
DESCRIPTION
- The strftime function formats the information from timeptr
- into the buffer buf according to the string pointed to by
- format.
+ The strftime function formats the information from timeptr into the
+ array pointed to by buf according to the string pointed to by format.
+
+ The format string consists of zero or more conversion specifications
+ and ordinary characters. All ordinary characters are copied directly
+ into the array. A conversion specification consists of a percent sign
+ and one other character.
+
+ No more than maxsize bytes are placed into the array.
+
+ Each conversion specification is replaced by the characters as follows
+ which are then copied into the array.
+
+ %A is replaced by the locale's full weekday name.
- The format string consists of zero or more conversion
- specifications and ordinary characters. All ordinary
- characters are copied directly into the buffer. A
- conversion specification consists of a percent sign and one
- other character.
+ %a is replaced by the locale's abbreviated weekday name.
- No more than maxsize characters are be placed into the
- array. If the total number of resulting characters,
- including the terminating null character, is not more than
- maxsize, strftime returns the number of characters in the
- array, not counting the terminating null. Otherwise, zero
- is returned.
+ %B is replaced by the locale's full month name.
- Each conversion specification is replaced by the characters
- as follows which are then copied into the buffer.
+ %b or %h
+ is replaced by the locale's abbreviated month name.
- %A is replaced by the locale's full weekday name.
+ %C is replaced by the century (a year divided by 100 and truncated
+ to an integer) as a decimal number [00,99].
- %a is replaced by the locale's abbreviated weekday name.
+ %c is replaced by the locale's appropriate date and time
+ representation.
- %B is replaced by the locale's full month name.
+ %D is equivalent to %m/%d/%y.
- %b or %h
- is replaced by the locale's abbreviated month name.
+ %d is replaced by the day of the month as a decimal number [01,31].
- %C is replaced by the century (a year divided by 100 and
- truncated to an integer) as a decimal number (00-99).
+ %e is replaced by the day of month as a decimal number [1,31];
+ single digits are preceded by a blank.
- %c is replaced by the locale's appropriate date and time
- representation.
+ %F is equivalent to %Y-%m-%d (the ISO 8601 date format).
- %D is replaced by the date in the format %m/%d/%y.
+ %G is replaced by the ISO 8601 year with century as a decimal
+ number. See also the %V conversion specification.
- %d is replaced by the day of the month as a decimal number
- (01-31).
+ %g is replaced by the ISO 8601 year without century as a decimal
+ number [00,99]. This is the year that includes the greater part
+ of the week. (Monday as the first day of a week). See also the
+ %V conversion specification.
- %e is replaced by the day of month as a decimal number
- (1-31); single digits are preceded by a blank.
- %F is replaced by the date in the format %Y-%m-%d.
+ %H is replaced by the hour (24-hour clock) as a decimal number
+ [00,23].
- %G is replaced by the ISO 8601 year with century as a
- decimal number.
+ %I is replaced by the hour (12-hour clock) as a decimal number
+ [01,12].
- %g is replaced by the ISO 8601 year without century as a
- decimal number (00-99).
- %H is replaced by the hour (24-hour clock) as a decimal
- number (00-23).
+ %j is replaced by the day of the year as a decimal number
+ [001,366].
- %I is replaced by the hour (12-hour clock) as a decimal
- number (01-12).
+ %k is replaced by the hour (24-hour clock) as a decimal number
+ [0,23]; single digits are preceded by a blank.
- %j is replaced by the day of the year as a decimal number
- (001-366).
+ %l is replaced by the hour (12-hour clock) as a decimal number
+ [1,12]; single digits are preceded by a blank.
- %k is replaced by the hour (24-hour clock) as a decimal
- number (0-23); single digits are preceded by a blank.
+ %M is replaced by the minute as a decimal number [00,59].
- %l is replaced by the hour (12-hour clock) as a decimal
- number (1-12); single digits are preceded by a blank.
+ %m is replaced by the month as a decimal number [01,12].
- %M is replaced by the minute as a decimal number (00-59).
+ %n is replaced by a newline.
- %m is replaced by the month as a decimal number (01-12).
+ %p is replaced by the locale's equivalent of either "AM" or "PM".
- %n is replaced by a newline.
+ %R is replaced by the time in the format %H:%M.
- %p is replaced by the locale's equivalent of either AM or
- PM.
+ %r is replaced by the locale's representation of 12-hour clock time
+ using AM/PM notation.
- %R is replaced by the time in the format %H:%M.
+ %S is replaced by the second as a decimal number [00,60]. The
+ range of seconds is [00,60] instead of [00,59] to allow for the
+ periodic occurrence of leap seconds.
- %r is replaced by the locale's representation of 12-hour
- clock time using AM/PM notation.
+ %s is replaced by the number of seconds since the Epoch (see
+ ctime(3)).
- %S is replaced by the second as a decimal number (00-60).
+ %T is replaced by the time in the format %H:%M:%S.
- %s is replaced by the number of seconds since the Epoch,
- UTC (see mktime(3)).
+ %t is replaced by a tab.
- %T is replaced by the time in the format %H:%M:%S.
+ %U is replaced by the week number of the year (Sunday as the first
+ day of the week) as a decimal number [00,53].
- %t is replaced by a tab.
+ %u is replaced by the weekday (Monday as the first day of the week)
+ as a decimal number [1,7].
- %U is replaced by the week number of the year (Sunday as
- the first day of the week) as a decimal number (00-53).
+ %V is replaced by the week number of the year (Monday as the first
+ day of the week) as a decimal number [01,53]. If the week
+ containing January 1 has four or more days in the new year, then
+ it is week 1; otherwise it is week 53 of the previous year, and
+ the next week is week 1. The year is given by the %G conversion
+ specification.
- %u is replaced by the weekday (Monday as the first day of
- the week) as a decimal number (1-7).
+ %W is replaced by the week number of the year (Monday as the first
+ day of the week) as a decimal number [00,53].
- %V is replaced by the week number of the year (Monday as
- the first day of the week) as a decimal number (01-53).
- If the week containing January 1 has four or more days
- in the new year, then it is week 1; otherwise it is
- week 53 of the previous year, and the next week is week
- 1.
+ %w is replaced by the weekday (Sunday as the first day of the week)
+ as a decimal number [0,6].
- %W is replaced by the week number of the year (Monday as
- the first day of the week) as a decimal number (00-53).
+ %X is replaced by the locale's appropriate time representation.
- %w is replaced by the weekday (Sunday as the first day of
- the week) as a decimal number (0-6).
+ %x is replaced by the locale's appropriate date representation.
- %X is replaced by the locale's appropriate time
- representation.
- %x is replaced by the locale's appropriate date
- representation.
+ %Y is replaced by the year with century as a decimal number.
- %Y is replaced by the year with century as a decimal
- number.
+ %y is replaced by the year without century as a decimal number
+ [00,99].
- %y is replaced by the year without century as a decimal
- number (00-99).
+ %Z is replaced by the time zone abbreviation, or by the empty
+ string if this is not determinable.
- %Z is replaced by the time zone name, or by the empty
- string if this is not determinable.
+ %z is replaced by the offset from the Prime Meridian in the format
+ +HHMM or -HHMM (ISO 8601) as appropriate, with positive values
+ representing locations east of Greenwich, or by the empty string
+ if this is not determinable. The numeric time zone abbreviation
+ -0000 is used when the time is Universal Time but local time is
+ indeterminate; by convention this is used for locations while
+ uninhabited, and corresponds to a zero offset when the time zone
+ abbreviation begins with "-".
- %z is replaced by the offset from UTC in the format +HHMM
- or -HHMM as appropriate, with positive values
- representing locations east of Greenwich, or by the
- empty string if this is not determinable.
+ %% is replaced by a single %.
- %% is replaced by a single %.
+ %+ is replaced by the locale's date and time in date(1) format.
- %+ is replaced by the date and time in date(1) format.
+RETURN VALUE
+ If the conversion is successful, strftime returns the number of bytes
+ placed into the array, not counting the terminating NUL; errno is
+ unchanged if the returned value is zero. Otherwise, errno is set to
+ indicate the error, zero is returned, and the array contents are
+ unspecified.
+
+ERRORS
+ This function fails if:
+
+ [ERANGE]
+ The total number of resulting bytes, including the terminating
+ NUL character, is more than maxsize.
+
+ This function may fail if:
+
+ [EOVERFLOW]
+ The format includes an %s conversion and the number of seconds
+ since the Epoch cannot be represented in a time_t.
SEE ALSO
- date(1), getenv(3), newctime(3), newtzset(3), time(2),
- tzfile(5)
+ date(1), getenv(3), newctime(3), newtzset(3), time(2), tzfile(5)
+
+BUGS
+ There is no conversion specification for the phase of the moon.
+
+ NEWSTRFTIME(3)
diff --git a/newtzset.3 b/newtzset.3
index 07c5e0c605a7..8aaa0ff41732 100644
--- a/newtzset.3
+++ b/newtzset.3
@@ -3,33 +3,89 @@
tzset \- initialize time conversion information
.SH SYNOPSIS
.nf
-.B void tzset()
+.ie \n(.g .ds - \f(CW-\fP
+.el .ds - \-
+.B #include <time.h>
.PP
-.B cc ... -ltz
+.B timezone_t tzalloc(char const *TZ);
+.PP
+.B void tzfree(timezone_t tz);
+.PP
+.B void tzset(void);
+.PP
+.B cc ... \*-ltz
.fi
.SH DESCRIPTION
-.I Tzset
-uses the value of the environment variable
+.ie '\(en'' .ds en \-
+.el .ds en \(en
+.ie '\(lq'' .ds lq \&"\"
+.el .ds lq \(lq\"
+.ie '\(rq'' .ds rq \&"\"
+.el .ds rq \(rq\"
+.de q
+\\$3\*(lq\\$1\*(rq\\$2
+..
+The
+.B tzalloc
+function
+allocates and returns a timezone object described by
+.BR TZ .
+If
.B TZ
-to set time conversion information used by
-.IR localtime .
+is not a valid timezone description, or if the object cannot be allocated,
+.B tzalloc
+returns a null pointer and sets
+.BR errno .
+.PP
+The
+.B tzfree
+function
+frees a timezone object
+.BR tz ,
+which should have been successfully allocated by
+.BR tzalloc .
+This invalidates any
+.B tm_zone
+pointers that
+.B tz
+was used to set.
+.PP
+The
+.B tzset
+function
+acts like
+.BR tzalloc(getenv("TZ")) ,
+except it saves any resulting timezone object into internal
+storage that is accessed by
+.BR localtime ,
+.BR localtime_r ,
+and
+.BR mktime .
+The anonymous shared timezone object is freed by the next call to
+.BR tzset .
+If the implied call to
+.B tzalloc
+fails,
+.B tzset
+falls back on Universal Time (UT).
+.PP
If
.B TZ
-does not appear in the environment,
-the best available approximation to local wall clock time, as specified
-by the
-.IR tzfile (5)-format
+is null, the best available approximation to local (wall
+clock) time, as specified by the
+.BR tzfile (5)-format
file
.B localtime
-in the system time conversion information directory, is used by
-.IR localtime .
+in the system time conversion information directory, is used.
If
.B TZ
-appears in the environment but its value is a null string,
-Coordinated Universal Time (UTC) is used (without leap second
-correction). If
+is the empty string,
+UT is used, with the abbreviation "UTC"
+and without leap second correction; please see
+.BR newctime (3)
+for more about UT, UTC, and leap seconds. If
.B TZ
-appears in the environment and its value is not a null string:
+is nonnull and nonempty:
.IP
if the value begins with a colon, it is used as a pathname of a file
from which to read the time conversion information;
@@ -46,7 +102,7 @@ it is used as an absolute pathname; otherwise,
it is used as a pathname relative to a system time conversion information
directory.
The file must be in the format specified in
-.IR tzfile (5).
+.BR tzfile (5).
.PP
When
.B TZ
@@ -61,23 +117,31 @@ Where:
.IR std " and " dst
Three or more bytes that are the designation for the standard
.RI ( std )
-or summer
-.RI ( dst )
+or the alternative
+.RI ( dst ,
+such as daylight saving time)
time zone. Only
.I std
is required; if
.I dst
-is missing, then summer time does not apply in this locale.
+is missing, then daylight saving time does not apply in this locale.
Upper- and lowercase letters are explicitly allowed. Any characters
except a leading colon
.RB ( : ),
digits, comma
.RB ( , ),
-minus
-.RB ( \(mi ),
-plus
-.RB ( \(pl ),
-and ASCII NUL are allowed.
+ASCII minus
+.RB ( \*- ),
+ASCII plus
+.RB ( + ),
+and NUL bytes are allowed.
+Alternatively, a designation can be surrounded by angle brackets
+.B <
+and
+.BR > ;
+in this case, the designation can contain any characters other than
+.B >
+and NUL.
.TP
.I offset
Indicates the value one must add to the local time to arrive at
@@ -103,17 +167,17 @@ is required. If no
.I offset
follows
.IR dst ,
-summer time is assumed to be one hour ahead of standard time. One or
+daylight saving time is assumed to be one hour ahead of standard time. One or
more digits may be used; the value is always interpreted as a decimal
number. The hour must be between zero and 24, and the minutes (and
-seconds) \(em if present \(em between zero and 59. If preceded by a
-.RB `` \(mi '',
+seconds) \*(en if present \*(en between zero and 59. If preceded by a
+.q "\*-" ,
the time zone shall be east of the Prime Meridian; otherwise it shall be
west (which may be indicated by an optional preceding
-.RB `` \(pl '').
+.q "+" .
.TP
.I rule
-Indicates when to change to and back from summer time. The
+Indicates when to change to and back from daylight saving time. The
.I rule
has the form:
.RS
@@ -123,13 +187,17 @@ has the form:
.IP
where the first
.I date
-describes when the change from standard to summer time occurs and the
+describes when the change from standard to daylight saving time occurs and the
second
.I date
describes when the change back happens. Each
.I time
field describes when, in current local time, the change to the other
time is made.
+As an extension to POSIX, daylight saving is assumed to be in effect
+all year if it begins January 1 at 00:00 and ends December 31 at
+24:00 plus the difference between daylight saving and standard time,
+leaving no room for standard time in the calendar.
.IP
The format of
.I date
@@ -140,8 +208,8 @@ is one of the following:
The Julian day
.I n
.RI "(1\ \(<=" "\ n\ " "\(<=\ 365).
-Leap days are not counted; that is, in all years \(em including leap
-years \(em February 28 is day 59 and March 1 is day 60. It is
+Leap days are not counted; that is, in all years \*(en including leap
+years \*(en February 28 is day 59 and March 1 is day 60. It is
impossible to explicitly refer to the occasional February 29.
.TP
.I n
@@ -161,10 +229,8 @@ of month
of the year
.RI "(1\ \(<=" "\ n\ " "\(<=\ 5,
.RI "1\ \(<=" "\ m\ " "\(<=\ 12,
-where week 5 means ``the last
-.I d
-day in month
-.IR m ''
+where week 5 means
+.q "the last \fId\fP day in month \fIm\fP"
which may occur in either the fourth or the fifth week). Week 1 is the
first week in which the
.IR d' th
@@ -175,27 +241,80 @@ The
.I time
has the same format as
.I offset
-except that no leading sign
-.RB (`` \(mi ''
+except that POSIX does not allow a leading sign (\c
+.q "\*-"
or
-.RB `` \(pl '')
-is allowed. The default, if
+.q "+" ).
+As an extension to POSIX, the hours part of
+.I time
+can range from \-167 through 167; this allows for unusual rules such
+as
+.q "the Saturday before the first Sunday of March" .
+The default, if
.I time
is not given, is
.BR 02:00:00 .
.RE
.LP
+Here are some examples of
+.B TZ
+values that directly specify the timezone; they use some of the
+extensions to POSIX.
+.TP
+.B EST5
+stands for US Eastern Standard
+Time (EST), 5 hours behind UT, without daylight saving.
+.TP
+.B <+12>\*-12<+13>,M11.1.0,M1.2.1/147
+stands for Fiji time, 12 hours ahead
+of UT, springing forward on November's first Sunday at 02:00, and
+falling back on January's second Monday at 147:00 (i.e., 03:00 on the
+first Sunday on or after January 14). The abbreviations for standard
+and daylight saving time are
+.q "+12"
+and
+.q "+13".
+.TP
+.B IST\*-2IDT,M3.4.4/26,M10.5.0
+stands for Israel Standard Time (IST) and Israel Daylight Time (IDT),
+2 hours ahead of UT, springing forward on March's fourth
+Thursday at 26:00 (i.e., 02:00 on the first Friday on or after March
+23), and falling back on October's last Sunday at 02:00.
+.TP
+.B <\*-04>4<\*-03>,J1/0,J365/25
+stands for permanent daylight saving time, 3 hours behind UT with
+abbreviation
+.q "\*-03".
+There is a dummy fall-back transition on December 31 at 25:00 daylight
+saving time (i.e., 24:00 standard time, equivalent to January 1 at
+00:00 standard time), and a simultaneous spring-forward transition on
+January 1 at 00:00 standard time, so daylight saving time is in effect
+all year and the initial
+.B <\*-04>
+is a placeholder.
+.TP
+.B <\*-03>3<\*-02>,M3.5.0/\*-2,M10.5.0/\*-1
+stands for time in western Greenland, 3 hours behind UT, where clocks
+follow the EU rules of
+springing forward on March's last Sunday at 01:00 UT (\-02:00 local
+time, i.e., 22:00 the previous day) and falling back on October's last
+Sunday at 01:00 UT (\-01:00 local time, i.e., 23:00 the previous day).
+The abbreviations for standard and daylight saving time are
+.q "\*-03"
+and
+.q "\*-02".
+.PP
If no
.I rule
is present in
.BR TZ ,
the rules specified
by the
-.IR tzfile (5)-format
+.BR tzfile (5)-format
file
.B posixrules
in the system time conversion information directory are used, with the
-standard and summer time offsets from UTC replaced by those specified by
+standard and daylight saving time offsets from UT replaced by those specified by
the
.I offset
values in
@@ -206,34 +325,26 @@ For compatibility with System V Release 3.1, a semicolon
may be used to separate the
.I rule
from the rest of the specification.
-.PP
-If the
-.B TZ
-environment variable does not specify a
-.IR tzfile (5)-format
-and cannot be interpreted as a direct specification,
-UTC is used.
.SH FILES
-.ta \w'/usr/local/etc/zoneinfo/posixrules\0\0'u
-/usr/local/etc/zoneinfo time zone information directory
+.ta \w'/usr/share/zoneinfo/posixrules\0\0'u
+/usr/share/zoneinfo timezone information directory
.br
-/usr/local/etc/zoneinfo/localtime local time zone file
+/usr/share/zoneinfo/localtime local timezone file
.br
-/usr/local/etc/zoneinfo/posixrules used with POSIX-style TZ's
+/usr/share/zoneinfo/posixrules used with POSIX-style TZ's
.br
-/usr/local/etc/zoneinfo/GMT for UTC leap seconds
+/usr/share/zoneinfo/GMT for UTC leap seconds
.sp
If
-.B /usr/local/etc/zoneinfo/GMT
+.B /usr/share/zoneinfo/GMT
is absent,
UTC leap seconds are loaded from
-.BR /usr/local/etc/zoneinfo/posixrules .
+.BR /usr/share/zoneinfo/posixrules .
.SH SEE ALSO
getenv(3),
newctime(3),
newstrftime(3),
time(2),
tzfile(5)
-.\" @(#)newtzset.3 8.2
.\" This file is in the public domain, so clarified as of
.\" 2009-05-17 by Arthur David Olson.
diff --git a/newtzset.3.txt b/newtzset.3.txt
index 9d7d02233ee0..171e8291f8ce 100644
--- a/newtzset.3.txt
+++ b/newtzset.3.txt
@@ -1,153 +1,199 @@
-NAME
+NEWTZSET(3) Library Functions Manual NEWTZSET(3)
- tzset - initialize time conversion information
+NAME
+ tzset - initialize time conversion information
SYNOPSIS
- void tzset()
+ #include <time.h>
+
+ timezone_t tzalloc(char const *TZ);
- cc ... -ltz
+ void tzfree(timezone_t tz);
+
+ void tzset(void);
+
+ cc ... -ltz
DESCRIPTION
- Tzset uses the value of the environment variable TZ to set
- time conversion information used by localtime. If TZ does
- not appear in the environment, the best available
- approximation to local wall clock time, as specified by the
- tzfile(5)-format file localtime in the system time
- conversion information directory, is used by localtime. If
- TZ appears in the environment but its value is a null
- string, Coordinated Universal Time (UTC) is used (without
- leap second correction). If TZ appears in the environment
- and its value is not a null string:
-
- if the value begins with a colon, it is used as a
- pathname of a file from which to read the time
- conversion information;
-
- if the value does not begin with a colon, it is first
- used as the pathname of a file from which to read the
- time conversion information, and, if that file cannot
- be read, is used directly as a specification of the
- time conversion information.
-
- When TZ is used as a pathname, if it begins with a slash, it
- is used as an absolute pathname; otherwise, it is used as a
- pathname relative to a system time conversion information
- directory. The file must be in the format specified in
- tzfile(5).
-
- When TZ is used directly as a specification of the time
- conversion information, it must have the following syntax
- (spaces inserted for clarity):
-
- stdoffset[dst[offset][,rule]]
-
- Where:
-
- std and dst Three or more bytes that are the
- designation for the standard (std) or
- summer (dst) time zone. Only std is
- required; if dst is missing, then summer
- time does not apply in this locale.
- Upper- and lowercase letters are
- explicitly allowed. Any characters
- except a leading colon (:), digits,
- comma (,), minus (-), plus (+), and
- ASCII NUL are allowed.
-
- offset Indicates the value one must add to the
- local time to arrive at Coordinated
- Universal Time. The offset has the
- form:
-
- hh[:mm[:ss]]
-
- The minutes (mm) and seconds (ss) are
- optional. The hour (hh) is required and
- may be a single digit. The offset
- following std is required. If no offset
- follows dst, summer time is assumed to
- be one hour ahead of standard time. One
- or more digits may be used; the value is
- always interpreted as a decimal number.
- The hour must be between zero and 24,
- and the minutes (and seconds) -- if
- present -- between zero and 59. If
- preceded by a ``-'', the time zone shall
- be east of the Prime Meridian; otherwise
- it shall be west (which may be indicated
- by an optional preceding ``+'').
-
- rule Indicates when to change to and back
- from summer time. The rule has the
- form:
-
- date/time,date/time
-
- where the first date describes when the
- change from standard to summer time
- occurs and the second date describes
- when the change back happens. Each time
- field describes when, in current local
- time, the change to the other time is
- made.
-
- The format of date is one of the
- following:
-
- Jn The Julian day n
- (1 <= n <= 365). Leap days
- are not counted; that is, in
- all years -- including leap
- years -- February 28 is day 59
- and March 1 is day 60. It is
- impossible to explicitly refer
- to the occasional February 29.
-
- n The zero-based Julian day
- (0 <= n <= 365). Leap days
- are counted, and it is
- possible to refer to February
- 29.
-
- Mm.n.d The d'th day (0 <= d <= 6) of
- week n of month m of the year
- (1 <= n <= 5, 1 <= m <= 12,
- where week 5 means ``the last
- d day in month m'' which may
- occur in either the fourth or
- the fifth week). Week 1 is
- the first week in which the
- d'th day occurs. Day zero is
- Sunday.
-
- The time has the same format as offset
- except that no leading sign (``-'' or
- ``+'') is allowed. The default, if time
- is not given, is 02:00:00.
-
- If no rule is present in TZ, the rules specified by the
- tzfile(5)-format file posixrules in the system time
- conversion information directory are used, with the standard
- and summer time offsets from UTC replaced by those specified
- by the offset values in TZ.
- For compatibility with System V Release 3.1, a semicolon (;)
- may be used to separate the rule from the rest of the
- specification.
-
- If the TZ environment variable does not specify a
- tzfile(5)-format and cannot be interpreted as a direct
- specification, UTC is used.
+ The tzalloc function allocates and returns a timezone object described
+ by TZ. If TZ is not a valid timezone description, or if the object
+ cannot be allocated, tzalloc returns a null pointer and sets errno.
+
+ The tzfree function frees a timezone object tz, which should have been
+ successfully allocated by tzalloc. This invalidates any tm_zone
+ pointers that tz was used to set.
+
+ The tzset function acts like tzalloc(getenv("TZ")), except it saves any
+ resulting timezone object into internal storage that is accessed by
+ localtime, localtime_r, and mktime. The anonymous shared timezone
+ object is freed by the next call to tzset. If the implied call to
+ tzalloc fails, tzset falls back on Universal Time (UT).
+
+ If TZ is null, the best available approximation to local (wall clock)
+ time, as specified by the tzfile(5)-format file localtime in the system
+ time conversion information directory, is used. If TZ is the empty
+ string, UT is used, with the abbreviation "UTC" and without leap second
+ correction; please see newctime(3) for more about UT, UTC, and leap
+ seconds. If TZ is nonnull and nonempty:
+
+ if the value begins with a colon, it is used as a pathname of a
+ file from which to read the time conversion information;
+
+ if the value does not begin with a colon, it is first used as
+ the pathname of a file from which to read the time conversion
+ information, and, if that file cannot be read, is used directly
+ as a specification of the time conversion information.
+
+ When TZ is used as a pathname, if it begins with a slash, it is used as
+ an absolute pathname; otherwise, it is used as a pathname relative to a
+ system time conversion information directory. The file must be in the
+ format specified in tzfile(5).
+
+ When TZ is used directly as a specification of the time conversion
+ information, it must have the following syntax (spaces inserted for
+ clarity):
+
+ stdoffset[dst[offset][,rule]]
+
+ Where:
+
+ std and dst Three or more bytes that are the designation for
+ the standard (std) or the alternative (dst, such
+ as daylight saving time) time zone. Only std is
+ required; if dst is missing, then daylight saving
+ time does not apply in this locale. Upper- and
+ lowercase letters are explicitly allowed. Any
+ characters except a leading colon (:), digits,
+ comma (,), ASCII minus (-), ASCII plus (+), and
+ NUL bytes are allowed. Alternatively, a
+ designation can be surrounded by angle brackets <
+ and >; in this case, the designation can contain
+ any characters other than > and NUL.
+
+ offset Indicates the value one must add to the local
+ time to arrive at Coordinated Universal Time.
+ The offset has the form:
+
+ hh[:mm[:ss]]
+
+ The minutes (mm) and seconds (ss) are optional.
+ The hour (hh) is required and may be a single
+ digit. The offset following std is required. If
+ no offset follows dst, daylight saving time is
+ assumed to be one hour ahead of standard time.
+ One or more digits may be used; the value is
+ always interpreted as a decimal number. The hour
+ must be between zero and 24, and the minutes (and
+ seconds) - if present - between zero and 59. If
+ preceded by a "-", the time zone shall be east of
+ the Prime Meridian; otherwise it shall be west
+ (which may be indicated by an optional preceding
+ "+".
+
+ rule Indicates when to change to and back from
+ daylight saving time. The rule has the form:
+
+ date/time,date/time
+
+ where the first date describes when the change
+ from standard to daylight saving time occurs and
+ the second date describes when the change back
+ happens. Each time field describes when, in
+ current local time, the change to the other time
+ is made. As an extension to POSIX, daylight
+ saving is assumed to be in effect all year if it
+ begins January 1 at 00:00 and ends December 31 at
+ 24:00 plus the difference between daylight saving
+ and standard time, leaving no room for standard
+ time in the calendar.
+
+ The format of date is one of the following:
+
+ Jn The Julian day n (1 <= n <= 365). Leap
+ days are not counted; that is, in all
+ years - including leap years - February
+ 28 is day 59 and March 1 is day 60. It
+ is impossible to explicitly refer to
+ the occasional February 29.
+
+ n The zero-based Julian day
+ (0 <= n <= 365). Leap days are
+ counted, and it is possible to refer to
+ February 29.
+
+ Mm.n.d The d'th day (0 <= d <= 6) of week n of
+ month m of the year (1 <= n <= 5,
+ 1 <= m <= 12, where week 5 means "the
+ last d day in month m" which may occur
+ in either the fourth or the fifth
+ week). Week 1 is the first week in
+ which the d'th day occurs. Day zero is
+ Sunday.
+
+ The time has the same format as offset except
+ that POSIX does not allow a leading sign ("-" or
+ "+"). As an extension to POSIX, the hours part
+ of time can range from -167 through 167; this
+ allows for unusual rules such as "the Saturday
+ before the first Sunday of March". The default,
+ if time is not given, is 02:00:00.
+
+ Here are some examples of TZ values that directly specify the timezone;
+ they use some of the extensions to POSIX.
+
+ EST5 stands for US Eastern Standard Time (EST), 5 hours behind UT,
+ without daylight saving.
+
+ <+12>-12<+13>,M11.1.0,M1.2.1/147
+ stands for Fiji time, 12 hours ahead of UT, springing forward on
+ November's first Sunday at 02:00, and falling back on January's
+ second Monday at 147:00 (i.e., 03:00 on the first Sunday on or
+ after January 14). The abbreviations for standard and daylight
+ saving time are "+12" and "+13".
+
+ IST-2IDT,M3.4.4/26,M10.5.0
+ stands for Israel Standard Time (IST) and Israel Daylight Time
+ (IDT), 2 hours ahead of UT, springing forward on March's fourth
+ Thursday at 26:00 (i.e., 02:00 on the first Friday on or after
+ March 23), and falling back on October's last Sunday at 02:00.
+
+ <-04>4<-03>,J1/0,J365/25
+ stands for permanent daylight saving time, 3 hours behind UT
+ with abbreviation "-03". There is a dummy fall-back transition
+ on December 31 at 25:00 daylight saving time (i.e., 24:00
+ standard time, equivalent to January 1 at 00:00 standard time),
+ and a simultaneous spring-forward transition on January 1 at
+ 00:00 standard time, so daylight saving time is in effect all
+ year and the initial <-04> is a placeholder.
+
+ <-03>3<-02>,M3.5.0/-2,M10.5.0/-1
+ stands for time in western Greenland, 3 hours behind UT, where
+ clocks follow the EU rules of springing forward on March's last
+ Sunday at 01:00 UT (-02:00 local time, i.e., 22:00 the previous
+ day) and falling back on October's last Sunday at 01:00 UT
+ (-01:00 local time, i.e., 23:00 the previous day). The
+ abbreviations for standard and daylight saving time are "-03"
+ and "-02".
+
+ If no rule is present in TZ, the rules specified by the
+ tzfile(5)-format file posixrules in the system time conversion
+ information directory are used, with the standard and daylight saving
+ time offsets from UT replaced by those specified by the offset values
+ in TZ.
+
+ For compatibility with System V Release 3.1, a semicolon (;) may be
+ used to separate the rule from the rest of the specification.
FILES
- /usr/local/etc/zoneinfo time zone information
- directory
- /usr/local/etc/zoneinfo/localtime local time zone file
- /usr/local/etc/zoneinfo/posixrules used with POSIX-style
- TZ's
- /usr/local/etc/zoneinfo/GMT for UTC leap seconds
+ /usr/share/zoneinfo timezone information directory
+ /usr/share/zoneinfo/localtime local timezone file
+ /usr/share/zoneinfo/posixrules used with POSIX-style TZ's
+ /usr/share/zoneinfo/GMT for UTC leap seconds
- If /usr/local/etc/zoneinfo/GMT is absent, UTC leap seconds
- are loaded from /usr/local/etc/zoneinfo/posixrules.
+ If /usr/share/zoneinfo/GMT is absent, UTC leap seconds are loaded from
+ /usr/share/zoneinfo/posixrules.
SEE ALSO
- getenv(3), newctime(3), newstrftime(3), time(2), tzfile(5)
+ getenv(3), newctime(3), newstrftime(3), time(2), tzfile(5)
+
+ NEWTZSET(3)
diff --git a/private.h b/private.h
index 008d468ac787..9c31ec5434f2 100644
--- a/private.h
+++ b/private.h
@@ -1,3 +1,5 @@
+/* Private header for tzdb code. */
+
#ifndef PRIVATE_H
#define PRIVATE_H
@@ -16,201 +18,665 @@
*/
/*
-** ID
+** zdump has been made independent of the rest of the time
+** conversion package to increase confidence in the verification it provides.
+** You can use zdump to help in verifying other implementations.
+** To do this, compile with -DUSE_LTZ=0 and link without the tz library.
*/
+#ifndef USE_LTZ
+# define USE_LTZ 1
+#endif
-#ifndef lint
-#ifndef NOID
-static char privatehid[] = "@(#)private.h 8.6";
-#endif /* !defined NOID */
-#endif /* !defined lint */
-
+/* This string was in the Factory zone through version 2016f. */
#define GRANDPARENTED "Local time zone must be set--see zic manual page"
/*
** Defaults for preprocessor symbols.
-** You can override these in your C compiler options, e.g. `-DHAVE_ADJTIME=0'.
+** You can override these in your C compiler options, e.g. '-DHAVE_GETTEXT=1'.
*/
-#ifndef HAVE_ADJTIME
-#define HAVE_ADJTIME 1
-#endif /* !defined HAVE_ADJTIME */
+#ifndef HAVE_DECL_ASCTIME_R
+# define HAVE_DECL_ASCTIME_R 1
+#endif
+
+#if !defined HAVE_GENERIC && defined __has_extension
+# if __has_extension(c_generic_selections)
+# define HAVE_GENERIC 1
+# else
+# define HAVE_GENERIC 0
+# endif
+#endif
+/* _Generic is buggy in pre-4.9 GCC. */
+#if !defined HAVE_GENERIC && defined __GNUC__
+# define HAVE_GENERIC (4 < __GNUC__ + (9 <= __GNUC_MINOR__))
+#endif
+#ifndef HAVE_GENERIC
+# define HAVE_GENERIC (201112 <= __STDC_VERSION__)
+#endif
#ifndef HAVE_GETTEXT
-#define HAVE_GETTEXT 0
+# define HAVE_GETTEXT 0
#endif /* !defined HAVE_GETTEXT */
#ifndef HAVE_INCOMPATIBLE_CTIME_R
-#define HAVE_INCOMPATIBLE_CTIME_R 0
-#endif /* !defined INCOMPATIBLE_CTIME_R */
+# define HAVE_INCOMPATIBLE_CTIME_R 0
+#endif
+
+#ifndef HAVE_LINK
+# define HAVE_LINK 1
+#endif /* !defined HAVE_LINK */
+
+#ifndef HAVE_MALLOC_ERRNO
+# define HAVE_MALLOC_ERRNO 1
+#endif
+
+#ifndef HAVE_POSIX_DECLS
+# define HAVE_POSIX_DECLS 1
+#endif
+
+#ifndef HAVE_STDBOOL_H
+# define HAVE_STDBOOL_H (199901 <= __STDC_VERSION__)
+#endif
-#ifndef HAVE_SETTIMEOFDAY
-#define HAVE_SETTIMEOFDAY 3
-#endif /* !defined HAVE_SETTIMEOFDAY */
+#ifndef HAVE_STRDUP
+# define HAVE_STRDUP 1
+#endif
+
+#ifndef HAVE_STRTOLL
+# define HAVE_STRTOLL 1
+#endif
#ifndef HAVE_SYMLINK
-#define HAVE_SYMLINK 1
+# define HAVE_SYMLINK 1
#endif /* !defined HAVE_SYMLINK */
#ifndef HAVE_SYS_STAT_H
-#define HAVE_SYS_STAT_H 1
+# define HAVE_SYS_STAT_H 1
#endif /* !defined HAVE_SYS_STAT_H */
-#ifndef HAVE_SYS_WAIT_H
-#define HAVE_SYS_WAIT_H 1
-#endif /* !defined HAVE_SYS_WAIT_H */
-
#ifndef HAVE_UNISTD_H
-#define HAVE_UNISTD_H 1
+# define HAVE_UNISTD_H 1
#endif /* !defined HAVE_UNISTD_H */
#ifndef HAVE_UTMPX_H
-#define HAVE_UTMPX_H 0
+# define HAVE_UTMPX_H 1
#endif /* !defined HAVE_UTMPX_H */
-#ifndef LOCALE_HOME
-#define LOCALE_HOME "/usr/lib/locale"
-#endif /* !defined LOCALE_HOME */
+#ifndef NETBSD_INSPIRED
+# define NETBSD_INSPIRED 1
+#endif
#if HAVE_INCOMPATIBLE_CTIME_R
-#define asctime_r _incompatible_asctime_r
-#define ctime_r _incompatible_ctime_r
+# define asctime_r _incompatible_asctime_r
+# define ctime_r _incompatible_ctime_r
#endif /* HAVE_INCOMPATIBLE_CTIME_R */
+/* Enable tm_gmtoff, tm_zone, and environ on GNUish systems. */
+#define _GNU_SOURCE 1
+/* Fix asctime_r on Solaris 11. */
+#define _POSIX_PTHREAD_SEMANTICS 1
+/* Enable strtoimax on pre-C99 Solaris 11. */
+#define __EXTENSIONS__ 1
+
+/* To avoid having 'stat' fail unnecessarily with errno == EOVERFLOW,
+ enable large files on GNUish systems ... */
+#ifndef _FILE_OFFSET_BITS
+# define _FILE_OFFSET_BITS 64
+#endif
+/* ... and on AIX ... */
+#define _LARGE_FILES 1
+/* ... and enable large inode numbers on Mac OS X 10.5 and later. */
+#define _DARWIN_USE_64_BIT_INODE 1
+
/*
** Nested includes
*/
-#include "sys/types.h" /* for time_t */
-#include "stdio.h"
-#include "errno.h"
-#include "string.h"
-#include "limits.h" /* for CHAR_BIT et al. */
-#include "time.h"
-#include "stdlib.h"
+/* Avoid clashes with NetBSD by renaming NetBSD's declarations.
+ If defining the 'timezone' variable, avoid a clash with FreeBSD's
+ 'timezone' function by renaming its declaration. */
+#define localtime_rz sys_localtime_rz
+#define mktime_z sys_mktime_z
+#define posix2time_z sys_posix2time_z
+#define time2posix_z sys_time2posix_z
+#if defined USG_COMPAT && USG_COMPAT == 2
+# define timezone sys_timezone
+#endif
+#define timezone_t sys_timezone_t
+#define tzalloc sys_tzalloc
+#define tzfree sys_tzfree
+#include <time.h>
+#undef localtime_rz
+#undef mktime_z
+#undef posix2time_z
+#undef time2posix_z
+#if defined USG_COMPAT && USG_COMPAT == 2
+# undef timezone
+#endif
+#undef timezone_t
+#undef tzalloc
+#undef tzfree
+
+#include <sys/types.h> /* for time_t */
+#include <string.h>
+#include <limits.h> /* for CHAR_BIT et al. */
+#include <stdlib.h>
-#if HAVE_GETTEXT
-#include "libintl.h"
-#endif /* HAVE_GETTEXT */
+#include <errno.h>
-#if HAVE_SYS_WAIT_H
-#include <sys/wait.h> /* for WIFEXITED and WEXITSTATUS */
-#endif /* HAVE_SYS_WAIT_H */
+#ifndef EINVAL
+# define EINVAL ERANGE
+#endif
+
+#ifndef ELOOP
+# define ELOOP EINVAL
+#endif
+#ifndef ENAMETOOLONG
+# define ENAMETOOLONG EINVAL
+#endif
+#ifndef ENOMEM
+# define ENOMEM EINVAL
+#endif
+#ifndef ENOTSUP
+# define ENOTSUP EINVAL
+#endif
+#ifndef EOVERFLOW
+# define EOVERFLOW EINVAL
+#endif
-#ifndef WIFEXITED
-#define WIFEXITED(status) (((status) & 0xff) == 0)
-#endif /* !defined WIFEXITED */
-#ifndef WEXITSTATUS
-#define WEXITSTATUS(status) (((status) >> 8) & 0xff)
-#endif /* !defined WEXITSTATUS */
+#if HAVE_GETTEXT
+# include <libintl.h>
+#endif /* HAVE_GETTEXT */
#if HAVE_UNISTD_H
-#include "unistd.h" /* for F_OK, R_OK, and other POSIX goodness */
+# include <unistd.h> /* for R_OK, and other POSIX goodness */
#endif /* HAVE_UNISTD_H */
-#ifndef F_OK
-#define F_OK 0
-#endif /* !defined F_OK */
+#ifndef HAVE_STRFTIME_L
+# if _POSIX_VERSION < 200809
+# define HAVE_STRFTIME_L 0
+# else
+# define HAVE_STRFTIME_L 1
+# endif
+#endif
+
+#ifndef USG_COMPAT
+# ifndef _XOPEN_VERSION
+# define USG_COMPAT 0
+# else
+# define USG_COMPAT 1
+# endif
+#endif
+
+#ifndef HAVE_TZNAME
+# if _POSIX_VERSION < 198808 && !USG_COMPAT
+# define HAVE_TZNAME 0
+# else
+# define HAVE_TZNAME 1
+# endif
+#endif
+
+#ifndef ALTZONE
+# if defined __sun || defined _M_XENIX
+# define ALTZONE 1
+# else
+# define ALTZONE 0
+# endif
+#endif
+
#ifndef R_OK
-#define R_OK 4
+# define R_OK 4
#endif /* !defined R_OK */
-/* Unlike <ctype.h>'s isdigit, this also works if c < 0 | c > UCHAR_MAX. */
-#define is_digit(c) ((unsigned)(c) - '0' <= 9)
-
/*
** Define HAVE_STDINT_H's default value here, rather than at the
-** start, since __GLIBC__'s value depends on previously-included
-** files.
-** (glibc 2.1 and later have stdint.h, even with pre-C99 compilers.)
+** start, since __GLIBC__ and INTMAX_MAX's values depend on
+** previously-included files. glibc 2.1 and Solaris 10 and later have
+** stdint.h, even with pre-C99 compilers.
*/
#ifndef HAVE_STDINT_H
-#define HAVE_STDINT_H \
- (199901 <= __STDC_VERSION__ || \
- 2 < (__GLIBC__ + (0 < __GLIBC_MINOR__)))
+# define HAVE_STDINT_H \
+ (199901 <= __STDC_VERSION__ \
+ || 2 < __GLIBC__ + (1 <= __GLIBC_MINOR__) \
+ || __CYGWIN__ || INTMAX_MAX)
#endif /* !defined HAVE_STDINT_H */
#if HAVE_STDINT_H
-#include "stdint.h"
+# include <stdint.h>
#endif /* !HAVE_STDINT_H */
-#ifndef INT_FAST64_MAX
+#ifndef HAVE_INTTYPES_H
+# define HAVE_INTTYPES_H HAVE_STDINT_H
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+
/* Pre-C99 GCC compilers define __LONG_LONG_MAX__ instead of LLONG_MAX. */
-#if defined LLONG_MAX || defined __LONG_LONG_MAX__
+#ifdef __LONG_LONG_MAX__
+# ifndef LLONG_MAX
+# define LLONG_MAX __LONG_LONG_MAX__
+# endif
+# ifndef LLONG_MIN
+# define LLONG_MIN (-1 - LLONG_MAX)
+# endif
+#endif
+
+#ifndef INT_FAST64_MAX
+# ifdef LLONG_MAX
typedef long long int_fast64_t;
-#else /* ! (defined LLONG_MAX || defined __LONG_LONG_MAX__) */
-#if (LONG_MAX >> 31) < 0xffffffff
+# define INT_FAST64_MIN LLONG_MIN
+# define INT_FAST64_MAX LLONG_MAX
+# else
+# if LONG_MAX >> 31 < 0xffffffff
Please use a compiler that supports a 64-bit integer type (or wider);
you may need to compile with "-DHAVE_STDINT_H".
-#endif /* (LONG_MAX >> 31) < 0xffffffff */
+# endif
typedef long int_fast64_t;
-#endif /* ! (defined LLONG_MAX || defined __LONG_LONG_MAX__) */
-#endif /* !defined INT_FAST64_MAX */
+# define INT_FAST64_MIN LONG_MIN
+# define INT_FAST64_MAX LONG_MAX
+# endif
+#endif
+
+#ifndef PRIdFAST64
+# if INT_FAST64_MAX == LLONG_MAX
+# define PRIdFAST64 "lld"
+# else
+# define PRIdFAST64 "ld"
+# endif
+#endif
+
+#ifndef SCNdFAST64
+# define SCNdFAST64 PRIdFAST64
+#endif
+
+#ifndef INT_FAST32_MAX
+# if INT_MAX >> 31 == 0
+typedef long int_fast32_t;
+# define INT_FAST32_MAX LONG_MAX
+# define INT_FAST32_MIN LONG_MIN
+# else
+typedef int int_fast32_t;
+# define INT_FAST32_MAX INT_MAX
+# define INT_FAST32_MIN INT_MIN
+# endif
+#endif
+
+#ifndef INTMAX_MAX
+# ifdef LLONG_MAX
+typedef long long intmax_t;
+# if HAVE_STRTOLL
+# define strtoimax strtoll
+# endif
+# define INTMAX_MAX LLONG_MAX
+# define INTMAX_MIN LLONG_MIN
+# else
+typedef long intmax_t;
+# define INTMAX_MAX LONG_MAX
+# define INTMAX_MIN LONG_MIN
+# endif
+# ifndef strtoimax
+# define strtoimax strtol
+# endif
+#endif
+
+#ifndef PRIdMAX
+# if INTMAX_MAX == LLONG_MAX
+# define PRIdMAX "lld"
+# else
+# define PRIdMAX "ld"
+# endif
+#endif
+
+#ifndef UINT_FAST32_MAX
+typedef unsigned long uint_fast32_t;
+#endif
+
+#ifndef UINT_FAST64_MAX
+# if defined ULLONG_MAX || defined __LONG_LONG_MAX__
+typedef unsigned long long uint_fast64_t;
+# else
+# if ULONG_MAX >> 31 >> 1 < 0xffffffff
+Please use a compiler that supports a 64-bit integer type (or wider);
+you may need to compile with "-DHAVE_STDINT_H".
+# endif
+typedef unsigned long uint_fast64_t;
+# endif
+#endif
+
+#ifndef UINTMAX_MAX
+# if defined ULLONG_MAX || defined __LONG_LONG_MAX__
+typedef unsigned long long uintmax_t;
+# else
+typedef unsigned long uintmax_t;
+# endif
+#endif
+
+#ifndef PRIuMAX
+# if defined ULLONG_MAX || defined __LONG_LONG_MAX__
+# define PRIuMAX "llu"
+# else
+# define PRIuMAX "lu"
+# endif
+#endif
#ifndef INT32_MAX
-#define INT32_MAX 0x7fffffff
+# define INT32_MAX 0x7fffffff
#endif /* !defined INT32_MAX */
#ifndef INT32_MIN
-#define INT32_MIN (-1 - INT32_MAX)
+# define INT32_MIN (-1 - INT32_MAX)
#endif /* !defined INT32_MIN */
+#ifndef SIZE_MAX
+# define SIZE_MAX ((size_t) -1)
+#endif
+
+#if 3 <= __GNUC__
+# define ATTRIBUTE_CONST __attribute__((const))
+# define ATTRIBUTE_MALLOC __attribute__((__malloc__))
+# define ATTRIBUTE_PURE __attribute__((__pure__))
+# define ATTRIBUTE_FORMAT(spec) __attribute__((__format__ spec))
+#else
+# define ATTRIBUTE_CONST /* empty */
+# define ATTRIBUTE_MALLOC /* empty */
+# define ATTRIBUTE_PURE /* empty */
+# define ATTRIBUTE_FORMAT(spec) /* empty */
+#endif
+
+#if !defined _Noreturn && __STDC_VERSION__ < 201112
+# if 2 < __GNUC__ + (8 <= __GNUC_MINOR__)
+# define _Noreturn __attribute__((__noreturn__))
+# else
+# define _Noreturn
+# endif
+#endif
+
+#if __STDC_VERSION__ < 199901 && !defined restrict
+# define restrict /* empty */
+#endif
+
/*
** Workarounds for compilers/systems.
*/
-/*
-** Some time.h implementations don't declare asctime_r.
-** Others might define it as a macro.
-** Fix the former without affecting the latter.
-*/
+#ifndef EPOCH_LOCAL
+# define EPOCH_LOCAL 0
+#endif
+#ifndef EPOCH_OFFSET
+# define EPOCH_OFFSET 0
+#endif
+#ifndef RESERVE_STD_EXT_IDS
+# define RESERVE_STD_EXT_IDS 0
+#endif
-#ifndef asctime_r
-extern char * asctime_r(struct tm const *, char *);
+/* If standard C identifiers with external linkage (e.g., localtime)
+ are reserved and are not already being renamed anyway, rename them
+ as if compiling with '-Dtime_tz=time_t'. */
+#if !defined time_tz && RESERVE_STD_EXT_IDS && USE_LTZ
+# define time_tz time_t
#endif
/*
-** Private function declarations.
+** Compile with -Dtime_tz=T to build the tz package with a private
+** time_t type equivalent to T rather than the system-supplied time_t.
+** This debugging feature can test unusual design decisions
+** (e.g., time_t wider than 'long', or unsigned time_t) even on
+** typical platforms.
*/
+#if defined time_tz || EPOCH_LOCAL || EPOCH_OFFSET != 0
+# define TZ_TIME_T 1
+#else
+# define TZ_TIME_T 0
+#endif
-char * icalloc(int nelem, int elsize);
-char * icatalloc(char * old, const char * new);
-char * icpyalloc(const char * string);
-char * imalloc(int n);
-void * irealloc(void * pointer, int size);
-void icfree(char * pointer);
-void ifree(char * pointer);
-const char * scheck(const char * string, const char * format);
+#if defined LOCALTIME_IMPLEMENTATION && TZ_TIME_T
+static time_t sys_time(time_t *x) { return time(x); }
+#endif
+
+#if TZ_TIME_T
+
+typedef time_tz tz_time_t;
+
+# undef asctime
+# define asctime tz_asctime
+# undef asctime_r
+# define asctime_r tz_asctime_r
+# undef ctime
+# define ctime tz_ctime
+# undef ctime_r
+# define ctime_r tz_ctime_r
+# undef difftime
+# define difftime tz_difftime
+# undef gmtime
+# define gmtime tz_gmtime
+# undef gmtime_r
+# define gmtime_r tz_gmtime_r
+# undef localtime
+# define localtime tz_localtime
+# undef localtime_r
+# define localtime_r tz_localtime_r
+# undef localtime_rz
+# define localtime_rz tz_localtime_rz
+# undef mktime
+# define mktime tz_mktime
+# undef mktime_z
+# define mktime_z tz_mktime_z
+# undef offtime
+# define offtime tz_offtime
+# undef posix2time
+# define posix2time tz_posix2time
+# undef posix2time_z
+# define posix2time_z tz_posix2time_z
+# undef strftime
+# define strftime tz_strftime
+# undef time
+# define time tz_time
+# undef time2posix
+# define time2posix tz_time2posix
+# undef time2posix_z
+# define time2posix_z tz_time2posix_z
+# undef time_t
+# define time_t tz_time_t
+# undef timegm
+# define timegm tz_timegm
+# undef timelocal
+# define timelocal tz_timelocal
+# undef timeoff
+# define timeoff tz_timeoff
+# undef tzalloc
+# define tzalloc tz_tzalloc
+# undef tzfree
+# define tzfree tz_tzfree
+# undef tzset
+# define tzset tz_tzset
+# if HAVE_STRFTIME_L
+# undef strftime_l
+# define strftime_l tz_strftime_l
+# endif
+# if HAVE_TZNAME
+# undef tzname
+# define tzname tz_tzname
+# endif
+# if USG_COMPAT
+# undef daylight
+# define daylight tz_daylight
+# undef timezone
+# define timezone tz_timezone
+# endif
+# if ALTZONE
+# undef altzone
+# define altzone tz_altzone
+# endif
+
+char *asctime(struct tm const *);
+char *asctime_r(struct tm const *restrict, char *restrict);
+char *ctime(time_t const *);
+char *ctime_r(time_t const *, char *);
+double difftime(time_t, time_t) ATTRIBUTE_CONST;
+size_t strftime(char *restrict, size_t, char const *restrict,
+ struct tm const *restrict);
+# if HAVE_STRFTIME_L
+size_t strftime_l(char *restrict, size_t, char const *restrict,
+ struct tm const *restrict, locale_t);
+# endif
+struct tm *gmtime(time_t const *);
+struct tm *gmtime_r(time_t const *restrict, struct tm *restrict);
+struct tm *localtime(time_t const *);
+struct tm *localtime_r(time_t const *restrict, struct tm *restrict);
+time_t mktime(struct tm *);
+time_t time(time_t *);
+void tzset(void);
+#endif
+
+#if !HAVE_DECL_ASCTIME_R && !defined asctime_r
+extern char *asctime_r(struct tm const *restrict, char *restrict);
+#endif
+
+#ifndef HAVE_DECL_ENVIRON
+# if defined environ || defined __USE_GNU
+# define HAVE_DECL_ENVIRON 1
+# else
+# define HAVE_DECL_ENVIRON 0
+# endif
+#endif
+
+#if !HAVE_DECL_ENVIRON
+extern char **environ;
+#endif
+
+#if 2 <= HAVE_TZNAME + (TZ_TIME_T || !HAVE_POSIX_DECLS)
+extern char *tzname[];
+#endif
+#if 2 <= USG_COMPAT + (TZ_TIME_T || !HAVE_POSIX_DECLS)
+extern long timezone;
+extern int daylight;
+#endif
+#if 2 <= ALTZONE + (TZ_TIME_T || !HAVE_POSIX_DECLS)
+extern long altzone;
+#endif
/*
-** Finally, some convenience items.
+** The STD_INSPIRED functions are similar, but most also need
+** declarations if time_tz is defined.
*/
-#ifndef TRUE
-#define TRUE 1
-#endif /* !defined TRUE */
-
-#ifndef FALSE
-#define FALSE 0
-#endif /* !defined FALSE */
+#ifdef STD_INSPIRED
+# if TZ_TIME_T || !defined offtime
+struct tm *offtime(time_t const *, long);
+# endif
+# if TZ_TIME_T || !defined timegm
+time_t timegm(struct tm *);
+# endif
+# if TZ_TIME_T || !defined timelocal
+time_t timelocal(struct tm *);
+# endif
+# if TZ_TIME_T || !defined timeoff
+time_t timeoff(struct tm *, long);
+# endif
+# if TZ_TIME_T || !defined time2posix
+time_t time2posix(time_t);
+# endif
+# if TZ_TIME_T || !defined posix2time
+time_t posix2time(time_t);
+# endif
+#endif
-#ifndef TYPE_BIT
-#define TYPE_BIT(type) (sizeof (type) * CHAR_BIT)
-#endif /* !defined TYPE_BIT */
+/* Infer TM_ZONE on systems where this information is known, but suppress
+ guessing if NO_TM_ZONE is defined. Similarly for TM_GMTOFF. */
+#if (defined __GLIBC__ \
+ || defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ \
+ || (defined __APPLE__ && defined __MACH__))
+# if !defined TM_GMTOFF && !defined NO_TM_GMTOFF
+# define TM_GMTOFF tm_gmtoff
+# endif
+# if !defined TM_ZONE && !defined NO_TM_ZONE
+# define TM_ZONE tm_zone
+# endif
+#endif
-#ifndef TYPE_SIGNED
-#define TYPE_SIGNED(type) (((type) -1) < 0)
-#endif /* !defined TYPE_SIGNED */
+/*
+** Define functions that are ABI compatible with NetBSD but have
+** better prototypes. NetBSD 6.1.4 defines a pointer type timezone_t
+** and labors under the misconception that 'const timezone_t' is a
+** pointer to a constant. This use of 'const' is ineffective, so it
+** is not done here. What we call 'struct state' NetBSD calls
+** 'struct __state', but this is a private name so it doesn't matter.
+*/
+#if NETBSD_INSPIRED
+typedef struct state *timezone_t;
+struct tm *localtime_rz(timezone_t restrict, time_t const *restrict,
+ struct tm *restrict);
+time_t mktime_z(timezone_t restrict, struct tm *restrict);
+timezone_t tzalloc(char const *);
+void tzfree(timezone_t);
+# ifdef STD_INSPIRED
+# if TZ_TIME_T || !defined posix2time_z
+time_t posix2time_z(timezone_t, time_t) ATTRIBUTE_PURE;
+# endif
+# if TZ_TIME_T || !defined time2posix_z
+time_t time2posix_z(timezone_t, time_t) ATTRIBUTE_PURE;
+# endif
+# endif
+#endif
/*
-** Since the definition of TYPE_INTEGRAL contains floating point numbers,
-** it cannot be used in preprocessor directives.
+** Finally, some convenience items.
*/
-#ifndef TYPE_INTEGRAL
-#define TYPE_INTEGRAL(type) (((type) 0.5) != 0.5)
-#endif /* !defined TYPE_INTEGRAL */
+#if HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# define true 1
+# define false 0
+# define bool int
+#endif
+
+#define TYPE_BIT(type) (sizeof(type) * CHAR_BIT)
+#define TYPE_SIGNED(type) (((type) -1) < 0)
+#define TWOS_COMPLEMENT(t) ((t) ~ (t) 0 < 0)
+
+/* Minimum and maximum of two values. Use lower case to avoid
+ naming clashes with standard include files. */
+#define max(a, b) ((a) > (b) ? (a) : (b))
+#define min(a, b) ((a) < (b) ? (a) : (b))
+
+/* Max and min values of the integer type T, of which only the bottom
+ B bits are used, and where the highest-order used bit is considered
+ to be a sign bit if T is signed. */
+#define MAXVAL(t, b) \
+ ((t) (((t) 1 << ((b) - 1 - TYPE_SIGNED(t))) \
+ - 1 + ((t) 1 << ((b) - 1 - TYPE_SIGNED(t)))))
+#define MINVAL(t, b) \
+ ((t) (TYPE_SIGNED(t) ? - TWOS_COMPLEMENT(t) - MAXVAL(t, b) : 0))
+
+/* The extreme time values, assuming no padding. */
+#define TIME_T_MIN_NO_PADDING MINVAL(time_t, TYPE_BIT(time_t))
+#define TIME_T_MAX_NO_PADDING MAXVAL(time_t, TYPE_BIT(time_t))
+
+/* The extreme time values. These are macros, not constants, so that
+ any portability problems occur only when compiling .c files that use
+ the macros, which is safer for applications that need only zdump and zic.
+ This implementation assumes no padding if time_t is signed and
+ either the compiler lacks support for _Generic or time_t is not one
+ of the standard signed integer types. */
+#if HAVE_GENERIC
+# define TIME_T_MIN \
+ _Generic((time_t) 0, \
+ signed char: SCHAR_MIN, short: SHRT_MIN, \
+ int: INT_MIN, long: LONG_MIN, long long: LLONG_MIN, \
+ default: TIME_T_MIN_NO_PADDING)
+# define TIME_T_MAX \
+ (TYPE_SIGNED(time_t) \
+ ? _Generic((time_t) 0, \
+ signed char: SCHAR_MAX, short: SHRT_MAX, \
+ int: INT_MAX, long: LONG_MAX, long long: LLONG_MAX, \
+ default: TIME_T_MAX_NO_PADDING) \
+ : (time_t) -1)
+#else
+# define TIME_T_MIN TIME_T_MIN_NO_PADDING
+# define TIME_T_MAX TIME_T_MAX_NO_PADDING
+#endif
-#ifndef INT_STRLEN_MAXIMUM
/*
** 302 / 1000 is log10(2.0) rounded up.
** Subtract one for the sign bit if the type is signed;
@@ -220,49 +686,55 @@ const char * scheck(const char * string, const char * format);
#define INT_STRLEN_MAXIMUM(type) \
((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + \
1 + TYPE_SIGNED(type))
-#endif /* !defined INT_STRLEN_MAXIMUM */
/*
** INITIALIZE(x)
*/
-#ifndef GNUC_or_lint
-#ifdef lint
-#define GNUC_or_lint
-#endif /* defined lint */
-#ifndef lint
-#ifdef __GNUC__
-#define GNUC_or_lint
-#endif /* defined __GNUC__ */
-#endif /* !defined lint */
-#endif /* !defined GNUC_or_lint */
-
-#ifndef INITIALIZE
-#ifdef GNUC_or_lint
-#define INITIALIZE(x) ((x) = 0)
-#endif /* defined GNUC_or_lint */
-#ifndef GNUC_or_lint
-#define INITIALIZE(x)
-#endif /* !defined GNUC_or_lint */
-#endif /* !defined INITIALIZE */
+#ifdef GCC_LINT
+# define INITIALIZE(x) ((x) = 0)
+#else
+# define INITIALIZE(x)
+#endif
+
+/* Whether memory access must strictly follow the C standard.
+ If 0, it's OK to read uninitialized storage so long as the value is
+ not relied upon. Defining it to 0 lets mktime access parts of
+ struct tm that might be uninitialized, as a heuristic when the
+ standard doesn't say what to return and when tm_gmtoff can help
+ mktime likely infer a better value. */
+#ifndef UNINIT_TRAP
+# define UNINIT_TRAP 0
+#endif
+
+#ifdef DEBUG
+# define UNREACHABLE() abort()
+#elif 4 < __GNUC__ + (5 <= __GNUC_MINOR__)
+# define UNREACHABLE() __builtin_unreachable()
+#elif defined __has_builtin
+# if __has_builtin(__builtin_unreachable)
+# define UNREACHABLE() __builtin_unreachable()
+# endif
+#endif
+#ifndef UNREACHABLE
+# define UNREACHABLE() ((void) 0)
+#endif
/*
** For the benefit of GNU folk...
-** `_(MSGID)' uses the current locale's message library string for MSGID.
+** '_(MSGID)' uses the current locale's message library string for MSGID.
** The default is to use gettext if available, and use MSGID otherwise.
*/
-#ifndef _
#if HAVE_GETTEXT
#define _(msgid) gettext(msgid)
#else /* !HAVE_GETTEXT */
#define _(msgid) msgid
#endif /* !HAVE_GETTEXT */
-#endif /* !defined _ */
-#ifndef TZ_DOMAIN
-#define TZ_DOMAIN "tz"
-#endif /* !defined TZ_DOMAIN */
+#if !defined TZ_DOMAIN && defined HAVE_GETTEXT
+# define TZ_DOMAIN "tz"
+#endif
#if HAVE_INCOMPATIBLE_CTIME_R
#undef asctime_r
@@ -271,28 +743,72 @@ char *asctime_r(struct tm const *, char *);
char *ctime_r(time_t const *, char *);
#endif /* HAVE_INCOMPATIBLE_CTIME_R */
-#ifndef YEARSPERREPEAT
-#define YEARSPERREPEAT 400 /* years before a Gregorian repeat */
-#endif /* !defined YEARSPERREPEAT */
+/* Handy macros that are independent of tzfile implementation. */
+
+enum {
+ SECSPERMIN = 60,
+ MINSPERHOUR = 60,
+ SECSPERHOUR = SECSPERMIN * MINSPERHOUR,
+ HOURSPERDAY = 24,
+ DAYSPERWEEK = 7,
+ DAYSPERNYEAR = 365,
+ DAYSPERLYEAR = DAYSPERNYEAR + 1,
+ MONSPERYEAR = 12,
+ YEARSPERREPEAT = 400 /* years before a Gregorian repeat */
+};
+
+#define SECSPERDAY ((int_fast32_t) SECSPERHOUR * HOURSPERDAY)
+
+#define DAYSPERREPEAT ((int_fast32_t) 400 * 365 + 100 - 4 + 1)
+#define SECSPERREPEAT ((int_fast64_t) DAYSPERREPEAT * SECSPERDAY)
+#define AVGSECSPERYEAR (SECSPERREPEAT / YEARSPERREPEAT)
+
+enum {
+ TM_SUNDAY,
+ TM_MONDAY,
+ TM_TUESDAY,
+ TM_WEDNESDAY,
+ TM_THURSDAY,
+ TM_FRIDAY,
+ TM_SATURDAY
+};
+
+enum {
+ TM_JANUARY,
+ TM_FEBRUARY,
+ TM_MARCH,
+ TM_APRIL,
+ TM_MAY,
+ TM_JUNE,
+ TM_JULY,
+ TM_AUGUST,
+ TM_SEPTEMBER,
+ TM_OCTOBER,
+ TM_NOVEMBER,
+ TM_DECEMBER
+};
+
+enum {
+ TM_YEAR_BASE = 1900,
+ TM_WDAY_BASE = TM_MONDAY,
+ EPOCH_YEAR = 1970,
+ EPOCH_WDAY = TM_THURSDAY
+};
+
+#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
/*
-** The Gregorian year averages 365.2425 days, which is 31556952 seconds.
+** Since everything in isleap is modulo 400 (or a factor of 400), we know that
+** isleap(y) == isleap(y % 400)
+** and so
+** isleap(a + b) == isleap((a + b) % 400)
+** or
+** isleap(a + b) == isleap(a % 400 + b % 400)
+** This is true even if % means modulo rather than Fortran remainder
+** (which is allowed by C89 but not by C99 or later).
+** We use this to avoid addition overflow problems.
*/
-#ifndef AVGSECSPERYEAR
-#define AVGSECSPERYEAR 31556952L
-#endif /* !defined AVGSECSPERYEAR */
-
-#ifndef SECSPERREPEAT
-#define SECSPERREPEAT ((int_fast64_t) YEARSPERREPEAT * (int_fast64_t) AVGSECSPERYEAR)
-#endif /* !defined SECSPERREPEAT */
-
-#ifndef SECSPERREPEAT_BITS
-#define SECSPERREPEAT_BITS 34 /* ceil(log2(SECSPERREPEAT)) */
-#endif /* !defined SECSPERREPEAT_BITS */
-
-/*
-** UNIX was a registered trademark of The Open Group in 2003.
-*/
+#define isleap_sum(a, b) isleap((a) % 400 + (b) % 400)
#endif /* !defined PRIVATE_H */
diff --git a/scheck.c b/scheck.c
deleted file mode 100644
index 74d9b07c149b..000000000000
--- a/scheck.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
-** This file is in the public domain, so clarified as of
-** 2006-07-17 by Arthur David Olson.
-*/
-
-#ifndef lint
-#ifndef NOID
-static char elsieid[] = "@(#)scheck.c 8.19";
-#endif /* !defined lint */
-#endif /* !defined NOID */
-
-/*LINTLIBRARY*/
-
-#include "private.h"
-
-const char *
-scheck(string, format)
-const char * const string;
-const char * const format;
-{
- register char * fbuf;
- register const char * fp;
- register char * tp;
- register int c;
- register const char * result;
- char dummy;
-
- result = "";
- if (string == NULL || format == NULL)
- return result;
- fbuf = imalloc((int) (2 * strlen(format) + 4));
- if (fbuf == NULL)
- return result;
- fp = format;
- tp = fbuf;
- while ((*tp++ = c = *fp++) != '\0') {
- if (c != '%')
- continue;
- if (*fp == '%') {
- *tp++ = *fp++;
- continue;
- }
- *tp++ = '*';
- if (*fp == '*')
- ++fp;
- while (is_digit(*fp))
- *tp++ = *fp++;
- if (*fp == 'l' || *fp == 'h')
- *tp++ = *fp++;
- else if (*fp == '[')
- do *tp++ = *fp++;
- while (*fp != '\0' && *fp != ']');
- if ((*tp++ = *fp++) == '\0')
- break;
- }
- *(tp - 1) = '%';
- *tp++ = 'c';
- *tp = '\0';
- if (sscanf(string, fbuf, &dummy) != 1)
- result = (char *) format;
- ifree(fbuf);
- return result;
-}
diff --git a/strftime.c b/strftime.c
index d036d07690f6..deba2b5e7a48 100644
--- a/strftime.c
+++ b/strftime.c
@@ -1,41 +1,47 @@
-#ifndef lint
-#ifndef NOID
-static char elsieid[] = "@(#)strftime.c 8.3";
+/* Convert a broken-down timestamp to a string. */
+
+/* Copyright 1989 The Regents of the University of California.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the University nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE. */
+
/*
-** Based on the UCB version with the ID appearing below.
+** Based on the UCB version with the copyright notice appearing above.
+**
** This is ANSIish only when "multibyte character == plain character".
*/
-#endif /* !defined NOID */
-#endif /* !defined lint */
#include "private.h"
-/*
-** Copyright (c) 1989 The Regents of the University of California.
-** All rights reserved.
-**
-** Redistribution and use in source and binary forms are permitted
-** provided that the above copyright notice and this paragraph are
-** duplicated in all such forms and that any documentation,
-** advertising materials, and other materials related to such
-** distribution and use acknowledge that the software was developed
-** by the University of California, Berkeley. The name of the
-** University may not be used to endorse or promote products derived
-** from this software without specific prior written permission.
-** THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
-** IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
-** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
-*/
-
-#ifndef LIBC_SCCS
-#ifndef lint
-static const char sccsid[] = "@(#)strftime.c 5.4 (Berkeley) 3/14/89";
-#endif /* !defined lint */
-#endif /* !defined LIBC_SCCS */
+#include <fcntl.h>
+#include <locale.h>
+#include <stdio.h>
-#include "tzfile.h"
-#include "fcntl.h"
-#include "locale.h"
+#ifndef DEPRECATE_TWO_DIGIT_YEARS
+# define DEPRECATE_TWO_DIGIT_YEARS false
+#endif
struct lc_time_T {
const char * mon[MONSPERYEAR];
@@ -50,16 +56,6 @@ struct lc_time_T {
const char * date_fmt;
};
-#ifdef LOCALE_HOME
-#include "sys/stat.h"
-static struct lc_time_T localebuf;
-static struct lc_time_T * _loc(void);
-#define Locale _loc()
-#endif /* defined LOCALE_HOME */
-#ifndef LOCALE_HOME
-#define Locale (&C_time_locale)
-#endif /* !defined LOCALE_HOME */
-
static const struct lc_time_T C_time_locale = {
{
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
@@ -80,7 +76,7 @@ static const struct lc_time_T C_time_locale = {
/*
** x_fmt
- ** C99 requires this format.
+ ** C99 and later require this format.
** Using just numbers (as here) makes Quakers happier;
** it's also compatible with SVR4.
*/
@@ -88,7 +84,7 @@ static const struct lc_time_T C_time_locale = {
/*
** c_fmt
- ** C99 requires this format.
+ ** C99 and later require this format.
** Previously this code used "%D %X", but we now conform to C99.
** Note that
** "%a %b %d %H:%M:%S %Y"
@@ -106,69 +102,68 @@ static const struct lc_time_T C_time_locale = {
"%a %b %e %H:%M:%S %Z %Y"
};
+enum warn { IN_NONE, IN_SOME, IN_THIS, IN_ALL };
+
static char * _add(const char *, char *, const char *);
static char * _conv(int, const char *, char *, const char *);
static char * _fmt(const char *, const struct tm *, char *, const char *,
- int *);
-static char * _yconv(int, int, int, int, char *, const char *);
-
-extern char * tzname[];
+ enum warn *);
+static char * _yconv(int, int, bool, bool, char *, char const *);
#ifndef YEAR_2000_NAME
-#define YEAR_2000_NAME "CHECK_STRFTIME_FORMATS_FOR_TWO_DIGIT_YEARS"
+# define YEAR_2000_NAME "CHECK_STRFTIME_FORMATS_FOR_TWO_DIGIT_YEARS"
#endif /* !defined YEAR_2000_NAME */
-#define IN_NONE 0
-#define IN_SOME 1
-#define IN_THIS 2
-#define IN_ALL 3
+#if HAVE_STRFTIME_L
+size_t
+strftime_l(char *s, size_t maxsize, char const *format, struct tm const *t,
+ locale_t locale)
+{
+ /* Just call strftime, as only the C locale is supported. */
+ return strftime(s, maxsize, format, t);
+}
+#endif
size_t
-strftime(s, maxsize, format, t)
-char * const s;
-const size_t maxsize;
-const char * const format;
-const struct tm * const t;
+strftime(char *s, size_t maxsize, const char *format, const struct tm *t)
{
char * p;
- int warn;
+ int saved_errno = errno;
+ enum warn warn = IN_NONE;
tzset();
-#ifdef LOCALE_HOME
- localebuf.mon[0] = 0;
-#endif /* defined LOCALE_HOME */
- warn = IN_NONE;
- p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn);
-#ifndef NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU
- if (warn != IN_NONE && getenv(YEAR_2000_NAME) != NULL) {
- (void) fprintf(stderr, "\n");
- if (format == NULL)
- (void) fprintf(stderr, "NULL strftime format ");
- else (void) fprintf(stderr, "strftime format \"%s\" ",
- format);
- (void) fprintf(stderr, "yields only two digits of years in ");
+ p = _fmt(format, t, s, s + maxsize, &warn);
+ if (!p) {
+ errno = EOVERFLOW;
+ return 0;
+ }
+ if (DEPRECATE_TWO_DIGIT_YEARS
+ && warn != IN_NONE && getenv(YEAR_2000_NAME)) {
+ fprintf(stderr, "\n");
+ fprintf(stderr, "strftime format \"%s\" ", format);
+ fprintf(stderr, "yields only two digits of years in ");
if (warn == IN_SOME)
- (void) fprintf(stderr, "some locales");
+ fprintf(stderr, "some locales");
else if (warn == IN_THIS)
- (void) fprintf(stderr, "the current locale");
- else (void) fprintf(stderr, "all locales");
- (void) fprintf(stderr, "\n");
+ fprintf(stderr, "the current locale");
+ else fprintf(stderr, "all locales");
+ fprintf(stderr, "\n");
}
-#endif /* !defined NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU */
- if (p == s + maxsize)
+ if (p == s + maxsize) {
+ errno = ERANGE;
return 0;
+ }
*p = '\0';
+ errno = saved_errno;
return p - s;
}
static char *
-_fmt(format, t, pt, ptlim, warnp)
-const char * format;
-const struct tm * const t;
-char * pt;
-const char * const ptlim;
-int * warnp;
+_fmt(const char *format, const struct tm *t, char *pt,
+ const char *ptlim, enum warn *warnp)
{
+ struct lc_time_T const *Locale = &C_time_locale;
+
for ( ; *format; ++format) {
if (*format == '%') {
label:
@@ -209,12 +204,12 @@ label:
** something completely different.
** (ado, 1993-05-24)
*/
- pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 0,
- pt, ptlim);
+ pt = _yconv(t->tm_year, TM_YEAR_BASE,
+ true, false, pt, ptlim);
continue;
case 'c':
{
- int warn2 = IN_SOME;
+ enum warn warn2 = IN_SOME;
pt = _fmt(Locale->c_fmt, t, pt, ptlim, &warn2);
if (warn2 == IN_ALL)
@@ -232,12 +227,12 @@ label:
case 'E':
case 'O':
/*
- ** C99 locale modifiers.
+ ** Locale modifiers of C99 and later.
** The sequences
** %Ec %EC %Ex %EX %Ey %EY
** %Od %oe %OH %OI %Om %OM
** %OS %Ou %OU %OV %Ow %OW %Oy
- ** are supposed to provide alternate
+ ** are supposed to provide alternative
** representations.
*/
goto label;
@@ -326,11 +321,17 @@ label:
tm = *t;
mkt = mktime(&tm);
- if (TYPE_SIGNED(time_t))
- (void) sprintf(buf, "%ld",
- (long) mkt);
- else (void) sprintf(buf, "%lu",
- (unsigned long) mkt);
+ /* There is no portable, definitive
+ test for whether whether mktime
+ succeeded, so treat (time_t) -1 as
+ the success that it might be. */
+ if (TYPE_SIGNED(time_t)) {
+ intmax_t n = mkt;
+ sprintf(buf, "%"PRIdMAX, n);
+ } else {
+ uintmax_t n = mkt;
+ sprintf(buf, "%"PRIuMAX, n);
+ }
pt = _add(buf, pt, ptlim);
}
continue;
@@ -365,7 +366,7 @@ label:
** (01-53)."
** (ado, 1993-05-24)
**
-** From "http://www.ft.uni-erlangen.de/~mskuhn/iso-time.html" by Markus Kuhn:
+** From <https://www.cl.cam.ac.uk/~mgk25/iso-time.html> by Markus Kuhn:
** "Week 01 of a year is per definition the first week which has the
** Thursday in this year, which is equivalent to the week which contains
** the fourth day of January. In other words, the first week of a new year
@@ -438,9 +439,11 @@ label:
pt, ptlim);
else if (*format == 'g') {
*warnp = IN_ALL;
- pt = _yconv(year, base, 0, 1,
+ pt = _yconv(year, base,
+ false, true,
pt, ptlim);
- } else pt = _yconv(year, base, 1, 1,
+ } else pt = _yconv(year, base,
+ true, true,
pt, ptlim);
}
continue;
@@ -467,7 +470,7 @@ label:
continue;
case 'x':
{
- int warn2 = IN_SOME;
+ enum warn warn2 = IN_SOME;
pt = _fmt(Locale->x_fmt, t, pt, ptlim, &warn2);
if (warn2 == IN_ALL)
@@ -478,40 +481,42 @@ label:
continue;
case 'y':
*warnp = IN_ALL;
- pt = _yconv(t->tm_year, TM_YEAR_BASE, 0, 1,
+ pt = _yconv(t->tm_year, TM_YEAR_BASE,
+ false, true,
pt, ptlim);
continue;
case 'Y':
- pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 1,
+ pt = _yconv(t->tm_year, TM_YEAR_BASE,
+ true, true,
pt, ptlim);
continue;
case 'Z':
#ifdef TM_ZONE
- if (t->TM_ZONE != NULL)
- pt = _add(t->TM_ZONE, pt, ptlim);
- else
-#endif /* defined TM_ZONE */
+ pt = _add(t->TM_ZONE, pt, ptlim);
+#elif HAVE_TZNAME
if (t->tm_isdst >= 0)
pt = _add(tzname[t->tm_isdst != 0],
pt, ptlim);
+#endif
/*
- ** C99 says that %Z must be replaced by the
- ** empty string if the time zone is not
+ ** C99 and later say that %Z must be
+ ** replaced by the empty string if the
+ ** time zone abbreviation is not
** determinable.
*/
continue;
case 'z':
+#if defined TM_GMTOFF || USG_COMPAT || ALTZONE
{
- int diff;
+ long diff;
char const * sign;
+ bool negative;
- if (t->tm_isdst < 0)
- continue;
-#ifdef TM_GMTOFF
+# ifdef TM_GMTOFF
diff = t->TM_GMTOFF;
-#else /* !defined TM_GMTOFF */
+# else
/*
- ** C99 says that the UTC offset must
+ ** C99 and later say that the UT offset must
** be computed by looking only at
** tm_isdst. This requirement is
** incorrect, since it means the code
@@ -519,30 +524,44 @@ label:
** altzone and timezone), and the
** magic might not have the correct
** offset. Doing things correctly is
- ** tricky and requires disobeying C99;
+ ** tricky and requires disobeying the standard;
** see GNU C strftime for details.
** For now, punt and conform to the
** standard, even though it's incorrect.
**
- ** C99 says that %z must be replaced by the
- ** empty string if the time zone is not
+ ** C99 and later say that %z must be replaced by
+ ** the empty string if the time zone is not
** determinable, so output nothing if the
** appropriate variables are not available.
*/
+ if (t->tm_isdst < 0)
+ continue;
if (t->tm_isdst == 0)
-#ifdef USG_COMPAT
+# if USG_COMPAT
diff = -timezone;
-#else /* !defined USG_COMPAT */
+# else
continue;
-#endif /* !defined USG_COMPAT */
+# endif
else
-#ifdef ALTZONE
+# if ALTZONE
diff = -altzone;
-#else /* !defined ALTZONE */
+# else
continue;
-#endif /* !defined ALTZONE */
-#endif /* !defined TM_GMTOFF */
- if (diff < 0) {
+# endif
+# endif
+ negative = diff < 0;
+ if (diff == 0) {
+# ifdef TM_ZONE
+ negative = t->TM_ZONE[0] == '-';
+# else
+ negative = t->tm_isdst < 0;
+# if HAVE_TZNAME
+ if (tzname[t->tm_isdst != 0][0] == '-')
+ negative = true;
+# endif
+# endif
+ }
+ if (negative) {
sign = "-";
diff = -diff;
} else sign = "+";
@@ -552,6 +571,7 @@ label:
(diff % MINSPERHOUR);
pt = _conv(diff, "%04d", pt, ptlim);
}
+#endif
continue;
case '+':
pt = _fmt(Locale->date_fmt, t, pt, ptlim,
@@ -575,23 +595,16 @@ label:
}
static char *
-_conv(n, format, pt, ptlim)
-const int n;
-const char * const format;
-char * const pt;
-const char * const ptlim;
+_conv(int n, const char *format, char *pt, const char *ptlim)
{
char buf[INT_STRLEN_MAXIMUM(int) + 1];
- (void) sprintf(buf, format, n);
+ sprintf(buf, format, n);
return _add(buf, pt, ptlim);
}
static char *
-_add(str, pt, ptlim)
-const char * str;
-char * pt;
-const char * const ptlim;
+_add(const char *str, char *pt, const char *ptlim)
{
while (pt < ptlim && (*pt = *str++) != '\0')
++pt;
@@ -607,18 +620,13 @@ const char * const ptlim;
*/
static char *
-_yconv(a, b, convert_top, convert_yy, pt, ptlim)
-const int a;
-const int b;
-const int convert_top;
-const int convert_yy;
-char * pt;
-const char * const ptlim;
+_yconv(int a, int b, bool convert_top, bool convert_yy,
+ char *pt, const char *ptlim)
{
register int lead;
register int trail;
-#define DIVISOR 100
+ int DIVISOR = 100;
trail = a % DIVISOR + b % DIVISOR;
lead = a / DIVISOR + b / DIVISOR + trail / DIVISOR;
trail %= DIVISOR;
@@ -638,124 +646,3 @@ const char * const ptlim;
pt = _conv(((trail < 0) ? -trail : trail), "%02d", pt, ptlim);
return pt;
}
-
-#ifdef LOCALE_HOME
-static struct lc_time_T *
-_loc(void)
-{
- static const char locale_home[] = LOCALE_HOME;
- static const char lc_time[] = "LC_TIME";
- static char * locale_buf;
-
- int fd;
- int oldsun; /* "...ain't got nothin' to do..." */
- char * lbuf;
- char * name;
- char * p;
- const char ** ap;
- const char * plim;
- char filename[FILENAME_MAX];
- struct stat st;
- size_t namesize;
- size_t bufsize;
-
- /*
- ** Use localebuf.mon[0] to signal whether locale is already set up.
- */
- if (localebuf.mon[0])
- return &localebuf;
- name = setlocale(LC_TIME, (char *) NULL);
- if (name == NULL || *name == '\0')
- goto no_locale;
- /*
- ** If the locale name is the same as our cache, use the cache.
- */
- lbuf = locale_buf;
- if (lbuf != NULL && strcmp(name, lbuf) == 0) {
- p = lbuf;
- for (ap = (const char **) &localebuf;
- ap < (const char **) (&localebuf + 1);
- ++ap)
- *ap = p += strlen(p) + 1;
- return &localebuf;
- }
- /*
- ** Slurp the locale file into the cache.
- */
- namesize = strlen(name) + 1;
- if (sizeof filename <
- ((sizeof locale_home) + namesize + (sizeof lc_time)))
- goto no_locale;
- oldsun = 0;
- (void) sprintf(filename, "%s/%s/%s", locale_home, name, lc_time);
- fd = open(filename, O_RDONLY);
- if (fd < 0) {
- /*
- ** Old Sun systems have a different naming and data convention.
- */
- oldsun = 1;
- (void) sprintf(filename, "%s/%s/%s", locale_home,
- lc_time, name);
- fd = open(filename, O_RDONLY);
- if (fd < 0)
- goto no_locale;
- }
- if (fstat(fd, &st) != 0)
- goto bad_locale;
- if (st.st_size <= 0)
- goto bad_locale;
- bufsize = namesize + st.st_size;
- locale_buf = NULL;
- lbuf = (lbuf == NULL) ? malloc(bufsize) : realloc(lbuf, bufsize);
- if (lbuf == NULL)
- goto bad_locale;
- (void) strcpy(lbuf, name);
- p = lbuf + namesize;
- plim = p + st.st_size;
- if (read(fd, p, (size_t) st.st_size) != st.st_size)
- goto bad_lbuf;
- if (close(fd) != 0)
- goto bad_lbuf;
- /*
- ** Parse the locale file into localebuf.
- */
- if (plim[-1] != '\n')
- goto bad_lbuf;
- for (ap = (const char **) &localebuf;
- ap < (const char **) (&localebuf + 1);
- ++ap) {
- if (p == plim)
- goto bad_lbuf;
- *ap = p;
- while (*p != '\n')
- ++p;
- *p++ = '\0';
- }
- if (oldsun) {
- /*
- ** SunOS 4 used an obsolescent format; see localdtconv(3).
- ** c_fmt had the ``short format for dates and times together''
- ** (SunOS 4 date, "%a %b %e %T %Z %Y" in the C locale);
- ** date_fmt had the ``long format for dates''
- ** (SunOS 4 strftime %C, "%A, %B %e, %Y" in the C locale).
- ** Discard the latter in favor of the former.
- */
- localebuf.date_fmt = localebuf.c_fmt;
- }
- /*
- ** Record the successful parse in the cache.
- */
- locale_buf = lbuf;
-
- return &localebuf;
-
-bad_lbuf:
- free(lbuf);
-bad_locale:
- (void) close(fd);
-no_locale:
- localebuf = C_time_locale;
- locale_buf = NULL;
- return &localebuf;
-}
-#endif /* defined LOCALE_HOME */
diff --git a/theory.html b/theory.html
new file mode 100644
index 000000000000..56390ae44a8d
--- /dev/null
+++ b/theory.html
@@ -0,0 +1,1479 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <title>Theory and pragmatics of the tz code and data</title>
+ <meta charset="UTF-8">
+ <style>
+ pre {margin-left: 2em; white-space: pre-wrap;}
+ </style>
+</head>
+
+<body>
+<h1>Theory and pragmatics of the <code><abbr>tz</abbr></code> code and data</h1>
+ <h3>Outline</h3>
+ <nav>
+ <ul>
+ <li><a href="#scope">Scope of the <code><abbr>tz</abbr></code>
+ database</a></li>
+ <li><a href="#naming">Timezone identifiers</a></li>
+ <li><a href="#abbreviations">Time zone abbreviations</a></li>
+ <li><a href="#accuracy">Accuracy of the <code><abbr>tz</abbr></code>
+ database</a></li>
+ <li><a href="#functions">Time and date functions</a></li>
+ <li><a href="#stability">Interface stability</a></li>
+ <li><a href="#leapsec">Leap seconds</a></li>
+ <li><a href="#calendar">Calendrical issues</a></li>
+ <li><a href="#planets">Time and time zones on other planets</a></li>
+ </ul>
+ </nav>
+
+<section>
+ <h2 id="scope">Scope of the <code><abbr>tz</abbr></code> database</h2>
+<p>
+The <a
+href="https://www.iana.org/time-zones"><code><abbr>tz</abbr></code>
+database</a> attempts to record the history and predicted future of
+civil time scales.
+It organizes <a href="tz-link.html">time zone and daylight saving time
+data</a> by partitioning the world into <a
+href="https://en.wikipedia.org/wiki/List_of_tz_database_time_zones"><dfn>timezones</dfn></a>
+whose clocks all agree about timestamps that occur after the <a
+href="https://en.wikipedia.org/wiki/Unix_time">POSIX Epoch</a>
+(1970-01-01 00:00:00 <a
+href="https://en.wikipedia.org/wiki/Coordinated_Universal_Time"><abbr
+title="Coordinated Universal Time">UTC</abbr></a>).
+Although 1970 is a somewhat-arbitrary cutoff, there are significant
+challenges to moving the cutoff earlier even by a decade or two, due
+to the wide variety of local practices before computer timekeeping
+became prevalent.
+Most timezones correspond to a notable location and the database
+records all known clock transitions for that location;
+some timezones correspond instead to a fixed <abbr>UTC</abbr> offset.
+</p>
+
+<p>
+Each timezone typically corresponds to a geographical region that is
+smaller than a traditional time zone, because clocks in a timezone
+all agree after 1970 whereas a traditional time zone merely
+specifies current standard time. For example, applications that deal
+with current and future timestamps in the traditional North
+American mountain time zone can choose from the timezones
+<code>America/Denver</code> which observes US-style daylight saving
+time (<abbr>DST</abbr>),
+<code>America/Mazatlan</code> which observes Mexican-style <abbr>DST</abbr>,
+and <code>America/Phoenix</code> which does not observe <abbr>DST</abbr>.
+Applications that also deal with past timestamps in the mountain time
+zone can choose from over a dozen timezones, such as
+<code>America/Boise</code>, <code>America/Edmonton</code>, and
+<code>America/Hermosillo</code>, each of which currently uses mountain
+time but differs from other timezones for some timestamps after 1970.
+</p>
+
+<p>
+Clock transitions before 1970 are recorded for location-based timezones,
+because most systems support timestamps before 1970 and could
+misbehave if data entries were omitted for pre-1970 transitions.
+However, the database is not designed for and does not suffice for
+applications requiring accurate handling of all past times everywhere,
+as it would take far too much effort and guesswork to record all
+details of pre-1970 civil timekeeping.
+Although some information outside the scope of the database is
+collected in a file <code>backzone</code> that is distributed along
+with the database proper, this file is less reliable and does not
+necessarily follow database guidelines.
+</p>
+
+<p>
+As described below, reference source code for using the
+<code><abbr>tz</abbr></code> database is also available.
+The <code><abbr>tz</abbr></code> code is upwards compatible with <a
+href="https://en.wikipedia.org/wiki/POSIX">POSIX</a>, an international
+standard for <a
+href="https://en.wikipedia.org/wiki/Unix">UNIX</a>-like systems.
+As of this writing, the current edition of POSIX is: <a
+href="https://pubs.opengroup.org/onlinepubs/9699919799/"> The Open
+Group Base Specifications Issue 7</a>, IEEE Std 1003.1-2017, 2018
+Edition.
+Because the database's scope encompasses real-world changes to civil
+timekeeping, its model for describing time is more complex than the
+standard and daylight saving times supported by POSIX.
+A <code><abbr>tz</abbr></code> timezone corresponds to a ruleset that can
+have more than two changes per year, these changes need not merely
+flip back and forth between two alternatives, and the rules themselves
+can change at times.
+Whether and when a timezone changes its clock,
+and even the timezone's notional base offset from <abbr>UTC</abbr>,
+are variable.
+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.
+Inexperienced users are not expected to select these names unaided.
+Distributors should provide documentation and/or a simple selection
+interface that explains each name via a map or via descriptive text like
+"Czech Republic" instead of the timezone name "<code>Europe/Prague</code>".
+If geolocation information is available, a selection interface can
+locate the user on a timezone map or prioritize names that are
+geographically close. For an example selection interface, see the
+<code>tzselect</code> program in the <code><abbr>tz</abbr></code> code.
+The <a href="https://cldr.unicode.org">Unicode Common Locale Data
+Repository</a> contains data that may be useful for other selection
+interfaces; it maps timezone names like <code>Europe/Prague</code> to
+locale-dependent strings like "Prague", "Praha", "Прага", and "布拉格".
+</p>
+
+<p>
+The naming conventions attempt to strike a balance
+among the following goals:
+</p>
+
+<ul>
+ <li>
+ Uniquely identify every timezone where clocks have agreed since 1970.
+ This is essential for the intended use: static clocks keeping local
+ civil time.
+ </li>
+ <li>
+ Indicate to experts where the timezone's clocks typically are.
+ </li>
+ <li>
+ Be robust in the presence of political changes.
+ For example, names are typically not tied to countries, to avoid
+ incompatibilities when countries change their name (e.g.,
+ Swaziland&rarr;Eswatini) or when locations change countries (e.g., Hong
+ Kong from UK colony to China).
+ There is no requirement that every country or national
+ capital must have a timezone name.
+ </li>
+ <li>
+ Be portable to a wide variety of implementations.
+ </li>
+ <li>
+ Use a consistent naming conventions over the entire world.
+ </li>
+</ul>
+
+<p>
+Names normally have the form
+<var>AREA</var><code>/</code><var>LOCATION</var>, where
+<var>AREA</var> is a continent or ocean, and
+<var>LOCATION</var> is a specific location within the area.
+North and South America share the same area, '<code>America</code>'.
+Typical names are '<code>Africa/Cairo</code>',
+'<code>America/New_York</code>', and '<code>Pacific/Honolulu</code>'.
+Some names are further qualified to help avoid confusion; for example,
+'<code>America/Indiana/Petersburg</code>' distinguishes Petersburg,
+Indiana from other Petersburgs in America.
+</p>
+
+<p>
+Here are the general guidelines used for
+choosing timezone names,
+in decreasing order of importance:
+</p>
+
+<ul>
+ <li>
+ Use only valid POSIX file name components (i.e., the parts of
+ names other than '<code>/</code>').
+ Do not use the file name components '<code>.</code>' and
+ '<code>..</code>'.
+ Within a file name component, use only <a
+ href="https://en.wikipedia.org/wiki/ASCII">ASCII</a> letters,
+ '<code>.</code>', '<code>-</code>' and '<code>_</code>'.
+ Do not use digits, as that might create an ambiguity with <a
+ href="https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03">POSIX
+ <code>TZ</code> strings</a>.
+ A file name component must not exceed 14 characters or start with
+ '<code>-</code>'.
+ E.g., prefer <code>America/Noronha</code> to
+ <code>America/Fernando_de_Noronha</code>.
+ Exceptions: see the discussion of legacy names below.
+ </li>
+ <li>
+ A name must not be empty, or contain '<code>//</code>', or
+ start or end with '<code>/</code>'.
+ </li>
+ <li>
+ Do not use names that differ only in case.
+ Although the reference implementation is case-sensitive, some
+ other implementations are not, and they would mishandle names
+ differing only in case.
+ </li>
+ <li>
+ If one name <var>A</var> is an initial prefix of another
+ name <var>AB</var> (ignoring case), then <var>B</var> must not
+ start with '<code>/</code>', as a regular file cannot have the
+ same name as a directory in POSIX.
+ For example, <code>America/New_York</code> precludes
+ <code>America/New_York/Bronx</code>.
+ </li>
+ <li>
+ Uninhabited regions like the North Pole and Bouvet Island
+ do not need locations, since local time is not defined there.
+ </li>
+ <li>
+ If all the clocks in a timezone have agreed since 1970,
+ do not bother to include more than one timezone
+ even if some of the clocks disagreed before 1970.
+ Otherwise these tables would become annoyingly large.
+ </li>
+ <li>
+ If boundaries between regions are fluid, such as during a war or
+ insurrection, do not bother to create a new timezone merely
+ because of yet another boundary change. This helps prevent table
+ bloat and simplifies maintenance.
+ </li>
+ <li>
+ If a name is ambiguous, use a less ambiguous alternative;
+ e.g., many cities are named San José and Georgetown, so
+ prefer <code>America/Costa_Rica</code> to
+ <code>America/San_Jose</code> and <code>America/Guyana</code>
+ to <code>America/Georgetown</code>.
+ </li>
+ <li>
+ Keep locations compact.
+ Use cities or small islands, not countries or regions, so that any
+ future changes do not split individual locations into different
+ timezones.
+ E.g., prefer <code>Europe/Paris</code> to <code>Europe/France</code>,
+ since
+ <a href="https://en.wikipedia.org/wiki/Time_in_France#History">France
+ has had multiple time zones</a>.
+ </li>
+ <li>
+ Use mainstream English spelling, e.g., prefer
+ <code>Europe/Rome</code> to <code>Europa/Roma</code>, and
+ prefer <code>Europe/Athens</code> to the Greek
+ <code>Ευρώπη/Αθήνα</code> or the Romanized
+ <code>Evrópi/Athína</code>.
+ The POSIX file name restrictions encourage this guideline.
+ </li>
+ <li>
+ Use the most populous among locations in a region,
+ e.g., prefer <code>Asia/Shanghai</code> to
+ <code>Asia/Beijing</code>.
+ Among locations with similar populations, pick the best-known
+ location, e.g., prefer <code>Europe/Rome</code> to
+ <code>Europe/Milan</code>.
+ </li>
+ <li>
+ Use the singular form, e.g., prefer <code>Atlantic/Canary</code> to
+ <code>Atlantic/Canaries</code>.
+ </li>
+ <li>
+ Omit common suffixes like '<code>_Islands</code>' and
+ '<code>_City</code>', unless that would lead to ambiguity.
+ E.g., prefer <code>America/Cayman</code> to
+ <code>America/Cayman_Islands</code> and
+ <code>America/Guatemala</code> to
+ <code>America/Guatemala_City</code>, but prefer
+ <code>America/Mexico_City</code> to
+ <code>America/Mexico</code>
+ because <a href="https://en.wikipedia.org/wiki/Time_in_Mexico">the
+ country of Mexico has several time zones</a>.
+ </li>
+ <li>
+ Use '<code>_</code>' to represent a space.
+ </li>
+ <li>
+ Omit '<code>.</code>' from abbreviations in names.
+ E.g., prefer <code>Atlantic/St_Helena</code> to
+ <code>Atlantic/St._Helena</code>.
+ </li>
+ <li>
+ Do not change established names if they only marginally violate
+ the above guidelines.
+ For example, do not change the existing name <code>Europe/Rome</code> to
+ <code>Europe/Milan</code> merely because Milan's population has grown
+ to be somewhat greater than Rome's.
+ </li>
+ <li>
+ If a name is changed, put its old spelling in the
+ '<code>backward</code>' file as a link to the new spelling.
+ This means old spellings will continue to work.
+ Ordinarily a name change should occur only in the rare case when
+ a location's consensus English-language spelling changes; for example,
+ in 2008 <code>Asia/Calcutta</code> was renamed to <code>Asia/Kolkata</code>
+ due to long-time widespread use of the new city name instead of the old.
+ </li>
+</ul>
+
+<p>
+Guidelines have evolved with time, and names following old versions of
+these guidelines might not follow the current version. When guidelines
+have changed, old names continue to be supported. Guideline changes
+have included the following:
+</p>
+
+<ul>
+<li>
+Older versions of this package used a different naming scheme.
+See the file '<code>backward</code>' for most of these older names
+(e.g., '<code>US/Eastern</code>' instead of '<code>America/New_York</code>').
+The other old-fashioned names still supported are
+'<code>WET</code>', '<code>CET</code>', '<code>MET</code>', and
+'<code>EET</code>' (see the file '<code>europe</code>').
+</li>
+
+<li>
+Older versions of this package defined legacy names that are
+incompatible with the first guideline of location names, but which are
+still supported.
+These legacy names are mostly defined in the file
+'<code>etcetera</code>'.
+Also, the file '<code>backward</code>' defines the legacy names
+'<code>GMT0</code>', '<code>GMT-0</code>' and '<code>GMT+0</code>',
+and the file '<code>northamerica</code>' defines the legacy names
+'<code>EST5EDT</code>', '<code>CST6CDT</code>',
+'<code>MST7MDT</code>', and '<code>PST8PDT</code>'.
+</li>
+
+<li>
+Older versions of these guidelines said that
+there should typically be at least one name for each <a
+href="https://en.wikipedia.org/wiki/ISO_3166-1"><abbr
+title="International Organization for Standardization">ISO</abbr>
+3166-1</a> officially assigned two-letter code for an inhabited
+country or territory.
+This old guideline has been dropped, as it was not needed to handle
+timestamps correctly and it increased maintenance burden.
+</li>
+</ul>
+
+<p>
+The file <code>zone1970.tab</code> lists geographical locations used
+to name timezones.
+It is intended to be an exhaustive list of names for geographic
+regions as described above; this is a subset of the timezones in the data.
+Although a <code>zone1970.tab</code> location's
+<a href="https://en.wikipedia.org/wiki/Longitude">longitude</a>
+corresponds to
+its <a href="https://en.wikipedia.org/wiki/Local_mean_time">local mean
+time (<abbr>LMT</abbr>)</a> offset with one hour for every 15&deg;
+east longitude, this relationship is not exact.
+The backward-compatibility file <code>zone.tab</code> is similar
+but conforms to the older-version guidelines related to <abbr>ISO</abbr> 3166-1;
+it lists only one country code per entry and unlike <code>zone1970.tab</code>
+it can list names defined in <code>backward</code>.
+</p>
+
+<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.
+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
+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 POSIX-style <code>TZ</code> strings;
+no other source file other than <code>backward</code>
+contains links to its zones.
+One of <code>etcetera</code>'s names is <code>Etc/UTC</code>,
+used by functions like <code>gmtime</code> to obtain leap
+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
+like '<code>EST</code>' to be compatible with human tradition and POSIX.
+Here are the general guidelines used for choosing time zone abbreviations,
+in decreasing order of importance:
+</p>
+
+<ul>
+ <li>
+ Use three to six characters that are ASCII alphanumerics or
+ '<code>+</code>' or '<code>-</code>'.
+ Previous editions of this database also used characters like
+ space and '<code>?</code>', but these characters have a
+ special meaning to the
+ <a href="https://en.wikipedia.org/wiki/Unix_shell">UNIX shell</a>
+ and cause commands like
+ '<code><a href="https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#set">set</a>
+ `<a href="https://pubs.opengroup.org/onlinepubs/9699919799/utilities/date.html">date</a>`</code>'
+ to have unexpected effects.
+ Previous editions of this guideline required upper-case letters, but the
+ Congressman who introduced
+ <a href="https://en.wikipedia.org/wiki/Chamorro_Time_Zone">Chamorro
+ Standard Time</a> preferred "ChST", so lower-case letters are now
+ allowed.
+ Also, POSIX from 2001 on relaxed the rule to allow '<code>-</code>',
+ '<code>+</code>', and alphanumeric characters from the portable
+ character set in the current locale.
+ In practice ASCII alphanumerics and '<code>+</code>' and
+ '<code>-</code>' are safe in all locales.
+
+ <p>
+ In other words, in the C locale the POSIX extended regular
+ expression <code>[-+[:alnum:]]{3,6}</code> should match the
+ abbreviation.
+ This guarantees that all abbreviations could have been specified by a
+ POSIX <code>TZ</code> string.
+ </p>
+ </li>
+ <li>
+ Use abbreviations that are in common use among English-speakers,
+ e.g., 'EST' for Eastern Standard Time in North America.
+ We assume that applications translate them to other languages
+ as part of the normal localization process; for example,
+ a French application might translate 'EST' to 'HNE'.
+
+ <p>
+ <small>These abbreviations (for standard/daylight/etc. time) are:
+ ACST/ACDT Australian Central,
+ AST/ADT/APT/AWT/ADDT Atlantic,
+ AEST/AEDT Australian Eastern,
+ AHST/AHDT Alaska-Hawaii,
+ AKST/AKDT Alaska,
+ AWST/AWDT Australian Western,
+ BST/BDT Bering,
+ CAT/CAST Central Africa,
+ CET/CEST/CEMT Central European,
+ ChST Chamorro,
+ CST/CDT/CWT/CPT/CDDT Central [North America],
+ CST/CDT China,
+ GMT/BST/IST/BDST Greenwich,
+ EAT East Africa,
+ EST/EDT/EWT/EPT/EDDT Eastern [North America],
+ EET/EEST Eastern European,
+ GST/GDT Guam,
+ HST/HDT/HWT/HPT Hawaii,
+ HKT/HKST/HKWT Hong Kong,
+ IST India,
+ IST/GMT Irish,
+ IST/IDT/IDDT Israel,
+ JST/JDT Japan,
+ KST/KDT Korea,
+ MET/MEST Middle European (a backward-compatibility alias for
+ Central European),
+ MSK/MSD Moscow,
+ MST/MDT/MWT/MPT/MDDT Mountain,
+ NST/NDT/NWT/NPT/NDDT Newfoundland,
+ NST/NDT/NWT/NPT Nome,
+ NZMT/NZST New Zealand through 1945,
+ NZST/NZDT New Zealand 1946&ndash;present,
+ PKT/PKST Pakistan,
+ PST/PDT/PWT/PPT/PDDT Pacific,
+ PST/PDT Philippine,
+ SAST South Africa,
+ SST Samoa,
+ UTC Universal,
+ WAT/WAST West Africa,
+ WET/WEST/WEMT Western European,
+ WIB Waktu Indonesia Barat,
+ WIT Waktu Indonesia Timur,
+ WITA Waktu Indonesia Tengah,
+ YST/YDT/YWT/YPT/YDDT Yukon</small>.
+ </p>
+ </li>
+ <li>
+ <p>
+ For times taken from a city's longitude, use the
+ traditional <var>x</var>MT notation.
+ The only abbreviation like this in current use is '<abbr>GMT</abbr>'.
+ The others are for timestamps before 1960,
+ except that Monrovia Mean Time persisted until 1972.
+ Typically, numeric abbreviations (e.g., '<code>-</code>004430' for
+ MMT) would cause trouble here, as the numeric strings would exceed
+ the POSIX length limit.
+ </p>
+
+ <p>
+ <small>These abbreviations are:
+ AMT Asunción, Athens;
+ BMT Baghdad, Bangkok, Batavia, Bermuda, Bern, Bogotá, Bridgetown,
+ Brussels, Bucharest;
+ CMT Calamarca, Caracas, Chisinau, Colón, Córdoba;
+ DMT Dublin/Dunsink;
+ EMT Easter;
+ FFMT Fort-de-France;
+ FMT Funchal;
+ GMT Greenwich;
+ HMT Havana, Helsinki, Horta, Howrah;
+ IMT Irkutsk, Istanbul;
+ JMT Jerusalem;
+ KMT Kaunas, Kyiv, Kingston;
+ LMT Lima, Lisbon, local, Luanda;
+ MMT Macassar, Madras, Malé, Managua, Minsk, Monrovia, Montevideo,
+ Moratuwa, Moscow;
+ PLMT Phù Liễn;
+ PMT Paramaribo, Paris, Perm, Pontianak, Prague;
+ PMMT Port Moresby;
+ QMT Quito;
+ RMT Rangoon, Riga, Rome;
+ SDMT Santo Domingo;
+ SJMT San José;
+ SMT Santiago, Simferopol, Singapore, Stanley;
+ TBMT Tbilisi;
+ TMT Tallinn, Tehran;
+ WMT Warsaw;
+ ZMT Zomba.</small>
+ </p>
+
+ <p>
+ <small>A few abbreviations also follow the pattern that
+ <abbr>GMT</abbr>/<abbr>BST</abbr> established for time in the UK.
+ They are:
+ BMT/BST for Bermuda 1890&ndash;1930,
+ CMT/BST for Calamarca Mean Time and Bolivian Summer Time
+ 1890&ndash;1932,
+ DMT/IST for Dublin/Dunsink Mean Time and Irish Summer Time
+ 1880&ndash;1916,
+ MMT/MST/MDST for Moscow 1880&ndash;1919, and
+ RMT/LST for Riga Mean Time and Latvian Summer time 1880&ndash;1926.
+ </small>
+ </p>
+ </li>
+ <li>
+ Use '<abbr>LMT</abbr>' for local mean time of locations before the
+ introduction of standard time; see "<a href="#scope">Scope of the
+ <code><abbr>tz</abbr></code> database</a>".
+ </li>
+ <li>
+ If there is no common English abbreviation, use numeric offsets like
+ <code>-</code>05 and <code>+</code>0530 that are generated
+ by <code>zic</code>'s <code>%z</code> notation.
+ </li>
+ <li>
+ Use current abbreviations for older timestamps to avoid confusion.
+ For example, in 1910 a common English abbreviation for time
+ in central Europe was 'MEZ' (short for both "Middle European
+ Zone" and for "Mitteleuropäische Zeit" in German).
+ Nowadays 'CET' ("Central European Time") is more common in
+ English, and the database uses 'CET' even for circa-1910
+ timestamps as this is less confusing for modern users and avoids
+ the need for determining when 'CET' supplanted 'MEZ' in common
+ usage.
+ </li>
+ <li>
+ Use a consistent style in a timezone's history.
+ For example, if a history tends to use numeric
+ abbreviations and a particular entry could go either way, use a
+ numeric abbreviation.
+ </li>
+ <li>
+ Use
+ <a href="https://en.wikipedia.org/wiki/Universal_Time">Universal Time</a>
+ (<abbr>UT</abbr>) (with time zone abbreviation '<code>-</code>00') for
+ locations while uninhabited.
+ The leading '<code>-</code>' is a flag that the <abbr>UT</abbr> offset is in
+ some sense undefined; this notation is derived
+ from <a href="https://datatracker.ietf.org/doc/html/rfc3339">Internet
+ <abbr title="Request For Comments">RFC</abbr> 3339</a>.
+ </li>
+</ul>
+
+<p>
+Application writers should note that these abbreviations are ambiguous
+in practice: e.g., 'CST' means one thing in China and something else
+in North America, and 'IST' can refer to time in India, Ireland or
+Israel.
+To avoid ambiguity, use numeric <abbr>UT</abbr> offsets like
+'<code>-</code>0600' instead of time zone