1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-10-18 02:19:39 +00:00

Import tzcode 2024a

This commit is contained in:
Dag-Erling Smørgrav 2024-02-13 19:30:52 +01:00
parent d5228e8957
commit 378c74faf3
31 changed files with 2717 additions and 2083 deletions

262
Makefile
View File

@ -1,7 +1,25 @@
# 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.
# Request POSIX conformance; this must be the first non-comment line.
.POSIX:
# On older platforms you may need to scrounge for a POSIX-conforming 'make'.
# For example, on Solaris 10 (2005), use /usr/sfw/bin/gmake or
# /usr/xpg4/bin/make, not /usr/ccs/bin/make.
# To affect how this Makefile works, you can run a shell script like this:
#
# #!/bin/sh
# make CC='gcc -std=gnu11' "$@"
#
# This example script is appropriate for a pre-2017 GNU/Linux system
# where a non-default setting is needed to support this package's use of C99.
#
# Alternatively, you can simply edit this Makefile to tailor the following
# macro definitions.
###############################################################################
# Start of macros that one plausibly might want to tailor.
# Package name for the code distribution.
PACKAGE= tzcode
@ -35,7 +53,7 @@ DATAFORM= main
LOCALTIME= Factory
# The POSIXRULES macro controls interpretation of POSIX-like TZ
# The POSIXRULES macro controls interpretation of POSIX-2017.1-like TZ
# settings like TZ='EET-2EEST' that lack DST transition rules.
# 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:
@ -191,8 +209,9 @@ UTF8_LOCALE= en_US.utf8
# On some hosts, this should have -lintl unless CFLAGS has -DHAVE_GETTEXT=0.
LDLIBS=
# 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".
# Add the following to an uncommented "CFLAGS=" line as needed
# to override defaults specified in the source code or by the system.
# "-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
@ -234,11 +253,16 @@ LDLIBS=
# -DHAVE_UNISTD_H=0 if <unistd.h> does not work*
# -DHAVE_UTMPX_H=0 if <utmpx.h> does not work*
# -Dlocale_t=XXX if your system uses XXX instead of locale_t
# -DPORT_TO_C89 if tzcode should also run on C89 platforms+
# -DPORT_TO_C89 if tzcode should also run on mostly-C89 platforms+
# Typically it is better to use a later standard. For example,
# with GCC 4.9.4 (2016), prefer '-std=gnu11' to '-DPORT_TO_C89'.
# Even with -DPORT_TO_C89, the code needs at least one C99
# feature (integers at least 64 bits wide) and maybe more.
# -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
# -DSUPPORT_C89 if the tzcode library should support C89 callers+
# However, this might trigger latent bugs in C99-or-later callers.
# -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;
@ -250,7 +274,7 @@ LDLIBS=
# -DTZ_DOMAINDIR=\"/path\" to use "/path" for gettext directory;
# the default is system-supplied, typically "/usr/lib/locale"
# -DTZDEFRULESTRING=\",date/time,date/time\" to default to the specified
# DST transitions for POSIX-style TZ strings lacking them,
# DST transitions for POSIX.1-2017-style TZ strings lacking them,
# in the usual case where POSIXRULES is '-'. If not specified,
# TZDEFRULESTRING defaults to US rules for future DST transitions.
# This mishandles some past timestamps, as US DST rules have changed.
@ -270,11 +294,15 @@ LDLIBS=
# -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)
# -g to generate symbolic debugging info
# -Idir to include from directory 'dir'
# -O0 to disable optimization; other -O options to enable more optimization
# -Uname to remove any definition of the macro 'name'
# $(GCC_DEBUG_FLAGS) if you are using recent GCC and want lots of checking
#
# * Options marked "*" can be omitted if your compiler is C23 compatible.
# * Options marked "+" are obsolescent and are planned to be removed
# once the code assumes C99 or later.
# once the code assumes C99 or later, say in the year 2029.
#
# Select instrumentation via "make GCC_INSTRUMENT='whatever'".
GCC_INSTRUMENT = \
@ -312,9 +340,10 @@ GCC_DEBUG_FLAGS = -DGCC_LINT -g3 -O3 -fno-common \
# 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
# 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.
# and define NO_TM_ZONE to suppress any guessing.
# Although these two fields are not required by POSIX.1-2017,
# POSIX 202x/D4 requires 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
@ -324,7 +353,7 @@ GCC_DEBUG_FLAGS = -DGCC_LINT -g3 -O3 -fno-common \
# # -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.
# # to the "CFLAGS=" line. "tzname" is required by POSIX.1-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,
@ -334,8 +363,8 @@ GCC_DEBUG_FLAGS = -DGCC_LINT -g3 -O3 -fno-common \
# # -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.
# # to the "CFLAGS=" line; "timezone" and "daylight" are inspired by Unix
# # Systems Group code and are required by POSIX.1-2008 and later (with XSI).
# # If not defined, the code attempts to guess USG_COMPAT from other macros.
# #
# # To support the external variable "altzone", add
@ -353,9 +382,11 @@ GCC_DEBUG_FLAGS = -DGCC_LINT -g3 -O3 -fno-common \
# functions to be added to the time conversion library.
# "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".
# I.e., "offtime" is like calling "localtime_rz" with a fixed-offset zone.
# "timelocal" is nearly equivalent to "mktime".
# "timeoff" is like "timegm" except that it accepts a second (long) argument
# that gives an offset to use when converting to a time_t.
# I.e., "timeoff" is like calling "mktime_z" with a fixed-offset zone.
# "posix2time" and "time2posix" are described in an included manual page.
# X3J11's work does not describe any of these functions.
# These functions may well disappear in future releases of the time
@ -378,7 +409,7 @@ GCC_DEBUG_FLAGS = -DGCC_LINT -g3 -O3 -fno-common \
#
# 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
# which claims to test C and POSIX conformance. If you want to pass PCTS, add
# -DPCTS
# to the end of the "CFLAGS=" line.
#
@ -388,19 +419,33 @@ GCC_DEBUG_FLAGS = -DGCC_LINT -g3 -O3 -fno-common \
# 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.
#
# POSIX says CFLAGS defaults to "-O 1".
# Uncomment the following line and edit its contents as needed.
CFLAGS=
#CFLAGS= -O 1
# Linker flags. Default to $(LFLAGS) for backwards compatibility
# to release 2012h and earlier.
LDFLAGS= $(LFLAGS)
# The name of a POSIX-like library archiver, its flags, C compiler,
# linker flags, and 'make' utility. Ordinarily the defaults suffice.
# The commented-out values are the defaults specified by POSIX.1-202x/D4.
#AR = ar
#ARFLAGS = -rv
#CC = c17
#LDFLAGS =
#MAKE = make
# For leap seconds, this Makefile uses LEAPSECONDS='-L leapseconds' in
# submake command lines. The default is no leap seconds.
LEAPSECONDS=
# Where to fetch leap-seconds.list from.
leaplist_URI = \
https://hpiers.obspm.fr/iers/bul/bulc/ntp/leap-seconds.list
# The file is generated by the IERS Earth Orientation Centre, in Paris.
leaplist_TZ = Europe/Paris
# The zic command and its arguments.
zic= ./zic
@ -418,22 +463,23 @@ ZFLAGS=
ZIC_INSTALL= $(ZIC) -d '$(DESTDIR)$(TZDIR)' $(LEAPSECONDS)
# The name of a Posix-compliant 'awk' on your system.
# 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 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
# 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.
# Name of curl <https://curl.haxx.se/>, used for HTML validation
# and to fetch leap-seconds.list from upstream.
CURL= curl
# Name of GNU Privacy Guard <https://gnupg.org/>, used to sign distributions.
@ -503,18 +549,17 @@ GZIPFLAGS= -9n
DIFF_TZS= diff -u$$(! diff -u -F'^TZ=' - - <>/dev/null >&0 2>&1 \
|| echo ' -F^TZ=')
###############################################################################
#MAKE= make
cc= cc
CC= $(cc) -DTZDIR='"$(TZDIR)"'
AR= ar
# ':' on typical hosts; 'ranlib' on the ancient hosts that still need ranlib.
RANLIB= :
# POSIX prohibits defining or using SHELL. However, csh users on systems
# that use the user shell for Makefile commands may need to define SHELL.
#SHELL= /bin/sh
# End of macros that one plausibly might want to tailor.
###############################################################################
TZCOBJS= zic.o
TZDOBJS= zdump.o localtime.o asctime.o strftime.o
DATEOBJS= date.o localtime.o strftime.o asctime.o
@ -543,7 +588,7 @@ YDATA= $(PRIMARY_YDATA) etcetera
NDATA= factory
TDATA_TO_CHECK= $(YDATA) $(NDATA) backward
TDATA= $(YDATA) $(NDATA) $(BACKWARD)
ZONETABLES= zone1970.tab zone.tab
ZONETABLES= zone.tab zone1970.tab zonenow.tab
TABDATA= iso3166.tab $(TZDATA_TEXT) $(ZONETABLES)
LEAP_DEPS= leapseconds.awk leap-seconds.list
TZDATA_ZI_DEPS= ziguard.awk zishrink.awk version $(TDATA) \
@ -551,7 +596,7 @@ TZDATA_ZI_DEPS= ziguard.awk zishrink.awk version $(TDATA) \
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 \
AWK_SCRIPTS= checklinks.awk checknow.awk checktab.awk leapseconds.awk \
ziguard.awk zishrink.awk
MISC= $(AWK_SCRIPTS)
TZS_YEAR= 2050
@ -572,7 +617,7 @@ VERSION_DEPS= \
calendars CONTRIBUTING LICENSE Makefile NEWS README SECURITY \
africa antarctica asctime.c asia australasia \
backward backzone \
checklinks.awk checktab.awk \
checklinks.awk checknow.awk checktab.awk \
date.1 date.c difftime.c \
etcetera europe factory iso3166.tab \
leap-seconds.list leapseconds.awk localtime.c \
@ -582,12 +627,7 @@ VERSION_DEPS= \
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
zone.tab zone1970.tab zonenow.tab
all: tzselect zic zdump libtz.a $(TABDATA) \
vanguard.zi main.zi rearguard.zi
@ -657,6 +697,16 @@ tzdata.zi: $(DATAFORM).zi version zishrink.awk
$(DATAFORM).zi >$@.out
mv $@.out $@
tzdir.h:
printf '%s\n' >$@.out \
'#ifndef TZDEFAULT' \
'# define TZDEFAULT "$(TZDEFAULT)" /* default zone */' \
'#endif' \
'#ifndef TZDIR' \
'# define TZDIR "$(TZDIR)" /* TZif directory */' \
'#endif'
mv $@.out $@
version.h: version
VERSION=`cat version` && printf '%s\n' \
'static char const PKGVERSION[]="($(PACKAGE)) ";' \
@ -676,6 +726,28 @@ leapseconds: $(LEAP_DEPS)
-f leapseconds.awk leap-seconds.list >$@.out
mv $@.out $@
# Awk script to extract a Git-style author from leap-seconds.list comments.
EXTRACT_AUTHOR = \
author_line { sub(/^.[[:space:]]*/, ""); \
sub(/:[[:space:]]*/, " <"); \
printf "%s>\n", $$0; \
success = 1; \
exit \
} \
/Questions or comments to:/ { author_line = 1 } \
END { exit !success }
# Fetch leap-seconds.list from upstream.
fetch-leap-seconds.list:
$(CURL) -OR $(leaplist_URI)
# Fetch leap-seconds.list from upstream and commit it to the local repository.
commit-leap-seconds.list: fetch-leap-seconds.list
author=$$($(AWK) '$(EXTRACT_AUTHOR)' leap-seconds.list) && \
date=$$(TZ=$(leaplist_TZ) stat -c%y leap-seconds.list) && \
git commit --author="$$author" --date="$$date" -m'make $@' \
leap-seconds.list
# Arguments to pass to submakes of install_data.
# They can be overridden by later submake arguments.
INSTALLARGS = \
@ -763,7 +835,7 @@ force_tzs: $(TZS_NEW)
libtz.a: $(LIBOBJS)
rm -f $@
$(AR) -rc $@ $(LIBOBJS)
$(AR) $(ARFLAGS) $@ $(LIBOBJS)
$(RANLIB) $@
date: $(DATEOBJS)
@ -771,26 +843,32 @@ date: $(DATEOBJS)
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)|' \
-e 's|\(TZVERSION\)=.*|\1='"$$VERSION"'|' \
<$@.ksh >$@.out
-e "s'#!/bin/bash'#!"'$(KSHELL)'\' \
-e s\''\(AWK\)=[^}]*'\''\1=\'\''$(AWK)\'\'\' \
-e s\''\(PKGVERSION\)=.*'\''\1=\'\''($(PACKAGE)) \'\'\' \
-e s\''\(REPORT_BUGS_TO\)=.*'\''\1=\'\''$(BUGEMAIL)\'\'\' \
-e s\''\(TZDIR\)=[^}]*'\''\1=\'\''$(TZDIR)\'\'\' \
-e s\''\(TZVERSION\)=.*'\''\1=\'"'$$VERSION\\''" \
<$@.ksh >$@.out
chmod +x $@.out
mv $@.out $@
check: check_back check_mild
check_mild: check_character_set check_white_space check_links \
check_name_lengths check_slashed_abbrs check_sorted \
check_name_lengths check_now \
check_slashed_abbrs check_sorted \
check_tables check_web check_ziguard check_zishrink check_tzs
# True if UTF8_LOCALE does not work;
# otherwise, false but with LC_ALL set to $(UTF8_LOCALE).
UTF8_LOCALE_MISSING = \
{ test ! '$(UTF8_LOCALE)' \
|| ! printf 'A\304\200B\n' \
| LC_ALL='$(UTF8_LOCALE)' grep -q '^A.B$$' >/dev/null 2>&1 \
|| { LC_ALL='$(UTF8_LOCALE)'; export LC_ALL; false; }; }
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 && \
$(UTF8_LOCALE_MISSING) || { \
sharp='#' && \
! grep -Env $(SAFE_LINE) $(MANS) date.1 $(MANTXTS) \
$(MISC) $(SOURCES) $(WEB_PAGES) \
@ -805,12 +883,12 @@ check_character_set: $(ENCHILADA)
touch $@
check_white_space: $(ENCHILADA)
$(UTF8_LOCALE_MISSING) || { \
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 $@
! grep -En "$$pat|[$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}
@ -851,7 +929,29 @@ check_links: checklinks.awk tzdata.zi
-f checklinks.awk tzdata.zi
touch $@
check_tables: checktab.awk $(YDATA) backward $(ZONETABLES)
# Check timestamps from now through 28 years from now, to make sure
# that zonenow.tab contains all sequences of planned timestamps,
# without any duplicate sequences. In theory this might require
# 2800 years but that would take a long time to check.
CHECK_NOW_TIMESTAMP = `./date +%s`
CHECK_NOW_FUTURE_YEARS = 28
CHECK_NOW_FUTURE_SECS = $(CHECK_NOW_FUTURE_YEARS) '*' 366 '*' 24 '*' 60 '*' 60
check_now: checknow.awk date tzdata.zi zdump zic zone1970.tab zonenow.tab
rm -fr $@.dir
mkdir $@.dir
./zic -d $@.dir tzdata.zi
now=$(CHECK_NOW_TIMESTAMP) && \
future=`expr $(CHECK_NOW_FUTURE_SECS) + $$now` && \
./zdump -i -t $$now,$$future \
$$(find $$PWD/$@.dir/????*/ -type f) \
>$@.dir/zdump.tab
$(AWK) \
-v zdump_table=$@.dir/zdump.tab \
-f checknow.awk zonenow.tab
rm -fr $@.dir
touch $@
check_tables: checktab.awk $(YDATA) backward zone.tab zone1970.tab
for tab in $(ZONETABLES); do \
test "$$tab" = zone.tab && links='$(BACKWARD)' || links=''; \
$(AWK) -f checktab.awk -v zone_table=$$tab $(YDATA) $$links \
@ -911,10 +1011,10 @@ check_zishrink_posix check_zishrink_right: \
touch $@
clean_misc:
rm -fr check_*.dir
rm -fr check_*.dir typecheck_*.dir
rm -f *.o *.out $(TIME_T_ALTERNATIVES) \
check_* core typecheck_* \
date tzselect version.h zdump zic libtz.a
date tzdir.h tzselect version.h zdump zic libtz.a
clean: clean_misc
rm -fr *.dir tzdb-*/
rm -f *.zi $(TZS_NEW)
@ -952,12 +1052,18 @@ $(MANTXTS): workman.sh
# 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" && \
<"$$dest" && \
if test $$n != 0 && \
lsout=`ls -n --time-style="+%s" "$$dest" 2>/dev/null`; then \
lsout=`ls -nt --time-style="+%s" "$$@" 2>/dev/null`; then \
set x $$lsout && \
touch -cmd @`expr $$7 + $$n` "$$dest"; \
else :; fi'
timestamp=`expr $$7 + $$n` && \
echo "+ touch -md @$$timestamp $$dest" && \
touch -md @$$timestamp "$$dest"; \
else \
newest=`ls -t "$$@" | sed 1q` && \
echo "+ touch -mr $$newest $$dest" && \
touch -mr "$$newest" "$$dest"; \
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.
@ -982,8 +1088,12 @@ set-timestamps.out: $(EIGHT_YARDS)
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; \
time=`TZ=UTC0 git log -1 \
--format='tformat:%cd' \
--date='format:%Y-%m-%dT%H:%M:%SZ' \
$$file` && \
echo "+ touch -md $$time $$file" && \
touch -md $$time $$file; \
else \
echo >&2 "$$file: warning: does not match repository"; \
fi || exit; \
@ -1008,7 +1118,8 @@ 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
cd public.dir \
&& $(MAKE) CFLAGS='$(GCC_DEBUG_FLAGS)' TZDIR='$(TZDIR)' ALL
for i in $(TDATA_TO_CHECK) public.dir/tzdata.zi \
public.dir/vanguard.zi public.dir/main.zi \
public.dir/rearguard.zi; \
@ -1139,7 +1250,7 @@ tzdata$(VERSION)-rearguard.tar.gz: rearguard.zi set-timestamps.out
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
touch -mr version $@.dir/version
LC_ALL=C && export LC_ALL && \
(cd $@.dir && \
tar $(TARFLAGS) -cf - \
@ -1163,7 +1274,7 @@ tzdata$(VERSION)-tailored.tar.gz: set-timestamps.out
`test $(DATAFORM) = vanguard || echo pacificnew`
(grep '^#' tzdata.zi && echo && cat $(DATAFORM).zi) \
>$@.dir/etcetera
touch -cmr tzdata.zi $@.dir/etcetera
touch -mr tzdata.zi $@.dir/etcetera
sed -n \
-e '/^# *version *\(.*\)/h' \
-e '/^# *ddeps */H' \
@ -1174,7 +1285,7 @@ tzdata$(VERSION)-tailored.tar.gz: set-timestamps.out
-e 's/ /-/g' \
-e 'p' \
<tzdata.zi >$@.dir/version
touch -cmr version $@.dir/version
touch -mr version $@.dir/version
links= && \
for file in $(TZDATA_DIST); do \
test -f $@.dir/$$file || links="$$links $$file"; \
@ -1226,15 +1337,16 @@ zonenames: tzdata.zi
asctime.o: private.h tzfile.h
date.o: private.h
difftime.o: private.h
localtime.o: private.h tzfile.h
localtime.o: private.h tzfile.h tzdir.h
strftime.o: private.h tzfile.h
zdump.o: version.h
zic.o: private.h tzfile.h version.h
zic.o: private.h tzfile.h tzdir.h version.h
.PHONY: ALL INSTALL all
.PHONY: check check_mild check_time_t_alternatives
.PHONY: check_web check_zishrink
.PHONY: clean clean_misc dummy.zd force_tzs
.PHONY: clean clean_misc commit-leap-seconds.list dummy.zd
.PHONY: fetch-leap-seconds.list force_tzs
.PHONY: install install_data maintainer-clean names
.PHONY: posix_only posix_right public
.PHONY: rearguard_signatures rearguard_signatures_version

193
NEWS
View File

@ -1,5 +1,177 @@
News for the tz database
Release 2024a - 2024-02-01 09:28:56 -0800
Briefly:
Kazakhstan unifies on UTC+5 beginning 2024-03-01.
Palestine springs forward a week later after Ramadan.
zic no longer pretends to support indefinite-past DST.
localtime no longer mishandles Ciudad Juárez in 2422.
Changes to future timestamps
Kazakhstan unifies on UTC+5. This affects Asia/Almaty and
Asia/Qostanay which together represent the eastern portion of the
country that will transition from UTC+6 on 2024-03-01 at 00:00 to
join the western portion. (Thanks to Zhanbolat Raimbekov.)
Palestine springs forward a week later than previously predicted
in 2024 and 2025. (Thanks to Heba Hamad.) Change spring-forward
predictions to the second Saturday after Ramadan, not the first;
this also affects other predictions starting in 2039.
Changes to past timestamps
Asia/Ho_Chi_Minh's 1955-07-01 transition occurred at 01:00
not 00:00. (Thanks to Đoàn Trần Công Danh.)
From 1947 through 1949, Toronto's transitions occurred at 02:00
not 00:00. (Thanks to Chris Walton.)
In 1911 Miquelon adopted standard time on June 15, not May 15.
Changes to code
The FROM and TO columns of Rule lines can no longer be "minimum"
or an abbreviation of "minimum", because TZif files do not support
DST rules that extend into the indefinite past - although these
rules were supported when TZif files had only 32-bit data, this
stopped working when 64-bit TZif files were introduced in 1995.
This should not be a problem for realistic data, since DST was
first used in the 20th century. As a transition aid, FROM columns
like "minimum" are now diagnosed and then treated as if they were
the year 1900; this should suffice for TZif files on old systems
with only 32-bit time_t, and it is more compatible with bugs in
2023c-and-earlier localtime.c. (Problem reported by Yoshito
Umaoka.)
localtime and related functions no longer mishandle some
timestamps that occur about 400 years after a switch to a time
zone with a DST schedule. In 2023d data this problem was visible
for some timestamps in November 2422, November 2822, etc. in
America/Ciudad_Juarez. (Problem reported by Gilmore Davidson.)
strftime %s now uses tm_gmtoff if available. (Problem and draft
patch reported by Dag-Erling Smørgrav.)
Changes to build procedure
The leap-seconds.list file is now copied from the IERS instead of
from its downstream counterpart at NIST, as the IERS version is
now in the public domain too and tends to be more up-to-date.
(Thanks to Martin Burnicki for liaisoning with the IERS.)
Changes to documentation
The strftime man page documents which struct tm members affect
which conversion specs, and that tzset is called. (Problems
reported by Robert Elz and Steve Summit.)
Release 2023d - 2023-12-21 20:02:24 -0800
Briefly:
Ittoqqortoormiit, Greenland changes time zones on 2024-03-31.
Vostok, Antarctica changed time zones on 2023-12-18.
Casey, Antarctica changed time zones five times since 2020.
Code and data fixes for Palestine timestamps starting in 2072.
A new data file zonenow.tab for timestamps starting now.
Changes to future timestamps
Ittoqqortoormiit, Greenland (America/Scoresbysund) joins most of
the rest of Greenland's timekeeping practice on 2024-03-31, by
changing its time zone from -01/+00 to -02/-01 at the same moment
as the spring-forward transition. Its clocks will therefore not
spring forward as previously scheduled. The time zone change
reverts to its common practice before 1981.
Fix predictions for DST transitions in Palestine in 2072-2075,
correcting a typo introduced in 2023a.
Changes to past and future timestamps
Vostok, Antarctica changed to +05 on 2023-12-18. It had been at
+07 (not +06) for years. (Thanks to Zakhary V. Akulov.)
Change data for Casey, Antarctica to agree with timeanddate.com,
by adding five time zone changes since 2020. Casey is now at +08
instead of +11.
Changes to past tm_isdst flags
Much of Greenland, represented by America/Nuuk, changed its
standard time from -03 to -02 on 2023-03-25, not on 2023-10-28.
This does not affect UTC offsets, only the tm_isdst flag.
(Thanks to Thomas M. Steenholdt.)
New data file
A new data file zonenow.tab helps configure applications that use
timestamps dated from now on. This simplifies configuration,
since users choose from a smaller Zone set. The file's format is
experimental and subject to change.
Changes to code
localtime.c no longer mishandles TZif files that contain a single
transition into a DST regime. Previously, it incorrectly assumed
DST was in effect before the transition too. (Thanks to Alois
Treindl for debugging help.)
localtime.c's timeoff no longer collides with OpenBSD 7.4.
The C code now uses _Generic only if __STDC_VERSION__ says the
compiler is C11 or later.
tzselect now optionally reads zonenow.tab, to simplify when
configuring only for timestamps dated from now on.
tzselect no longer creates temporary files.
tzselect no longer mishandles the following:
Spaces and most other special characters in BUGEMAIL, PACKAGE,
TZDIR, and VERSION.
TZ strings when using mawk 1.4.3, which mishandles regular
expressions of the form /X{2,}/.
ISO 6709 coordinates when using an awk that lacks the GNU
extension of newlines in -v option-arguments.
Non UTF-8 locales when using an iconv command that lacks the GNU
//TRANSLIT extension.
zic no longer mishandles data for Palestine after the year 2075.
Previously, it incorrectly omitted post-2075 transitions that are
predicted for just before and just after Ramadan. (Thanks to Ken
Murchison for debugging help.)
zic now works again on Linux 2.6.16 and 2.6.17 (2006).
(Problem reported by Rune Torgersen.)
Changes to build procedure
The Makefile is now more compatible with POSIX:
* It no longer defines AR, CC, CFLAGS, LDFLAGS, and SHELL.
* It no longer uses its own 'cc' in place of CC.
* It now uses ARFLAGS, with default specified by POSIX.
* It does not use LFLAGS incompatibly with POSIX.
* It uses the special .POSIX target.
* It quotes special characters more carefully.
* It no longer mishandles builds in an ISO 8859 locale.
Due to the CC changes, TZDIR is now #defined in a file tzfile.h
built by 'make', not in a $(CC) -D option. Also, TZDEFAULT is
now treated like TZDIR as they have similar roles.
Changes to commentary
Limitations and hazards of the optional support for obsolescent
C89 platforms are documented better, along with a tentative
schedule for removing this support.
Release 2023c - 2023-03-28 12:42:14 -0700
Changes to past and future timestamps
@ -76,11 +248,14 @@ Release 2023a - 2023-03-22 12:39:33 -0700
platform dependent and abbreviations were silently truncated to
16 bytes even when the limit was greater than 16.
The code by default is now designed for C99 or later. To build in
a C89 environment, compile with -DPORT_TO_C89. To support C89
callers of the tzcode library, compile with -DSUPPORT_C89. The
two new macros are transitional aids planned to be removed in a
future version, when C99 or later will be required.
The code by default is now designed for C99 or later. To build on
a mostly-C89 platform, compile with -DPORT_TO_C89; this should
work on C89 platforms that also support C99 'long long' and
perhaps a few other extensions to C89. To support C89 callers of
tzcode's library, compile with -DSUPPORT_C89; however, this could
trigger latent bugs in C99-or-later callers. The two new macros
are transitional aids planned to be removed in a future version
(say, in 2029), when C99 or later will be required.
The code now builds again on pre-C99 platforms, if you compile
with -DPORT_TO_C89. This fixes a bug introduced in 2022f.
@ -723,6 +898,8 @@ Release 2021b - 2021-09-24 16:23:00 -0700
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.
The old-format "#expires" comments are now treated solely as
comments and have no effect on the TZif files.
zic -L LEAPFILE -r @LO no longer generates an invalid TZif file
that omits leap second information for the range LO..B when LO
@ -4302,7 +4479,7 @@ Release 2012j - 2012-11-12 18:34:49 -0800
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
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,
@ -4467,8 +4644,8 @@ 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)
made in all 4 Ukrainian zones, rather than just Europe/Kiev
(again, thanks to Tim Parenti, and also Denys Gavrysh).
In addition, I added Europe/Tiraspol to zone.tab.

17
README
View File

@ -11,14 +11,17 @@ changes made by political bodies to time zone boundaries, UTC offsets,
and daylight-saving rules.
See <https://www.iana.org/time-zones/repository/tz-link.html> or the
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":
file tz-link.html for how to acquire the code and data.
make TOPDIR=$HOME/tzdir install
$HOME/tzdir/usr/bin/zdump -v America/Los_Angeles
Once acquired, read the leading comments in the file "Makefile"
and make any changes needed to make things right for your system,
especially when using a platform other than current GNU/Linux.
Then run the following commands, substituting your desired
installation directory for "$HOME/tzdir":
make TOPDIR="$HOME/tzdir" install
"$HOME/tzdir/usr/bin/zdump" -v America/Los_Angeles
See the file tz-how-to.html for examples of how to read the data files.

14
date.1
View File

@ -154,15 +154,11 @@ hexadecimal (leading 0x), preceded by an optional sign.
.br
/usr/lib/locale/\f2L\fP/LC_TIME description of time locale \f2L\fP
.br
/usr/share/zoneinfo timezone information directory
/usr/share/zoneinfo timezone directory
.br
/usr/share/zoneinfo/posixrules default DST rules (obsolete,
and can cause bugs if present)
/usr/share/zoneinfo/posixrules default DST rules (obsolete)
.br
/usr/share/zoneinfo/GMT for UTC leap seconds
.sp
If
.B /usr/share/zoneinfo/GMT
is absent,
UTC leap seconds are loaded from
.BR /usr/share/zoneinfo/posixrules .
.PP
If /usr/share/zoneinfo/GMT is absent,
UTC leap seconds are loaded from /usr/share/zoneinfo/GMT0 if present.

View File

@ -89,20 +89,19 @@ DESCRIPTION
Use Universal Time when setting and showing the date and 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),
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
/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 default DST rules (obsolete,
and can cause bugs if present)
/usr/share/zoneinfo timezone directory
/usr/share/zoneinfo/posixrules default DST rules (obsolete)
/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/share/zoneinfo/GMT is absent, UTC leap seconds are loaded from
/usr/share/zoneinfo/GMT0 if present.
Time Zone Database date(1)

View File

@ -7,7 +7,7 @@
/*
** Leap second handling from Bradley White.
** POSIX-style TZ environment variable handling from Guy Harris.
** POSIX.1-1988 style TZ environment variable handling from Guy Harris.
*/
/*LINTLIBRARY*/
@ -15,6 +15,7 @@
#define LOCALTIME_IMPLEMENTATION
#include "private.h"
#include "tzdir.h"
#include "tzfile.h"
#include <fcntl.h>
@ -105,12 +106,17 @@ static char const UNSPEC[] = "-00";
for ttunspecified to work without crashing. */
enum { CHARS_EXTRA = max(sizeof UNSPEC, 2) - 1 };
/* Limit to time zone abbreviation length in POSIX-style TZ strings.
/* Limit to time zone abbreviation length in POSIX.1-2017-style TZ strings.
This is distinct from TZ_MAX_CHARS, which limits TZif file contents. */
#ifndef TZNAME_MAXIMUM
# define TZNAME_MAXIMUM 255
#endif
/* A representation of the contents of a TZif file. Ideally this
would have no size limits; the following sizes should suffice for
practical use. This struct should not be too large, as instances
are put on the stack and stacks are relatively small on some platforms.
See tzfile.h for more about the sizes. */
struct state {
int leapcnt;
int timecnt;
@ -153,8 +159,7 @@ 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 *);
static bool tzparse(char const *, struct state *, struct state const *);
#ifdef ALL_STATE
static struct state * lclptr;
@ -369,7 +374,8 @@ union input_buffer {
/* The first part of the buffer, interpreted as a header. */
struct tzhead tzhead;
/* The entire buffer. */
/* The entire buffer. Ideally this would have no size limits;
the following should suffice for practical use. */
char buf[2 * sizeof(struct tzhead) + 2 * sizeof(struct state)
+ 4 * TZ_MAX_TIMES];
};
@ -388,7 +394,12 @@ union local_storage {
struct state st;
} u;
/* The file name to be opened. */
/* The name of the file to be opened. Ideally this would have no
size limits, to support arbitrarily long Zone names.
Limiting Zone names to 1024 bytes should suffice for practical use.
However, there is no need for this to be smaller than struct
file_analysis as that struct is allocated anyway, as the other
union member. */
char fullname[max(sizeof(struct file_analysis), sizeof tzdirslash + 1024)];
};
@ -674,14 +685,18 @@ tzloadbody(char const *name, struct state *sp, bool doextend,
== sp->types[sp->timecnt - 2]))
sp->timecnt--;
for (i = 0;
i < ts->timecnt && sp->timecnt < TZ_MAX_TIMES;
i++) {
sp->goahead = ts->goahead;
for (i = 0; i < ts->timecnt; 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;
if (TZ_MAX_TIMES <= sp->timecnt) {
sp->goahead = false;
break;
}
sp->ats[sp->timecnt] = t;
sp->types[sp->timecnt] = (sp->typecnt
+ ts->types[i]);
@ -694,28 +709,6 @@ tzloadbody(char const *name, struct state *sp, bool doextend,
}
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 (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 (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,
@ -792,31 +785,6 @@ tzload(char const *name, struct state *sp, bool doextend)
#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;
else {
/* Compare the relevant members of *AP and *BP.
Ignore tt_ttisstd and tt_ttisut, as they are
irrelevant now and counting them could cause
sp->goahead to mistakenly remain false. */
register const struct ttinfo * ap = &sp->ttis[a];
register const struct ttinfo * bp = &sp->ttis[b];
result = (ap->tt_utoff == bp->tt_utoff
&& ap->tt_isdst == bp->tt_isdst
&& (strcmp(&sp->chars[ap->tt_desigidx],
&sp->chars[bp->tt_desigidx])
== 0));
}
return result;
}
static const int mon_lengths[2][MONSPERYEAR] = {
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
@ -913,8 +881,8 @@ getsecs(register const char *strp, int_fast32_t *const secsp)
int_fast32_t secsperhour = SECSPERHOUR;
/*
** 'HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
** "M10.4.6/26", which does not conform to Posix,
** '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".
*/
@ -967,7 +935,8 @@ getoffset(register const char *strp, int_fast32_t *const offsetp)
/*
** 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".
** date[/time]. See POSIX Base Definitions section 8.3 variable TZ
** 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.
*/
@ -1111,12 +1080,12 @@ transtime(const int year, register const struct rule *const rulep,
}
/*
** Given a POSIX section 8-style TZ string, fill in the rule tables as
** Given a POSIX.1-2017-style TZ string, fill in the rule tables as
** appropriate.
*/
static bool
tzparse(const char *name, struct state *sp, struct state *basep)
tzparse(const char *name, struct state *sp, struct state const *basep)
{
const char * stdname;
const char * dstname;
@ -1159,6 +1128,7 @@ tzparse(const char *name, struct state *sp, struct state *basep)
}
if (0 < sp->leapcnt)
leaplo = sp->lsis[sp->leapcnt - 1].ls_trans;
sp->goback = sp->goahead = false;
if (*name != '\0') {
if (*name == '<') {
dstname = ++name;
@ -1206,7 +1176,6 @@ tzparse(const char *name, struct state *sp, struct state *basep)
*/
init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
init_ttinfo(&sp->ttis[1], -dstoffset, true, stdlen + 1);
sp->defaulttype = 0;
timecnt = 0;
janfirst = 0;
yearbeg = EPOCH_YEAR;
@ -1236,7 +1205,7 @@ tzparse(const char *name, struct state *sp, struct state *basep)
}
yearlim = yearbeg;
if (increment_overflow(&yearlim, YEARSPERREPEAT + 1))
if (increment_overflow(&yearlim, years_of_observations))
yearlim = INT_MAX;
for (year = yearbeg; year < yearlim; year++) {
int_fast32_t
@ -1273,7 +1242,7 @@ tzparse(const char *name, struct state *sp, struct state *basep)
if (endtime < leaplo) {
yearlim = year;
if (increment_overflow(&yearlim,
YEARSPERREPEAT + 1))
years_of_observations))
yearlim = INT_MAX;
}
if (increment_overflow_time
@ -1285,7 +1254,7 @@ tzparse(const char *name, struct state *sp, struct state *basep)
if (! timecnt) {
sp->ttis[0] = sp->ttis[1];
sp->typecnt = 1; /* Perpetual DST. */
} else if (YEARSPERREPEAT < year - yearbeg)
} else if (years_of_observations <= year - yearbeg)
sp->goback = sp->goahead = true;
} else {
register int_fast32_t theirstdoffset;
@ -1344,8 +1313,8 @@ tzparse(const char *name, struct state *sp, struct state *basep)
/*
** Transitions from DST to DDST
** will effectively disappear since
** POSIX provides for only one DST
** offset.
** POSIX.1-2017 provides for only one
** DST offset.
*/
if (isdst && !sp->ttis[j].tt_ttisstd) {
sp->ats[i] += dstoffset -
@ -1366,15 +1335,14 @@ tzparse(const char *name, struct state *sp, struct state *basep)
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;
init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
sp->defaulttype = 0;
}
sp->defaulttype = 0;
sp->charcnt = charcnt;
cp = sp->chars;
memcpy(cp, stdname, stdlen);
@ -1516,7 +1484,8 @@ tzfree(timezone_t sp)
**
** 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,
** however, it's OK to omit this step
** if the timezone is compatible with POSIX.1-2017
** 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.
@ -1703,6 +1672,9 @@ gmtime(const time_t *timep)
#if STD_INSPIRED
/* This function is obsolescent and may disappear in future releases.
Callers can instead use localtime_rz with a fixed-offset zone. */
struct tm *
offtime(const time_t *timep, long offset)
{
@ -2313,6 +2285,8 @@ mktime(struct tm *tmp)
}
#if STD_INSPIRED
/* This function is obsolescent and may disapper in future releases.
Callers can instead use mktime. */
time_t
timelocal(struct tm *tmp)
{
@ -2320,10 +2294,18 @@ timelocal(struct tm *tmp)
tmp->tm_isdst = -1; /* in case it wasn't initialized */
return mktime(tmp);
}
#else
static
#endif
time_t
#ifndef EXTERN_TIMEOFF
# ifndef timeoff
# define timeoff my_timeoff /* Don't collide with OpenBSD 7.4 <time.h>. */
# endif
# define EXTERN_TIMEOFF static
#endif
/* This function is obsolescent and may disapper in future releases.
Callers can instead use mktime_z with a fixed-offset zone. */
EXTERN_TIMEOFF time_t
timeoff(struct tm *tmp, long offset)
{
if (tmp)

View File

@ -292,20 +292,16 @@ will
continue to exist in this form in future releases of this code.
.SH FILES
.ta \w'/usr/share/zoneinfo/posixrules\0\0'u
/usr/share/zoneinfo timezone information directory
/etc/localtime local timezone file
.br
/usr/share/zoneinfo/localtime local timezone file
/usr/share/zoneinfo timezone directory
.br
/usr/share/zoneinfo/posixrules default DST rules (obsolete,
and can cause bugs if present)
/usr/share/zoneinfo/posixrules default DST rules (obsolete)
.br
/usr/share/zoneinfo/GMT for UTC leap seconds
.sp
If
.B /usr/share/zoneinfo/GMT
is absent,
UTC leap seconds are loaded from
.BR /usr/share/zoneinfo/posixrules .
.PP
If /usr/share/zoneinfo/GMT is absent,
UTC leap seconds are loaded from /usr/share/zoneinfo/GMT0 if present.
.SH SEE ALSO
getenv(3),
newstrftime(3),

View File

@ -143,14 +143,13 @@ DESCRIPTION
exist in this form in future releases of this code.
FILES
/usr/share/zoneinfo timezone information directory
/usr/share/zoneinfo/localtime local timezone file
/usr/share/zoneinfo/posixrules default DST rules (obsolete,
and can cause bugs if present)
/etc/localtime local timezone file
/usr/share/zoneinfo timezone directory
/usr/share/zoneinfo/posixrules default DST rules (obsolete)
/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.
/usr/share/zoneinfo/GMT0 if present.
SEE ALSO
getenv(3), newstrftime(3), newtzset(3), time(2), tzfile(5)

View File

@ -64,7 +64,7 @@ strftime \- format date and time
The
.B strftime
function formats the information from
.I timeptr
.BI * timeptr
into the array pointed to by
.I buf
according to the string pointed to by
@ -85,47 +85,94 @@ bytes are placed into the array.
.PP
Each conversion specification is replaced by the characters as
follows which are then copied into the array.
The characters depend on the values of zero or more members of
.BI * timeptr
as specified by brackets in the description.
If a bracketed member name is followed by
.q + ,
.B strftime
can use the named member even though POSIX.1-2017 does not list it;
if the name is followed by
.q \*- ,
.B strftime
ignores the member even though POSIX.1-2017 lists it
which means portable code should set it.
For portability,
.BI * timeptr
should be initialized as if by a successful call to
.BR gmtime ,
.BR localtime ,
.BR mktime ,
.BR timegm ,
or similar functions.
.TP
%A
is replaced by the locale's full weekday name.
.RI [ tm_wday ]
.TP
%a
is replaced by the locale's abbreviated weekday name.
.RI [ tm_wday ]
.TP
%B
is replaced by the locale's full month name.
.RI [ tm_mon ]
.TP
%b or %h
is replaced by the locale's abbreviated month name.
.RI [ tm_mon ]
.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, with at least two digits by default.
.RI [ tm_year ]
.TP
%c
is replaced by the locale's appropriate date and time representation.
.RI [ tm_year ,
.IR tm_yday ,
.IR tm_mon ,
.IR tm_mday ,
.IR tm_wday ,
.IR tm_hour ,
.IR tm_min ,
.IR tm_sec ,
.IR tm_gmtoff +,
.IR tm_zone +,
.IR tm_isdst \*-].
.TP
%D
is equivalent to
.c %m/%d/%y .
.RI [ tm_year ,
.IR tm_mon ,
.IR tm_mday ]
.TP
%d
is replaced by the day of the month as a decimal number [01,31].
.RI [ tm_mday ]
.TP
%e
is replaced by the day of month as a decimal number [1,31];
single digits are preceded by a blank.
.RI [ tm_mday ]
.TP
%F
is equivalent to
.c %Y-%m-%d
(the ISO 8601 date format).
.RI [ tm_year ,
.IR tm_mon ,
.IR tm_mday ]
.TP
%G
is replaced by the ISO 8601 year with century as a decimal number.
See also the
.c %V
conversion specification.
.RI [ tm_year ,
.IR tm_yday ,
.IR tm_wday ]
.TP
%g
is replaced by the ISO 8601 year without century as a decimal number [00,99].
@ -134,29 +181,39 @@ This is the year that includes the greater part of the week.
See also the
.c %V
conversion specification.
.RI [ tm_year ,
.IR tm_yday ,
.IR tm_wday ]
.TP
%H
is replaced by the hour (24-hour clock) as a decimal number [00,23].
.RI [ tm_hour ]
.TP
%I
is replaced by the hour (12-hour clock) as a decimal number [01,12].
.RI [ tm_hour ]
.TP
%j
is replaced by the day of the year as a decimal number [001,366].
.RI [ tm_yday ]
.TP
%k
is replaced by the hour (24-hour clock) as a decimal number [0,23];
single digits are preceded by a blank.
.RI [ tm_hour ]
.TP
%l
is replaced by the hour (12-hour clock) as a decimal number [1,12];
single digits are preceded by a blank.
.RI [ tm_hour ]
.TP
%M
is replaced by the minute as a decimal number [00,59].
.RI [ tm_min ]
.TP
%m
is replaced by the month as a decimal number [01,12].
.RI [ tm_mon ]
.TP
%n
is replaced by a newline.
@ -166,28 +223,58 @@ is replaced by the locale's equivalent of either
.q AM
or
.q PM .
.RI [ tm_hour ]
.TP
%R
is replaced by the time in the format
.c %H:%M .
.RI [ tm_hour ,
.IR tm_min ]
.TP
%r
is replaced by the locale's representation of 12-hour clock time
using AM/PM notation.
.RI [ tm_hour ,
.IR tm_min ,
.IR tm_sec ]
.TP
%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.
.RI [ tm_sec ]
.TP
%s
is replaced by the number of seconds since the Epoch (see
.BR ctime (3)).
Although %s is reliable in this implementation,
it can have glitches on other platforms (notably platforms lacking
.IR tm_gmtoff ),
so portable code should format a
.B time_t
value directly via something like
.B sprintf
instead of via
.B localtime
followed by
.B strftime
with "%s".
.RI [ tm_year ,
.IR tm_mon ,
.IR tm_mday ,
.IR tm_hour ,
.IR tm_min ,
.IR tm_sec ,
.IR tm_gmtoff +,
.IR tm_isdst \*-].
.TP
%T
is replaced by the time in the format
.c %H:%M:%S .
.RI [ tm_hour ,
.IR tm_min ,
.IR tm_sec ]
.TP
%t
is replaced by a tab.
@ -195,10 +282,14 @@ is replaced by a tab.
%U
is replaced by the week number of the year (Sunday as the first day of
the week) as a decimal number [00,53].
.RI [ tm_wday ,
.IR tm_yday ,
.IR tm_year \*-]
.TP
%u
is replaced by the weekday (Monday as the first day of the week)
as a decimal number [1,7].
.RI [ tm_wday ]
.TP
%V
is replaced by the week number of the year (Monday as the first day of
@ -208,30 +299,64 @@ 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.
.RI [ tm_year ,
.IR tm_yday ,
.IR tm_wday ]
.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].
.RI [ tm_yday ,
.IR tm_wday ]
.TP
%w
is replaced by the weekday (Sunday as the first day of the week)
as a decimal number [0,6].
.RI [ tm_year ,
.IR tm_yday ,
.IR tm_wday ]
.TP
%X
is replaced by the locale's appropriate time representation.
.RI [ tm_year \*-,
.IR tm_yday \*-,
.IR tm_mon \*-,
.IR tm_mday \*-,
.IR tm_wday \*-,
.IR tm_hour ,
.IR tm_min ,
.IR tm_sec ,
.IR tm_gmtoff +,
.IR tm_zone +,
.IR tm_isdst \*-].
.TP
%x
is replaced by the locale's appropriate date representation.
.RI [ tm_year ,
.IR tm_yday ,
.IR tm_mon ,
.IR tm_mday ,
.IR tm_wday ,
.IR tm_hour \*-,
.IR tm_min \*-,
.IR tm_sec \*-,
.IR tm_gmtoff \*-,
.IR tm_zone \*-,
.IR tm_isdst \*-].
.TP
%Y
is replaced by the year with century as a decimal number.
.RI [ tm_year ]
.TP
%y
is replaced by the year without century as a decimal number [00,99].
.RI [ tm_year ]
.TP
%Z
is replaced by the time zone abbreviation,
or by the empty string if this is not determinable.
.RI [ tm_zone +,
.IR tm_isdst \*-]
.TP
%z
is replaced by the offset from the Prime Meridian
@ -244,6 +369,9 @@ 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 "\*-" .
.RI [ tm_gmtoff +,
.IR tm_zone +,
.IR tm_isdst \*-]
.TP
%%
is replaced by a single %.
@ -252,6 +380,26 @@ is replaced by a single %.
is replaced by the locale's date and time in
.BR date (1)
format.
.RI [ tm_year ,
.IR tm_yday ,
.IR tm_mon ,
.IR tm_mday ,
.IR tm_wday ,
.IR tm_hour ,
.IR tm_min ,
.IR tm_sec ,
.IR tm_gmtoff ,
.IR tm_zone ]
.PP
As a side effect,
.B strftime
also behaves as if
.B tzset
were called.
This is for compatibility with older platforms, as required by POSIX;
it is not needed for
.BR tzset 's
own use.
.SH "RETURN VALUE"
If the conversion is successful,
.B strftime

View File

@ -12,7 +12,7 @@ SYNOPSIS
cc ... -ltz
DESCRIPTION
The strftime function formats the information from timeptr into the
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
@ -23,141 +23,174 @@ DESCRIPTION
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.
which are then copied into the array. The characters depend on the
values of zero or more members of *timeptr as specified by brackets in
the description. If a bracketed member name is followed by "+",
strftime can use the named member even though POSIX.1-2017 does not
list it; if the name is followed by "-", strftime ignores the member
even though POSIX.1-2017 lists it which means portable code should set
it. For portability, *timeptr should be initialized as if by a
successful call to gmtime, localtime, mktime, timegm, or similar
functions.
%A is replaced by the locale's full weekday name.
%A is replaced by the locale's full weekday name. [tm_wday]
%a is replaced by the locale's abbreviated weekday name.
%a is replaced by the locale's abbreviated weekday name. [tm_wday]
%B is replaced by the locale's full month name.
%B is replaced by the locale's full month name. [tm_mon]
%b or %h
is replaced by the locale's abbreviated month name.
is replaced by the locale's abbreviated month name. [tm_mon]
%C is replaced by the century (a year divided by 100 and truncated
to an integer) as a decimal number [00,99].
%C is replaced by the century (a year divided by 100 and truncated
to an integer) as a decimal number, with at least two digits by
default. [tm_year]
%c is replaced by the locale's appropriate date and time
representation.
%c is replaced by the locale's appropriate date and time
representation. [tm_year, tm_yday, tm_mon, tm_mday, tm_wday,
tm_hour, tm_min, tm_sec, tm_gmtoff+, tm_zone+, tm_isdst-].
%D is equivalent to %m/%d/%y.
%D is equivalent to %m/%d/%y. [tm_year, tm_mon, tm_mday]
%d is replaced by the day of the month as a decimal number [01,31].
[tm_mday]
%e is replaced by the day of month as a decimal number [1,31];
single digits are preceded by a blank.
%e is replaced by the day of month as a decimal number [1,31];
single digits are preceded by a blank. [tm_mday]
%F is equivalent to %Y-%m-%d (the ISO 8601 date format).
%F is equivalent to %Y-%m-%d (the ISO 8601 date format). [tm_year,
tm_mon, tm_mday]
%G is replaced by the ISO 8601 year with century as a decimal
number. See also the %V conversion specification.
%G is replaced by the ISO 8601 year with century as a decimal
number. See also the %V conversion specification. [tm_year,
tm_yday, tm_wday]
%g is replaced by the ISO 8601 year without century as a decimal
%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.
%V conversion specification. [tm_year, tm_yday, tm_wday]
%H is replaced by the hour (24-hour clock) as a decimal number
[00,23].
%H is replaced by the hour (24-hour clock) as a decimal number
[00,23]. [tm_hour]
%I is replaced by the hour (12-hour clock) as a decimal number
[01,12].
%I is replaced by the hour (12-hour clock) as a decimal number
[01,12]. [tm_hour]
%j is replaced by the day of the year as a decimal number
[001,366].
%j is replaced by the day of the year as a decimal number
[001,366]. [tm_yday]
%k is replaced by the hour (24-hour clock) as a decimal number
[0,23]; 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. [tm_hour]
%l is replaced by the hour (12-hour clock) as a decimal number
[1,12]; single digits are preceded by a blank.
%l is replaced by the hour (12-hour clock) as a decimal number
[1,12]; single digits are preceded by a blank. [tm_hour]
%M is replaced by the minute as a decimal number [00,59].
%M is replaced by the minute as a decimal number [00,59]. [tm_min]
%m is replaced by the month as a decimal number [01,12].
%m is replaced by the month as a decimal number [01,12]. [tm_mon]
%n is replaced by a newline.
%p is replaced by the locale's equivalent of either "AM" or "PM".
%p is replaced by the locale's equivalent of either "AM" or "PM".
[tm_hour]
%R is replaced by the time in the format %H:%M.
%R is replaced by the time in the format %H:%M. [tm_hour, tm_min]
%r is replaced by the locale's representation of 12-hour clock time
using AM/PM notation.
using AM/PM notation. [tm_hour, tm_min, tm_sec]
%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.
%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. [tm_sec]
%s is replaced by the number of seconds since the Epoch (see
ctime(3)).
%s is replaced by the number of seconds since the Epoch (see
ctime(3)). Although %s is reliable in this implementation, it
can have glitches on other platforms (notably platforms lacking
tm_gmtoff), so portable code should format a time_t value
directly via something like sprintf instead of via localtime
followed by strftime with "%s". [tm_year, tm_mon, tm_mday,
tm_hour, tm_min, tm_sec, tm_gmtoff+, tm_isdst-].
%T is replaced by the time in the format %H:%M:%S.
%T is replaced by the time in the format %H:%M:%S. [tm_hour,
tm_min, tm_sec]
%t is replaced by a tab.
%U is replaced by the week number of the year (Sunday as the first
day of the week) as a decimal number [00,53].
%U is replaced by the week number of the year (Sunday as the first
day of the week) as a decimal number [00,53]. [tm_wday,
tm_yday, tm_year-]
%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]. [tm_wday]
%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
%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
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.
specification. [tm_year, tm_yday, tm_wday]
%W is replaced by the week number of the year (Monday as the first
day of the week) as a decimal number [00,53].
%W is replaced by the week number of the year (Monday as the first
day of the week) as a decimal number [00,53]. [tm_yday,
tm_wday]
%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]. [tm_year, tm_yday, tm_wday]
%X is replaced by the locale's appropriate time representation.
%X is replaced by the locale's appropriate time representation.
[tm_year-, tm_yday-, tm_mon-, tm_mday-, tm_wday-, tm_hour,
tm_min, tm_sec, tm_gmtoff+, tm_zone+, tm_isdst-].
%x is replaced by the locale's appropriate date representation.
%x is replaced by the locale's appropriate date representation.
[tm_year, tm_yday, tm_mon, tm_mday, tm_wday, tm_hour-, tm_min-,
tm_sec-, tm_gmtoff-, tm_zone-, tm_isdst-].
%Y is replaced by the year with century as a decimal number.
%Y is replaced by the year with century as a decimal number.
[tm_year]
%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]. [tm_year]
%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 abbreviation, or by the empty
string if this is not determinable. [tm_zone+, tm_isdst-]
%z is replaced by the offset from the Prime Meridian in the format
+HHMM or -HHMM (ISO 8601) as appropriate, with positive values
%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
-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 "-".
abbreviation begins with "-". [tm_gmtoff+, tm_zone+, tm_isdst-]
%% is replaced by a single %.
%+ is replaced by the locale's date and time in date(1) format.
%+ is replaced by the locale's date and time in date(1) format.
[tm_year, tm_yday, tm_mon, tm_mday, tm_wday, tm_hour, tm_min,
tm_sec, tm_gmtoff, tm_zone]
As a side effect, strftime also behaves as if tzset were called. This
is for compatibility with older platforms, as required by POSIX; it is
not needed for tzset's own use.
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
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
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
The format includes an %s conversion and the number of seconds
since the Epoch cannot be represented in a time_t.
SEE ALSO

View File

@ -9,9 +9,9 @@ tzset \- initialize time conversion information
.el .ds - \-
.B #include <time.h>
.PP
.B timezone_t tzalloc(char const *TZ);
.BI "timezone_t tzalloc(char const *" TZ );
.PP
.B void tzfree(timezone_t tz);
.BI "void tzfree(timezone_t " tz );
.PP
.B void tzset(void);
.PP
@ -31,62 +31,30 @@ The
.B tzalloc
function
allocates and returns a timezone object described by
.BR TZ .
If
.B TZ
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).
.IR TZ .
.PP
If
.B TZ
is null, the best available approximation to local (wall
.I TZ
is a null pointer,
.B tzalloc
uses 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.
in the system time conversion information directory.
.PP
If
.B TZ
.I TZ
is the empty string,
UT is used, with the abbreviation "UTC"
.B tzalloc
uses Universal Time (UT), 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
for more about UT, UTC, and leap seconds.
.PP
If
.I TZ
is nonnull and nonempty:
.IP
if the value begins with a colon, it is used as a pathname of a file
@ -98,24 +66,25 @@ and, if that file cannot be read, is used directly as a specification of
the time conversion information.
.PP
When
.B 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
.I TZ
contents are used as a pathname, a pathname beginning with
.q "/"
is used as-is; otherwise
the pathname is relative to a system time conversion information
directory.
The file must be in the format specified in
.BR tzfile (5).
.PP
When
.B TZ
.I TZ
is used directly as a specification of the time conversion information,
it must have the following syntax (spaces inserted for clarity):
it must have the following syntax:
.IP
\fIstd\|offset\fR[\fIdst\fR[\fIoffset\fR][\fB,\fIrule\fR]]
.PP
Where:
.RS
.TP 15
.TP
.IR std " and " dst
Three or more bytes that are the designation for the standard
.RI ( std )
@ -196,7 +165,7 @@ 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
As an extension to POSIX.1-2017, 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.
@ -205,7 +174,7 @@ The format of
.I date
is one of the following:
.RS
.TP 10
.TP
.BI J n
The Julian day
.I n
@ -238,16 +207,16 @@ first week in which the
.IR d' th
day occurs. Day zero is Sunday.
.RE
.IP "" 15
.IP
The
.I time
has the same format as
.I offset
except that POSIX does not allow a leading sign (\c
except that POSIX.1-2017 does not allow a leading sign (\c
.q "\*-"
or
.q "+" ).
As an extension to POSIX, the hours part of
As an extension to POSIX.1-2017, the hours part of
.I time
can range from \-167 through 167; this allows for unusual rules such
as
@ -259,9 +228,9 @@ is not given, is
.RE
.LP
Here are some examples of
.B TZ
.I TZ
values that directly specify the timezone; they use some of the
extensions to POSIX.
extensions to POSIX.1-2017.
.TP
.B EST5
stands for US Eastern Standard
@ -306,43 +275,114 @@ The abbreviations for standard and daylight saving time are
and
.q "\*-02".
.PP
If no
.I rule
is present in
.BR TZ ,
the rules specified
by the
If
.I TZ
specifies daylight saving time but does not specify a
.IR rule ,
and the optional
.BR tzfile (5)-format
file
.B 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
is present in the system time conversion information directory, the
rules in
.B posixrules
are used, with the
.B posixrules
standard and daylight saving time offsets from UT
replaced by those specified by the
.I offset
values in
.BR TZ .
.IR TZ .
However, the
.B posixrules
file is obsolete: if it is present it is only for backward compatibility,
and it does not work reliably.
Therefore, if a
.I TZ
string directly specifies a timezone with daylight saving time,
it should specify the daylight saving rules explicitly.
.PP
For compatibility with System V Release 3.1, a semicolon
.RB ( ; )
may be used to separate the
.I rule
from the rest of the specification.
from the rest of the specification;
this is an extension to POSIX.
.PP
The
.B tzfree
function
frees a timezone object
.IR tz ,
which should have been successfully allocated by
.BR tzalloc .
This invalidates any
.B tm_zone
pointers that
.I 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 getenv
fails,
.B tzset
acts like
.BR tzalloc(nullptr) ;
if the implied call to
.B tzalloc
fails,
.B tzset
falls back on UT.
.SH "RETURN VALUE"
If successful, the
.B tzalloc
function returns a nonnull pointer to the newly allocated object.
Otherwise, it returns a null pointer and sets
.IR errno .
.SH ERRORS
.TP
.B EOVERFLOW
.I TZ
directly specifies time conversion information,
and contains an integer out of machine range
or a time zone abbreviation that is too long for this platform.
.PP
The
.B tzalloc
function may also fail and set
.I errno
for any of the errors specified for the routines
.BR access (2),
.BR close (2),
.BR malloc (3),
.BR open (2),
and
.BR read (2).
.SH FILES
.ta \w'/usr/share/zoneinfo/posixrules\0\0'u
/usr/share/zoneinfo timezone information directory
/etc/localtime local timezone file
.br
/usr/share/zoneinfo/localtime local timezone file
/usr/share/zoneinfo timezone directory
.br
/usr/share/zoneinfo/posixrules default DST rules (obsolete,
and can cause bugs if present)
/usr/share/zoneinfo/posixrules default DST rules (obsolete)
.br
/usr/share/zoneinfo/GMT for UTC leap seconds
.sp
If
.B /usr/share/zoneinfo/GMT
is absent,
UTC leap seconds are loaded from
.BR /usr/share/zoneinfo/posixrules .
.PP
If /usr/share/zoneinfo/GMT is absent,
UTC leap seconds are loaded from /usr/share/zoneinfo/GMT0 if present.
.SH SEE ALSO
getenv(3),
newctime(3),

View File

@ -16,25 +16,17 @@ SYNOPSIS
DESCRIPTION
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.
by TZ.
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.
If TZ is a null pointer, tzalloc uses 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.
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 the empty string, tzalloc uses Universal Time (UT), with the
abbreviation "UTC" and without leap second correction; please see
newctime(3) for more about UT, UTC, and leap seconds.
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 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;
@ -44,155 +36,176 @@ DESCRIPTION
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 contents are used as a pathname, a pathname beginning with "/"
is used as-is; otherwise the pathname is 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):
information, it must have the following syntax:
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.
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:
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]]
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
"+".
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:
rule Indicates when to change to and back from daylight saving
time. The rule has the form:
date/time,date/time
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.
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.1-2017, 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:
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.
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.
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.
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.
The time has the same format as offset except that
POSIX.1-2017 does not allow a leading sign ("-" or "+").
As an extension to POSIX.1-2017, 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.
they use some of the extensions to POSIX.1-2017.
EST5 stands for US Eastern Standard Time (EST), 5 hours behind UT,
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
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
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
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"
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.
If TZ specifies daylight saving time but does not specify a rule, and
the optional tzfile(5)-format file posixrules is present in the system
time conversion information directory, the rules in posixrules are
used, with the posixrules standard and daylight saving time offsets
from UT replaced by those specified by the offset values in TZ.
However, the posixrules file is obsolete: if it is present it is only
for backward compatibility, and it does not work reliably. Therefore,
if a TZ string directly specifies a timezone with daylight saving time,
it should specify the daylight saving rules explicitly.
For compatibility with System V Release 3.1, a semicolon (;) may be
used to separate the rule from the rest of the specification.
For compatibility with System V Release 3.1, a semicolon (;) may be
used to separate the rule from the rest of the specification; this is
an extension to POSIX.
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
getenv fails, tzset acts like tzalloc(nullptr); if the implied call to
tzalloc fails, tzset falls back on UT.
RETURN VALUE
If successful, the tzalloc function returns a nonnull pointer to the
newly allocated object. Otherwise, it returns a null pointer and sets
errno.
ERRORS
EOVERFLOW
TZ directly specifies time conversion information, and contains
an integer out of machine range or a time zone abbreviation that
is too long for this platform.
The tzalloc function may also fail and set errno for any of the errors
specified for the routines access(2), close(2), malloc(3), open(2), and
read(2).
FILES
/usr/share/zoneinfo timezone information directory
/usr/share/zoneinfo/localtime local timezone file
/usr/share/zoneinfo/posixrules default DST rules (obsolete,
and can cause bugs if present)
/etc/localtime local timezone file
/usr/share/zoneinfo timezone directory
/usr/share/zoneinfo/posixrules default DST rules (obsolete)
/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/share/zoneinfo/GMT is absent, UTC leap seconds are loaded from
/usr/share/zoneinfo/GMT0 if present.
SEE ALSO
getenv(3), newctime(3), newstrftime(3), time(2), tzfile(5)

