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:
parent
d5228e8957
commit
378c74faf3
258
Makefile
258
Makefile
@ -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"'|' \
|
||||
-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,11 +883,11 @@ 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)
|
||||
! grep -En "$$pat|[$s]\$$" \
|
||||
$$(ls $(ENCHILADA) | grep -Fvx leap-seconds.list); \
|
||||
}
|
||||
touch $@
|
||||
|
||||
PRECEDES_FILE_NAME = ^(Zone|Link[$s]+[^$s]+)[$s]+
|
||||
@ -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
193
NEWS
@ -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
17
README
@ -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
14
date.1
@ -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.
|
||||
|
@ -97,12 +97,11 @@ DESCRIPTION
|
||||
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.
|
||||
/usr/share/zoneinfo/GMT0 if present.
|
||||
|
||||
Time Zone Database date(1)
|
||||
|
128
localtime.c
128
localtime.c
@ -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)
|
||||
|
16
newctime.3
16
newctime.3
@ -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),
|
||||
|
@ -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)
|
||||
|
152
newstrftime.3
152
newstrftime.3
@ -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
|
||||
|
@ -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,109 +23,136 @@ 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].
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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
|
||||
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].
|
||||
[00,23]. [tm_hour]
|
||||
|
||||
%I is replaced by the hour (12-hour clock) as a decimal number
|
||||
[01,12].
|
||||
[01,12]. [tm_hour]
|
||||
|
||||
%j is replaced by the day of the year as a decimal number
|
||||
[001,366].
|
||||
[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.
|
||||
[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.
|
||||
[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".
|
||||
[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.
|
||||
periodic occurrence of leap seconds. [tm_sec]
|
||||
|
||||
%s is replaced by the number of seconds since the Epoch (see
|
||||
ctime(3)).
|
||||
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].
|
||||
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
|
||||
containing January 1 has four or more days in the new year, then
|
||||
it is week 1; otherwise it is week 53 of the previous year, and
|
||||
the next week is week 1. The year is given by the %G conversion
|
||||
specification.
|
||||
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].
|
||||
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.
|
||||
[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.
|
||||
[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.
|
||||
[tm_year]
|
||||
|
||||
%y is replaced by the year without century as a decimal number
|
||||
[00,99].
|
||||
[00,99]. [tm_year]
|
||||
|
||||
%Z is replaced by the time zone abbreviation, or by the empty
|
||||
string if this is not determinable.
|
||||
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
|
||||
@ -134,11 +161,17 @@ DESCRIPTION
|
||||
-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.
|
||||
[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
|
||||
|
206
newtzset.3
206
newtzset.3
@ -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),
|
||||
|
207
newtzset.3.txt
207
newtzset.3.txt
@ -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,102 +36,93 @@ 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]]
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
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:
|
||||
|
||||
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
|
||||
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
|
||||
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,
|
||||
without daylight saving.
|
||||
@ -175,24 +158,54 @@ DESCRIPTION
|
||||
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.
|
||||
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.
|
||||
/usr/share/zoneinfo/GMT0 if present.
|
||||
|
||||
SEE ALSO
|
||||
getenv(3), newctime(3), newstrftime(3), time(2), tzfile(5)
|
||||
|
44
private.h
44
private.h
@ -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,
|
||||
|
@ -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
|
||||
|
37
theory.html
37
theory.html
@ -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><-03>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>,
|
||||
|
@ -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
|
||||
|
413
tz-art.html
413
tz-art.html
@ -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
|
||||
— and, once, Denmark — 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.
|
||||
@ -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> </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 ★,
|
||||
<a href="https://www.allmusic.com/album/i-didnt-know-about-you-mw0000618657">AMG</a>
|
||||
★★★★, Penguin ★★★⯪.
|
||||
</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> </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> </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 ★⯪,
|
||||
<a href="https://www.allmusic.com/album/double-rainbow-mw0000620371">AMG</a>
|
||||
★★★, Penguin ★★★.
|
||||
</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 •,
|
||||
<a href="https://www.allmusic.com/album/heres-to-life-mw0000623648">AMG</a>
|
||||
★★, Penguin ★★★.
|
||||
</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 ★,
|
||||
<a href="https://www.allmusic.com/album/keeper-of-the-spirit-mw0000176559">AMG</a>
|
||||
unrated, Penguin ★★★.
|
||||
</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> </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 ★★⯪,
|
||||
<a href="https://www.allmusic.com/album/blame-it-on-my-youth-mw0000274303">AMG</a>
|
||||
★★★, 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> </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 ★★★,
|
||||
<a href="https://www.allmusic.com/album/old-man-time-mw0000269353">AMG</a>
|
||||
★★★★⯪, Penguin ★★★.
|
||||
</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> </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 ★,
|
||||
<a href="https://www.allmusic.com/album/pacific-standard-time-mw0000645433">AMG</a>
|
||||
★★★★, Penguin ★★★⯪.
|
||||
</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> </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> </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> </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 •,
|
||||
<a href="https://www.allmusic.com/album/silence-time-zones-mw0000595735">AMG</a>
|
||||
★★★★.
|
||||
</li>
|
||||
<li>
|
||||
Charles Gayle, <em>Time Zones</em> (2006). Tompkins Square TSQ2839, 49:06.
|
||||
Charles Gayle, piano.
|
||||
ADO ★,
|
||||
<a href="https://www.allmusic.com/album/time-zones-mw0000349642">AMG</a>
|
||||
★★★★⯪.
|
||||
</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>
|
||||
★★⯪.
|
||||
</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> </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é
|
||||
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–3). Its lyrics include "Amanecí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> </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> </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> </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> </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 ★★,
|
||||
<a href="https://www.allmusic.com/album/lobster-leaps-in-mw0000794929">AMG</a>
|
||||
★★★⯪.
|
||||
</li>
|
||||
<li>
|
||||
Bob Dylan, <em>The Times They Are a-Changin'</em> (1964).
|
||||
Columbia CK-8905, 45:36.
|
||||
ADO ★⯪,
|
||||
<a href="https://www.allmusic.com/album/the-times-they-a-changin-mw0000202344">AMG</a>
|
||||
★★★★⯪.
|
||||
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 ★★⯪,
|
||||
<a href="https://www.allmusic.com/album/tide-mw0000815692">AMG</a>
|
||||
★★★⯪.
|
||||
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> </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> </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> </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 ★,
|
||||
<a href="https://www.allmusic.com/album/youre-getting-better-the-word-jazz-dot-masters-mw0000736197">AMG</a>
|
||||
★★★★⯪.
|
||||
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> ★★★★.
|
||||
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?"
|
||||
@ -608,7 +559,7 @@ entitled "The Kid," originally aired 1997-11-04)
|
||||
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
|
||||
|
118
tz-link.html
118
tz-link.html
@ -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 –
|
||||
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
|
||||
– 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–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–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–230.
|
||||
<em>J Biol Rhythms.</em> 2019;34(3):227–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
114
tzfile.5
@ -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),
|
||||
|
361
tzfile.5.txt
361
tzfile.5.txt
@ -14,19 +14,19 @@ 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
|
||||
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,
|
||||
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.)
|
||||
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.
|
||||
@ -50,20 +50,21 @@ DESCRIPTION
|
||||
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;
|
||||
@ -71,103 +72,109 @@ DESCRIPTION
|
||||
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
|
||||
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
|
||||
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.
|
||||
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
|
||||
@ -233,13 +240,13 @@ DESCRIPTION
|
||||
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
|
||||
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
|
||||
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
|
||||
@ -254,116 +261,120 @@ DESCRIPTION
|
||||
|
||||
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
|
||||
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
|
||||
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.
|
||||
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
|
||||
mostly as warnings to developers of readers.
|
||||
|
||||
* Some readers do not support negative timestamps. Developers of
|
||||
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
|
||||
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
|
||||
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
|
||||
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>.
|
||||
(TZif). 2019 Feb. Internet RFC 8536 doi:10.17487/RFC8536.
|
||||
|
||||
Time Zone Database tzfile(5)
|
||||
|
14
tzfile.h
14
tzfile.h
@ -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
|
||||
|
@ -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 ).
|
||||
|
@ -47,7 +47,7 @@ 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:
|
||||
/usr/share/zoneinfo).
|
||||
|
482
tzselect.ksh
482
tzselect.ksh
@ -10,7 +10,7 @@ REPORT_BUGS_TO=tz@iana.org
|
||||
|
||||
# Porting notes:
|
||||
#
|
||||
# This script requires a Posix-like shell and prefers the extension of a
|
||||
# This script requires a POSIX-like shell and prefers the extension of a
|
||||
# 'select' statement. The 'select' statement was introduced in the
|
||||
# Korn shell and is available in Bash and other shell implementations.
|
||||
# If your host lacks both Bash and the Korn shell, you can get their
|
||||
@ -21,23 +21,32 @@ REPORT_BUGS_TO=tz@iana.org
|
||||
# MirBSD Korn Shell <http://www.mirbsd.org/mksh.htm>
|
||||
#
|
||||
# For portability to Solaris 10 /bin/sh (supported by Oracle through
|
||||
# January 2024) this script avoids some POSIX features and common
|
||||
# extensions, such as $(...) (which works sometimes but not others),
|
||||
# $((...)), ! CMD, ${#ID}, ${ID##PAT}, ${ID%%PAT}, and $10.
|
||||
|
||||
# January 2027) this script avoids some POSIX features and common
|
||||
# extensions, such as $(...), $((...)), ! CMD, unquoted ^, ${#ID},
|
||||
# ${ID##PAT}, ${ID%%PAT}, and $10. Although some of these constructs
|
||||
# work sometimes, it's simpler to avoid them entirely.
|
||||
#
|
||||
# This script also uses several features of modern awk programs.
|
||||
# If your host lacks awk, or has an old awk that does not conform to Posix,
|
||||
# you can use either of the following free programs instead:
|
||||
# This script also uses several features of POSIX awk.
|
||||
# If your host lacks awk, or has an old awk that does not conform to POSIX,
|
||||
# you can use any of the following free programs instead:
|
||||
#
|
||||
# Gawk (GNU awk) <https://www.gnu.org/software/gawk/>
|
||||
# mawk <https://invisible-island.net/mawk/>
|
||||
# nawk <https://github.com/onetrueawk/awk>
|
||||
#
|
||||
# Because 'awk "VAR=VALUE" ...' and 'awk -v "VAR=VALUE" ...' are not portable
|
||||
# if VALUE contains \, ", or newline, awk scripts in this file use:
|
||||
# awk 'BEGIN { VAR = substr(ARGV[1], 2); ARGV[1] = "" } ...' ="VALUE"
|
||||
# The substr avoids problems when VALUE is of the form X=Y and would be
|
||||
# misinterpreted as an assignment.
|
||||
|
||||
# This script does not want path expansion.
|
||||
set -f
|
||||
|
||||
# Specify default values for environment variables if they are unset.
|
||||
: ${AWK=awk}
|
||||
: ${TZDIR=`pwd`}
|
||||
: ${PWD=`pwd`}
|
||||
: ${TZDIR=$PWD}
|
||||
|
||||
# Output one argument as-is to standard output, with trailing newline.
|
||||
# Safer than 'echo', which can mishandle '\' or leading '-'.
|
||||
@ -45,10 +54,10 @@ say() {
|
||||
printf '%s\n' "$1"
|
||||
}
|
||||
|
||||
# Check for awk Posix compliance.
|
||||
($AWK -v x=y 'BEGIN { exit 123 }') </dev/null >/dev/null 2>&1
|
||||
# Check for awk POSIX compliance.
|
||||
($AWK -v x=y 'BEGIN { exit 123 }') <>/dev/null >&0 2>&0
|
||||
[ $? = 123 ] || {
|
||||
say >&2 "$0: Sorry, your '$AWK' program is not Posix compatible."
|
||||
say >&2 "$0: Sorry, your '$AWK' program is not POSIX compatible."
|
||||
exit 1
|
||||
}
|
||||
|
||||
@ -89,7 +98,7 @@ if
|
||||
?*) :;;
|
||||
'')
|
||||
# '; exit' should be redundant, but Dash doesn't properly fail without it.
|
||||
(eval 'set --; select x; do break; done; exit') </dev/null 2>/dev/null
|
||||
(eval 'set --; select x; do break; done; exit') <>/dev/null 2>&0
|
||||
esac
|
||||
then
|
||||
# Do this inside 'eval', as otherwise the shell might exit when parsing it
|
||||
@ -108,7 +117,8 @@ then
|
||||
else
|
||||
doselect() {
|
||||
# Field width of the prompt numbers.
|
||||
select_width=`expr $# : '.*'`
|
||||
print_nargs_length="BEGIN {print length(\"$#\");}"
|
||||
select_width=`$AWK "$print_nargs_length"`
|
||||
|
||||
select_i=
|
||||
|
||||
@ -119,14 +129,14 @@ else
|
||||
select_i=0
|
||||
for select_word
|
||||
do
|
||||
select_i=`expr $select_i + 1`
|
||||
select_i=`$AWK "BEGIN { print $select_i + 1 }"`
|
||||
printf >&2 "%${select_width}d) %s\\n" $select_i "$select_word"
|
||||
done;;
|
||||
*[!0-9]*)
|
||||
echo >&2 'Please enter a number in range.';;
|
||||
*)
|
||||
if test 1 -le $select_i && test $select_i -le $#; then
|
||||
shift `expr $select_i - 1`
|
||||
shift `$AWK "BEGIN { print $select_i - 1 }"`
|
||||
select_result=$1
|
||||
break
|
||||
fi
|
||||
@ -156,42 +166,43 @@ do
|
||||
-*)
|
||||
say >&2 "$0: -$opt$OPTARG: unknown option; try '$0 --help'"; exit 1;;
|
||||
*)
|
||||
say >&2 "$0: try '$0 --help'"; exit 1 ;;
|
||||
say >&2 "$0: try '$0 --help'"; exit 1
|
||||
esac
|
||||
done
|
||||
|
||||
shift `expr $OPTIND - 1`
|
||||
shift `$AWK "BEGIN { print $OPTIND - 1 }"`
|
||||
case $# in
|
||||
0) ;;
|
||||
*) say >&2 "$0: $1: unknown argument"; exit 1 ;;
|
||||
*) say >&2 "$0: $1: unknown argument"; exit 1
|
||||
esac
|
||||
|
||||
# Make sure the tables are readable.
|
||||
TZ_COUNTRY_TABLE=$TZDIR/iso3166.tab
|
||||
TZ_ZONE_TABLE=$TZDIR/$zonetabtype.tab
|
||||
for f in $TZ_COUNTRY_TABLE $TZ_ZONE_TABLE
|
||||
do
|
||||
<"$f" || {
|
||||
# translit=true to try transliteration.
|
||||
# This is false if U+12345 CUNEIFORM SIGN URU TIMES KI has length 1
|
||||
# which means awk (and presumably the shell) do not need transliteration.
|
||||
if $AWK 'BEGIN { u12345 = "\360\222\215\205"; exit length(u12345) == 1 }'; then
|
||||
translit=true
|
||||
else
|
||||
translit=false
|
||||
fi
|
||||
|
||||
# Read into shell variable $1 the contents of file $2.
|
||||
# Convert to the current locale's encoding if possible,
|
||||
# as the shell aligns columns better that way.
|
||||
# If GNU iconv's //TRANSLIT does not work, fall back on POSIXish iconv;
|
||||
# if that does not work, fall back on 'cat'.
|
||||
read_file() {
|
||||
{ $translit && {
|
||||
eval "$1=\`(iconv -f UTF-8 -t //TRANSLIT) 2>/dev/null <\"\$2\"\`" ||
|
||||
eval "$1=\`(iconv -f UTF-8) 2>/dev/null <\"\$2\"\`"
|
||||
}; } ||
|
||||
eval "$1=\`cat <\"\$2\"\`" || {
|
||||
say >&2 "$0: time zone files are not set up correctly"
|
||||
exit 1
|
||||
}
|
||||
done
|
||||
|
||||
# If the current locale does not support UTF-8, convert data to current
|
||||
# locale's format if possible, as the shell aligns columns better that way.
|
||||
# Check the UTF-8 of U+12345 CUNEIFORM SIGN URU TIMES KI.
|
||||
$AWK 'BEGIN { u12345 = "\360\222\215\205"; exit length(u12345) != 1 }' || {
|
||||
{ tmp=`(mktemp -d) 2>/dev/null` || {
|
||||
tmp=${TMPDIR-/tmp}/tzselect.$$ &&
|
||||
(umask 77 && mkdir -- "$tmp")
|
||||
};} &&
|
||||
trap 'status=$?; rm -fr -- "$tmp"; exit $status' 0 HUP INT PIPE TERM &&
|
||||
(iconv -f UTF-8 -t //TRANSLIT <"$TZ_COUNTRY_TABLE" >$tmp/iso3166.tab) \
|
||||
2>/dev/null &&
|
||||
TZ_COUNTRY_TABLE=$tmp/iso3166.tab &&
|
||||
iconv -f UTF-8 -t //TRANSLIT <"$TZ_ZONE_TABLE" >$tmp/$zonetabtype.tab &&
|
||||
TZ_ZONE_TABLE=$tmp/$zonetabtype.tab
|
||||
}
|
||||
read_file TZ_COUNTRY_TABLE "$TZDIR/iso3166.tab"
|
||||
read_file TZ_ZONETABTYPE_TABLE "$TZDIR/$zonetabtype.tab"
|
||||
TZ_ZONENOW_TABLE=
|
||||
|
||||
newline='
|
||||
'
|
||||
@ -199,12 +210,19 @@ IFS=$newline
|
||||
|
||||
# Awk script to output a country list.
|
||||
output_country_list='
|
||||
BEGIN { FS = "\t" }
|
||||
/^#$/ { next }
|
||||
/^#[^@]/ { next }
|
||||
{
|
||||
BEGIN {
|
||||
continent_re = substr(ARGV[1], 2)
|
||||
TZ_COUNTRY_TABLE = substr(ARGV[2], 2)
|
||||
TZ_ZONE_TABLE = substr(ARGV[3], 2)
|
||||
ARGV[1] = ARGV[2] = ARGV[3] = ""
|
||||
FS = "\t"
|
||||
nlines = split(TZ_ZONE_TABLE, line, /\n/)
|
||||
for (iline = 1; iline <= nlines; iline++) {
|
||||
$0 = line[iline]
|
||||
commentary = $0 ~ /^#@/
|
||||
if (commentary) {
|
||||
if ($0 !~ /^#@/)
|
||||
continue
|
||||
col1ccs = substr($1, 3)
|
||||
conts = $2
|
||||
} else {
|
||||
@ -217,43 +235,52 @@ output_country_list='
|
||||
elsewhere = commentary
|
||||
for (ci = 1; ci <= ncont; ci++) {
|
||||
if (cont[ci] ~ continent_re) {
|
||||
if (!cc_seen[cc[i]]++) cc_list[++ccs] = cc[i]
|
||||
if (!cc_seen[cc[i]]++)
|
||||
cc_list[++ccs] = cc[i]
|
||||
elsewhere = 0
|
||||
}
|
||||
}
|
||||
if (elsewhere) {
|
||||
for (i = 1; i <= ncc; i++) {
|
||||
if (elsewhere)
|
||||
for (i = 1; i <= ncc; i++)
|
||||
cc_elsewhere[cc[i]] = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
END {
|
||||
while (getline <TZ_COUNTRY_TABLE) {
|
||||
if ($0 !~ /^#/) cc_name[$1] = $2
|
||||
nlines = split(TZ_COUNTRY_TABLE, line, /\n/)
|
||||
for (i = 1; i <= nlines; i++) {
|
||||
$0 = line[i]
|
||||
if ($0 !~ /^#/)
|
||||
cc_name[$1] = $2
|
||||
}
|
||||
for (i = 1; i <= ccs; i++) {
|
||||
country = cc_list[i]
|
||||
if (cc_elsewhere[country]) continue
|
||||
if (cc_name[country]) {
|
||||
if (cc_elsewhere[country])
|
||||
continue
|
||||
if (cc_name[country])
|
||||
country = cc_name[country]
|
||||
}
|
||||
print country
|
||||
}
|
||||
}
|
||||
'
|
||||
|
||||
# Awk script to read a time zone table and output the same table,
|
||||
# Awk script to process a time zone table and output the same table,
|
||||
# with each row preceded by its distance from 'here'.
|
||||
# If output_times is set, each row is instead preceded by its local time
|
||||
# and any apostrophes are escaped for the shell.
|
||||
output_distances_or_times='
|
||||
BEGIN {
|
||||
coord = substr(ARGV[1], 2)
|
||||
TZ_COUNTRY_TABLE = substr(ARGV[2], 2)
|
||||
TZ_ZONE_TABLE = substr(ARGV[3], 2)
|
||||
ARGV[1] = ARGV[2] = ARGV[3] = ""
|
||||
FS = "\t"
|
||||
if (!output_times) {
|
||||
while (getline <TZ_COUNTRY_TABLE)
|
||||
if ($0 ~ /^[^#]/)
|
||||
nlines = split(TZ_COUNTRY_TABLE, line, /\n/)
|
||||
for (i = 1; i <= nlines; i++) {
|
||||
$0 = line[i]
|
||||
if ($0 ~ /^#/)
|
||||
continue
|
||||
country[$1] = $2
|
||||
}
|
||||
country["US"] = "US" # Otherwise the strings get too long.
|
||||
}
|
||||
}
|
||||
@ -315,35 +342,39 @@ output_distances_or_times='
|
||||
BEGIN {
|
||||
coord_lat = convert_latitude(coord)
|
||||
coord_long = convert_longitude(coord)
|
||||
}
|
||||
/^[^#]/ {
|
||||
nlines = split(TZ_ZONE_TABLE, line, /\n/)
|
||||
for (h = 1; h <= nlines; h++) {
|
||||
$0 = line[h]
|
||||
if ($0 ~ /^#/)
|
||||
continue
|
||||
inline[inlines++] = $0
|
||||
ncc = split($1, cc, /,/)
|
||||
for (i = 1; i <= ncc; i++)
|
||||
cc_used[cc[i]]++
|
||||
}
|
||||
END {
|
||||
for (h = 0; h < inlines; h++) {
|
||||
$0 = inline[h]
|
||||
line = $1 "\t" $2 "\t" $3
|
||||
outline = $1 "\t" $2 "\t" $3
|
||||
sep = "\t"
|
||||
ncc = split($1, cc, /,/)
|
||||
split("", item_seen)
|
||||
item_seen[""] = 1
|
||||
for (i = 1; i <= ncc; i++) {
|
||||
item = cc_used[cc[i]] <= 1 ? country[cc[i]] : $4
|
||||
if (item_seen[item]++) continue
|
||||
line = line sep item
|
||||
if (item_seen[item]++)
|
||||
continue
|
||||
outline = outline sep item
|
||||
sep = "; "
|
||||
}
|
||||
if (output_times) {
|
||||
fmt = "TZ='\''%s'\'' date +'\''%d %%Y %%m %%d %%H:%%M %%a %%b\t%s'\''\n"
|
||||
gsub(/'\''/, "&\\\\&&", line)
|
||||
printf fmt, $3, h, line
|
||||
gsub(/'\''/, "&\\\\&&", outline)
|
||||
printf fmt, $3, h, outline
|
||||
} else {
|
||||
here_lat = convert_latitude($2)
|
||||
here_long = convert_longitude($2)
|
||||
printf "%g\t%s\n", dist(coord_lat, coord_long, here_lat, here_long), line
|
||||
printf "%g\t%s\n", dist(coord_lat, coord_long, here_lat, here_long), \
|
||||
outline
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -357,7 +388,10 @@ while
|
||||
|
||||
continent=
|
||||
country=
|
||||
country_result=
|
||||
region=
|
||||
time=
|
||||
TZ_ZONE_TABLE=$TZ_ZONETABTYPE_TABLE
|
||||
|
||||
case $coord in
|
||||
?*)
|
||||
@ -366,7 +400,8 @@ while
|
||||
|
||||
# Ask the user for continent or ocean.
|
||||
|
||||
echo >&2 'Please select a continent, ocean, "coord", "TZ", or "time".'
|
||||
echo >&2 \
|
||||
'Please select a continent, ocean, "coord", "TZ", "time", or "now".'
|
||||
|
||||
quoted_continents=`
|
||||
$AWK '
|
||||
@ -378,17 +413,23 @@ while
|
||||
entry = entry " Ocean"
|
||||
printf "'\''%s'\''\n", entry
|
||||
}
|
||||
BEGIN { FS = "\t" }
|
||||
/^[^#]/ {
|
||||
BEGIN {
|
||||
TZ_ZONETABTYPE_TABLE = substr(ARGV[1], 2)
|
||||
ARGV[1] = ""
|
||||
FS = "\t"
|
||||
nlines = split(TZ_ZONETABTYPE_TABLE, line, /\n/)
|
||||
for (i = 1; i <= nlines; i++) {
|
||||
$0 = line[i]
|
||||
if ($0 ~ /^[^#]/)
|
||||
handle_entry($3)
|
||||
}
|
||||
/^#@/ {
|
||||
else if ($0 ~ /^#@/) {
|
||||
ncont = split($2, cont, /,/)
|
||||
for (ci = 1; ci <= ncont; ci++) {
|
||||
for (ci = 1; ci <= ncont; ci++)
|
||||
handle_entry(cont[ci])
|
||||
}
|
||||
}
|
||||
' <"$TZ_ZONE_TABLE" |
|
||||
}
|
||||
' ="$TZ_ZONETABTYPE_TABLE" |
|
||||
sort -u |
|
||||
tr '\n' ' '
|
||||
echo ''
|
||||
@ -397,19 +438,50 @@ while
|
||||
eval '
|
||||
doselect '"$quoted_continents"' \
|
||||
"coord - I want to use geographical coordinates." \
|
||||
"TZ - I want to specify the timezone using the Posix TZ format." \
|
||||
"time - I know local time already."
|
||||
"TZ - I want to specify the timezone using a POSIX.1-2017 TZ string." \
|
||||
"time - I know local time already." \
|
||||
"now - Like \"time\", but configure only for timestamps from now on."
|
||||
continent=$select_result
|
||||
case $continent in
|
||||
Americas) continent=America;;
|
||||
*" "*) continent=`expr "$continent" : '\''\([^ ]*\)'\''`
|
||||
*)
|
||||
# Get the first word of $continent. Path expansion is disabled
|
||||
# so this works even with "*", which should not happen.
|
||||
IFS=" "
|
||||
for continent in $continent ""; do break; done
|
||||
IFS=$newline;;
|
||||
esac
|
||||
case $zonetabtype,$continent in
|
||||
zonenow,*) ;;
|
||||
*,now)
|
||||
${TZ_ZONENOW_TABLE:+:} read_file TZ_ZONENOW_TABLE "$TZDIR/zonenow.tab"
|
||||
TZ_ZONE_TABLE=$TZ_ZONENOW_TABLE
|
||||
esac
|
||||
'
|
||||
esac
|
||||
|
||||
case $continent in
|
||||
TZ)
|
||||
# Ask the user for a Posix TZ string. Check that it conforms.
|
||||
# Ask the user for a POSIX.1-2017 TZ string. Check that it conforms.
|
||||
check_POSIX_TZ_string='
|
||||
BEGIN {
|
||||
tz = substr(ARGV[1], 2)
|
||||
ARGV[1] = ""
|
||||
tzname = ("(<[[:alnum:]+-][[:alnum:]+-][[:alnum:]+-]+>" \
|
||||
"|[[:alpha:]][[:alpha:]][[:alpha:]]+)")
|
||||
time = ("(2[0-4]|[0-1]?[0-9])" \
|
||||
"(:[0-5][0-9](:[0-5][0-9])?)?")
|
||||
offset = "[-+]?" time
|
||||
mdate = "M([1-9]|1[0-2])\\.[1-5]\\.[0-6]"
|
||||
jdate = ("((J[1-9]|[0-9]|J?[1-9][0-9]" \
|
||||
"|J?[1-2][0-9][0-9])|J?3[0-5][0-9]|J?36[0-5])")
|
||||
datetime = ",(" mdate "|" jdate ")(/" time ")?"
|
||||
tzpattern = ("^(:.*|" tzname offset "(" tzname \
|
||||
"(" offset ")?(" datetime datetime ")?)?)$")
|
||||
exit tz ~ tzpattern
|
||||
}
|
||||
'
|
||||
|
||||
while
|
||||
echo >&2 'Please enter the desired value' \
|
||||
'of the TZ environment variable.'
|
||||
@ -417,25 +489,12 @@ while
|
||||
'AEST and is 10 hours'
|
||||
echo >&2 'ahead (east) of Greenwich,' \
|
||||
'with no daylight saving time.'
|
||||
read TZ
|
||||
$AWK -v TZ="$TZ" 'BEGIN {
|
||||
tzname = "(<[[:alnum:]+-]{3,}>|[[:alpha:]]{3,})"
|
||||
time = "(2[0-4]|[0-1]?[0-9])" \
|
||||
"(:[0-5][0-9](:[0-5][0-9])?)?"
|
||||
offset = "[-+]?" time
|
||||
mdate = "M([1-9]|1[0-2])\\.[1-5]\\.[0-6]"
|
||||
jdate = "((J[1-9]|[0-9]|J?[1-9][0-9]" \
|
||||
"|J?[1-2][0-9][0-9])|J?3[0-5][0-9]|J?36[0-5])"
|
||||
datetime = ",(" mdate "|" jdate ")(/" time ")?"
|
||||
tzpattern = "^(:.*|" tzname offset "(" tzname \
|
||||
"(" offset ")?(" datetime datetime ")?)?)$"
|
||||
if (TZ ~ tzpattern) exit 1
|
||||
exit 0
|
||||
}'
|
||||
read tz
|
||||
$AWK "$check_POSIX_TZ_string" ="$tz"
|
||||
do
|
||||
say >&2 "'$TZ' is not a conforming Posix timezone string."
|
||||
say >&2 "'$tz' is not a conforming POSIX.1-2017 timezone string."
|
||||
done
|
||||
TZ_for_date=$TZ;;
|
||||
TZ_for_date=$tz;;
|
||||
*)
|
||||
case $continent in
|
||||
coord)
|
||||
@ -446,105 +505,156 @@ while
|
||||
echo >&2 'For example, +4042-07403 stands for'
|
||||
echo >&2 '40 degrees 42 minutes north,' \
|
||||
'74 degrees 3 minutes west.'
|
||||
read coord;;
|
||||
read coord
|
||||
esac
|
||||
distance_table=`$AWK \
|
||||
-v coord="$coord" \
|
||||
-v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \
|
||||
"$output_distances_or_times" <"$TZ_ZONE_TABLE" |
|
||||
distance_table=`
|
||||
$AWK \
|
||||
"$output_distances_or_times" \
|
||||
="$coord" ="$TZ_COUNTRY_TABLE" ="$TZ_ZONE_TABLE" |
|
||||
sort -n |
|
||||
sed "${location_limit}q"
|
||||
$AWK "{print} NR == $location_limit { exit }"
|
||||
`
|
||||
regions=`$AWK \
|
||||
-v distance_table="$distance_table" '
|
||||
regions=`
|
||||
$AWK '
|
||||
BEGIN {
|
||||
distance_table = substr(ARGV[1], 2)
|
||||
ARGV[1] = ""
|
||||
nlines = split(distance_table, line, /\n/)
|
||||
for (nr = 1; nr <= nlines; nr++) {
|
||||
nf = split(line[nr], f, /\t/)
|
||||
print f[nf]
|
||||
}
|
||||
}
|
||||
'`
|
||||
' ="$distance_table"
|
||||
`
|
||||
echo >&2 'Please select one of the following timezones,'
|
||||
echo >&2 'listed roughly in increasing order' \
|
||||
"of distance from $coord".
|
||||
doselect $regions
|
||||
region=$select_result
|
||||
TZ=`$AWK \
|
||||
-v distance_table="$distance_table" \
|
||||
-v region="$region" '
|
||||
tz=`
|
||||
$AWK '
|
||||
BEGIN {
|
||||
distance_table = substr(ARGV[1], 2)
|
||||
region = substr(ARGV[2], 2)
|
||||
ARGV[1] = ARGV[2] = ""
|
||||
nlines = split(distance_table, line, /\n/)
|
||||
for (nr = 1; nr <= nlines; nr++) {
|
||||
nf = split(line[nr], f, /\t/)
|
||||
if (f[nf] == region) {
|
||||
if (f[nf] == region)
|
||||
print f[4]
|
||||
}
|
||||
}
|
||||
}
|
||||
'`
|
||||
;;
|
||||
' ="$distance_table" ="$region"
|
||||
`;;
|
||||
*)
|
||||
case $continent in
|
||||
time)
|
||||
now|time)
|
||||
minute_format='%a %b %d %H:%M'
|
||||
old_minute=`TZ=UTC0 date +"$minute_format"`
|
||||
for i in 1 2 3
|
||||
do
|
||||
time_table_command=`
|
||||
$AWK -v output_times=1 \
|
||||
"$output_distances_or_times" <"$TZ_ZONE_TABLE"
|
||||
$AWK \
|
||||
-v output_times=1 \
|
||||
"$output_distances_or_times" \
|
||||
= = ="$TZ_ZONE_TABLE"
|
||||
`
|
||||
time_table=`eval "$time_table_command"`
|
||||
new_minute=`TZ=UTC0 date +"$minute_format"`
|
||||
case $old_minute in
|
||||
"$new_minute") break;;
|
||||
"$new_minute") break
|
||||
esac
|
||||
old_minute=$new_minute
|
||||
done
|
||||
echo >&2 "The system says Universal Time is $new_minute."
|
||||
echo >&2 "Assuming that's correct, what is the local time?"
|
||||
sorted_table=`say "$time_table" | sort -k2n -k2,5 -k1n` || {
|
||||
say >&2 "$0: cannot sort time table"
|
||||
exit 1
|
||||
}
|
||||
eval doselect `
|
||||
say "$time_table" |
|
||||
sort -k2n -k2,5 -k1n |
|
||||
$AWK '{
|
||||
line = $6 " " $7 " " $4 " " $5
|
||||
if (line == oldline) next
|
||||
oldline = line
|
||||
gsub(/'\''/, "&\\\\&&", line)
|
||||
printf "'\''%s'\''\n", line
|
||||
}'
|
||||
$AWK '
|
||||
BEGIN {
|
||||
sorted_table = substr(ARGV[1], 2)
|
||||
ARGV[1] = ""
|
||||
nlines = split(sorted_table, line, /\n/)
|
||||
for (i = 1; i <= nlines; i++) {
|
||||
$0 = line[i]
|
||||
outline = $6 " " $7 " " $4 " " $5
|
||||
if (outline == oldline)
|
||||
continue
|
||||
oldline = outline
|
||||
gsub(/'\''/, "&\\\\&&", outline)
|
||||
printf "'\''%s'\''\n", outline
|
||||
}
|
||||
}
|
||||
' ="$sorted_table"
|
||||
`
|
||||
time=$select_result
|
||||
continent_re='^'
|
||||
zone_table=`
|
||||
say "$time_table" |
|
||||
$AWK -v time="$time" '{
|
||||
$AWK '
|
||||
BEGIN {
|
||||
time = substr(ARGV[1], 2)
|
||||
time_table = substr(ARGV[2], 2)
|
||||
ARGV[1] = ARGV[2] = ""
|
||||
nlines = split(time_table, line, /\n/)
|
||||
for (i = 1; i <= nlines; i++) {
|
||||
$0 = line[i]
|
||||
if ($6 " " $7 " " $4 " " $5 == time) {
|
||||
sub(/[^\t]*\t/, "")
|
||||
print
|
||||
}
|
||||
}'
|
||||
}
|
||||
}
|
||||
' ="$time" ="$time_table"
|
||||
`
|
||||
countries=`
|
||||
say "$zone_table" |
|
||||
$AWK \
|
||||
-v continent_re='' \
|
||||
-v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \
|
||||
"$output_country_list" |
|
||||
"$output_country_list" \
|
||||
="$continent_re" ="$TZ_COUNTRY_TABLE" ="$zone_table" |
|
||||
sort -f
|
||||
`
|
||||
;;
|
||||
*)
|
||||
zone_table=file
|
||||
# Get list of names of countries in the continent or ocean.
|
||||
countries=`$AWK \
|
||||
-v continent_re="^$continent/" \
|
||||
-v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \
|
||||
"$output_country_list" \
|
||||
<"$TZ_ZONE_TABLE" | sort -f
|
||||
`;;
|
||||
continent_re="^$continent/"
|
||||
zone_table=$TZ_ZONE_TABLE
|
||||
esac
|
||||
|
||||
# Get list of names of countries in the continent or ocean.
|
||||
countries=`
|
||||
$AWK \
|
||||
"$output_country_list" \
|
||||
="$continent_re" ="$TZ_COUNTRY_TABLE" ="$zone_table" |
|
||||
sort -f
|
||||
`
|
||||
# If all zone table entries have comments, and there are
|
||||
# at most 22 entries, asked based on those comments.
|
||||
# This fits the prompt onto old-fashioned 24-line screens.
|
||||
regions=`
|
||||
$AWK '
|
||||
BEGIN {
|
||||
TZ_ZONE_TABLE = substr(ARGV[1], 2)
|
||||
ARGV[1] = ""
|
||||
FS = "\t"
|
||||
nlines = split(TZ_ZONE_TABLE, line, /\n/)
|
||||
for (i = 1; i <= nlines; i++) {
|
||||
$0 = line[i]
|
||||
if ($0 ~ /^[^#]/ && !missing_comment) {
|
||||
if ($4)
|
||||
comment[++inlines] = $4
|
||||
else
|
||||
missing_comment = 1
|
||||
}
|
||||
}
|
||||
if (!missing_comment && inlines <= 22)
|
||||
for (i = 1; i <= inlines; i++)
|
||||
print comment[i]
|
||||
}
|
||||
' ="$zone_table"
|
||||
`
|
||||
|
||||
# If there's more than one country, ask the user which one.
|
||||
case $countries in
|
||||
*"$newline"*)
|
||||
@ -560,30 +670,34 @@ while
|
||||
|
||||
# Get list of timezones in the country.
|
||||
regions=`
|
||||
case $zone_table in
|
||||
file) cat -- "$TZ_ZONE_TABLE";;
|
||||
*) say "$zone_table";;
|
||||
esac |
|
||||
$AWK \
|
||||
-v country="$country" \
|
||||
-v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \
|
||||
'
|
||||
$AWK '
|
||||
BEGIN {
|
||||
country = substr(ARGV[1], 2)
|
||||
TZ_COUNTRY_TABLE = substr(ARGV[2], 2)
|
||||
TZ_ZONE_TABLE = substr(ARGV[3], 2)
|
||||
ARGV[1] = ARGV[2] = ARGV[3] = ""
|
||||
FS = "\t"
|
||||
cc = country
|
||||
while (getline <TZ_COUNTRY_TABLE) {
|
||||
nlines = split(TZ_COUNTRY_TABLE, line, /\n/)
|
||||
for (i = 1; i <= nlines; i++) {
|
||||
$0 = line[i]
|
||||
if ($0 !~ /^#/ && country == $2) {
|
||||
cc = $1
|
||||
break
|
||||
}
|
||||
}
|
||||
nlines = split(TZ_ZONE_TABLE, line, /\n/)
|
||||
for (i = 1; i <= nlines; i++) {
|
||||
$0 = line[i]
|
||||
if ($0 ~ /^#/)
|
||||
continue
|
||||
if ($1 ~ cc)
|
||||
print $4
|
||||
}
|
||||
/^#/ { next }
|
||||
$1 ~ cc { print $4 }
|
||||
'
|
||||
}
|
||||
' ="$country" ="$TZ_COUNTRY_TABLE" ="$zone_table"
|
||||
`
|
||||
|
||||
|
||||
# If there's more than one region, ask the user which one.
|
||||
case $regions in
|
||||
*"$newline"*)
|
||||
@ -592,35 +706,40 @@ while
|
||||
region=$select_result
|
||||
esac
|
||||
|
||||
# Determine TZ from country and region.
|
||||
TZ=`
|
||||
case $zone_table in
|
||||
file) cat -- "$TZ_ZONE_TABLE";;
|
||||
*) say "$zone_table";;
|
||||
esac |
|
||||
$AWK \
|
||||
-v country="$country" \
|
||||
-v region="$region" \
|
||||
-v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \
|
||||
'
|
||||
# Determine tz from country and region.
|
||||
tz=`
|
||||
$AWK '
|
||||
BEGIN {
|
||||
country = substr(ARGV[1], 2)
|
||||
region = substr(ARGV[2], 2)
|
||||
TZ_COUNTRY_TABLE = substr(ARGV[3], 2)
|
||||
TZ_ZONE_TABLE = substr(ARGV[4], 2)
|
||||
ARGV[1] = ARGV[2] = ARGV[3] = ARGV[4] = ""
|
||||
FS = "\t"
|
||||
cc = country
|
||||
while (getline <TZ_COUNTRY_TABLE) {
|
||||
nlines = split(TZ_COUNTRY_TABLE, line, /\n/)
|
||||
for (i = 1; i <= nlines; i++) {
|
||||
$0 = line[i]
|
||||
if ($0 !~ /^#/ && country == $2) {
|
||||
cc = $1
|
||||
break
|
||||
}
|
||||
}
|
||||
nlines = split(TZ_ZONE_TABLE, line, /\n/)
|
||||
for (i = 1; i <= nlines; i++) {
|
||||
$0 = line[i]
|
||||
if ($0 ~ /^#/)
|
||||
continue
|
||||
if ($1 ~ cc && ($4 == region || !region))
|
||||
print $3
|
||||
}
|
||||
/^#/ { next }
|
||||
$1 ~ cc && ($4 == region || !region) { print $3 }
|
||||
'
|
||||
`;;
|
||||
}
|
||||
' ="$country" ="$region" ="$TZ_COUNTRY_TABLE" ="$zone_table"
|
||||
`
|
||||
esac
|
||||
|
||||
# Make sure the corresponding zoneinfo file exists.
|
||||
TZ_for_date=$TZDIR/$TZ
|
||||
TZ_for_date=$TZDIR/$tz
|
||||
<"$TZ_for_date" || {
|
||||
say >&2 "$0: time zone files are not set up correctly"
|
||||
exit 1
|
||||
@ -637,15 +756,18 @@ while
|
||||
do
|
||||
TZdate=`LANG=C TZ="$TZ_for_date" date`
|
||||
UTdate=`LANG=C TZ=UTC0 date`
|
||||
TZsec=`expr "$TZdate" : '.*:\([0-5][0-9]\)'`
|
||||
UTsec=`expr "$UTdate" : '.*:\([0-5][0-9]\)'`
|
||||
case $TZsec in
|
||||
$UTsec)
|
||||
if $AWK '
|
||||
function getsecs(d) {
|
||||
return match(d, /.*:[0-5][0-9]/) ? substr(d, RLENGTH - 1, 2) : ""
|
||||
}
|
||||
BEGIN { exit getsecs(ARGV[1]) != getsecs(ARGV[2]) }
|
||||
' ="$TZdate" ="$UTdate"
|
||||
then
|
||||
extra_info="
|
||||
Selected time is now: $TZdate.
|
||||
Universal Time is now: $UTdate."
|
||||
break
|
||||
esac
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
@ -663,10 +785,10 @@ Universal Time is now: $UTdate."
|
||||
%?*%%) say >&2 " $country_result";;
|
||||
%%?*%?*) say >&2 " coord $coord$newline $region";;
|
||||
%%%?*) say >&2 " coord $coord";;
|
||||
*) say >&2 " TZ='$TZ'"
|
||||
*) say >&2 " TZ='$tz'"
|
||||
esac
|
||||
say >&2 ""
|
||||
say >&2 "TZ='$TZ' will be used.$extra_info"
|
||||
say >&2 "TZ='$tz' will be used.$extra_info"
|
||||
say >&2 "Is the above information OK?"
|
||||
|
||||
doselect Yes No
|
||||
@ -678,8 +800,8 @@ do coord=
|
||||
done
|
||||
|
||||
case $SHELL in
|
||||
*csh) file=.login line="setenv TZ '$TZ'";;
|
||||
*) file=.profile line="TZ='$TZ'; export TZ"
|
||||
*csh) file=.login line="setenv TZ '$tz'";;
|
||||
*) file=.profile line="TZ='$tz'; export TZ"
|
||||
esac
|
||||
|
||||
test -t 1 && say >&2 "
|
||||
@ -690,4 +812,4 @@ to the file '$file' in your home directory; then log out and log in again.
|
||||
Here is that TZ value again, this time on standard output so that you
|
||||
can use the $0 command in shell scripts:"
|
||||
|
||||
say "$TZ"
|
||||
say "$tz"
|
||||
|
5
zdump.8
5
zdump.8
@ -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
|
||||
|
2
zdump.c
2
zdump.c
@ -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
83
zic.8
@ -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
|
||||
|
105
zic.8.txt
105
zic.8.txt
@ -52,14 +52,15 @@ OPTIONS
|
||||
|
||||
Link timezone posixrules
|
||||
|
||||
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
|
||||
range from lo (inclusive) to hi (exclusive), where lo and hi are
|
||||
@ -76,16 +77,16 @@ OPTIONS
|
||||
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.
|
||||
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
|
||||
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
|
||||
@ -119,11 +120,11 @@ OPTIONS
|
||||
|
||||
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.
|
||||
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
|
||||
@ -200,17 +201,15 @@ FILES
|
||||
|
||||
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.
|
||||
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
|
||||
@ -218,8 +217,8 @@ FILES
|
||||
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:
|
||||
@ -254,13 +253,13 @@ FILES
|
||||
- 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
|
||||
(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
|
||||
@ -269,18 +268,18 @@ FILES
|
||||
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
|
||||
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.
|
||||
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"
|
||||
@ -298,16 +297,15 @@ FILES
|
||||
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 "/".
|
||||
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
|
||||
@ -317,8 +315,7 @@ FILES
|
||||
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
|
||||
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,
|
||||
@ -336,10 +333,10 @@ FILES
|
||||
[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.
|
||||
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
|
||||
|
225
zic.c
225
zic.c
@ -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,14 +167,9 @@ 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);
|
||||
static int addtype(zic_t, char const *, bool, bool, bool);
|
||||
@ -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,7 +1080,8 @@ _("%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;
|
||||
}
|
||||
@ -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,14 +1884,12 @@ 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"),
|
||||
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"),
|
||||
error(_("\"Zone %s\" line and -p option are mutually exclusive"),
|
||||
TZDEFRULES);
|
||||
return false;
|
||||
}
|
||||
@ -1944,9 +1983,8 @@ 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"
|
||||
));
|
||||
error(_("Zone continuation line end time is"
|
||||
" not after end time of previous line"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user