Bump to tzdata 2016i 53/96153/3
authorDongHun Kwak <dh0128.kwak@samsung.com>
Tue, 8 Nov 2016 05:08:39 +0000 (14:08 +0900)
committerMyoungJune Park <mj2004.park@samsung.com>
Thu, 10 Nov 2016 08:09:48 +0000 (17:09 +0900)
[Model] ALL
[BinType] AP
[Customer] OPEN

[Issue#] N/A
[Request] N/A
[Occurrence Version] N/A

[Problem] Bump to tzdata 2016i
[Cause & Measure] Bump to tzdata 2016i
[Checking Method] N/A

[Team] Open Source Management and Setting Part
[Developer] dh0128.kwak
[Solution company] Samsung
[Change Type] N/A

Change-Id: Ie1262517e06eb1208f7f3a27b7e0bafec2d6d370
Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
Signed-off-by: MyoungJune Park <mj2004.park@samsung.com>
32 files changed:
Makefile
NEWS
README
Theory
africa
antarctica
asia
australasia
backward
backzone
date.c
etcetera
europe
leap-seconds.list
leapseconds
localtime.c
newtzset.3
newtzset.3.txt
northamerica
packaging/tzdata.spec
private.h
southamerica
strftime.c
tz-art.htm
tz-link.htm
tzfile.5
tzfile.5.txt
zdump.8
zdump.8.txt
zdump.c
zic.c
zone1970.tab

index bbe1ba8..03b3657 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -4,8 +4,8 @@
 # Package name for the code distribution.
 PACKAGE=       tzcode
 
-# Version numbers of the code and data distributions.
-VERSION=       2016f
+# Version number for the distribution, overridden in the 'tarballs' rule below.
+VERSION=       2016i
 
 # Email address for bug reports.
 BUGEMAIL=      tz@iana.org
@@ -101,7 +101,6 @@ PACKRATDATA=
 YEARISTYPE=    ./yearistype
 
 # Non-default libraries needed to link.
-# Add -lintl if you want to use 'gettext' on Solaris.
 LDLIBS=
 
 # Add the following to the end of the "CFLAGS=" line as needed.
@@ -109,9 +108,10 @@ LDLIBS=
 #  -DHAVE_DECL_ASCTIME_R=0 if <time.h> does not declare asctime_r
 #  -DHAVE_DIRECT_H if mkdir needs <direct.h> (MS-Windows)
 #  -DHAVE_DOS_FILE_NAMES if file names have drive specifiers etc. (MS-DOS)
-#  -DHAVE_GETTEXT=1 if 'gettext' works (GNU, Linux, Solaris); also see LDLIBS
+#  -DHAVE_GETTEXT=1 if 'gettext' works (e.g., GNU/Linux, FreeBSD, Solaris)
 #  -DHAVE_INCOMPATIBLE_CTIME_R=1 if your system's time.h declares
-#      ctime_r and asctime_r incompatibly with the POSIX standard (Solaris 8).
+#      ctime_r and asctime_r incompatibly with the POSIX standard
+#      (Solaris when _POSIX_PTHREAD_SEMANTICS is not defined).
 #  -DHAVE_INTTYPES_H=1 if you have a pre-C99 compiler with "inttypes.h"
 #  -DHAVE_LINK=0 if your system lacks a link function
 #  -DHAVE_LOCALTIME_R=0 if your system lacks a localtime_r function
@@ -129,6 +129,10 @@ LDLIBS=
 #  -DHAVE_SYS_WAIT_H=0 if your compiler lacks a "sys/wait.h"
 #  -DHAVE_TZSET=0 if your system lacks a tzset function
 #  -DHAVE_UNISTD_H=0 if your compiler lacks a "unistd.h" (Microsoft C++ 7?)
+#  -DEPOCH_LOCAL=1 if the 'time' function returns local time not UT
+#  -DEPOCH_OFFSET=N if the 'time' function returns a value N greater
+#      than what POSIX specifies, assuming local time is UT.
+#      For example, N is 252460800 on AmigaOS.
 #  -DNO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU=1
 #      if you do not want run time warnings about formats that may cause
 #      year 2000 grief
@@ -240,7 +244,7 @@ GCC_DEBUG_FLAGS = -Dlint -g3 -O3 -fno-common -fstrict-aliasing \
 CFLAGS=
 
 # Linker flags.  Default to $(LFLAGS) for backwards compatibility
-# to tzcode2012h and earlier.
+# to release 2012h and earlier.
 
 LDFLAGS=       $(LFLAGS)
 
@@ -256,7 +260,7 @@ ZIC=                $(zic) $(ZFLAGS)
 
 ZFLAGS=
 
-# How to use zic to install tzdata binary files.
+# How to use zic to install tz binary files.
 
 ZIC_INSTALL=   $(ZIC) -y $(YEARISTYPE) -d $(DESTDIR)$(TZDIR) $(LEAPSECONDS)
 
@@ -272,16 +276,16 @@ AWK=              awk
 KSHELL=                /bin/bash
 
 # The path where SGML DTDs are kept and the catalog file(s) to use when
-# validating.  The default is appropriate for Ubuntu 13.10.
+# validating.  The default should work on both Debian and Red Hat.
 SGML_TOPDIR= /usr
 SGML_DTDDIR= $(SGML_TOPDIR)/share/xml/w3c-sgml-lib/schema/dtd
 SGML_SEARCH_PATH= $(SGML_DTDDIR)/REC-html401-19991224
 SGML_CATALOG_FILES= \
-  $(SGML_TOPDIR)/share/doc/w3-recs/html/www.w3.org/TR/1999/REC-html401-19991224/HTML4.cat
+  $(SGML_TOPDIR)/share/doc/w3-recs/html/www.w3.org/TR/1999/REC-html401-19991224/HTML4.cat:$(SGML_TOPDIR)/share/sgml/html/4.01/HTML4.cat
 
 # The name, arguments and environment of a program to validate your web pages.
-# See <http://www.jclark.com/sp/> for a validator, and
-# <http://validator.w3.org/source/> for a validation library.
+# See <http://openjade.sourceforge.net/doc/> for a validator, and
+# <https://validator.w3.org/source/> for a validation library.
 VALIDATE = nsgmls
 VALIDATE_FLAGS = -s -B -wall -wno-unused-param
 VALIDATE_ENV = \
@@ -326,7 +330,7 @@ OK_LINE=    '^'$(OK_CHAR)'*$$'
 
 # Flags to give 'tar' when making a distribution.
 # Try to use flags appropriate for GNU tar.
-GNUTARFLAGS=   --numeric-owner --owner=0 --group=0 --mode=go+u,go-w
+GNUTARFLAGS= --numeric-owner --owner=0 --group=0 --mode=go+u,go-w --sort=name
 TARFLAGS=      `if tar $(GNUTARFLAGS) --version >/dev/null 2>&1; \
                 then echo $(GNUTARFLAGS); \
                 else :; \
@@ -363,7 +367,7 @@ MANTXTS=    newctime.3.txt newstrftime.3.txt newtzset.3.txt \
                        time2posix.3.txt \
                        tzfile.5.txt tzselect.8.txt zic.8.txt zdump.8.txt \
                        date.1.txt
-COMMON=                CONTRIBUTING LICENSE Makefile NEWS README Theory
+COMMON=                CONTRIBUTING LICENSE Makefile NEWS README Theory version
 WEB_PAGES=     tz-art.htm tz-how-to.html tz-link.htm
 DOCS=          $(MANS) date.1 $(MANTXTS) $(WEB_PAGES)
 PRIMARY_YDATA= africa antarctica asia australasia \
@@ -378,7 +382,32 @@ DATA=              $(YDATA) $(NDATA) backzone $(TABDATA) \
                        leap-seconds.list yearistype.sh
 AWK_SCRIPTS=   checklinks.awk checktab.awk leapseconds.awk
 MISC=          $(AWK_SCRIPTS) zoneinfo2tdf.pl
-ENCHILADA=     $(COMMON) $(DOCS) $(SOURCES) $(DATA) $(MISC)
+TZS_YEAR=      2050
+TZS=           to$(TZS_YEAR).tzs
+TZS_NEW=       to$(TZS_YEAR)new.tzs
+TZS_DEPS=      $(PRIMARY_YDATA) asctime.c localtime.c \
+                       private.h tzfile.h zdump.c zic.c
+ENCHILADA=     $(COMMON) $(DOCS) $(SOURCES) $(DATA) $(MISC) $(TZS)
+
+# Consult these files when deciding whether to rebuild the 'version' file.
+# This list is not the same as the output of 'git ls-files', since
+# .gitignore is not distributed.
+VERSION_DEPS= \
+               CONTRIBUTING LICENSE Makefile NEWS README Theory \
+               africa antarctica asctime.c asia australasia \
+               backward backzone \
+               checklinks.awk checktab.awk \
+               date.1 date.c difftime.c \
+               etcetera europe factory iso3166.tab \
+               leap-seconds.list leapseconds.awk localtime.c \
+               newctime.3 newstrftime.3 newtzset.3 northamerica \
+               pacificnew private.h \
+               southamerica strftime.c systemv \
+               time2posix.3 tz-art.htm tz-how-to.html tz-link.htm \
+               tzfile.5 tzfile.h tzselect.8 tzselect.ksh \
+               workman.sh yearistype.sh \
+               zdump.8 zdump.c zic.8 zic.c \
+               zone.tab zone1970.tab zoneinfo2tdf.pl
 
 # And for the benefit of csh users on systems that assume the user
 # shell should be used to handle commands in Makefiles. . .
@@ -408,10 +437,21 @@ INSTALL:  ALL install date.1
                cp date $(DESTDIR)$(BINDIR)/.
                cp -f date.1 $(DESTDIR)$(MANDIR)/man1/.
 
-version.h:
-               (echo 'static char const PKGVERSION[]="($(PACKAGE)) ";' && \
-                echo 'static char const TZVERSION[]="$(VERSION)";' && \
-                echo 'static char const REPORT_BUGS_TO[]="$(BUGEMAIL)";') >$@
+version:       $(VERSION_DEPS)
+               { (type git) >/dev/null 2>&1 && \
+                 V=`git describe --match '[0-9][0-9][0-9][0-9][a-z]*' \
+                               --abbrev=7 --dirty` || \
+                 V=$(VERSION); } && \
+               printf '%s\n' "$$V" >$@.out
+               mv $@.out $@
+
+version.h:     version
+               VERSION=`cat version` && printf '%s\n' \
+                 'static char const PKGVERSION[]="($(PACKAGE)) ";' \
+                 "static char const TZVERSION[]=\"$$VERSION\";" \
+                 'static char const REPORT_BUGS_TO[]="$(BUGEMAIL)";' \
+                 >$@.out
+               mv $@.out $@
 
 zdump:         $(TZDOBJS)
                $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $(TZDOBJS) $(LDLIBS)
@@ -424,7 +464,8 @@ yearistype: yearistype.sh
                chmod +x yearistype
 
 leapseconds:   $(LEAP_DEPS)
-               $(AWK) -f leapseconds.awk leap-seconds.list >$@
+               $(AWK) -f leapseconds.awk leap-seconds.list >$@.out
+               mv $@.out $@
 
 # Arguments to pass to submakes of install_data.
 # They can be overridden by later submake arguments.
@@ -477,6 +518,29 @@ posix_packrat:
 
 zones:         $(REDO)
 
+$(TZS_NEW):    $(TDATA) zdump zic
+               mkdir -p tzs.dir
+               $(zic) -d tzs.dir $(TDATA)
+               $(AWK) '/^Link/{print $$1 "\t" $$2 "\t" $$3}' \
+                  $(TDATA) | LC_ALL=C sort >$@.out
+               wd=`pwd` && \
+               zones=`$(AWK) -v wd="$$wd" \
+                               '/^Zone/{print wd "/tzs.dir/" $$2}' $(TDATA) \
+                        | LC_ALL=C sort` && \
+               ./zdump -i -c $(TZS_YEAR) $$zones >>$@.out
+               sed 's,^TZ=".*tzs\.dir/,TZ=",' $@.out >$@.sed.out
+               rm -fr tzs.dir $@.out
+               mv $@.sed.out $@
+
+# If $(TZS) does not already exist (e.g., old-format tarballs), create it.
+# If it exists but 'make check_tzs' fails, a maintainer should inspect the
+# failed output and fix the inconsistency, perhaps by running 'make force_tzs'.
+$(TZS):
+               $(MAKE) force_tzs
+
+force_tzs:     $(TZS_NEW)
+               cp $(TZS_NEW) $(TZS)
+
 libtz.a:       $(LIBOBJS)
                $(AR) ru $@ $(LIBOBJS)
                $(RANLIB) $@
@@ -484,31 +548,34 @@ libtz.a:  $(LIBOBJS)
 date:          $(DATEOBJS)
                $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $(DATEOBJS) $(LDLIBS)
 
-tzselect:      tzselect.ksh
-               sed \
+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)|' \
-                       <$? >$@
-               chmod +x $@
+                       -e 's|\(TZVERSION\)=.*|\1='"$$VERSION"'|' \
+                       <$@.ksh >$@.out
+               chmod +x $@.out
+               mv $@.out $@
 
 check:         check_character_set check_white_space check_links check_sorted \
-                 check_tables check_web
+                 check_tables check_tzs check_web
 
 check_character_set: $(ENCHILADA)
                LC_ALL=en_US.utf8 && export LC_ALL && \
                sharp='#' && \
-               ! grep -Env $(SAFE_LINE) Makefile $(MANS) date.1 $(MANTXTS) \
-                       $(MISC) $(SOURCES) $(WEB_PAGES) && \
+               ! grep -Env $(SAFE_LINE) $(MANS) date.1 $(MANTXTS) \
+                       $(MISC) $(SOURCES) $(WEB_PAGES) \
+                       CONTRIBUTING LICENSE Makefile README version && \
                ! grep -Env $(SAFE_SHARP_LINE) $(TDATA) backzone \
                        leapseconds yearistype.sh zone.tab && \
                ! grep -Env $(OK_LINE) $(ENCHILADA)
 
 check_white_space: $(ENCHILADA)
-               ! grep -En ' '$(TAB_CHAR)"|$$(printf '[\f\r\v]')" $(ENCHILADA)
+               patfmt=' \t|[\f\r\v]' && pat=`printf "$$patfmt\\n"` && \
+               ! grep -En "$$pat" $(ENCHILADA)
                ! grep -n '[[:space:]]$$' $(ENCHILADA)
 
 CHECK_CC_LIST = { n = split($$1,a,/,/); for (i=2; i<=n; i++) print a[1], a[i]; }
@@ -532,6 +599,9 @@ check_tables:       checktab.awk $(PRIMARY_YDATA) $(ZONETABLES)
                    || exit; \
                done
 
+check_tzs:     $(TZS) $(TZS_NEW)
+               diff -u $(TZS) $(TZS_NEW)
+
 check_web:     $(WEB_PAGES)
                $(VALIDATE_ENV) $(VALIDATE) $(VALIDATE_FLAGS) $(WEB_PAGES)
 
@@ -539,12 +609,12 @@ clean_misc:
                rm -f core *.o *.out \
                  date tzselect version.h zdump zic yearistype libtz.a
 clean:         clean_misc
-               rm -fr tzpublic
+               rm -fr *.dir tzdb-*/ $(TZS_NEW)
 
 maintainer-clean: clean
                @echo 'This command is intended for maintainers to use; it'
                @echo 'deletes files that may need special tools to rebuild.'
-               rm -f leapseconds $(MANTXTS) *.asc *.tar.gz
+               rm -f leapseconds version $(MANTXTS) $(TZS) *.asc *.tar.*
 
 names:
                @echo $(ENCHILADA)
@@ -563,7 +633,8 @@ zdump.8.txt:        zdump.8
 zic.8.txt:     zic.8
 
 $(MANTXTS):    workman.sh
-               LC_ALL=C sh workman.sh `expr $@ : '\(.*\)\.txt$$'` >$@
+               LC_ALL=C sh workman.sh `expr $@ : '\(.*\)\.txt$$'` >$@.out
+               mv $@.out $@
 
 # Set the time stamps to those of the git repository, if available,
 # and if the files have not changed since then.
@@ -574,7 +645,8 @@ $(MANTXTS): workman.sh
 # to be the maximum of the files it depends on.
 set-timestamps.out: $(ENCHILADA)
                rm -f $@
-               if files=`git ls-files $(ENCHILADA)` && \
+               if (type git) >/dev/null 2>&1 && \
+                  files=`git ls-files $(ENCHILADA)` && \
                   touch -md @1 test.out; then \
                  rm -f test.out && \
                  for file in $$files; do \
@@ -591,6 +663,8 @@ set-timestamps.out: $(ENCHILADA)
                  touch -cmr `ls -t $$file workman.sh | sed 1q` $$file.txt || \
                    exit; \
                done
+               touch -cmr `ls -t $(TZS_DEPS) | sed 1q` $(TZS)
+               touch -cmr `ls -t $(VERSION_DEPS) | sed 1q` version
                touch $@
 
 # The zics below ensure that each data file can stand on its own.
@@ -599,12 +673,12 @@ set-timestamps.out: $(ENCHILADA)
 check_public:
                $(MAKE) maintainer-clean
                $(MAKE) "CFLAGS=$(GCC_DEBUG_FLAGS)" ALL
-               mkdir tzpublic
+               mkdir -p public.dir
                for i in $(TDATA) ; do \
-                 $(zic) -v -d tzpublic $$i 2>&1 || exit; \
+                 $(zic) -v -d public.dir $$i 2>&1 || exit; \
                done
-               $(zic) -v -d tzpublic $(TDATA)
-               rm -fr tzpublic
+               $(zic) -v -d public.dir $(TDATA)
+               rm -fr public.dir
 
 # Check that the code works under various alternative
 # implementations of time_t.
@@ -614,17 +688,18 @@ check_time_t_alternatives:
                else \
                  quiet_option=''; \
                fi && \
+               wd=`pwd` && \
                zones=`$(AWK) '/^[^#]/ { print $$3 }' <zone1970.tab` && \
                for type in $(TIME_T_ALTERNATIVES); do \
-                 mkdir -p tzpublic/$$type && \
+                 mkdir -p time_t.dir/$$type && \
                  $(MAKE) clean_misc && \
-                 $(MAKE) TOPDIR=`pwd`/tzpublic/$$type \
+                 $(MAKE) TOPDIR="$$wd/time_t.dir/$$type" \
                    CFLAGS='$(CFLAGS) -Dtime_tz='"'$$type'" \
                    REDO='$(REDO)' \
                    install && \
                  diff $$quiet_option -r \
-                   tzpublic/int64_t/etc/zoneinfo \
-                   tzpublic/$$type/etc/zoneinfo && \
+                   time_t.dir/int64_t/etc/zoneinfo \
+                   time_t.dir/$$type/etc/zoneinfo && \
                  case $$type in \
                  int32_t) range=-2147483648,2147483647;; \
                  uint32_t) range=0,4294967296;; \
@@ -633,29 +708,47 @@ check_time_t_alternatives:
                  *) range=-10000000000,10000000000;; \
                  esac && \
                  echo checking $$type zones ... && \
-                 tzpublic/int64_t/etc/zdump -V -t $$range $$zones \
-                     >tzpublic/int64_t.out && \
-                 tzpublic/$$type/etc/zdump -V -t $$range $$zones \
-                     >tzpublic/$$type.out && \
-                 diff -u tzpublic/int64_t.out tzpublic/$$type.out \
+                 time_t.dir/int64_t/etc/zdump -V -t $$range $$zones \
+                     >time_t.dir/int64_t.out && \
+                 time_t.dir/$$type/etc/zdump -V -t $$range $$zones \
+                     >time_t.dir/$$type.out && \
+                 diff -u time_t.dir/int64_t.out time_t.dir/$$type.out \
                    || exit; \
                done
-               rm -fr tzpublic
+               rm -fr time_t.dir
 
-tarballs:      tzcode$(VERSION).tar.gz tzdata$(VERSION).tar.gz
+tarballs traditional_tarballs signatures traditional_signatures: version
+               VERSION=`cat version` && \
+               $(MAKE) VERSION="$$VERSION" $@_version
+
+tarballs_version: traditional_tarballs_version tzdb-$(VERSION).tar.lz
+traditional_tarballs_version: \
+  tzcode$(VERSION).tar.gz tzdata$(VERSION).tar.gz
+signatures_version: traditional_signatures_version tzdb-$(VERSION).tar.lz.asc
+traditional_signatures_version: \
+  tzcode$(VERSION).tar.gz.asc tzdata$(VERSION).tar.gz.asc \
 
 tzcode$(VERSION).tar.gz: set-timestamps.out
                LC_ALL=C && export LC_ALL && \
                tar $(TARFLAGS) -cf - \
                    $(COMMON) $(DOCS) $(SOURCES) | \
-                 gzip $(GZIPFLAGS) > $@
+                 gzip $(GZIPFLAGS) >$@.out
+               mv $@.out $@
 
 tzdata$(VERSION).tar.gz: set-timestamps.out
                LC_ALL=C && export LC_ALL && \
                tar $(TARFLAGS) -cf - $(COMMON) $(DATA) $(MISC) | \
-                 gzip $(GZIPFLAGS) > $@
-
-signatures:    tzcode$(VERSION).tar.gz.asc tzdata$(VERSION).tar.gz.asc
+                 gzip $(GZIPFLAGS) >$@.out
+               mv $@.out $@
+
+tzdb-$(VERSION).tar.lz: set-timestamps.out
+               rm -fr tzdb-$(VERSION)
+               mkdir tzdb-$(VERSION)
+               ln $(ENCHILADA) tzdb-$(VERSION)
+               touch -cmr `ls -t tzdb-$(VERSION)/* | sed 1q` tzdb-$(VERSION)
+               LC_ALL=C && export LC_ALL && \
+               tar $(TARFLAGS) -cf - tzdb-$(VERSION) | lzip -9 >$@.out
+               mv $@.out $@
 
 tzcode$(VERSION).tar.gz.asc: tzcode$(VERSION).tar.gz
                gpg --armor --detach-sign $?
@@ -663,6 +756,9 @@ tzcode$(VERSION).tar.gz.asc: tzcode$(VERSION).tar.gz
 tzdata$(VERSION).tar.gz.asc: tzdata$(VERSION).tar.gz
                gpg --armor --detach-sign $?
 
+tzdb-$(VERSION).tar.lz.asc: tzdb-$(VERSION).tar.lz
+               gpg --armor --detach-sign $?
+
 typecheck:
                $(MAKE) clean
                for i in "long long" unsigned; \
@@ -688,8 +784,10 @@ zic.o:             private.h tzfile.h version.h
 .PHONY: ALL INSTALL all
 .PHONY: check check_character_set check_links
 .PHONY: check_public check_sorted check_tables
-.PHONY: check_time_t_alternatives check_web check_white_space clean clean_misc
+.PHONY: check_time_t_alternatives check_tzs check_web check_white_space
+.PHONY: clean clean_misc force_tzs
 .PHONY: install install_data maintainer-clean names
 .PHONY: posix_only posix_packrat posix_right
-.PHONY: public right_only right_posix signatures tarballs typecheck
+.PHONY: public right_only right_posix signatures signatures_version
+.PHONY: tarballs tarballs_version typecheck
 .PHONY: zonenames zones
diff --git a/NEWS b/NEWS
index f59583f..da5c2a5 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,245 @@
 News for the tz database
 
+Release 2016i - 2016-11-01 23:19:52 -0700
+
+  Briefly: Cyprus split into two time zones on 2016-10-30, and Tonga
+  reintroduces DST on 2016-11-06.
+
+  Changes to future time stamps
+
+    Pacific/Tongatapu begins DST on 2016-11-06 at 02:00, ending on
+    2017-01-15 at 03:00.  Assume future observances in Tonga will be
+    from the first Sunday in November through the third Sunday in
+    January, like Fiji.  (Thanks to Pulu ʻAnau.)  Switch to numeric
+    time zone abbreviations for this zone.
+
+  Changes to past and future time stamps
+
+    Northern Cyprus is now +03 year round, causing a split in Cyprus
+    time zones starting 2016-10-30 at 04:00.  This creates a zone
+    Asia/Famagusta.  (Thanks to Even Scharning and Matt Johnson.)
+
+    Antarctica/Casey switched from +08 to +11 on 2016-10-22.
+    (Thanks to Steffen Thorsen.)
+
+  Changes to past time stamps
+
+    Several corrections were made for pre-1975 time stamps in Italy.
+    These affect Europe/Malta, Europe/Rome, Europe/San_Marino, and
+    Europe/Vatican.
+
+    First, the 1893-11-01 00:00 transition in Italy used the new UT
+    offset (+01), not the old (+00:49:56).  (Thanks to Michael
+    Deckers.)
+
+    Second, rules for daylight saving in Italy were changed to agree
+    with Italy's National Institute of Metrological Research (INRiM)
+    except for 1944, as follows (thanks to Pierpaolo Bernardi, Brian
+    Inglis, and Michael Deckers):
+
+      The 1916-06-03 transition was at 24:00, not 00:00.
+
+      The 1916-10-01, 1919-10-05, and 1920-09-19 transitions were at
+      00:00, not 01:00.
+
+      The 1917-09-30 and 1918-10-06 transitions were at 24:00, not
+      01:00.
+
+      The 1944-09-17 transition was at 03:00, not 01:00.  This
+      particular change is taken from Italian law as INRiM's table,
+      (which says 02:00) appears to have a typo here.  Also, keep the
+      1944-04-03 transition for Europe/Rome, as Rome was controlled by
+      Germany then.
+
+      The 1967-1970 and 1972-1974 fallback transitions were at 01:00,
+      not 00:00.
+
+  Changes to code
+
+    The code should now be buildable on AmigaOS merely by setting the
+    appropriate Makefile variables.  (From a patch by Carsten Larsen.)
+
+
+Release 2016h - 2016-10-19 23:17:57 -0700
+
+  Changes to future time stamps
+
+    Asia/Gaza and Asia/Hebron end DST on 2016-10-29 at 01:00, not
+    2016-10-21 at 00:00.  (Thanks to Sharef Mustafa.)  Predict that
+    future fall transitions will be on the last Saturday of October
+    at 01:00, which is consistent with predicted spring transitions
+    on the last Saturday of March.  (Thanks to Tim Parenti.)
+
+  Changes to past time stamps
+
+    In Turkey, transitions in 1986-1990 were at 01:00 standard time
+    not at 02:00, and the spring 1994 transition was on March 20, not
+    March 27.  (Thanks to Kıvanç Yazan.)
+
+  Changes to past and future time zone abbreviations
+
+    Asia/Colombo now uses numeric time zone abbreviations like "+0530"
+    instead of alphabetic ones like "IST" and "LKT".  Various
+    English-language sources use "IST", "LKT" and "SLST", with no
+    working consensus.  (Usage of "SLST" mentioned by Sadika
+    Sumanapala.)
+
+  Changes to code
+
+    zic no longer mishandles relativizing file names when creating
+    symbolic links like /etc/localtime, when these symbolic links
+    are outside the usual directory hierarchy.  This fixes a bug
+    introduced in 2016g.  (Problem reported by Andreas Stieger.)
+
+  Changes to build procedure
+
+    New rules 'traditional_tarballs' and 'traditional_signatures' for
+    building just the traditional-format distribution.  (Requested by
+    Deborah Goldsmith.)
+
+    The file 'version' is now put into the tzdata tarball too.
+    (Requested by Howard Hinnant.)
+
+  Changes to documentation and commentary
+
+    The 'Theory' file now has a section on interface stability.
+    (Requested by Paul Koning.)  It also mentions features like
+    tm_zone and localtime_rz that have long been supported by the
+    reference code.
+
+    tz-link.htm has improved coverage of time zone boundaries suitable
+    for geolocation.  (Thanks to heads-ups from Evan Siroky and Matt
+    Johnson.)
+
+    The US commentary now mentions Allen and the "day of two noons".
+
+    The Fiji commentary mentions the government's 2016-10-03 press
+    release.  (Thanks to Raymond Kumar.)
+
+
+Release 2016g - 2016-09-13 08:56:38 -0700
+
+  Changes to future time stamps
+
+    Turkey switched from EET/EEST (+02/+03) to permanent +03,
+    effective 2016-09-07.  (Thanks to Burak AYDIN.)  Use "+03" rather
+    than an invented abbreviation for the new time.
+
+    New leap second 2016-12-31 23:59:60 UTC as per IERS Bulletin C 52.
+    (Thanks to Tim Parenti.)
+
+  Changes to past time stamps
+
+    For America/Los_Angeles, spring-forward transition times have been
+    corrected from 02:00 to 02:01 in 1948, and from 02:00 to 01:00 in
+    1950-1966.
+
+    For zones using Soviet time on 1919-07-01, transitions to UT-based
+    time were at 00:00 UT, not at 02:00 local time.  The affected
+    zones are Europe/Kirov, Europe/Moscow, Europe/Samara, and
+    Europe/Ulyanovsk.  (Thanks to Alexander Belopolsky.)
+
+  Changes to past and future time zone abbreviations
+
+    The Factory zone now uses the time zone abbreviation -00 instead
+    of a long English-language string, as -00 is now the normal way to
+    represent an undefined time zone.
+
+    Several zones in Antarctica and the former Soviet Union, along
+    with zones intended for ships at sea that cannot use POSIX TZ
+    strings, now use numeric time zone abbreviations instead of
+    invented or obsolete alphanumeric abbreviations.  The affected
+    zones are Antarctica/Casey, Antarctica/Davis,
+    Antarctica/DumontDUrville, Antarctica/Mawson, Antarctica/Rothera,
+    Antarctica/Syowa, Antarctica/Troll, Antarctica/Vostok,
+    Asia/Anadyr, Asia/Ashgabat, Asia/Baku, Asia/Bishkek, Asia/Chita,
+    Asia/Dushanbe, Asia/Irkutsk, Asia/Kamchatka, Asia/Khandyga,
+    Asia/Krasnoyarsk, Asia/Magadan, Asia/Omsk, Asia/Sakhalin,
+    Asia/Samarkand, Asia/Srednekolymsk, Asia/Tashkent, Asia/Tbilisi,
+    Asia/Ust-Nera, Asia/Vladivostok, Asia/Yakutsk, Asia/Yekaterinburg,
+    Asia/Yerevan, Etc/GMT-14, Etc/GMT-13, Etc/GMT-12, Etc/GMT-11,
+    Etc/GMT-10, Etc/GMT-9, Etc/GMT-8, Etc/GMT-7, Etc/GMT-6, Etc/GMT-5,
+    Etc/GMT-4, Etc/GMT-3, Etc/GMT-2, Etc/GMT-1, Etc/GMT+1, Etc/GMT+2,
+    Etc/GMT+3, Etc/GMT+4, Etc/GMT+5, Etc/GMT+6, Etc/GMT+7, Etc/GMT+8,
+    Etc/GMT+9, Etc/GMT+10, Etc/GMT+11, Etc/GMT+12, Europe/Kaliningrad,
+    Europe/Minsk, Europe/Samara, Europe/Volgograd, and
+    Indian/Kerguelen.  For Europe/Moscow the invented abbreviation MSM
+    was replaced by +05, whereas MSK and MSD were kept as they are not
+    our invention and are widely used.
+
+  Changes to zone names
+
+    Rename Asia/Rangoon to Asia/Yangon, with a backward compatibility link.
+    (Thanks to David Massoud.)
+
+  Changes to code
+
+    zic no longer generates binary files containing POSIX TZ-like
+    strings that disagree with the local time type after the last
+    explicit transition in the data.  This fixes a bug with
+    Africa/Casablanca and Africa/El_Aaiun in some year-2037 time
+    stamps on the reference platform.  (Thanks to Alexander Belopolsky
+    for reporting the bug and suggesting a way forward.)
+
+    If the installed localtime and/or posixrules files are symbolic
+    links, zic now keeps them symbolic links when updating them, for
+    compatibility with platforms like OpenSUSE where other programs
+    configure these files as symlinks.
+
+    zic now avoids hard linking to symbolic links, avoids some
+    unnecessary mkdir and stat system calls, and uses shorter file
+    names internally.
+
+    zdump has a new -i option to generate transitions in a
+    more-compact but still human-readable format.  This option is
+    experimental, and the output format may change in future versions.
+    (Thanks to Jon Skeet for suggesting that an option was needed,
+    and thanks to Tim Parenti and Chris Rovick for further comments.)
+
+  Changes to build procedure
+
+    An experimental distribution format is available, in addition
+    to the traditional format which will continue to be distributed.
+    The new format is a tarball tzdb-VERSION.tar.lz with signature
+    file tzdb-VERSION.tar.lz.asc.  It unpacks to a top-level directory
+    tzdb-VERSION containing the code and data of the traditional
+    two-tarball format, along with extra data that may be useful.
+    (Thanks to Antonio Diaz Diaz, Oscar van Vlijmen, and many others
+    for comments about the experimental format.)
+
+    The release version number is now more accurate in the usual case
+    where releases are built from a Git repository.  For example, if
+    23 commits and some working-file changes have been made since
+    release 2016g, the version number is now something like
+    '2016g-23-g50556e3-dirty' instead of the misleading '2016g'.
+    Official releases uses the same version number format as before,
+    e.g., '2016g'.  To support the more-accurate version number, its
+    specification has moved from a line in the Makefile to a new
+    source file 'version'.
+
+    The experimental distribution contains a file to2050.tzs that
+    contains what should be the output of 'zdump -i -c 2050' on
+    primary zones.  If this file is available, 'make check' now checks
+    that zdump generates this output.
+
+    'make check_web' now works on Fedora-like distributions.
+
+  Changes to documentation and commentary
+
+    tzfile.5 now documents the new restriction on POSIX TZ-like
+    strings that is now implemented by zic.
+
+    Comments now cite URLs for some 1917-1921 Russian DST decrees.
+    (Thanks to Alexander Belopolsky.)
+
+    tz-link.htm mentions JuliaTime (thanks to Curtis Vogt) and Time4J
+    (thanks to Meno Hochschild) and ThreeTen-Extra, and its
+    description of Java 8 has been brought up to date (thanks to
+    Stephen Colebourne).  Its description of local time on Mars has
+    been updated to match current practice, and URLs have been updated
+    and some obsolete ones removed.
+
+
 Release 2016f - 2016-07-05 16:26:51 +0200
 
   Changes affecting future time stamps
@@ -393,7 +633,7 @@ Release 2015d - 2015-04-24 08:09:46 -0700
 
   Changes affecting past time stamps
 
-    America/Whitehorse switched from UTC-9 to UTC-8 on 1967-05-28, not
+    America/Whitehorse switched from UT -09 to -08 on 1967-05-28, not
     1966-07-01.  Also, Yukon's time zone history is documented better.
     (Thanks to Brian Inglis and Dennis Ferguson.)
 
@@ -427,12 +667,12 @@ Release 2015c - 2015-04-11 08:55:55 -0700
 
       The 1918 transition was September 10, not September 1.
 
-      The UTC-4 time observed from 1932 to 1942 is now considered to be
-      standard time, not year-round DST.
+      The UT -04 time observed from 1932 to 1942 is now considered to
+      be standard time, not year-round DST.
 
-      Santiago observed DST (UTC-3) from 1946-07-15 through 1946-08-31,
-      then reverted to standard time, then switched its time zone to
-      UTC-5 on 1947-04-01.
+      Santiago observed DST (UT -03) from 1946-07-15 through
+      1946-08-31, then reverted to standard time, then switched to -05
+      on 1947-04-01.
 
       Assume transitions before 1968 were at 00:00, since we have no data
       saying otherwise.
@@ -561,7 +801,7 @@ Release 2014j - 2014-11-10 17:37:11 -0800
 
   Changes affecting current and future time stamps
 
-    Turks & Caicos' switch from US eastern time to UTC-4 year-round
+    Turks & Caicos' switch from US eastern time to UT -04 year-round
     did not occur on 2014-11-02 at 02:00.  It's currently scheduled
     for 2015-11-01 at 02:00.  (Thanks to Chris Walton.)
 
@@ -597,7 +837,7 @@ Release 2014i - 2014-10-21 22:04:57 -0700
     years will use a similar pattern.
 
     A new Zone Pacific/Bougainville, for the part of Papua New Guinea
-    that plans to switch from UTC+10 to UTC+11 on 2014-12-28 at 02:00.
+    that plans to switch from UT +10 to +11 on 2014-12-28 at 02:00.
     (Thanks to Kiley Walbom for the heads-up.)
 
   Changes affecting time zone abbreviations
@@ -607,8 +847,8 @@ Release 2014i - 2014-10-21 22:04:57 -0700
     to its more-traditional value MSK on 2014-10-26 at 01:00.
     (Thanks to Alexander Bokovoy for the heads-up about Belarus.)
 
-    The new abbreviation IDT stands for the pre-1976 use of UT+8 in
-    Indochina, to distinguish it better from ICT (UT+7).
+    The new abbreviation IDT stands for the pre-1976 use of UT +08 in
+    Indochina, to distinguish it better from ICT (+07).
 
   Changes affecting past time stamps
 
@@ -686,7 +926,7 @@ Release 2014h - 2014-09-25 18:59:03 -0700
     zdump -c no longer mishandles transitions near year boundaries.
     (Thanks to Tim Parenti for reporting the problem.)
 
-    An access to uninitalized data has been fixed.
+    An access to uninitialized data has been fixed.
     (Thanks to Jörg Richter for reporting the problem.)
 
     When THREAD_SAFE is defined, the code ports to the C11 memory model.
@@ -719,8 +959,8 @@ Release 2014g - 2014-08-28 12:31:23 -0700
 
   Changes affecting future time stamps
 
-    Turks & Caicos is switching from US eastern time to UTC-4 year-round,
-    modeled as a switch from EST/EDT to AST on 2014-11-02 at 02:00.
+    Turks & Caicos is switching from US eastern time to UT -04
+    year-round, modeled as a switch on 2014-11-02 at 02:00.
     [As noted in 2014j, this switch was later delayed.]
 
   Changes affecting past time stamps
@@ -903,7 +1143,7 @@ Release 2014f - 2014-08-05 17:42:36 -0700
     This change does not affect UTC offsets, only time zone abbreviations.
     (Thanks to Rich Tibbett and many others.)
 
-    Asia/Novokuznetsk shifts from NOVT to KRAT (remaining on UTC+7)
+    Asia/Novokuznetsk shifts from NOVT to KRAT (remaining on UT +07)
     effective 2014-10-26 at 02:00 local time.
 
     The time zone abbreviation for Xinjiang Time (observed in Ürümqi)
@@ -932,8 +1172,8 @@ Release 2014f - 2014-08-05 17:42:36 -0700
     zones Asia/Harbin, Asia/Chongqing, and Asia/Kashgar have been
     removed; backwards-compatibility links still work, albeit with
     different behaviors for time stamps before May 1980.  Asia/Urumqi's
-    1980 transition to UTC+8 has been removed, so that it is now at
-    UTC+6 and not UTC+8.  (Thanks to Luther Ma and to Alois Treindl;
+    1980 transition to UT +08 has been removed, so that it is now at
+    +06 and not +08.  (Thanks to Luther Ma and to Alois Treindl;
     Treindl sent helpful translations of two papers by Guo Qingsheng.)
 
     Some zones have been turned into links, when they differed from existing
@@ -963,8 +1203,8 @@ Release 2014f - 2014-08-05 17:42:36 -0700
     Europe/Helsinki's 1942 fall-back transition was 10-04 at 01:00, not
     10-03 at 00:00.  (Thanks to Konstantin Hyppönen.)
 
-    Pacific/Pago_Pago has been changed from UTC-11:30 to UTC-11 for the period
-    from 1911 to 1950.
+    Pacific/Pago_Pago has been changed from UT -11:30 to -11 for the
+    period from 1911 to 1950.
 
     Pacific/Chatham has been changed to New Zealand standard time plus
     45 minutes for the period before 1957, reflecting a 1956 remark in
@@ -1291,15 +1531,15 @@ Release 2013h - 2013-10-25 15:32:32 -0700
 
   Changes affecting current and future time stamps:
 
-    Libya has switched its time zone back to UTC+2 without DST,
-    instead of UTC+1 with DST.  (Thanks to Even Scharning.)
+    Libya has switched its UT offset back to +02 without DST, instead
+    of +01 with DST.  (Thanks to Even Scharning.)
 
     Western Sahara (Africa/El_Aaiun) uses Morocco's DST rules.
     (Thanks to Gwillim Law.)
 
   Changes affecting future time stamps:
 
-    Acre and (we guess) western Amazonas will switch from UTC-4 to UTC-5
+    Acre and (we guess) western Amazonas will switch from UT -04 to -05
     on 2013-11-10.  This affects America/Rio_Branco and America/Eirunepe.
     (Thanks to Steffen Thorsen.)
 
@@ -1386,7 +1626,7 @@ Release 2013f - 2013-09-24 23:37:36 -0700
     Tocantins will very likely not observe DST starting this spring.
     (Thanks to Steffen Thorsen.)
 
-    Jordan will likely stay at UTC+3 indefinitely, and will not fall
+    Jordan will likely stay at UT +03 indefinitely, and will not fall
     back this fall.
 
     Palestine will fall back at 00:00, not 01:00.  (Thanks to Steffen Thorsen.)
@@ -1443,7 +1683,7 @@ Release 2013e - 2013-09-19 23:50:04 -0700
     Benny Lin.)  This affects Asia/Dili, Asia/Jakarta, Asia/Jayapura,
     Asia/Makassar, and Asia/Pontianak.
 
-    Use ART (UTC-3, standard time), rather than WARST (also UTC-3, but
+    Use ART (UT -03, standard time), rather than WARST (also -03, but
     daylight saving time) for San Luis, Argentina since 2009.
 
   Changes affecting Godthåb time stamps after 2037 if version mismatch
@@ -1900,7 +2140,7 @@ Release 2012f - 2012-09-12 23:17:03 -0700
 
 Release 2012e - 2012-08-02 20:44:55 -0700
 
-  * australasia (Pacific/Fakaofo): Tokelau is UTC+13, not UTC+14.
+  * australasia (Pacific/Fakaofo): Tokelau is UT +13, not +14.
     (Thanks to Steffen Thorsen.)
 
   * Use a single version number for both code and data.
@@ -3519,14 +3759,15 @@ This file contains copies of the part of each release announcement
 that talks about the changes in that release.  The text has been
 adapted and reformatted for the purposes of this file.
 
-Typically a release R consists of a pair of tarball files,
+Traditionally a release R consists of a pair of tarball files,
 tzcodeR.tar.gz and tzdataR.tar.gz.  However, some releases (e.g.,
 code2010a, data2012c) consist of just one or the other tarball, and a
 few (e.g., code2012c-data2012d) have tarballs with mixed version
-numbers.
+numbers.  Recent releases also come in an experimental format
+consisting of a single tarball tzdb-R.tar.lz with extra data.
 
 Release time stamps are taken from the release's commit (for newer,
-git releases), from the newest file in the tarball (for older
+Git-based releases), from the newest file in the tarball (for older
 releases, where this info is available) or from the email announcing
 the release (if all else fails; these are marked with a time zone of
 -0000 and an "is missing!" comment).
diff --git a/README b/README
index 8deaf16..8a09aa2 100644 (file)
--- a/README
+++ b/README
@@ -13,12 +13,20 @@ and daylight-saving rules.
 Here is a recipe for acquiring, building, installing, and testing the
 tz distribution on a GNU/Linux or similar host.
 
+To acquire the distribution, run the following shell commands:
+
        mkdir tz
        cd tz
        wget --retr-symlinks 'ftp://ftp.iana.org/tz/tz*-latest.tar.gz'
        gzip -dc tzcode-latest.tar.gz | tar -xf -
        gzip -dc tzdata-latest.tar.gz | tar -xf -
 
+Alternatively, the following shell commands acquire the same
+distribution, with extra data useful for regression testing:
+
+       wget --retr-symlinks 'ftp://ftp.iana.org/tz/tzdb-latest.tar.lz'
+       lzip -dc tzdb-latest.tar.lz | tar -xf -
+
 Be sure to read the comments in "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,
diff --git a/Theory b/Theory
index 60678fe..677baf6 100644 (file)
--- a/Theory
+++ b/Theory
@@ -323,7 +323,7 @@ Errors in the tz database arise from many sources:
 
  * Sometimes historical timekeeping was specified more precisely
    than what the tz database can handle.  For example, from 1909 to
-   1937 Netherlands clocks were legally UT+00:19:32.13, but the tz
+   1937 Netherlands clocks were legally UT +00:19:32.13, but the tz
    database cannot represent the fractional second.
 
  * Even when all the timestamp transitions recorded by the tz database
@@ -445,6 +445,10 @@ POSIX has the following properties and limitations.
        rules change (as in the United States in 1987), all programs that
        do time conversion must be recompiled to ensure proper results.
 
+*      The TZ environment variable is process-global, which makes it hard
+       to write efficient, thread-safe applications that need access
+       to multiple time zones.
+
 *      In POSIX, there's no tamper-proof way for a process to learn the
        system's best idea of local wall clock.  (This is important for
        applications that an administrator wants used only at certain times -
@@ -454,6 +458,11 @@ POSIX has the following properties and limitations.
        daylight saving time shifts - as might be required to limit phone
        calls to off-peak hours.)
 
+*      POSIX provides no convenient and efficient way to determine the UT
+       offset and time zone abbreviation of arbitrary time stamps,
+       particularly for time zone settings that do not fit into the
+       POSIX model.
+
 *      POSIX requires that systems ignore leap seconds.
 
 *      The tz code attempts to support all the time_t implementations
@@ -494,20 +503,23 @@ These are the extensions that have been made to the POSIX functions:
        "new" programs (a la POSIX) and "old" programs (as zone names and
        offsets).
 
-*      To handle places where more than two time zone abbreviations are used,
-       the functions "localtime" and "gmtime" set tzname[tmp->tm_isdst]
-       (where "tmp" is the value the function returns) to the time zone
-       abbreviation to be used.  This differs from POSIX, where the elements
-       of tzname are only changed as a result of calls to tzset.
+*      The code supports platforms with a UT offset member in struct tm,
+       e.g., tm_gmtoff.
+
+*      The code supports platforms with a time zone abbreviation member in
+       struct tm, e.g., tm_zone.
 
 *      Since the "TZ" environment variable can now be used to control time
        conversion, the "daylight" and "timezone" variables are no longer
        needed.  (These variables are defined and set by "tzset"; however, their
        values will not be used by "localtime.")
 
-*      The "localtime" function has been set up to deliver correct results
-       for near-minimum or near-maximum time_t values.  (A comment in the
-       source code tells how to get compatibly wrong results).
+*      Functions tzalloc, tzfree, localtime_rz, and mktime_z for
+       more-efficient thread-safe applications that need to use
+       multiple time zones.  The tzalloc and tzfree functions
+       allocate and free objects of type timezone_t, and localtime_rz
+       and mktime_z are like localtime_r and mktime with an extra
+       timezone_t argument.  The functions were inspired by NetBSD.
 
 *      A function "tzsetwall" has been added to arrange for the system's
        best approximation to local wall clock time to be delivered by
@@ -526,14 +538,15 @@ These are the extensions that have been made to the POSIX functions:
 
 Points of interest to folks with other systems:
 
-*      This package is already part of many POSIX-compliant hosts,
-       including BSD, HP, Linux, Network Appliance, SCO, SGI, and Sun.
+*      Code compatible with this package is already part of many platforms,
+       including GNU/Linux, Android, the BSDs, Chromium OS, Cygwin, AIX, iOS,
+       BlackBery 10, macOS, Microsoft Windows, OpenVMS, and Solaris.
        On such hosts, the primary use of this package
        is to update obsolete time zone rule tables.
        To do this, you may need to compile the time zone compiler
        'zic' supplied with this package instead of using the system 'zic',
-       since the format of zic's input changed slightly in late 1994,
-       and many vendors still do not support the new input format.
+       since the format of zic's input is occasionally extended,
+       and a platform may still be shipping an older zic.
 
 *      The UNIX Version 7 "timezone" function is not present in this package;
        it's impossible to reliably map timezone's arguments (a "minutes west
@@ -551,6 +564,8 @@ Points of interest to folks with other systems:
 *      In SVR2, time conversion fails for near-minimum or near-maximum
        time_t values when doing conversions for places that don't use UT.
        This package takes care to do these conversions correctly.
+       A comment in the source code tells how to get compatibly wrong
+       results.
 
 The functions that are conditionally compiled if STD_INSPIRED is defined
 should, at this point, be looked on primarily as food for thought.  They are
@@ -568,6 +583,35 @@ more powerful time conversion functions can be standardized, so much the
 better.
 
 
+----- Interface stability -----
+
+The tz code and data supply the following interfaces:
+
+ * A set of zone names as per "Names of time zone rules" above.
+
+ * Library functions described in "Time and date functions" above.
+
+ * The programs tzselect, zdump, and zic, documented in their man pages.
+
+ * The format of zic input files, documented in the zic man page.
+
+ * The format of zic output files, documented in the tzfile man page.
+
+ * The format of zone table files, documented in zone1970.tab.
+
+ * The format of the country code file, documented in iso3166.tab.
+
+When these interfaces are changed, an effort is made to preserve
+backward compatibility.  For example, tz data files typically do not
+rely on recently-added zic features, so that users can run older zic
+versions to process newer data files.
+
+Interfaces not listed above are less stable.  For example, users
+should not rely on particular UT offsets or abbreviations for time
+stamps, as data entries are often based on guesswork and these guesses
+may be corrected or improved.
+
+
 ----- Calendrical issues -----
 
 Calendrical issues are a bit out of scope for a time zone database,
diff --git a/africa b/africa
index 50f29d5..d35aaa5 100644 (file)
--- a/africa
+++ b/africa
@@ -464,7 +464,7 @@ Zone        Africa/Monrovia -0:43:08 -      LMT     1882
 # http://www.libyaherald.com/2013/10/24/correction-no-time-change-tomorrow/
 #
 # From Paul Eggert (2013-10-25):
-# For now, assume they're reverting to the pre-2012 rules of permanent UTC+2.
+# For now, assume they're reverting to the pre-2012 rules of permanent UT +02.
 
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   Libya   1951    only    -       Oct     14      2:00    1:00    S
index 3466a50..6da1aef 100644 (file)
@@ -10,9 +10,7 @@
 # http://www.spri.cam.ac.uk/bob/periant.htm
 # for information.
 # Unless otherwise specified, we have no time zone information.
-#
-# Except for the French entries,
-# I made up all time zone abbreviations mentioned here; corrections welcome!
+
 # FORMAT is '-00' and GMTOFF is 0 for locations while uninhabited.
 
 # Argentina - year-round bases
@@ -29,7 +27,7 @@
 #      previously sealers and scientific personnel wintered
 #      Margaret Turner reports
 #      http://web.archive.org/web/20021204222245/http://www.dstc.qut.edu.au/DST/marg/daylight.html
-#      (1999-09-30) that they're UTC+5, with no DST;
+#      (1999-09-30) that they're UT +05, with no DST;
 #      presumably this is when they have visitors.
 #
 # year-round bases
 # Background:
 # http://www.timeanddate.com/news/time/antartica-time-changes-2010.html
 
+# From Steffen Thorsen (2016-10-28):
+# Australian Antarctica Division informed us that Casey changed time
+# zone to UTC+11 in "the morning of 22nd October 2016".
+
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone Antarctica/Casey  0       -       -00     1969
-                       8:00    -       AWST    2009 Oct 18  2:00
-                                               # Australian Western Std Time
-                       11:00   -       CAST    2010 Mar  5  2:00  # Casey Time
-                       8:00    -       AWST    2011 Oct 28  2:00
-                       11:00   -       CAST    2012 Feb 21 17:00u
-                       8:00    -       AWST
+                       8:00    -       +08     2009 Oct 18  2:00
+                       11:00   -       +11     2010 Mar  5  2:00
+                       8:00    -       +08     2011 Oct 28  2:00
+                       11:00   -       +11     2012 Feb 21 17:00u
+                       8:00    -       +08     2016 Oct 22
+                       11:00   -       +11
 Zone Antarctica/Davis  0       -       -00     1957 Jan 13
-                       7:00    -       DAVT    1964 Nov    # Davis Time
+                       7:00    -       +07     1964 Nov
                        0       -       -00     1969 Feb
-                       7:00    -       DAVT    2009 Oct 18  2:00
-                       5:00    -       DAVT    2010 Mar 10 20:00u
-                       7:00    -       DAVT    2011 Oct 28  2:00
-                       5:00    -       DAVT    2012 Feb 21 20:00u
-                       7:00    -       DAVT
+                       7:00    -       +07     2009 Oct 18  2:00
+                       5:00    -       +05     2010 Mar 10 20:00u
+                       7:00    -       +07     2011 Oct 28  2:00
+                       5:00    -       +05     2012 Feb 21 20:00u
+                       7:00    -       +07
 Zone Antarctica/Mawson 0       -       -00     1954 Feb 13
-                       6:00    -       MAWT    2009 Oct 18  2:00 # Mawson Time
-                       5:00    -       MAWT
+                       6:00    -       +06     2009 Oct 18  2:00
+                       5:00    -       +05
 # References:
 # Casey Weather (1998-02-26)
 # http://www.antdiv.gov.au/aad/exop/sfo/casey/casey_aws.html
@@ -138,7 +140,7 @@ Zone Antarctica/Mawson      0       -       -00     1954 Feb 13
 #
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone Indian/Kerguelen  0       -       -00     1950 # Port-aux-Français
-                       5:00    -       TFT     # ISO code TF Time
+                       5:00    -       +05
 #
 # year-round base in the main continent
 # Dumont d'Urville, Île des Pétrels, -6640+14001, since 1956-11
@@ -148,10 +150,10 @@ Zone Indian/Kerguelen     0       -       -00     1950 # Port-aux-Français
 # It was destroyed by fire on 1952-01-14.
 #
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
-Zone Antarctica/DumontDUrville 0 -     zzz     1947
-                       10:00   -       PMT     1952 Jan 14 # Port-Martin Time
-                       0       -       zzz     1956 Nov
-                       10:00   -       DDUT    # Dumont-d'Urville Time
+Zone Antarctica/DumontDUrville 0 -     -00     1947
+                       10:00   -       +10     1952 Jan 14
+                       0       -       -00     1956 Nov
+                       10:00   -       +10
 
 # France & Italy - year-round base
 # Concordia, -750600+1232000, since 2005
@@ -214,17 +216,17 @@ Zone Antarctica/Syowa     0       -       -00     1957 Jan 29
 # correct, but they should be quite close to the actual dates.
 #
 # From Paul Eggert (2014-03-21):
-# The CET-switching Troll rules require zic from tzcode 2014b or later, so as
+# The CET-switching Troll rules require zic from tz 2014b or later, so as
 # suggested by Bengt-Inge Larsson comment them out for now, and approximate
 # with only UTC and CEST.  Uncomment them when 2014b is more prevalent.
 #
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
-#Rule  Troll   2005    max     -       Mar      1      1:00u   1:00    CET
-Rule   Troll   2005    max     -       Mar     lastSun 1:00u   2:00    CEST
-#Rule  Troll   2005    max     -       Oct     lastSun 1:00u   1:00    CET
-#Rule  Troll   2004    max     -       Nov      7      1:00u   0:00    UTC
+#Rule  Troll   2005    max     -       Mar      1      1:00u   1:00    +01
+Rule   Troll   2005    max     -       Mar     lastSun 1:00u   2:00    +02
+#Rule  Troll   2005    max     -       Oct     lastSun 1:00u   1:00    +01
+#Rule  Troll   2004    max     -       Nov      7      1:00u   0:00    +00
 # Remove the following line when uncommenting the above '#Rule' lines.
-Rule   Troll   2004    max     -       Oct     lastSun 1:00u   0:00    UTC
+Rule   Troll   2004    max     -       Oct     lastSun 1:00u   0:00    +00
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone Antarctica/Troll  0       -       -00     2005 Feb 12
                        0:00    Troll   %s
diff --git a/asia b/asia
index c26d730..67164b3 100644 (file)
--- a/asia
+++ b/asia
@@ -116,13 +116,11 @@ Zone      Asia/Kabul      4:36:48 -       LMT     1890
 # http://www.worldtimezone.com/dst_news/dst_news_armenia03.html
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Asia/Yerevan    2:58:00 -       LMT     1924 May  2
-                       3:00    -       YERT    1957 Mar    # Yerevan Time
-                       4:00 RussiaAsia YER%sT  1991 Mar 31  2:00s
-                       3:00    1:00    YERST   1991 Sep 23 # independence
-                       3:00 RussiaAsia AM%sT   1995 Sep 24  2:00s
-                       4:00    -       AMT     1997
-                       4:00 RussiaAsia AM%sT   2012 Feb  9
-                       4:00    -       AMT
+                       3:00    -       +03     1957 Mar
+                       4:00 RussiaAsia +04/+05 1991 Mar 31  2:00s
+                       3:00 RussiaAsia +03/+04 1995 Sep 24  2:00s
+                       4:00    -       +04     1997
+                       4:00 RussiaAsia +04/+05
 
 # Azerbaijan
 
@@ -143,13 +141,12 @@ Rule      Azer    1997    2015    -       Mar     lastSun  4:00   1:00    S
 Rule   Azer    1997    2015    -       Oct     lastSun  5:00   0       -
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Asia/Baku       3:19:24 -       LMT     1924 May  2
-                       3:00    -       BAKT    1957 Mar    # Baku Time
-                       4:00 RussiaAsia BAK%sT  1991 Mar 31  2:00s
-                       3:00    1:00    BAKST   1991 Aug 30 # independence
-                       3:00 RussiaAsia AZ%sT   1992 Sep lastSun  2:00s
-                       4:00    -       AZT     1996     # Azerbaijan Time
-                       4:00    EUAsia  AZ%sT   1997
-                       4:00    Azer    AZ%sT
+                       3:00    -       +03     1957 Mar
+                       4:00 RussiaAsia +04/+05 1991 Mar 31  2:00s
+                       3:00 RussiaAsia +03/+04 1992 Sep lastSun  2:00s
+                       4:00    -       +04     1996
+                       4:00    EUAsia  +04/+05 1997
+                       4:00    Azer    +04/+05
 
 # Bahrain
 # See Asia/Qatar.
@@ -268,7 +265,7 @@ Zone        Asia/Brunei     7:39:40 -       LMT     1926 Mar # Bandar Seri Begawan
 # Milne says 6:24:40 was the meridian of the time ball observatory at Rangoon.
 
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
-Zone   Asia/Rangoon    6:24:40 -       LMT     1880        # or Yangon
+Zone   Asia/Yangon     6:24:40 -       LMT     1880        # or Rangoon
                        6:24:40 -       RMT     1920        # Rangoon Mean Time?
                        6:30    -       BURT    1942 May    # Burma Time
                        9:00    -       JST     1945 May  3
@@ -383,7 +380,7 @@ Rule        PRC     1987    1991    -       Apr     Sun>=10 0:00    1:00    D
 # Lewiston (ME) Daily Sun (1939-05-29), p 17, said "Even the time is
 # different - the occupied districts going by Tokyo time, an hour
 # ahead of that prevailing in the rest of Shanghai."  Guess that the
-# Xujiahui Observatory was under French control and stuck with UT+8.
+# Xujiahui Observatory was under French control and stuck with UT +08.
 #
 # In earlier versions of this file, China had many separate Zone entries, but
 # this was based on what were apparently incorrect data in Shanks & Pottenger.
@@ -392,26 +389,26 @@ Rule      PRC     1987    1991    -       Apr     Sun>=10 0:00    1:00    D
 # Proposed in 1918 and theoretically in effect until 1949 (although in practice
 # mainly observed in coastal areas), the five zones were:
 #
-# Changbai Time ("Long-white Time", Long-white = Heilongjiang area) UT+8.5
+# Changbai Time ("Long-white Time", Long-white = Heilongjiang area) UT +08:30
 # Asia/Harbin (currently a link to Asia/Shanghai)
 # Heilongjiang (except Mohe county), Jilin
 #
-# Zhongyuan Time ("Central plain Time") UT+8
+# Zhongyuan Time ("Central plain Time") UT +08
 # Asia/Shanghai
 # most of China
 # This currently represents most other zones as well,
 # as apparently these regions have been the same since 1970.
 # Milne gives 8:05:43.2 for Xujiahui Observatory time; round to nearest.
-# Guo says Shanghai switched to UT+8 "from the end of the 19th century".
+# Guo says Shanghai switched to UT +08 "from the end of the 19th century".
 #
-# Long-shu Time (probably due to Long and Shu being two names of that area) UT+7
+# Long-shu Time (probably due to Long and Shu being two names of the area) UT +07
 # Asia/Chongqing (currently a link to Asia/Shanghai)
 # Guangxi, Guizhou, Hainan, Ningxia, Sichuan, Shaanxi, and Yunnan;
 # most of Gansu; west Inner Mongolia; west Qinghai; and the Guangdong
 # counties Deqing, Enping, Kaiping, Luoding, Taishan, Xinxing,
 # Yangchun, Yangjiang, Yu'nan, and Yunfu.
 #
-# Xin-zang Time ("Xinjiang-Tibet Time") UT+6
+# Xin-zang Time ("Xinjiang-Tibet Time") UT +06
 # Asia/Urumqi
 # This currently represents Kunlun Time as well,
 # as apparently the two regions have been the same since 1970.
@@ -424,7 +421,7 @@ Rule        PRC     1987    1991    -       Apr     Sun>=10 0:00    1:00    D
 # Shihezi, Changji, Yanqi, Heshuo, Tuokexun, Tulufan, Shanshan, Hami,
 # Fukang, Kuitun, Kumukuli, Miquan, Qitai, and Turfan.
 #
-# Kunlun Time UT+5.5
+# Kunlun Time UT +05:30
 # Asia/Kashgar (currently a link to Asia/Urumqi)
 # West Tibet, including Pulan, Aheqi, Shufu, Shule;
 # West Xinjiang, including Aksu, Atushi, Yining, Hetian, Cele, Luopu, Nileke,
@@ -496,8 +493,8 @@ Rule        PRC     1987    1991    -       Apr     Sun>=10 0:00    1:00    D
 # having the same time as Beijing.
 
 # From Paul Eggert (2014-06-30):
-# In the early days of the PRC, Tibet was given its own time zone (UT+6) but
-# this was withdrawn in 1959 and never reinstated; see Tubten Khétsun,
+# In the early days of the PRC, Tibet was given its own time zone (UT +06)
+# but this was withdrawn in 1959 and never reinstated; see Tubten Khétsun,
 # Memories of life in Lhasa under Chinese Rule, Columbia U Press, ISBN
 # 978-0231142861 (2008), translator's introduction by Matthew Akester, p x.
 # As this is before our 1970 cutoff, Tibet doesn't need a separate zone.
@@ -511,12 +508,12 @@ Rule      PRC     1987    1991    -       Apr     Sun>=10 0:00    1:00    D
 # Republics, the Soviet Union, the Kuomintang, and the People's Republic of
 # China, and tracking down all these organizations' timekeeping rules would be
 # quite a trick.  Approximate this lost history by a transition from LMT to
-# XJT at the start of 1928, the year of accession of the warlord Jin Shuren,
+# UT +06 at the start of 1928, the year of accession of the warlord Jin Shuren,
 # which happens to be the date given by Shanks & Pottenger (no doubt as a
-# guess) as the transition from LMT.  Ignore the usage of UT+8 before
-# 1986-02-01 under the theory that the transition date to UT+8 is unknown and
+# guess) as the transition from LMT.  Ignore the usage of +08 before
+# 1986-02-01 under the theory that the transition date to +08 is unknown and
 # that the sort of users who prefer Asia/Urumqi now typically ignored the
-# UT+8 mandate back then.
+# +08 mandate back then.
 
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 # Beijing time, used throughout China; represented by Shanghai.
@@ -721,7 +718,7 @@ Zone        Asia/Hong_Kong  7:36:42 -       LMT     1904 Oct 30
 # be found from historical government announcement database.
 
 # From Paul Eggert (2014-07-03):
-# As per Yu-Cheng Chuang, say that Taiwan was at UT+9 from 1937-10-01
+# As per Yu-Cheng Chuang, say that Taiwan was at UT +09 from 1937-10-01
 # until 1945-09-21 at 01:00, overriding Shanks & Pottenger.
 # Likewise, use Yu-Cheng Chuang's data for DST in Taiwan.
 
@@ -774,9 +771,19 @@ Zone       Asia/Macau      7:34:20 -       LMT     1912 Jan  1
 ###############################################################################
 
 # Cyprus
-#
+
 # Milne says the Eastern Telegraph Company used 2:14:00.  Stick with LMT.
+# IATA SSIM (1998-09) has Cyprus using EU rules for the first time.
+
+# From Paul Eggert (2016-09-09):
+# Yesterday's Cyprus Mail reports that Northern Cyprus followed Turkey's
+# lead and switched from +02/+03 to +03 year-round.
+# http://cyprus-mail.com/2016/09/08/two-time-zones-cyprus-turkey-will-not-turn-clocks-back-next-month/
 #
+# From Even Scharning (2016-10-31):
+# Looks like the time zone split in Cyprus went through last night.
+# http://cyprus-mail.com/2016/10/30/cyprus-new-division-two-time-zones-now-reality/
+
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   Cyprus  1975    only    -       Apr     13      0:00    1:00    S
 Rule   Cyprus  1975    only    -       Oct     12      0:00    0       -
@@ -838,16 +845,15 @@ Link      Asia/Nicosia    Europe/Nicosia
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Asia/Tbilisi    2:59:11 -       LMT     1880
                        2:59:11 -       TBMT    1924 May  2 # Tbilisi Mean Time
-                       3:00    -       TBIT    1957 Mar    # Tbilisi Time
-                       4:00 RussiaAsia TBI%sT  1991 Mar 31  2:00s
-                       3:00    1:00    TBIST   1991 Apr  9 # independence
-                       3:00 RussiaAsia GE%sT   1992        # Georgia Time
-                       3:00 E-EurAsia  GE%sT   1994 Sep lastSun
-                       4:00 E-EurAsia  GE%sT   1996 Oct lastSun
-                       4:00    1:00    GEST    1997 Mar lastSun
-                       4:00 E-EurAsia  GE%sT   2004 Jun 27
-                       3:00 RussiaAsia GE%sT   2005 Mar lastSun  2:00
-                       4:00    -       GET
+                       3:00    -       +03     1957 Mar
+                       4:00 RussiaAsia +04/+05 1991 Mar 31  2:00s
+                       3:00 RussiaAsia +03/+04 1992
+                       3:00 E-EurAsia  +03/+04 1994 Sep lastSun
+                       4:00 E-EurAsia  +04/+05 1996 Oct lastSun
+                       4:00    1:00    +05     1997 Mar lastSun
+                       4:00 E-EurAsia  +04/+05 2004 Jun 27
+                       3:00 RussiaAsia +03/+04 2005 Mar lastSun  2:00
+                       4:00    -       +04
 
 # East Timor
 
@@ -935,11 +941,11 @@ Zone      Asia/Kolkata    5:53:28 -       LMT     1880        # Kolkata
 # summary published by the Time and Frequency Laboratory of the
 # Research Center for Calibration, Instrumentation and Metrology,
 # Indonesia, <http://time.kim.lipi.go.id/time-eng.php> (2006-09-29).
-# The abbreviations are:
+# The time zone abbreviations and UT offsets are:
 #
-# WIB  - UTC+7 - Waktu Indonesia Barat (Indonesia western time)
-# WITA - UTC+8 - Waktu Indonesia Tengah (Indonesia central time)
-# WIT  - UTC+9 - Waktu Indonesia Timur (Indonesia eastern time)
+# WIB  - +07 - Waktu Indonesia Barat (Indonesia western time)
+# WITA - +08 - Waktu Indonesia Tengah (Indonesia central time)
+# WIT  - +09 - Waktu Indonesia Timur (Indonesia eastern time)
 #
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 # Java, Sumatra
@@ -1828,11 +1834,11 @@ Rule    Kyrgyz  1997    2005    -       Mar     lastSun 2:30    1:00    S
 Rule   Kyrgyz  1997    2004    -       Oct     lastSun 2:30    0       -
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Asia/Bishkek    4:58:24 -       LMT     1924 May  2
-                       5:00    -       FRUT    1930 Jun 21 # Frunze Time
-                       6:00 RussiaAsia FRU%sT  1991 Mar 31  2:00s
-                       5:00    1:00    FRUST   1991 Aug 31  2:00 # independence
-                       5:00    Kyrgyz  KG%sT   2005 Aug 12 # Kyrgyzstan Time
-                       6:00    -       KGT
+                       5:00    -       +05     1930 Jun 21
+                       6:00 RussiaAsia +06/+07 1991 Mar 31  2:00s
+                       5:00 RussiaAsia +05/+06 1991 Aug 31  2:00
+                       5:00    Kyrgyz  +05/+06 2005 Aug 12
+                       6:00    -       +06
 
 ###############################################################################
 
@@ -2048,7 +2054,7 @@ Zone      Indian/Maldives 4:54:00 -       LMT     1880 # Male
 # Bill Bonnet (2005-05-19) reports that the US Embassy in Ulaanbaatar says
 # there is only one time zone and that DST is observed, citing Microsoft
 # Windows XP as the source.  Risto Nykänen (2005-05-16) reports that
-# travelmongolia.org says there are two time zones (UTC+7, UTC+8) with no DST.
+# travelmongolia.org says there are two time zones (UT +07, +08) with no DST.
 # Oscar van Vlijmen (2005-05-20) reports that the Mongolian Embassy in
 # Washington, DC says there are two time zones, with DST observed.
 # He also found
@@ -2551,11 +2557,6 @@ Zone     Asia/Karachi    4:28:12 -       LMT     1907
 # From Paul Eggert (2015-03-03):
 # http://www.timeanddate.com/time/change/west-bank/ramallah?year=2014
 # says that the fall 2014 transition was Oct 23 at 24:00.
-# For future dates, guess the last Friday in March at 24:00 through
-# the first Friday on or after October 21 at 00:00.  This is consistent with
-# the predictions in today's editions of the following URLs:
-# http://www.timeanddate.com/time/change/gaza-strip/gaza
-# http://www.timeanddate.com/time/change/west-bank/hebron
 
 # From Hannah Kreitem (2016-03-09):
 # http://www.palestinecabinet.gov.ps/WebSite/ar/ViewDetails?ID=31728
@@ -2565,7 +2566,21 @@ Zone     Asia/Karachi    4:28:12 -       LMT     1907
 #
 # From Paul Eggert (2016-03-12):
 # Predict spring transitions on March's last Saturday at 01:00 from now on.
-# Leave fall predictions alone for now.
+
+# From Sharef Mustafa (2016-10-19):
+# [T]he Palestinian cabinet decision (Mar 8th 2016) published on
+# http://www.palestinecabinet.gov.ps/WebSite/Upload/Decree/GOV_17/16032016134830.pdf
+# states that summer time will end on Oct 29th at 01:00.
+#
+# From Tim Parenti (2016-10-19):
+# Predict fall transitions on October's last Saturday at 01:00 from now on.
+# This is consistent with the 2016 transition as well as our spring
+# predictions.
+#
+# From Paul Eggert (2016-10-19):
+# It's also consistent with predictions in the following URLs today:
+# http://www.timeanddate.com/time/change/gaza-strip/gaza
+# http://www.timeanddate.com/time/change/west-bank/hebron
 
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule EgyptAsia 1957    only    -       May     10      0:00    1:00    S
@@ -2594,9 +2609,10 @@ Rule Palestine   2011    only    -       Sep     30      0:00    0       -
 Rule Palestine 2012    2014    -       Mar     lastThu 24:00   1:00    S
 Rule Palestine 2012    only    -       Sep     21      1:00    0       -
 Rule Palestine 2013    only    -       Sep     Fri>=21 0:00    0       -
-Rule Palestine 2014    max     -       Oct     Fri>=21 0:00    0       -
+Rule Palestine 2014    2015    -       Oct     Fri>=21 0:00    0       -
 Rule Palestine 2015    only    -       Mar     lastFri 24:00   1:00    S
 Rule Palestine 2016    max     -       Mar     lastSat 1:00    1:00    S
+Rule Palestine 2016    max     -       Oct     lastSat 1:00    0       -
 
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Asia/Gaza       2:17:52 -       LMT     1900 Oct
@@ -2684,7 +2700,7 @@ Link Asia/Qatar Asia/Bahrain
 # earlier date.
 #
 # Shanks & Pottenger also state that until 1968-05-01 Saudi Arabia had two
-# time zones; the other zone, at UTC+4, was in the far eastern part of
+# time zones; the other zone, at UT +04, was in the far eastern part of
 # the country.  Ignore this, as it's before our 1970 cutoff.
 #
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
@@ -2746,45 +2762,31 @@ Zone    Asia/Singapore  6:55:25 -       LMT     1901 Jan  1
 # People who live in regions under Tamil control can use [TZ='Asia/Kolkata'],
 # as that zone has agreed with the Tamil areas since our cutoff date of 1970.
 
-# From K Sethu (2006-04-25):
-# I think the abbreviation LKT originated from the world of computers at
-# the time of or subsequent to the time zone changes by SL Government
-# twice in 1996 and probably SL Government or its standardization
-# agencies never declared an abbreviation as a national standard.
-#
-# I recollect before the recent change the government announcements
-# mentioning it as simply changing Sri Lanka Standard Time or Sri Lanka
-# Time and no mention was made about the abbreviation.
-#
-# If we look at Sri Lanka Department of Government's "Official News
-# Website of Sri Lanka" ... http://www.news.lk/ we can see that they
-# use SLT as abbreviation in time stamp at the beginning of each news
-# item....
-#
-# Within Sri Lanka I think LKT is well known among computer users and
-# administrators.  In my opinion SLT may not be a good choice because the
-# nation's largest telcom / internet operator Sri Lanka Telcom is well
-# known by that abbreviation - simply as SLT (there IP domains are
-# slt.lk and sltnet.lk).
-#
-# But if indeed our government has adopted SLT as standard abbreviation
-# (that we have not known so far) then  it is better that it be used for
-# all computers.
-
-# From Paul Eggert (2006-04-25):
-# One possibility is that we wait for a bit for the dust to settle down
-# and then see what people actually say in practice.
+# From Sadika Sumanapala (2016-10-19):
+# According to http://www.sltime.org (maintained by Measurement Units,
+# Standards & Services Department, Sri Lanka) abbreviation for Sri Lanka
+# standard time is SLST.
+#
+# From Paul Eggert (2016-10-18):
+# "SLST" seems to be reasonably recent and rarely-used outside time
+# zone nerd sources.  I searched Google News and found three uses of
+# it in the International Business Times of India in February and
+# March of this year when discussing cricket match times, but nothing
+# since then (though there has been a lot of cricket) and nothing in
+# other English-language news sources.  Our old abbreviation "LKT" is
+# even worse.  For now, let's use a numeric abbreviation; we can
+# switch to "SLST" if it catches on.
 
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Asia/Colombo    5:19:24 -       LMT     1880
                        5:19:32 -       MMT     1906        # Moratuwa Mean Time
-                       5:30    -       IST     1942 Jan  5
-                       5:30    0:30    IHST    1942 Sep
-                       5:30    1:00    IST     1945 Oct 16  2:00
-                       5:30    -       IST     1996 May 25  0:00
-                       6:30    -       LKT     1996 Oct 26  0:30
-                       6:00    -       LKT     2006 Apr 15  0:30
-                       5:30    -       IST
+                       5:30    -       +0530   1942 Jan  5
+                       5:30    0:30    +0530/+06 1942 Sep
+                       5:30    1:00    +0530/+0630 1945 Oct 16  2:00
+                       5:30    -       +0530   1996 May 25  0:00
+                       6:30    -       +0630   1996 Oct 26  0:30
+                       6:00    -       +06     2006 Apr 15  0:30
+                       5:30    -       +0530
 
 # Syria
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
@@ -2953,10 +2955,10 @@ Zone    Asia/Damascus   2:25:12 -       LMT     1920 # Dimashq
 # From Shanks & Pottenger.
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Asia/Dushanbe   4:35:12 -       LMT     1924 May  2
-                       5:00    -       DUST    1930 Jun 21 # Dushanbe Time
-                       6:00 RussiaAsia DUS%sT  1991 Mar 31  2:00s
-                       5:00    1:00    DUSST   1991 Sep  9  2:00s
-                       5:00    -       TJT     # Tajikistan Time
+                       5:00    -       +05     1930 Jun 21
+                       6:00 RussiaAsia +06/+07 1991 Mar 31  2:00s
+                       5:00    1:00    +05/+06 1991 Sep  9  2:00s
+                       5:00    -       +05
 
 # Thailand
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
@@ -2970,11 +2972,10 @@ Link Asia/Bangkok Asia/Vientiane        # Laos
 # From Shanks & Pottenger.
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Asia/Ashgabat   3:53:32 -       LMT     1924 May  2 # or Ashkhabad
-                       4:00    -       ASHT    1930 Jun 21 # Ashkhabad Time
-                       5:00 RussiaAsia ASH%sT  1991 Mar 31  2:00
-                       4:00 RussiaAsia ASH%sT  1991 Oct 27 # independence
-                       4:00 RussiaAsia TM%sT   1992 Jan 19  2:00
-                       5:00    -       TMT
+                       4:00    -       +04     1930 Jun 21
+                       5:00 RussiaAsia +05/+06 1991 Mar 31  2:00
+                       4:00 RussiaAsia +04/+05 1992 Jan 19  2:00
+                       5:00    -       +05
 
 # United Arab Emirates
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
@@ -2986,20 +2987,18 @@ Link Asia/Dubai Asia/Muscat     # Oman
 # Byalokoz 1919 says Uzbekistan was 4:27:53.
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Asia/Samarkand  4:27:53 -       LMT     1924 May  2
-                       4:00    -       SAMT    1930 Jun 21 # Samarkand Time
-                       5:00    -       SAMT    1981 Apr  1
-                       5:00    1:00    SAMST   1981 Oct  1
-                       6:00    -       TAST    1982 Apr  1 # Tashkent Time
-                       5:00 RussiaAsia SAM%sT  1991 Sep  1 # independence
-                       5:00 RussiaAsia UZ%sT   1992
-                       5:00    -       UZT
+                       4:00    -       +04     1930 Jun 21
+                       5:00    -       +05     1981 Apr  1
+                       5:00    1:00    +06     1981 Oct  1
+                       6:00    -       +06     1982 Apr  1
+                       5:00 RussiaAsia +05/+06 1992
+                       5:00    -       +05
 # Milne says Tashkent was 4:37:10.8; round to nearest.
 Zone   Asia/Tashkent   4:37:11 -       LMT     1924 May  2
-                       5:00    -       TAST    1930 Jun 21 # Tashkent Time
-                       6:00 RussiaAsia TAS%sT  1991 Mar 31  2:00
-                       5:00 RussiaAsia TAS%sT  1991 Sep  1 # independence
-                       5:00 RussiaAsia UZ%sT   1992
-                       5:00    -       UZT
+                       5:00    -       +05     1930 Jun 21
+                       6:00 RussiaAsia +06/+07 1991 Mar 31  2:00
+                       5:00 RussiaAsia +05/+06 1992
+                       5:00    -       +05
 
 # Vietnam
 
index a79737a..0bca53e 100644 (file)
@@ -350,7 +350,13 @@ Zone       Indian/Cocos    6:27:40 -       LMT     1900
 # commencing at 2.00 am on Sunday 1st November, 2015 and ending at
 # 3.00 am on Sunday 17th January, 2016.
 
-# From Paul Eggert (2015-09-01):
+# From Raymond Kumar (2016-10-04):
+# http://www.fiji.gov.fj/Media-Center/Press-Releases/DAYLIGHT-SAVING-STARTS-ON-6th-NOVEMBER,-2016.aspx
+# "Fiji's daylight savings will begin on Sunday, 6 November 2016, when
+# clocks go forward an hour at 2am to 3am....  Daylight Saving will
+# end at 3.00am on Sunday 15th January 2017."
+
+# From Paul Eggert (2016-10-03):
 # For now, guess DST from 02:00 the first Sunday in November to
 # 03:00 the third Sunday in January.  Although ad hoc, it matches
 # transitions since late 2014 and seems more likely to match future
@@ -545,7 +551,7 @@ Zone Pacific/Port_Moresby 9:48:40 - LMT     1880
 # Base the Bougainville entry on the Arawa-Kieta region, which appears to have
 # the most people even though it was devastated in the Bougainville Civil War.
 #
-# Although Shanks gives 1942-03-15 / 1943-11-01 for JST, these dates
+# Although Shanks gives 1942-03-15 / 1943-11-01 for UT +09, these dates
 # are apparently rough guesswork from the starts of military campaigns.
 # The World War II entries below are instead based on Arawa-Kieta.
 # The Japanese occupied Kieta in July 1942,
@@ -553,8 +559,8 @@ Zone Pacific/Port_Moresby 9:48:40 - LMT     1880
 # http://pwencycl.kgbudge.com/B/o/Bougainville.htm
 # and seem to have controlled it until their 1945-08-21 surrender.
 #
-# The Autonomous Region of Bougainville plans to switch from UTC+10 to UTC+11
-# on 2014-12-28 at 02:00.  They call UTC+11 "Bougainville Standard Time";
+# The Autonomous Region of Bougainville switched from UT +10 to +11
+# on 2014-12-28 at 02:00.  They call +11 "Bougainville Standard Time";
 # abbreviate this as BST.  See:
 # http://www.bougainville24.com/bougainville-issues/bougainville-gets-own-timezone/
 #
@@ -620,7 +626,7 @@ Link Pacific/Pago_Pago Pacific/Midway # in US minor outlying islands
 # From Paul Eggert (2014-06-27):
 # The International Date Line Act 2011
 # http://www.parliament.gov.ws/images/ACTS/International_Date_Line_Act__2011_-_Eng.pdf
-# changed Samoa from UTC-11 to UTC+13, effective "12 o'clock midnight, on
+# changed Samoa from UT -11 to +13, effective "12 o'clock midnight, on
 # Thursday 29th December 2011".  The International Date Line was adjusted
 # accordingly.
 
@@ -717,7 +723,7 @@ Zone Pacific/Funafuti       11:56:52 -      LMT     1901
 # 1886-1891; Baker was similar but exact dates are not known.
 # Inhabited by civilians 1935-1942; U.S. military bases 1943-1944;
 # uninhabited thereafter.
-# Howland observed Hawaii Standard Time (UT-10:30) in 1937;
+# Howland observed Hawaii Standard Time (UT -10:30) in 1937;
 # see page 206 of Elgen M. Long and Marie K. Long,
 # Amelia Earhart: the Mystery Solved, Simon & Schuster (2000).
 # So most likely Howland and Baker observed Hawaii Time from 1935
@@ -1475,7 +1481,7 @@ Zone      Pacific/Wallis  12:15:20 -      LMT     1901
 # Zealand time.  I understand that is the time they keep locally, anyhow."
 # For now, assume this practice goes back to the introduction of standard time
 # in New Zealand, as this would make Chatham Islands time almost exactly match
-# LMT back when New Zealand was at UTC+11:30; also, assume Chatham Islands did
+# LMT back when New Zealand was at UT +11:30; also, assume Chatham Islands did
 # not observe New Zealand's prewar DST.
 
 ###############################################################################
@@ -1550,8 +1556,8 @@ Zone      Pacific/Wallis  12:15:20 -      LMT     1901
 # The Federated States of Micronesia Visitors Board writes in
 # The Federated States of Micronesia - Visitor Information (1999-01-26)
 # http://www.fsmgov.org/info/clocks.html
-# that Truk and Yap are UTC+10, and Ponape and Kosrae are UTC+11.
-# We don't know when Kosrae switched from UTC+12; assume January 1 for now.
+# that Truk and Yap are UT +10, and Ponape and Kosrae are +11.
+# We don't know when Kosrae switched from +12; assume January 1 for now.
 
 
 # Midway
@@ -1617,11 +1623,11 @@ Zone    Pacific/Wallis  12:15:20 -      LMT     1901
 # ordaining - by a masterpiece of diplomatic flattery - that
 # the Fourth of July should be celebrated twice in that year."
 
-# Although Shanks & Pottenger says they both switched to UTC-11:30
-# in 1911, and to UTC-11 in 1950. many earlier sources give UTC-11
+# Although Shanks & Pottenger says they both switched to UT -11:30
+# in 1911, and to -11 in 1950. many earlier sources give -11
 # for American Samoa, e.g., the US National Bureau of Standards
 # circular "Standard Time Throughout the World", 1932.
-# Assume American Samoa switched to UTC-11 in 1911, not 1950,
+# Assume American Samoa switched to -11 in 1911, not 1950,
 # and that after 1950 they agreed until (western) Samoa skipped a
 # day in 2011.  Assume also that the Samoas follow the US and New
 # Zealand's "ST"/"DT" style of daylight-saving abbreviations.
index aab237a..aa23dd8 100644 (file)
--- a/backward
+++ b/backward
@@ -36,6 +36,7 @@ Link  Asia/Shanghai           Asia/Harbin
 Link   Asia/Urumqi             Asia/Kashgar
 Link   Asia/Kathmandu          Asia/Katmandu
 Link   Asia/Macau              Asia/Macao
+Link   Asia/Yangon             Asia/Rangoon
 Link   Asia/Ho_Chi_Minh        Asia/Saigon
 Link   Asia/Jerusalem          Asia/Tel_Aviv
 Link   Asia/Thimphu            Asia/Thimbu
index 13dc8d4..4a5085f 100644 (file)
--- a/backzone
+++ b/backzone
@@ -194,9 +194,9 @@ Zone        Africa/Lusaka   1:53:08 -       LMT     1903 Mar
 
 # Equatorial Guinea
 #
-# Although Shanks says that Malabo switched from UTC to UTC+1 on 1963-12-15,
+# Although Shanks says that Malabo switched from UT +00 to +01 on 1963-12-15,
 # a Google Books search says that London Calling, Issues 432-465 (1948), p 19,
-# says that Spanish Guinea was at GMT+1 back then.  The Shanks data entries
+# says that Spanish Guinea was at +01 back then.  The Shanks data entries
 # are most likely wrong, but we have nothing better; use them here for now.
 #
 Zone   Africa/Malabo   0:35:08 -       LMT     1912
@@ -479,14 +479,14 @@ Zone      Asia/Muscat     3:54:24 -       LMT     1920
 # From Paul Eggert (2014-08-11), after a heads-up from Stephen Colebourne:
 # According to a Portuguese decree (1911-05-26)
 # http://dre.pt/pdf1sdip/1911/05/12500/23132313.pdf
-# Portuguese India switched to GMT+5 on 1912-01-01.
+# Portuguese India switched to UT +05 on 1912-01-01.
 #Zone  Asia/Panaji     [not enough info to complete]
 
 # Cambodia
 # From Paul Eggert (2014-10-11):
 # See Asia/Ho_Chi_Minh for the source for most of this data.  Also, guess
-# (1) Cambodia reverted to UT+7 on 1945-09-02, when Vietnam did, and
-# (2) they also reverted to UT+7 on 1953-11-09, the date of independence.
+# (1) Cambodia reverted to UT +07 on 1945-09-02, when Vietnam did, and
+# (2) they also reverted to +07 on 1953-11-09, the date of independence.
 # These guesses are probably wrong but they're better than guessing no
 # transitions there.
 Zone   Asia/Phnom_Penh 6:59:40 -       LMT     1906 Jul  1
@@ -506,8 +506,8 @@ Zone        Asia/Tel_Aviv   2:19:04 -       LMT     1880
 # Laos
 # From Paul Eggert (2014-10-11):
 # See Asia/Ho_Chi_Minh for the source for most of this data.
-# Trần's book says that Laos reverted to UT+7 on 1955-04-15.
-# Also, guess that Laos reverted to UT+7 on 1945-09-02, when Vietnam did;
+# Trần's book says that Laos reverted to UT +07 on 1955-04-15.
+# Also, guess that Laos reverted to +07 on 1945-09-02, when Vietnam did;
 # this is probably wrong but it's better than guessing no transition.
 Zone   Asia/Vientiane  6:50:24 -       LMT     1906 Jul  1
                        7:06:30 -       PLMT    1911 May  1
diff --git a/date.c b/date.c
index 4c11f61..512d1ef 100644 (file)
--- a/date.c
+++ b/date.c
@@ -42,8 +42,9 @@
 #define SECSPERMIN     60
 #endif /* !defined SECSPERMIN */
 
-#if !HAVE_POSIX_DECLS
 extern char **         environ;
+
+#if !HAVE_POSIX_DECLS
 extern char *          optarg;
 extern int             optind;
 extern char *          tzname[];
index 822a38e..f5fa4c9 100644 (file)
--- a/etcetera
+++ b/etcetera
@@ -37,19 +37,9 @@ Link Etc/GMT                         Etc/GMT0
 # even though this is the opposite of what many people expect.
 # POSIX has positive signs west of Greenwich, but many people expect
 # positive signs east of Greenwich.  For example, TZ='Etc/GMT+4' uses
-# the abbreviation "GMT+4" and corresponds to 4 hours behind UT
+# the abbreviation "-04" and corresponds to 4 hours behind UT
 # (i.e. west of Greenwich) even though many people would expect it to
 # mean 4 hours ahead of UT (i.e. east of Greenwich).
-#
-# In the draft 5 of POSIX 1003.1-200x, the angle bracket notation allows for
-# TZ='<GMT-4>+4'; if you want time zone abbreviations conforming to
-# ISO 8601 you can use TZ='<-0400>+4'.  Thus the commonly-expected
-# offset is kept within the angle bracket (and is used for display)
-# while the POSIX sign is kept outside the angle bracket (and is used
-# for calculation).
-#
-# Do not use a TZ setting like TZ='GMT+4', which is four hours behind
-# GMT but uses the completely misleading abbreviation "GMT".
 
 # Earlier incarnations of this package were not POSIX-compliant,
 # and had lines such as
diff --git a/europe b/europe
index 728e3a8..4709cc7 100644 (file)
--- a/europe
+++ b/europe
@@ -75,8 +75,7 @@
 #        1:00       CET CEST CEMT Central Europe
 #        1:00:14    SET           Swedish (1879-1899)*
 #        2:00       EET EEST      Eastern Europe
-#        3:00       FET           Further-eastern Europe (2011-2014)*
-#        3:00       MSK MSD  MSM* Minsk, Moscow
+#        3:00       MSK MSD       Moscow
 
 # From Peter Ilieve (1994-12-04),
 # The original six [EU members]: Belgium, France, (West) Germany, Italy,
@@ -590,16 +589,26 @@ Rule      E-Eur   1996    max     -       Oct     lastSun  0:00   0       -
 
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   Russia  1917    only    -       Jul      1      23:00   1:00    MST  # Moscow Summer Time
+#
+# Decree No. 142 (1917-12-22) http://istmat.info/node/28137
 Rule   Russia  1917    only    -       Dec     28       0:00   0       MMT  # Moscow Mean Time
+#
+# Decree No. 497 (1918-05-30) http://istmat.info/node/30001
 Rule   Russia  1918    only    -       May     31      22:00   2:00    MDST # Moscow Double Summer Time
 Rule   Russia  1918    only    -       Sep     16       1:00   1:00    MST
 #
 # Decree No. 258 (1919-05-29) http://istmat.info/node/37949
 Rule   Russia  1919    only    -       May     31      23:00   2:00    MDST
-Rule   Russia  1919    only    -       Jul      1       2:00   1:00    MSD
+#
+Rule   Russia  1919    only    -       Jul      1       0:00u  1:00    MSD
 Rule   Russia  1919    only    -       Aug     16       0:00   0       MSK
+#
+# Decree No. 63 (1921-02-03) http://istmat.info/node/45840
 Rule   Russia  1921    only    -       Feb     14      23:00   1:00    MSD
-Rule   Russia  1921    only    -       Mar     20      23:00   2:00    MSM  # Midsummer
+#
+# Decree No. 121 (1921-03-07) http://istmat.info/node/45949
+Rule   Russia  1921    only    -       Mar     20      23:00   2:00    +05
+#
 Rule   Russia  1921    only    -       Sep      1       0:00   1:00    MSD
 Rule   Russia  1921    only    -       Oct      1       0:00   0       -
 # Act No. 925 of the Council of Ministers of the USSR (1980-10-24):
@@ -782,8 +791,6 @@ Zone        Europe/Vienna   1:05:21 -       LMT     1893 Apr
 # From Alexander Bokovoy (2014-10-09):
 # Belarussian government decided against changing to winter time....
 # http://eng.belta.by/all_news/society/Belarus-decides-against-adjusting-time-in-Russias-wake_i_76335.html
-# From Paul Eggert (2014-10-08):
-# Hence Belarus can share time zone abbreviations with Moscow again.
 #
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Europe/Minsk    1:50:16 -       LMT     1880
@@ -794,8 +801,7 @@ Zone        Europe/Minsk    1:50:16 -       LMT     1880
                        3:00    Russia  MSK/MSD 1990
                        3:00    -       MSK     1991 Mar 31  2:00s
                        2:00    Russia  EE%sT   2011 Mar 27  2:00s
-                       3:00    -       FET     2014 Oct 26  1:00s
-                       3:00    -       MSK
+                       3:00    -       +03
 
 # Belgium
 #
@@ -1494,30 +1500,36 @@ Zone Atlantic/Reykjavik -1:28   -       LMT     1908
 # But these events all occurred before the 1970 cutoff,
 # so record only the time in Rome.
 #
-# From Paul Eggert (2006-03-22):
-# For Italian DST we have three sources: Shanks & Pottenger, Whitman, and
-# F. Pollastri
-# Day-light Saving Time in Italy (2006-02-03)
-# http://toi.iriti.cnr.it/uk/ienitlt.html
-# ('FP' below), taken from an Italian National Electrotechnical Institute
-# publication. When the three sources disagree, guess who's right, as follows:
-#
-# year FP      Shanks&P. (S)   Whitman (W)     Go with:
-# 1916 06-03   06-03 24:00     06-03 00:00     FP & W
-#      09-30   09-30 24:00     09-30 01:00     FP; guess 24:00s
-# 1917 04-01   03-31 24:00     03-31 00:00     FP & S
-#      09-30   09-29 24:00     09-30 01:00     FP & W
-# 1918 03-09   03-09 24:00     03-09 00:00     FP & S
-#      10-06   10-05 24:00     10-06 01:00     FP & W
-# 1919 03-01   03-01 24:00     03-01 00:00     FP & S
-#      10-04   10-04 24:00     10-04 01:00     FP; guess 24:00s
-# 1920 03-20   03-20 24:00     03-20 00:00     FP & S
-#      09-18   09-18 24:00     10-01 01:00     FP; guess 24:00s
-# 1944 04-02   04-03 02:00                     S (see C-Eur)
-#      09-16   10-02 03:00                     FP; guess 24:00s
-# 1945 09-14   09-16 24:00                     FP; guess 24:00s
-# 1970 05-21   05-31 00:00                     S
-#      09-20   09-27 00:00                     S
+# From Michael Deckers (2016-10-24):
+# http://www.ac-ilsestante.it/MERIDIANE/ora_legale quotes a law of 1893-08-10
+# ... [translated as] "The preceding dispositions will enter into
+# force at the instant at which, according to the time specified in
+# the 1st article, the 1st of November 1893 will begin...."
+#
+# From Pierpaolo Bernardi (2016-10-20):
+# The authoritative source for time in Italy is the national metrological
+# institute, which has a summary page of historical DST data at
+# http://www.inrim.it/res/tf/ora_legale_i.shtml
+# (2016-10-24):
+# http://www.renzobaldini.it/le-ore-legali-in-italia/
+# has still different data for 1944.  It divides Italy in two, as
+# there were effectively two governments at the time, north of Gothic
+# Line German controlled territory, official government RSI, and south
+# of the Gothic Line, controlled by allied armies.
+#
+# From Brian Inglis (2016-10-23):
+# Viceregal LEGISLATIVE DECREE. 14 September 1944, no. 219.
+# Restoration of Standard Time. (044U0219) (OJ 62 of 30.9.1944) ...
+# Given the R. law decreed on 1944-03-29, no. 92, by which standard time is
+# advanced to sixty minutes later starting at hour two on 1944-04-02; ...
+# Starting at hour three on the date 1944-09-17 standard time will be resumed.
+#
+# From Paul Eggert (2016-10-27):
+# Go with INRiM for DST rules, except as corrected by Inglis for 1944
+# for the Kingdom of Italy.  This is consistent with Renzo Baldini.
+# Model Rome's occupation by using using C-Eur rules from 1943-09-10
+# to 1944-06-04; although Rome was an open city during this period, it
+# was effectively controlled by Germany.
 #
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   Italy   1916    only    -       Jun      3      24:00   1:00    S
@@ -1563,9 +1575,9 @@ Rule      Italy   1978    only    -       Oct      1       0:00s  0       -
 Rule   Italy   1979    only    -       Sep     30       0:00s  0       -
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Europe/Rome     0:49:56 -       LMT     1866 Sep 22
-                       0:49:56 -       RMT     1893 Nov  1  0:00s # Rome Mean
-                       1:00    Italy   CE%sT   1942 Nov  2  2:00s
-                       1:00    C-Eur   CE%sT   1944 Jul
+                       0:49:56 -       RMT     1893 Oct 31 23:49:56 # Rome Mean
+                       1:00    Italy   CE%sT   1943 Sep 10
+                       1:00    C-Eur   CE%sT   1944 Jun  4
                        1:00    Italy   CE%sT   1980
                        1:00    EU      CE%sT
 
@@ -1778,8 +1790,6 @@ Rule      Malta   1975    1980    -       Sep     Sun>=15 2:00    0       -
 Rule   Malta   1980    only    -       Mar     31      2:00    1:00    S
 # Zone NAME            GMTOFF  RULES   FORMAT  [UNTIL]
 Zone   Europe/Malta    0:58:04 -       LMT     1893 Nov  2  0:00s # Valletta
-                       1:00    Italy   CE%sT   1942 Nov  2  2:00s
-                       1:00    C-Eur   CE%sT   1945 Apr  2  2:00s
                        1:00    Italy   CE%sT   1973 Mar 31
                        1:00    Malta   CE%sT   1981
                        1:00    EU      CE%sT
@@ -1911,7 +1921,7 @@ Zone      Europe/Monaco   0:29:32 -       LMT     1891 Mar 15
 # Amsterdam mean time.
 
 # The data entries before 1945 are taken from
-# http://www.phys.uu.nl/~vgent/wettijd/wettijd.htm
+# http://www.staff.science.uu.nl/~gent0113/wettijd/wettijd.htm
 
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   Neth    1916    only    -       May      1      0:00    1:00    NST     # Netherlands Summer Time
@@ -2351,7 +2361,7 @@ Zone Europe/Kaliningrad    1:22:00 -      LMT     1893 Apr
                         2:00   Poland  CE%sT   1946
                         3:00   Russia  MSK/MSD 1989 Mar 26  2:00s
                         2:00   Russia  EE%sT   2011 Mar 27  2:00s
-                        3:00   -       FET     2014 Oct 26  2:00s
+                        3:00   -       +03     2014 Oct 26  2:00s
                         2:00   -       EET
 
 
@@ -2404,6 +2414,16 @@ Zone Europe/Kaliningrad   1:22:00 -      LMT     1893 Apr
 # 78   RU-SPE  Saint Petersburg
 # 83   RU-NEN  Nenets Autonomous Okrug
 
+# From Paul Eggert (2016-08-23):
+# The Soviets switched to UT-based time in 1919.  Decree No. 59
+# (1919-02-08) http://istmat.info/node/35567 established UT-based time
+# zones, and Decree No. 147 (1919-03-29) http://istmat.info/node/35854
+# specified a transition date of 1919-07-01, apparently at 00:00 UT.
+# No doubt only the Soviet-controlled regions switched on that date;
+# later transitions to UT-based time in other parts of Russia are
+# taken from what appear to be guesses by Shanks.
+# (Thanks to Alexander Belopolsky for pointers to the decrees.)
+
 # From Stepan Golosunov (2016-03-07):
 # 11. Regions-violators, 1981-1982.
 # Wikipedia refers to
@@ -2445,7 +2465,7 @@ Zone Europe/Kaliningrad    1:22:00 -      LMT     1893 Apr
 # attributes the 1982 changes to the Act of the Council of Ministers
 # of the USSR No. 126 from 18.02.1982.  1980-925.txt also adds
 # Udmurtia to the list of affected territories and lists Khatangsky
-# district separately from Taymyr Autonomous Okurg.  Probably erroneously.
+# district separately from Taymyr Autonomous Okrug.  Probably erroneously.
 #
 # The affected territories are currently listed under Europe/Moscow,
 # Asia/Yekaterinburg and Asia/Krasnoyarsk.
@@ -2505,7 +2525,7 @@ Zone Europe/Kaliningrad    1:22:00 -      LMT     1893 Apr
 
 Zone Europe/Moscow      2:30:17 -      LMT     1880
                         2:30:17 -      MMT     1916 Jul  3 # Moscow Mean Time
-                        2:31:19 Russia %s      1919 Jul  1  2:00
+                        2:31:19 Russia %s      1919 Jul  1  0:00u
                         3:00   Russia  %s      1921 Oct
                         3:00   Russia  MSK/MSD 1922 Oct
                         2:00   -       EET     1930 Jun 21
@@ -2588,22 +2608,21 @@ Zone Europe/Astrakhan    3:12:12 -      LMT     1924 May
 # The 1988 transition is from USSR act No. 5 (1988-01-04).
 
 Zone Europe/Volgograd   2:57:40 -      LMT     1920 Jan  3
-                        3:00   -       TSAT    1925 Apr  6 # Tsaritsyn Time
-                        3:00   -       STAT    1930 Jun 21 # Stalingrad Time
-                        4:00   -       STAT    1961 Nov 11
-                        4:00   Russia  VOL%sT  1988 Mar 27  2:00s # Volgograd T
-                        3:00   Russia  VOL%sT  1991 Mar 31  2:00s
-                        4:00   -       VOLT    1992 Mar 29  2:00s
-                        3:00   Russia  MSK/MSD 2011 Mar 27  2:00s
-                        4:00   -       MSK     2014 Oct 26  2:00s
-                        3:00   -       MSK
+                        3:00   -       +03     1930 Jun 21
+                        4:00   -       +04     1961 Nov 11
+                        4:00   Russia  +04/+05 1988 Mar 27  2:00s
+                        3:00   Russia  +03/+04 1991 Mar 31  2:00s
+                        4:00   -       +04     1992 Mar 29  2:00s
+                        3:00   Russia  +03/+04 2011 Mar 27  2:00s
+                        4:00   -       +04     2014 Oct 26  2:00s
+                        3:00   -       +03
 
 # From Paul Eggert (2016-03-18):
 # Europe/Kirov covers:
 # 43   RU-KIR  Kirov Oblast
 # The 1989 transition is from USSR act No. 227 (1989-03-14).
 #
-Zone Europe/Kirov       3:18:48 -      LMT     1919 Jul  1  2:00
+Zone Europe/Kirov       3:18:48 -      LMT     1919 Jul  1  0:00u
                         3:00   -       +03     1930 Jun 21
                         4:00   Russia  +04/+05 1989 Mar 26  2:00s
                         3:00   Russia  +03/+04 1991 Mar 31  2:00s
@@ -2621,16 +2640,16 @@ Zone Europe/Kirov        3:18:48 -      LMT     1919 Jul  1  2:00
 # Byalokoz 1919 says Samara was 3:20:20.
 # The 1989 transition is from USSR act No. 227 (1989-03-14).
 
-Zone Europe/Samara      3:20:20 -      LMT     1919 Jul  1  2:00
-                        3:00   -       SAMT    1930 Jun 21 # Samara Time
-                        4:00   -       SAMT    1935 Jan 27
-                        4:00   Russia  KUY%sT  1989 Mar 26  2:00s # Kuybyshev
-                        3:00   Russia  MSK/MSD 1991 Mar 31  2:00s
-                        2:00   Russia  EE%sT   1991 Sep 29  2:00s
-                        3:00   -       SAMT    1991 Oct 20  3:00
-                        4:00   Russia  SAM%sT  2010 Mar 28  2:00s
-                        3:00   Russia  SAM%sT  2011 Mar 27  2:00s
-                        4:00   -       SAMT
+Zone Europe/Samara      3:20:20 -      LMT     1919 Jul  1  0:00u
+                        3:00   -       +03     1930 Jun 21
+                        4:00   -       +04     1935 Jan 27
+                        4:00   Russia  +04/+05 1989 Mar 26  2:00s
+                        3:00   Russia  +03/+04 1991 Mar 31  2:00s
+                        2:00   Russia  +02/+03 1991 Sep 29  2:00s
+                        3:00   -       +03     1991 Oct 20  3:00
+                        4:00   Russia  +04/+05 2010 Mar 28  2:00s
+                        3:00   Russia  +03/+04 2011 Mar 27  2:00s
+                        4:00   -       +04
 
 # From Paul Eggert (2016-03-18):
 # Europe/Ulyanovsk covers:
@@ -2645,7 +2664,7 @@ Zone Europe/Samara         3:20:20 -      LMT     1919 Jul  1  2:00
 # From Matt Johnson (2016-03-09):
 # http://publication.pravo.gov.ru/Document/View/0001201603090051
 
-Zone Europe/Ulyanovsk   3:13:36 -      LMT     1919 Jul  1  2:00
+Zone Europe/Ulyanovsk   3:13:36 -      LMT     1919 Jul  1  0:00u
                         3:00   -       +03     1930 Jun 21
                         4:00   Russia  +04/+05 1989 Mar 26  2:00s
                         3:00   Russia  +03/+04 1991 Mar 31  2:00s
@@ -2677,12 +2696,12 @@ Zone Europe/Ulyanovsk    3:13:36 -      LMT     1919 Jul  1  2:00
 
 Zone Asia/Yekaterinburg         4:02:33 -      LMT     1916 Jul  3
                         3:45:05 -      PMT     1919 Jul 15  4:00
-                        4:00   -       SVET    1930 Jun 21 # Sverdlovsk Time
-                        5:00   Russia  SVE%sT  1991 Mar 31  2:00s
-                        4:00   Russia  SVE%sT  1992 Jan 19  2:00s
-                        5:00   Russia  YEK%sT  2011 Mar 27  2:00s
-                        6:00   -       YEKT    2014 Oct 26  2:00s
-                        5:00   -       YEKT
+                        4:00   -       +04     1930 Jun 21
+                        5:00   Russia  +05/+06 1991 Mar 31  2:00s
+                        4:00   Russia  +04/+05 1992 Jan 19  2:00s
+                        5:00   Russia  +05/+06 2011 Mar 27  2:00s
+                        6:00   -       +06     2014 Oct 26  2:00s
+                        5:00   -       +05
 
 
 # From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
@@ -2692,12 +2711,12 @@ Zone Asia/Yekaterinburg  4:02:33 -      LMT     1916 Jul  3
 # Byalokoz 1919 says Omsk was 4:53:30.
 
 Zone Asia/Omsk          4:53:30 -      LMT     1919 Nov 14
-                        5:00   -       OMST    1930 Jun 21 # Omsk Time
-                        6:00   Russia  OMS%sT  1991 Mar 31  2:00s
-                        5:00   Russia  OMS%sT  1992 Jan 19  2:00s
-                        6:00   Russia  OMS%sT  2011 Mar 27  2:00s
-                        7:00   -       OMST    2014 Oct 26  2:00s
-                        6:00   -       OMST
+                        5:00   -       +05     1930 Jun 21
+                        6:00   Russia  +06/+07 1991 Mar 31  2:00s
+                        5:00   Russia  +05/+06 1992 Jan 19  2:00s
+                        6:00   Russia  +06/+07 2011 Mar 27  2:00s
+                        7:00   -       +07     2014 Oct 26  2:00s
+                        6:00   -       +06
 
 # From Paul Eggert (2016-02-22):
 # Asia/Barnaul covers:
@@ -2777,7 +2796,7 @@ Zone Asia/Novosibirsk      5:31:40 -      LMT     1919 Dec 14  6:00
 # Note that time belts (numbered from 2 (Moscow) to 12 according to their
 # GMT/UTC offset and having too many exceptions like regions formally
 # belonging to one belt but using time from another) were replaced
-# with time zones in 2011 with different numberings (there was a
+# with time zones in 2011 with different numbering (there was a
 # 2-hour gap between second and third zones in 2011-2014).
 
 # From Stepan Golosunov (2016-04-12):
@@ -2835,23 +2854,18 @@ Zone    Asia/Tomsk       5:39:51 -      LMT     1919 Dec 22
 #
 # Thus, when Russia will switch to DST on the night of March 28, 2010
 # Kemerovo region (Kemerovo oblast') will not change the clock.
-#
-# As a result, Kemerovo oblast' will be in the same time zone as
-# Novosibirsk, Omsk, Tomsk, Barnaul and Altai Republic.
 
 # From Tim Parenti (2014-07-02), per Alexander Krivenyshev (2014-07-02):
 # The Kemerovo region will remain at UTC+7 through the 2014-10-26 change, thus
 # realigning itself with KRAT.
 
 Zone Asia/Novokuznetsk  5:48:48 -      LMT     1924 May  1
-                        6:00   -       KRAT    1930 Jun 21 # Krasnoyarsk Time
-                        7:00   Russia  KRA%sT  1991 Mar 31  2:00s
-                        6:00   Russia  KRA%sT  1992 Jan 19  2:00s
-                        7:00   Russia  KRA%sT  2010 Mar 28  2:00s
-                        6:00   Russia  NOV%sT  2011 Mar 27  2:00s # Novosibirsk
-                        7:00   -       NOVT    2014 Oct 26  2:00s
-                        7:00   -       KRAT    # Krasnoyarsk Time
-
+                        6:00   -       +06     1930 Jun 21
+                        7:00   Russia  +07/+08 1991 Mar 31  2:00s
+                        6:00   Russia  +06/+07 1992 Jan 19  2:00s
+                        7:00   Russia  +07/+08 2010 Mar 28  2:00s
+                        6:00   Russia  +06/+07 2011 Mar 27  2:00s
+                        7:00   -       +07
 
 # From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
 # Asia/Krasnoyarsk covers...
@@ -2865,12 +2879,12 @@ Zone Asia/Novokuznetsk   5:48:48 -      LMT     1924 May  1
 # Byalokoz 1919 says Krasnoyarsk was 6:11:26.
 
 Zone Asia/Krasnoyarsk   6:11:26 -      LMT     1920 Jan  6
-                        6:00   -       KRAT    1930 Jun 21 # Krasnoyarsk Time
-                        7:00   Russia  KRA%sT  1991 Mar 31  2:00s
-                        6:00   Russia  KRA%sT  1992 Jan 19  2:00s
-                        7:00   Russia  KRA%sT  2011 Mar 27  2:00s
-                        8:00   -       KRAT    2014 Oct 26  2:00s
-                        7:00   -       KRAT
+                        6:00   -       +06     1930 Jun 21
+                        7:00   Russia  +07/+08 1991 Mar 31  2:00s
+                        6:00   Russia  +06/+07 1992 Jan 19  2:00s
+                        7:00   Russia  +07/+08 2011 Mar 27  2:00s
+                        8:00   -       +08     2014 Oct 26  2:00s
+                        7:00   -       +07
 
 
 # From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
@@ -2887,12 +2901,12 @@ Zone Asia/Krasnoyarsk    6:11:26 -      LMT     1920 Jan  6
 
 Zone Asia/Irkutsk       6:57:05 -      LMT     1880
                         6:57:05 -      IMT     1920 Jan 25 # Irkutsk Mean Time
-                        7:00   -       IRKT    1930 Jun 21 # Irkutsk Time
-                        8:00   Russia  IRK%sT  1991 Mar 31  2:00s
-                        7:00   Russia  IRK%sT  1992 Jan 19  2:00s
-                        8:00   Russia  IRK%sT  2011 Mar 27  2:00s
-                        9:00   -       IRKT    2014 Oct 26  2:00s
-                        8:00   -       IRKT
+                        7:00   -       +07     1930 Jun 21
+                        8:00   Russia  +08/+09 1991 Mar 31  2:00s
+                        7:00   Russia  +07/+08 1992 Jan 19  2:00s
+                        8:00   Russia  +08/+09 2011 Mar 27  2:00s
+                        9:00   -       +09     2014 Oct 26  2:00s
+                        8:00   -       +08
 
 
 # From Tim Parenti (2014-07-06):
@@ -2909,13 +2923,13 @@ Zone Asia/Irkutsk        6:57:05 -      LMT     1880
 # http://publication.pravo.gov.ru/Document/View/0001201512300107
 
 Zone Asia/Chita         7:33:52 -      LMT     1919 Dec 15
-                        8:00   -       YAKT    1930 Jun 21 # Yakutsk Time
-                        9:00   Russia  YAK%sT  1991 Mar 31  2:00s
-                        8:00   Russia  YAK%sT  1992 Jan 19  2:00s
-                        9:00   Russia  YAK%sT  2011 Mar 27  2:00s
-                       10:00   -       YAKT    2014 Oct 26  2:00s
-                        8:00   -       IRKT    2016 Mar 27  2:00
-                        9:00   -       YAKT
+                        8:00   -       +08     1930 Jun 21
+                        9:00   Russia  +09/+10 1991 Mar 31  2:00s
+                        8:00   Russia  +08/+09 1992 Jan 19  2:00s
+                        9:00   Russia  +09/+10 2011 Mar 27  2:00s
+                       10:00   -       +10     2014 Oct 26  2:00s
+                        8:00   -       +08     2016 Mar 27  2:00
+                        9:00   -       +09
 
 
 # From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2009-11-29):
@@ -2955,12 +2969,12 @@ Zone Asia/Chita  7:33:52 -      LMT     1919 Dec 15
 # Byalokoz 1919 says Yakutsk was 8:38:58.
 
 Zone Asia/Yakutsk       8:38:58 -      LMT     1919 Dec 15
-                        8:00   -       YAKT    1930 Jun 21 # Yakutsk Time
-                        9:00   Russia  YAK%sT  1991 Mar 31  2:00s
-                        8:00   Russia  YAK%sT  1992 Jan 19  2:00s
-                        9:00   Russia  YAK%sT  2011 Mar 27  2:00s
-                       10:00   -       YAKT    2014 Oct 26  2:00s
-                        9:00   -       YAKT
+                        8:00   -       +08     1930 Jun 21
+                        9:00   Russia  +09/+10 1991 Mar 31  2:00s
+                        8:00   Russia  +08/+09 1992 Jan 19  2:00s
+                        9:00   Russia  +09/+10 2011 Mar 27  2:00s
+                       10:00   -       +10     2014 Oct 26  2:00s
+                        9:00   -       +09
 
 
 # From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2009-11-29):
@@ -2978,12 +2992,12 @@ Zone Asia/Yakutsk        8:38:58 -      LMT     1919 Dec 15
 # Go with Byalokoz.
 
 Zone Asia/Vladivostok   8:47:31 -      LMT     1922 Nov 15
-                        9:00   -       VLAT    1930 Jun 21 # Vladivostok Time
-                       10:00   Russia  VLA%sT  1991 Mar 31  2:00s
-                        9:00   Russia  VLA%sT  1992 Jan 19  2:00s
-                       10:00   Russia  VLA%sT  2011 Mar 27  2:00s
-                       11:00   -       VLAT    2014 Oct 26  2:00s
-                       10:00   -       VLAT
+                        9:00   -       +09     1930 Jun 21
+                       10:00   Russia  +10/+11 1991 Mar 31  2:00s
+                        9:00   Russia  +09/+10 1992 Jan 19  2:00s
+                       10:00   Russia  +10/+11 2011 Mar 27  2:00s
+                       11:00   -       +11     2014 Oct 26  2:00s
+                       10:00   -       +10
 
 
 # From Tim Parenti (2014-07-03):
@@ -3001,14 +3015,14 @@ Zone Asia/Vladivostok    8:47:31 -      LMT     1922 Nov 15
 # This transition is no doubt wrong, but we have no better info.
 
 Zone Asia/Khandyga      9:02:13 -      LMT     1919 Dec 15
-                        8:00   -       YAKT    1930 Jun 21 # Yakutsk Time
-                        9:00   Russia  YAK%sT  1991 Mar 31  2:00s
-                        8:00   Russia  YAK%sT  1992 Jan 19  2:00s
-                        9:00   Russia  YAK%sT  2004
-                       10:00   Russia  VLA%sT  2011 Mar 27  2:00s
-                       11:00   -       VLAT    2011 Sep 13  0:00s # Decree 725?
-                       10:00   -       YAKT    2014 Oct 26  2:00s
-                        9:00   -       YAKT
+                        8:00   -       +08     1930 Jun 21
+                        9:00   Russia  +09/+10 1991 Mar 31  2:00s
+                        8:00   Russia  +08/+09 1992 Jan 19  2:00s
+                        9:00   Russia  +09/+10 2004
+                       10:00   Russia  +10/+11 2011 Mar 27  2:00s
+                       11:00   -       +11     2011 Sep 13  0:00s # Decree 725?
+                       10:00   -       +10     2014 Oct 26  2:00s
+                        9:00   -       +09
 
 
 # From Tim Parenti (2014-07-03):
@@ -3024,15 +3038,14 @@ Zone Asia/Khandyga       9:02:13 -      LMT     1919 Dec 15
 
 # The Zone name should be Asia/Yuzhno-Sakhalinsk, but that's too long.
 Zone Asia/Sakhalin      9:30:48 -      LMT     1905 Aug 23
-                        9:00   -       JCST    1937 Oct  1
-                        9:00   -       JST     1945 Aug 25
-                       11:00   Russia  SAK%sT  1991 Mar 31  2:00s # Sakhalin T
-                       10:00   Russia  SAK%sT  1992 Jan 19  2:00s
-                       11:00   Russia  SAK%sT  1997 Mar lastSun  2:00s
-                       10:00   Russia  SAK%sT  2011 Mar 27  2:00s
-                       11:00   -       SAKT    2014 Oct 26  2:00s
-                       10:00   -       SAKT    2016 Mar 27  2:00s
-                       11:00   -       SAKT
+                        9:00   -       +09     1945 Aug 25
+                       11:00   Russia  +11/+12 1991 Mar 31  2:00s # Sakhalin T
+                       10:00   Russia  +10/+11 1992 Jan 19  2:00s
+                       11:00   Russia  +11/+12 1997 Mar lastSun  2:00s
+                       10:00   Russia  +10/+11 2011 Mar 27  2:00s
+                       11:00   -       +11     2014 Oct 26  2:00s
+                       10:00   -       +10     2016 Mar 27  2:00s
+                       11:00   -       +11
 
 
 # From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2009-11-29):
@@ -3055,13 +3068,13 @@ Zone Asia/Sakhalin       9:30:48 -      LMT     1905 Aug 23
 # http://publication.pravo.gov.ru/Document/View/0001201604050038
 
 Zone Asia/Magadan      10:03:12 -      LMT     1924 May  2
-                       10:00   -       MAGT    1930 Jun 21 # Magadan Time
-                       11:00   Russia  MAG%sT  1991 Mar 31  2:00s
-                       10:00   Russia  MAG%sT  1992 Jan 19  2:00s
-                       11:00   Russia  MAG%sT  2011 Mar 27  2:00s
-                       12:00   -       MAGT    2014 Oct 26  2:00s
-                       10:00   -       MAGT    2016 Apr 24  2:00s
-                       11:00   -       MAGT
+                       10:00   -       +10     1930 Jun 21 # Magadan Time
+                       11:00   Russia  +11/+12 1991 Mar 31  2:00s
+                       10:00   Russia  +10/+11 1992 Jan 19  2:00s
+                       11:00   Russia  +11/+12 2011 Mar 27  2:00s
+                       12:00   -       +12     2014 Oct 26  2:00s
+                       10:00   -       +10     2016 Apr 24  2:00s
+                       11:00   -       +11
 
 
 # From Tim Parenti (2014-07-06):
@@ -3104,17 +3117,14 @@ Zone Asia/Magadan       10:03:12 -      LMT     1924 May  2
 # in Russian.)  In addition, Srednekolymsk appears to be a much older
 # settlement and the population of Zyryanka seems to be declining.
 # Go with Srednekolymsk.
-#
-# Since Magadan Oblast moves to UTC+10 on 2014-10-26, we cannot keep using MAGT
-# as the abbreviation.  Use SRET instead.
 
 Zone Asia/Srednekolymsk        10:14:52 -      LMT     1924 May  2
-                       10:00   -       MAGT    1930 Jun 21 # Magadan Time
-                       11:00   Russia  MAG%sT  1991 Mar 31  2:00s
-                       10:00   Russia  MAG%sT  1992 Jan 19  2:00s
-                       11:00   Russia  MAG%sT  2011 Mar 27  2:00s
-                       12:00   -       MAGT    2014 Oct 26  2:00s
-                       11:00   -       SRET    # Srednekolymsk Time
+                       10:00   -       +10     1930 Jun 21
+                       11:00   Russia  +11/+12 1991 Mar 31  2:00s
+                       10:00   Russia  +10/+11 1992 Jan 19  2:00s
+                       11:00   Russia  +11/+12 2011 Mar 27  2:00s
+                       12:00   -       +12     2014 Oct 26  2:00s
+                       11:00   -       +11
 
 
 # From Tim Parenti (2014-07-03):
@@ -3132,14 +3142,14 @@ Zone Asia/Srednekolymsk 10:14:52 -      LMT     1924 May  2
 # UTC+12 since at least then, too.
 
 Zone Asia/Ust-Nera      9:32:54 -      LMT     1919 Dec 15
-                        8:00   -       YAKT    1930 Jun 21 # Yakutsk Time
-                        9:00   Russia  YAKT    1981 Apr  1
-                       11:00   Russia  MAG%sT  1991 Mar 31  2:00s
-                       10:00   Russia  MAG%sT  1992 Jan 19  2:00s
-                       11:00   Russia  MAG%sT  2011 Mar 27  2:00s
-                       12:00   -       MAGT    2011 Sep 13  0:00s # Decree 725?
-                       11:00   -       VLAT    2014 Oct 26  2:00s
-                       10:00   -       VLAT
+                        8:00   -       +08     1930 Jun 21
+                        9:00   Russia  +09/+10 1981 Apr  1
+                       11:00   Russia  +11/+12 1991 Mar 31  2:00s
+                       10:00   Russia  +10/+11 1992 Jan 19  2:00s
+                       11:00   Russia  +11/+12 2011 Mar 27  2:00s
+                       12:00   -       +12     2011 Sep 13  0:00s # Decree 725?
+                       11:00   -       +11     2014 Oct 26  2:00s
+                       10:00   -       +10
 
 
 # From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
@@ -3152,12 +3162,12 @@ Zone Asia/Ust-Nera       9:32:54 -      LMT     1919 Dec 15
 # The Zone name should be Asia/Petropavlovsk-Kamchatski or perhaps
 # Asia/Petropavlovsk-Kamchatsky, but these are too long.
 Zone Asia/Kamchatka    10:34:36 -      LMT     1922 Nov 10
-                       11:00   -       PETT    1930 Jun 21 # P-K Time
-                       12:00   Russia  PET%sT  1991 Mar 31  2:00s
-                       11:00   Russia  PET%sT  1992 Jan 19  2:00s
-                       12:00   Russia  PET%sT  2010 Mar 28  2:00s
-                       11:00   Russia  PET%sT  2011 Mar 27  2:00s
-                       12:00   -       PETT
+                       11:00   -       +11     1930 Jun 21
+                       12:00   Russia  +12/+13 1991 Mar 31  2:00s
+                       11:00   Russia  +11/+12 1992 Jan 19  2:00s
+                       12:00   Russia  +12/+13 2010 Mar 28  2:00s
+                       11:00   Russia  +11/+12 2011 Mar 27  2:00s
+                       12:00   -       +12
 
 
 # From Tim Parenti (2014-07-03):
@@ -3165,13 +3175,13 @@ Zone Asia/Kamchatka     10:34:36 -      LMT     1922 Nov 10
 # 87   RU-CHU  Chukotka Autonomous Okrug
 
 Zone Asia/Anadyr       11:49:56 -      LMT     1924 May  2
-                       12:00   -       ANAT    1930 Jun 21 # Anadyr Time
-                       13:00   Russia  ANA%sT  1982 Apr  1  0:00s
-                       12:00   Russia  ANA%sT  1991 Mar 31  2:00s
-                       11:00   Russia  ANA%sT  1992 Jan 19  2:00s
-                       12:00   Russia  ANA%sT  2010 Mar 28  2:00s
-                       11:00   Russia  ANA%sT  2011 Mar 27  2:00s
-                       12:00   -       ANAT
+                       12:00   -       +12     1930 Jun 21
+                       13:00   Russia  +13/+14 1982 Apr  1  0:00s
+                       12:00   Russia  +12/+13 1991 Mar 31  2:00s
+                       11:00   Russia  +11/+12 1992 Jan 19  2:00s
+                       12:00   Russia  +12/+13 2010 Mar 28  2:00s
+                       11:00   Russia  +11/+12 2011 Mar 27  2:00s
+                       12:00   -       +12
 
 
 # San Marino
@@ -3430,22 +3440,24 @@ Zone    Europe/Zurich   0:34:08 -       LMT     1853 Jul 16 # See above comment.
 
 # Turkey
 
-# From Amar Devegowda (2007-01-03):
-# The time zone rules for Istanbul, Turkey have not been changed for years now.
-# ... The latest rules are available at:
-# http://www.timeanddate.com/worldclock/timezone.html?n=107
-# From Steffen Thorsen (2007-01-03):
-# I have been able to find press records back to 1996 which all say that
-# DST started 01:00 local time and end at 02:00 local time.  I am not sure
-# what happened before that.  One example for each year from 1996 to 2001:
-# http://newspot.byegm.gov.tr/arsiv/1996/21/N4.htm
-# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING97/03/97X03X25.TXT
-# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING98/03/98X03X02.HTM
-# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING99/10/99X10X26.HTM#%2016
-# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING2000/03/00X03X06.HTM#%2021
-# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING2001/03/23x03x01.HTM#%2027
-# From Paul Eggert (2007-01-03):
-# Prefer the above source to Shanks & Pottenger for time stamps after 1990.
+# From Kıvanç Yazan (2016-09-25):
+# 1) For 1986-2006, DST started at 01:00 local and ended at 02:00 local, with
+#    no exceptions.
+# 2) 1994's lastSun was overridden with Mar 20 ...
+# Here are official papers:
+# http://www.resmigazete.gov.tr/arsiv/19032.pdf  - page 2 for 1986
+# http://www.resmigazete.gov.tr/arsiv/19400.pdf  - page 4 for 1987
+# http://www.resmigazete.gov.tr/arsiv/19752.pdf  - page 15 for 1988
+# http://www.resmigazete.gov.tr/arsiv/20102.pdf  - page 6 for 1989
+# http://www.resmigazete.gov.tr/arsiv/20464.pdf  - page 1 for 1990 - 1992
+# http://www.resmigazete.gov.tr/arsiv/21531.pdf  - page 15 for 1993 - 1995
+# http://www.resmigazete.gov.tr/arsiv/21879.pdf  - page 1 for overriding 1994
+# http://www.resmigazete.gov.tr/arsiv/22588.pdf  - page 1 for 1996, 1997
+# http://www.resmigazete.gov.tr/arsiv/23286.pdf  - page 10 for 1998 - 2000
+# http://www.resmigazete.gov.tr/eskiler/2001/03/20010324.htm#2  - for 2001
+# http://www.resmigazete.gov.tr/eskiler/2002/03/20020316.htm#2  - for 2002-2006
+# From Paul Eggert (2016-09-25):
+# Prefer the above sources to Shanks & Pottenger for time stamps after 1985.
 
 # From Steffen Thorsen (2007-03-09):
 # Starting 2007 though, it seems that they are adopting EU's 1:00 UTC
@@ -3492,6 +3504,14 @@ Zone     Europe/Zurich   0:34:08 -       LMT     1853 Jul 16 # See above comment.
 # Engineered Standard Time," said Twitter user @aysekarahasan.
 # http://www.bbc.com/news/world-europe-34631326
 
+# From Burak AYDIN (2016-09-08):
+# Turkey will stay in Daylight Saving Time even in winter....
+# http://www.resmigazete.gov.tr/eskiler/2016/09/20160908-2.pdf
+#
+# From Paul Eggert (2016-09-07):
+# The change is permanent, so this is the new standard time in Turkey.
+# It takes effect today, which is not much notice.
+
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER/S
 Rule   Turkey  1916    only    -       May      1      0:00    1:00    S
 Rule   Turkey  1916    only    -       Oct      1      0:00    0       -
@@ -3563,7 +3583,8 @@ Zone      Europe/Istanbul 1:55:52 -       LMT     1880
                        2:00    -       EET     2014 Mar 31  1:00u
                        2:00    EU      EE%sT   2015 Oct 25  1:00u
                        2:00    1:00    EEST    2015 Nov  8  1:00u
-                       2:00    EU      EE%sT
+                       2:00    EU      EE%sT   2016 Sep  7
+                       3:00    -       +03
 Link   Europe/Istanbul Asia/Istanbul   # Istanbul is in both continents.
 
 # Ukraine
index 7552796..22fa785 100644 (file)
 #              Boulder, Colorado
 #              Judah.Levine@nist.gov
 #
-#      Last Update of leap second values:   5 January 2015
+#      Last Update of leap second values:   8 July 2016
 #
 #      The following line shows this last update date in NTP timestamp
 #      format. This is the date on which the most recent change to
 #      be identified by the unique pair of characters in the first two
 #      columns as shown below.
 #
-#$      3629404800
+#$      3676924800
 #
 #      The NTP timestamps are in units of seconds since the NTP epoch,
 #      which is 1 January 1900, 00:00:00. The Modified Julian Day number
 #      current -- the update time stamp, the data and the name of the file
 #      will not change.
 #
-#      Updated through IERS Bulletin C51
-#      File expires on:  28 December 2016
+#      Updated through IERS Bulletin C52
+#      File expires on:  28 June 2017
 #
-#@     3691872000
+#@     3707596800
 #
 2272060800     10      # 1 Jan 1972
 2287785600     11      # 1 Jul 1972
 3439756800     34      # 1 Jan 2009
 3550089600     35      # 1 Jul 2012
 3644697600     36      # 1 Jul 2015
+3692217600     37      # 1 Jan 2017
 #
 #      the following special comment contains the
 #      hash value of the data in this file computed
 #      the hash line is also ignored in the
 #      computation.
 #
-#h     afc03691 8ff53838 42080ba1 cdd22f1 48192c10
+#h     dacf2c42 2c4765d6 3c797af8 2cf630eb 699c8c67
index 73befed..b4411f9 100644 (file)
@@ -56,6 +56,7 @@ Leap  2005    Dec     31      23:59:60        +       S
 Leap   2008    Dec     31      23:59:60        +       S
 Leap   2012    Jun     30      23:59:60        +       S
 Leap   2015    Jun     30      23:59:60        +       S
+Leap   2016    Dec     31      23:59:60        +       S
 
-#      Updated through IERS Bulletin C51
-#      File expires on:  28 December 2016
+#      Updated through IERS Bulletin C52
+#      File expires on:  28 June 2017
index 276ce34..385b6bb 100644 (file)
@@ -1510,7 +1510,7 @@ gmtsub(struct state const *sp, time_t const *timep, int_fast32_t offset,
 #ifdef TM_ZONE
        /*
        ** Could get fancy here and deliver something such as
-       ** "UT+xxxx" or "UT-xxxx" if offset is non-zero,
+       ** "+xx" or "-xx" if offset is non-zero,
        ** but this is no time for a treasure hunt.
        */
        tmp->TM_ZONE = ((char *)
@@ -2254,15 +2254,39 @@ posix2time(time_t t)
 
 #endif /* defined STD_INSPIRED */
 
-#ifdef time_tz
+#if defined time_tz || EPOCH_LOCAL || EPOCH_OFFSET != 0
+
+# ifndef USG_COMPAT
+#  define daylight 0
+#  define timezone 0
+# endif
+# ifndef ALTZONE
+#  define altzone 0
+# endif
 
 /* Convert from the underlying system's time_t to the ersatz time_tz,
-   which is called 'time_t' in this file.  */
+   which is called 'time_t' in this file.  Typically, this merely
+   converts the time's integer width.  On some platforms, the system
+   time is local time not UT, or uses some epoch other than the POSIX
+   epoch.
+
+   Although this code appears to define a function named 'time' that
+   returns time_t, the macros in private.h cause this code to actually
+   define a function named 'tz_time' that returns tz_time_t.  The call
+   to sys_time invokes the underlying system's 'time' function.  */
 
 time_t
 time(time_t *p)
 {
   time_t r = sys_time(0);
+  if (r != (time_t) -1) {
+    int_fast32_t offset = EPOCH_LOCAL ? (daylight ? timezone : altzone) : 0;
+    if (increment_overflow32(&offset, -EPOCH_OFFSET)
+       || increment_overflow_time (&r, offset)) {
+      errno = EOVERFLOW;
+      r = -1;
+    }
+  }
   if (p)
     *p = r;
   return r;
index 62277f7..c3e22dc 100644 (file)
@@ -128,6 +128,13 @@ ASCII minus
 ASCII plus
 .RB ( + ),
 and NUL bytes are allowed.
+Alternatively, a designation can be surrounded by angle brackets
+.B <
+and
+.BR > ;
+in this case, the designation can contain any characters other than
+.B >
+and NUL.
 .TP
 .I offset
 Indicates the value one must add to the local time to arrive at
index 4df0e4a..791bfb7 100644 (file)
@@ -65,6 +65,10 @@ DESCRIPTION
                              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.
index b3d66a7..e1ed9e4 100644 (file)
@@ -437,6 +437,37 @@ Zone America/Denver        -6:59:56 -      LMT     1883 Nov 18 12:00:04
 # north of the Salmon River, and the towns of Burgdorf and Warren),
 # Nevada (except West Wendover), Oregon (except the northern 3/4 of
 # Malheur county), and Washington
+
+# From Paul Eggert (2016-08-20):
+# In early February 1948, in response to California's electricity shortage,
+# PG&E changed power frequency from 60 to 59.5 Hz during daylight hours,
+# causing electric clocks to lose six minutes per day.  (This did not change
+# legal time, and is not part of the data here.)  See:
+# Ross SA. An energy crisis from the past: Northern California in 1948.
+# Working Paper No. 8, Institute of Governmental Studies, UC Berkeley,
+# 1973-11.  http://escholarship.org/uc/item/8x22k30c
+#
+# In another measure to save electricity, DST was instituted from 1948-03-14
+# at 02:01 to 1949-01-16 at 02:00, with the governor having the option to move
+# the fallback transition earlier.  See pages 3-4 of:
+# http://clerk.assembly.ca.gov/sites/clerk.assembly.ca.gov/files/archive/Statutes/1948/48Vol1_Chapters.pdf
+#
+# In response:
+#
+#   Governor Warren received a torrent of objecting mail, and it is not too much
+#   to speculate that the objections to Daylight Saving Time were one important
+#   factor in the defeat of the Dewey-Warren Presidential ticket in California.
+#     -- Ross, p 25
+#
+# On December 8 the governor exercised the option, setting the date to January 1
+# (LA Times 1948-12-09).  The transition time was 02:00 (LA Times 1949-01-01).
+#
+# Despite the controversy, in 1949 California voters approved Proposition 12,
+# which established DST from April's last Sunday at 01:00 until September's
+# last Sunday at 02:00. This was amended by 1962's Proposition 6, which changed
+# the fall-back date to October's last Sunday. See:
+# http://repository.uchastings.edu/cgi/viewcontent.cgi?article=1501&context=ca_ballot_props
+# http://repository.uchastings.edu/cgi/viewcontent.cgi?article=1636&context=ca_ballot_props
 #
 # Rule NAME    FROM    TO      TYPE    IN      ON      AT      SAVE    LETTER
 Rule   CA      1948    only    -       Mar     14      2:01    1:00    D
@@ -3305,7 +3336,7 @@ Zone America/Miquelon     -3:44:40 -      LMT     1911 May 15 # St Pierre
 # indicating that the normal ET rules are followed.
 #
 # From Paul Eggert (2014-08-19):
-# The 2014-08-13 Cabinet meeting decided to stay on UTC-4 year-round.  See:
+# The 2014-08-13 Cabinet meeting decided to stay on UT -04 year-round.  See:
 # http://tcweeklynews.com/daylight-savings-time-to-be-maintained-p5353-127.htm
 # Model this as a switch from EST/EDT to AST ...
 # From Chris Walton (2014-11-04):
index b49a713..26ac30c 100644 (file)
@@ -5,7 +5,7 @@ Group:          Base/Configuration
 Url:            http://www.gnu.org/software/libc/libc.html
 Requires(pre):         filesystem, coreutils
 # COMMON-BEGIN
-Version:        2016f
+Version:        2016i
 Release:        0
 Source:         ftp://ftp.iana.org/tz/releases/tzdata%{version}.tar.gz
 Source1001:     tzdata.manifest
index 941e91b..0bd1d00 100644 (file)
--- a/private.h
+++ b/private.h
@@ -15,6 +15,7 @@
 ** Thank you!
 */
 
+/* This string was in the Factory zone through version 2016f.  */
 #define GRANDPARENTED  "Local time zone must be set--see zic manual page"
 
 /*
@@ -77,9 +78,9 @@
 
 /* Enable tm_gmtoff and tm_zone on GNUish systems.  */
 #define _GNU_SOURCE 1
-/* Fix asctime_r on Solaris 10.  */
+/* Fix asctime_r on Solaris 11.  */
 #define _POSIX_PTHREAD_SEMANTICS 1
-/* Enable strtoimax on Solaris 10.  */
+/* Enable strtoimax on pre-C99 Solaris 11.  */
 #define __EXTENSIONS__ 1
 
 /*
 
 /*
 ** Define HAVE_STDINT_H's default value here, rather than at the
-** start, since __GLIBC__'s value depends on previously-included
-** files.
-** (glibc 2.1 and later have stdint.h, even with pre-C99 compilers.)
+** start, since __GLIBC__ and INTMAX_MAX's values depend on
+** previously-included files.  glibc 2.1 and Solaris 10 and later have
+** stdint.h, even with pre-C99 compilers.
 */
 #ifndef HAVE_STDINT_H
 #define HAVE_STDINT_H \
    (199901 <= __STDC_VERSION__ \
     || 2 < __GLIBC__ + (1 <= __GLIBC_MINOR__)  \
-    || __CYGWIN__)
+    || __CYGWIN__ || INTMAX_MAX)
 #endif /* !defined HAVE_STDINT_H */
 
 #if HAVE_STDINT_H
@@ -208,14 +209,18 @@ typedef long              int_fast64_t;
 # endif
 #endif
 
-#ifndef SCNdFAST64
+#ifndef PRIdFAST64
 # if INT_FAST64_MAX == LLONG_MAX
-#  define SCNdFAST64 "lld"
+#  define PRIdFAST64 "lld"
 # else
-#  define SCNdFAST64 "ld"
+#  define PRIdFAST64 "ld"
 # endif
 #endif
 
+#ifndef SCNdFAST64
+# define SCNdFAST64 PRIdFAST64
+#endif
+
 #ifndef INT_FAST32_MAX
 # if INT_MAX >> 31 == 0
 typedef long int_fast32_t;
@@ -315,6 +320,13 @@ typedef unsigned long uintmax_t;
 ** Workarounds for compilers/systems.
 */
 
+#ifndef EPOCH_LOCAL
+# define EPOCH_LOCAL 0
+#endif
+#ifndef EPOCH_OFFSET
+# define EPOCH_OFFSET 0
+#endif
+
 /*
 ** Compile with -Dtime_tz=T to build the tz package with a private
 ** time_t type equivalent to T rather than the system-supplied time_t.
@@ -322,7 +334,7 @@ typedef unsigned long uintmax_t;
 ** (e.g., time_t wider than 'long', or unsigned time_t) even on
 ** typical platforms.
 */
-#ifdef time_tz
+#if defined time_tz || EPOCH_LOCAL || EPOCH_OFFSET != 0
 # ifdef LOCALTIME_IMPLEMENTATION
 static time_t sys_time(time_t *x) { return time(x); }
 # endif
@@ -507,9 +519,28 @@ time_t time2posix_z(timezone_t, time_t) ATTRIBUTE_PURE;
 #define MINVAL(t, b)                                           \
   ((t) (TYPE_SIGNED(t) ? - TWOS_COMPLEMENT(t) - MAXVAL(t, b) : 0))
 
-/* The minimum and maximum finite time values.  This assumes no padding.  */
+/* The minimum and maximum finite time values.  This implementation
+   assumes no padding if time_t is signed and either the compiler is
+   pre-C11 or time_t is not one of the standard signed integer types.  */
+#if 201112 <= __STDC_VERSION__
+static time_t const time_t_min
+  = (TYPE_SIGNED(time_t)
+     ? _Generic((time_t) 0,
+               signed char: SCHAR_MIN, short: SHRT_MIN,
+               int: INT_MIN, long: LONG_MIN, long long: LLONG_MIN,
+               default: MINVAL(time_t, TYPE_BIT(time_t)))
+     : 0);
+static time_t const time_t_max
+  = (TYPE_SIGNED(time_t)
+     ? _Generic((time_t) 0,
+               signed char: SCHAR_MAX, short: SHRT_MAX,
+               int: INT_MAX, long: LONG_MAX, long long: LLONG_MAX,
+               default: MAXVAL(time_t, TYPE_BIT(time_t)))
+     : -1);
+#else
 static time_t const time_t_min = MINVAL(time_t, TYPE_BIT(time_t));
 static time_t const time_t_max = MAXVAL(time_t, TYPE_BIT(time_t));
+#endif
 
 #ifndef INT_STRLEN_MAXIMUM
 /*
index 1c38f63..5321451 100644 (file)
@@ -410,9 +410,9 @@ Rule        Arg     2008    only    -       Oct     Sun>=15 0:00    1:00    S
 # stuck on Summer daylight savings time even though the summer is over.
 
 # From Paul Eggert (2013-09-05):
-# Perhaps San Luis operates on the legal fiction that it is at UTC-4
+# Perhaps San Luis operates on the legal fiction that it is at -04
 # with perpetual summer time, but ordinary usage typically seems to
-# just say it's at UTC-3; see, for example,
+# just say it's at -03; see, for example,
 # http://es.wikipedia.org/wiki/Hora_oficial_argentina
 # We've documented similar situations as being plain changes to
 # standard time, so let's do that here too.  This does not change UTC
index f75f9fd..984ead5 100644 (file)
@@ -137,14 +137,11 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *t)
 
        tzset();
        warn = IN_NONE;
-       p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn);
+       p = _fmt(format, t, s, s + maxsize, &warn);
 #ifndef NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU
        if (warn != IN_NONE && getenv(YEAR_2000_NAME) != NULL) {
                fprintf(stderr, "\n");
-               if (format == NULL)
-                       fprintf(stderr, "NULL strftime format ");
-               else    fprintf(stderr, "strftime format \"%s\" ",
-                               format);
+               fprintf(stderr, "strftime format \"%s\" ", format);
                fprintf(stderr, "yields only two digits of years in ");
                if (warn == IN_SOME)
                        fprintf(stderr, "some locales");
@@ -499,15 +496,14 @@ label:
                                */
                                continue;
                        case 'z':
+#if defined TM_GMTOFF || defined USG_COMPAT || defined ALTZONE
                                {
                                long            diff;
                                char const *    sign;
 
-                               if (t->tm_isdst < 0)
-                                       continue;
-#ifdef TM_GMTOFF
+# ifdef TM_GMTOFF
                                diff = t->TM_GMTOFF;
-#else /* !defined TM_GMTOFF */
+# else
                                /*
                                ** C99 says that the UT offset must
                                ** be computed by looking only at
@@ -527,19 +523,21 @@ label:
                                ** determinable, so output nothing if the
                                ** appropriate variables are not available.
                                */
+                               if (t->tm_isdst < 0)
+                                       continue;
                                if (t->tm_isdst == 0)
-#ifdef USG_COMPAT
+#  ifdef USG_COMPAT
                                        diff = -timezone;
-#else /* !defined USG_COMPAT */
+#  else
                                        continue;
-#endif /* !defined USG_COMPAT */
+#  endif
                                else
-#ifdef ALTZONE
+#  ifdef ALTZONE
                                        diff = -altzone;
-#else /* !defined ALTZONE */
+#  else
                                        continue;
-#endif /* !defined ALTZONE */
-#endif /* !defined TM_GMTOFF */
+#  endif
+# endif
                                if (diff < 0) {
                                        sign = "-";
                                        diff = -diff;
@@ -550,6 +548,7 @@ label:
                                        (diff % MINSPERHOUR);
                                pt = _conv(diff, "%04d", pt, ptlim);
                                }
+#endif
                                continue;
                        case '+':
                                pt = _fmt(Locale->date_fmt, t, pt, ptlim,
index c06d805..8ec9e21 100644 (file)
@@ -24,6 +24,184 @@ into problems that programmers have with timekeeping.</li>
 Bell Science extravaganza, with Frank Baxter, Richard Deacon, and Les Tremayne.
 (<a href="http://www.imdb.com/title/tt0154110/">IMDb entry</a>.)</li>
 </ul>
+<h2>Movies</h2>
+<ul>
+<li>
+In the 1946 movie <em>A Matter of Life and Death</em>
+(U.S. title <em>Stairway to Heaven</em>)
+there is a reference to British Double Summer Time.
+The time does not play a large part in the plot;
+it's just a passing reference to the time when one of the
+characters was supposed to have died (but didn't).
+The IMDb page is at
+<a href="http://us.imdb.com/title/tt0038733/">
+http://us.imdb.com/title/tt0038733/
+</a>. (Dave Cantor)
+<li>
+The 1953 railway comedy movie <em>The Titfield Thunderbolt</em> includes a
+play on words on British Double Summer Time. Valentine's wife wants
+him to leave the pub and asks him, "Do you know what time it is?"
+And he, happy where he is, replies: "Yes, my love. Summer double time."
+IMDb page:
+<a href="http://us.imdb.com/title/tt0046436/">
+http://us.imdb.com/title/tt0046436/
+</a>. (Mark Brader, 2009-10-02)
+</li>
+<li>
+The premise of the 1999 caper movie <em>Entrapment</em> involves computers
+in an international banking network being shut down briefly at
+midnight in each time zone to avoid any problems at the transition
+from the year 1999 to 2000 in that zone. (Hmmmm.) If this shutdown
+is extended by 10 seconds, it will create a one-time opportunity for
+a gigantic computerized theft. To achieve this, at one location the
+crooks interfere with the microwave system supplying time signals to
+the computer, advancing the time by 0.1 second each minute over the
+last hour of 1999. (So this movie teaches us that 0.1 &times; 60 = 10.)
+IMDb page:
+<a href="http://us.imdb.com/title/tt0137494/">
+http://us.imdb.com/title/tt0137494/
+</a>. (Mark Brader, 2009-10-02)
+</li>
+<li>
+One mustn't forget the
+<a href="https://www.youtube.com/watch?v=k4EUTMPuvHo">trailer</a>
+(2014; 2:23) for the movie <em>Daylight Saving</em>.
+</li>
+</ul>
+<h2>TV episodes</h2>
+<ul>
+<li>
+An episode of <em>The Adventures of Superman</em> entitled "The Mysterious
+Cube," first aired 1958-02-24, had Superman convincing the controllers
+of the Arlington Time Signal to broadcast ahead of actual time;
+doing so got a crook trying to be declared dead to
+emerge a bit too early from the titular enclosure.
+</li>
+<li>
+The 1960s ITC television series <em>The Prisoner</em> included an episode
+entitled "The Chimes of Big Ben" in which our protagonist tumbled to
+the fraudulent nature of a Poland-to-England escape upon hearing "Big
+Ben" chiming on Polish local time.
+</li>
+<li>
+The series <em>Seinfeld</em> included an episode entitled "The Susie," first
+broadcast 1997-02-13, in which Kramer decides that daylight saving time
+isn't coming fast enough, so he sets his watch ahead an hour.
+</li>
+<li>
+The "20 Hours in America" episode of <em>The West Wing</em>,
+first aired 2002-09-25, contained a <a
+href="https://www.youtube.com/watch?v=-J1NHzQ1sgc">scene</a> that
+saw White House staffers stranded in Indiana; they thought they had time to
+catch Air Force One but were done in by intra-Indiana local time changes.
+</li>
+<li>
+"In what time zone would you find New York City?" was a $200 question on
+the 1999-11-13 United States airing of <em>Who Wants to Be a Millionaire?</em>,
+and "In 1883, what industry led the movement to divide the U.S. into four time
+zones?" was a $32,000 question on the 2001-05-23 United States airing of
+the same show. At this rate, the million-dollar time-zone
+question should have been asked 2002-06-04.
+</li>
+<li>
+A private jet's mid-flight change of time zones distorts Alison Dubois'
+premonition in the "We Had a Dream" episode of <em>Medium</em>
+(originally aired 2007-02-28).
+</li>
+<li>
+In the <em>30 Rock</em> episode "Anna Howard Shaw Day"
+(first broadcast 2010-02-11),
+Jack Donaghy's date realizes that a Geneva-to-New-York business phone call
+received in the evening must be fake given the difference in local times.
+</li>
+<li>
+In the "Run by the Monkeys" episode of <em>Da Vinci's Inquest</em>
+(first broadcast 2002-11-17),
+a witness in a five-year-old fire case realizes they may not have set
+their clock back when daylight saving ended on the day of the fire,
+introducing the possibility of an hour when arson might have occurred.
+</li>
+<li>
+In "The Todd Couple" episode of <em>Outsourced</em> (first aired 2011-02-10),
+Manmeet sets up Valentine's Day teledates for 6:00 and 9:00pm;
+since one is with a New Yorker and the other with a San Franciscan,
+hilarity ensues.
+(Never mind that this should be 7:30am in Mumbai, yet for some reason the show
+proceeds as though it's also mid-evening there.)
+</li>
+<li>
+In the "14 Days to Go"/"T Minus..." episode of
+<em>You, Me and the Apocalypse</em>
+(first aired 2015-11-11 in the UK, 2016-03-10 in the US),
+the success of a mission to deal with a comet
+hinges on whether or not Russia observes daylight saving time.
+(In the US, the episode first aired in the week before the switch to DST.)
+</li>
+<li>
+"The Lost Hour", <em>Eerie, Indiana</em>, episode 10, NBC, 1991-12-01.
+Despite Indiana's then-lack of DST, Marshall changes his clock with
+unusual consequences.
+</li>
+<li>
+"Time Tunnel", <em>The Adventures of Pete &amp; Pete</em>, season 2, episode 5,
+Nickelodeon, 1994-10-23.
+The two Petes travel back in time an hour on the day that DST ends.
+</li>
+<li>
+"King-Size Homer", <em>The Simpsons</em>, episode 135, Fox, 1995-11-05.
+Homer, working from home, remarks "8:58, first
+time I've ever been early for work. Except for all those daylight
+savings days. Lousy farmers."
+</li>
+<li>
+"Tracks", <em>The Good Wife</em>, season 7, episode 12,
+CBS, 2016-01-17.
+The applicability of a contract hinges on the
+time zone associated with a video time stamp.
+</li>
+</ul>
+<h2>Books, plays, and magazines</h2>
+<ul>
+<li>
+Jules Verne, <em>Around the World in Eighty Days</em>
+(<em>Le tour du monde en quatre-vingts jours</em>).
+Wall-clock time plays a central role in the plot.
+European readers of the 1870s clearly held the U.S. press in
+deep contempt; the protagonists cross the U.S. without once
+reading a paper.
+Available versions include
+<a href="http://www.literature.org/Works/Jules-Verne/eighty">an English
+translation</a>, and
+<a href="http://fourmilab.ch/etexts/www/tdm80j">the original French</a>
+"with illustrations from the original 1873 French-language edition".
+</li>
+<li>
+Nick Enright, <em>Daylight Saving</em>, 1989.
+A fast-paced comedy about love and loneliness as the clocks turn back.
+</li>
+<li>
+Umberto Eco, <em>The Island of the Day Before</em>
+(<em>L'isola del giorno prima</em>), 1994.
+"...the story of a 17th century Italian nobleman trapped near an island
+on the International Date Line.  Time and time zones play an integral
+part in the novel." (Paul Eggert, 2006-04-22)
+</li>
+<li>
+John Dunning, <a
+href="http://books.simonandschuster.com/Two-OClock-Eastern-Wartime/John-Dunning/9781439171530"><em>Two
+O'Clock, Eastern Wartime</em></a>, 2001.
+Mystery, history, daylight saving time, and old-time radio.
+</li>
+<li>
+Surrealist artist Guy Billout's work "Date Line" appeared on page 103
+of the 1999-11 <em>Atlantic Monthly</em>.
+</li>
+<li>
+"Gloom, Gloom, Go Away" by Walter Kirn appeared on page 106 of <em>Time</em>
+magazine's 2002-11-11 issue; among other things, it proposed
+year-round DST 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>
@@ -254,222 +432,14 @@ Supernaw.</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>
 </table>
-
-<h2>TV episodes</h2>
-
-<ul>
-<li>
-An episode of <em>The Adventures of Superman</em> entitled "The Mysterious
-Cube," first aired 1958-02-24, had Superman convincing the controllers
-of the Arlington Time Signal to broadcast ahead of actual time;
-doing so got a crook trying to be declared dead to
-emerge a bit too early from the titular enclosure.
-</li>
-<li>
-The 1960s ITC television series <em>The Prisoner</em> included an episode
-entitled "The Chimes of Big Ben" in which our protagonist tumbled to
-the fraudulent nature of a Poland-to-England escape upon hearing "Big
-Ben" chiming on Polish local time.
-</li>
-<li>
-The series <em>Seinfeld</em> included an episode entitled "The Susie," first
-broadcast 1997-02-13, in which Kramer decides that daylight saving time
-isn't coming fast enough, so he sets his watch ahead an hour.
-</li>
-<li>
-The "20 Hours in America" episode of <em>The West Wing</em>,
-first aired 2002-09-25,
-saw White House staffers stranded in Indiana; they thought they had time to
-catch Air Force One but were done in by intra-Indiana local time changes.
-</li>
-<li>
-"In what time zone would you find New York City?" was a $200 question on
-the 1999-11-13 United States airing of <em>Who Wants to Be a Millionaire?</em>,
-and "In 1883, what industry led the movement to divide the U.S. into four time
-zones?" was a $32,000 question on the 2001-05-23 United States airing of
-the same show. At this rate, the million-dollar time-zone
-question should have been asked 2002-06-04.
-</li>
-<li>
-A private jet's mid-flight change of time zones distorts Alison Dubois'
-premonition in the "We Had a Dream" episode of <em>Medium</em>
-(originally aired 2007-02-28).
-</li>
-<li>
-In the <em>30 Rock</em> episode "Anna Howard Shaw Day"
-(first broadcast 2010-02-11),
-Jack Donaghy's date realizes that a Geneva-to-New-York business phone call
-received in the evening must be fake given the difference in local times.
-</li>
-<li>
-In the "Run by the Monkeys" episode of <em>Da Vinci's Inquest</em>
-(first broadcast 2002-11-17),
-a witness in a five-year-old fire case realizes they may not have set
-their clock back when daylight saving ended on the day of the fire,
-introducing the possibility of an hour when arson might have occurred.
-</li>
-<li>
-In "The Todd Couple" episode of <em>Outsourced</em> (first aired 2011-02-10),
-Manmeet sets up Valentine's Day teledates for 6:00 and 9:00pm;
-since one is with a New Yorker and the other with a San Franciscan,
-hilarity ensues.
-(Never mind that this should be 7:30am in Mumbai, yet for some reason the show
-proceeds as though it's also mid-evening there.)
-</li>
-<li>
-In the "14 Days to Go"/"T Minus..." episode of
-<em>You, Me and the Apocalypse</em>
-(first aired 2015-11-11 in the UK, 2016-03-10 in the US),
-the success of a mission to deal with a comet
-hinges on whether or not Russia observes daylight saving time.
-(In the US, the episode first aired in the week before the switch to DST.)
-</li>
-</ul>
-
-<table>
-<tr><td>TV episode title</td><td>The Lost Hour</td>
-<tr><td>TV series</td><td><em>Eerie, Indiana</em></td>
-<tr><td>TV episode number</td><td>10</td>
-<tr><td>Network</td><td>NBC</td>
-<tr><td>Air date</td><td>1991-12-01</td>
-<tr><td>Notes</td><td>Despite Indiana's then-lack of DST, Marshall changes his clock with unusual consequences.</td></tr>
-<tr><td>&nbsp;</td></tr>
-
-<tr><td>TV episode title</td><td>Time Tunnel</td>
-<tr><td>TV series</td><td><em>The Adventures of Pete &amp; Pete</em></td>
-<tr><td>TV episode number</td><td>5, season 2</td>
-<tr><td>Network</td><td>Nickelodeon</td>
-<tr><td>Air date</td><td>1994-10-23</td>
-<tr><td>Notes</td><td>The two Petes travel back in time an hour on the day that DST ends.</td></tr>
-<tr><td>&nbsp;</td></tr>
-
-<tr><td>TV episode title</td><td>King-Size Homer</td>
-<tr><td>TV series</td><td><em>The Simpsons</em></td>
-<tr><td>TV episode number</td><td>135</td>
-<tr><td>Network</td><td>Fox</td>
-<tr><td>Air date</td><td>1995-11-05</td>
-<tr><td>Notes</td><td>Homer, working from home, remarks "8:58, first
-time I've ever been early for work. Except for all those daylight
-savings days. Lousy farmers."</td></tr>
-<tr><td>&nbsp;</td></tr>
-
-<tr><td>TV episode title</td><td>Tracks</td></tr>
-<tr><td>TV series</td><td><em>The Good Wife</em></td></tr>
-<tr><td>TV episode number</td><td>12, season 7</td></tr>
-<tr><td>Network</td><td>CBS</td></tr>
-<tr><td>Air date</td><td>2016-01-17</td></tr>
-<tr><td>Notes</td><td>The applicability of a contract hinges on the
-time zone associated with a video time stamp.</td></tr>
-</table>
-
-<h2>Books, plays, and magazines</h2>
-
-<table>
-<tr><td>Artist</td><td>Jules Verne</td></tr>
-<tr><td>Book</td><td><em>Around the World in Eighty Days</em>
-(<em>Le tour du monde en quatre-vingts jours</em>)</td></tr>
-<tr><td>Notes</td><td>Wall-clock time plays a central role in the plot.
-European readers of the 1870s clearly held the U.S. press in
-deep contempt; the protagonists cross the U.S. without once
-reading a paper.
-An on-line French-language version of the book
-"with illustrations from the original 1873 French-language edition"
-is available at
-<a href="http://fourmilab.ch/etexts/www/tdm80j">http://fourmilab.ch/etexts/www/tdm80j</a>
-An on-line English-language translation of the book is available at
-<a href="http://www.literature.org/Works/Jules-Verne/eighty">http://www.literature.org/Works/Jules-Verne/eighty</a></td></tr>
-
-<tr><td>&nbsp;</td></tr>
-<tr><td>Artist</td><td>Nick Enright</td></tr>
-<tr><td>Play</td><td><em>Daylight Saving</em></td></tr>
-<tr><td>Copyright Date</td><td>1989</td></tr>
-<tr><td>Notes</td><td>
-A fast-paced comedy about love and loneliness as the clocks turn back.
-</td></tr>
-
-<tr><td>&nbsp;</td></tr>
-<tr><td>Artist</td><td>Umberto Eco</td></tr>
-<tr><td>Book</td><td><em>The Island of the Day Before</em>
-(<em>L'isola del giorno prima</em>)</td></tr>
-<tr><td>Copyright Date</td><td>1994</td></tr>
-<tr><td>Notes</td><td>
-"...the story of a 17th century Italian nobleman trapped near an island
-on the International Date Line.  Time and time zones play an integral
-part in the novel." (Paul Eggert, 2006-04-22)
-</td></tr>
-<tr><td>&nbsp;</td></tr>
-<tr><td>Artist</td><td>John Dunning</td></tr>
-<tr><td>Book</td><td><a
-href="http://books.simonandschuster.com/Two-OClock-Eastern-Wartime/John-Dunning/9781439171530"><em>Two
-O'Clock, Eastern Wartime</em></a></td></tr>
-<tr><td>Copyright Date</td><td>2001</td></tr>
-<tr><td>Notes</td><td>
-Mystery, history, daylight saving time, and old-time radio.
-</td></tr>
-</table>
-<hr>
-<ul>
-<li>
-Surrealist artist Guy Billout's work "Date Line" appeared on page 103
-of the 1999-11 <em>Atlantic Monthly</em>.
-</li>
-<li>
-"Gloom, Gloom, Go Away" by Walter Kirn appeared on page 106 of <em>Time</em>
-magazine's 2002-11-11 issue; among other things, it proposed
-year-round DST as a way of lessening wintertime despair.
-</li>
-</ul>
-<h2>Movies</h2>
-<ul>
-<li>
-In the 1946 movie <em>A Matter of Life and Death</em>
-(U.S. title <em>Stairway to Heaven</em>)
-there is a reference to British Double Summer Time.
-The time does not play a large part in the plot;
-it's just a passing reference to the time when one of the
-characters was supposed to have died (but didn't).
-The IMDb page is at
-<a href="http://us.imdb.com/title/tt0038733/">
-http://us.imdb.com/title/tt0038733/
-</a>. (Dave Cantor)
-<li>
-The 1953 railway comedy movie <em>The Titfield Thunderbolt</em> includes a
-play on words on British Double Summer Time. Valentine's wife wants
-him to leave the pub and asks him, "Do you know what time it is?"
-And he, happy where he is, replies: "Yes, my love. Summer double time."
-IMDb page:
-<a href="http://us.imdb.com/title/tt0046436/">
-http://us.imdb.com/title/tt0046436/
-</a>. (Mark Brader, 2009-10-02)
-</li>
-<li>
-The premise of the 1999 caper movie <em>Entrapment</em> involves computers
-in an international banking network being shut down briefly at
-midnight in each time zone to avoid any problems at the transition
-from the year 1999 to 2000 in that zone. (Hmmmm.) If this shutdown
-is extended by 10 seconds, it will create a one-time opportunity for
-a gigantic computerized theft. To achieve this, at one location the
-crooks interfere with the microwave system supplying time signals to
-the computer, advancing the time by 0.1 second each minute over the
-last hour of 1999. (So this movie teaches us that 0.1 &times; 60 = 10.)
-IMDb page:
-<a href="http://us.imdb.com/title/tt0137494/">
-http://us.imdb.com/title/tt0137494/
-</a>. (Mark Brader, 2009-10-02)
-</li>
-<li>
-One mustn't forget the
-<a href="https://www.youtube.com/watch?v=k4EUTMPuvHo">trailer</a>
-(2014; 2:23) for the movie <em>Daylight Saving</em>.
-</li>
-</ul>
 <h2>Comics</h2>
 <ul>
 <li>
 The webcomic <em>xkcd</em> has the strip
 "<a href='http://xkcd.com/673/'>The Sun</a>" (2009-12-09) and the panels
 "<a href='http://xkcd.com/1017/'>Backward in Time</a>" (2012-02-14),
-"<a href='http://xkcd.com/1061/'>EST</a>" (2012-05-28), and
+"<a href='http://xkcd.com/1061/'>EST</a>" (2012-05-28),
+"<a href='http://xkcd.com/1179/'>ISO 8601</a>" (2013-02-27),
 "<a href='http://xkcd.com/1335/'>Now</a>" (2014-02-26), and
 "<a href='http://xkcd.com/1655/'>Doomsday Clock</a>" (2016-03-14).
 The related book <em>What If?</em> has an entry
index adb4fac..aec8a1c 100644 (file)
@@ -10,7 +10,7 @@
  content="Sources for time zone and daylight saving time data">
 <meta name="DC.Creator" content="Eggert, Paul">
 <meta name="DC.Contributor" content="Olson, Arthur David">
-<meta name="DC.Date" content="2016-06-14">
+<meta name="DC.Date" content="2016-11-01">
 <meta name="DC.Description"
  content="Sources of information about time zones and daylight saving time">
 <meta name="DC.Identifier"
@@ -27,7 +27,7 @@ histories and planned futures are often recorded only fitfully. Here
 is a summary of attempts to organize and record relevant data in this
 area.
 </p>
-<h2>The <code><abbr title="time zone">tz</abbr></code> database</h2>
+<h2 id="tzdb">The <code><abbr title="time zone">tz</abbr></code> database</h2>
 <p>
 The <a href="https://en.wikipedia.org/wiki/Public_domain">public-domain</a>
 time zone database contains code and data
@@ -42,7 +42,7 @@ This database (often called <code>zoneinfo</code> or
 <code><abbr>tz</abbr></code>)
 is used by several implementations,
 including
-<a href="http://www.gnu.org/software/libc/">the
+<a href="https://www.gnu.org/software/libc/">the
 <abbr title="GNU's Not Unix">GNU</abbr>
 C Library</a> (used in
 <a href="https://en.wikipedia.org/wiki/Linux"><abbr>GNU</abbr>/Linux</a>),
@@ -65,13 +65,13 @@ title="Advanced Interactive eXecutive">AIX</abbr></a>,
 <a href="https://en.wikipedia.org/wiki/BlackBerry_10">BlackBerry 10</a>,
 <a href="http://www.apple.com/ios/"><abbr
 title="iPhone OS">iOS</abbr></a>,
-<a href="http://windows.microsoft.com">Microsoft Windows</a>,
+<a href="http://www.apple.com/macos/"><abbr
+title="Mac Operating System">macOS</abbr></a>,
+<a href="https://www.microsoft.com/en-us/windows">Microsoft Windows</a>,
 <a href="http://www.hp.com/go/openvms/">Open<abbr
 title="Virtual Memory System">VMS</abbr></a>,
-<a href="https://www.oracle.com/database/index.html">Oracle Database</a>,
-<a href="http://oracle.com/solaris">Oracle Solaris</a>, and
-<a href="http://www.apple.com/osx/"><abbr title="Operating System Ten">OS
-X</abbr></a>.</p>
+<a href="https://www.oracle.com/database/index.html">Oracle Database</a>, and
+<a href="https://www.oracle.com/solaris">Oracle Solaris</a>.</p>
 <p>
 Each location in the database represents a region where all
 clocks keeping local time have agreed since 1970.
@@ -103,60 +103,62 @@ for time stamps after 1960 this is more precisely <a
 href="https://en.wikipedia.org/wiki/Coordinated_Universal_Time">Coordinated
 Universal Time</a> (<abbr>UTC</abbr>).
 The database also records when daylight saving time was in use,
-along with alphabetic time zone abbreviations such as <abbr>EST</abbr>
+along with some time zone abbreviations such as <abbr>EST</abbr>
 for Eastern Standard Time in the <abbr>US</abbr>.</p>
 <p>
-In the <code><abbr>tz</abbr></code> database's
+The following <a
+href="https://en.wikipedia.org/wiki/Unix_shell">shell</a> commands download
+the latest release's two
+<a href="https://en.wikipedia.org/wiki/Tar_(computing)">tarballs</a>
+to a <abbr>GNU</abbr>/Linux or similar host.</p>
+<pre style="margin-left: 2em"><code>mkdir tzdb
+cd tzdb
+<a href="https://www.gnu.org/software/wget/">wget</a> --retr-symlinks 'ftp://ftp.iana.org/tz/tz*-latest.tar.gz'
+<a href="https://www.gnu.org/software/gzip/">gzip</a> -dc tzcode-latest.tar.gz | <a href="https://www.gnu.org/software/tar/">tar</a> -xf -
+gzip -dc tzdata-latest.tar.gz | tar -xf -
+</code></pre>
+<p>Alternatively, the following shell commands download the same
+release in a single-tarball format containing extra data
+useful for regression testing:</p>
+<pre style="margin-left: 2em"><code>wget --retr-symlinks 'ftp://ftp.iana.org/tz/tzdb-latest.tar.lz'
+<a href="http://www.nongnu.org/lzip/">lzip</a> -dc tzdb-latest.tar.lz | tar -xf -
+</code></pre>
+<p>These commands use convenience links to the latest of the
 <a href="ftp://ftp.iana.org/tz/releases/"><abbr
 title="File Transfer Protocol">FTP</abbr> releases</a>
-the code is in the file <code>tzcode<var>C</var>.tar.gz</code>,
-where <code><var>C</var></code> is the code's version;
-similarly, the data entries are in <code>tzdata<var>D</var>.tar.gz</code>,
-where <code><var>D</var></code> is the data's version.
+of the <code><abbr>tz</abbr></code> database.
+Older releases are in files named
+<code>tzcode<var>V</var>.tar.gz</code>,
+<code>tzdata<var>V</var>.tar.gz</code>, and
+<code>tzdb-<var>V</var>.tar.lz</code>,
+where <code><var>V</var></code> is the version.
 Since 1996, each version has been a four-digit year followed by
 lower-case letter (<samp>a</samp> through <samp>z</samp>,
 then <samp>za</samp> through <samp>zz</samp>, then <samp>zza</samp>
 through <samp>zzz</samp>, and so on).
-Convenience links to
-the <a href="ftp://ftp.iana.org/tz/tzcode-latest.tar.gz">latest
-code</a> and
-<a href="ftp://ftp.iana.org/tz/tzdata-latest.tar.gz">latest data</a> revisions
-are also available.
-The following <a
-href="https://en.wikipedia.org/wiki/Unix_shell">shell</a> commands download
-these files to a <abbr>GNU</abbr>/Linux or similar host;
-see the downloaded
-<code>README</code> file for what to do next.</p>
-<pre style="margin-left: 2em"><code>mkdir tz
-cd tz
-<a href="http://www.gnu.org/software/wget/">wget</a> --retr-symlinks 'ftp://ftp.iana.org/tz/tz*-latest.tar.gz'
-<a href="http://www.gnu.org/software/gzip/">gzip</a> -dc tzcode-latest.tar.gz | <a href="http://www.gnu.org/software/tar/">tar</a> -xf -
-gzip -dc tzdata-latest.tar.gz | tar -xf -
-</code></pre>
-<p>
-The code and data files can also be obtained from the
+The releases can also be obtained from the
 <a href="http://www.iana.org/time-zones">Time Zone Database website</a>
 of the <a href="http://www.iana.org">Internet Assigned Numbers
 Authority (IANA)</a>.
-An <a href="https://github.com/eggert/tz">unofficial development
+A <a href="https://github.com/eggert/tz">development
 repository</a> of the code and data is available
-in <a href="http://git-scm.com">Git</a> form
+in <a href="https://git-scm.com">Git</a> form
 from <a href="https://github.com">GitHub</a>; be careful, as this
 repository is less well tested and probably contains more errors.
 <p>
+After extracting a distribution's files, see its
+<code>README</code> file for what to do next.
 The code lets you compile the <code><abbr>tz</abbr></code> source files into
 machine-readable binary files, one for each location. It also lets
 you read a <code><abbr>tz</abbr></code> binary file and interpret time stamps for that
 location.</p>
-<h2>Changes to the <code><abbr>tz</abbr></code> database</h2>
+<h2 id="changes">Changes to the <code><abbr>tz</abbr></code> database</h2>
 <p>
 The <code><abbr>tz</abbr></code> code and data
 are by no means authoritative. If you find errors, please
 send changes to the <a href="mailto:tz@iana.org">time zone
 mailing list</a>. You can also <a
-href="http://news.gmane.org/gmane.comp.time.tz">browse recent
-messages</a> sent to the mailing list, <a
-href="https://mm.icann.org/mailman/listinfo/tz">subscribe</a> to it,
+href="https://mm.icann.org/mailman/listinfo/tz">subscribe</a> to it
 and browse the <a
 href="http://mm.icann.org/pipermail/tz/">archive of old
 messages</a>.</p>
@@ -190,7 +192,7 @@ For further information about updates, please see
 <a href="https://tools.ietf.org/html/rfc6557">Procedures for
 Maintaining the Time Zone Database</a> (Internet <abbr
 title="Request For Comments">RFC</abbr> 6557).</p>
-<h2>Commentary on the <code><abbr>tz</abbr></code> database</h2>
+<h2 id="commentary">Commentary on the <code><abbr>tz</abbr></code> database</h2>
 <ul>
 <li>The article
 <a href="https://en.wikipedia.org/wiki/Tz_database">tz database</a> is
@@ -204,11 +206,12 @@ the Timing of Time Zone Changes</a> gives examples of problems caused
 by inadequate notice by governments of time zone and daylight saving
 rule changes.</li>
 <li><a
-href="http://blog.jonudell.net/2009/10/23/a-literary-appreciation-of-the-olsonzoneinfotz-database/">A
+href="https://blog.jonudell.net/2009/10/23/a-literary-appreciation-of-the-olsonzoneinfotz-database/">A
 literary appreciation of the Olson/Zoneinfo/tz database</a> comments on the
 database's style.</li>
 </ul>
-<h2>Web sites using recent versions of the <code><abbr>tz</abbr></code> database</h2>
+<h2 id="web">Web sites using recent versions of the
+<code><abbr>tz</abbr></code> database</h2>
 <p>
 These are listed roughly in ascending order of complexity and fanciness.
 </p>
@@ -238,17 +241,20 @@ calculates the current time difference between locations.</li>
 also contains data about time zone boundaries; it supports queries via place
 names and shows location maps.</li>
 </ul>
-<h2>Network protocols for <code><abbr>tz</abbr></code> data</h2>
+<h2 id="protocols">Network protocols for <code><abbr>tz</abbr></code> data</h2>
 <ul>
-<li>The <a href="http://www.ietf.org">Internet Engineering Task Force</a>'s
+<li>The <a href="https://www.ietf.org">Internet Engineering Task Force</a>'s
 <a href="https://datatracker.ietf.org/wg/tzdist/charter/">Time Zone Data
 Distribution Service (tzdist) working group</a> defined <a
 href="https://tools.ietf.org/html/rfc7808">TZDIST</a>
 (Internet <abbr>RFC</abbr> 7808), a time zone data distribution service,
-along with a <a href="https://tools.ietf.org/html/rfc7809">calendar access
-protocol for transferring time zone data by reference</a>
-(Internet <abbr>RFC</abbr> 7809). This work was based
-on the iCalendar and CalConnect efforts described below.</li>
+along with <a href="https://tools.ietf.org/html/rfc7809">CalDAV</a>
+(Internet <abbr>RFC</abbr> 7809), a calendar access protocol for
+transferring time zone data by reference. The draft <a name="TZDIST-Geolocate"
+href="https://tools.ietf.org/html/draft-murchison-tzdist-geolocate-00">TZDIST
+Geolocate Extension</a> lets a client determine its time zone region
+from its geographic location using a <a
+href="https://tools.ietf.org/html/rfc5870">'geo' URI</a>.</li>
 <li>The <a href="https://tools.ietf.org/html/rfc5545">
 Internet Calendaring and Scheduling Core Object Specification
 (iCalendar)</a> (Internet <abbr>RFC</abbr> 5445)
@@ -257,37 +263,14 @@ data; see its VTIMEZONE calendar component.
 The iCalendar format requires specialized parsers and generators; a
 variant <a href="https://tools.ietf.org/html/rfc6321">xCal</a>
 (Internet <abbr>RFC</abbr> 6321) uses
-<a href="http://www.w3.org/XML/"><abbr
+<a href="https://www.w3.org/XML/"><abbr
 title="Extensible Markup Language">XML</abbr></a> format, and a variant
 <a href="https://tools.ietf.org/html/rfc7265">jCal</a>
 (Internet <abbr>RFC</abbr> 7265)
 uses <a href="http://www.json.org"><abbr
-title="JavaScript Object Notation">JSON</abbr></a> format.
-<a href="https://www.calconnect.org">CalConnect, The Calendaring and Scheduling
-Consortium</a> is promoting further work in this area. <a
-href="http://calconnect.org/publications/icalendartimezoneproblemsandrecommendationsv1.0.pdf">iCalendar
-TIMEZONE Problems and Recommendations</a> offers guidelines and
-recommendations for the use of VTIMEZONE and <code><abbr>tz</abbr></code>.</li>
-<li>The <a
-href="http://calconnect.org/publications/timezoneregistryandservicerecommendationsv1.0.pdf">Timezone
-Registry and Service Recommendations</a> of CalConnect's
-<a href="https://www.calconnect.org/about/technical-committees/tc-timezone">TIMEZONE
-Technical Committee</a> discusses a
-strategy for defining and deploying a time zone
-registration process that would establish unique names for each
-version of each <code><abbr>tz</abbr></code> zone, along with a polygonal
-representation of the geographical area corresponding to the
-zone.</li>
-<li>The <a
-href="http://lists.w3.org/Archives/Public/www-rdf-calendar/">www-rdf-calendar</a>
-list discusses <a
-href="http://www.w3.org/RDF/"><abbr
-title="Resource Description Framework">RDF</abbr></a>-based calendar
-and group scheduling systems, and has a <a
-href="http://www.w3.org/2002/12/cal/#tzd">workspace on time zone
-data</a> converted from <code><abbr>tz</abbr></code>.</li>
+title="JavaScript Object Notation">JSON</abbr></a> format.</li>
 </ul>
-<h2>Other <code><abbr>tz</abbr></code> compilers</h2>
+<h2 id="compilers">Other <code><abbr>tz</abbr></code> compilers</h2>
 <ul>
 <li><a href="https://sourceforge.net/projects/vzic/">Vzic</a> is a <a
 href="https://en.wikipedia.org/wiki/C_%28programming_language%29">C</a>
@@ -295,7 +278,7 @@ program that compiles
 <code><abbr>tz</abbr></code> source into iCalendar-compatible VTIMEZONE files.
 Vzic is freely
 available under the <a
-href="http://www.gnu.org/copyleft/gpl.html"><abbr>GNU</abbr>
+href="https://www.gnu.org/copyleft/gpl.html"><abbr>GNU</abbr>
 General Public License (<abbr
 title="General Public License">GPL</abbr>)</a>.</li>
 <li><a href="https://sourceforge.net/projects/tzical/">tziCal &ndash; tz
@@ -318,13 +301,13 @@ Database Parser</a> is a
 runtime library. It is freely available under the
 <a href="http://creativecommons.org/licenses/by/4.0/">Creative Commons
 Attribution 4.0 International Public License</a>.</li>
-<li><a href="http://site.icu-project.org">International Components for
+<li><a name="ICU" href="http://site.icu-project.org">International Components for
 Unicode (<abbr>ICU</abbr>)</a> contains C/C++ and <a
 href="https://en.wikipedia.org/wiki/Java_%28programming_language%29">Java</a>
 libraries for internationalization that
 has a compiler from <code><abbr>tz</abbr></code> source
 and from <abbr title="Common Locale Data Repository">CLDR</abbr> data
-(mentioned below)
+(mentioned <a href="#CLDR">below</a>)
 into an <abbr>ICU</abbr>-specific format.
 <abbr>ICU</abbr> is freely available under a
 <abbr>BSD</abbr>-style license.</li>
@@ -334,21 +317,41 @@ and compiles tz source and exposes <abbr
 title="Application Program Interface">API</abbr>s for use. It is
 freely available under the <abbr
 title="Massachusetts Institute of Technology">MIT</abbr> license.</li>
+<li>Java-based compilers and libraries include:
+<ul>
 <li>The <a
 href="http://www.oracle.com/technetwork/java/javase/tzupdater-readme-136440.html">TZUpdater
 tool</a> compiles <code><abbr>tz</abbr></code> source into the format used by
 Oracle Java.</li>
+<li>The <a
+href="http://www.oracle.com/technetwork/articles/java/jf14-date-time-2125367.html">Java
+8 <code>java.time</code> <abbr>API</abbr></a> can be supplemented by <a
+href="http://www.threeten.org/threeten-extra/">ThreeTen-Extra</a>,
+which is freely available under a <abbr>BSD</abbr>-style license.</li>
 <li><a href="http://www.joda.org/joda-time/">Joda-Time &ndash; Java date
 and time <abbr>API</abbr></a> contains a class
 <code>org.joda.time.tz.ZoneInfoCompiler</code> that compiles
-<code><abbr>tz</abbr></code> source into a Joda-specific binary format. Joda Time
-is freely available under a <abbr>BSD</abbr>-style license.</li>
+<code><abbr>tz</abbr></code> source into a binary format. It inspired
+Java 8 <code>java.time</code>, which its users should migrate to once
+they can assume Java 8 or later. It is available under the <a
+href="http://www.apache.org/licenses/LICENSE-2.0">Apache License</a>.</li>
+<li><a href="https://github.com/MenoData/Time4J/">Time4J &ndash;
+Advanced date, time and interval library for Java</a> contains a class
+<code>net.time4j.tool.TimezoneRepositoryCompiler</code> that compiles
+<code><abbr>tz</abbr></code> source into a binary format. Time4J is
+available under the <a
+href="https://www.gnu.org/copyleft/lesser.html"><abbr>GNU</abbr> Lesser
+General Public License (<abbr title="Lesser General Public
+License">LGPL</abbr>)</a>.</li>
+<li><abbr>ICU</abbr> (mentioned <a href="#ICU">above</a>) contains compilers and
+Java-based libraries.</li>
+</ul>
 <li><a href="http://nodatime.org">Noda Time &ndash; Date and
 time <abbr>API</abbr> for .NET</a>
 and <a href="http://www.babiej.demon.nl/Tz4Net/main.htm">TZ4Net</a>
-are similar to Joda Time, but for the .NET framework instead of
+are similar to Joda-Time and Time4J, but for the .NET framework instead of
 Java. They are freely available under the
-<a href="http://www.apache.org/licenses/LICENSE-2.0">Apache License</a>
+Apache License
 and a <abbr>BSD</abbr>-style license, respectively.</li>
 <li><a href="https://en.wikipedia.org/wiki/JavaScript">JavaScript</a>-based
 compilers and libraries include:
@@ -364,6 +367,10 @@ Dates. It is freely available under the Apache License.</li>
 translates <abbr>UT</abbr> to local time. It is freely available under
 the <abbr>MIT</abbr> license.</li>
 </ul>
+<li><a href="https://github.com/JuliaTime/">JuliaTime</a> contains a
+compiler from <code><abbr>tz</abbr></code> source into
+<a href="http://julialang.org/">Julia</a>. It is freely available
+under the <abbr>MIT</abbr> license.</li>
 <li><a href="http://pytz.sourceforge.net">pytz &ndash; World Timezone
 Definitions for Python</a> compiles <code><abbr>tz</abbr></code> source into
 <a href="https://www.python.org">Python</a>.
@@ -380,25 +387,23 @@ library that compiles <code><abbr>tz</abbr></code> source into a time
 zone repository whose format
 is either proprietary or an <abbr>XML</abbr>-encoded
 representation.</li>
-<li><a href="http://tcl.tk">Tcl</a>
+<li><a name="Tcl" href="http://tcl.tk">Tcl</a>
 contains a developer-oriented parser that compiles <code><abbr>tz</abbr></code>
 source into text files, along with a runtime that can read those
 files. Tcl is freely available under a <abbr>BSD</abbr>-style
 license.</li>
 </ul>
-<h2>Other <code><abbr>tz</abbr></code> binary file readers</h2>
+<h2 id="binary">Other <code><abbr>tz</abbr></code> binary file readers</h2>
 <ul>
 <li>The <a
-href="http://www.gnu.org/software/libc/"><abbr>GNU</abbr> C
+href="https://www.gnu.org/software/libc/"><abbr>GNU</abbr> C
 Library</a>
 has an independent, thread-safe implementation of
 a <code><abbr>tz</abbr></code> binary file reader.
-This library is freely available under the
-<a href="http://www.gnu.org/copyleft/lesser.html">
-<abbr>GNU</abbr> Lesser General Public License
-(<abbr title="Lesser General Public License">LGPL</abbr>)</a>,
+This library is freely available under the LGPL
 and is widely used in <abbr>GNU</abbr>/Linux systems.</li>
-<li><a href="https://www.gnome.org">GNOME</a>'s Glib has
+<li><a href="https://www.gnome.org">GNOME</a>'s
+<a href="https://developer.gnome.org/glib/">GLib</a> has
 a <code><abbr>tz</abbr></code> binary file reader written in C that
 creates a <code>GTimeZone</code> object representing sets
 of <abbr>UT</abbr> offsets.
@@ -417,7 +422,7 @@ It is freely available under the <abbr>LGPL</abbr>.</li>
 <li><a href="https://github.com/bigeasy/timezone">Timezone</a> is a
 JavaScript library that supports date arithmetic that is time zone
 aware. It is freely available under the <abbr>MIT</abbr> license.</li>
-<li>Tcl, mentioned above, also contains a
+<li>Tcl, mentioned <a href="#Tcl">above</a>, also contains a
 <code><abbr>tz</abbr></code> binary file reader.</li>
 <li><a href="http://search.cpan.org/perldoc?DateTime::TimeZone::Tzfile">
 DateTime::TimeZone::Tzfile</a>
@@ -437,7 +442,7 @@ package contains <a href="https://www.haskell.org">Haskell</a> code that
 parses and uses <code><abbr>tz</abbr></code> binary data. It is freely
 available under a <abbr>BSD</abbr>-style license.</li>
 </ul>
-<h2>Other <code><abbr>tz</abbr></code>-based time zone software</h2>
+<h2 id="software">Other <code><abbr>tz</abbr></code>-based time zone software</h2>
 <ul>
 <li><a href="https://foxclocks.org">FoxClocks</a>
 is an extension for <a href="https://www.google.com/chrome/">Google
@@ -460,11 +465,11 @@ clock (intclock)</a> is a clock that displays multiple time zones on
 under the <abbr>GPL</abbr>.</li>
 <li>Microsoft Windows 8.1
 and later has <code><abbr>tz</abbr></code> data and <abbr>CLDR</abbr>
-data (mentioned below) used by
+data (mentioned <a href="#CLDR">below</a>) used by
 <a href="https://en.wikipedia.org/wiki/Windows_Runtime">Windows Runtime</a>
 classes such as <a
 href="https://msdn.microsoft.com/en-us/library/windows/apps/windows.globalization.datetimeformatting.datetimeformatter.aspx"><code>DateTimeFormatter</code></a>.
-<a
+<a name="System.TimeZoneInfo"
 href="https://blogs.msdn.microsoft.com/bclteam/2007/06/07/exploring-windows-time-zones-with-system-timezoneinfo-josh-free/">Exploring
 Windows Time Zones with <code>System.TimeZoneInfo</code></a> describes
 the older, proprietary method of Microsoft Windows 2000 and later,
@@ -486,15 +491,15 @@ a <a href="https://wordpress.org">WordPress</a> plugin. It is freely
 available under a <abbr>BSD</abbr>-style license.</li>
 <li><a href="http://www.relativedata.com/time-zone-master">Time Zone
 Master</a> is a Microsoft Windows clock program that can automatically
-download, compile and use the <code>tzdata<var>D</var>.tar.gz</code>
-files as they are released. The Basic version is free.</li>
+download, compile and use <code>tz</code> releases. The Basic version
+is free.</li>
 <li><a
 href="http://veladg.com/velaterra.html">VelaTerra</a> is
 an <abbr>OS X</abbr> program. Its developers
 <a href="http://veladg.com/tzoffer.html">offer free
 licenses</a> to <code><abbr>tz</abbr></code> contributors.</li>
 </ul>
-<h2>Other time zone databases</h2>
+<h2 id="other-dbs">Other time zone databases</h2>
 <ul>
 <li><a href="http://www.astro.com/atlas">Time-zone Atlas</a>
 is Astrodienst's Web version of Shanks and Pottenger's
@@ -511,18 +516,20 @@ guessed many <abbr>UT</abbr> offsets and transitions. The atlases cite no
 sources and do not indicate which entries are guesswork.</li>
 <li><a href="https://en.wikipedia.org/wiki/HP-UX">HP-UX</a> has a database in
 its own <code>tztab</code>(4) format.</li>
-<li>Microsoft Windows has proprietary data mentioned above.</li>
+<li>Microsoft Windows has proprietary data mentioned
+<a href="#System.TimeZoneInfo">above</a>.</li>
 <li><a href="http://www.worldtimeserver.com">World Time Server</a>
 is another time zone database.</li>
 <li><a href="http://tycho.usno.navy.mil/tzones.html">World Time Zones</a>
 contains data from the Time Service Department of the
 <abbr>US</abbr> Naval Observatory.</li>
-<li>The <a href="http://www.iata.org/publications/Pages/ssim.aspx">Standard
+<li>The <a
+href="http://www.iata.org/publications/store/Pages/standard-schedules-information.aspx">Standard
 Schedules Information Manual</a> of the
 International Air Transport Association
 gives current time zone rules for airports served by commercial aviation.</li>
 </ul>
-<h2>Maps</h2>
+<h2 id="maps">Maps</h2>
 <ul>
 <li>The <a href="https://www.cia.gov/index.html">United States Central
 Intelligence Agency (<abbr
@@ -549,20 +556,74 @@ much is time wrong around the world?</a> maps the difference between
 mean solar and standard time, highlighting areas such as western China
 where the two differ greatly. It's a bit out of date, unfortunately.</li>
 </ul>
-<h2>Time zone boundaries</h2>
+<h2 id="boundaries">Time zone boundaries</h2>
+<p>Geographical boundaries between time zone regions are available
+from several <a href="https://en.wikipedia.org/wiki/Geolocation">geolocation</a>
+services and other sources.</p>
+<ul>
+<li>Databases of time zone boundaries include:
 <ul>
+<li><a href="https://github.com/evansiroky/timezone-boundary-builder">Timezone
+Boundary Builder</a> extracts
+<a href="http://www.openstreetmap.org">Open Street Map</a> data to build
+boundaries of <code><abbr>tz</abbr></code> regions.
+Its code is freely available under the <abbr>MIT</abbr> license, and
+its data entries are freely available under the
+<a href="http://opendatacommons.org/licenses/odbl/">Open Data Commons
+Open Database License</a>. The maps' borders appear to be quite accurate.</li>
 <li><a href="http://efele.net/maps/tz/"><abbr>TZ</abbr> timezones
 maps</a> contains <a
 href="https://en.wikipedia.org/wiki/Shapefile">shapefiles</a> of
-sets of <code><abbr>tz</abbr></code> regions.</li>
+sets of <code><abbr>tz</abbr></code> regions. This includes
+<a href="http://efele.net/maps/tz/world/">tz_world</a>, a shapefile
+for all the world's regions</li>
+<li><a
+href="https://github.com/straup/whereonearth-timezone">Whereonearth-timezone</a>
+is in <a href="http://geojson.org">GeoJSON</a> form, and combines the
+the tz_world shapefiles with the GeoPlanet dataset.</li>
+</ul></li>
+<li>Programmatic interfaces that map geographical coordinates via tz_world to
+<code><abbr>tz</abbr></code> regions 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>
-maps geographical coordinates to a <code><abbr>tz</abbr></code> region.
-It is written in Go and is freely available under the Apache License.</li>
+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>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>
+<li>The <a href="https://www.npmjs.com/package/tz-lookup">tz-lookup module</a>
+for <a href="https://nodejs.org/en/">Node.js</a> is in the public domain.</li>
 <li><a href="https://derickrethans.nl/what-time-is-it.html">What Time
 is It Here?</a> applies <a href="https://www.mongodb.com">MongoDB</a>
 geospatial query operators to shapefiles' data.</li>
+</ul></li>
+<li>Free access via a network API, if you register a key, is provided by
+the <a href="http://www.geonames.org/export/web-services.html#timezone">GeoNames Timezone web service</a>,
+the <a href="https://developers.google.com/maps/documentation/timezone/intro">Google Maps Time Zone API</a>, and
+the <a href="https://timezonedb.com">Time Zone Database &amp; API</a>.
+Commercial network API access is provided
+by <a href="https://askgeo.com">AskGeo</a>
+and <a href="https://www.geogarage.com/blog/news-1/post/geogarage-time-zone-api-31">GeoGarage</a>.
+Also, an <a
+href="http://mm.icann.org/pipermail/tz/2016-October/024309.html">experimental
+server</a> is available for the TZDIST Geolocate Extension mentioned
+<a href="#TZDIST-Geolocate">above</a>.</li>
+<li>"<a
+href="http://stackoverflow.com/questions/16086962/how-to-get-a-time-zone-from-a-location-using-latitude-and-longitude-coordinates/16086964">How
+to get a time zone from a location using latitude and longitude
+coordinates?</a>" discusses other geolocation possibilities.</li>
 <li><a href="http://statoids.com/statoids.html">Administrative
-Divisions of Countries ("Statoids")</a> contains lists of
+Divisions of Countries ("Statoids")</a> lists
 political subdivision data related to time zones.</li>
 <li><a href="http://home.kpn.nl/vanadovv/time/Multizones.html">Time
 zone boundaries for multizone countries</a> summarizes legal
@@ -586,9 +647,9 @@ for land and territorial waters only). A captain can change ship's
 clocks any time after entering a new time zone; midnight changes are
 common.</li>
 </ul>
-<h2>Civil time concepts and history</h2>
+<h2 id="civil">Civil time concepts and history</h2>
 <ul>
-<li><a href="http://www.nist.gov/pml/general/time/index.cfm">A
+<li><a href="http://physics.nist.gov/time">A
 Walk through Time</a>
 surveys the evolution of timekeeping.</li>
 <li><a href="http://www.webexhibits.org/daylightsaving/">About Daylight
@@ -597,8 +658,6 @@ is an overall history of <abbr>DST</abbr>.</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="http://energy.ca.gov/daylightsaving.html">Saving Time,
-Saving Energy</a> discusses a primary justification for <abbr>DST</abbr>.</li>
 <li><a href="http://seizethedaylight.com/dst/">A Brief
 History of Daylight Saving Time</a> summarizes some of the contentious
 history of <abbr>DST</abbr>.</li>
@@ -608,7 +667,7 @@ time zone boundary.</li>
 <li><a href="http://statoids.com/tconcept.html">Basic Time
 Zone Concepts</a> discusses terminological issues behind time zones.</li>
 </ul>
-<h2>National histories of legal time</h2>
+<h2 id="national">National histories of legal time</h2>
 <dl>
 <dt>Australia</dt>
 <dd>The Parliamentary Library has commissioned a <a
@@ -643,25 +702,29 @@ of Legal Time in Germany</a>.</dd>
 <dd>The Interior Ministry periodically issues <a
 href="ftp://ftp.cs.huji.ac.il/pub/tz/announcements"
 hreflang="he">announcements (in Hebrew)</a>.</dd>
+<dt>Italy</dt>
+<dd>The National Institute of Metrological Research maintains a
+<a href="http://www.inrim.it/res/tf/ora_legale_i.shtml">table of civil time
+(in Italian)</a>.</dd>
 <dt>Mexico</dt>
 <dd>The Investigation and Analysis Service of the Mexican Library of
 Congress has published a <a
 href="http://www.diputados.gob.mx/bibliot/publica/inveyana/polisoc/horver/index.htm"
 hreflang="es">history of Mexican local time (in Spanish)</a>.</dd>
 <dt>Malaysia</dt>
-<dd>See Singapore below.</dd>
+<dd>See Singapore <a href="#Singapore">below</a>.</dd>
 <dt>Netherlands</dt>
 <dd><a href="http://www.staff.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>
 <dd>The Department of Internal Affairs maintains a brief <a
-href="http://www.dia.govt.nz/Daylight-Saving-History">History of
+href="https://www.dia.govt.nz/Daylight-Saving-History">History of
 Daylight Saving</a>. The privately-maintained <a
 href="http://astrologyschool.com/nztime.html">History of New Zealand
 time</a> has more details.</dd>
 <dt>Singapore</dt>
-<dd><a
+<dd><a name="Singapore"
 href="http://www.math.nus.edu.sg/aslaksen/teaching/timezone.html">Why
 is Singapore in the "Wrong" Time Zone?</a> details the
 history of legal time in Singapore and Malaysia.</dd>
@@ -671,14 +734,14 @@ href="https://www.polyomino.org.uk/british-time/">History of
 legal time in Britain</a> discusses in detail the country
 with perhaps the best-documented history of clock adjustments.
 The National Physical Laboratory also maintains an <a
-href="http://www.npl.co.uk/educate-explore/what-is-time/archive-of-summer-time-dates-1916-2006">Archive
+href="http://www.npl.co.uk/educate-explore/what-is-time/archive-of-summer-time-dates">Archive
 of Summer time dates</a>.</dd>
 <dt>United States</dt>
 <dd>The Department of Transportation's <a
 href="https://www.transportation.gov/regulations/recent-time-zone-proceedings">Recent
 Time Zone Proceedings</a> lists changes to time zone boundaries.</dd>
 </dl>
-<h2>Precision timekeeping</h2>
+<h2 id="precision">Precision timekeeping</h2>
 <ul>
 <li><a
 href="http://literature.agilent.com/litweb/pdf/5965-7984E.pdf">The
@@ -686,10 +749,11 @@ Science of Timekeeping</a> is a thorough introduction
 to the theory and practice of precision timekeeping.</li>
 <li><a href="http://www.ntp.org"><abbr
 title="Network Time Protocol">NTP</abbr>: The Network
-Time Protocol</a>
+Time Protocol</a> (Internet <abbr>RFC</abbr> 5905)
 discusses how to synchronize clocks of
 Internet hosts.</li>
-<li>The <a href="http://www.nist.gov/el/isd/ieee/ieee1588.cfm">Precision
+<li>The <a
+href="https://www.nist.gov/intelligent-systems-division/ieee-1588">Precision
 Time Protocol</a> (<abbr
 title="Institute of Electrical and Electronics Engineers">IEEE</abbr> 1588)
 can achieve submicrosecond clock accuracy on a local area network.</li>
@@ -701,11 +765,6 @@ specifies a <a
 href="https://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol"><abbr>DHCP</abbr></a>
 option for a server to configure
 a client's time zone and daylight saving settings automatically.</li>
-<li><a href="http://gauss.gge.unb.ca/GMT.UT.and.the.RGO.html">A Few Facts
-Concerning <abbr>GMT</abbr>, <abbr>UT</abbr>, and
-the <abbr title="Royal Greenwich Observatory">RGO</abbr></a>
-answers questions like "What is the
-difference between <abbr>GMT</abbr> and <abbr>UTC</abbr>?"</li>
 <li><a
 href="http://www.cv.nrao.edu/~rfisher/Ephemerides/times.html">Astronomical
 Times</a> explains more abstruse astronomical time scales like
@@ -714,7 +773,7 @@ Times</a> explains more abstruse astronomical time scales like
 <abbr title="Barycentric Dynamic Time">TDB</abbr>.
 <a href="http://www.ucolick.org/~sla/leapsecs/timescales.html">Time
 Scales</a> goes into more detail, particularly for historical variants.</li>
-<li>The <a href="http://iau.org"><abbr
+<li>The <a href="http://www.iau.org"><abbr
 title="International Astronomical Union">IAU</abbr></a>'s <a
 href="http://www.iausofa.org"><abbr
 title="Standards Of Fundamental Astronomy">SOFA</abbr></a>
@@ -728,10 +787,8 @@ code for converting among time scales like
 Space Flight &ndash; Reference Systems &ndash; Time Conventions</a>
 briefly explains interplanetary space flight timekeeping.</li>
 <li><a
-href="http://www.giss.nasa.gov/tools/mars24/help/notes.html">Technical
-Notes on Mars Solar Time as Adopted by the Mars24 Sunclock</a> briefly
-describes Mars Coordinated Time (<abbr
-title="Mars Coordinated Time">MTC</abbr>) and the
+href="http://www.giss.nasa.gov/tools/mars24/help/notes.html">Mars24 Sunclock
+&ndash; Time on Mars</a> describes Airy Mean Time (<abbr>AMT</abbr>) and the
 diverse local time
 scales used by each landed mission on Mars.</li>
 <li><a href="http://leapsecond.com">LeapSecond.com</a> is
@@ -747,7 +804,7 @@ when leap seconds occur.</li>
 <li>The <a
 href="https://pairlist6.pair.net/mailman/listinfo/leapsecs">Leap
 Second Discussion List</a> covers <a
-href="http://gauss.gge.unb.ca/papers.pdf/gpsworld.november99.pdf">McCarthy
+href="http://www2.unb.ca/gge/Resources/gpsworld.november99.pdf">McCarthy
 and Klepczynski's proposal to discontinue leap seconds</a>,
 discussed further in
 <a href="http://www.cl.cam.ac.uk/~mgk25/time/metrologia-leapsecond.pdf">The
@@ -757,15 +814,15 @@ might be redefined
 without Leap Seconds</a> gives pointers on this
 contentious issue.</li>
 </ul>
-<h2>Time notation</h2>
+<h2 id="notation">Time notation</h2>
 <ul>
-<li>The <a href="http://cldr.unicode.org">Unicode Common Locale Data
+<li>The <a name="CLDR" href="http://cldr.unicode.org">Unicode Common Locale Data
 Repository (<abbr>CLDR</abbr>) Project</a> has localizations for time
 zone names, abbreviations, identifiers, and formats. For example, it
 contains French translations for "Eastern European Summer Time",
 "<abbr title="Eastern European Summer Time">EEST</abbr>", and
 "Bucharest". Its
-<a href="http://unicode.org/cldr/charts/by_type/index.html">by-type
+<a href="http://www.unicode.org/cldr/charts/latest/by_type/">by-type
 charts</a> show these values for many locales. Data values are available in
 both <abbr title="Locale Data Markup Language">LDML</abbr>
 (an <abbr>XML</abbr> format) and <abbr>JSON</abbr>.
@@ -782,9 +839,8 @@ interchange &ndash; Representation of dates and times</a>.</li>
 <a href="https://www.w3.org/TR/xmlschema-2/#dateTime"><abbr>XML</abbr>
 Schema: Datatypes &ndash; dateTime</a> specifies a format inspired by
 <abbr>ISO</abbr> 8601 that is in common use in <abbr>XML</abbr> data.</li>
-<li>
-<a href="https://tools.ietf.org/html/rfc5322">Internet
-Message Format</a> (Internet <abbr>RFC</abbr> 5322) &sect;3.3
+<li><a href="https://tools.ietf.org/html/rfc5322#section-3.3">&sect;3.3 of
+Internet Message Format</a> (Internet <abbr>RFC</abbr> 5322)
 specifies the time notation used in email and <a
 href="https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol"><abbr>HTTP</abbr></a>
 headers.</li>
@@ -809,10 +865,10 @@ practice. For example, in English-speaking North America
 but in China it denotes 8 hours ahead of <abbr>UTC</abbr>,
 and French-speaking North Americans prefer
 "<abbr title="Heure Normale du Centre">HNC</abbr>" to
-"<abbr>CST</abbr>". For <abbr>POSIX</abbr> the <code><abbr>tz</abbr></code>
-database contains English abbreviations for all time stamps but in
-many cases these are merely inventions of the database
-maintainers.</li>
+"<abbr>CST</abbr>". The <code><abbr>tz</abbr></code>
+database contains English abbreviations for many time stamps;
+unfortunately some of these abbreviations were merely the database maintainers'
+inventions, and are gradually being removed.</li>
 <li>Numeric time zone abbreviations typically count hours east of
 <abbr>UTC</abbr>, e.g., +09 for Japan and
 &minus;10 for Hawaii. However, the <abbr>POSIX</abbr>
@@ -827,11 +883,11 @@ settings like <code><abbr>TZ</abbr>="Asia/Tokyo"</code> and
 confusion, handle old time stamps better, and insulate you better from
 any future changes to the rules. One should never set
 <abbr>POSIX</abbr> <code><abbr>TZ</abbr></code> to a value like
-<code>"GMT-9"</code>, though, since this would falsely claim that
+<code>"GMT-9"</code>, though, since this would incorrectly imply that
 local time is nine hours ahead of <abbr>UTC</abbr> and the time zone
 is called "<abbr>GMT</abbr>".</li>
 </ul>
-<h2>See also</h2>
+<h2 id="see-also">See also</h2>
 <ul>
 <li><a href="tz-art.htm">Time and the Arts</a></li>
 </ul>
index b7e6d45..0c907bc 100644 (file)
--- a/tzfile.5
+++ b/tzfile.5
@@ -2,6 +2,13 @@
 .SH NAME
 tzfile \- time zone information
 .SH DESCRIPTION
+.ie '\(lq'' .ds lq \&"\"
+.el .ds lq \(lq\"
+.ie '\(rq'' .ds rq \&"\"
+.el .ds rq \(rq\"
+.de q
+\\$3\*(lq\\$1\*(rq\\$2
+..
 The time zone information files used by
 .IR tzset (3)
 begin with the magic characters "TZif" to identify them as
@@ -138,6 +145,13 @@ 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).
+The POSIX-style string must must agree with the local time type after
+both data's last transition times; for example, given the string
+.q "WET0WEST,M3.5.0,M10.5.0/3"
+then if a last transition time is in July, the transition's local time
+type must specify a daylight-saving time abbreviated
+.q "WEST"
+that is one hour east of UT.
 .PP
 For version-3-format time zone files, the POSIX-TZ-style string may
 use two minor extensions to the POSIX TZ format, as described in
index fbc44e6..ca632ea 100644 (file)
@@ -89,7 +89,12 @@ DESCRIPTION
        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 (with nothing between the
-       newlines if there is no POSIX representation for such instants).
+       newlines if there is no POSIX representation for such instants).  The
+       POSIX-style string must must agree with the local time type after both
+       data's last transition times; for example, given the string
+       "WET0WEST,M3.5.0,M10.5.0/3" 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.
 
        For version-3-format time zone files, the POSIX-TZ-style string may use
        two minor extensions to the POSIX TZ format, as described in
diff --git a/zdump.8 b/zdump.8
index db73f49..14ca60b 100644 (file)
--- a/zdump.8
+++ b/zdump.8
@@ -9,6 +9,13 @@ zdump \- time zone dumper
 .I zonename
 \&... ]
 .SH DESCRIPTION
+.ie '\(lq'' .ds lq \&"\"
+.el .ds lq \(lq\"
+.ie '\(rq'' .ds rq \&"\"
+.el .ds rq \(rq\"
+.de q
+\\$3\*(lq\\$1\*(rq\\$2
+..
 .ie \n(.g .ds - \f(CW-\fP
 .el ds - \-
 .I Zdump
@@ -21,7 +28,17 @@ These options are available:
 .BI "\*-\*-version"
 Output version information and exit.
 .TP
+.B \*-i
+.I "(This option is experimental: its behavior may change in future versions.)"
+Output a description of time intervals.  For each
+.I zonename
+on the command line, output an interval-format description of the
+zone.  See
+.q "INTERVAL FORMAT"
+below.
+.TP
 .B \*-v
+Output a verbose description of time intervals.
 For each
 .I zonename
 on the command line,
@@ -52,7 +69,7 @@ This generates output that is easier to compare to that of
 implementations with different time representations.
 .TP
 .BI "\*-c " [loyear,]hiyear
-Cut off verbose output at the given year(s).
+Cut off interval output at the given year(s).
 Cutoff times are computed using the proleptic Gregorian calendar with year 0
 and with Universal Time (UT) ignoring leap seconds.
 The lower bound is exclusive and the upper is inclusive; for example, a
@@ -64,7 +81,7 @@ The default cutoff is
 .BR \*-500,2500 .
 .TP
 .BI "\*-t " [lotime,]hitime
-Cut off verbose output at the given time(s),
+Cut off interval output at the given time(s),
 given in decimal seconds since 1970-01-01 00:00:00
 Coordinated Universal Time (UTC).
 The
@@ -73,19 +90,135 @@ determines whether the count includes leap seconds.
 As with
 .BR \*-c ,
 the cutoff's lower bound is exclusive and its upper bound is inclusive.
+.SH "INTERVAL FORMAT"
+.I "This format is experimental: it may change in future versions."
+.PP
+The interval format is a compact text representation that is intended
+to be both human- and machine-readable.  It consists of an empty line,
+then a line
+.q "TZ=\fIstring\fP"
+where
+.I string
+is a double-quoted string giving the zone name, a second line
+.q "\*- \*- \fIinterval\fP"
+describing the time interval before the first transition if any, and
+zero or more following lines
+.q "\fIdate time interval\fP",
+one line for each transition time and following interval.  Fields are
+separated by single tabs.
+.PP
+Dates are in
+.IR yyyy - mm - dd
+format and times are in 24-hour
+.IR hh : mm : ss
+format where
+.IR hh <24.
+Times are in local time immediately after the transition.  A
+time interval description consists of a UT offset in signed
+.RI \(+- hh : mm : ss
+format, a time zone abbreviation, and an isdst flag.  An abbreviation
+that equals the UT offset is omitted; other abbreviations are
+double-quoted strings unless they consist of one or more alphabetic
+characters.  An isdst flag is omitted for standard time, and otherwise
+is a decimal integer that is unsigned and positive (typically 1) for
+daylight saving time and negative for unknown.
+.PP
+In times and UT offsets, the seconds are omitted if they are zero, and
+the minutes are also omitted if they are also zero.  Positive UT
+offsets are east of Greenwich.  The UT offset \*-00 denotes a UT
+placeholder in areas where the actual offset is unspecified; by
+convention, this occurs when the UT offset is zero and the time zone
+abbreviation begins with
+.q "\*-"
+or is
+.q "zzz".
+.PP
+In double-quoted strings, escape sequences represent unusual
+characters.  The escape sequences are \es for space, and \e", \e\e,
+\ef, \en, \er, \et, and \ev with their usual meaning in the C
+programming language.  E.g., the double-quoted string
+\*(lq"CET\es\e"\e\e"\*(rq represents the character sequence \*(lqCET
+"\e\*(rq.\""
+.PP
+.ne 9
+Here is an example of the output, with the leading empty line omitted.
+(This example is shown with tab stops set far enough apart so that the
+tabbed columns line up.)
+.nf
+.sp
+.if \n(.g .ft CW
+.if t .in +.5i
+.if n .in +2
+.nr w \w'1896-01-13 'u
+.ta \nwu +\nwu +\nwu +\nwu
+TZ="Pacific/Honolulu"
+-      -       -10:31:26       LMT
+1896-01-13     12:01:26        -10:30  HST
+1933-04-30     03      -09:30  HDT     1
+1933-05-21     11      -10:30  HST
+1942-02-09     03      -09:30  HDT     1
+1945-09-30     01      -10:30  HST
+1947-06-08     02:30   -10     HST
+.in
+.if \n(.g .ft
+.sp
+.fi
+Here, local time begins 10 hours, 31 minutes and 26 seconds west of
+UT, and is a standard time abbreviated LMT.  Immediately after the
+first transition, the date is 1896-01-13 and the time is 12:01:26, and
+the following time interval is 10.5 hours west of UT, a standard time
+abbreviated HST.  Immediately after the second transition, the date is
+1933-04-30 and the time is 03:00:00 and the following time interval is
+9.5 hours west of UT, is abbreviated HDT, and is daylight saving time.
+Immediately after the last transition the date is 1947-06-08 and the
+time is 02:30:00, and the following time interval is 10 hours west of
+UT, a standard time abbreviated HST.
+.PP
+.ne 10
+Here are excerpts from another example:
+.nf
+.sp
+.if \n(.g .ft CW
+.if t .in +.5i
+.if n .in +2
+TZ="Europe/Astrakhan"
+-      -       +03:12:12       LMT
+1924-04-30     23:47:48        +03
+1930-06-21     01      +04
+1981-04-01     01      +05             1
+1981-09-30     23      +04
+\&...
+2014-10-26     01      +03
+2016-03-27     03      +04
+.in
+.if \n(.g .ft
+.sp
+.fi
+This time zone is east of UT, so its UT offsets are positive.  Also,
+many of its time zone abbreviations are omitted since they duplicate
+the text of the UT offset.
 .SH LIMITATIONS
 Time discontinuities are found by sampling the results returned by localtime
 at twelve-hour intervals.
 This works in all real-world cases;
 one can construct artificial time zones for which this fails.
 .PP
-In the output, "UT" denotes the value returned by
+In the
+.B \*-v
+and
+.B \*-V
+output,
+.q "UT"
+denotes the value returned by
 .IR gmtime (3),
 which uses UTC for modern time stamps and some other UT flavor for
 time stamps that predate the introduction of UTC.
-No attempt is currently made to have the output use "UTC" for newer
-and "UT" for older time stamps,
-partly because the exact date of the introduction of UTC is problematic.
+No attempt is currently made to have the output use
+.q "UTC"
+for newer and
+.q "UT"
+for older time stamps, partly because the exact date of the
+introduction of UTC is problematic.
 .SH "SEE ALSO"
 newctime(3), tzfile(5), zic(8)
 .\" This file is in the public domain, so clarified as of
index df8d1fd..bae93d8 100644 (file)
@@ -15,24 +15,29 @@ DESCRIPTION
        --version
               Output version information and exit.
 
-       -v     For each zonename on the command line, print the time at the
-              lowest possible time value, the time one day after the lowest
-              possible time value, the times both one second before and
-              exactly at each detected time discontinuity, the time at one day
-              less than the highest possible time value, and the time at the
-              highest possible time value.  Each line is followed by isdst=D
-              where D is positive, zero, or negative depending on whether the
-              given time is daylight saving time, standard time, or an unknown
-              time type, respectively.  Each line is also followed by gmtoff=N
-              if the given local time is known to be N seconds east of
-              Greenwich.
+       -i     (This option is experimental: its behavior may change in future
+              versions.)  Output a description of time intervals.  For each
+              zonename on the command line, output an interval-format
+              description of the zone.  See "INTERVAL FORMAT" below.
+
+       -v     Output a verbose description of time intervals.  For each
+              zonename on the command line, print the time at the lowest
+              possible time value, the time one day after the lowest possible
+              time value, the times both one second before and exactly at each
+              detected time discontinuity, the time at one day less than the
+              highest possible time value, and the time at the highest
+              possible time value.  Each line is followed by isdst=D where D
+              is positive, zero, or negative depending on whether the given
+              time is daylight saving time, standard time, or an unknown time
+              type, respectively.  Each line is also followed by gmtoff=N if
+              the given local time is known to be N seconds east of Greenwich.
 
        -V     Like -v, except omit the times relative to the extreme time
               values.  This generates output that is easier to compare to that
               of implementations with different time representations.
 
        -c [loyear,]hiyear
-              Cut off verbose output at the given year(s).  Cutoff times are
+              Cut off interval output at the given year(s).  Cutoff times are
               computed using the proleptic Gregorian calendar with year 0 and
               with Universal Time (UT) ignoring leap seconds.  The lower bound
               is exclusive and the upper is inclusive; for example, a loyear
@@ -41,22 +46,96 @@ DESCRIPTION
               cutoff is -500,2500.
 
        -t [lotime,]hitime
-              Cut off verbose output at the given time(s), given in decimal
+              Cut off interval output at the given time(s), given in decimal
               seconds since 1970-01-01 00:00:00 Coordinated Universal Time
               (UTC).  The zonename determines whether the count includes leap
               seconds.  As with -c, the cutoff's lower bound is exclusive and
               its upper bound is inclusive.
 
+INTERVAL FORMAT
+       This format is experimental: it may change in future versions.
+
+       The interval format is a compact text representation that is intended
+       to be both human- and machine-readable.  It consists of an empty line,
+       then a line "TZ=string" where string is a double-quoted string giving
+       the zone name, a second line "- - interval" describing the time
+       interval before the first transition if any, and zero or more following
+       lines "date time interval", one line for each transition time and
+       following interval.  Fields are separated by single tabs.
+
+       Dates are in yyyy-mm-dd format and times are in 24-hour hh:mm:ss format
+       where hh<24.  Times are in local time immediately after the transition.
+       A time interval description consists of a UT offset in signed
+       +-hh:mm:ss format, a time zone abbreviation, and an isdst flag.  An
+       abbreviation that equals the UT offset is omitted; other abbreviations
+       are double-quoted strings unless they consist of one or more alphabetic
+       characters.  An isdst flag is omitted for standard time, and otherwise
+       is a decimal integer that is unsigned and positive (typically 1) for
+       daylight saving time and negative for unknown.
+
+       In times and UT offsets, the seconds are omitted if they are zero, and
+       the minutes are also omitted if they are also zero.  Positive UT
+       offsets are east of Greenwich.  The UT offset -00 denotes a UT
+       placeholder in areas where the actual offset is unspecified; by
+       convention, this occurs when the UT offset is zero and the time zone
+       abbreviation begins with "-" or is "zzz".
+
+       In double-quoted strings, escape sequences represent unusual
+       characters.  The escape sequences are \s for space, and \", \\, \f, \n,
+       \r, \t, and \v with their usual meaning in the C programming language.
+       E.g., the double-quoted string ""CET\s\"\\"" represents the character
+       sequence "CET "\".
+
+       Here is an example of the output, with the leading empty line omitted.
+       (This example is shown with tab stops set far enough apart so that the
+       tabbed columns line up.)
+
+         TZ="Pacific/Honolulu"
+         -          -          -10:31:26  LMT
+         1896-01-13 12:01:26   -10:30     HST
+         1933-04-30 03         -09:30     HDT        1
+         1933-05-21 11         -10:30     HST
+         1942-02-09 03         -09:30     HDT        1
+         1945-09-30 01         -10:30     HST
+         1947-06-08 02:30      -10        HST
+
+       Here, local time begins 10 hours, 31 minutes and 26 seconds west of UT,
+       and is a standard time abbreviated LMT.  Immediately after the first
+       transition, the date is 1896-01-13 and the time is 12:01:26, and the
+       following time interval is 10.5 hours west of UT, a standard time
+       abbreviated HST.  Immediately after the second transition, the date is
+       1933-04-30 and the time is 03:00:00 and the following time interval is
+       9.5 hours west of UT, is abbreviated HDT, and is daylight saving time.
+       Immediately after the last transition the date is 1947-06-08 and the
+       time is 02:30:00, and the following time interval is 10 hours west of
+       UT, a standard time abbreviated HST.
+
+       Here are excerpts from another example:
+
+         TZ="Europe/Astrakhan"
+         -          -          +03:12:12  LMT
+         1924-04-30 23:47:48   +03
+         1930-06-21 01         +04
+         1981-04-01 01         +05                   1
+         1981-09-30 23         +04
+         ...
+         2014-10-26 01         +03
+         2016-03-27 03         +04
+
+       This time zone is east of UT, so its UT offsets are positive.  Also,
+       many of its time zone abbreviations are omitted since they duplicate
+       the text of the UT offset.
+
 LIMITATIONS
        Time discontinuities are found by sampling the results returned by
        localtime at twelve-hour intervals.  This works in all real-world
        cases; one can construct artificial time zones for which this fails.
 
-       In the output, "UT" denotes the value returned by gmtime(3), which uses
-       UTC for modern time stamps and some other UT flavor for time stamps
-       that predate the introduction of UTC.  No attempt is currently made to
-       have the output use "UTC" for newer and "UT" for older time stamps,
-       partly because the exact date of the introduction of UTC is
+       In the -v and -V output, "UT" denotes the value returned by gmtime(3),
+       which uses UTC for modern time stamps and some other UT flavor for time
+       stamps that predate the introduction of UTC.  No attempt is currently
+       made to have the output use "UTC" for newer and "UT" for older time
+       stamps, partly because the exact date of the introduction of UTC is
        problematic.
 
 SEE ALSO
diff --git a/zdump.c b/zdump.c
index 64d90f6..a901aff 100644 (file)
--- a/zdump.c
+++ b/zdump.c
@@ -45,7 +45,7 @@
 # define HAVE_STDINT_H \
     (199901 <= __STDC_VERSION__ \
      || 2 < __GLIBC__ + (1 <= __GLIBC_MINOR__) \
-     || __CYGWIN__)
+     || __CYGWIN__ || INTMAX_MAX)
 #endif
 #if HAVE_STDINT_H
 # include "stdint.h"
@@ -139,6 +139,26 @@ typedef long intmax_t;
 # include <stdbool.h>
 #endif
 
+#ifndef TYPE_BIT
+#define TYPE_BIT(type) (sizeof (type) * CHAR_BIT)
+#endif /* !defined TYPE_BIT */
+
+#ifndef TYPE_SIGNED
+#define TYPE_SIGNED(type) (((type) -1) < 0)
+#endif /* !defined TYPE_SIGNED */
+
+#ifndef INT_STRLEN_MAXIMUM
+/*
+** 302 / 1000 is log10(2.0) rounded up.
+** Subtract one for the sign bit if the type is signed;
+** add one for integer division truncation;
+** add one more for a minus sign if the type is signed.
+*/
+#define INT_STRLEN_MAXIMUM(type) \
+       ((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + \
+       1 + TYPE_SIGNED(type))
+#endif /* !defined INT_STRLEN_MAXIMUM */
+
 #ifndef EXIT_SUCCESS
 #define EXIT_SUCCESS   0
 #endif /* !defined EXIT_SUCCESS */
@@ -238,8 +258,9 @@ enum { SECSPER400YEARS_FITS = SECSPERLYEAR <= INTMAX_MAX / 400 };
 # define timezone_t char **
 #endif
 
-#if !HAVE_POSIX_DECLS
 extern char ** environ;
+
+#if !HAVE_POSIX_DECLS
 extern int     getopt(int argc, char * const argv[],
                        const char * options);
 extern char *  optarg;
@@ -268,6 +289,8 @@ static intmax_t     delta(struct tm *, struct tm *) ATTRIBUTE_PURE;
 static void dumptime(struct tm const *);
 static time_t hunt(timezone_t, char *, time_t, time_t);
 static void show(timezone_t, char *, time_t, bool);
+static void showtrans(char const *, struct tm const *, time_t, char const *,
+                     char const *);
 static const char *tformat(void);
 static time_t yeartot(intmax_t) ATTRIBUTE_PURE;
 
@@ -305,6 +328,19 @@ sumsize(size_t a, size_t b)
   return sum;
 }
 
+/* Return a pointer to a newly allocated buffer of size SIZE, exiting
+   on failure.  SIZE should be nonzero.  */
+static void *
+xmalloc(size_t size)
+{
+  void *p = malloc(size);
+  if (!p) {
+    perror(progname);
+    exit(EXIT_FAILURE);
+  }
+  return p;
+}
+
 #if ! HAVE_TZSET
 # undef tzset
 # define tzset zdump_tzset
@@ -392,21 +428,13 @@ tzalloc(char const *val)
 
     while (*e++)
       continue;
-    env = malloc(sumsize(sizeof *environ,
-                        (e - environ) * sizeof *environ));
-    if (! env) {
-      perror(progname);
-      exit(EXIT_FAILURE);
-    }
+    env = xmalloc(sumsize(sizeof *environ,
+                         (e - environ) * sizeof *environ));
     to = 1;
     for (e = environ; (env[to] = *e); e++)
       to += strncmp(*e, "TZ=", 3) != 0;
   }
-  env0 = malloc(sumsize(sizeof "TZ=", strlen(val)));
-  if (! env0) {
-    perror(progname);
-    exit(EXIT_FAILURE);
-  }
+  env0 = xmalloc(sumsize(sizeof "TZ=", strlen(val)));
   env[0] = strcat(strcpy(env0, "TZ="), val);
   environ = fakeenv = env;
   tzset();
@@ -527,11 +555,7 @@ saveabbr(char **buf, size_t *bufalloc, struct tm const *tmp)
         to avoid O(N**2) behavior on repeated calls.  */
       *bufalloc = sumsize(*bufalloc, ablen + 1);
 
-      *buf = malloc(*bufalloc);
-      if (! *buf) {
-       perror(progname);
-       exit(EXIT_FAILURE);
-      }
+      *buf = xmalloc(*bufalloc);
     }
     return strcpy(*buf, ab);
   }
@@ -552,10 +576,18 @@ static void
 usage(FILE * const stream, const int status)
 {
        fprintf(stream,
-_("%s: usage: %s [--version] [--help] [-{vV}] [-{ct} [lo,]hi] zonename ...\n"
+_("%s: usage: %s OPTIONS ZONENAME ...\n"
+  "Options include:\n"
+  "  -c [L,]U   Start at year L (default -500), end before year U (default 2500)\n"
+  "  -t [L,]U   Start at time L, end before time U (in seconds since 1970)\n"
+  "  -i         List transitions briefly (format is experimental)\n" \
+  "  -v         List transitions verbosely\n"
+  "  -V         List transitions a bit less verbosely\n"
+  "  --help     Output this help\n"
+  "  --version  Output version info\n"
   "\n"
   "Report bugs to %s.\n"),
-                      progname, progname, REPORT_BUGS_TO);
+               progname, progname, REPORT_BUGS_TO);
        if (status == EXIT_SUCCESS)
          close_file(stream);
        exit(status);
@@ -567,7 +599,6 @@ main(int argc, char *argv[])
        /* These are static so that they're initially zero.  */
        static char *           abbrev;
        static size_t           abbrevsize;
-       static struct tm        newtm;
 
        register int            i;
        register bool           vflag;
@@ -577,11 +608,7 @@ main(int argc, char *argv[])
        register time_t         cutlotime;
        register time_t         cuthitime;
        time_t                  now;
-       time_t                  t;
-       time_t                  newt;
-       struct tm               tm;
-       register struct tm *    tmp;
-       register struct tm *    newtmp;
+       bool iflag = false;
 
        cutlotime = absolute_min_time;
        cuthitime = absolute_max_time;
@@ -603,9 +630,10 @@ main(int argc, char *argv[])
        vflag = Vflag = false;
        cutarg = cuttimes = NULL;
        for (;;)
-         switch (getopt(argc, argv, "c:t:vV")) {
+         switch (getopt(argc, argv, "c:it:vV")) {
          case 'c': cutarg = optarg; break;
          case 't': cuttimes = optarg; break;
+         case 'i': iflag = true; break;
          case 'v': vflag = true; break;
          case 'V': Vflag = true; break;
          case -1:
@@ -617,7 +645,7 @@ main(int argc, char *argv[])
          }
  arg_processing_done:;
 
-       if (vflag | Vflag) {
+       if (iflag | vflag | Vflag) {
                intmax_t        lo;
                intmax_t        hi;
                char *loend, *hiend;
@@ -674,7 +702,9 @@ main(int argc, char *argv[])
                }
        }
        gmtzinit();
-       now = time(NULL);
+       INITIALIZE (now);
+       if (! (iflag | vflag | Vflag))
+         now = time(NULL);
        longest = 0;
        for (i = optind; i < argc; i++) {
          size_t arglen = strlen(argv[i]);
@@ -685,48 +715,66 @@ main(int argc, char *argv[])
        for (i = optind; i < argc; ++i) {
                timezone_t tz = tzalloc(argv[i]);
                char const *ab;
+               time_t t;
+               struct tm tm, newtm;
+               bool tm_ok;
                if (!tz) {
                  perror(argv[i]);
                  return EXIT_FAILURE;
                }
-               if (! (vflag | Vflag)) {
+               if (! (iflag | vflag | Vflag)) {
                        show(tz, argv[i], now, false);
                        tzfree(tz);
                        continue;
                }
                warned = false;
                t = absolute_min_time;
-               if (!Vflag) {
+               if (! (iflag | Vflag)) {
                        show(tz, argv[i], t, true);
                        t += SECSPERDAY;
                        show(tz, argv[i], t, true);
                }
                if (t < cutlotime)
                        t = cutlotime;
-               tmp = my_localtime_rz(tz, &t, &tm);
-               if (tmp)
+               tm_ok = my_localtime_rz(tz, &t, &tm) != NULL;
+               if (tm_ok) {
                  ab = saveabbr(&abbrev, &abbrevsize, &tm);
+                 if (iflag) {
+                   showtrans("\nTZ=%f", &tm, t, ab, argv[i]);
+                   showtrans("-\t-\t%Q", &tm, t, ab, argv[i]);
+                 }
+               }
                while (t < cuthitime) {
-                       newt = ((t < absolute_max_time - SECSPERDAY / 2
-                                && t + SECSPERDAY / 2 < cuthitime)
-                               ? t + SECSPERDAY / 2
-                               : cuthitime);
-                       newtmp = localtime_rz(tz, &newt, &newtm);
-                       if ((tmp == NULL || newtmp == NULL) ? (tmp != newtmp) :
-                               (delta(&newtm, &tm) != (newt - t) ||
-                               newtm.tm_isdst != tm.tm_isdst ||
-                               strcmp(abbr(&newtm), ab) != 0)) {
-                                       newt = hunt(tz, argv[i], t, newt);
-                                       newtmp = localtime_rz(tz, &newt, &newtm);
-                                       if (newtmp)
-                                         ab = saveabbr(&abbrev, &abbrevsize,
-                                                       &newtm);
-                       }
-                       t = newt;
-                       tm = newtm;
-                       tmp = newtmp;
+                 time_t newt = ((t < absolute_max_time - SECSPERDAY / 2
+                                 && t + SECSPERDAY / 2 < cuthitime)
+                                ? t + SECSPERDAY / 2
+                                : cuthitime);
+                 struct tm *newtmp = localtime_rz(tz, &newt, &newtm);
+                 bool newtm_ok = newtmp != NULL;
+                 if (! (tm_ok & newtm_ok
+                        ? (delta(&newtm, &tm) == newt - t
+                           && newtm.tm_isdst == tm.tm_isdst
+                           && strcmp(abbr(&newtm), ab) == 0)
+                        : tm_ok == newtm_ok)) {
+                   newt = hunt(tz, argv[i], t, newt);
+                   newtmp = localtime_rz(tz, &newt, &newtm);
+                   newtm_ok = newtmp != NULL;
+                   if (iflag)
+                     showtrans("%Y-%m-%d\t%L\t%Q", newtmp, newt,
+                               newtm_ok ? abbr(&newtm) : NULL, argv[i]);
+                   else {
+                     show(tz, argv[i], newt - 1, true);
+                     show(tz, argv[i], newt, true);
+                   }
+                 }
+                 t = newt;
+                 tm_ok = newtm_ok;
+                 if (newtm_ok) {
+                   ab = saveabbr(&abbrev, &abbrevsize, &newtm);
+                   tm = newtm;
+                 }
                }
-               if (!Vflag) {
+               if (! (iflag | Vflag)) {
                        t = absolute_max_time;
                        t -= SECSPERDAY;
                        show(tz, argv[i], t, true);
@@ -792,12 +840,11 @@ hunt(timezone_t tz, char *name, time_t lot, time_t hit)
        char const *            ab;
        time_t                  t;
        struct tm               lotm;
-       register struct tm *    lotmp;
        struct tm               tm;
-       register struct tm *    tmp;
+       bool lotm_ok = my_localtime_rz(tz, &lot, &lotm) != NULL;
+       bool tm_ok;
 
-       lotmp = my_localtime_rz(tz, &lot, &lotm);
-       if (lotmp)
+       if (lotm_ok)
          ab = saveabbr(&loab, &loabsize, &lotm);
        for ( ; ; ) {
                time_t diff = hit - lot;
@@ -809,18 +856,17 @@ hunt(timezone_t tz, char *name, time_t lot, time_t hit)
                        ++t;
                else if (t >= hit)
                        --t;
-               tmp = my_localtime_rz(tz, &t, &tm);
-               if ((lotmp == NULL || tmp == NULL) ? (lotmp == tmp) :
-                       (delta(&tm, &lotm) == (t - lot) &&
-                       tm.tm_isdst == lotm.tm_isdst &&
-                       strcmp(abbr(&tm), ab) == 0)) {
-                               lot = t;
-                               lotm = tm;
-                               lotmp = tmp;
+               tm_ok = my_localtime_rz(tz, &t, &tm) != NULL;
+               if (lotm_ok & tm_ok
+                   ? (delta(&tm, &lotm) == t - lot
+                      && tm.tm_isdst == lotm.tm_isdst
+                      && strcmp(abbr(&tm), ab) == 0)
+                   : lotm_ok == tm_ok) {
+                 lot = t;
+                 if (tm_ok)
+                   lotm = tm;
                } else  hit = t;
        }
-       show(tz, name, lot, true);
-       show(tz, name, hit, true);
        return hit;
 }
 
@@ -864,13 +910,20 @@ adjusted_yday(struct tm const *a, struct tm const *b)
 
 /* If A is the broken-down local time and B the broken-down UTC for
    the same instant, return A's UTC offset in seconds, where positive
-   offsets are east of Greenwich.  On failure, return LONG_MIN.  */
+   offsets are east of Greenwich.  On failure, return LONG_MIN.
+
+   If T is nonnull, *T is the time stamp that corresponds to A; call
+   my_gmtime_r and use its result instead of B.  Otherwise, B is the
+   possibly nonnull result of an earlier call to my_gmtime_r.  */
 static long
-gmtoff(struct tm const *a, struct tm const *b)
+gmtoff(struct tm const *a, time_t *t, struct tm const *b)
 {
 #ifdef TM_GMTOFF
   return a->TM_GMTOFF;
 #else
+  struct tm tm;
+  if (t)
+    b = my_gmtime_r(t, &tm);
   if (! b)
     return LONG_MIN;
   else {
@@ -909,7 +962,7 @@ show(timezone_t tz, char *zone, time_t t, bool v)
                if (*abbr(tmp) != '\0')
                        printf(" %s", abbr(tmp));
                if (v) {
-                       long off = gmtoff(tmp, gmtmp);
+                       long off = gmtoff(tmp, NULL, gmtmp);
                        printf(" isdst=%d", tmp->tm_isdst);
                        if (off != LONG_MIN)
                          printf(" gmtoff=%ld", off);
@@ -920,6 +973,204 @@ show(timezone_t tz, char *zone, time_t t, bool v)
                abbrok(abbr(tmp), zone);
 }
 
+/* Store into BUF, of size SIZE, a formatted local time taken from *TM.
+   Use ISO 8601 format +HH:MM:SS.  Omit :SS if SS is zero, and omit
+   :MM too if MM is also zero.
+
+   Return the length of the resulting string.  If the string does not
+   fit, return the length that the string would have been if it had
+   fit; do not overrun the output buffer.  */
+static int
+format_local_time(char *buf, size_t size, struct tm const *tm)
+{
+  int ss = tm->tm_sec, mm = tm->tm_min, hh = tm->tm_hour;
+  return (ss
+         ? snprintf(buf, size, "%02d:%02d:%02d", hh, mm, ss)
+         : mm
+         ? snprintf(buf, size, "%02d:%02d", hh, mm)
+         : snprintf(buf, size, "%02d", hh));
+}
+
+/* Store into BUF, of size SIZE, a formatted UTC offset for the
+   localtime *TM corresponding to time T.  Use ISO 8601 format
+   +HH:MM:SS, or -HH:MM:SS for time stamps west of Greenwich.  Omit
+   :SS if :SS is zero, and omit :MM too if :MM is also zero.  If the
+   time stamp represents an unknown UTC offset, use the format -00.
+
+   Return the length of the resulting string, or -1 if the result is
+   not representable as a string.  If the string does not fit, return
+   the length that the string would have been if it had fit; do not
+   overrun the output buffer.  */
+static int
+format_utc_offset(char *buf, size_t size, struct tm const *tm, time_t t)
+{
+  long off = gmtoff(tm, &t, NULL);
+  char sign = ((off < 0
+               || (off == 0
+                   && (*abbr(tm) == '-' || strcmp(abbr(tm), "zzz") == 0)))
+              ? '-' : '+');
+  long hh;
+  int mm, ss;
+  if (off < 0)
+    {
+      if (off == LONG_MIN)
+       return -1;
+      off = -off;
+    }
+  ss = off % 60;
+  mm = off / 60 % 60;
+  hh = off / 60 / 60;
+  return (ss
+         ? snprintf(buf, size, "%c%02ld:%02d:%02d", sign, hh, mm, ss)
+         : mm
+         ? snprintf(buf, size, "%c%02ld:%02d", sign, hh, mm)
+         : snprintf(buf, size, "%c%02ld", sign, hh));
+}
+
+/* Store into BUF (of size SIZE) a quoted string representation of P.
+   If the representation's length is less than SIZE, return the
+   length; the representation is not null terminated.  Otherwise
+   return SIZE, to indicate that BUF is too small.  */
+static size_t
+format_quoted_string(char *buf, size_t size, char const *p)
+{
+  char *b = buf;
+  size_t s = size;
+  if (!s)
+    return size;
+  *b++ = '"', s--;
+  for (;;) {
+    char c = *p++;
+    if (s <= 1)
+      return size;
+    switch (c) {
+    default: *b++ = c, s--; continue;
+    case '\0': *b++ = '"', s--; return size - s;
+    case '"': case '\\': break;
+    case ' ': c = 's'; break;
+    case '\f': c = 'f'; break;
+    case '\n': c = 'n'; break;
+    case '\r': c = 'r'; break;
+    case '\t': c = 't'; break;
+    case '\v': c = 'v'; break;
+    }
+    *b++ = '\\', *b++ = c, s -= 2;
+  }
+}
+
+/* Store into BUF (of size SIZE) a time stamp formatted by TIME_FMT.
+   TM is the broken-down time, T the seconds count, AB the time zone
+   abbreviation, and ZONE_NAME the zone name.  Return true if
+   successful, false if the output would require more than SIZE bytes.
+   TIME_FMT uses the same format that strftime uses, with these
+   additions:
+
+   %f zone name
+   %L local time as per format_local_time
+   %Q like "U\t%Z\tD" where U is the UTC offset as for format_utc_offset
+      and D is the isdst flag; except omit D if it is zero, omit %Z if
+      it equals U, quote and escape %Z if it contains nonalphabetics,
+      and omit any trailing tabs.  */
+
+static bool
+istrftime(char *buf, size_t size, char const *time_fmt,
+         struct tm const *tm, time_t t, char const *ab, char const *zone_name)
+{
+  char *b = buf;
+  size_t s = size;
+  char const *f = time_fmt, *p;
+
+  for (p = f; ; p++)
+    if (*p == '%' && p[1] == '%')
+      p++;
+    else if (!*p
+            || (*p == '%'
+                && (p[1] == 'f' || p[1] == 'L' || p[1] == 'Q'))) {
+      size_t formatted_len;
+      size_t f_prefix_len = p - f;
+      size_t f_prefix_copy_size = p - f + 2;
+      char fbuf[100];
+      bool oversized = sizeof fbuf <= f_prefix_copy_size;
+      char *f_prefix_copy = oversized ? xmalloc(f_prefix_copy_size) : fbuf;
+      memcpy(f_prefix_copy, f, f_prefix_len);
+      strcpy(f_prefix_copy + f_prefix_len, "X");
+      formatted_len = strftime(b, s, f_prefix_copy, tm);
+      if (oversized)
+       free(f_prefix_copy);
+      if (formatted_len == 0)
+       return false;
+      formatted_len--;
+      b += formatted_len, s -= formatted_len;
+      if (!*p++)
+       break;
+      switch (*p) {
+      case 'f':
+       formatted_len = format_quoted_string(b, s, zone_name);
+       break;
+      case 'L':
+       formatted_len = format_local_time(b, s, tm);
+       break;
+      case 'Q':
+       {
+         bool show_abbr;
+         int offlen = format_utc_offset(b, s, tm, t);
+         if (! (0 <= offlen && offlen < s))
+           return false;
+         show_abbr = strcmp(b, ab) != 0;
+         b += offlen, s -= offlen;
+         if (show_abbr) {
+           char const *abp;
+           size_t len;
+           if (s <= 1)
+             return false;
+           *b++ = '\t', s--;
+           for (abp = ab; is_alpha(*abp); abp++)
+             continue;
+           len = (!*abp && *ab
+                  ? snprintf(b, s, "%s", ab)
+                  : format_quoted_string(b, s, ab));
+           if (s <= len)
+             return false;
+           b += len, s -= len;
+         }
+         formatted_len = (tm->tm_isdst
+                          ? snprintf(b, s, &"\t\t%d"[show_abbr], tm->tm_isdst)
+                          : 0);
+       }
+       break;
+      }
+      if (! (0 <= formatted_len && formatted_len < s))
+       return false;
+      b += formatted_len, s -= formatted_len;
+      f = p + 1;
+    }
+  *b = '\0';
+  return true;
+}
+
+/* Show a time transition.  */
+static void
+showtrans(char const *time_fmt, struct tm const *tm, time_t t, char const *ab,
+         char const *zone_name)
+{
+  if (!tm) {
+    printf(tformat(), t);
+    putchar('\n');
+  } else {
+    char stackbuf[1000];
+    size_t size = sizeof stackbuf;
+    char *buf = stackbuf;
+    char *bufalloc = NULL;
+    while (! istrftime(buf, size, time_fmt, tm, t, ab, zone_name)) {
+      size = sumsize(size, size);
+      free(bufalloc);
+      buf = bufalloc = xmalloc(size);
+    }
+    puts(buf);
+    free(bufalloc);
+  }
+}
+
 static char const *
 abbr(struct tm const *tmp)
 {
diff --git a/zic.c b/zic.c
index 3eb65d3..f6baf10 100644 (file)
--- a/zic.c
+++ b/zic.c
@@ -9,6 +9,7 @@
 #include "tzfile.h"
 
 #include <stdarg.h>
+#include <stddef.h>
 
 #define        ZIC_VERSION_PRE_2013 '2'
 #define        ZIC_VERSION     '3'
@@ -16,6 +17,7 @@
 typedef int_fast64_t   zic_t;
 #define ZIC_MIN INT_FAST64_MIN
 #define ZIC_MAX INT_FAST64_MAX
+#define PRIdZIC PRIdFAST64
 #define SCNdZIC SCNdFAST64
 
 #ifndef ZIC_MAX_ABBR_LEN_WO_WARN
@@ -38,9 +40,18 @@ typedef int_fast64_t zic_t;
 #define MKDIR_UMASK 0755
 #endif
 
+/* The maximum ptrdiff_t value, for pre-C99 platforms.  */
+#ifndef PTRDIFF_MAX
+static ptrdiff_t const PTRDIFF_MAX = MAXVAL(ptrdiff_t, TYPE_BIT(ptrdiff_t));
+#endif
+
+/* The type and printf format for line numbers.  */
+typedef intmax_t lineno;
+#define PRIdLINENO PRIdMAX
+
 struct rule {
        const char *    r_filename;
-       int             r_linenum;
+       lineno          r_linenum;
        const char *    r_name;
 
        zic_t           r_loyear;       /* for example, 1986 */
@@ -63,7 +74,7 @@ struct rule {
        zic_t           r_stdoff;       /* offset from standard time */
        const char *    r_abbrvar;      /* variable part of abbreviation */
 
-       int             r_todo;         /* a rule to do (used in outzone) */
+       bool            r_todo;         /* a rule to do (used in outzone) */
        zic_t           r_temp;         /* used in outzone */
 };
 
@@ -77,7 +88,7 @@ struct rule {
 
 struct zone {
        const char *    z_filename;
-       int             z_linenum;
+       lineno          z_linenum;
 
        const char *    z_name;
        zic_t           z_gmtoff;
@@ -88,7 +99,7 @@ struct zone {
        zic_t           z_stdoff;
 
        struct rule *   z_rules;
-       int             z_nrules;
+       ptrdiff_t       z_nrules;
 
        struct rule     z_untilrule;
        zic_t           z_untiltime;
@@ -106,7 +117,9 @@ extern int  optind;
 # define link(from, to) (errno = ENOTSUP, -1)
 #endif
 #if ! HAVE_SYMLINK
+# define lstat(name, st) stat(name, st)
 # define symlink(from, to) (errno = ENOTSUP, -1)
+# define S_ISLNK(m) 0
 #endif
 
 static void    addtt(zic_t starttime, int type);
@@ -114,7 +127,7 @@ static int  addtype(zic_t, char const *, bool, bool, bool);
 static void    leapadd(zic_t, bool, int, int);
 static void    adjleap(void);
 static void    associate(void);
-static void    dolink(const char * fromfield, const char * tofield);
+static void    dolink(const char *, const char *, bool);
 static char ** getfields(char * buf);
 static zic_t   gethms(const char * string, const char * errstring,
                       bool);
@@ -128,23 +141,23 @@ static bool       inzsub(char **, int, bool);
 static int     itsdir(const char * name);
 static bool    is_alpha(char a);
 static char    lowerit(char);
-static bool    mkdirs(char *);
+static void    mkdirs(char const *, bool);
 static void    newabbr(const char * abbr);
 static zic_t   oadd(zic_t t1, zic_t t2);
-static void    outzone(const struct zone * zp, int ntzones);
+static void    outzone(const struct zone * zp, ptrdiff_t ntzones);
 static zic_t   rpytime(const struct rule * rp, zic_t wantedy);
 static void    rulesub(struct rule * rp,
                        const char * loyearp, const char * hiyearp,
                        const char * typep, const char * monthp,
                        const char * dayp, const char * timep);
 static zic_t   tadd(zic_t t1, zic_t t2);
-static bool    yearistype(int year, const char * type);
+static bool    yearistype(zic_t year, const char * type);
 
 /* Bound on length of what %z can expand to.  */
 enum { PERCENT_Z_LEN_BOUND = sizeof "+995959" - 1 };
 
 /* If true, work around a bug in Qt 5.6.1 and earlier, which mishandles
-   tzdata binary files whose POSIX-TZ-style strings contain '<'; see
+   tz binary files whose POSIX-TZ-style strings contain '<'; see
    QTBUG-53071 <https://bugreports.qt.io/browse/QTBUG-53071>.  This
    workaround will no longer be needed when Qt 5.6.1 and earlier are
    obsolete, say in the year 2021.  */
@@ -158,17 +171,17 @@ static int                leapcnt;
 static bool            leapseen;
 static zic_t           leapminyear;
 static zic_t           leapmaxyear;
-static int             linenum;
+static lineno          linenum;
 static int             max_abbrvar_len = PERCENT_Z_LEN_BOUND;
 static int             max_format_len;
 static zic_t           max_year;
 static zic_t           min_year;
 static bool            noise;
 static const char *    rfilename;
-static int             rlinenum;
+static lineno          rlinenum;
 static const char *    progname;
-static int             timecnt;
-static int             timecnt_alloc;
+static ptrdiff_t       timecnt;
+static ptrdiff_t       timecnt_alloc;
 static int             typecnt;
 
 /*
@@ -253,23 +266,23 @@ static int                typecnt;
 #define YR_ONLY                2
 
 static struct rule *   rules;
-static int             nrules; /* number of rules */
-static int             nrules_alloc;
+static ptrdiff_t       nrules; /* number of rules */
+static ptrdiff_t       nrules_alloc;
 
 static struct zone *   zones;
-static int             nzones; /* number of zones */
-static int             nzones_alloc;
+static ptrdiff_t       nzones; /* number of zones */
+static ptrdiff_t       nzones_alloc;
 
 struct link {
        const char *    l_filename;
-       int             l_linenum;
+       lineno          l_linenum;
        const char *    l_from;
        const char *    l_to;
 };
 
 static struct link *   links;
-static int             nlinks;
-static int             nlinks_alloc;
+static ptrdiff_t       nlinks;
+static ptrdiff_t       nlinks_alloc;
 
 struct lookup {
        const char *    l_word;
@@ -355,6 +368,7 @@ static const int    len_years[2] = {
 
 static struct attype {
        zic_t           at;
+       bool            dontmerge;
        unsigned char   type;
 } *                    attypes;
 static zic_t           gmtoffs[TZ_MAX_TYPES];
@@ -422,16 +436,16 @@ ecpyalloc (char const *str)
 }
 
 static void *
-growalloc(void *ptr, size_t itemsize, int nitems, int *nitems_alloc)
+growalloc(void *ptr, size_t itemsize, ptrdiff_t nitems, ptrdiff_t *nitems_alloc)
 {
        if (nitems < *nitems_alloc)
                return ptr;
        else {
-               int nitems_max = INT_MAX - WORK_AROUND_QTBUG_53071;
-               int amax = nitems_max < SIZE_MAX ? nitems_max : SIZE_MAX;
+               ptrdiff_t nitems_max = PTRDIFF_MAX - WORK_AROUND_QTBUG_53071;
+               ptrdiff_t amax = nitems_max < SIZE_MAX ? nitems_max : SIZE_MAX;
                if ((amax - 1) / 3 * 2 < *nitems_alloc)
-                       memory_exhausted(_("int overflow"));
-               *nitems_alloc = *nitems_alloc + (*nitems_alloc >> 1) + 1;
+                       memory_exhausted(_("integer overflow"));
+               *nitems_alloc += (*nitems_alloc >> 1) + 1;
                return erealloc(ptr, size_product(*nitems_alloc, itemsize));
        }
 }
@@ -441,8 +455,7 @@ growalloc(void *ptr, size_t itemsize, int nitems, int *nitems_alloc)
 */
 
 static void
-eats(const char *const name, const int num, const char *const rname,
-     const int rnum)
+eats(char const *name, lineno num, char const *rname, lineno rnum)
 {
        filename = name;
        linenum = num;
@@ -451,7 +464,7 @@ eats(const char *const name, const int num, const char *const rname,
 }
 
 static void
-eat(const char *const name, const int num)
+eat(char const *name, lineno num)
 {
        eats(name, num, NULL, -1);
 }
@@ -465,10 +478,10 @@ verror(const char *const string, va_list args)
        ** on BSD systems.
        */
        if (filename)
-         fprintf(stderr, _("\"%s\", line %d: "), filename, linenum);
+         fprintf(stderr, _("\"%s\", line %"PRIdLINENO": "), filename, linenum);
        vfprintf(stderr, string, args);
        if (rfilename != NULL)
-               fprintf(stderr, _(" (rule from \"%s\", line %d)"),
+               fprintf(stderr, _(" (rule from \"%s\", line %"PRIdLINENO")"),
                        rfilename, rlinenum);
        fprintf(stderr, "\n");
 }
@@ -495,15 +508,15 @@ warning(const char *const string, ...)
 }
 
 static void
-close_file(FILE *stream, char const *name)
+close_file(FILE *stream, char const *dir, char const *name)
 {
   char const *e = (ferror(stream) ? _("I/O error")
                   : fclose(stream) != 0 ? strerror(errno) : NULL);
   if (e) {
-    fprintf(stderr, "%s: ", progname);
-    if (name)
-      fprintf(stderr, "%s: ", name);
-    fprintf(stderr, "%s\n", e);
+    fprintf(stderr, "%s: %s%s%s%s%s\n", progname,
+           dir ? dir : "", dir ? "/" : "",
+           name ? name : "", name ? ": " : "",
+           e);
     exit(EXIT_FAILURE);
   }
 }
@@ -518,10 +531,30 @@ usage(FILE *stream, int status)
            "Report bugs to %s.\n"),
          progname, progname, REPORT_BUGS_TO);
   if (status == EXIT_SUCCESS)
-    close_file(stream, NULL);
+    close_file(stream, NULL, NULL);
   exit(status);
 }
 
+/* Change the working directory to DIR, possibly creating DIR and its
+   ancestors.  After this is done, all files are accessed with names
+   relative to DIR.  */
+static void
+change_directory (char const *dir)
+{
+  if (chdir(dir) != 0) {
+    int chdir_errno = errno;
+    if (chdir_errno == ENOENT) {
+      mkdirs(dir, false);
+      chdir_errno = chdir(dir) == 0 ? 0 : errno;
+    }
+    if (chdir_errno != 0) {
+      fprintf(stderr, _("%s: Can't chdir to %s: %s\n"),
+             progname, dir, strerror(chdir_errno));
+      exit(EXIT_FAILURE);
+    }
+  }
+}
+
 static const char *    psxrules;
 static const char *    lcltime;
 static const char *    directory;
@@ -531,9 +564,8 @@ static const char * yitcommand;
 int
 main(int argc, char **argv)
 {
-       register int    i;
-       register int    j;
-       register int    c;
+       register int c, k;
+       register ptrdiff_t i, j;
 
 #ifdef S_IWGRP
        umask(umask(S_IWGRP | S_IWOTH) | (S_IWGRP | S_IWOTH));
@@ -551,12 +583,12 @@ main(int argc, char **argv)
                        _("wild compilation-time specification of zic_t"));
                return EXIT_FAILURE;
        }
-       for (i = 1; i < argc; ++i)
-               if (strcmp(argv[i], "--version") == 0) {
+       for (k = 1; k < argc; k++)
+               if (strcmp(argv[k], "--version") == 0) {
                        printf("zic %s%s\n", PKGVERSION, TZVERSION);
-                       close_file(stdout, NULL);
+                       close_file(stdout, NULL, NULL);
                        return EXIT_SUCCESS;
-               } else if (strcmp(argv[i], "--help") == 0) {
+               } else if (strcmp(argv[k], "--help") == 0) {
                        usage(stdout, EXIT_SUCCESS);
                }
        while ((c = getopt(argc, argv, "d:l:p:L:vsy:")) != EOF && c != -1)
@@ -632,11 +664,12 @@ _("%s: More than one -L option specified\n"),
                adjleap();
        }
 
-       for (i = optind; i < argc; ++i)
-               infile(argv[i]);
+       for (k = optind; k < argc; k++)
+               infile(argv[k]);
        if (errors)
                return EXIT_FAILURE;
        associate();
+       change_directory(directory);
        for (i = 0; i < nzones; i = j) {
                /*
                ** Find the next non-continuation zone entry.
@@ -650,7 +683,7 @@ _("%s: More than one -L option specified\n"),
        */
        for (i = 0; i < nlinks; ++i) {
                eat(links[i].l_filename, links[i].l_linenum);
-               dolink(links[i].l_from, links[i].l_to);
+               dolink(links[i].l_from, links[i].l_to, false);
                if (noise)
                        for (j = 0; j < nlinks; ++j)
                                if (strcmp(links[i].l_to,
@@ -659,11 +692,11 @@ _("%s: More than one -L option specified\n"),
        }
        if (lcltime != NULL) {
                eat(_("command line"), 1);
-               dolink(lcltime, TZDEFAULT);
+               dolink(lcltime, TZDEFAULT, true);
        }
        if (psxrules != NULL) {
                eat(_("command line"), 1);
-               dolink(psxrules, TZDEFRULES);
+               dolink(psxrules, TZDEFRULES, true);
        }
        if (warnings && (ferror(stderr) || fclose(stderr) != 0))
          return EXIT_FAILURE;
@@ -675,7 +708,7 @@ componentcheck(char const *name, char const *component,
               char const *component_end)
 {
        enum { component_len_max = 14 };
-       size_t component_len = component_end - component;
+       ptrdiff_t component_len = component_end - component;
        if (component_len == 0) {
          if (!*name)
            error (_("empty file name"));
@@ -690,8 +723,9 @@ componentcheck(char const *name, char const *component,
        }
        if (0 < component_len && component_len <= 2
            && component[0] == '.' && component_end[-1] == '.') {
+         int len = component_len;
          error(_("file name '%s' contains '%.*s' component"),
-               name, (int) component_len, component);
+               name, len, component);
          return false;
        }
        if (noise) {
@@ -740,118 +774,128 @@ namecheck(const char *name)
        return componentcheck(name, component, cp);
 }
 
+/* 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
+   relative or absolute.  */
 static char *
-relname(char const *dir, char const *base)
-{
-  if (*base == '/')
-    return ecpyalloc(base);
-  else {
-    size_t dir_len = strlen(dir);
-    bool needs_slash = dir_len && dir[dir_len - 1] != '/';
-    char *result = emalloc(dir_len + needs_slash + strlen(base) + 1);
-    result[dir_len] = '/';
-    strcpy(result + dir_len + needs_slash, base);
-    return memcpy(result, dir, dir_len);
+relname(char const *from, char const *to)
+{
+  size_t i, taillen, dotdotetcsize;
+  size_t dir_len = 0, dotdots = 0, linksize = SIZE_MAX;
+  char const *f = from;
+  char *result = NULL;
+  if (*to == '/') {
+    /* Make F absolute too.  */
+    size_t len = strlen(directory);
+    bool needslash = len && directory[len - 1] != '/';
+    linksize = len + needslash + strlen(from) + 1;
+    f = result = emalloc(linksize);
+    strcpy(result, directory);
+    result[len] = '/';
+    strcpy(result + len + needslash, from);
+  }
+  for (i = 0; f[i] && f[i] == to[i]; i++)
+    if (f[i] == '/')
+      dir_len = i + 1;
+  for (; f[i]; i++)
+    dotdots += f[i] == '/' && f[i - 1] != '/';
+  taillen = i - dir_len;
+  dotdotetcsize = 3 * dotdots + taillen + 1;
+  if (dotdotetcsize <= linksize) {
+    if (!result)
+      result = emalloc(dotdotetcsize);
+    for (i = 0; i < dotdots; i++)
+      memcpy(result + 3 * i, "../", 3);
+    memmove(result + 3 * dotdots, f + dir_len, taillen + 1);
   }
+  return result;
 }
 
 static void
-dolink(char const *fromfield, char const *tofield)
+dolink(char const *fromfield, char const *tofield, bool staysymlink)
 {
-       register char * fromname;
-       register char * toname;
        register int fromisdir;
+       bool todirs_made = false;
+       int link_errno;
 
-       fromname = relname(directory, fromfield);
-       toname = relname(directory, tofield);
        /*
        ** We get to be careful here since
        ** there's a fair chance of root running us.
        */
-       fromisdir = itsdir(fromname);
+       fromisdir = itsdir(fromfield);
        if (fromisdir) {
                char const *e = strerror(fromisdir < 0 ? errno : EPERM);
-               fprintf(stderr, _("%s: link from %s failed: %s"),
-                       progname, fromname, e);
+               fprintf(stderr, _("%s: link from %s/%s failed: %s\n"),
+                       progname, directory, fromfield, e);
                exit(EXIT_FAILURE);
        }
-       if (link(fromname, toname) != 0) {
-         int link_errno = errno;
-         bool retry_if_link_supported = false;
-
-         if (link_errno == ENOENT || link_errno == ENOTSUP) {
-           if (! mkdirs(toname))
-             exit(EXIT_FAILURE);
-           retry_if_link_supported = true;
+       if (staysymlink)
+         staysymlink = itsdir(tofield) == 2;
+       if (remove(tofield) == 0)
+         todirs_made = true;
+       else if (errno != ENOENT) {
+         char const *e = strerror(errno);
+         fprintf(stderr, _("%s: Can't remove %s/%s: %s\n"),
+                 progname, directory, tofield, e);
+         exit(EXIT_FAILURE);
+       }
+       link_errno = (staysymlink ? ENOTSUP
+                     : link(fromfield, tofield) == 0 ? 0 : errno);
+       if (link_errno == ENOENT && !todirs_made) {
+         mkdirs(tofield, true);
+         todirs_made = true;
+         link_errno = link(fromfield, tofield) == 0 ? 0 : errno;
+       }
+       if (link_errno != 0) {
+         bool absolute = *fromfield == '/';
+         char *linkalloc = absolute ? NULL : relname(fromfield, tofield);
+         char const *contents = absolute ? fromfield : linkalloc;
+         int symlink_errno = symlink(contents, tofield) == 0 ? 0 : errno;
+         if (symlink_errno == ENOENT && !todirs_made) {
+           mkdirs(tofield, true);
+           symlink_errno = symlink(contents, tofield) == 0 ? 0 : errno;
          }
-         if ((link_errno == EEXIST || link_errno == ENOTSUP)
-             && itsdir(toname) == 0
-             && (remove(toname) == 0 || errno == ENOENT))
-           retry_if_link_supported = true;
-         if (retry_if_link_supported && link_errno != ENOTSUP)
-           link_errno = link(fromname, toname) == 0 ? 0 : errno;
-         if (link_errno != 0) {
-           const char *s = fromfield;
-           const char *t;
-           char *p;
-           size_t dotdots = 0;
-           char *symlinkcontents;
-           int symlink_result;
-
-           do
-             t = s;
-           while ((s = strchr(s, '/'))
-                  && strncmp(fromfield, tofield, ++s - fromfield) == 0);
-
-           for (s = tofield + (t - fromfield); *s; s++)
-             dotdots += *s == '/';
-           symlinkcontents = emalloc(3 * dotdots + strlen(t) + 1);
-           for (p = symlinkcontents; dotdots-- != 0; p += 3)
-             memcpy(p, "../", 3);
-           strcpy(p, t);
-           symlink_result = symlink(symlinkcontents, toname);
-           free(symlinkcontents);
-           if (symlink_result == 0) {
-             if (link_errno != ENOTSUP)
-               warning(_("symbolic link used because hard link failed: %s"),
-                       strerror (link_errno));
-           } else {
-                       FILE *fp, *tp;
-                       int c;
-                       fp = fopen(fromname, "rb");
-                       if (!fp) {
-                               const char *e = strerror(errno);
-                               fprintf(stderr,
-                                              _("%s: Can't read %s: %s\n"),
-                                              progname, fromname, e);
-                               exit(EXIT_FAILURE);
-                       }
-                       tp = fopen(toname, "wb");
-                       if (!tp) {
-                               const char *e = strerror(errno);
-                               fprintf(stderr,
-                                              _("%s: Can't create %s: %s\n"),
-                                              progname, toname, e);
-                               exit(EXIT_FAILURE);
-                       }
-                       while ((c = getc(fp)) != EOF)
-                               putc(c, tp);
-                       close_file(fp, fromname);
-                       close_file(tp, toname);
-                       if (link_errno != ENOTSUP)
-                         warning(_("copy used because hard link failed: %s"),
-                                 strerror (link_errno));
+         free(linkalloc);
+         if (symlink_errno == 0) {
+           if (link_errno != ENOTSUP)
+             warning(_("symbolic link used because hard link failed: %s"),
+                     strerror(link_errno));
+         } else {
+           FILE *fp, *tp;
+           int c;
+           fp = fopen(fromfield, "rb");
+           if (!fp) {
+             char const *e = strerror(errno);
+             fprintf(stderr, _("%s: Can't read %s/%s: %s\n"),
+                     progname, directory, fromfield, e);
+             exit(EXIT_FAILURE);
+           }
+           tp = fopen(tofield, "wb");
+           if (!tp) {
+             char const *e = strerror(errno);
+             fprintf(stderr, _("%s: Can't create %s/%s: %s\n"),
+                     progname, directory, tofield, e);
+             exit(EXIT_FAILURE);
            }
+           while ((c = getc(fp)) != EOF)
+             putc(c, tp);
+           close_file(fp, directory, fromfield);
+           close_file(tp, directory, tofield);
+           if (link_errno != ENOTSUP)
+             warning(_("copy used because hard link failed: %s"),
+                     strerror(link_errno));
+           else if (symlink_errno != ENOTSUP)
+             warning(_("copy used because symbolic link failed: %s"),
+                     strerror(symlink_errno));
          }
        }
-       free(fromname);
-       free(toname);
 }
 
 #define TIME_T_BITS_IN_FILE    64
 
-static zic_t const min_time = MINVAL (zic_t, TIME_T_BITS_IN_FILE);
-static zic_t const max_time = MAXVAL (zic_t, TIME_T_BITS_IN_FILE);
+static zic_t const min_time = MINVAL(zic_t, TIME_T_BITS_IN_FILE);
+static zic_t const max_time = MAXVAL(zic_t, TIME_T_BITS_IN_FILE);
 
 /* Estimated time of the Big Bang, in seconds since the POSIX epoch.
    rounded downward to the negation of a power of two that is
@@ -891,21 +935,26 @@ static const zic_t early_time = (WORK_AROUND_GNOME_BUG_730332
                                 ? BIG_BANG
                                 : MINVAL(zic_t, TIME_T_BITS_IN_FILE));
 
-/* Return 1 if NAME is a directory, 0 if it's something else, -1 if trouble.  */
+/* Return 1 if NAME is a directory, 2 if a symbolic link, 0 if
+   something else, -1 (setting errno) if trouble.  */
 static int
 itsdir(char const *name)
 {
        struct stat st;
-       int res = stat(name, &st);
+       int res = lstat(name, &st);
+       if (res == 0) {
 #ifdef S_ISDIR
-       if (res == 0)
-               return S_ISDIR(st.st_mode) != 0;
-#endif
-       if (res == 0 || errno == EOVERFLOW) {
-               char *nameslashdot = relname(name, ".");
-               bool dir = stat(nameslashdot, &st) == 0 || errno == EOVERFLOW;
+               return S_ISDIR(st.st_mode) ? 1 : S_ISLNK(st.st_mode) ? 2 : 0;
+#else
+               size_t n = strlen(name);
+               char *nameslashdot = emalloc(n + 3);
+               bool dir;
+               memcpy(nameslashdot, name, n);
+               strcpy(&nameslashdot[n], &"/."[! (n && name[n - 1] != '/')]);
+               dir = lstat(nameslashdot, &st) == 0;
                free(nameslashdot);
                return dir;
+#endif
        }
        return -1;
 }
@@ -930,8 +979,7 @@ associate(void)
 {
        register struct zone *  zp;
        register struct rule *  rp;
-       register int            base, out;
-       register int            i, j;
+       register ptrdiff_t i, j, base, out;
 
        if (nrules != 0) {
                qsort(rules, nrules, sizeof *rules, rcomp);
@@ -1009,7 +1057,7 @@ infile(const char *name)
        register const struct lookup *  lp;
        register int                    nfields;
        register bool                   wantcont;
-       register int                    num;
+       register lineno                 num;
        char                            buf[BUFSIZ];
 
        if (strcmp(name, "-") == 0) {
@@ -1050,7 +1098,7 @@ infile(const char *name)
                        lp = byword(fields[0], line_codes);
                        if (lp == NULL)
                                error(_("input line of unknown type"));
-                       else switch ((int) (lp->l_value)) {
+                       else switch (lp->l_value) {
                                case LC_RULE:
                                        inrule(fields, nfields);
                                        wantcont = false;
@@ -1079,7 +1127,7 @@ _("%s: panic: Invalid l_value %d\n"),
                }
                free(fields);
        }
-       close_file(fp, filename);
+       close_file(fp, NULL, filename);
        if (wantcont)
                error(_("expected continuation line not found"));
 }
@@ -1162,7 +1210,7 @@ inrule(char **fields, int nfields)
 static bool
 inzone(char **fields, int nfields)
 {
-       register int    i;
+       register ptrdiff_t i;
 
        if (nfields < ZONE_MINFIELDS || nfields > ZONE_MAXFIELDS) {
                error(_("wrong number of fields on Zone line"));
@@ -1183,8 +1231,8 @@ _("\"Zone %s\" line and -p option are mutually exclusive"),
        for (i = 0; i < nzones; ++i)
                if (zones[i].z_name != NULL &&
                        strcmp(zones[i].z_name, fields[ZF_NAME]) == 0) {
-                               error(
-_("duplicate zone name %s (file \"%s\", line %d)"),
+                               error(_("duplicate zone name %s"
+                                       " (file \"%s\", line %"PRIdLINENO")"),
                                        fields[ZF_NAME],
                                        zones[i].z_filename,
                                        zones[i].z_linenum);
@@ -1296,7 +1344,7 @@ inleap(char **fields, int nfields)
 {
        register const char *           cp;
        register const struct lookup *  lp;
-       register int                    i, j;
+       register zic_t                  i, j;
        zic_t                           year;
        int                             month, day;
        zic_t                           dayoff, tod;
@@ -1468,7 +1516,7 @@ 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 ((int) lp->l_value) {
+       if (!rp->r_lowasnum) switch (lp->l_value) {
                case YR_MINIMUM:
                        rp->r_loyear = ZIC_MIN;
                        break;
@@ -1487,7 +1535,7 @@ rulesub(struct rule *rp, const char *loyearp, const char *hiyearp,
        cp = hiyearp;
        lp = byword(cp, end_years);
        rp->r_hiwasnum = lp == NULL;
-       if (!rp->r_hiwasnum) switch ((int) lp->l_value) {
+       if (!rp->r_hiwasnum) switch (lp->l_value) {
                case YR_MINIMUM:
                        rp->r_hiyear = ZIC_MIN;
                        break;
@@ -1625,16 +1673,16 @@ static void
 writezone(const char *const name, const char *const string, char version)
 {
        register FILE *                 fp;
-       register int                    i, j;
+       register ptrdiff_t              i, j;
        register int                    leapcnt32, leapi32;
-       register int                    timecnt32, timei32;
+       register ptrdiff_t              timecnt32, timei32;
        register int                    pass;
-       char *                          fullname;
        static const struct tzhead      tzh0;
        static struct tzhead            tzh;
+       bool dir_checked = false;
        zic_t one = 1;
        zic_t y2038_boundary = one << 31;
-       int nats = timecnt + WORK_AROUND_QTBUG_53071;
+       ptrdiff_t nats = timecnt + WORK_AROUND_QTBUG_53071;
        zic_t *ats = emalloc(size_product(nats, sizeof *ats + 1));
        void *typesptr = ats + nats;
        unsigned char *types = typesptr;
@@ -1648,8 +1696,7 @@ writezone(const char *const name, const char *const string, char version)
        ** Optimize.
        */
        {
-               int     fromi;
-               int     toi;
+               ptrdiff_t fromi, toi;
 
                toi = 0;
                fromi = 0;
@@ -1664,15 +1711,23 @@ writezone(const char *const name, const char *const string, char version)
                                                attypes[fromi].type;
                                        continue;
                        }
-                       if (toi == 0 ||
-                               attypes[toi - 1].type != attypes[fromi].type)
+                       if (toi == 0
+                           || attypes[fromi].dontmerge
+                           || attypes[toi - 1].type != attypes[fromi].type)
                                        attypes[toi++] = attypes[fromi];
                }
                timecnt = toi;
        }
-       if (noise && timecnt > 1200)
+
+       if (noise && timecnt > 1200) {
+         if (timecnt > TZ_MAX_TIMES)
+               warning(_("reference clients mishandle"
+                         " more than %d transition times"),
+                       TZ_MAX_TIMES);
+         else
                warning(_("pre-2014 clients may mishandle"
                          " more than 1200 transition times"));
+       }
        /*
        ** Transfer.
        */
@@ -1730,50 +1785,58 @@ writezone(const char *const name, const char *const string, char version)
                --leapcnt32;
                ++leapi32;
        }
-       fullname = relname(directory, name);
        /*
        ** Remove old file, if any, to snap links.
        */
-       if (itsdir(fullname) == 0 && remove(fullname) != 0 && errno != ENOENT) {
+       if (remove(name) == 0)
+               dir_checked = true;
+       else if (errno != ENOENT) {
                const char *e = strerror(errno);
 
-               fprintf(stderr, _("%s: Can't remove %s: %s\n"),
-                       progname, fullname, e);
+               fprintf(stderr, _("%s: Can't remove %s/%s: %s\n"),
+                       progname, directory, name, e);
                exit(EXIT_FAILURE);
        }
-       if ((fp = fopen(fullname, "wb")) == NULL) {
-               if (! mkdirs(fullname))
-                       exit(EXIT_FAILURE);
-               if ((fp = fopen(fullname, "wb")) == NULL) {
-                       const char *e = strerror(errno);
-
-                       fprintf(stderr, _("%s: Can't create %s: %s\n"),
-                               progname, fullname, e);
-                       exit(EXIT_FAILURE);
-               }
+       fp = fopen(name, "wb");
+       if (!fp) {
+         int fopen_errno = errno;
+         if (fopen_errno == ENOENT && !dir_checked) {
+           mkdirs(name, true);
+           fp = fopen(name, "wb");
+           fopen_errno = errno;
+         }
+         if (!fp) {
+           fprintf(stderr, _("%s: Can't create %s/%s: %s\n"),
+                   progname, directory, name, strerror(fopen_errno));
+           exit(EXIT_FAILURE);
+         }
        }
        for (pass = 1; pass <= 2; ++pass) {
-               register int    thistimei, thistimecnt;
-               register int    thisleapi, thisleapcnt;
-               register int    thistimelim, thisleaplim;
+               register ptrdiff_t thistimei, thistimecnt, thistimelim;
+               register int    thisleapi, thisleapcnt, thisleaplim;
                int             writetype[TZ_MAX_TYPES];
                int             typemap[TZ_MAX_TYPES];
                register int    thistypecnt;
                char            thischars[TZ_MAX_CHARS];
-               char            thischarcnt;
+               int             thischarcnt;
+               bool            toomanytimes;
                int             indmap[TZ_MAX_CHARS];
 
                if (pass == 1) {
                        thistimei = timei32;
                        thistimecnt = timecnt32;
+                       toomanytimes = thistimecnt >> 31 >> 1 != 0;
                        thisleapi = leapi32;
                        thisleapcnt = leapcnt32;
                } else {
                        thistimei = 0;
                        thistimecnt = timecnt;
+                       toomanytimes = thistimecnt >> 31 >> 31 >> 2 != 0;
                        thisleapi = 0;
                        thisleapcnt = leapcnt;
                }
+               if (toomanytimes)
+                 error(_("too many transition times"));
                thistimelim = thistimei + thistimecnt;
                thisleaplim = thisleapi + thisleapcnt;
                for (i = 0; i < typecnt; ++i)
@@ -1860,8 +1923,7 @@ writezone(const char *const name, const char *const string, char version)
                                if (strcmp(&thischars[j], thisabbr) == 0)
                                        break;
                        if (j == thischarcnt) {
-                               strcpy(&thischars[(int) thischarcnt],
-                                       thisabbr);
+                               strcpy(&thischars[thischarcnt], thisabbr);
                                thischarcnt += strlen(thisabbr) + 1;
                        }
                        indmap[abbrinds[i]] = j;
@@ -1943,9 +2005,8 @@ writezone(const char *const name, const char *const string, char version)
                                putc(ttisgmts[i], fp);
        }
        fprintf(fp, "\n%s\n", string);
-       close_file(fp, fullname);
+       close_file(fp, directory, name);
        free(ats);
-       free(fullname);
 }
 
 static char const *
@@ -2146,13 +2207,13 @@ rule_cmp(struct rule const *a, struct rule const *b)
 enum { YEAR_BY_YEAR_ZONE = 1 };
 
 static int
-stringzone(char *result, const struct zone *const zpfirst, const int zonecount)
+stringzone(char *result, struct zone const *zpfirst, ptrdiff_t zonecount)
 {
        register const struct zone *    zp;
        register struct rule *          rp;
        register struct rule *          stdrp;
        register struct rule *          dstrp;
-       register int                    i;
+       register ptrdiff_t              i;
        register const char *           abbrvar;
        register int                    compat = 0;
        register int                    c;
@@ -2265,11 +2326,11 @@ stringzone(char *result, const struct zone *const zpfirst, const int zonecount)
 }
 
 static void
-outzone(const struct zone *zpfirst, int zonecount)
+outzone(const struct zone *zpfirst, ptrdiff_t zonecount)
 {
        register const struct zone *    zp;
        register struct rule *          rp;
-       register int                    i, j;
+       register ptrdiff_t              i, j;
        register bool                   usestart, useuntil;
        register zic_t                  starttime, untiltime;
        register zic_t                  gmtoff;
@@ -2288,6 +2349,7 @@ outzone(const struct zone *zpfirst, int zonecount)
        register int                    compat;
        register bool                   do_extend;
        register char                   version;
+       ptrdiff_t lastatmax = -1;
 
        max_abbr_len = 2 + max_format_len + max_abbrvar_len;
        max_envvar_len = 2 * max_abbr_len + 5 * 9;
@@ -2431,7 +2493,7 @@ outzone(const struct zone *zpfirst, int zonecount)
                                        rp->r_temp = rpytime(rp, year);
                        }
                        for ( ; ; ) {
-                               register int    k;
+                               register ptrdiff_t k;
                                register zic_t  jtime, ktime;
                                register zic_t  offset;
 
@@ -2520,6 +2582,10 @@ outzone(const struct zone *zpfirst, int zonecount)
                                offset = oadd(zp->z_gmtoff, rp->r_stdoff);
                                type = addtype(offset, ab, rp->r_stdoff != 0,
                                        rp->r_todisstd, rp->r_todisgmt);
+                               if (rp->r_hiyear == ZIC_MAX
+                                   && ! (0 <= lastatmax
+                                         && ktime < attypes[lastatmax].at))
+                                 lastatmax = timecnt;
                                addtt(ktime, type);
                        }
                }
@@ -2551,6 +2617,8 @@ error(_("can't determine time zone abbreviation to use just after until time"));
                                starttime = tadd(starttime, -gmtoff);
                }
        }
+       if (0 <= lastatmax)
+         attypes[lastatmax].dontmerge = true;
        if (do_extend) {
                /*
                ** If we're extending the explicitly listed observations
@@ -2572,21 +2640,8 @@ error(_("can't determine time zone abbreviation to use just after until time"));
                        if (attypes[i].at > lastat->at)
                                lastat = &attypes[i];
                if (lastat->at < rpytime(&xr, max_year - 1)) {
-                       /*
-                       ** Create new type code for the redundant entry,
-                       ** to prevent it being optimized away.
-                       */
-                       if (typecnt >= TZ_MAX_TYPES) {
-                               error(_("too many local time types"));
-                               exit(EXIT_FAILURE);
-                       }
-                       gmtoffs[typecnt] = gmtoffs[lastat->type];
-                       isdsts[typecnt] = isdsts[lastat->type];
-                       ttisstds[typecnt] = ttisstds[lastat->type];
-                       ttisgmts[typecnt] = ttisgmts[lastat->type];
-                       abbrinds[typecnt] = abbrinds[lastat->type];
-                       ++typecnt;
                        addtt(rpytime(&xr, max_year + 1), typecnt-1);
+                       attypes[timecnt - 1].dontmerge = true;
                }
        }
        writezone(zpfirst->z_name, envvar, version);
@@ -2614,6 +2669,7 @@ addtt(zic_t starttime, int type)
        }
        attypes = growalloc(attypes, sizeof *attypes, timecnt, &timecnt_alloc);
        attypes[timecnt].at = starttime;
+       attypes[timecnt].dontmerge = false;
        attypes[timecnt].type = type;
        ++timecnt;
 }
@@ -2706,28 +2762,48 @@ adjleap(void)
        }
 }
 
+static char *
+shellquote(char *b, char const *s)
+{
+  *b++ = '\'';
+  while (*s) {
+    if (*s == '\'')
+      *b++ = '\'', *b++ = '\\', *b++ = '\'';
+    *b++ = *s++;
+  }
+  *b++ = '\'';
+  return b;
+}
+
 static bool
-yearistype(int year, const char *type)
+yearistype(zic_t year, const char *type)
 {
-       static char *   buf;
-       int             result;
+       char *buf;
+       char *b;
+       int result;
 
        if (type == NULL || *type == '\0')
                return true;
-       buf = erealloc(buf, 132 + strlen(yitcommand) + strlen(type));
-       sprintf(buf, "%s %d %s", yitcommand, year, type);
+       buf = emalloc(1 + 4 * strlen(yitcommand) + 2
+                     + INT_STRLEN_MAXIMUM(zic_t) + 2 + 4 * strlen(type) + 2);
+       b = shellquote(buf, yitcommand);
+       *b++ = ' ';
+       b += sprintf(b, "%"PRIdZIC, year);
+       *b++ = ' ';
+       b = shellquote(b, type);
+       *b = '\0';
        result = system(buf);
-       if (WIFEXITED(result)) switch (WEXITSTATUS(result)) {
-               case 0:
-                       return true;
-               case 1:
-                       return false;
+       if (WIFEXITED(result)) {
+         int status = WEXITSTATUS(result);
+         if (status <= 1) {
+           free(buf);
+           return status == 0;
+         }
        }
        error(_("Wild result from command execution"));
        fprintf(stderr, _("%s: command was '%s', result was %d\n"),
                progname, buf, result);
-       for ( ; ; )
-               exit(EXIT_FAILURE);
+       exit(EXIT_FAILURE);
 }
 
 /* Is A a space character in the C locale?  */
@@ -2855,10 +2931,8 @@ getfields(register char *cp)
                                if (*dp != '\0')
                                        ++dp;
                                else {
-                                       error(_(
-                                               "Odd number of quotation marks"
-                                               ));
-                                       exit(1);
+                                 error(_("Odd number of quotation marks"));
+                                 exit(EXIT_FAILURE);
                                }
                } while (*cp && *cp != '#' && !is_space(*cp));
                if (is_space(*cp))
@@ -3021,44 +3095,45 @@ mp = _("time zone abbreviation differs from POSIX standard");
        charcnt += i;
 }
 
-static bool
-mkdirs(char *argname)
+/* Ensure that the directories of ARGNAME exist, by making any missing
+   ones.  If ANCESTORS, do this only for ARGNAME's ancestors; otherwise,
+   do it for ARGNAME too.  Exit with failure if there is trouble.  */
+static void
+mkdirs(char const *argname, bool ancestors)
 {
        register char * name;
        register char * cp;
 
-       if (argname == NULL || *argname == '\0')
-               return true;
        cp = name = ecpyalloc(argname);
-       while ((cp = strchr(cp + 1, '/')) != 0) {
-               *cp = '\0';
+
+       /* Do not mkdir a root directory, as it must exist.  */
 #ifdef HAVE_DOS_FILE_NAMES
-               /*
-               ** DOS drive specifier?
-               */
-               if (is_alpha(name[0]) && name[1] == ':' && name[2] == '\0') {
-                               *cp = '/';
-                               continue;
-               }
+       if (is_alpha(name[0]) && name[1] == ':')
+         cp += 2;
 #endif
+       while (*cp == '/')
+         cp++;
+
+       while (cp && ((cp = strchr(cp, '/')) || !ancestors)) {
+               if (cp)
+                 *cp = '\0';
                /*
                ** Try to create it.  It's OK if creation fails because
                ** the directory already exists, perhaps because some
-               ** other process just created it.
+               ** other process just created it.  For simplicity do
+               ** not check first whether it already exists, as that
+               ** is checked anyway if the mkdir fails.
                */
                if (mkdir(name, MKDIR_UMASK) != 0) {
                        int err = errno;
-                       if (itsdir(name) <= 0) {
-                               char const *e = strerror(err);
-                               warning(_("%s: Can't create directory"
-                                         " %s: %s"),
-                                       progname, name, e);
-                               free(name);
-                               return false;
+                       if (err != EEXIST && itsdir(name) < 0) {
+                               error(_("%s: Can't create directory %s: %s"),
+                                     progname, name, strerror(err));
+                               exit(EXIT_FAILURE);
                        }
                }
-               *cp = '/';
+               if (cp)
+                 *cp++ = '/';
        }
        free(name);
-       return true;
 }
index 49f0b0b..f48f7a6 100644 (file)
@@ -144,7 +144,8 @@ CU  +2308-08222     America/Havana
 CV     +1455-02331     Atlantic/Cape_Verde
 CW,AW,BQ,SX    +1211-06900     America/Curacao
 CX     -1025+10543     Indian/Christmas
-CY     +3510+03322     Asia/Nicosia
+CY     +3510+03322     Asia/Nicosia    Cyprus (most areas)
+CY     +3507+03357     Asia/Famagusta  Northern Cyprus
 CZ,SK  +5005+01426     Europe/Prague
 DE     +5230+01322     Europe/Berlin   Germany (most areas)
 DK     +5540+01235     Europe/Copenhagen
@@ -224,7 +225,7 @@ MC  +4342+00723     Europe/Monaco
 MD     +4700+02850     Europe/Chisinau
 MH     +0709+17112     Pacific/Majuro  Marshall Islands (most areas)
 MH     +0905+16720     Pacific/Kwajalein       Kwajalein
-MM     +1647+09610     Asia/Rangoon
+MM     +1647+09610     Asia/Yangon
 MN     +4755+10653     Asia/Ulaanbaatar        Mongolia (most areas)
 MN     +4801+09139     Asia/Hovd       Bayan-Ölgii, Govi-Altai, Hovd, Uvs, Zavkhan
 MN     +4804+11430     Asia/Choibalsan Dornod, Sükhbaatar