View File

@ -18,11 +18,15 @@
*/
/* PORT_TO_C89 means the code should work even if the underlying
compiler and library support only C89. SUPPORT_C89 means the
compiler and library support only C89 plus C99's 'long long'
and perhaps a few other extensions to C89. SUPPORT_C89 means the
tzcode library should support C89 callers in addition to the usual
support for C99-and-later callers. These macros are obsolescent,
support for C99-and-later callers; however, C89 support can trigger
latent bugs in C99-and-later callers. These macros are obsolescent,
and the plan is to remove them along with any code needed only when
they are nonzero. */
they are nonzero. A good time to do that might be in the year 2029
because RHEL 7 (whose GCC defaults to C89) extended life cycle
support (ELS) is scheduled to end on 2028-06-30. */
#ifndef PORT_TO_C89
# define PORT_TO_C89 0
#endif
@ -70,9 +74,7 @@
#endif
#if !defined HAVE__GENERIC && defined __has_extension
# if __has_extension(c_generic_selections)
# define HAVE__GENERIC 1
# else
# if !__has_extension(c_generic_selections)
# define HAVE__GENERIC 0
# endif
#endif
@ -754,7 +756,7 @@ struct tm *offtime(time_t const *, long);
time_t timelocal(struct tm *);
# endif
# if TZ_TIME_T || !defined timeoff
time_t timeoff(struct tm *, long);
# define EXTERN_TIMEOFF
# endif
# if TZ_TIME_T || !defined time2posix
time_t time2posix(time_t);
@ -766,7 +768,8 @@ time_t posix2time(time_t);
/* 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__ \
#if (200809 < _POSIX_VERSION \
|| defined __GLIBC__ \
|| defined __tm_zone /* musl */ \
|| defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ \
|| (defined __APPLE__ && defined __MACH__))
@ -896,6 +899,19 @@ static_assert(! TYPE_SIGNED(time_t) || ! SIGNED_PADDING_CHECK_NEEDED
# define UNINIT_TRAP 0
#endif
/* localtime.c sometimes needs access to timeoff if it is not already public.
tz_private_timeoff should be used only by localtime.c. */
#if (!defined EXTERN_TIMEOFF \
&& defined TM_GMTOFF && (200809 < _POSIX_VERSION || ! UNINIT_TRAP))
# ifndef timeoff
# define timeoff tz_private_timeoff
# endif
# define EXTERN_TIMEOFF
#endif
#ifdef EXTERN_TIMEOFF
time_t timeoff(struct tm *, long);
#endif
#ifdef DEBUG
# undef unreachable
# define unreachable() abort()
@ -955,6 +971,18 @@ enum {
#define SECSPERREPEAT ((int_fast64_t) DAYSPERREPEAT * SECSPERDAY)
#define AVGSECSPERYEAR (SECSPERREPEAT / YEARSPERREPEAT)
/* How many years to generate (in zic.c) or search through (in localtime.c).
This is two years larger than the obvious 400, to avoid edge cases.
E.g., suppose a non-POSIX.1-2017 rule applies from 2012 on with transitions
in March and September, plus one-off transitions in November 2013.
If zic looked only at the last 400 years, it would set max_year=2413,
with the intent that the 400 years 2014 through 2413 will be repeated.
The last transition listed in the tzfile would be in 2413-09,
less than 400 years after the last one-off transition in 2013-11.
Two years is not overkill for localtime.c, as a one-year bump
would mishandle 2023d's America/Ciudad_Juarez for November 2422. */
enum { years_of_observations = YEARSPERREPEAT + 2 };
enum {
TM_SUNDAY,
TM_MONDAY,

View File

@ -327,11 +327,12 @@ _fmt(const char *format, const struct tm *t, char *pt,
tm.tm_mday = t->tm_mday;
tm.tm_mon = t->tm_mon;
tm.tm_year = t->tm_year;
#ifdef TM_GMTOFF
mkt = timeoff(&tm, t->TM_GMTOFF);
#else
tm.tm_isdst = t->tm_isdst;
#if defined TM_GMTOFF && ! UNINIT_TRAP
tm.TM_GMTOFF = t->TM_GMTOFF;
#endif
mkt = mktime(&tm);
#endif
/* If mktime fails, %s expands to the
value of (time_t) -1 as a failure
marker; this is better in practice

View File

@ -95,7 +95,7 @@ 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.
standard and daylight saving times supported by POSIX.1-2017.
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
@ -187,7 +187,7 @@ in decreasing order of importance:
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
href="https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03">POSIX.1-2017
<code>TZ</code> strings</a>.
A file name component must not exceed 14 characters or start with
'<code>-</code>'.
@ -362,6 +362,11 @@ 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>.
Applications that process only timestamps from now on can instead use the file
<code>zonenow.tab</code>, which partitions the world more coarsely,
into regions where clocks agree now and in the predicted future;
this file is smaller and simpler than <code>zone1970.tab</code>
and <code>zone.tab</code>.
</p>
<p>
@ -373,7 +378,7 @@ 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;
on platforms that do not support POSIX.1-2017-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>,
@ -421,7 +426,7 @@ in decreasing order of importance:
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.
POSIX.1-2017 <code>TZ</code> string.
</p>
</li>
<li>
@ -765,12 +770,12 @@ href="https://www.dissentmagazine.org/blog/booked-a-global-history-of-time-vanes
calendar with 24-hour days. These divergences range from
relatively minor, such as Japanese bars giving times like "24:30" for the
wee hours of the morning, to more-significant differences such as <a
href="https://www.pri.org/stories/2015-01-30/if-you-have-meeting-ethiopia-you-better-double-check-time">the
href="https://theworld.org/stories/2015-01-30/if-you-have-meeting-ethiopia-you-better-double-check-time">the
east African practice of starting the day at dawn</a>, renumbering
the Western 06:00 to be 12:00. These practices are largely outside
the scope of the <code><abbr>tz</abbr></code> code and data, which
provide only limited support for date and time localization
such as that required by POSIX.
such as that required by POSIX.1-2017.
If <abbr>DST</abbr> is not used a different time zone
can often do the trick; for example, in Kenya a <code>TZ</code> setting
like <code>&lt;-03&gt;3</code> or <code>America/Cayenne</code> starts
@ -867,23 +872,23 @@ input is occasionally extended, and a platform may still be shipping
an older <code>zic</code>.
</p>
<h3 id="POSIX">POSIX properties and limitations</h3>
<h3 id="POSIX">POSIX.1-2017 properties and limitations</h3>
<ul>
<li>
<p>
In POSIX, time display in a process is controlled by the
In POSIX.1-2017, time display in a process is controlled by the
environment variable <code>TZ</code>.
Unfortunately, the POSIX
Unfortunately, the POSIX.1-2017
<code>TZ</code> string takes a form that is hard to describe and
is error-prone in practice.
Also, POSIX <code>TZ</code> strings cannot deal with daylight
Also, POSIX.1-2017 <code>TZ</code> strings cannot deal with daylight
saving time rules not based on the Gregorian calendar (as in
Morocco), or with situations where more than two time zone
abbreviations or <abbr>UT</abbr> offsets are used in an area.
</p>
<p>
The POSIX <code>TZ</code> string takes the following form:
The POSIX.1-2017 <code>TZ</code> string takes the following form:
</p>
<p>
@ -950,7 +955,7 @@ an older <code>zic</code>.
</dl>
<p>
Here is an example POSIX <code>TZ</code> string for New
Here is an example POSIX.1-2017 <code>TZ</code> string for New
Zealand after 2007.
It says that standard time (<abbr>NZST</abbr>) is 12 hours ahead
of <abbr>UT</abbr>, and that daylight saving time
@ -961,7 +966,7 @@ an older <code>zic</code>.
<pre><code>TZ='NZST-12NZDT,M9.5.0,M4.1.0/3'</code></pre>
<p>
This POSIX <code>TZ</code> string is hard to remember, and
This POSIX.1-2017 <code>TZ</code> string is hard to remember, and
mishandles some timestamps before 2008.
With this package you can use this instead:
</p>
@ -999,7 +1004,7 @@ an older <code>zic</code>.
limit phone calls to off-peak hours.
</li>
<li>
POSIX provides no convenient and efficient way to determine
POSIX.1-2017 provides no convenient and efficient way to determine
the <abbr>UT</abbr> offset and time zone abbreviation of arbitrary
timestamps, particularly for timezones
that do not fit into the POSIX model.
@ -1026,14 +1031,14 @@ an older <code>zic</code>.
</li>
</ul>
<h3 id="POSIX-extensions">Extensions to POSIX in the
<h3 id="POSIX-extensions">Extensions to POSIX.1-2017 in the
<code><abbr>tz</abbr></code> code</h3>
<ul>
<li>
<p>
The <code>TZ</code> environment variable is used in generating
the name of a file from which time-related information is read
(or is interpreted à la POSIX); <code>TZ</code> is no longer
(or is interpreted à la POSIX.1-2017); <code>TZ</code> is no longer
constrained to be a string containing abbreviations
and numeric data as described <a href="#POSIX">above</a>.
The file's format is <dfn><abbr>TZif</abbr></dfn>,

View File

@ -100,7 +100,7 @@ and back from,
the POSIX representation over the leap second inserted at the end of June,
1993.
.nf
.ta \w'93/06/30 'u +\w'23:59:59 'u +\w'A+0 'u +\w'X=time2posix(T) 'u
.ta \w'93/06/30\0'u +\w'23:59:59\0'u +\w'A+0\0'u +\w'X=time2posix(T)\0'u
DATE TIME T X=time2posix(T) posix2time(X)
93/06/30 23:59:59 A+0 B+0 A+0
93/06/30 23:59:60 A+1 B+1 A+1 or A+2

View File

@ -22,9 +22,10 @@ into problems that programmers have with timekeeping.</li>
Explaining The Mysteries Of Time Zones</a>" (2017; 2:15)
briefly says why France has more time zones than Russia.
<li>
"<a href="https://www.youtube.com/watch?v=yRz-Dl60Lfc">Why Denmark is
.17 Seconds Behind The World</a>" (2019; 6:29) explains why Denmark and
the United Kingdom don't exactly follow their own law about civil time.
"<a href="https://www.youtube.com/watch?v=yRz-Dl60Lfc">Why Denmark used to be
.04 seconds behind the world</a>" (2019; 6:29) explains why the United Kingdom
&mdash; and, once, Denmark &mdash; haven't always exactly followed their own
laws about civil time.
<li>
"About Time" (1962; 59 minutes) is part of the
Bell Science extravaganza, with Frank Baxter, Richard Deacon, and Les Tremayne.
@ -209,7 +210,7 @@ Umberto Eco,
Island of the Day Before</em></a>
(<em>L'isola del giorno prima</em>), 1994.
"...the story of a 17th century Italian nobleman trapped near an island
on the International Date Line. Time and time zones play an integral
on the International Date Line. Time and time zones play an integral
part in the novel." (Paul Eggert, 2006-04-22)
</li>
<li>
@ -229,94 +230,73 @@ year-round <abbr>DST</abbr> as a way of lessening wintertime despair.
</li>
</ul>
<h2>Music</h2>
<p>
Data on recordings of "Save That Time," Russ Long, Serrob Publishing, BMI:</p>
<table>
<tr><td>Artist</td><td>Karrin Allyson</td></tr>
<tr><td>CD</td><td>I Didn't Know About You</td></tr>
<tr><td>Copyright Date</td><td>1993</td></tr>
<tr><td>Label</td><td>Concord Jazz, Inc.</td></tr>
<tr><td>ID</td><td>CCD-4543</td></tr>
<tr><td>Track Time</td><td>3:44</td></tr>
<tr><td>Personnel</td><td>Karrin Allyson, vocal;
<ul>
<li>
Recordings of "Save That Time," Russ Long, Serrob Publishing, BMI:
<ul>
<li>
Karrin Allyson, <em>I Didn't Know About You</em> (1993), track 11, 3:44.
Concord Jazz CCD-4543.
Karrin Allyson, vocal;
Russ Long, piano;
Gerald Spaits, bass;
Todd Strait, drums</td></tr>
<tr><td>Notes</td><td>CD notes "additional lyric by Karrin Allyson;
arranged by Russ Long and Karrin Allyson"</td></tr>
<tr><td>ADO Rating</td><td>1 star</td></tr>
<tr><td><a href="https://www.allmusic.com/album/i-didnt-know-about-you-mw0000618657">AMG Rating</a></td><td>4 stars</td></tr>
<tr><td>Penguin Rating</td><td>3.5 stars</td></tr>
<tr><td>&nbsp;</td><td></td></tr>
<tr><td>Artist</td><td>Kevin Mahogany</td></tr>
<tr><td>CD</td><td>Double Rainbow</td></tr>
<tr><td>Copyright Date</td><td>1993</td></tr>
<tr><td>Label</td><td>Enja Records</td></tr>
<tr><td>ID</td><td>ENJ-7097 2</td></tr>
<tr><td>Track Time</td><td>6:27</td></tr>
<tr><td>Personnel</td><td>Kevin Mahogany, vocal;
Todd Strait, drums.
CD notes "additional lyric by Karrin Allyson;
arranged by Russ Long and Karrin Allyson".
ADO &#x2605;,
<a href="https://www.allmusic.com/album/i-didnt-know-about-you-mw0000618657">AMG</a>
&#x2605;&#x2605;&#x2605;&#x2605;, Penguin &#x2605;&#x2605;&#x2605;&#x2BEA;.
</li>
<li>
Kevin Mahogany, <em>Double Rainbow</em> (1993), track 3, 6:27. Enja ENJ-7097 2.
Kevin Mahogany, vocal;
Kenny Barron, piano;
Ray Drummond, bass;
Ralph Moore, tenor saxophone;
Lewis Nash, drums</td></tr>
<tr><td>ADO Rating</td><td>1.5 stars</td></tr>
<tr><td><a href="https://www.allmusic.com/album/double-rainbow-mw0000620371">AMG Rating</a></td><td>3 stars</td></tr>
<tr><td>Penguin Rating</td><td>3 stars</td></tr>
<tr><td>&nbsp;</td><td></td></tr>
<tr><td>Artist</td><td>Joe Williams</td></tr>
<tr><td>CD</td><td>Here's to Life</td></tr>
<tr><td>Copyright Date</td><td>1994</td></tr>
<tr><td>Label</td><td>Telarc International Corporation</td></tr>
<tr><td>ID</td><td>CD-83357</td></tr>
<tr><td>Track Time</td><td>3:58</td></tr>
<tr><td>Personnel</td><td>Joe Williams, vocal
The Robert Farnon [39 piece] Orchestra</td></tr>
<tr><td>Notes</td><td>This CD is also available as part of a 3-CD package from
Telarc, "Triple Play" (CD-83461)</td></tr>
<tr><td>ADO Rating</td><td>black dot</td></tr>
<tr><td><a href="https://www.allmusic.com/album/heres-to-life-mw0000623648">AMG Rating</a></td><td>2 stars</td></tr>
<tr><td>Penguin Rating</td><td>3 stars</td></tr>
<tr><td>&nbsp;</td><td></td></tr>
<tr><td>Artist</td><td>Charles Fambrough</td></tr>
<tr><td>CD</td><td>Keeper of the Spirit</td></tr>
<tr><td>Copyright Date</td><td>1995</td></tr>
<tr><td>Label</td><td>AudioQuest Music</td></tr>
<tr><td>ID</td><td>AQ-CD1033</td></tr>
<tr><td>Track Time</td><td>7:07</td></tr>
<tr><td>Personnel</td><td>Charles Fambrough, bass;
Lewis Nash, drums.
ADO &#x2605;&#x2BEA;,
<a href="https://www.allmusic.com/album/double-rainbow-mw0000620371">AMG</a>
&#x2605;&#x2605;&#x2605;, Penguin &#x2605;&#x2605;&#x2605;.
</li>
<li>
Joe Williams, <em>Here's to Life</em> (1994), track 7, 3:58.
Telarc Jazz CD-83357.
Joe Williams, vocal; The Robert Farnon [39 piece] Orchestra.
Also in a 3-CD package "Triple Play", Telarc CD-83461.
ADO &#x2022;,
<a href="https://www.allmusic.com/album/heres-to-life-mw0000623648">AMG</a>
&#x2605;&#x2605;, Penguin &#x2605;&#x2605;&#x2605;.
</li>
<li>
Charles Fambrough, <em>Keeper of the Spirit</em> (1995), track 7, 7:07.
AudioQuest AQ-CD1033.
Charles Fambrough, bass;
Joel Levine, tenor recorder;
Edward Simon, piano;
Lenny White, drums;
Marion Simon, percussion</td></tr>
<tr><td>ADO Rating</td><td>2 stars</td></tr>
<tr><td><a href="https://www.allmusic.com/album/keeper-of-the-spirit-mw0000176559">AMG Rating</a></td><td>unrated</td></tr>
<tr><td>Penguin Rating</td><td>3 stars</td></tr>
</table>
<hr>
<p>Also of note:</p>
<table>
<tr><td>Artist</td><td>Holly Cole Trio</td></tr>
<tr><td>CD</td><td>Blame It On My Youth</td></tr>
<tr><td>Copyright Date</td><td>1992</td></tr>
<tr><td>Label</td><td>Manhattan</td></tr>
<tr><td>ID</td><td>CDP 7 97349 2</td></tr>
<tr><td>Total Time</td><td>37:45</td></tr>
<tr><td>Personnel</td><td>Holly Cole, voice;
Marion Simon, percussion.
ADO &#x2605;,
<a href="https://www.allmusic.com/album/keeper-of-the-spirit-mw0000176559">AMG</a>
unrated, Penguin &#x2605;&#x2605;&#x2605;.
</ul>
</li>
<li>
Holly Cole Trio, Blame It On My Youth (1992). Manhattan CDP 7 97349 2, 37:45.
Holly Cole, voice;
Aaron Davis, piano;
David Piltch, string bass</td></tr>
<tr><td>Notes</td><td>Lyrical reference to "Eastern Standard Time" in
Tom Waits' "Purple Avenue"</td></tr>
<tr><td>ADO Rating</td><td>2.5 stars</td></tr>
<tr><td><a href="https://www.allmusic.com/album/blame-it-on-my-youth-mw0000274303">AMG Rating</a></td><td>3 stars</td></tr>
<tr><td>Penguin Rating</td><td>unrated</td></tr>
<tr><td>&nbsp;</td><td></td></tr>
<tr><td>Artist</td><td>Milt Hinton</td></tr>
<tr><td>CD</td><td>Old Man Time</td></tr>
<tr><td>Copyright Date</td><td>1990</td></tr>
<tr><td>Label</td><td>Chiaroscuro</td></tr>
<tr><td>ID</td><td>CR(D) 310</td></tr>
<tr><td>Total Time</td><td>149:38 (two CDs)</td></tr>
<tr><td>Personnel</td><td>Milt Hinton, bass;
David Piltch, string bass.
Lyrical reference to "Eastern Standard Time" in
Tom Waits's "Purple Avenue".
ADO &#x2605;&#x2605;&#x2BEA;,
<a href="https://www.allmusic.com/album/blame-it-on-my-youth-mw0000274303">AMG</a>
&#x2605;&#x2605;&#x2605;, Penguin unrated.
</li>
<li>
Milt Hinton,
<a href="https://chiaroscurojazz.org/catalog/old-man-time-2-cd-set/"><em>Old
Man Time</em></a> (1990).
Chiaroscuro CR(D) 310, 149:38 (two CDs).
Milt Hinton, bass;
Doc Cheatham, Dizzy Gillespie, Clark Terry, trumpet;
Al Grey, trombone;
Eddie Barefield, Joe Camel (Flip Phillips), Buddy Tate,
@ -328,165 +308,129 @@ Gus Johnson, Gerryck King, Bob Rosengarden, Jackie Williams,
drums;
Lionel Hampton, vibraphone;
Cab Calloway, Joe Williams, vocal;
Buck Clayton, arrangements</td></tr>
<tr><td>Notes</td><td>tunes include Old Man Time, Time After Time,
Sometimes I'm Happy,
A Hot Time in the Old Town Tonight,
Four or Five Times, Now's the Time,
Time on My Hands, This Time It's Us,
and Good Time Charlie.
<a href="http://www.chiaroscurojazz.com/album.php?C=310">Album info</a>
is available.</td></tr>
<tr><td>ADO Rating</td><td>3 stars</td></tr>
<tr><td><a href="https://www.allmusic.com/album/old-man-time-mw0000269353">AMG Rating</a></td><td>4.5 stars</td></tr>
<tr><td>Penguin Rating</td><td>3 stars</td></tr>
<tr><td>&nbsp;</td><td></td></tr>
<tr><td>Artist</td><td>Alan Broadbent</td></tr>
<tr><td>CD</td><td>Pacific Standard Time</td></tr>
<tr><td>Copyright Date</td><td>1995</td></tr>
<tr><td>Label</td><td>Concord Jazz, Inc.</td></tr>
<tr><td>ID</td><td>CCD-4664</td></tr>
<tr><td>Total Time</td><td>62:42</td></tr>
<tr><td>Personnel</td><td>Alan Broadbent, piano;
Buck Clayton, arrangements.
Tunes include "Old Man Time", "Time After Time",
"Sometimes I'm Happy",
"A Hot Time in the Old Town Tonight",
"Four or Five Times", "Now's the Time",
"Time on My Hands", "This Time It's Us",
and "Good Time Charlie".
ADO &#x2605;&#x2605;&#x2605;,
<a href="https://www.allmusic.com/album/old-man-time-mw0000269353">AMG</a>
&#x2605;&#x2605;&#x2605;&#x2605;&#x2BEA;, Penguin &#x2605;&#x2605;&#x2605;.
</li>
<li>
Alan Broadbent, <em>Pacific Standard Time</em> (1995).
Concord Jazz CCD-4664, 62:42.
Alan Broadbent, piano;
Putter Smith, Bass;
Frank Gibson, Jr., drums</td></tr>
<tr><td>Notes</td><td>The CD cover features an analemma for equation-of-time fans</td></tr>
<tr><td>ADO Rating</td><td>1 star</td></tr>
<tr><td><a href="https://www.allmusic.com/album/pacific-standard-time-mw0000645433">AMG Rating</a></td><td>4 stars</td></tr>
<tr><td>Penguin Rating</td><td>3.5 stars</td></tr>
<tr><td>&nbsp;</td><td></td></tr>
<tr><td>Artist</td><td>Anthony Braxton/Richard Teitelbaum</td></tr>
<tr><td>CD</td><td>Silence/Time Zones</td></tr>
<tr><td>Copyright Date</td><td>1996</td></tr>
<tr><td>Label</td><td>Black Lion</td></tr>
<tr><td>ID</td><td>BLCD 760221</td></tr>
<tr><td>Total Time</td><td>72:58</td></tr>
<tr><td>Personnel</td><td>Anthony Braxton, sopranino and alto saxophones,
Frank Gibson, Jr., drums.
The CD cover features an analemma for equation-of-time fans.
ADO &#x2605;,
<a href="https://www.allmusic.com/album/pacific-standard-time-mw0000645433">AMG</a>
&#x2605;&#x2605;&#x2605;&#x2605;, Penguin &#x2605;&#x2605;&#x2605;&#x2BEA;.
</li>
<li>
Anthony Braxton/Richard Teitelbaum, <em>Silence/Time Zones</em> (1996).
Black Lion BLCD 760221, 72:58.
Anthony Braxton, sopranino and alto saxophones,
contrebasse clarinet, miscellaneous instruments;
Leo Smith, trumpet and miscellaneous instruments;
Leroy Jenkins, violin and miscellaneous instruments;
Richard Teitelbaum, modular moog and micromoog synthesizer</td></tr>
<tr><td>ADO Rating</td><td>black dot</td></tr>
<tr><td><a href="https://www.allmusic.com/album/silence-time-zones-mw0000595735">AMG Rating</a></td><td>4 stars</td></tr>
<tr><td>&nbsp;</td><td></td></tr>
<tr><td>Artist</td><td>Charles Gayle</td></tr>
<tr><td>CD</td><td>Time Zones</td></tr>
<tr><td>Copyright Date</td><td>2006</td></tr>
<tr><td>Label</td><td>Tompkins Square</td></tr>
<tr><td>ID</td><td>TSQ2839</td></tr>
<tr><td>Total Time</td><td>49:06</td></tr>
<tr><td>Personnel</td><td>Charles Gayle, piano</td></tr>
<tr><td>ADO Rating</td><td>1 star</td></tr>
<tr><td><a href="https://www.allmusic.com/album/time-zones-mw0000349642">AMG Rating</a></td><td>4.5 stars</td></tr>
<tr><td>&nbsp;</td><td></td></tr>
<tr><td>Artist</td><td>The Get Up Kids</td></tr>
<tr><td>CD</td><td>Eudora</td></tr>
<tr><td>Copyright Date</td><td>2001</td></tr>
<tr><td>Label</td><td>Vagrant</td></tr>
<tr><td>ID</td><td>357</td></tr>
<tr><td>Total Time</td><td>65:12</td></tr>
<tr><td>Notes</td><td>Includes the song "Central Standard Time." Thanks to Colin Bowern for this information.</td></tr>
<tr><td><a href="https://www.allmusic.com/album/eudora-mw0000592063">AMG Rating</a></td><td>2.5 stars</td></tr>
<tr><td>&nbsp;</td><td></td></tr>
<tr><td>Artist</td><td>Coldplay</td></tr>
<tr><td>Song</td><td>Clocks</td></tr>
<tr><td>Copyright Date</td><td>2003</td></tr>
<tr><td>Label</td><td>Capitol Records</td></tr>
<tr><td>ID</td><td>52608</td></tr>
<tr><td>Total Time</td><td>4:13</td></tr>
<tr><td>Notes</td><td>Won the 2004 Record of the Year honor at the
Richard Teitelbaum, modular moog and micromoog synthesizer.
ADO &#x2022;,
<a href="https://www.allmusic.com/album/silence-time-zones-mw0000595735">AMG</a>
&#x2605;&#x2605;&#x2605;&#x2605;.
</li>
<li>
Charles Gayle, <em>Time Zones</em> (2006). Tompkins Square TSQ2839, 49:06.
Charles Gayle, piano.
ADO &#x2605;,
<a href="https://www.allmusic.com/album/time-zones-mw0000349642">AMG</a>
&#x2605;&#x2605;&#x2605;&#x2605;&#x2BEA;.
</li>
<li>
The Get Up Kids, <em>Eudora</em> (2001). Vagrant 357, 65:12.
Includes the song "Central Standard Time."
Thanks to Colin Bowern for this information.
<a href="https://www.allmusic.com/album/eudora-mw0000592063">AMG</a>
&#x2605;&#x2605;&#x2BEA;.
</li>
<li>
Coldplay, "Clocks" (2003).
Capitol 52608, 4:13.
Won the 2004 Record of the Year honor at the
Grammy Awards. Co-written and performed by Chris Martin,
great-great-grandson of <abbr>DST</abbr> inventor William Willett.
The song's first line is "Lights go out and I can't be saved".</td></tr>
<tr><td>&nbsp;</td><td></td></tr>
<tr><td>Artist</td><td>Jaime Guevara</td></tr>
<tr><td>Song</td><td><a
The song's first line is "Lights go out and I can't be saved".
</li>
<li>
Jaime Guevara, "<a
href="https://www.youtube.com/watch?v=ZfN4Fe_A50U">Qu&eacute;
hora es</a></td></tr>
<tr><td>Date</td><td>1993</td></tr>
<tr><td>Total Time</td><td>3:04</td></tr>
<tr><td>Notes</td><td>The song protested "Sixto Hour" in Ecuador
hora es</a>" (1993), 3:04.
The song protested "Sixto Hour" in Ecuador
(1992&ndash;3). Its lyrics include "Amanec&iacute;a en mitad de la noche, los
guaguas iban a clase sin sol" ("It was dawning in the middle of the
night, the buses went to class without sun").
<tr><td>&nbsp;</td><td></td></tr>
<tr><td>Artist</td><td>Irving Kahal and Harry Richman</td></tr>
<tr><td>Song</td><td>There Ought to be a Moonlight Saving Time</td></tr>
<tr><td>Copyright Date</td><td>1931</td>
<tr><td>Notes</td><td>This musical standard was a No. 1 hit for Guy Lombardo
</li>
<li>
Irving Kahal and Harry Richman,
"There Ought to be a Moonlight Saving Time" (1931).
This musical standard was a No. 1 hit for Guy Lombardo
in 1931, and was also performed by Maurice Chevalier, Blossom Dearie
and many others. The phrase "Moonlight saving time" also appears in
the 1995 country song "Not Enough Hours in the Night" written by Aaron
Barker, Kim Williams and Rob Harbin and performed by Doug
Supernaw.</td></tr>
<tr><td>&nbsp;</td><td></td></tr>
<tr><td>Artist</td><td>The Microscopic Septet</td></tr>
<tr><td>CD</td><td>Lobster Leaps In</td></tr>
<tr><td>Copyright Date</td><td>2008</td></tr>
<tr><td>Label</td><td>Cuneiform</td></tr>
<tr><td>ID</td><td>272</td></tr>
<tr><td>Total Time</td><td>73:05</td></tr>
<tr><td>Notes</td><td>Includes the song "Twilight Time Zone."</td></tr>
<tr><td><a href="https://www.allmusic.com/album/lobster-leaps-in-mw0000794929">AMG Rating</a></td><td>3.5 stars</td></tr>
<tr><td>ADO Rating</td><td>2 stars</td></tr>
<tr><td>&nbsp;</td><td></td></tr>
<tr><td>Artist</td><td>Bob Dylan</td></tr>
<tr><td>CD</td><td>The Times They Are a-Changin'</td></tr>
<tr><td>Copyright Date</td><td>1964</td></tr>
<tr><td>Label</td><td>Columbia</td></tr>
<tr><td>ID</td><td>CK-8905</td></tr>
<tr><td>Total Time</td><td>45:36</td></tr>
<tr><td><a href="https://www.allmusic.com/album/the-times-they-a-changin-mw0000202344">AMG Rating</a></td><td>4.5 stars</td></tr>
<tr><td>ADO Rating</td><td>1.5 stars</td></tr>
<tr><td>Notes<td>The title song is also available on "Bob Dylan's Greatest Hits" and "The Essential Bob Dylan."</td></tr>
<tr><td>&nbsp;</td><td></td></tr>
<tr><td>Artist</td><td>Luciana Souza</td></tr>
<tr><td>CD</td><td>Tide</td></tr>
<tr><td>Copyright Date</td><td>2009</td></tr>
<tr><td>Label</td><td>Universal Jazz France</td></tr>
<tr><td>ID</td><td>B0012688-02</td></tr>
<tr><td>Total Time</td><td>42:31</td></tr>
<tr><td><a href="https://www.allmusic.com/album/tide-mw0000815692">AMG Rating</a></td><td>3.5 stars</td></tr>
<tr><td>ADO Rating</td><td>2.5 stars</td></tr>
<tr><td>Notes<td>Includes the song "Fire and Wood" with the lyric
Supernaw.
</li>
<li>
The Microscopic Septet, <em>Lobster Leaps In</em> (2008).
Cuneiform 272, 73:05.
Includes the song "Twilight Time Zone."
ADO &#x2605;&#x2605;,
<a href="https://www.allmusic.com/album/lobster-leaps-in-mw0000794929">AMG</a>
&#x2605;&#x2605;&#x2605;&#x2BEA;.
</li>
<li>
Bob Dylan, <em>The Times They Are a-Changin'</em> (1964).
Columbia CK-8905, 45:36.
ADO &#x2605;&#x2BEA;,
<a href="https://www.allmusic.com/album/the-times-they-a-changin-mw0000202344">AMG</a>
&#x2605;&#x2605;&#x2605;&#x2605;&#x2BEA;.
The title song is also available on "Bob Dylan's Greatest Hits" and "The Essential Bob Dylan."
</li>
<li>
Luciana Souza, <em>Tide</em> (2009). Universal Jazz France B0012688-02, 42:31.
ADO &#x2605;&#x2605;&#x2BEA;,
<a href="https://www.allmusic.com/album/tide-mw0000815692">AMG</a>
&#x2605;&#x2605;&#x2605;&#x2BEA;.
Includes the song "Fire and Wood" with the lyric
"The clocks were turned back you remember/Think it's still November."
</td></tr>
<tr><td>&nbsp;</td><td></td></tr>
<tr><td>Artist</td><td>Ken Nordine</td></tr>
<tr><td>CD</td><td>You're Getting Better: The Word Jazz Dot Masters</td></tr>
<tr><td>Copyright Date</td><td>2005</td></tr>
<tr><td>Label</td><td>Geffen</td></tr>
<tr><td>ID</td><td>B0005171-02</td></tr>
<tr><td>Total Time</td><td>156:22</td></tr>
<tr><td>ADO Rating</td><td>1 star</td></tr>
<tr><td><a href="https://www.allmusic.com/album/youre-getting-better-the-word-jazz-dot-masters-mw0000736197">AMG Rating</a></td><td>4.5 stars</td></tr>
<tr><td>Notes</td><td>Includes the piece "What Time Is It"
("He knew what time it was everywhere...that counted").</td></tr>
<tr><td>&nbsp;</td><td></td></tr>
<tr><td>Artist</td><td>Chicago</td></tr>
<tr><td>CD</td><td>Chicago Transit Authority</td></tr>
<tr><td>Copyright Date</td><td>1969</td></tr>
<tr><td>Label</td><td>Columbia</td></tr>
<tr><td>ID</td><td>64409</td></tr>
<tr><td>Total Time</td><td>1:16:20</td></tr>
<tr><td><a href="https://www.allmusic.com/album/chicago-transit-authority-mw0000189364">AMG Rating</a></td><td>4 stars</td></tr>
<tr><td>Notes</td><td>Includes the song "Does Anybody Really Know What Time It Is?"</td></tr>
<tr><td>&nbsp;</td><td></td></tr>
<tr><td>Artist</td><td>Emanuele Arciuli</td></tr>
<tr><td>Composer</td><td>William Duckworth</td></tr>
<tr><td>CD</td><td><a href="https://neumarecords.org/ols/products/william-duckworth-the-time-curve-preludes">The Time Curve Preludes</a></td></tr>
<tr><td>Copyright Date</td><td>2023</td></tr>
<tr><td>Label</td><td>Neuma</td></tr>
<tr><td>Total Time</td><td>44:46</td></tr>
<tr><td>Notes</td><td>The first work of postminimal music. Unlike minimalism, it does not assume that the listener has plenty of time.</td></tr>
</table>
</li>
<li>
Ken Nordine, <em>You're Getting Better: The Word Jazz Dot Masters</em> (2005).
Geffen B0005171-02, 156:22.
ADO &#x2605;,
<a href="https://www.allmusic.com/album/youre-getting-better-the-word-jazz-dot-masters-mw0000736197">AMG</a>
&#x2605;&#x2605;&#x2605;&#x2605;&#x2BEA;.
Includes the piece "What Time Is It"
("He knew what time it was everywhere...that counted").
</li>
<li>
Chicago, <em>Chicago Transit Authority</em> (1969). Columbia 64409, 1:16:20.
<a href="https://www.allmusic.com/album/chicago-transit-authority-mw0000189364">AMG</a> &#x2605;&#x2605;&#x2605;&#x2605;.
Includes the song "Does Anybody Really Know What Time It Is?".
</li>
<li>
Emanuele Arciuli,
<a href="https://neumarecords.org/ols/products/william-duckworth-the-time-curve-preludes"><em>The Time Curve Preludes</em></a> (2023).
Neuma 174, 44:46.
The title piece, composed by
<a href="https://en.wikipedia.org/wiki/William_Duckworth_(composer)">William
Duckworth</a>, is the first work of postminimal music.
Unlike minimalism, it does not assume that the listener has plenty of time.
</li>
</ul>
<h2>Comics</h2>
<ul>
<li>
@ -506,7 +450,10 @@ along with the panels
"<a href="https://xkcd.com/2050/">6/6 Time</a>" (2018-09-24),
"<a href="https://xkcd.com/2092/">Consensus New Year</a>" (2018-12-31),
"<a href="https://xkcd.com/2266/">Leap Smearing</a>" (2020-02-10),
and "<a href="https://xkcd.com/2594/">Consensus Time</a>" (2022-03-16).
"<a href="https://xkcd.com/2594/">Consensus Time</a>" (2022-03-16),
"<a href="https://xkcd.com/2846/">Daylight Saving Choice</a>" (2023-10-25),
"<a href="https://xkcd.com/2854/">Date Line</a>" (2023-11-13),
and "<a href="https://xkcd.com/2867/">DateTime</a>" (2023-12-13).
The related book <em>What If?</em> has an entry
"<a href="https://what-if.xkcd.com/26/">Leap Seconds</a>" (2012-12-31).
</li>
@ -519,9 +466,13 @@ Before Swine</em> (2016-11-06)</a>.
Stonehenge is abandoned in <a
href="https://www.gocomics.com/nonsequitur/2017/03/12"><em>Non Sequitur</em>
(2017-03-12)</a>.
</li>
<li>
The boss freaks out in <a
href="https://dilbert.com/strip/1998-03-14"><em>Dilbert</em> (1998-03-14)</a>.
Caulfield proposes changing clocks just once a year in
<a href="https://www.gocomics.com/frazz/2023/12/31"><em>Frazz</em>
(2023-12-31)</a>, while Peter and Jason go multi-lingual and -zonal in
<a href="https://www.gocomics.com/foxtrot/2023/12/31"><em>FoxTrot</em>
(the same day)</a>.
</li>
<li>
Peppermint Patty: "What if the world comes to an end tonight, Marcie?"
@ -605,10 +556,10 @@ entitled "The Kid," originally aired 1997-11-04)
</li>
<li>
"I put myself and my staff through this crazy, huge ordeal, all because
I refused to go on at midnight, okay? And so I work, you know, and
then I get this job at eleven, supposed to be a big deal. Then
I refused to go on at midnight, okay? And so I work, you know, and
then I get this job at eleven, supposed to be a big deal. Then
yesterday daylight [saving] time ended. Right now it's basically
midnight." (Conan O'Brien on the 2010-11-08 premiere of <em>Conan</em>.)
midnight." (Conan O'Brien on the 2010-11-08 premiere of <em>Conan</em>)
</li>
<li>
"The best method, I told folks, was to hang a large clock high on a
@ -616,7 +567,7 @@ barn wall where all the cows could see it. If you have Holsteins, you
will need to use an analog clock." (Jerry Nelson, <a
href="http://www.agriculture.com/family/farm-humor/how-to-adjust-dairy-cows-to-daylight-savings-time">How
to adjust dairy cows to daylight saving time</a>", <em>Successful Farming</em>,
2017-10-09.)
2017-10-09)
</li>
<li>
"And now, driving to California, I find that I must enter a password

View File

@ -114,7 +114,7 @@ Indiana, which switched from central to eastern time in 1991
and switched back in 2006.
To use the database on an extended <a
href="https://en.wikipedia.org/wiki/POSIX"><abbr
title="Portable Operating System Interface">POSIX</abbr></a>
title="Portable Operating System Interface">POSIX</abbr>.1-2017</a>
implementation set the <code><abbr>TZ</abbr></code>
environment variable to the location's full name,
e.g., <code><abbr>TZ</abbr>="America/New_York"</code>.</p>
@ -172,7 +172,7 @@ Since version 2022a, each release has been distributed in
ustar interchange format</a>, compressed as described above;
older releases use a nearly compatible format.
Since version 2016h, each release has contained a text file named
"<samp>version</samp>" whose first (and currently only) line is the version.
"<code>version</code>" whose first (and currently only) line is the version.
Older releases are <a href="https://ftp.iana.org/tz/releases/">archived</a>,
and are also available in an
<a href="ftp://ftp.iana.org/tz/releases/"><abbr
@ -362,9 +362,6 @@ lets you see the <code><abbr>TZ</abbr></code> values directly.</li>
<li><a
href="https://www.convertit.com/Go/ConvertIt/World_Time/Current_Time.ASP">Current
Time in 1000 Places</a> uses descriptions of the values.</li>
<li><a href="https://home.kpn.nl/vanadovv/time/TZworld.html">Complete
timezone information for all countries</a>
displays tables of <abbr>DST</abbr> rules.
<li><a href="https://www.timeanddate.com/worldclock/">The World Clock &ndash;
Worldwide</a> lets you sort zone names and convert times.</li>
<li><a href="https://24timezones.com">24TimeZones</a> has a world
@ -511,12 +508,12 @@ It is freely available under the Apache License.</li>
<li>Many modern
<a href="https://en.wikipedia.org/wiki/JavaScript">JavaScript</a>
runtimes support <code><abbr>tz</abbr></code> natively via the
<samp>timeZone</samp> option of <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat"><samp>Intl.DateTimeFormat</samp></a>.
<code>timeZone</code> option of <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat"><code>Intl.DateTimeFormat</code></a>.
This can be used as-is or with most of the following libraries,
many of which also support runtimes lacking the <samp>timeZone</samp> option.
many of which also support runtimes lacking the <code>timeZone</code> option.
<ul>
<li>The <a
href="https://github.com/formatjs/date-time-format-timezone"><samp>Intl.DateTimeFormat</samp>
href="https://github.com/formatjs/date-time-format-timezone"><code>Intl.DateTimeFormat</code>
timezone polyfill</a>
is freely available under a <abbr>BSD</abbr>-style license.</li>
<li>The <a href="https://date-fns.org/">date-fns</a>
@ -529,7 +526,7 @@ the <a href="https://momentjs.com/docs/">now-legacy Moment.js</a> date
manipulation library.
It is freely available under the <abbr>MIT</abbr> license.</li>
<li><a href="https://moment.github.io/luxon/">Luxon</a> improves
timezone support for the <samp>Intl</samp> API.
timezone support for the <code>Intl</code> API.
It is freely available under the <abbr>MIT</abbr> license.</li>
<li><a href="https://momentjs.com/timezone/">Moment Timezone</a> is a
Moment.js plugin.
@ -550,11 +547,11 @@ convert timestamps, view transition histories, and download code and data.
It is freely available under the <abbr>MIT</abbr> license.</li>
</ul>
The proposed <a
href="https://github.com/tc39/proposal-temporal"><samp>Temporal</samp>
href="https://github.com/tc39/proposal-temporal"><code>Temporal</code>
objects</a> let programs access an abstract view of
<code><abbr>tzdb</abbr></code> data, and are designed to replace <a
href="https://codeofmatt.com/javascript-date-type-is-horribly-broken/">JavaScript's
problematic <samp>Date</samp> objects</a> when working with dates and times.
problematic <code>Date</code> objects</a> when working with dates and times.
<li><a href="https://github.com/JuliaTime/">JuliaTime</a> contains a
compiler from <code><abbr>tz</abbr></code> source into
<a href="https://julialang.org/">Julia</a>. It is freely available
@ -620,6 +617,16 @@ the Apache License.</li>
library that translates between <abbr>UT</abbr> and civil time and
can read <abbr>TZif</abbr> files. It is freely available under the Apache
License.</li>
<li>The
<a href="https://github.com/nayarsystems/posix_tz_db"><code>posix_tz_db</code>
package</a> contains Python code
to generate <abbr>CSV</abbr> and <abbr>JSON</abbr> tables that map
<code><abbr>tz</abbr></code> settings to POSIX.1-2017-like approximations.
For example, it maps <code>"Africa/Cairo"</code>
to <code>"EET-2EEST,M4.5.5/0,M10.5.4/24"</code>,
an approximation valid for Cairo timestamps from 2023 on.
This can help porting to platforms that support only POSIX.1-2017.
The package is freely available under the MIT license.</li>
<li><a href="https://github.com/derickr/timelib">Timelib</a> is a C
library that reads <abbr>TZif</abbr> files and converts
timestamps from one time zone or format to another.
@ -666,9 +673,7 @@ available under a <abbr>BSD</abbr>-style license.</li>
<ul>
<li><a href="https://foxclocks.org">FoxClocks</a>
is an extension for <a href="https://www.google.com/chrome/">Google
Chrome</a> and for <a
href="https://wiki.mozilla.org/Modules/Toolkit">Mozilla
Toolkit</a> applications like <a
Chrome</a>, <a
href="https://www.mozilla.org/en-US/firefox/new/">Firefox</a> and <a
href="https://www.mozilla.org/en-US/thunderbird/">Thunderbird</a>.
It displays multiple clocks in the application window, and has a mapping
@ -782,32 +787,9 @@ boundaries of <code><abbr>tzdb</abbr></code> timezones.
Its code is freely available under the <abbr>MIT</abbr> license, and
its data entries are freely available under the
<a href="https://opendatacommons.org/licenses/odbl/">Open Data Commons
Open Database License</a>. The maps' borders appear to be quite accurate.</li>
<li>Programmatic interfaces that map geographical coordinates via tz_world to
<code><abbr>tzdb</abbr></code> timezones include:
<ul>
<li><a href="https://github.com/mj1856/GeoTimeZone">GeoTimeZone</a> is
written in <a
href="https://en.wikipedia.org/wiki/C_Sharp_(programming_language)">C#</a>
and is freely available under the <abbr>MIT</abbr> license.</li>
<li>The <a href="https://github.com/bradfitz/latlong">latlong package</a>
is written in Go and is freely available under the Apache License.</li>
<li><a href="https://github.com/drtimcooper/LatLongToTimezone">LatLongToTimezone</a>,
in both Java and
<a href="https://en.wikipedia.org/wiki/Swift_(programming_language)">Swift</a>
form, is freely available under the MIT license.</li>
<li>For Node.js,
the <a href="https://www.npmjs.com/package/geo-tz">geo-tz module</a>
is freely available under the MIT license, and
the <a href="https://www.npmjs.com/package/tz-lookup">tz-lookup module</a>
is in the public domain.</li>
<li>The <a
href="https://github.com/MrMinimal64/timezonefinder">timezonefinder</a>
library for Python is freely available under the MIT license.
<li>The <a
href="https://github.com/gunyarakun/timezone_finder">timezone_finder</a>
library for Ruby is freely available under the MIT license.</li>
</ul></li>
Open Database License</a>. The borders appear to be quite accurate.
Its main web page lists more than twenty libraries
for looking up a timezone name from a GPS coordinate.</li>
<li>Free access via a network API, if you register a key, is provided by
the <a
href="https://www.geonames.org/export/web-services.html#timezone">GeoNames
@ -826,12 +808,9 @@ coordinates?</a>" discusses other geolocation possibilities.</li>
<li><a href="http://statoids.com/statoids.html">Administrative
Divisions of Countries ("Statoids")</a> lists
political subdivision data related to time zones.</li>
<li><a href="https://home.kpn.nl/vanadovv/time/Multizones.html">Time
zone boundaries for multizone countries</a> summarizes legal
boundaries between time zones within countries.</li>
<li><a href="https://manifold.net/info/freestuff.shtml">Manifold Software
&ndash; GIS and Database Tools</a> includes a Manifold-format map of
world time zone boundaries distributed under the
world time zone boundaries circa 2007, distributed under the
<abbr>GPL</abbr>.</li>
<li>A ship within the <a
href="https://en.wikipedia.org/wiki/Territorial_waters">territorial
@ -862,7 +841,7 @@ Lords</a> discusses how authoritarians manipulate civil time.</li>
<li><a href="https://www.w3.org/TR/timezone/">Working with Time Zones</a>
contains guidelines and best practices for software applications that
deal with civil time.</li>
<li><a href="https://www.staff.science.uu.nl/~gent0113/idl/idl.htm">A History of
<li><a href="https://webspace.science.uu.nl/~gent0113/idl/idl.htm">A History of
the International Date Line</a> tells the story of the most important
time zone boundary.</li>
<li><a href="http://statoids.com/tconcept.html">Basic Time
@ -875,7 +854,7 @@ Zone Concepts</a> discusses terminological issues behind time zones.</li>
<dl>
<dt>Australia</dt>
<dd>The Parliamentary Library commissioned a <a
href="https://www.aph.gov.au/binaries/library/pubs/rp/2009-10/10rp10.pdf">research
href="https://parlinfo.aph.gov.au/parlInfo/download/library/prspub/359V6/upload_binary/359v60.pdf">research
paper on daylight saving time in Australia</a>.
The Bureau of Meteorology publishes a list of <a
href="http://www.bom.gov.au/climate/averages/tables/dst_times.shtml">Implementation
@ -883,9 +862,9 @@ Dates of Daylight Savings Time within Australia</a>.</dd>
<dt>Belgium</dt>
<dd>The Royal Observatory of Belgium maintains a table of time in
Belgium (in
<a href="https://www.astro.oma.be/GENERAL/INFO/nli001a.html"
<a href="https://robinfo.oma.be/nl/astro-info/tijd/"
hreflang="nl">Dutch</a> and <a
href="https://www.astro.oma.be/GENERAL/INFO/fri001a.html"
href="https://robinfo.oma.be/fr/astro-info/heure/"
hreflang="fr">French</a>).</dd>
<dt>Brazil</dt>
<dd>The Time Service Department of the National Observatory
@ -929,7 +908,7 @@ Congress has published a <a
href="https://www.diputados.gob.mx/bibliot/publica/inveyana/polisoc/horver/index.htm"
hreflang="es">history of Mexican local time (in Spanish)</a>.</dd>
<dt>Netherlands</dt>
<dd><a href="https://www.staff.science.uu.nl/~gent0113/wettijd/wettijd.htm"
<dd><a href="https://webspace.science.uu.nl/~gent0113/wettijd/wettijd.htm"
hreflang="nl">Legal time in the Netherlands (in Dutch)</a>
covers the history of local time in the Netherlands from ancient times.</dd>
<dt>New Zealand</dt>
@ -938,7 +917,7 @@ href="https://www.dia.govt.nz/Daylight-Saving-History">History of
Daylight Saving</a>.</dd>
<dt>Palestine</dt>
<dd>The Ministry of Telecom and IT publishes a <a
href="https://mtit.pna.ps/Site/TimeZoon"
href="https://mtit.pna.ps/home/TimeZone"
hreflang="ar">history of clock changes (in Arabic)</a>.</dd>
<dt>Portugal</dt>
<dd>The Lisbon Astronomical Observatory publishes a
@ -973,6 +952,9 @@ zone shifts, and many scientific studies have been conducted. This
section summarizes reviews and position statements based on
scientific literature in the area.</p>
<ul>
<li>In 2022 the American Medical Association issued a
<a href="https://www.ama-assn.org/press-center/press-releases/ama-calls-permanent-standard-time">statement
supporting permanent standard time</a> on health grounds.</li>
<li>Carey RN, Sarma KM.
<a href="https://bmjopen.bmj.com/content/7/6/e014319.long">Impact of
daylight saving time on road traffic collision risk: a systematic
@ -983,25 +965,36 @@ neither supports nor refutes road safety benefits from
shifts in time zones.</li>
<li>Havranek T, Herman D, Irsova D.
<a href="https://www.iaee.org/en/publications/ejarticle.aspx?id=3051">Does
daylight saving save electricity? A meta-analysis.</a>
daylight saving save electricity? A meta-analysis</a>.
<em>Energy J.</em> 2018;39(2):35&ndash;61.
doi:<a href="https://doi.org/10.5547/01956574.39.2.thav">10.5547/01956574.39.2.thav</a>.
This analyzes research literature and concludes, "Electricity savings
are larger for countries farther away from the equator, while
subtropical regions consume more electricity because of <abbr>DST</abbr>."</li>
<li>Rishi MA, Ahmed O, Barrantes Perez JH <em>et al</em>.
<a href="https://jcsm.aasm.org/doi/10.5664/jcsm.8780">Daylight saving time:
<li>Malow BA. <a
href="https://academic.oup.com/sleep/article/45/12/zsac236/6717940">It is time
to abolish the clock change and adopt permanent
standard time in the United States:
a Sleep Research Society position statement</a>.
<em>Sleep.</em> 2022;45(12):zsac236.
doi:<a href="https://doi.org/10.1093/sleep/zsac236">10.1093/sleep/zsac236</a>.
After reviewing the scientific literature, the Sleep Research Society
advocates permanent standard time due to its health benefits.
<li>Rishi MA, Cheng JY, Strang AR <em>et al</em>.
<a href="https://jcsm.aasm.org/doi/10.5664/jcsm.10898">Permanent standard time
is the optimal choice for health and safety:
an American Academy of Sleep Medicine position statement</a>.
<em>J Clin Sleep Med.</em>
2020;<a href="https://doi.org/10.5664/jcsm.8780">10.5664/jcsm.8780</a>.
This argues for permanent standard time due to health risks of both
<abbr>DST</abbr> transitions and permanent <abbr>DST</abbr>.</li>
<em>J Clin Sleep Med.</em> 2024;20(1):121&ndash;125.
doi:<a href="https://doi.org/10.5664/jcsm.10898">10.5664/jcsm.10898</a>.
The AASM argues for permanent standard time due to health and safety risks
and economic costs of both <abbr>DST</abbr> transitions and
permanent <abbr>DST</abbr>.</li>
<li>Roenneberg T, Wirz-Justice A, Skene DJ <em>et al</em>.
<a href="https://www.ncbi.nlm.nih.gov/pmc/articles/PMC7205184/">Why
<a href="https://journals.sagepub.com/doi/10.1177/0748730419854197">Why
should we abolish Daylight Saving Time?</a>
<em>J Biol Rhythms</em>. 2019;34(3):227&ndash;230.
<em>J Biol Rhythms.</em> 2019;34(3):227&ndash;230.
doi:<a href="https://doi.org/10.1177/0748730419854197">10.1177/0748730419854197</a>.
This position paper of the Society for Research on Biological Rhythms
The Society for Research on Biological Rhythms
opposes DST changes and permanent DST, and advocates that governments adopt
"permanent Standard Time for the health and safety of their citizens".</li>
</ul>
@ -1117,9 +1110,12 @@ might be redefined
without Leap Seconds</a> gives pointers on this
contentious issue.
The General Conference on Weights and Measures
<a href="https://www.bipm.org/en/cgpm-2022/resolution-4">voted in 2022</a>
<a href="https://www.bipm.org/en/cgpm-2022/resolution-4">decided in 2022</a>
to discontinue the use of leap seconds by 2035, replacing them with an
as-yet-undetermined scheme some time after the year 2135.
The World Radiocommunication Conference <a
href="https://www.itu.int/dms_pub/itu-r/opb/act/R-ACT-WRC.15-2023-PDF-E.pdf">resolved
in 2023</a> to cooperate with this process.
</li>
</ul>
</section>

114
tzfile.5
View File

@ -26,23 +26,24 @@ a signed binary integer is represented using two's complement,
and a boolean is represented by a one-byte binary integer that is
either 0 (false) or 1 (true).
The format begins with a 44-byte header containing the following fields:
.IP * 2
.RS "\w' 'u"
.IP \(bu "\w'\(bu 'u"
The magic four-byte ASCII sequence
.q "TZif"
identifies the file as a timezone information file.
.IP *
.IP \(bu
A byte identifying the version of the file's format
(as of 2021, either an ASCII NUL,
.q "2",
.q "3",
or
.q "4" ).
.IP *
.IP \(bu
Fifteen bytes containing zeros reserved for future use.
.IP *
.IP \(bu
Six four-byte integer values, in the following order:
.RS
.TP
.RS "\w' \(bu 'u"
.TP "\w' 'u"
.B tzh_ttisutcnt
The number of UT/local indicators stored in the file.
(UT is Universal Time.)
@ -68,14 +69,15 @@ stored in the file.
.PP
The above header is followed by the following fields, whose lengths
depend on the contents of the header:
.IP * 2
.RS "\w' 'u"
.IP \(bu "\w'\(bu 'u"
.B tzh_timecnt
four-byte signed integer values sorted in ascending order.
These values are written in network byte order.
Each is used as a transition time (as returned by
.BR time (2))
at which the rules for computing local time change.
.IP *
.IP \(bu
.B tzh_timecnt
one-byte unsigned integer values;
each one but the last tells which of the different types of local time types
@ -83,22 +85,22 @@ described in the file is associated with the time period
starting with the same-indexed transition time
and continuing up to but not including the next transition time.
(The last time type is present only for consistency checking with the
POSIX-style TZ string described below.)
POSIX.1-2017-style TZ string described below.)
These values serve as indices into the next field.
.IP *
.IP \(bu
.B tzh_typecnt
.B ttinfo
entries, each defined as follows:
.in +.5i
.in +2
.sp
.nf
.ta .5i +\w'unsigned char\0\0'u
.ta \w'\0\0\0\0'u +\w'unsigned char\0'u
struct ttinfo {
int32_t tt_utoff;
unsigned char tt_isdst;
unsigned char tt_desigidx;
};
.in -.5i
.in
.fi
.sp
Each structure is written as a four-byte signed integer value for
@ -132,7 +134,8 @@ Also, in realistic applications
is in the range [\-89999, 93599] (i.e., more than \-25 hours and less
than 26 hours); this allows easy support by implementations that
already support the POSIX-required range [\-24:59:59, 25:59:59].
.IP *
.RS "\w' 'u"
.IP \(bu "\w'\(bu 'u"
.B tzh_charcnt
bytes that represent time zone designations,
which are null-terminated byte strings, each indexed by the
@ -140,7 +143,7 @@ which are null-terminated byte strings, each indexed by the
values mentioned above.
The byte strings can overlap if one is a suffix of the other.
The encoding of these strings is not specified.
.IP *
.IP \(bu
.B tzh_leapcnt
pairs of four-byte values, written in network byte order;
the first value of each pair gives the nonnegative time
@ -167,22 +170,24 @@ otherwise, for timestamps before the first occurrence time,
the leap-second correction is zero if the first pair's correction is 1 or \-1,
and is unspecified otherwise (which can happen only in files
truncated at the start).
.IP *
.IP \(bu
.B tzh_ttisstdcnt
standard/wall indicators, each stored as a one-byte boolean;
they tell whether the transition times associated with local time types
were specified as standard time or local (wall clock) time.
.IP *
.IP \(bu
.B tzh_ttisutcnt
UT/local indicators, each stored as a one-byte boolean;
they tell whether the transition times associated with local time types
were specified as UT or local time.
If a UT/local indicator is set, the corresponding standard/wall indicator
must also be set.
.RE
.PP
The standard/wall and UT/local indicators were designed for
transforming a TZif file's transition times into transitions appropriate
for another time zone specified via a POSIX-style TZ string that lacks rules.
for another time zone specified via
a POSIX.1-2017-style TZ string that lacks rules.
For example, when TZ="EET\*-2EEST" and there is no TZif file "EET\*-2EEST",
the idea was to adapt the transition times from a TZif file with the
well-known name "posixrules" that is present only for this purpose and
@ -211,13 +216,14 @@ the above header and data are followed by a second header and data,
identical in format except that
eight bytes are used for each transition time or leap second time.
(Leap second counts remain four bytes.)
After the second header and data comes a newline-enclosed,
POSIX-TZ-environment-variable-style string for use in handling instants
After the second header and data comes a newline-enclosed string
in the style of the contents of a POSIX.1-2017 TZ environment variable,
for use in handling instants
after the last transition time stored in the file
or for all instants if the file has no transitions.
The POSIX-style TZ string is empty (i.e., nothing between the newlines)
if there is no POSIX-style representation for such instants.
If nonempty, the POSIX-style TZ string must agree with the local time
The TZ string is empty (i.e., nothing between the newlines)
if there is no POSIX.1-2017-style representation for such instants.
If nonempty, the TZ string must agree with the local time
type after the last transition time if present in the eight-byte data;
for example, given the string
.q "WET0WEST,M3.5.0/1,M10.5.0"
@ -229,8 +235,8 @@ Also, if there is at least one transition, time type 0 is associated
with the time period from the indefinite past up to but not including
the earliest transition time.
.SS Version 3 format
For version-3-format timezone files, the POSIX-TZ-style string may
use two minor extensions to the POSIX TZ format, as described in
For version-3-format timezone files, the TZ string may
use two minor extensions to the POSIX.1-2017 TZ format, as described in
.BR newtzset (3).
First, the hours part of its transition times may be signed and range from
\-167 through 167 instead of the POSIX-required unsigned values
@ -312,15 +318,17 @@ This section documents common problems in reading or writing TZif files.
Most of these are problems in generating TZif files for use by
older readers.
The goals of this section are:
.IP * 2
.RS "\w' 'u"
.IP \(bu "\w'\(bu 'u"
to help TZif writers output files that avoid common
pitfalls in older or buggy TZif readers,
.IP *
.IP \(bu
to help TZif readers avoid common pitfalls when reading
files generated by future TZif writers, and
.IP *
.IP \(bu
to help any future specification authors see what sort of
problems arise when the TZif format is changed.
.RE
.PP
When new versions of the TZif format have been defined, a
design goal has been that a reader can successfully use a TZif
@ -335,21 +343,22 @@ workarounds, as well as to document other common bugs in
readers.
.PP
Interoperability problems with TZif include the following:
.IP * 2
.RS "\w' 'u"
.IP \(bu "\w'\(bu 'u"
Some readers examine only version 1 data.
As a partial workaround, a writer can output as much version 1
data as possible.
However, a reader should ignore version 1 data, and should use
version 2+ data even if the reader's native timestamps have only
32 bits.
.IP *
.IP \(bu
Some readers designed for version 2 might mishandle
timestamps after a version 3 or higher file's last transition, because
they cannot parse extensions to POSIX in the TZ-like string.
they cannot parse extensions to POSIX.1-2017 in the TZ-like string.
As a partial workaround, a writer can output more transitions
than necessary, so that only far-future timestamps are
mishandled by version 2 readers.
.IP *
.IP \(bu
Some readers designed for version 2 do not support
permanent daylight saving time with transitions after 24:00
\(en e.g., a TZ string
@ -367,22 +376,22 @@ for the next time zone east \(en e.g.,
.q "AST4"
for permanent
Atlantic Standard Time (\-04).
.IP *
.IP \(bu
Some readers designed for version 2 or 3, and that require strict
conformance to RFC 8536, reject version 4 files whose leap second
tables are truncated at the start or that end in expiration times.
.IP *
.IP \(bu
Some readers ignore the footer, and instead predict future
timestamps from the time type of the last transition.
As a partial workaround, a writer can output more transitions
than necessary.
.IP *
.IP \(bu
Some readers do not use time type 0 for timestamps before
the first transition, in that they infer a time type using a
heuristic that does not always select time type 0.
As a partial workaround, a writer can output a dummy (no-op)
first transition at an early time.
.IP *
.IP \(bu
Some readers mishandle timestamps before the first
transition that has a timestamp not less than \-2**31.
Readers that support only 32-bit timestamps are likely to be
@ -391,12 +400,12 @@ more prone to this problem, for example, when they process
bits.
As a partial workaround, a writer can output a dummy
transition at timestamp \-2**31.
.IP *
.IP \(bu
Some readers mishandle a transition if its timestamp has
the minimum possible signed 64-bit value.
Timestamps less than \-2**59 are not recommended.
.IP *
Some readers mishandle POSIX-style TZ strings that
.IP \(bu
Some readers mishandle TZ strings that
contain
.q "<"
or
@ -407,11 +416,11 @@ or
.q ">"
for time zone abbreviations containing only alphabetic
characters.
.IP *
.IP \(bu
Many readers mishandle time zone abbreviations that contain
non-ASCII characters.
These characters are not recommended.
.IP *
.IP \(bu
Some readers may mishandle time zone abbreviations that
contain fewer than 3 or more than 6 characters, or that
contain ASCII characters other than alphanumerics,
@ -419,23 +428,23 @@ contain ASCII characters other than alphanumerics,
and
.q "+".
These abbreviations are not recommended.
.IP *
.IP \(bu
Some readers mishandle TZif files that specify
daylight-saving time UT offsets that are less than the UT
offsets for the corresponding standard time.
These readers do not support locations like Ireland, which
uses the equivalent of the POSIX TZ string
uses the equivalent of the TZ string
.q "IST\*-1GMT0,M10.5.0,M3.5.0/1",
observing standard time
(IST, +01) in summer and daylight saving time (GMT, +00) in winter.
As a partial workaround, a writer can output data for the
equivalent of the POSIX TZ string
equivalent of the TZ string
.q "GMT0IST,M3.5.0/1,M10.5.0",
thus swapping standard and daylight saving time.
Although this workaround misidentifies which part of the year
uses daylight saving time, it records UT offsets and time zone
abbreviations correctly.
.IP *
.IP \(bu
Some readers generate ambiguous timestamps for positive leap seconds
that occur when the UTC offset is not a multiple of 60 seconds.
For example, in a timezone with UTC offset +01:23:45 and with
@ -446,38 +455,41 @@ instead of mapping the latter to 01:23:46, and they will map 78796815 to
This has not yet been a practical problem, since no civil authority
has observed such UTC offsets since leap seconds were
introduced in 1972.
.RE
.PP
Some interoperability problems are reader bugs that
are listed here mostly as warnings to developers of readers.
.IP * 2
.RS "\w' 'u"
.IP \(bu "\w'\(bu 'u"
Some readers do not support negative timestamps.
Developers of distributed applications should keep this
in mind if they need to deal with pre-1970 data.
.IP *
.IP \(bu
Some readers mishandle timestamps before the first
transition that has a nonnegative timestamp.
Readers that do not support negative timestamps are likely to
be more prone to this problem.
.IP *
.IP \(bu
Some readers mishandle time zone abbreviations like
.q "\*-08"
that contain
.q "+",
.q "\*-",
or digits.
.IP *
.IP \(bu
Some readers mishandle UT offsets that are out of the
traditional range of \-12 through +12 hours, and so do not
support locations like Kiritimati that are outside this
range.
.IP *
.IP \(bu
Some readers mishandle UT offsets in the range [\-3599, \-1]
seconds from UT, because they integer-divide the offset by
3600 to get 0 and then display the hour part as
.q "+00".
.IP *
.IP \(bu
Some readers mishandle UT offsets that are not a multiple
of one hour, or of 15 minutes, or of 1 minute.
.RE
.SH SEE ALSO
.BR time (2),
.BR localtime (3),

View File

@ -14,356 +14,367 @@ DESCRIPTION
a one-byte binary integer that is either 0 (false) or 1 (true). The
format begins with a 44-byte header containing the following fields:
* The magic four-byte ASCII sequence "TZif" identifies the file as a
timezone information file.
o The magic four-byte ASCII sequence "TZif" identifies the file as a
timezone information file.
* A byte identifying the version of the file's format (as of 2021,
either an ASCII NUL, "2", "3", or "4").
o A byte identifying the version of the file's format (as of 2021,
either an ASCII NUL, "2", "3", or "4").
* Fifteen bytes containing zeros reserved for future use.
o Fifteen bytes containing zeros reserved for future use.
* Six four-byte integer values, in the following order:
o Six four-byte integer values, in the following order:
tzh_ttisutcnt
The number of UT/local indicators stored in the file. (UT is
Universal Time.)
tzh_ttisutcnt
The number of UT/local indicators stored in the file. (UT
is Universal Time.)
tzh_ttisstdcnt
The number of standard/wall indicators stored in the file.
tzh_ttisstdcnt
The number of standard/wall indicators stored in the file.
tzh_leapcnt
The number of leap seconds for which data entries are stored
in the file.
tzh_leapcnt
The number of leap seconds for which data entries are stored
in the file.
tzh_timecnt
The number of transition times for which data entries are
stored in the file.
tzh_timecnt
The number of transition times for which data entries are
stored in the file.
tzh_typecnt
The number of local time types for which data entries are
stored in the file (must not be zero).
tzh_typecnt
The number of local time types for which data entries are
stored in the file (must not be zero).
tzh_charcnt
The number of bytes of time zone abbreviation strings stored
in the file.
tzh_charcnt
The number of bytes of time zone abbreviation strings stored
in the file.
The above header is followed by the following fields, whose lengths
depend on the contents of the header:
The above header is followed by the following fields, whose lengths
depend on the contents of the header:
* tzh_timecnt four-byte signed integer values sorted in ascending
order. These values are written in network byte order. Each is used
as a transition time (as returned by time(2)) at which the rules for
computing local time change.
o tzh_timecnt four-byte signed integer values sorted in ascending
order. These values are written in network byte order. Each is
used as a transition time (as returned by time(2)) at which the
rules for computing local time change.
* tzh_timecnt one-byte unsigned integer values; each one but the last
tells which of the different types of local time types described in
the file is associated with the time period starting with the same-
indexed transition time and continuing up to but not including the
next transition time. (The last time type is present only for
consistency checking with the POSIX-style TZ string described below.)
These values serve as indices into the next field.
o tzh_timecnt one-byte unsigned integer values; each one but the
last tells which of the different types of local time types
described in the file is associated with the time period
starting with the same-indexed transition time and continuing up
to but not including the next transition time. (The last time
type is present only for consistency checking with the
POSIX.1-2017-style TZ string described below.) These values
serve as indices into the next field.
* tzh_typecnt ttinfo entries, each defined as follows:
o tzh_typecnt ttinfo entries, each defined as follows:
struct ttinfo {
int32_t tt_utoff;
unsigned char tt_isdst;
unsigned char tt_desigidx;
};
struct ttinfo {
int32_t tt_utoff;
unsigned char tt_isdst;
unsigned char tt_desigidx;
};
Each structure is written as a four-byte signed integer value for
tt_utoff, in network byte order, followed by a one-byte boolean for
tt_isdst and a one-byte value for tt_desigidx. In each structure,
tt_utoff gives the number of seconds to be added to UT, tt_isdst
tells whether tm_isdst should be set by localtime(3) and tt_desigidx
serves as an index into the array of time zone abbreviation bytes
that follow the ttinfo entries in the file; if the designated string
is "-00", the ttinfo entry is a placeholder indicating that local
time is unspecified. The tt_utoff value is never equal to -2**31, to
let 32-bit clients negate it without overflow. Also, in realistic
applications tt_utoff is in the range [-89999, 93599] (i.e., more
than -25 hours and less than 26 hours); this allows easy support by
implementations that already support the POSIX-required range
[-24:59:59, 25:59:59].
Each structure is written as a four-byte signed integer value
for tt_utoff, in network byte order, followed by a one-byte
boolean for tt_isdst and a one-byte value for tt_desigidx. In
each structure, tt_utoff gives the number of seconds to be added
to UT, tt_isdst tells whether tm_isdst should be set by
localtime(3) and tt_desigidx serves as an index into the array
of time zone abbreviation bytes that follow the ttinfo entries
in the file; if the designated string is "-00", the ttinfo entry
is a placeholder indicating that local time is unspecified. The
tt_utoff value is never equal to -2**31, to let 32-bit clients
negate it without overflow. Also, in realistic applications
tt_utoff is in the range [-89999, 93599] (i.e., more than -25
hours and less than 26 hours); this allows easy support by
implementations that already support the POSIX-required range
[-24:59:59, 25:59:59].
* tzh_charcnt bytes that represent time zone designations, which are
null-terminated byte strings, each indexed by the tt_desigidx values
mentioned above. The byte strings can overlap if one is a suffix of
the other. The encoding of these strings is not specified.
o tzh_charcnt bytes that represent time zone designations, which
are null-terminated byte strings, each indexed by the
tt_desigidx values mentioned above. The byte strings can
overlap if one is a suffix of the other. The encoding of
these strings is not specified.
* tzh_leapcnt pairs of four-byte values, written in network byte order;
the first value of each pair gives the nonnegative time (as returned
by time(2)) at which a leap second occurs or at which the leap second
table expires; the second is a signed integer specifying the
correction, which is the total number of leap seconds to be applied
during the time period starting at the given time. The pairs of
values are sorted in strictly ascending order by time. Each pair
denotes one leap second, either positive or negative, except that if
the last pair has the same correction as the previous one, the last
pair denotes the leap second table's expiration time. Each leap
second is at the end of a UTC calendar month. The first leap second
has a nonnegative occurrence time, and is a positive leap second if
and only if its correction is positive; the correction for each leap
second after the first differs from the previous leap second by
either 1 for a positive leap second, or -1 for a negative leap
second. If the leap second table is empty, the leap-second
correction is zero for all timestamps; otherwise, for timestamps
before the first occurrence time, the leap-second correction is zero
if the first pair's correction is 1 or -1, and is unspecified
otherwise (which can happen only in files truncated at the start).
o tzh_leapcnt pairs of four-byte values, written in network byte
order; the first value of each pair gives the nonnegative time
(as returned by time(2)) at which a leap second occurs or at
which the leap second table expires; the second is a signed
integer specifying the correction, which is the total number
of leap seconds to be applied during the time period starting
at the given time. The pairs of values are sorted in strictly
ascending order by time. Each pair denotes one leap second,
either positive or negative, except that if the last pair has
the same correction as the previous one, the last pair denotes
the leap second table's expiration time. Each leap second is
at the end of a UTC calendar month. The first leap second has
a nonnegative occurrence time, and is a positive leap second
if and only if its correction is positive; the correction for
each leap second after the first differs from the previous
leap second by either 1 for a positive leap second, or -1 for
a negative leap second. If the leap second table is empty,
the leap-second correction is zero for all timestamps;
otherwise, for timestamps before the first occurrence time,
the leap-second correction is zero if the first pair's
correction is 1 or -1, and is unspecified otherwise (which can
happen only in files truncated at the start).
* tzh_ttisstdcnt standard/wall indicators, each stored as a one-byte
boolean; they tell whether the transition times associated with local
time types were specified as standard time or local (wall clock)
time.
o tzh_ttisstdcnt standard/wall indicators, each stored as a one-
byte boolean; they tell whether the transition times
associated with local time types were specified as standard
time or local (wall clock) time.
* tzh_ttisutcnt UT/local indicators, each stored as a one-byte boolean;
they tell whether the transition times associated with local time
types were specified as UT or local time. If a UT/local indicator is
set, the corresponding standard/wall indicator must also be set.
o tzh_ttisutcnt UT/local indicators, each stored as a one-byte
boolean; they tell whether the transition times associated
with local time types were specified as UT or local time. If
a UT/local indicator is set, the corresponding standard/wall
indicator must also be set.
The standard/wall and UT/local indicators were designed for
transforming a TZif file's transition times into transitions
appropriate for another time zone specified via a POSIX-style TZ string
that lacks rules. For example, when TZ="EET-2EEST" and there is no
TZif file "EET-2EEST", the idea was to adapt the transition times from
a TZif file with the well-known name "posixrules" that is present only
for this purpose and is a copy of the file "Europe/Brussels", a file
with a different UT offset. POSIX does not specify this obsolete
transformational behavior, the default rules are installation-
dependent, and no implementation is known to support this feature for
timestamps past 2037, so users desiring (say) Greek time should instead
specify TZ="Europe/Athens" for better historical coverage, falling back
on TZ="EET-2EEST,M3.5.0/3,M10.5.0/4" if POSIX conformance is required
and older timestamps need not be handled accurately.
The standard/wall and UT/local indicators were designed for
transforming a TZif file's transition times into transitions
appropriate for another time zone specified via a
POSIX.1-2017-style TZ string that lacks rules. For example, when
TZ="EET-2EEST" and there is no TZif file "EET-2EEST", the idea was
to adapt the transition times from a TZif file with the well-known
name "posixrules" that is present only for this purpose and is a
copy of the file "Europe/Brussels", a file with a different UT
offset. POSIX does not specify this obsolete transformational
behavior, the default rules are installation-dependent, and no
implementation is known to support this feature for timestamps past
2037, so users desiring (say) Greek time should instead specify
TZ="Europe/Athens" for better historical coverage, falling back on
TZ="EET-2EEST,M3.5.0/3,M10.5.0/4" if POSIX conformance is required
and older timestamps need not be handled accurately.
The localtime(3) function normally uses the first ttinfo structure in
the file if either tzh_timecnt is zero or the time argument is less
than the first transition time recorded in the file.
The localtime(3) function normally uses the first ttinfo structure
in the file if either tzh_timecnt is zero or the time argument is
less than the first transition time recorded in the file.
Version 2 format
For version-2-format timezone files, the above header and data are
followed by a second header and data, identical in format except that
eight bytes are used for each transition time or leap second time.
(Leap second counts remain four bytes.) After the second header and
data comes a newline-enclosed, POSIX-TZ-environment-variable-style
string for use in handling instants after the last transition time
stored in the file or for all instants if the file has no transitions.
The POSIX-style TZ string is empty (i.e., nothing between the newlines)
if there is no POSIX-style representation for such instants. If
nonempty, the POSIX-style TZ string must agree with the local time type
after the last transition time if present in the eight-byte data; for
example, given the string "WET0WEST,M3.5.0/1,M10.5.0" then if a last
transition time is in July, the transition's local time type must
specify a daylight-saving time abbreviated "WEST" that is one hour east
of UT. Also, if there is at least one transition, time type 0 is
associated with the time period from the indefinite past up to but not
including the earliest transition time.
For version-2-format timezone files, the above header and data are
followed by a second header and data, identical in format except that
eight bytes are used for each transition time or leap second time.
(Leap second counts remain four bytes.) After the second header and
data comes a newline-enclosed string in the style of the contents of a
POSIX.1-2017 TZ environment variable, for use in handling instants
after the last transition time stored in the file or for all instants
if the file has no transitions. The TZ string is empty (i.e., nothing
between the newlines) if there is no POSIX.1-2017-style representation
for such instants. If nonempty, the TZ string must agree with the
local time type after the last transition time if present in the eight-
byte data; for example, given the string "WET0WEST,M3.5.0/1,M10.5.0"
then if a last transition time is in July, the transition's local time
type must specify a daylight-saving time abbreviated "WEST" that is one
hour east of UT. Also, if there is at least one transition, time type
0 is associated with the time period from the indefinite past up to but
not including the earliest transition time.
Version 3 format
For version-3-format timezone files, the POSIX-TZ-style string may use
two minor extensions to the POSIX TZ format, as described in
newtzset(3). First, the hours part of its transition times may be
signed and range from -167 through 167 instead of the POSIX-required
unsigned values from 0 through 24. Second, DST is in effect all year
if it starts January 1 at 00:00 and ends December 31 at 24:00 plus the
difference between daylight saving and standard time.
For version-3-format timezone files, the TZ string may use two minor
extensions to the POSIX.1-2017 TZ format, as described in newtzset(3).
First, the hours part of its transition times may be signed and range
from -167 through 167 instead of the POSIX-required unsigned values
from 0 through 24. Second, DST is in effect all year if it starts
January 1 at 00:00 and ends December 31 at 24:00 plus the difference
between daylight saving and standard time.
Version 4 format
For version-4-format TZif files, the first leap second record can have
a correction that is neither +1 nor -1, to represent truncation of the
TZif file at the start. Also, if two or more leap second transitions
are present and the last entry's correction equals the previous one,
the last entry denotes the expiration of the leap second table instead
of a leap second; timestamps after this expiration are unreliable in
that future releases will likely add leap second entries after the
expiration, and the added leap seconds will change how post-expiration
For version-4-format TZif files, the first leap second record can have
a correction that is neither +1 nor -1, to represent truncation of the
TZif file at the start. Also, if two or more leap second transitions
are present and the last entry's correction equals the previous one,
the last entry denotes the expiration of the leap second table instead
of a leap second; timestamps after this expiration are unreliable in
that future releases will likely add leap second entries after the
expiration, and the added leap seconds will change how post-expiration
timestamps are treated.
Interoperability considerations
Future changes to the format may append more data.
Version 1 files are considered a legacy format and should not be
Version 1 files are considered a legacy format and should not be
generated, as they do not support transition times after the year 2038.
Readers that understand only Version 1 must ignore any data that
Readers that understand only Version 1 must ignore any data that
extends beyond the calculated end of the version 1 data block.
Other than version 1, writers should generate the lowest version number
needed by a file's data. For example, a writer should generate a
version 4 file only if its leap second table either expires or is
truncated at the start. Likewise, a writer not generating a version 4
file should generate a version 3 file only if TZ string extensions are
needed by a file's data. For example, a writer should generate a
version 4 file only if its leap second table either expires or is
truncated at the start. Likewise, a writer not generating a version 4
file should generate a version 3 file only if TZ string extensions are
necessary to accurately model transition times.
The sequence of time changes defined by the version 1 header and data
block should be a contiguous sub-sequence of the time changes defined
by the version 2+ header and data block, and by the footer. This
guideline helps obsolescent version 1 readers agree with current
readers about timestamps within the contiguous sub-sequence. It also
lets writers not supporting obsolescent readers use a tzh_timecnt of
The sequence of time changes defined by the version 1 header and data
block should be a contiguous sub-sequence of the time changes defined
by the version 2+ header and data block, and by the footer. This
guideline helps obsolescent version 1 readers agree with current
readers about timestamps within the contiguous sub-sequence. It also
lets writers not supporting obsolescent readers use a tzh_timecnt of
zero in the version 1 data block to save space.
When a TZif file contains a leap second table expiration time, TZif
readers should either refuse to process post-expiration timestamps, or
process them as if the expiration time did not exist (possibly with an
When a TZif file contains a leap second table expiration time, TZif
readers should either refuse to process post-expiration timestamps, or
process them as if the expiration time did not exist (possibly with an
error indication).
Time zone designations should consist of at least three (3) and no more
than six (6) ASCII characters from the set of alphanumerics, "-", and
"+". This is for compatibility with POSIX requirements for time zone
than six (6) ASCII characters from the set of alphanumerics, "-", and
"+". This is for compatibility with POSIX requirements for time zone
abbreviations.
When reading a version 2 or higher file, readers should ignore the
When reading a version 2 or higher file, readers should ignore the
version 1 header and data block except for the purpose of skipping over
them.
Readers should calculate the total lengths of the headers and data
Readers should calculate the total lengths of the headers and data
blocks and check that they all fit within the actual file size, as part
of a validity check for the file.
When a positive leap second occurs, readers should append an extra
second to the local minute containing the second just before the leap
second. If this occurs when the UTC offset is not a multiple of 60
seconds, the leap second occurs earlier than the last second of the
local minute and the minute's remaining local seconds are numbered
When a positive leap second occurs, readers should append an extra
second to the local minute containing the second just before the leap
second. If this occurs when the UTC offset is not a multiple of 60
seconds, the leap second occurs earlier than the last second of the
local minute and the minute's remaining local seconds are numbered
through 60 instead of the usual 59; the UTC offset is unaffected.
Common interoperability issues
This section documents common problems in reading or writing TZif
files. Most of these are problems in generating TZif files for use by
This section documents common problems in reading or writing TZif
files. Most of these are problems in generating TZif files for use by
older readers. The goals of this section are:
* to help TZif writers output files that avoid common pitfalls in older
or buggy TZif readers,
o to help TZif writers output files that avoid common pitfalls in
older or buggy TZif readers,
* to help TZif readers avoid common pitfalls when reading files
generated by future TZif writers, and
o to help TZif readers avoid common pitfalls when reading files
generated by future TZif writers, and
* to help any future specification authors see what sort of problems
arise when the TZif format is changed.
o to help any future specification authors see what sort of problems
arise when the TZif format is changed.
When new versions of the TZif format have been defined, a design goal
has been that a reader can successfully use a TZif file even if the
file is of a later TZif version than what the reader was designed for.
When complete compatibility was not achieved, an attempt was made to
limit glitches to rarely used timestamps and allow simple partial
workarounds in writers designed to generate new-version data useful
even for older-version readers. This section attempts to document
these compatibility issues and workarounds, as well as to document
When new versions of the TZif format have been defined, a design goal
has been that a reader can successfully use a TZif file even if the
file is of a later TZif version than what the reader was designed for.
When complete compatibility was not achieved, an attempt was made to
limit glitches to rarely used timestamps and allow simple partial
workarounds in writers designed to generate new-version data useful
even for older-version readers. This section attempts to document
these compatibility issues and workarounds, as well as to document
other common bugs in readers.
Interoperability problems with TZif include the following:
* Some readers examine only version 1 data. As a partial workaround, a
writer can output as much version 1 data as possible. However, a
reader should ignore version 1 data, and should use version 2+ data
even if the reader's native timestamps have only 32 bits.
o Some readers examine only version 1 data. As a partial
workaround, a writer can output as much version 1 data as
possible. However, a reader should ignore version 1 data, and
should use version 2+ data even if the reader's native timestamps
have only 32 bits.
* Some readers designed for version 2 might mishandle timestamps after
a version 3 or higher file's last transition, because they cannot
parse extensions to POSIX in the TZ-like string. As a partial
workaround, a writer can output more transitions than necessary, so
that only far-future timestamps are mishandled by version 2 readers.
o Some readers designed for version 2 might mishandle timestamps
after a version 3 or higher file's last transition, because they
cannot parse extensions to POSIX.1-2017 in the TZ-like string. As
a partial workaround, a writer can output more transitions than
necessary, so that only far-future timestamps are mishandled by
version 2 readers.
* Some readers designed for version 2 do not support permanent daylight
saving time with transitions after 24:00 - e.g., a TZ string
"EST5EDT,0/0,J365/25" denoting permanent Eastern Daylight Time (-04).
As a workaround, a writer can substitute standard time for two time
zones east, e.g., "XXX3EDT4,0/0,J365/23" for a time zone with a
never-used standard time (XXX, -03) and negative daylight saving time
(EDT, -04) all year. Alternatively, as a partial workaround a writer
can substitute standard time for the next time zone east - e.g.,
"AST4" for permanent Atlantic Standard Time (-04).
o Some readers designed for version 2 do not support permanent
daylight saving time with transitions after 24:00 - e.g., a TZ
string "EST5EDT,0/0,J365/25" denoting permanent Eastern Daylight
Time (-04). As a workaround, a writer can substitute standard
time for two time zones east, e.g., "XXX3EDT4,0/0,J365/23" for a
time zone with a never-used standard time (XXX, -03) and negative
daylight saving time (EDT, -04) all year. Alternatively, as a
partial workaround a writer can substitute standard time for the
next time zone east - e.g., "AST4" for permanent Atlantic Standard
Time (-04).
* Some readers designed for version 2 or 3, and that require strict
conformance to RFC 8536, reject version 4 files whose leap second
tables are truncated at the start or that end in expiration times.
o Some readers designed for version 2 or 3, and that require strict
conformance to RFC 8536, reject version 4 files whose leap second
tables are truncated at the start or that end in expiration times.
* Some readers ignore the footer, and instead predict future timestamps
from the time type of the last transition. As a partial workaround,
a writer can output more transitions than necessary.
o Some readers ignore the footer, and instead predict future
timestamps from the time type of the last transition. As a
partial workaround, a writer can output more transitions than
necessary.
* Some readers do not use time type 0 for timestamps before the first
transition, in that they infer a time type using a heuristic that
does not always select time type 0. As a partial workaround, a
writer can output a dummy (no-op) first transition at an early time.
o Some readers do not use time type 0 for timestamps before the
first transition, in that they infer a time type using a heuristic
that does not always select time type 0. As a partial workaround,
a writer can output a dummy (no-op) first transition at an early
time.
* Some readers mishandle timestamps before the first transition that
has a timestamp not less than -2**31. Readers that support only
32-bit timestamps are likely to be more prone to this problem, for
example, when they process 64-bit transitions only some of which are
representable in 32 bits. As a partial workaround, a writer can
output a dummy transition at timestamp -2**31.
o Some readers mishandle timestamps before the first transition that
has a timestamp not less than -2**31. Readers that support only
32-bit timestamps are likely to be more prone to this problem, for
example, when they process 64-bit transitions only some of which
are representable in 32 bits. As a partial workaround, a writer
can output a dummy transition at timestamp -2**31.
* Some readers mishandle a transition if its timestamp has the minimum
possible signed 64-bit value. Timestamps less than -2**59 are not
recommended.
o Some readers mishandle a transition if its timestamp has the
minimum possible signed 64-bit value. Timestamps less than -2**59
are not recommended.
* Some readers mishandle POSIX-style TZ strings that contain "<" or
">". As a partial workaround, a writer can avoid using "<" or ">"
for time zone abbreviations containing only alphabetic characters.
o Some readers mishandle TZ strings that contain "<" or ">". As a
partial workaround, a writer can avoid using "<" or ">" for time
zone abbreviations containing only alphabetic characters.
* Many readers mishandle time zone abbreviations that contain non-ASCII
characters. These characters are not recommended.
o Many readers mishandle time zone abbreviations that contain non-
ASCII characters. These characters are not recommended.
* Some readers may mishandle time zone abbreviations that contain fewer
than 3 or more than 6 characters, or that contain ASCII characters
other than alphanumerics, "-", and "+". These abbreviations are not
recommended.
o Some readers may mishandle time zone abbreviations that contain
fewer than 3 or more than 6 characters, or that contain ASCII
characters other than alphanumerics, "-", and "+". These
abbreviations are not recommended.
* Some readers mishandle TZif files that specify daylight-saving time
UT offsets that are less than the UT offsets for the corresponding
standard time. These readers do not support locations like Ireland,
which uses the equivalent of the POSIX TZ string
"IST-1GMT0,M10.5.0,M3.5.0/1", observing standard time (IST, +01) in
summer and daylight saving time (GMT, +00) in winter. As a partial
workaround, a writer can output data for the equivalent of the POSIX
TZ string "GMT0IST,M3.5.0/1,M10.5.0", thus swapping standard and
daylight saving time. Although this workaround misidentifies which
part of the year uses daylight saving time, it records UT offsets and
time zone abbreviations correctly.
o Some readers mishandle TZif files that specify daylight-saving
time UT offsets that are less than the UT offsets for the
corresponding standard time. These readers do not support
locations like Ireland, which uses the equivalent of the TZ string
"IST-1GMT0,M10.5.0,M3.5.0/1", observing standard time (IST, +01)
in summer and daylight saving time (GMT, +00) in winter. As a
partial workaround, a writer can output data for the equivalent of
the TZ string "GMT0IST,M3.5.0/1,M10.5.0", thus swapping standard
and daylight saving time. Although this workaround misidentifies
which part of the year uses daylight saving time, it records UT
offsets and time zone abbreviations correctly.
* Some readers generate ambiguous timestamps for positive leap seconds
that occur when the UTC offset is not a multiple of 60 seconds. For
example, in a timezone with UTC offset +01:23:45 and with a positive
leap second 78796801 (1972-06-30 23:59:60 UTC), some readers will map
both 78796800 and 78796801 to 01:23:45 local time the next day
instead of mapping the latter to 01:23:46, and they will map 78796815
to 01:23:59 instead of to 01:23:60. This has not yet been a
practical problem, since no civil authority has observed such UTC
offsets since leap seconds were introduced in 1972.
o Some readers generate ambiguous timestamps for positive leap
seconds that occur when the UTC offset is not a multiple of 60
seconds. For example, in a timezone with UTC offset +01:23:45 and
with a positive leap second 78796801 (1972-06-30 23:59:60 UTC),
some readers will map both 78796800 and 78796801 to 01:23:45 local
time the next day instead of mapping the latter to 01:23:46, and
they will map 78796815 to 01:23:59 instead of to 01:23:60. This
has not yet been a practical problem, since no civil authority has
observed such UTC offsets since leap seconds were introduced in
1972.
Some interoperability problems are reader bugs that are listed here
Some interoperability problems are reader bugs that are listed here
mostly as warnings to developers of readers.
* Some readers do not support negative timestamps. Developers of
distributed applications should keep this in mind if they need to
deal with pre-1970 data.
o Some readers do not support negative timestamps. Developers of
distributed applications should keep this in mind if they need to
deal with pre-1970 data.
* Some readers mishandle timestamps before the first transition that
has a nonnegative timestamp. Readers that do not support negative
timestamps are likely to be more prone to this problem.
o Some readers mishandle timestamps before the first transition that
has a nonnegative timestamp. Readers that do not support negative
timestamps are likely to be more prone to this problem.
* Some readers mishandle time zone abbreviations like "-08" that
contain "+", "-", or digits.
o Some readers mishandle time zone abbreviations like "-08" that
contain "+", "-", or digits.
* Some readers mishandle UT offsets that are out of the traditional
range of -12 through +12 hours, and so do not support locations like
Kiritimati that are outside this range.
o Some readers mishandle UT offsets that are out of the traditional
range of -12 through +12 hours, and so do not support locations
like Kiritimati that are outside this range.
* Some readers mishandle UT offsets in the range [-3599, -1] seconds
from UT, because they integer-divide the offset by 3600 to get 0 and
then display the hour part as "+00".
o Some readers mishandle UT offsets in the range [-3599, -1] seconds
from UT, because they integer-divide the offset by 3600 to get 0
and then display the hour part as "+00".
* Some readers mishandle UT offsets that are not a multiple of one
hour, or of 15 minutes, or of 1 minute.
o Some readers mishandle UT offsets that are not a multiple of one
hour, or of 15 minutes, or of 1 minute.
SEE ALSO
time(2), localtime(3), tzset(3), tzselect(8), zdump(8), zic(8).
Olson A, Eggert P, Murchison K. The Time Zone Information Format
(TZif). 2019 Feb. Internet RFC 8536 <https://datatracker.ietf.org/
doc/html/rfc8536> doi:10.17487/RFC8536 <https://doi.org/10.17487/
RFC8536>.
Olson A, Eggert P, Murchison K. The Time Zone Information Format
(TZif). 2019 Feb. Internet RFC 8536 doi:10.17487/RFC8536.
Time Zone Database tzfile(5)

View File

@ -21,14 +21,6 @@
** Information about time zone files.
*/
#ifndef TZDIR
# define TZDIR "/usr/share/zoneinfo" /* Time zone object file directory */
#endif /* !defined TZDIR */
#ifndef TZDEFAULT
# define TZDEFAULT "/etc/localtime"
#endif /* !defined TZDEFAULT */
#ifndef TZDEFRULES
# define TZDEFRULES "posixrules"
#endif /* !defined TZDEFRULES */
@ -86,11 +78,11 @@ struct tzhead {
** time uses 8 rather than 4 chars,
** then a POSIX-TZ-environment-variable-style string for use in handling
** instants after the last transition time stored in the file
** (with nothing between the newlines if there is no POSIX representation for
** such instants).
** (with nothing between the newlines if there is no POSIX.1-2017
** representation for such instants).
**
** If tz_version is '3' or greater, the above is extended as follows.
** First, the POSIX TZ string's hour offset may range from -167
** First, the TZ string's hour offset may range from -167
** through 167 as compared to the POSIX-required 0 through 24.
** Second, its DST start time may be January 1 at 00:00 and its stop
** time December 31 at 24:00 plus the difference between DST and

View File

@ -95,7 +95,7 @@ Output version information and exit.
.SH "ENVIRONMENT VARIABLES"
.TP
\f3AWK\fP
Name of a Posix-compliant
Name of a POSIX-compliant
.B awk
program (default:
.BR awk ).

View File

@ -16,29 +16,29 @@ DESCRIPTION
OPTIONS
-c coord
Instead of asking for continent and then country and then city,
ask for selection from time zones whose largest cities are
closest to the location with geographical coordinates coord.
Instead of asking for continent and then country and then city,
ask for selection from time zones whose largest cities are
closest to the location with geographical coordinates coord.
Use ISO 6709 notation for coord, that is, a latitude immediately
followed by a longitude. The latitude and longitude should be
signed integers followed by an optional decimal point and
fraction: positive numbers represent north and east, negative
south and west. Latitudes with two and longitudes with three
integer digits are treated as degrees; latitudes with four or
followed by a longitude. The latitude and longitude should be
signed integers followed by an optional decimal point and
fraction: positive numbers represent north and east, negative
south and west. Latitudes with two and longitudes with three
integer digits are treated as degrees; latitudes with four or
six and longitudes with five or seven integer digits are treated
as DDMM, DDDMM, DDMMSS, or DDDMMSS representing DD or DDD
degrees, MM minutes, and zero or SS seconds, with any trailing
fractions represent fractional minutes or (if SS is present)
seconds. The decimal point is that of the current locale. For
as DDMM, DDDMM, DDMMSS, or DDDMMSS representing DD or DDD
degrees, MM minutes, and zero or SS seconds, with any trailing
fractions represent fractional minutes or (if SS is present)
seconds. The decimal point is that of the current locale. For
example, in the (default) C locale, -c +40.689-074.045 specifies
40.689 degrees N, 74.045 degrees W, -c +4041.4-07402.7 specifies
40 degrees 41.4 minutes N, 74 degrees 2.7 minutes W, and
40 degrees 41.4 minutes N, 74 degrees 2.7 minutes W, and
-c +404121-0740240 specifies 40 degrees 41 minutes 21 seconds N,
74 degrees 2 minutes 40 seconds W. If coord is not one of the
74 degrees 2 minutes 40 seconds W. If coord is not one of the
documented forms, the resulting behavior is unspecified.
-n limit
When -c is used, display the closest limit locations (default
When -c is used, display the closest limit locations (default
10).
--help Output help information and exit.
@ -47,9 +47,9 @@ OPTIONS
Output version information and exit.
ENVIRONMENT VARIABLES
AWK Name of a Posix-compliant awk program (default: awk).
AWK Name of a POSIX-compliant awk program (default: awk).
TZDIR Name of the directory containing timezone data files (default:
TZDIR Name of the directory containing timezone data files (default:
/usr/share/zoneinfo).
FILES
@ -57,21 +57,21 @@ FILES
Table of ISO 3166 2-letter country codes and country names.
TZDIR/zone1970.tab
Table of country codes, latitude and longitude, timezones, and
Table of country codes, latitude and longitude, timezones, and
descriptive comments.
TZDIR/TZ
Timezone data file for timezone TZ.
EXIT STATUS
The exit status is zero if a timezone was successfully obtained from
The exit status is zero if a timezone was successfully obtained from
the user, nonzero otherwise.
SEE ALSO
newctime(3), tzfile(5), zdump(8), zic(8)
NOTES
Applications should not assume that tzselect's output matches the
Applications should not assume that tzselect's output matches the
user's political preferences.
Time Zone Database tzselect(8)

File diff suppressed because it is too large Load Diff

View File

@ -1 +1 @@
2023c
2024a

View File

@ -152,10 +152,9 @@ tabbed columns line up.)
.nf
.sp
.if \n(.g .ft CR
.if t .in +.5i
.if n .in +2
.in +2
.nr w \w'1896-01-13 'u+\n(.i
.ta \w'1896-01-13 'u +\w'12:01:26 'u +\w'-103126 'u +\w'HWT 'u
.ta \w'1896-01-13\0\0'u +\w'12:01:26\0\0'u +\w'-103126\0\0'u +\w'HWT\0\0'u
TZ="Pacific/Honolulu"
- - -103126 LMT
1896-01-13 12:01:26 -1030 HST

View File

@ -16,77 +16,77 @@ OPTIONS
--help Output short usage message and exit.
-i Output a description of time intervals. For each timezone on
the command line, output an interval-format description of the
-i Output a description of time intervals. For each timezone on
the command line, output an interval-format description of the
timezone. See "INTERVAL FORMAT" below.
-v Output a verbose description of time intervals. For each
-v Output a verbose description of time intervals. For each
timezone on the command line, print the times at the two extreme
time values, the times (if present) at and just beyond the
boundaries of years that localtime(3) and gmtime(3) can
represent, and the times both one second before and exactly at
each detected time discontinuity. Each line is followed by
isdst=D where D is positive, zero, or negative depending on
whether the given time is daylight saving time, standard time,
or an unknown time type, respectively. Each line is also
followed by gmtoff=N if the given local time is known to be N
time values, the times (if present) at and just beyond the
boundaries of years that localtime(3) and gmtime(3) can
represent, and the times both one second before and exactly at
each detected time discontinuity. Each line is followed by
isdst=D where D is positive, zero, or negative depending on
whether the given time is daylight saving time, standard time,
or an unknown time type, respectively. Each line is also
followed by gmtoff=N if the given local time is known to be N
seconds east of Greenwich.
-V Like -v, except omit output concerning extreme time and year
-V Like -v, except omit output concerning extreme time and year
values. This generates output that is easier to compare to that
of implementations with different time representations.
-c [loyear,]hiyear
Cut off interval output at the given year(s). Cutoff times are
computed using the proleptic Gregorian calendar with year 0 and
with Universal Time (UT) ignoring leap seconds. Cutoffs are at
the start of each year, where the lower-bound timestamp is
inclusive and the upper is exclusive; for example, -c 1970,2070
selects transitions on or after 1970-01-01 00:00:00 UTC and
before 2070-01-01 00:00:00 UTC. The default cutoff is
Cut off interval output at the given year(s). Cutoff times are
computed using the proleptic Gregorian calendar with year 0 and
with Universal Time (UT) ignoring leap seconds. Cutoffs are at
the start of each year, where the lower-bound timestamp is
inclusive and the upper is exclusive; for example, -c 1970,2070
selects transitions on or after 1970-01-01 00:00:00 UTC and
before 2070-01-01 00:00:00 UTC. The default cutoff is
-500,2500.
-t [lotime,]hitime
Cut off interval output at the given time(s), given in decimal
seconds since 1970-01-01 00:00:00 Coordinated Universal Time
(UTC). The timezone determines whether the count includes leap
seconds. As with -c, the cutoff's lower bound is inclusive and
Cut off interval output at the given time(s), given in decimal
seconds since 1970-01-01 00:00:00 Coordinated Universal Time
(UTC). The timezone determines whether the count includes leap
seconds. As with -c, the cutoff's lower bound is inclusive and
its upper bound is exclusive.
INTERVAL FORMAT
The interval format is a compact text representation that is intended
to be both human- and machine-readable. It consists of an empty line,
then a line "TZ=string" where string is a double-quoted string giving
The interval format is a compact text representation that is intended
to be both human- and machine-readable. It consists of an empty line,
then a line "TZ=string" where string is a double-quoted string giving
the timezone, a second line "- - interval" describing the time interval
before the first transition if any, and zero or more following lines
"date time interval", one line for each transition time and following
before the first transition if any, and zero or more following lines
"date time interval", one line for each transition time and following
interval. Fields are separated by single tabs.
Dates are in yyyy-mm-dd format and times are in 24-hour hh:mm:ss format
where hh<24. Times are in local time immediately after the transition.
A time interval description consists of a UT offset in signed +-hhmmss
format, a time zone abbreviation, and an isdst flag. An abbreviation
that equals the UT offset is omitted; other abbreviations are double-
quoted strings unless they consist of one or more alphabetic
characters. An isdst flag is omitted for standard time, and otherwise
is a decimal integer that is unsigned and positive (typically 1) for
A time interval description consists of a UT offset in signed +-hhmmss
format, a time zone abbreviation, and an isdst flag. An abbreviation
that equals the UT offset is omitted; other abbreviations are double-
quoted strings unless they consist of one or more alphabetic
characters. An isdst flag is omitted for standard time, and otherwise
is a decimal integer that is unsigned and positive (typically 1) for
daylight saving time and negative for unknown.
In times and in UT offsets with absolute value less than 100 hours, the
seconds are omitted if they are zero, and the minutes are also omitted
seconds are omitted if they are zero, and the minutes are also omitted
if they are also zero. Positive UT offsets are east of Greenwich. The
UT offset -00 denotes a UT placeholder in areas where the actual offset
is unspecified; by convention, this occurs when the UT offset is zero
is unspecified; by convention, this occurs when the UT offset is zero
and the time zone abbreviation begins with "-" or is "zzz".
In double-quoted strings, escape sequences represent unusual
In double-quoted strings, escape sequences represent unusual
characters. The escape sequences are \s for space, and \", \\, \f, \n,
\r, \t, and \v with their usual meaning in the C programming language.
E.g., the double-quoted string ""CET\s\"\\"" represents the character
\r, \t, and \v with their usual meaning in the C programming language.
E.g., the double-quoted string ""CET\s\"\\"" represents the character
sequence "CET "\".
Here is an example of the output, with the leading empty line omitted.
(This example is shown with tab stops set far enough apart so that the
Here is an example of the output, with the leading empty line omitted.
(This example is shown with tab stops set far enough apart so that the
tabbed columns line up.)
TZ="Pacific/Honolulu"
@ -100,14 +100,14 @@ INTERVAL FORMAT
1947-06-08 02:30 -10 HST
Here, local time begins 10 hours, 31 minutes and 26 seconds west of UT,
and is a standard time abbreviated LMT. Immediately after the first
transition, the date is 1896-01-13 and the time is 12:01:26, and the
following time interval is 10.5 hours west of UT, a standard time
abbreviated HST. Immediately after the second transition, the date is
1933-04-30 and the time is 03:00:00 and the following time interval is
9.5 hours west of UT, is abbreviated HDT, and is daylight saving time.
Immediately after the last transition the date is 1947-06-08 and the
time is 02:30:00, and the following time interval is 10 hours west of
and is a standard time abbreviated LMT. Immediately after the first
transition, the date is 1896-01-13 and the time is 12:01:26, and the
following time interval is 10.5 hours west of UT, a standard time
abbreviated HST. Immediately after the second transition, the date is
1933-04-30 and the time is 03:00:00 and the following time interval is
9.5 hours west of UT, is abbreviated HDT, and is daylight saving time.
Immediately after the last transition the date is 1947-06-08 and the
time is 02:30:00, and the following time interval is 10 hours west of
UT, a standard time abbreviated HST.
Here are excerpts from another example:
@ -122,20 +122,20 @@ INTERVAL FORMAT
2014-10-26 01 +03
2016-03-27 03 +04
This time zone is east of UT, so its UT offsets are positive. Also,
many of its time zone abbreviations are omitted since they duplicate
This time zone is east of UT, so its UT offsets are positive. Also,
many of its time zone abbreviations are omitted since they duplicate
the text of the UT offset.
LIMITATIONS
Time discontinuities are found by sampling the results returned by
localtime(3) at twelve-hour intervals. This works in all real-world
Time discontinuities are found by sampling the results returned by
localtime(3) at twelve-hour intervals. This works in all real-world
cases; one can construct artificial time zones for which this fails.
In the -v and -V output, "UT" denotes the value returned by gmtime(3),
which uses UTC for modern timestamps and some other UT flavor for
timestamps that predate the introduction of UTC. No attempt is
currently made to have the output use "UTC" for newer and "UT" for
older timestamps, partly because the exact date of the introduction of
In the -v and -V output, "UT" denotes the value returned by gmtime(3),
which uses UTC for modern timestamps and some other UT flavor for
timestamps that predate the introduction of UTC. No attempt is
currently made to have the output use "UTC" for newer and "UT" for
older timestamps, partly because the exact date of the introduction of
UTC is problematic.
SEE ALSO

View File

@ -602,7 +602,7 @@ main(int argc, char *argv[])
if (!tz) {
char const *e = strerror(errno);
fprintf(stderr, _("%s: unknown timezone '%s': %s\n"),
progname, argv[1], e);
progname, argv[i], e);
return EXIT_FAILURE;
}
if (now) {

83
zic.8
View File

@ -95,7 +95,7 @@ as local time.
.B zic
will act as if the input contained a link line of the form
.sp
.ti +.5i
.ti +2
.ta \w'Link\0\0'u +\w'\fItimezone\fP\0\0'u
Link \fItimezone\fP localtime
.sp
@ -118,9 +118,15 @@ TZ strings like "EET\*-2EEST" that lack transition rules.
.B zic
will act as if the input contained a link line of the form
.sp
.ti +.5i
.ti +2
Link \fItimezone\fP posixrules
.sp
If
.I timezone
is
.q "\*-"
(the default), any already-existing link is removed.
.sp
Unless
.I timezone is
.q "\*-" ,
@ -131,12 +137,6 @@ and it should not be combined with
if
.IR timezone 's
transitions are at standard time or Universal Time (UT) instead of local time.
.sp
If
.I timezone
is
.BR \*- ,
any already-existing link is removed.
.TP
.BR "\*-r " "[\fB@\fP\fIlo\fP][\fB/@\fP\fIhi\fP]"
Limit the applicability of output files
@ -171,7 +171,7 @@ boundaries, particularly if
causes a TZif file to contain explicit entries for
.RI pre- hi
transitions rather than concisely representing them
with an extended POSIX TZ string.
with an extended POSIX.1-2017 TZ string.
Also see the
.B "\*-b slim"
option for another way to shrink output size.
@ -181,10 +181,10 @@ Generate redundant trailing explicit transitions for timestamps
that occur less than
.I hi
seconds since the Epoch, even though the transitions could be
more concisely represented via the extended POSIX TZ string.
more concisely represented via the extended POSIX.1-2017 TZ string.
This option does not affect the represented timestamps.
Although it accommodates nonstandard TZif readers
that ignore the extended POSIX TZ string,
that ignore the extended POSIX.1-2017 TZ string,
it increases the size of the altered output files.
.TP
.BI "\*-t " file
@ -245,10 +245,10 @@ for
.PP
The output file does not contain all the information about the
long-term future of a timezone, because the future cannot be summarized as
an extended POSIX TZ string. For example, as of 2023 this problem
an extended POSIX.1-2017 TZ string. For example, as of 2023 this problem
occurs for Morocco's daylight-saving rules, as these rules are based
on predictions for when Ramadan will be observed, something that
an extended POSIX TZ string cannot represent.
an extended POSIX.1-2017 TZ string cannot represent.
.PP
The output contains data that may not be handled properly by client
code designed for older
@ -330,19 +330,19 @@ abbreviation must be unambiguous in context.
.PP
A rule line has the form
.nf
.ti +.5i
.ti +2
.ta \w'Rule\0\0'u +\w'NAME\0\0'u +\w'FROM\0\0'u +\w'1973\0\0'u +\w'\*-\0\0'u +\w'Apr\0\0'u +\w'lastSun\0\0'u +\w'2:00w\0\0'u +\w'1:00d\0\0'u
.sp
Rule NAME FROM TO \*- IN ON AT SAVE LETTER/S
.sp
For example:
.ti +.5i
.ti +2
.sp
Rule US 1967 1973 \*- Apr lastSun 2:00w 1:00d D
.sp
.fi
The fields that make up a rule line are:
.TP "\w'LETTER/S'u"
.TP
.B NAME
Gives the name of the rule set that contains this line.
The name must start with a character that is neither
@ -360,24 +360,15 @@ an unquoted name should not contain characters from the set
Gives the first year in which the rule applies.
Any signed integer year can be supplied; the proleptic Gregorian calendar
is assumed, with year 0 preceding year 1.
The word
.B minimum
(or an abbreviation) means the indefinite past.
The word
.B maximum
(or an abbreviation) means the indefinite future.
Rules can describe times that are not representable as time values,
with the unrepresentable times ignored; this allows rules to be portable
among hosts with differing time value types.
.TP
.B TO
Gives the final year in which the rule applies.
In addition to
.B minimum
and
The word
.B maximum
(as above),
the word
(or an abbreviation) means the indefinite future, and the word
.B only
(or an abbreviation)
may be used to repeat the value of the
@ -404,7 +395,7 @@ Month names may be abbreviated.
Gives the day on which the rule takes effect.
Recognized forms include:
.nf
.in +.5i
.in +2
.sp
.ta \w'Sun<=25\0\0'u
5 the fifth of the month
@ -413,7 +404,7 @@ lastMon the last Monday in the month
Sun>=8 first Sunday on or after the eighth
Sun<=25 last Sunday on or before the 25th
.fi
.in -.5i
.in
.sp
A weekday name (e.g.,
.BR "Sunday" )
@ -440,7 +431,7 @@ Gives the time of day at which the rule takes effect,
relative to 00:00, the start of a calendar day.
Recognized forms include:
.nf
.in +.5i
.in +2
.sp
.ta \w'00:19:32.13\0\0'u
2 time in hours
@ -454,7 +445,7 @@ Recognized forms include:
\*-2:30 2.5 hours before 00:00
\*- equivalent to 0
.fi
.in -.5i
.in
.sp
Although
.B zic
@ -532,18 +523,18 @@ the variable part is null.
A zone line has the form
.sp
.nf
.ti +.5i
.ti +2
.ta \w'Zone\0\0'u +\w'Asia/Amman\0\0'u +\w'STDOFF\0\0'u +\w'Jordan\0\0'u +\w'FORMAT\0\0'u
Zone NAME STDOFF RULES FORMAT [UNTIL]
.sp
For example:
.sp
.ti +.5i
.ti +2
Zone Asia/Amman 2:00 Jordan EE%sT 2017 Oct 27 01:00
.sp
.fi
The fields that make up a zone line are:
.TP "\w'STDOFF'u"
.TP
.B NAME
The name of the timezone.
This is the name used in creating the time conversion information file for the
@ -663,15 +654,15 @@ For example:
.br
.ne 7
.nf
.in +2m
.in +2
.ta \w'# Rule\0\0'u +\w'NAME\0\0'u +\w'FROM\0\0'u +\w'2006\0\0'u +\w'\*-\0\0'u +\w'Oct\0\0'u +\w'lastSun\0\0'u +\w'2:00\0\0'u +\w'SAVE\0\0'u
.sp
# Rule NAME FROM TO \*- IN ON AT SAVE LETTER/S
Rule US 1967 2006 - Oct lastSun 2:00 0 S
Rule US 1967 1973 - Apr lastSun 2:00 1:00 D
.ta \w'Zone\0\0America/Menominee\0\0'u +\w'STDOFF\0\0'u +\w'RULES\0\0'u +\w'FORMAT\0\0'u
# Zone\0\0NAME STDOFF RULES FORMAT [UNTIL]
Zone\0\0America/Menominee \*-5:00 \*- EST 1973 Apr 29 2:00
.ta \w'# Zone\0\0'u +\w'America/Menominee\0\0'u +\w'STDOFF\0\0'u +\w'RULES\0\0'u +\w'FORMAT\0\0'u
# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Menominee \*-5:00 \*- EST 1973 Apr 29 2:00
\*-6:00 US C%sT
.sp
.in
@ -687,13 +678,13 @@ interprets this more sensibly as a single transition from 02:00 CST (\*-05) to
A link line has the form
.sp
.nf
.ti +.5i
.ti +2
.ta \w'Link\0\0'u +\w'Europe/Istanbul\0\0'u
Link TARGET LINK-NAME
.sp
For example:
.sp
.ti +.5i
.ti +2
Link Europe/Istanbul Asia/Istanbul
.sp
.fi
@ -717,7 +708,7 @@ For example:
.sp
.ne 3
.nf
.in +2m
.in +2
.ta \w'Zone\0\0'u +\w'Greenwich\0\0'u
Link Greenwich G_M_T
Link Etc/GMT Greenwich
@ -737,13 +728,13 @@ The file that describes leap seconds can have leap lines and an
expiration line.
Leap lines have the following form:
.nf
.ti +.5i
.ti +2
.ta \w'Leap\0\0'u +\w'YEAR\0\0'u +\w'MONTH\0\0'u +\w'DAY\0\0'u +\w'HH:MM:SS\0\0'u +\w'CORR\0\0'u
.sp
Leap YEAR MONTH DAY HH:MM:SS CORR R/S
.sp
For example:
.ti +.5i
.ti +2
.sp
Leap 2016 Dec 31 23:59:60 + S
.sp
@ -791,13 +782,13 @@ option is used.
.PP
The expiration line, if present, has the form:
.nf
.ti +.5i
.ti +2
.ta \w'Expires\0\0'u +\w'YEAR\0\0'u +\w'MONTH\0\0'u +\w'DAY\0\0'u
.sp
Expires YEAR MONTH DAY HH:MM:SS
.sp
For example:
.ti +.5i
.ti +2
.sp
Expires 2020 Dec 28 00:00:00
.sp
@ -816,7 +807,7 @@ Here is an extended example of
.B zic
input, intended to illustrate many of its features.
.nf
.in +2m
.in +2
.ta \w'# Rule\0\0'u +\w'NAME\0\0'u +\w'FROM\0\0'u +\w'1973\0\0'u +\w'\*-\0\0'u +\w'Apr\0\0'u +\w'lastSun\0\0'u +\w'2:00\0\0'u +\w'SAVE\0\0'u
.sp
# Rule NAME FROM TO \*- IN ON AT SAVE LETTER/S

573
zic.8.txt
View File

@ -18,74 +18,75 @@ OPTIONS
--help Output short usage message and exit.
-b bloat
Output backward-compatibility data as specified by bloat. If
bloat is fat, generate additional data entries that work around
potential bugs or incompatibilities in older software, such as
Output backward-compatibility data as specified by bloat. If
bloat is fat, generate additional data entries that work around
potential bugs or incompatibilities in older software, such as
software that mishandles the 64-bit generated data. If bloat is
slim, keep the output files small; this can help check for the
bugs and incompatibilities. The default is slim, as software
that mishandles 64-bit data typically mishandles timestamps
after the year 2038 anyway. Also see the -r option for another
slim, keep the output files small; this can help check for the
bugs and incompatibilities. The default is slim, as software
that mishandles 64-bit data typically mishandles timestamps
after the year 2038 anyway. Also see the -r option for another
way to alter output size.
-d directory
Create time conversion information files in the named directory
Create time conversion information files in the named directory
rather than in the standard directory named below.
-l timezone
Use timezone as local time. zic will act as if the input
Use timezone as local time. zic will act as if the input
contained a link line of the form
Link timezone localtime
Link timezone localtime
If timezone is -, any already-existing link is removed.
-L leapsecondfilename
Read leap second information from the file with the given name.
If this option is not used, no leap second information appears
Read leap second information from the file with the given name.
If this option is not used, no leap second information appears
in output files.
-p timezone
Use timezone's rules when handling nonstandard TZ strings like
"EET-2EEST" that lack transition rules. zic will act as if the
Use timezone's rules when handling nonstandard TZ strings like
"EET-2EEST" that lack transition rules. zic will act as if the
input contained a link line of the form
Link timezone posixrules
Link timezone posixrules
Unless timezone is "-", this option is obsolete and poorly
supported. Among other things it should not be used for
timestamps after the year 2037, and it should not be combined
with -b slim if timezone's transitions are at standard time or
If timezone is "-" (the default), any already-existing link is
removed.
Unless timezone is "-", this option is obsolete and poorly
supported. Among other things it should not be used for
timestamps after the year 2037, and it should not be combined
with -b slim if timezone's transitions are at standard time or
Universal Time (UT) instead of local time.
If timezone is -, any already-existing link is removed.
-r [@lo][/@hi]
Limit the applicability of output files to timestamps in the
Limit the applicability of output files to timestamps in the
range from lo (inclusive) to hi (exclusive), where lo and hi are
possibly signed decimal counts of seconds since the Epoch
(1970-01-01 00:00:00 UTC). Omitted counts default to extreme
possibly signed decimal counts of seconds since the Epoch
(1970-01-01 00:00:00 UTC). Omitted counts default to extreme
values. The output files use UT offset 0 and abbreviation "-00"
in place of the omitted timestamp data. For example, "zic -r
@0" omits data intended for negative timestamps (i.e., before
the Epoch), and "zic -r @0/@2147483648" outputs data intended
only for nonnegative timestamps that fit into 31-bit signed
integers. On platforms with GNU date, "zic -r @$(date +%s)"
omits data intended for past timestamps. Although this option
typically reduces the output file's size, the size can increase
due to the need to represent the timestamp range boundaries,
particularly if hi causes a TZif file to contain explicit
entries for pre-hi transitions rather than concisely
representing them with an extended POSIX TZ string. Also see
the -b slim option for another way to shrink output size.
in place of the omitted timestamp data. For example, "zic -r
@0" omits data intended for negative timestamps (i.e., before
the Epoch), and "zic -r @0/@2147483648" outputs data intended
only for nonnegative timestamps that fit into 31-bit signed
integers. On platforms with GNU date, "zic -r @$(date +%s)"
omits data intended for past timestamps. Although this option
typically reduces the output file's size, the size can increase
due to the need to represent the timestamp range boundaries,
particularly if hi causes a TZif file to contain explicit
entries for pre-hi transitions rather than concisely
representing them with an extended POSIX.1-2017 TZ string. Also
see the -b slim option for another way to shrink output size.
-R @hi Generate redundant trailing explicit transitions for timestamps
-R @hi Generate redundant trailing explicit transitions for timestamps
that occur less than hi seconds since the Epoch, even though the
transitions could be more concisely represented via the extended
POSIX TZ string. This option does not affect the represented
timestamps. Although it accommodates nonstandard TZif readers
that ignore the extended POSIX TZ string, it increases the size
of the altered output files.
POSIX.1-2017 TZ string. This option does not affect the
represented timestamps. Although it accommodates nonstandard
TZif readers that ignore the extended POSIX.1-2017 TZ string, it
increases the size of the altered output files.
-t file
When creating local time information, put the configuration link
@ -96,356 +97,352 @@ OPTIONS
The input specifies a link to a link, something not supported by
some older parsers, including zic itself through release 2022e.
A year that appears in a data file is outside the range of
A year that appears in a data file is outside the range of
representable years.
A time of 24:00 or more appears in the input. Pre-1998 versions
of zic prohibit 24:00, and pre-2007 versions prohibit times
of zic prohibit 24:00, and pre-2007 versions prohibit times
greater than 24:00.
A rule goes past the start or end of the month. Pre-2004
A rule goes past the start or end of the month. Pre-2004
versions of zic prohibit this.
A time zone abbreviation uses a %z format. Pre-2015 versions of
zic do not support this.
A timestamp contains fractional seconds. Pre-2018 versions of
A timestamp contains fractional seconds. Pre-2018 versions of
zic do not support this.
The input contains abbreviations that are mishandled by pre-2018
versions of zic due to a longstanding coding bug. These
abbreviations include "L" for "Link", "mi" for "min", "Sa" for
versions of zic due to a longstanding coding bug. These
abbreviations include "L" for "Link", "mi" for "min", "Sa" for
"Sat", and "Su" for "Sun".
The output file does not contain all the information about the
long-term future of a timezone, because the future cannot be
summarized as an extended POSIX TZ string. For example, as of
2023 this problem occurs for Morocco's daylight-saving rules, as
these rules are based on predictions for when Ramadan will be
observed, something that an extended POSIX TZ string cannot
represent.
The output file does not contain all the information about the
long-term future of a timezone, because the future cannot be
summarized as an extended POSIX.1-2017 TZ string. For example,
as of 2023 this problem occurs for Morocco's daylight-saving
rules, as these rules are based on predictions for when Ramadan
will be observed, something that an extended POSIX.1-2017 TZ
string cannot represent.
The output contains data that may not be handled properly by
client code designed for older zic output formats. These
The output contains data that may not be handled properly by
client code designed for older zic output formats. These
compatibility issues affect only timestamps before 1970 or after
the start of 2038.
The output contains a truncated leap second table, which can
cause some older TZif readers to misbehave. This can occur if
the -L option is used, and either an Expires line is present or
The output contains a truncated leap second table, which can
cause some older TZif readers to misbehave. This can occur if
the -L option is used, and either an Expires line is present or
the -r option is also used.
The output file contains more than 1200 transitions, which may
be mishandled by some clients. The current reference client
supports at most 2000 transitions; pre-2014 versions of the
The output file contains more than 1200 transitions, which may
be mishandled by some clients. The current reference client
supports at most 2000 transitions; pre-2014 versions of the
reference client support at most 1200 transitions.
A time zone abbreviation has fewer than 3 or more than 6
characters. POSIX requires at least 3, and requires
A time zone abbreviation has fewer than 3 or more than 6
characters. POSIX requires at least 3, and requires
implementations to support at least 6.
An output file name contains a byte that is not an ASCII letter,
"-", "/", or "_"; or it contains a file name component that
"-", "/", or "_"; or it contains a file name component that
contains more than 14 bytes or that starts with "-".
FILES
Input files use the format described in this section; output files use
Input files use the format described in this section; output files use
tzfile(5) format.
Input files should be text files, that is, they should be a series of
zero or more lines, each ending in a newline byte and containing at
most 2048 bytes counting the newline, and without any NUL bytes. The
input text's encoding is typically UTF-8 or ASCII; it should have a
unibyte representation for the POSIX Portable Character Set (PPCS)
Input files should be text files, that is, they should be a series of
zero or more lines, each ending in a newline byte and containing at
most 2048 bytes counting the newline, and without any NUL bytes. The
input text's encoding is typically UTF-8 or ASCII; it should have a
unibyte representation for the POSIX Portable Character Set (PPCS)
<https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap06
.html> and the encoding's non-unibyte characters should consist
entirely of non-PPCS bytes. Non-PPCS characters typically occur only
.html> and the encoding's non-unibyte characters should consist
entirely of non-PPCS bytes. Non-PPCS characters typically occur only
in comments: although output file names and time zone abbreviations can
contain nearly any character, other software will work better if these
contain nearly any character, other software will work better if these
are limited to the restricted syntax described under the -v option.
Input lines are made up of fields. Fields are separated from one
another by one or more white space characters. The white space
characters are space, form feed, carriage return, newline, tab, and
vertical tab. Leading and trailing white space on input lines is
ignored. An unquoted sharp character (#) in the input introduces a
comment which extends to the end of the line the sharp character
appears on. White space characters and sharp characters may be
Input lines are made up of fields. Fields are separated from one
another by one or more white space characters. The white space
characters are space, form feed, carriage return, newline, tab, and
vertical tab. Leading and trailing white space on input lines is
ignored. An unquoted sharp character (#) in the input introduces a
comment which extends to the end of the line the sharp character
appears on. White space characters and sharp characters may be
enclosed in double quotes (") if they're to be used as part of a field.
Any line that is blank (after comment stripping) is ignored. Nonblank
Any line that is blank (after comment stripping) is ignored. Nonblank
lines are expected to be of one of three types: rule lines, zone lines,
and link lines.
Names must be in English and are case insensitive. They appear in
Names must be in English and are case insensitive. They appear in
several contexts, and include month and weekday names and keywords such
as maximum, only, Rolling, and Zone. A name can be abbreviated by
omitting all but an initial prefix; any abbreviation must be
as maximum, only, Rolling, and Zone. A name can be abbreviated by
omitting all but an initial prefix; any abbreviation must be
unambiguous in context.
A rule line has the form
Rule NAME FROM TO - IN ON AT SAVE LETTER/S
Rule NAME FROM TO - IN ON AT SAVE LETTER/S
For example:
Rule US 1967 1973 - Apr lastSun 2:00w 1:00d D
Rule US 1967 1973 - Apr lastSun 2:00w 1:00d D
The fields that make up a rule line are:
NAME Gives the name of the rule set that contains this line. The
name must start with a character that is neither an ASCII digit
nor "-" nor "+". To allow for future extensions, an unquoted
name should not contain characters from the set
"!$%&'()*,/:;<=>?@[\]^`{|}~".
NAME Gives the name of the rule set that contains this line. The
name must start with a character that is neither an ASCII digit
nor "-" nor "+". To allow for future extensions, an unquoted
name should not contain characters from the set
"!$%&'()*,/:;<=>?@[\]^`{|}~".
FROM Gives the first year in which the rule applies. Any signed
integer year can be supplied; the proleptic Gregorian calendar
is assumed, with year 0 preceding year 1. The word minimum (or
an abbreviation) means the indefinite past. The word maximum
(or an abbreviation) means the indefinite future. Rules can
describe times that are not representable as time values, with
the unrepresentable times ignored; this allows rules to be
portable among hosts with differing time value types.
FROM Gives the first year in which the rule applies. Any signed
integer year can be supplied; the proleptic Gregorian calendar
is assumed, with year 0 preceding year 1. Rules can describe
times that are not representable as time values, with the
unrepresentable times ignored; this allows rules to be portable
among hosts with differing time value types.
TO Gives the final year in which the rule applies. In addition to
minimum and maximum (as above), the word only (or an
abbreviation) may be used to repeat the value of the FROM
field.
TO Gives the final year in which the rule applies. The word
maximum (or an abbreviation) means the indefinite future, and
the word only (or an abbreviation) may be used to repeat the
value of the FROM field.
- Is a reserved field and should always contain "-" for
compatibility with older versions of zic. It was previously
known as the TYPE field, which could contain values to allow a
separate script to further restrict in which "types" of years
the rule would apply.
- Is a reserved field and should always contain "-" for
compatibility with older versions of zic. It was previously
known as the TYPE field, which could contain values to allow a
separate script to further restrict in which "types" of years
the rule would apply.
IN Names the month in which the rule takes effect. Month names
may be abbreviated.
IN Names the month in which the rule takes effect. Month names may
be abbreviated.
ON Gives the day on which the rule takes effect. Recognized forms
include:
ON Gives the day on which the rule takes effect. Recognized forms
include:
5 the fifth of the month
lastSun the last Sunday in the month
lastMon the last Monday in the month
Sun>=8 first Sunday on or after the eighth
Sun<=25 last Sunday on or before the 25th
5 the fifth of the month
lastSun the last Sunday in the month
lastMon the last Monday in the month
Sun>=8 first Sunday on or after the eighth
Sun<=25 last Sunday on or before the 25th
A weekday name (e.g., Sunday) or a weekday name preceded by
"last" (e.g., lastSunday) may be abbreviated or spelled out in
full. There must be no white space characters within the ON
field. The "<=" and ">=" constructs can result in a day in the
neighboring month; for example, the IN-ON combination "Oct
Sun>=31" stands for the first Sunday on or after October 31,
even if that Sunday occurs in November.
A weekday name (e.g., Sunday) or a weekday name preceded by
"last" (e.g., lastSunday) may be abbreviated or spelled out in
full. There must be no white space characters within the ON
field. The "<=" and ">=" constructs can result in a day in the
neighboring month; for example, the IN-ON combination "Oct
Sun>=31" stands for the first Sunday on or after October 31,
even if that Sunday occurs in November.
AT Gives the time of day at which the rule takes effect, relative
to 00:00, the start of a calendar day. Recognized forms
include:
AT Gives the time of day at which the rule takes effect, relative
to 00:00, the start of a calendar day. Recognized forms
include:
2 time in hours
2:00 time in hours and minutes
01:28:14 time in hours, minutes, and seconds
00:19:32.13 time with fractional seconds
12:00 midday, 12 hours after 00:00
15:00 3 PM, 15 hours after 00:00
24:00 end of day, 24 hours after 00:00
260:00 260 hours after 00:00
-2:30 2.5 hours before 00:00
- equivalent to 0
2 time in hours
2:00 time in hours and minutes
01:28:14 time in hours, minutes, and seconds
00:19:32.13 time with fractional seconds
12:00 midday, 12 hours after 00:00
15:00 3 PM, 15 hours after 00:00
24:00 end of day, 24 hours after 00:00
260:00 260 hours after 00:00
-2:30 2.5 hours before 00:00
- equivalent to 0
Although zic rounds times to the nearest integer second
(breaking ties to the even integer), the fractions may be
useful to other applications requiring greater precision. The
source format does not specify any maximum precision. Any of
these forms may be followed by the letter w if the given time
is local or "wall clock" time, s if the given time is standard
time without any adjustment for daylight saving, or u (or g or
z) if the given time is universal time; in the absence of an
indicator, local (wall clock) time is assumed. These forms
ignore leap seconds; for example, if a leap second occurs at
00:59:60 local time, "1:00" stands for 3601 seconds after local
midnight instead of the usual 3600 seconds. The intent is that
a rule line describes the instants when a clock/calendar set to
the type of time specified in the AT field would show the
specified date and time of day.
Although zic rounds times to the nearest integer second
(breaking ties to the even integer), the fractions may be useful
to other applications requiring greater precision. The source
format does not specify any maximum precision. Any of these
forms may be followed by the letter w if the given time is local
or "wall clock" time, s if the given time is standard time
without any adjustment for daylight saving, or u (or g or z) if
the given time is universal time; in the absence of an
indicator, local (wall clock) time is assumed. These forms
ignore leap seconds; for example, if a leap second occurs at
00:59:60 local time, "1:00" stands for 3601 seconds after local
midnight instead of the usual 3600 seconds. The intent is that
a rule line describes the instants when a clock/calendar set to
the type of time specified in the AT field would show the
specified date and time of day.
SAVE Gives the amount of time to be added to local standard time
when the rule is in effect, and whether the resulting time is
standard or daylight saving. This field has the same format as
the AT field except with a different set of suffix letters: s
for standard time and d for daylight saving time. The suffix
letter is typically omitted, and defaults to s if the offset is
zero and to d otherwise. Negative offsets are allowed; in
Ireland, for example, daylight saving time is observed in
winter and has a negative offset relative to Irish Standard
Time. The offset is merely added to standard time; for
example, zic does not distinguish a 10:30 standard time plus an
0:30 SAVE from a 10:00 standard time plus a 1:00 SAVE.
SAVE Gives the amount of time to be added to local standard time when
the rule is in effect, and whether the resulting time is
standard or daylight saving. This field has the same format as
the AT field except with a different set of suffix letters: s
for standard time and d for daylight saving time. The suffix
letter is typically omitted, and defaults to s if the offset is
zero and to d otherwise. Negative offsets are allowed; in
Ireland, for example, daylight saving time is observed in winter
and has a negative offset relative to Irish Standard Time. The
offset is merely added to standard time; for example, zic does
not distinguish a 10:30 standard time plus an 0:30 SAVE from a
10:00 standard time plus a 1:00 SAVE.
LETTER/S
Gives the "variable part" (for example, the "S" or "D" in "EST"
or "EDT") of time zone abbreviations to be used when this rule
is in effect. If this field is "-", the variable part is null.
Gives the "variable part" (for example, the "S" or "D" in "EST"
or "EDT") of time zone abbreviations to be used when this rule
is in effect. If this field is "-", the variable part is null.
A zone line has the form
Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone NAME STDOFF RULES FORMAT [UNTIL]
For example:
Zone Asia/Amman 2:00 Jordan EE%sT 2017 Oct 27 01:00
Zone Asia/Amman 2:00 Jordan EE%sT 2017 Oct 27 01:00
The fields that make up a zone line are:
NAME The name of the timezone. This is the name used in creating the
time conversion information file for the timezone. It should not
contain a file name component "." or ".."; a file name component
is a maximal substring that does not contain "/".
NAME The name of the timezone. This is the name used in creating the
time conversion information file for the timezone. It should
not contain a file name component "." or ".."; a file name
component is a maximal substring that does not contain "/".
STDOFF
The amount of time to add to UT to get standard time, without any
adjustment for daylight saving. This field has the same format
as the AT and SAVE fields of rule lines, except without suffix
letters; begin the field with a minus sign if time must be
subtracted from UT.
STDOFF The amount of time to add to UT to get standard time, without
any adjustment for daylight saving. This field has the same
format as the AT and SAVE fields of rule lines, except without
suffix letters; begin the field with a minus sign if time must
be subtracted from UT.
RULES The name of the rules that apply in the timezone or,
alternatively, a field in the same format as a rule-line SAVE
column, giving the amount of time to be added to local standard
time and whether the resulting time is standard or daylight
saving. If this field is - then standard time always applies.
When an amount of time is given, only the sum of standard time
and this amount matters.
RULES The name of the rules that apply in the timezone or,
alternatively, a field in the same format as a rule-line SAVE
column, giving the amount of time to be added to local standard
time and whether the resulting time is standard or daylight
saving. If this field is - then standard time always applies.
When an amount of time is given, only the sum of standard time
and this amount matters.
FORMAT
The format for time zone abbreviations. The pair of characters
%s is used to show where the "variable part" of the time zone
abbreviation goes. Alternatively, a format can use the pair of
characters %z to stand for the UT offset in the form +-hh,
+-hhmm, or +-hhmmss, using the shortest form that does not lose
information, where hh, mm, and ss are the hours, minutes, and
seconds east (+) or west (-) of UT. Alternatively, a slash (/)
separates standard and daylight abbreviations. To conform to
POSIX, a time zone abbreviation should contain only alphanumeric
ASCII characters, "+" and "-". By convention, the time zone
abbreviation "-00" is a placeholder that means local time is
unspecified.
FORMAT The format for time zone abbreviations. The pair of characters
%s is used to show where the "variable part" of the time zone
abbreviation goes. Alternatively, a format can use the pair of
characters %z to stand for the UT offset in the form +-hh,
+-hhmm, or +-hhmmss, using the shortest form that does not lose
information, where hh, mm, and ss are the hours, minutes, and
seconds east (+) or west (-) of UT. Alternatively, a slash (/)
separates standard and daylight abbreviations. To conform to
POSIX, a time zone abbreviation should contain only alphanumeric
ASCII characters, "+" and "-". By convention, the time zone
abbreviation "-00" is a placeholder that means local time is
unspecified.
UNTIL The time at which the UT offset or the rule(s) change for a
location. It takes the form of one to four fields YEAR [MONTH
[DAY [TIME]]]. If this is specified, the time zone information
is generated from the given UT offset and rule change until the
time specified, which is interpreted using the rules in effect
just before the transition. The month, day, and time of day have
the same format as the IN, ON, and AT fields of a rule; trailing
fields can be omitted, and default to the earliest possible value
for the missing fields.
UNTIL The time at which the UT offset or the rule(s) change for a
location. It takes the form of one to four fields YEAR [MONTH
[DAY [TIME]]]. If this is specified, the time zone information
is generated from the given UT offset and rule change until the
time specified, which is interpreted using the rules in effect
just before the transition. The month, day, and time of day
have the same format as the IN, ON, and AT fields of a rule;
trailing fields can be omitted, and default to the earliest
possible value for the missing fields.
The next line must be a "continuation" line; this has the same
form as a zone line except that the string "Zone" and the name
are omitted, as the continuation line will place information
starting at the time specified as the "until" information in the
previous line in the file used by the previous line.
Continuation lines may contain "until" information, just as zone
lines do, indicating that the next line is a further
continuation.
The next line must be a "continuation" line; this has the same
form as a zone line except that the string "Zone" and the name
are omitted, as the continuation line will place information
starting at the time specified as the "until" information in the
previous line in the file used by the previous line.
Continuation lines may contain "until" information, just as zone
lines do, indicating that the next line is a further
continuation.
If a zone changes at the same instant that a rule would otherwise take
effect in the earlier zone or continuation line, the rule is ignored.
A zone or continuation line L with a named rule set starts with
standard time by default: that is, any of L's timestamps preceding L's
earliest rule use the rule in effect after L's first transition into
standard time. In a single zone it is an error if two rules take
effect at the same instant, or if two zone changes take effect at the
If a zone changes at the same instant that a rule would otherwise take
effect in the earlier zone or continuation line, the rule is ignored.
A zone or continuation line L with a named rule set starts with
standard time by default: that is, any of L's timestamps preceding L's
earliest rule use the rule in effect after L's first transition into
standard time. In a single zone it is an error if two rules take
effect at the same instant, or if two zone changes take effect at the
same instant.
If a continuation line subtracts N seconds from the UT offset after a
transition that would be interpreted to be later if using the
continuation line's UT offset and rules, the "until" time of the
previous zone or continuation line is interpreted according to the
continuation line's UT offset and rules, and any rule that would
otherwise take effect in the next N seconds is instead assumed to take
If a continuation line subtracts N seconds from the UT offset after a
transition that would be interpreted to be later if using the
continuation line's UT offset and rules, the "until" time of the
previous zone or continuation line is interpreted according to the
continuation line's UT offset and rules, and any rule that would
otherwise take effect in the next N seconds is instead assumed to take
effect simultaneously. For example:
# Rule NAME FROM TO - IN ON AT SAVE LETTER/S
Rule US 1967 2006 - Oct lastSun 2:00 0 S
Rule US 1967 1973 - Apr lastSun 2:00 1:00 D
# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Menominee -5:00 - EST 1973 Apr 29 2:00
-6:00 US C%sT
# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Menominee -5:00 - EST 1973 Apr 29 2:00
-6:00 US C%sT
Here, an incorrect reading would be there were two clock changes on
1973-04-29, the first from 02:00 EST (-05) to 01:00 CST (-06), and the
Here, an incorrect reading would be there were two clock changes on
1973-04-29, the first from 02:00 EST (-05) to 01:00 CST (-06), and the
second an hour later from 02:00 CST (-06) to 03:00 CDT (-05). However,
zic interprets this more sensibly as a single transition from 02:00 CST
(-05) to 02:00 CDT (-05).
A link line has the form
Link TARGET LINK-NAME
Link TARGET LINK-NAME
For example:
Link Europe/Istanbul Asia/Istanbul
Link Europe/Istanbul Asia/Istanbul
The TARGET field should appear as the NAME field in some zone line or
as the LINK-NAME field in some link line. The LINK-NAME field is used
as an alternative name for that zone; it has the same syntax as a zone
line's NAME field. Links can chain together, although the behavior is
unspecified if a chain of one or more links does not terminate in a
Zone name. A link line can appear before the line that defines the
The TARGET field should appear as the NAME field in some zone line or
as the LINK-NAME field in some link line. The LINK-NAME field is used
as an alternative name for that zone; it has the same syntax as a zone
line's NAME field. Links can chain together, although the behavior is
unspecified if a chain of one or more links does not terminate in a
Zone name. A link line can appear before the line that defines the
link target. For example:
Link Greenwich G_M_T
Link Etc/GMT Greenwich
Zone Etc/GMT 0 - GMT
The two links are chained together, and G_M_T, Greenwich, and Etc/GMT
The two links are chained together, and G_M_T, Greenwich, and Etc/GMT
all name the same zone.
Except for continuation lines, lines may appear in any order in the
input. However, the behavior is unspecified if multiple zone or link
Except for continuation lines, lines may appear in any order in the
input. However, the behavior is unspecified if multiple zone or link
lines define the same name.
The file that describes leap seconds can have leap lines and an
The file that describes leap seconds can have leap lines and an
expiration line. Leap lines have the following form:
Leap YEAR MONTH DAY HH:MM:SS CORR R/S
Leap YEAR MONTH DAY HH:MM:SS CORR R/S
For example:
Leap 2016 Dec 31 23:59:60 + S
Leap 2016 Dec 31 23:59:60 + S
The YEAR, MONTH, DAY, and HH:MM:SS fields tell when the leap second
The YEAR, MONTH, DAY, and HH:MM:SS fields tell when the leap second
happened. The CORR field should be "+" if a second was added or "-" if
a second was skipped. The R/S field should be (an abbreviation of)
"Stationary" if the leap second time given by the other fields should
be interpreted as UTC or (an abbreviation of) "Rolling" if the leap
second time given by the other fields should be interpreted as local
a second was skipped. The R/S field should be (an abbreviation of)
"Stationary" if the leap second time given by the other fields should
be interpreted as UTC or (an abbreviation of) "Rolling" if the leap
second time given by the other fields should be interpreted as local
(wall clock) time.
Rolling leap seconds were implemented back when it was not clear
whether common practice was rolling or stationary, with concerns that
one would see Times Square ball drops where there'd be a "3... 2...
1... leap... Happy New Year" countdown, placing the leap second at
midnight New York time rather than midnight UTC. However, this
countdown style does not seem to have caught on, which means rolling
leap seconds are not used in practice; also, they are not supported if
Rolling leap seconds were implemented back when it was not clear
whether common practice was rolling or stationary, with concerns that
one would see Times Square ball drops where there'd be a "3... 2...
1... leap... Happy New Year" countdown, placing the leap second at
midnight New York time rather than midnight UTC. However, this
countdown style does not seem to have caught on, which means rolling
leap seconds are not used in practice; also, they are not supported if
the -r option is used.
The expiration line, if present, has the form:
Expires YEAR MONTH DAY HH:MM:SS
Expires YEAR MONTH DAY HH:MM:SS
For example:
Expires 2020 Dec 28 00:00:00
Expires 2020 Dec 28 00:00:00
The YEAR, MONTH, DAY, and HH:MM:SS fields give the expiration timestamp
in UTC for the leap second table.
EXTENDED EXAMPLE
Here is an extended example of zic input, intended to illustrate many
Here is an extended example of zic input, intended to illustrate many
of its features.
# Rule NAME FROM TO - IN ON AT SAVE LETTER/S
@ -466,29 +463,29 @@ EXTENDED EXAMPLE
Link Europe/Zurich Europe/Vaduz
In this example, the EU rules are for the European Union and for its
predecessor organization, the European Communities. The timezone is
named Europe/Zurich and it has the alias Europe/Vaduz. This example
says that Zurich was 34 minutes and 8 seconds east of UT until
1853-07-16 at 00:00, when the legal offset was changed to 7 degrees 26
minutes 22.50 seconds, which works out to 0:29:45.50; zic treats this
by rounding it to 0:29:46. After 1894-06-01 at 00:00 the UT offset
became one hour and Swiss daylight saving rules (defined with lines
beginning with "Rule Swiss") apply. From 1981 to the present, EU
daylight saving rules have applied, and the UTC offset has remained at
In this example, the EU rules are for the European Union and for its
predecessor organization, the European Communities. The timezone is
named Europe/Zurich and it has the alias Europe/Vaduz. This example
says that Zurich was 34 minutes and 8 seconds east of UT until
1853-07-16 at 00:00, when the legal offset was changed to 7 degrees 26
minutes 22.50 seconds, which works out to 0:29:45.50; zic treats this
by rounding it to 0:29:46. After 1894-06-01 at 00:00 the UT offset
became one hour and Swiss daylight saving rules (defined with lines
beginning with "Rule Swiss") apply. From 1981 to the present, EU
daylight saving rules have applied, and the UTC offset has remained at
one hour.
In 1941 and 1942, daylight saving time applied from the first Monday in
May at 01:00 to the first Monday in October at 02:00. The pre-1981 EU
daylight-saving rules have no effect here, but are included for
May at 01:00 to the first Monday in October at 02:00. The pre-1981 EU
daylight-saving rules have no effect here, but are included for
completeness. Since 1981, daylight saving has begun on the last Sunday
in March at 01:00 UTC. Until 1995 it ended the last Sunday in
September at 01:00 UTC, but this changed to the last Sunday in October
in March at 01:00 UTC. Until 1995 it ended the last Sunday in
September at 01:00 UTC, but this changed to the last Sunday in October
starting in 1996.
For purposes of display, "LMT" and "BMT" were initially used,
respectively. Since Swiss rules and later EU rules were applied, the
time zone abbreviation has been CET for standard time and CEST for
For purposes of display, "LMT" and "BMT" were initially used,
respectively. Since Swiss rules and later EU rules were applied, the
time zone abbreviation has been CET for standard time and CEST for
daylight saving time.
FILES
@ -499,15 +496,15 @@ FILES
Default timezone information directory.
NOTES
For areas with more than two types of local time, you may need to use
local standard time in the AT field of the earliest transition time's
rule to ensure that the earliest transition time recorded in the
For areas with more than two types of local time, you may need to use
local standard time in the AT field of the earliest transition time's
rule to ensure that the earliest transition time recorded in the
compiled file is correct.
If, for a particular timezone, a clock advance caused by the start of
daylight saving coincides with and is equal to a clock retreat caused
by a change in UT offset, zic produces a single transition to daylight
saving at the new UT offset without any change in local (wall clock)
If, for a particular timezone, a clock advance caused by the start of
daylight saving coincides with and is equal to a clock retreat caused
by a change in UT offset, zic produces a single transition to daylight
saving at the new UT offset without any change in local (wall clock)
time. To get separate transitions use multiple zone continuation lines
specifying transition instants using universal time.

239
zic.c
View File

@ -14,6 +14,7 @@
#include "version.h"
#include "private.h"
#include "tzdir.h"
#include "tzfile.h"
#include <fcntl.h>
@ -34,6 +35,9 @@ static zic_t const
# define ZIC_MAX_ABBR_LEN_WO_WARN 6
#endif /* !defined ZIC_MAX_ABBR_LEN_WO_WARN */
/* Minimum and maximum years, assuming signed 32-bit time_t. */
enum { YEAR_32BIT_MIN = 1901, YEAR_32BIT_MAX = 2038 };
/* An upper bound on how much a format might grow due to concatenation. */
enum { FORMAT_LEN_GROWTH_BOUND = 5 };
@ -92,7 +96,6 @@ struct rule {
zic_t r_loyear; /* for example, 1986 */
zic_t r_hiyear; /* for example, 1986 */
bool r_lowasnum;
bool r_hiwasnum;
int r_month; /* 0..11 */
@ -164,13 +167,8 @@ symlink(char const *target, char const *linkname)
}
#endif
#ifndef AT_SYMLINK_FOLLOW
# if HAVE_LINK
# define linkat(targetdir, target, linknamedir, linkname, flag) \
(itssymlink(target) ? (errno = ENOTSUP, -1) : link(target, linkname))
# else
# define linkat(targetdir, target, linknamedir, linkname, flag) \
(errno = ENOTSUP, -1)
# endif
#endif
static void addtt(zic_t starttime, int type);
@ -190,7 +188,7 @@ static void inrule(char ** fields, int nfields);
static bool inzcont(char ** fields, int nfields);
static bool inzone(char ** fields, int nfields);
static bool inzsub(char **, int, bool);
static bool itssymlink(char const *);
static int itssymlink(char const *, int *);
static bool is_alpha(char a);
static char lowerit(char);
static void mkdirs(char const *, bool);
@ -332,7 +330,7 @@ enum {
*/
enum {
YR_MINIMUM,
YR_MINIMUM, /* "minimum" is for backward compatibility only */
YR_MAXIMUM,
YR_ONLY
};
@ -416,12 +414,10 @@ static struct lookup const lasts[] = {
static struct lookup const begin_years[] = {
{ "minimum", YR_MINIMUM },
{ "maximum", YR_MAXIMUM },
{ NULL, 0 }
};
static struct lookup const end_years[] = {
{ "minimum", YR_MINIMUM },
{ "maximum", YR_MAXIMUM },
{ "only", YR_ONLY },
{ NULL, 0 }
@ -901,7 +897,8 @@ static zic_t const max_time = MAXVAL(zic_t, TIME_T_BITS_IN_FILE);
static zic_t lo_time = MINVAL(zic_t, TIME_T_BITS_IN_FILE);
static zic_t hi_time = MAXVAL(zic_t, TIME_T_BITS_IN_FILE);
/* The time specified by the -R option, defaulting to MIN_TIME. */
/* The time specified by the -R option, defaulting to MIN_TIME;
or lo_time, whichever is greater. */
static zic_t redundant_time = MINVAL(zic_t, TIME_T_BITS_IN_FILE);
/* The time specified by an Expires line, or negative if no such line. */
@ -1025,7 +1022,8 @@ main(int argc, char **argv)
directory = optarg;
else {
fprintf(stderr,
_("%s: More than one -d option specified\n"),
_("%s: More than one -d option"
" specified\n"),
progname);
return EXIT_FAILURE;
}
@ -1035,7 +1033,8 @@ _("%s: More than one -d option specified\n"),
lcltime = optarg;
else {
fprintf(stderr,
_("%s: More than one -l option specified\n"),
_("%s: More than one -l option"
" specified\n"),
progname);
return EXIT_FAILURE;
}
@ -1045,7 +1044,8 @@ _("%s: More than one -l option specified\n"),
psxrules = optarg;
else {
fprintf(stderr,
_("%s: More than one -p option specified\n"),
_("%s: More than one -p option"
" specified\n"),
progname);
return EXIT_FAILURE;
}
@ -1068,7 +1068,8 @@ _("%s: More than one -p option specified\n"),
leapsec = optarg;
else {
fprintf(stderr,
_("%s: More than one -L option specified\n"),
_("%s: More than one -L option"
" specified\n"),
progname);
return EXIT_FAILURE;
}
@ -1079,13 +1080,14 @@ _("%s: More than one -L option specified\n"),
case 'r':
if (timerange_given) {
fprintf(stderr,
_("%s: More than one -r option specified\n"),
_("%s: More than one -r option"
" specified\n"),
progname);
return EXIT_FAILURE;
}
if (! timerange_option(optarg)) {
fprintf(stderr,
_("%s: invalid time range: %s\n"),
_("%s: invalid time range: %s\n"),
progname, optarg);
return EXIT_FAILURE;
}
@ -1108,6 +1110,8 @@ _("%s: invalid time range: %s\n"),
fprintf(stderr, _("%s: -R time exceeds -r cutoff\n"), progname);
return EXIT_FAILURE;
}
if (redundant_time < lo_time)
redundant_time = lo_time;
if (bloat == 0) {
static char const bloat_default[] = ZIC_BLOAT_DEFAULT;
if (strcmp(bloat_default, "slim") == 0)
@ -1389,9 +1393,9 @@ rename_dest(char *tempname, char const *name)
}
}
/* Create symlink contents suitable for symlinking FROM to TO, as a
freshly allocated string. FROM should be a relative file name, and
is relative to the global variable DIRECTORY. TO can be either
/* Create symlink contents suitable for symlinking TARGET to LINKNAME, as a
freshly allocated string. TARGET should be a relative file name, and
is relative to the global variable DIRECTORY. LINKNAME can be either
relative or absolute. */
static char *
relname(char const *target, char const *linkname)
@ -1428,6 +1432,18 @@ relname(char const *target, char const *linkname)
return result;
}
/* Return true if A and B must have the same parent dir if A and B exist.
Return false if this is not necessarily true (though it might be true).
Keep it simple, and do not inspect the file system. */
static bool
same_parent_dirs(char const *a, char const *b)
{
for (; *a == *b; a++, b++)
if (!*a)
return true;
return ! (strchr(a, '/') || strchr(b, '/'));
}
static void
dolink(char const *target, char const *linkname, bool staysymlink)
{
@ -1435,6 +1451,7 @@ dolink(char const *target, char const *linkname, bool staysymlink)
int link_errno;
char *tempname = NULL;
char const *outname = linkname;
int targetissym = -2, linknameissym = -2;
check_for_signal();
@ -1456,13 +1473,32 @@ dolink(char const *target, char const *linkname, bool staysymlink)
break;
}
link_errno = errno;
/* Linux 2.6.16 and 2.6.17 mishandle AT_SYMLINK_FOLLOW. */
if (link_errno == EINVAL)
link_errno = ENOTSUP;
#if HAVE_LINK
/* If linkat is not supported, fall back on link(A, B).
However, skip this if A is a relative symlink
and A and B might not have the same parent directory.
On some platforms link(A, B) does not follow a symlink A,
and if A is relative it might misbehave elsewhere. */
if (link_errno == ENOTSUP
&& (same_parent_dirs(target, outname)
|| 0 <= itssymlink(target, &targetissym))) {
if (link(target, outname) == 0) {
link_errno = 0;
break;
}
link_errno = errno;
}
#endif
if (link_errno == EXDEV || link_errno == ENOTSUP)
break;
if (link_errno == EEXIST) {
staysymlink &= !tempname;
random_dirent(&outname, &tempname);
if (staysymlink && itssymlink(linkname))
if (staysymlink && itssymlink(linkname, &linknameissym))
break;
} else if (link_errno == ENOENT && !linkdirs_made) {
mkdirs(linkname, true);
@ -1525,12 +1561,17 @@ dolink(char const *target, char const *linkname, bool staysymlink)
rename_dest(tempname, linkname);
}
/* Return true if NAME is a symbolic link. */
static bool
itssymlink(char const *name)
/* Return 1 if NAME is an absolute symbolic link, -1 if it is relative,
0 if it is not a symbolic link. If *CACHE is not -2, it is the
cached result of a previous call to this function with the same NAME. */
static int
itssymlink(char const *name, int *cache)
{
char c;
return 0 <= readlink(name, &c, 1);
if (*cache == -2) {
char c = '\0';
*cache = readlink(name, &c, 1) < 0 ? 0 : c == '/' ? 1 : -1;
}
return *cache;
}
/*
@ -1843,16 +1884,14 @@ inzone(char **fields, int nfields)
return false;
}
if (lcltime != NULL && strcmp(fields[ZF_NAME], tzdefault) == 0) {
error(
_("\"Zone %s\" line and -l option are mutually exclusive"),
tzdefault);
return false;
error(_("\"Zone %s\" line and -l option are mutually exclusive"),
tzdefault);
return false;
}
if (strcmp(fields[ZF_NAME], TZDEFRULES) == 0 && psxrules != NULL) {
error(
_("\"Zone %s\" line and -p option are mutually exclusive"),
TZDEFRULES);
return false;
error(_("\"Zone %s\" line and -p option are mutually exclusive"),
TZDEFRULES);
return false;
}
for (i = 0; i < nzones; ++i)
if (zones[i].z_name != NULL &&
@ -1944,10 +1983,9 @@ inzsub(char **fields, int nfields, bool iscont)
zones[nzones - 1].z_untiltime > min_time &&
zones[nzones - 1].z_untiltime < max_time &&
zones[nzones - 1].z_untiltime >= z.z_untiltime) {
error(_(
"Zone continuation line end time is not after end time of previous line"
));
return false;
error(_("Zone continuation line end time is"
" not after end time of previous line"));
return false;
}
}
z.z_name = iscont ? NULL : estrdup(fields[ZF_NAME]);
@ -2149,13 +2187,12 @@ rulesub(struct rule *rp, const char *loyearp, const char *hiyearp,
*/
cp = loyearp;
lp = byword(cp, begin_years);
rp->r_lowasnum = lp == NULL;
if (!rp->r_lowasnum) switch (lp->l_value) {
if (lp) switch (lp->l_value) {
case YR_MINIMUM:
rp->r_loyear = ZIC_MIN;
break;
case YR_MAXIMUM:
rp->r_loyear = ZIC_MAX;
warning(_("FROM year \"%s\" is obsolete;"
" treated as %d"),
cp, YEAR_32BIT_MIN - 1);
rp->r_loyear = YEAR_32BIT_MIN - 1;
break;
default: unreachable();
} else if (sscanf(cp, "%"SCNdZIC"%c", &rp->r_loyear, &xs) != 1) {
@ -2166,9 +2203,6 @@ rulesub(struct rule *rp, const char *loyearp, const char *hiyearp,
lp = byword(cp, end_years);
rp->r_hiwasnum = lp == NULL;
if (!rp->r_hiwasnum) switch (lp->l_value) {
case YR_MINIMUM:
rp->r_hiyear = ZIC_MIN;
break;
case YR_MAXIMUM:
rp->r_hiyear = ZIC_MAX;
break;
@ -2948,6 +2982,10 @@ rule_cmp(struct rule const *a, struct rule const *b)
return a->r_dayofmonth - b->r_dayofmonth;
}
/* Store into RESULT a POSIX.1-2017 TZ string that represent the future
predictions for the zone ZPFIRST with ZONECOUNT entries. Return a
compatibility indicator (a TZDB release year) if successful, a
negative integer if no such TZ string exissts. */
static int
stringzone(char *result, struct zone const *zpfirst, ptrdiff_t zonecount)
{
@ -3083,11 +3121,11 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
register char * envvar;
register int max_abbr_len;
register int max_envvar_len;
register bool prodstic; /* all rules are min to max */
register int compat;
register bool do_extend;
register char version;
ptrdiff_t lastatmax = -1;
zic_t nonTZlimtime = ZIC_MIN;
int nonTZlimtype = -1;
zic_t max_year0;
int defaulttype = -1;
@ -3108,7 +3146,6 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
timecnt = 0;
typecnt = 0;
charcnt = 0;
prodstic = zonecount == 1;
/*
** Thanks to Earl Chew
** for noting the need to unconditionally initialize startttisstd.
@ -3126,12 +3163,9 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
updateminmax(zp->z_untilrule.r_loyear);
for (j = 0; j < zp->z_nrules; ++j) {
struct rule *rp = &zp->z_rules[j];
if (rp->r_lowasnum)
updateminmax(rp->r_loyear);
updateminmax(rp->r_loyear);
if (rp->r_hiwasnum)
updateminmax(rp->r_hiyear);
if (rp->r_lowasnum || rp->r_hiwasnum)
prodstic = false;
}
}
/*
@ -3143,7 +3177,8 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
if (noise) {
if (!*envvar)
warning("%s %s",
_("no POSIX environment variable for zone"),
_("no POSIX.1-2017 environment variable"
" for zone"),
zpfirst->z_name);
else if (compat != 0) {
/* Circa-COMPAT clients, and earlier clients, might
@ -3155,37 +3190,12 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
}
}
if (do_extend) {
/*
** Search through a couple of extra years past the obvious
** 400, to avoid edge cases. For example, suppose a non-POSIX
** rule applies from 2012 onwards and has transitions in March
** and September, plus some one-off transitions in November
** 2013. If zic looked only at the last 400 years, it would
** set max_year=2413, with the intent that the 400 years 2014
** through 2413 will be repeated. The last transition listed
** in the tzfile would be in 2413-09, less than 400 years
** after the last one-off transition in 2013-11. Two years
** might be overkill, but with the kind of edge cases
** available we're not sure that one year would suffice.
*/
enum { years_of_observations = YEARSPERREPEAT + 2 };
if (min_year >= ZIC_MIN + years_of_observations)
min_year -= years_of_observations;
else min_year = ZIC_MIN;
if (max_year <= ZIC_MAX - years_of_observations)
max_year += years_of_observations;
else max_year = ZIC_MAX;
/*
** Regardless of any of the above,
** for a "proDSTic" zone which specifies that its rules
** always have and always will be in effect,
** we only need one cycle to define the zone.
*/
if (prodstic) {
min_year = 1900;
max_year = min_year + years_of_observations;
}
}
max_year = max(max_year, (redundant_time / (SECSPERDAY * DAYSPERNYEAR)
+ EPOCH_YEAR + 1));
@ -3193,17 +3203,16 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
if (want_bloat()) {
/* For the benefit of older systems,
generate data from 1900 through 2038. */
if (min_year > 1900)
min_year = 1900;
if (max_year < 2038)
max_year = 2038;
if (min_year > YEAR_32BIT_MIN - 1)
min_year = YEAR_32BIT_MIN - 1;
if (max_year < YEAR_32BIT_MAX)
max_year = YEAR_32BIT_MAX;
}
if (min_time < lo_time || hi_time < max_time)
unspecifiedtype = addtype(0, "-00", false, false, false);
for (i = 0; i < zonecount; ++i) {
struct rule *prevrp = NULL;
/*
** A guess that may well be corrected later.
*/
@ -3213,8 +3222,6 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
bool useuntil = i < (zonecount - 1);
zic_t stdoff = zp->z_stdoff;
zic_t startoff = stdoff;
zic_t prevktime;
INITIALIZE(prevktime);
if (useuntil && zp->z_untiltime <= min_time)
continue;
eat(zp->z_filenum, zp->z_linenum);
@ -3228,6 +3235,10 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
startttisut);
if (usestart) {
addtt(starttime, type);
if (useuntil && nonTZlimtime < starttime) {
nonTZlimtime = starttime;
nonTZlimtype = type;
}
usestart = false;
} else
defaulttype = type;
@ -3355,23 +3366,16 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
doabbr(ab, zp, rp->r_abbrvar,
rp->r_isdst, rp->r_save, false);
offset = oadd(zp->z_stdoff, rp->r_save);
if (!want_bloat() && !useuntil && !do_extend
&& prevrp && lo_time <= prevktime
&& redundant_time <= ktime
&& rp->r_hiyear == ZIC_MAX
&& prevrp->r_hiyear == ZIC_MAX)
break;
type = addtype(offset, ab, rp->r_isdst,
rp->r_todisstd, rp->r_todisut);
if (defaulttype < 0 && !rp->r_isdst)
defaulttype = type;
if (rp->r_hiyear == ZIC_MAX
&& ! (0 <= lastatmax
&& ktime < attypes[lastatmax].at))
lastatmax = timecnt;
addtt(ktime, type);
prevrp = rp;
prevktime = ktime;
if (nonTZlimtime < ktime
&& (useuntil || rp->r_hiyear != ZIC_MAX)) {
nonTZlimtime = ktime;
nonTZlimtype = type;
}
}
}
}
@ -3382,7 +3386,8 @@ outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
isdst, save, false);
eat(zp->z_filenum, zp->z_linenum);
if (*startbuf == '\0')
error(_("can't determine time zone abbreviation to use just after until time"));
error(_("can't determine time zone abbreviation"
" to use just after until time"));
else {
int type = addtype(startoff, startbuf, isdst,
startttisstd, startttisut);
@ -3406,12 +3411,38 @@ error(_("can't determine time zone abbreviation to use just after until time"));
}
if (defaulttype < 0)
defaulttype = 0;
if (0 <= lastatmax)
attypes[lastatmax].dontmerge = true;
if (!do_extend && !want_bloat()) {
/* Keep trailing transitions that are no greater than this. */
zic_t keep_at_max;
/* The earliest transition into a time governed by the TZ string. */
zic_t TZstarttime = ZIC_MAX;
for (i = 0; i < timecnt; i++) {
zic_t at = attypes[i].at;
if (nonTZlimtime < at && at < TZstarttime)
TZstarttime = at;
}
if (TZstarttime == ZIC_MAX)
TZstarttime = nonTZlimtime;
/* Omit trailing transitions deducible from the TZ string,
and not needed for -r or -R. */
keep_at_max = max(TZstarttime, redundant_time);
for (i = j = 0; i < timecnt; i++)
if (attypes[i].at <= keep_at_max) {
attypes[j].at = attypes[i].at;
attypes[j].dontmerge = (attypes[i].at == TZstarttime
&& (nonTZlimtype != attypes[i].type
|| strchr(envvar, ',')));
attypes[j].type = attypes[i].type;
j++;
}
timecnt = j;
}
if (do_extend) {
/*
** If we're extending the explicitly listed observations
** for 400 years because we can't fill the POSIX-TZ field,
** If we're extending the explicitly listed observations for
** 400 years because we can't fill the POSIX.1-2017 TZ field,
** check whether we actually ended up explicitly listing
** observations through that period. If there aren't any
** near the end of the 400-year period, add a redundant