Module Name:    src
Committed By:   christos
Date:           Fri Oct  7 15:29:42 UTC 2016

Modified Files:
        src/lib/libc/time: Makefile NEWS README Theory localtime.c private.h
            strftime.c tz-art.htm tz-how-to.html tz-link.htm tzfile.5 tzset.3
            zdump.8 zdump.c zic.c

Log Message:
merge tzcode2016g


To generate a diff of this commit:
cvs rdiff -u -r1.33 -r1.34 src/lib/libc/time/Makefile
cvs rdiff -u -r1.16 -r1.17 src/lib/libc/time/NEWS
cvs rdiff -u -r1.10 -r1.11 src/lib/libc/time/README
cvs rdiff -u -r1.20 -r1.21 src/lib/libc/time/Theory
cvs rdiff -u -r1.103 -r1.104 src/lib/libc/time/localtime.c
cvs rdiff -u -r1.45 -r1.46 src/lib/libc/time/private.h
cvs rdiff -u -r1.36 -r1.37 src/lib/libc/time/strftime.c
cvs rdiff -u -r1.13 -r1.14 src/lib/libc/time/tz-art.htm
cvs rdiff -u -r1.1 -r1.2 src/lib/libc/time/tz-how-to.html
cvs rdiff -u -r1.26 -r1.27 src/lib/libc/time/tz-link.htm
cvs rdiff -u -r1.23 -r1.24 src/lib/libc/time/tzfile.5
cvs rdiff -u -r1.34 -r1.35 src/lib/libc/time/tzset.3
cvs rdiff -u -r1.14 -r1.15 src/lib/libc/time/zdump.8
cvs rdiff -u -r1.43 -r1.44 src/lib/libc/time/zdump.c
cvs rdiff -u -r1.62 -r1.63 src/lib/libc/time/zic.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/lib/libc/time/Makefile
diff -u src/lib/libc/time/Makefile:1.33 src/lib/libc/time/Makefile:1.34
--- src/lib/libc/time/Makefile:1.33	Fri Sep 16 13:12:06 2016
+++ src/lib/libc/time/Makefile	Fri Oct  7 11:29:42 2016
@@ -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=	2016g
 
 # Email address for bug reports.
 BUGEMAIL=	t...@iana.org
@@ -241,7 +241,7 @@ GCC_DEBUG_FLAGS = -Dlint -g3 -O3 -fno-co
 CFLAGS=
 
 # Linker flags.  Default to $(LFLAGS) for backwards compatibility
-# to tzcode2012h and earlier.
+# to release 2012h and earlier.
 
 LDFLAGS=	$(LFLAGS)
 
@@ -257,7 +257,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)
 
@@ -273,16 +273,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 = \
@@ -327,7 +327,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 :; \
@@ -357,7 +357,7 @@ HEADERS=	tzfile.h private.h
 NONLIBSRCS=	zic.c zdump.c
 NEWUCBSRCS=	date.c strftime.c
 SOURCES=	$(HEADERS) $(LIBSRCS) $(NONLIBSRCS) $(NEWUCBSRCS) \
-			tzselect.ksh workman.sh
+			tzselect.ksh version workman.sh
 MANS=		newctime.3 newstrftime.3 newtzset.3 time2posix.3 \
 			tzfile.5 tzselect.8 zic.8 zdump.8
 MANTXTS=	newctime.3.txt newstrftime.3.txt newtzset.3.txt \
@@ -379,7 +379,32 @@ DATA=		$(YDATA) $(NDATA) backzone $(TABD
 			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. . .
@@ -409,9 +434,16 @@ INSTALL:	ALL install date.1
 		cp date $(DESTDIR)$(BINDIR)/.
 		cp -f date.1 $(DESTDIR)$(MANDIR)/man1/.
 
-version.h:
+version:	$(VERSION_DEPS)
+		{ V=$$(git describe --match '[0-9][0-9][0-9][0-9][a-z]*' \
+				--abbrev=7 --dirty) || \
+		  V=$(VERSION); } && \
+		printf '%s\n' "$$V" >$@
+
+version.h:	version
 		(echo 'static char const PKGVERSION[]="($(PACKAGE)) ";' && \
-		 echo 'static char const TZVERSION[]="$(VERSION)";' && \
+		 printf 'static char const TZVERSION[]="%s";\n' \
+		   "$$(cat version)" && \
 		 echo 'static char const REPORT_BUGS_TO[]="$(BUGEMAIL)";') >$@
 
 zdump:		$(TZDOBJS)
@@ -478,6 +510,27 @@ 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
+		zones=$$($(AWK) -v wd="$$(pwd)" \
+				'/^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 >$@
+		rm -fr tzs.dir $@.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) $@
@@ -485,19 +538,19 @@ libtz.a:	$(LIBOBJS)
 date:		$(DATEOBJS)
 		$(CC) -o $@ $(CFLAGS) $(LDFLAGS) $(DATEOBJS) $(LDLIBS)
 
-tzselect:	tzselect.ksh
+tzselect:	tzselect.ksh version
 		sed \
 			-e 's|#!/bin/bash|#!$(KSHELL)|g' \
 			-e 's|AWK=[^}]*|AWK=$(AWK)|g' \
 			-e 's|\(PKGVERSION\)=.*|\1='\''($(PACKAGE)) '\''|' \
 			-e 's|\(REPORT_BUGS_TO\)=.*|\1=$(BUGEMAIL)|' \
 			-e 's|TZDIR=[^}]*|TZDIR=$(TZDIR)|' \
-			-e 's|\(TZVERSION\)=.*|\1=$(VERSION)|' \
-			<$? >$@
+			-e 's|\(TZVERSION\)=.*|\1='"$$(cat version)"'|' \
+			<$@.ksh >$@
 		chmod +x $@
 
 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 && \
@@ -533,6 +586,9 @@ check_tables:	checktab.awk $(PRIMARY_YDA
 		    || exit; \
 		done
 
+check_tzs:	$(TZS) $(TZS_NEW)
+		diff -u $(TZS) $(TZS_NEW)
+
 check_web:	$(WEB_PAGES)
 		$(VALIDATE_ENV) $(VALIDATE) $(VALIDATE_FLAGS) $(WEB_PAGES)
 
@@ -540,12 +596,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)
@@ -592,6 +648,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.
@@ -600,12 +658,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.
@@ -617,15 +675,15 @@ check_time_t_alternatives:
 		fi && \
 		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=$$(pwd)/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;; \
@@ -634,16 +692,20 @@ 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 signatures: version
+		$(MAKE) VERSION="$$(cat version)" $@_version
 
-tarballs:	tzcode$(VERSION).tar.gz tzdata$(VERSION).tar.gz
+tarballs_version: tzcode$(VERSION).tar.gz tzdata$(VERSION).tar.gz \
+		tzdb-$(VERSION).tar.lz
 
 tzcode$(VERSION).tar.gz: set-timestamps.out
 		LC_ALL=C && export LC_ALL && \
@@ -656,7 +718,16 @@ tzdata$(VERSION).tar.gz: set-timestamps.
 		tar $(TARFLAGS) -cf - $(COMMON) $(DATA) $(MISC) | \
 		  ${TOOL_GZIP} $(GZIPFLAGS) > $@
 
-signatures:	tzcode$(VERSION).tar.gz.asc tzdata$(VERSION).tar.gz.asc
+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 > $@
+
+signatures_version: tzcode$(VERSION).tar.gz.asc tzdata$(VERSION).tar.gz.asc \
+		tzdb-$(VERSION).tar.lz.asc
 
 tzcode$(VERSION).tar.gz.asc: tzcode$(VERSION).tar.gz
 		gpg --armor --detach-sign $?
@@ -664,6 +735,9 @@ tzcode$(VERSION).tar.gz.asc: tzcode$(VER
 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; \
@@ -689,8 +763,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

Index: src/lib/libc/time/NEWS
diff -u src/lib/libc/time/NEWS:1.16 src/lib/libc/time/NEWS:1.17
--- src/lib/libc/time/NEWS:1.16	Fri Sep 16 13:12:06 2016
+++ src/lib/libc/time/NEWS	Fri Oct  7 11:29:42 2016
@@ -1,5 +1,128 @@
 News for the tz database
 
+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 +516,7 @@ Release 2015d - 2015-04-24 08:09:46 -070
 
   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 +550,12 @@ Release 2015c - 2015-04-11 08:55:55 -070
 
       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 +684,7 @@ Release 2014j - 2014-11-10 17:37:11 -080
 
   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 +720,7 @@ Release 2014i - 2014-10-21 22:04:57 -070
     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 +730,8 @@ Release 2014i - 2014-10-21 22:04:57 -070
     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 +809,7 @@ Release 2014h - 2014-09-25 18:59:03 -070
     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 +842,8 @@ Release 2014g - 2014-08-28 12:31:23 -070
 
   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 +1026,7 @@ Release 2014f - 2014-08-05 17:42:36 -070
     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 +1055,8 @@ Release 2014f - 2014-08-05 17:42:36 -070
     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 +1086,8 @@ Release 2014f - 2014-08-05 17:42:36 -070
     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 +1414,15 @@ Release 2013h - 2013-10-25 15:32:32 -070
 
   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 +1509,7 @@ Release 2013f - 2013-09-24 23:37:36 -070
     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 +1566,7 @@ Release 2013e - 2013-09-19 23:50:04 -070
     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 +2023,7 @@ Release 2012f - 2012-09-12 23:17:03 -070
 
 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 +3642,15 @@ This file contains copies of the part of
 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).

Index: src/lib/libc/time/README
diff -u src/lib/libc/time/README:1.10 src/lib/libc/time/README:1.11
--- src/lib/libc/time/README:1.10	Tue Mar 15 11:16:01 2016
+++ src/lib/libc/time/README	Fri Oct  7 11:29:42 2016
@@ -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,

Index: src/lib/libc/time/Theory
diff -u src/lib/libc/time/Theory:1.20 src/lib/libc/time/Theory:1.21
--- src/lib/libc/time/Theory:1.20	Fri Sep 16 13:12:06 2016
+++ src/lib/libc/time/Theory	Fri Oct  7 11:29:42 2016
@@ -323,7 +323,7 @@ Errors in the tz database arise from man
 
  * 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

Index: src/lib/libc/time/localtime.c
diff -u src/lib/libc/time/localtime.c:1.103 src/lib/libc/time/localtime.c:1.104
--- src/lib/libc/time/localtime.c:1.103	Fri Mar 18 08:41:25 2016
+++ src/lib/libc/time/localtime.c	Fri Oct  7 11:29:42 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: localtime.c,v 1.103 2016/03/18 12:41:25 ginsbach Exp $	*/
+/*	$NetBSD: localtime.c,v 1.104 2016/10/07 15:29:42 christos Exp $	*/
 
 /*
 ** This file is in the public domain, so clarified as of
@@ -10,7 +10,7 @@
 #if 0
 static char	elsieid[] = "@(#)localtime.c	8.17";
 #else
-__RCSID("$NetBSD: localtime.c,v 1.103 2016/03/18 12:41:25 ginsbach Exp $");
+__RCSID("$NetBSD: localtime.c,v 1.104 2016/10/07 15:29:42 christos Exp $");
 #endif
 #endif /* LIBC_SCCS and not lint */
 
@@ -1560,7 +1560,7 @@ gmtsub(struct state const *sp, const tim
 #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.
 	*/
 	if (result)

Index: src/lib/libc/time/private.h
diff -u src/lib/libc/time/private.h:1.45 src/lib/libc/time/private.h:1.46
--- src/lib/libc/time/private.h:1.45	Tue Mar 15 11:16:01 2016
+++ src/lib/libc/time/private.h	Fri Oct  7 11:29:42 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: private.h,v 1.45 2016/03/15 15:16:01 christos Exp $	*/
+/*	$NetBSD: private.h,v 1.46 2016/10/07 15:29:42 christos Exp $	*/
 
 #ifndef PRIVATE_H
 #define PRIVATE_H
@@ -27,6 +27,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"
 
 /*

Index: src/lib/libc/time/strftime.c
diff -u src/lib/libc/time/strftime.c:1.36 src/lib/libc/time/strftime.c:1.37
--- src/lib/libc/time/strftime.c:1.36	Tue Mar 15 11:16:01 2016
+++ src/lib/libc/time/strftime.c	Fri Oct  7 11:29:42 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: strftime.c,v 1.36 2016/03/15 15:16:01 christos Exp $	*/
+/*	$NetBSD: strftime.c,v 1.37 2016/10/07 15:29:42 christos Exp $	*/
 
 /* Convert a broken-down time stamp to a string.  */
 
@@ -35,7 +35,7 @@
 static char	elsieid[] = "@(#)strftime.c	7.64";
 static char	elsieid[] = "@(#)strftime.c	8.3";
 #else
-__RCSID("$NetBSD: strftime.c,v 1.36 2016/03/15 15:16:01 christos Exp $");
+__RCSID("$NetBSD: strftime.c,v 1.37 2016/10/07 15:29:42 christos Exp $");
 #endif
 #endif /* LIBC_SCCS and not lint */
 
@@ -124,15 +124,11 @@ strftime_lz(const timezone_t sp, char *c
 	int	warn;
 
 	warn = IN_NONE;
-	p = _fmt(sp, ((format == NULL) ? "%c" : format), t, s, s + maxsize,
-	    &warn, loc);
+	p = _fmt(sp, format, t, s, s + maxsize, &warn, loc);
 #ifndef NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU
 	if (warn != IN_NONE && getenv(YEAR_2000_NAME) != NULL) {
 		(void) fprintf(stderr, "\n");
-		if (format == NULL)
-			(void) fprintf(stderr, "NULL strftime format ");
-		else	(void) fprintf(stderr, "strftime format \"%s\" ",
-				format);
+		(void) fprintf(stderr, "strftime format \"%s\" ", format);
 		(void) fprintf(stderr, "yields only two digits of years in ");
 		if (warn == IN_SOME)
 			(void) fprintf(stderr, "some locales");

Index: src/lib/libc/time/tz-art.htm
diff -u src/lib/libc/time/tz-art.htm:1.13 src/lib/libc/time/tz-art.htm:1.14
--- src/lib/libc/time/tz-art.htm:1.13	Fri Sep 16 13:12:06 2016
+++ src/lib/libc/time/tz-art.htm	Fri Oct  7 11:29:42 2016
@@ -24,6 +24,184 @@ into problems that programmers have with
 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,215 +432,6 @@ 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>

Index: src/lib/libc/time/tz-how-to.html
diff -u src/lib/libc/time/tz-how-to.html:1.1 src/lib/libc/time/tz-how-to.html:1.2
--- src/lib/libc/time/tz-how-to.html:1.1	Fri Sep 16 13:12:06 2016
+++ src/lib/libc/time/tz-how-to.html	Fri Oct  7 11:29:42 2016
@@ -12,8 +12,7 @@ Database</a> Source Files</h2>
 times of day from the <a href="tz-link.htm">tz database</a>
 source files. It might be helpful, but not absolutely necessary,
 for the reader to have already downloaded the
-<a href="http://www.iana.org/time-zones/repository/tzdata-latest.tar.gz";>latest
-release of the database</a> and become familiar with the basic layout
+latest release of the database and become familiar with the basic layout
 of the data files. The format is explained in the &ldquo;man
 page&rdquo; for the zic compiler, <code>zic.8.txt</code>, in
 the <code>code</code> subdirectory.</p>
@@ -251,7 +250,7 @@ local standard time (different from wall
 daylight saving time); or it can be suffixed with &lsquo;g&rsquo;,
 &lsquo;u&rsquo;, or &lsquo;z&rsquo;, all three of which mean the
 standard time at the
-<a href="https://en.wikipedia.org/wiki/Prime_Meridian";>prime meridan</a>.
+<a href="https://en.wikipedia.org/wiki/Prime_Meridian";>prime meridian</a>.
 &lsquo;g&rsquo; stands for &ldquo;<a
 href="https://en.wikipedia.org/wiki/Greenwich_Mean_Time";>GMT</a>&rdquo;;
 &lsquo;u&rsquo; stands for &ldquo;<a

Index: src/lib/libc/time/tz-link.htm
diff -u src/lib/libc/time/tz-link.htm:1.26 src/lib/libc/time/tz-link.htm:1.27
--- src/lib/libc/time/tz-link.htm:1.26	Fri Sep 16 13:12:06 2016
+++ src/lib/libc/time/tz-link.htm	Fri Oct  7 11:29:42 2016
@@ -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-09-09">
 <meta name="DC.Description"
  content="Sources of information about time zones and daylight saving time">
 <meta name="DC.Identifier"
@@ -42,7 +42,7 @@ This database (often called <code>zonein
 <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">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,47 +103,51 @@ for time stamps after 1960 this is more 
 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
 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
@@ -204,7 +208,7 @@ the Timing of Time Zone Changes</a> give
 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>
@@ -240,15 +244,14 @@ names and shows location maps.</li>
 </ul>
 <h2>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>
+(Internet <abbr>RFC</abbr> 7809).</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,35 +260,12 @@ data; see its VTIMEZONE calendar compone
 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>
 <ul>
@@ -295,7 +275,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
@@ -334,21 +314,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 above) 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 +364,10 @@ Dates. It is freely available under the 
 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>.
@@ -389,16 +393,14 @@ license.</li>
 <h2>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.
@@ -486,8 +488,8 @@ a <a href="https://wordpress.org";>WordPr
 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
@@ -517,7 +519,8 @@ 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>
@@ -588,7 +591,7 @@ common.</li>
 </ul>
 <h2>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 +600,6 @@ is an overall history of <abbr>DST</abbr
 <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>
@@ -656,7 +657,7 @@ hreflang="nl">Legal time in the Netherla
 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>
@@ -689,7 +690,8 @@ title="Network Time Protocol">NTP</abbr>
 Time Protocol</a>
 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 +703,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 +711,7 @@ Times</a> explains more abstruse astrono
 <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 +725,8 @@ code for converting among time scales li
 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 +742,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
@@ -765,7 +760,7 @@ zone names, abbreviations, identifiers, 
 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>.
@@ -809,10 +804,10 @@ practice. For example, in English-speaki
 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,7 +822,7 @@ settings like <code><abbr>TZ</abbr>="Asi
 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>

Index: src/lib/libc/time/tzfile.5
diff -u src/lib/libc/time/tzfile.5:1.23 src/lib/libc/time/tzfile.5:1.24
--- src/lib/libc/time/tzfile.5:1.23	Fri Oct  9 13:21:45 2015
+++ src/lib/libc/time/tzfile.5	Fri Oct  7 11:29:42 2016
@@ -1,8 +1,8 @@
-.\"	$NetBSD: tzfile.5,v 1.23 2015/10/09 17:21:45 christos Exp $
+.\"	$NetBSD: tzfile.5,v 1.24 2016/10/07 15:29:42 christos Exp $
 .\"
 .\" This file is in the public domain, so clarified as of
 .\" 1996-06-05 by Arthur David Olson (arthur_david_ol...@nih.gov).
-.Dd October 6, 2014
+.Dd October 6, 2016
 .Dt TZFILE 5
 .Os
 .Sh NAME
@@ -138,6 +138,13 @@ POSIX-TZ-environment-variable-style stri
 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
+.Dq 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
+.Dq 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: src/lib/libc/time/tzset.3
diff -u src/lib/libc/time/tzset.3:1.34 src/lib/libc/time/tzset.3:1.35
--- src/lib/libc/time/tzset.3:1.34	Thu Oct 29 18:42:55 2015
+++ src/lib/libc/time/tzset.3	Fri Oct  7 11:29:42 2016
@@ -1,5 +1,5 @@
-.\"	$NetBSD: tzset.3,v 1.34 2015/10/29 22:42:55 wiz Exp $
-.Dd October 29, 2015
+.\"	$NetBSD: tzset.3,v 1.35 2016/10/07 15:29:42 christos Exp $
+.Dd October 6, 2016
 .Dt TZSET 3
 .Os
 .Sh NAME
@@ -186,6 +186,14 @@ is missing, then summer time does not ap
 Upper- and lowercase letters are explicitly allowed.
 Any characters except a leading colon (:), digits, comma (,), minus (-),
 plus (+), and NUL bytes are allowed.
+Alternatively, a designation can be surrounded by angle brackets
+.Dv \*[Lt]
+and
+.Dv \*[Gt] ;
+in this case, the designation can contain any characters other than
+.Dv \*[Gt]
+and 
+.Dv NUL .
 .It Cm offset
 Indicates the value one must add to the local time to arrive at
 Coordinated Universal Time.

Index: src/lib/libc/time/zdump.8
diff -u src/lib/libc/time/zdump.8:1.14 src/lib/libc/time/zdump.8:1.15
--- src/lib/libc/time/zdump.8:1.14	Thu Oct 23 14:45:58 2014
+++ src/lib/libc/time/zdump.8	Fri Oct  7 11:29:42 2016
@@ -1,5 +1,5 @@
-.\"	$NetBSD: zdump.8,v 1.14 2014/10/23 18:45:58 christos Exp $
-.Dd October 23, 2014
+.\"	$NetBSD: zdump.8,v 1.15 2016/10/07 15:29:42 christos Exp $
+.Dd October 6, 2016
 .Dt ZDUMP 8
 .Os
 .Sh NAME
@@ -26,7 +26,18 @@ These options are available:
 .Bl -tag -width XXXXXXXXX -compact
 .It Fl \-version
 Output version information and exit.
+.It Fl i
+.Em This option is experimental: its behavior may change in future versions.
+Output a description of time intervals.
+For each
+.Ar zonename
+on the command line, output an interval-format description of the
+zone.
+See
+.Sx "INTERVAL FORMAT"
+below.
 .It Fl v
+Output a verbose description of time intervals.
 For each
 .Ar zonename
 on the command line,
@@ -37,30 +48,30 @@ 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
-.Dl isdst= D
+.Em isdst=D
 where
-.Dl D
+.Em 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
-.Dl gmtoff= N
+.Em gmtoff=N
 if the given local time is known to be
-.D N
+.Em N
 seconds east of Greenwich.
 .It Fl c Ar [loyear,]highyear
-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
-.Dl loyear
+.Em loyear
 of 1970 excludes a transition occurring at 1970-01-01 00:00:00 UTC but a
-.Dl hiyear
+.Em hiyear
 of 1970 includes the transition.
 The default cutoff is
-.Dl \*-500,2500 .
+.Em \&-500,2500 .
 .It Fl t Ar [lotime,]hightime
-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
@@ -76,13 +87,116 @@ except omit the times relative to the ex
 This generates output that is easier to compare to that of
 implementations with different time representations.
 .El
+.Sh "INTERVAL FORMAT"
+.Em 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
+.Dq TZ=string
+where
+.Dv string
+is a double-quoted string giving the zone name, a second line
+.Dq \&- \&- interval
+describing the time interval before the first transition if any, and
+zero or more following lines
+.Dq date time interval
+one line for each transition time and following interval.
+Fields are separated by single tabs.
+.Pp
+Dates are in
+.Dv yyyy-mm-dd
+format and times are in 24-hour
+.Dv hh:mm:ss
+format where
+.Dv hh \*[Lt] 24 .
+Times are in local time immediately after the transition.
+A time interval description consists of a UT offset in signed
+.Dv \&+- 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
+.Dq \&-
+or is
+.Dq 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
+.Sq "CET\es\e"\e\e"
+represents the character sequence
+.Sq CET
+.Pp
+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.)
+.Bd -literal
+TZ="Pacific/Honolulu"
+.Ed
+.Bl -column "XXXX-XX-XX" "HH:MM:SS" "-HH:MM:SS" "TZT" "X" -compact
+.It - Ta - Ta -10:31:26 Ta LMT Ta
+.It 1896-01-13 Ta 12:01:26 Ta -10:30 Ta HST Ta
+.It 1933-04-30 Ta 03 Ta -09:30 Ta HDT Ta 1
+.It 1933-05-21 Ta 11 Ta -10:30 Ta HST Ta
+.It 1942-02-09 Ta 03 Ta -09:30 Ta HDT Ta 1
+.It 1945-09-30 Ta 01 Ta -10:30 Ta HST Ta
+.It 1947-06-08 Ta 02:30 Ta -10 Ta HST Ta
+.El
+.Pp
+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
+Here are excerpts from another example:
+.Bd -literal
+TZ="Europe/Astrakhan"
+.Ed
+.Bl -column "XXXX-XX-XX" "HH:MM:SS" "-HH:MM:SS" "TZT" "X" -compact
+.It - Ta - Ta +03:12:12 Ta LMT Ta
+.It 1924-04-30 Ta 23:47:48 Ta +03 Ta Ta
+.It 1930-06-21 Ta 01 Ta +04 Ta Ta
+.It 1981-04-01 Ta 01 Ta +05 Ta Ta 1
+.It 1981-09-30 Ta 23 Ta +04 Ta Ta
+.It \&... Ta Ta Ta Ta
+.It 2014-10-26 Ta 01 Ta +03 Ta Ta
+.It 2016-03-27 Ta 03 Ta +04 Ta Ta
+.El
+.Pp
+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, 
+In the
+.Fl v
+and
+.Fl V
+output,
 .Dq UT
 denotes the value returned by
 .Xr gmtime 3 ,
@@ -92,8 +206,8 @@ No attempt is currently made to have the
 .Dq UTC
 for newer and
 .Dq UT
-for older time stamps,
-partly because the exact date of the introduction of UTC is problematic.
+for older time stamps, partly because the exact date of the
+introduction of UTC is problematic.
 .Sh SEE ALSO
 .Xr ctime 3 ,
 .Xr tzfile 5 ,

Index: src/lib/libc/time/zdump.c
diff -u src/lib/libc/time/zdump.c:1.43 src/lib/libc/time/zdump.c:1.44
--- src/lib/libc/time/zdump.c:1.43	Tue Mar 15 11:16:01 2016
+++ src/lib/libc/time/zdump.c	Fri Oct  7 11:29:42 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: zdump.c,v 1.43 2016/03/15 15:16:01 christos Exp $	*/
+/*	$NetBSD: zdump.c,v 1.44 2016/10/07 15:29:42 christos Exp $	*/
 /*
 ** This file is in the public domain, so clarified as of
 ** 2009-05-17 by Arthur David Olson.
@@ -6,7 +6,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: zdump.c,v 1.43 2016/03/15 15:16:01 christos Exp $");
+__RCSID("$NetBSD: zdump.c,v 1.44 2016/10/07 15:29:42 christos Exp $");
 #endif /* !defined lint */
 
 /*
@@ -145,6 +145,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 */
@@ -254,8 +274,9 @@ enum { SECSPER400YEARS_FITS = SECSPERLYE
 # 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;
@@ -284,6 +305,8 @@ static intmax_t	delta(struct tm *, struc
 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;
 
@@ -319,6 +342,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
@@ -406,19 +442,13 @@ tzalloc(char const *val)
 
 		while (*e++)
 			continue;
-		env = malloc(sumsize(sizeof *environ,
+		env = xmalloc(sumsize(sizeof *environ,
 		    (e - environ) * sizeof *environ));
-		if (! env) {
-			err(EXIT_FAILURE, "malloc");
-		}
 		to = 1;
 		for (e = environ; (env[to] = *e); e++)
 			to += strncmp(*e, "TZ=", 3) != 0;
 	}
-	env0 = malloc(sumsize(sizeof "TZ=", strlen(val)));
-	if (! env0) {
-		err(EXIT_FAILURE, "malloc");
-	}
+	env0 = xmalloc(sumsize(sizeof "TZ=", strlen(val)));
 	env[0] = strcat(strcpy(env0, "TZ="), val);
 	environ = fakeenv = env;
 	tzset();
@@ -537,10 +567,7 @@ saveabbr(char **buf, size_t *bufalloc, s
 			/* Make the new buffer at least twice as long as the
 			   old, to avoid O(N**2) behavior on repeated calls.  */
 			*bufalloc = sumsize(*bufalloc, ablen + 1);
-			*buf = malloc(*bufalloc);
-			if (! *buf) {
-				err(EXIT_FAILURE, "malloc");
-			}
+			*buf = xmalloc(*bufalloc);
 		}
 		return strcpy(*buf, ab);
 	}
@@ -560,10 +587,18 @@ __dead static void
 usage(FILE *const stream, const int status)
 {
 	(void) 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);
@@ -575,7 +610,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;
 
 	int		i;
 	bool		vflag;
@@ -585,11 +619,7 @@ main(int argc, char *argv[])
 	time_t		cutlotime;
 	time_t		cuthitime;
 	time_t		now;
-	time_t		t;
-	time_t		newt;
-	struct tm	tm;
-	struct tm *	tmp;
-	struct tm *	newtmp;
+	bool iflag = false;
 
 	cutlotime = absolute_min_time;
 	cuthitime = absolute_max_time;
@@ -611,9 +641,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:
@@ -625,7 +656,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;
@@ -682,7 +713,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]);
@@ -693,49 +726,67 @@ 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) {
 			errx(EXIT_FAILURE, "%s", argv[i]);
 		}
-		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);
-		else
+			if (iflag) {
+				showtrans("\nTZ=%f", &tm, t, ab, argv[i]);
+				showtrans("-\t-\t%Q", &tm, t, ab, argv[i]);
+			}
+		} else
 			ab = NULL;
 		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)) {
+			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);
-				if (newtmp)
-					  ab = saveabbr(&abbrev, &abbrevsize,
-							&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 = newtm;
-			tmp = newtmp;
+			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);
@@ -801,12 +852,11 @@ hunt(timezone_t tz, char *name, time_t l
 	char const *		ab;
 	time_t			t;
 	struct tm		lotm;
-	struct tm *	lotmp;
 	struct tm		tm;
-	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);
 	else
 		ab = NULL;
@@ -820,18 +870,17 @@ hunt(timezone_t tz, char *name, time_t l
 			++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;
 }
 
@@ -875,13 +924,20 @@ adjusted_yday(struct tm const *a, struct
 
 /* 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 {
@@ -920,7 +976,7 @@ show(timezone_t tz, char *zone, time_t t
 		if (*abbr(tmp) != '\0')
 			(void) printf(" %s", abbr(tmp));
 		if (v) {
-			long off = gmtoff(tmp, gmtmp);
+			long off = gmtoff(tmp, NULL,  gmtmp);
 			(void) printf(" isdst=%d", tmp->tm_isdst);
 			if (off != LONG_MIN)
 				(void) printf(" gmtoff=%ld", off);
@@ -931,6 +987,204 @@ show(timezone_t tz, char *zone, time_t t
 		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 && (size_t)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
+		   ? (size_t)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 (! (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 const char *
 abbr(struct tm const *tmp)
 {

Index: src/lib/libc/time/zic.c
diff -u src/lib/libc/time/zic.c:1.62 src/lib/libc/time/zic.c:1.63
--- src/lib/libc/time/zic.c:1.62	Tue Sep 20 11:03:07 2016
+++ src/lib/libc/time/zic.c	Fri Oct  7 11:29:42 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: zic.c,v 1.62 2016/09/20 15:03:07 christos Exp $	*/
+/*	$NetBSD: zic.c,v 1.63 2016/10/07 15:29:42 christos Exp $	*/
 /*
 ** This file is in the public domain, so clarified as of
 ** 2006-07-17 by Arthur David Olson.
@@ -10,7 +10,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: zic.c,v 1.62 2016/09/20 15:03:07 christos Exp $");
+__RCSID("$NetBSD: zic.c,v 1.63 2016/10/07 15:29:42 christos Exp $");
 #endif /* !defined lint */
 
 #include "private.h"
@@ -19,6 +19,7 @@ __RCSID("$NetBSD: zic.c,v 1.62 2016/09/2
 
 #include <stdarg.h>
 #include <unistd.h>
+#include <util.h>
 
 #define	ZIC_VERSION_PRE_2013 '2'
 #define	ZIC_VERSION	'3'
@@ -116,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);
@@ -124,7 +127,7 @@ static int	addtype(zic_t, char const *, 
 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);
@@ -138,7 +141,7 @@ static bool	inzsub(char **, int, int);
 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);
@@ -154,7 +157,7 @@ static bool	yearistype(int year, const c
 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.  */
@@ -365,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];
@@ -506,15 +510,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);
   }
 }
@@ -529,10 +533,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;
@@ -565,7 +589,7 @@ main(int argc, char **argv)
 	for (i = 1; i < argc; ++i)
 		if (strcmp(argv[i], "--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) {
 			usage(stdout, EXIT_SUCCESS);
@@ -648,6 +672,7 @@ _("%s: More than one -L option specified
 	if (errors)
 		return EXIT_FAILURE;
 	associate();
+	change_directory(directory);
 	for (i = 0; i < nzones; i = j) {
 		/*
 		** Find the next non-continuation zone entry.
@@ -661,7 +686,7 @@ _("%s: More than one -L option specified
 	*/
 	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,
@@ -670,11 +695,11 @@ _("%s: More than one -L option specified
 	}
 	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;
@@ -751,112 +776,99 @@ namecheck(const char *name)
 	return componentcheck(name, component, cp);
 }
 
-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 = zic_malloc(dir_len + needs_slash + strlen(base) + 1);
-		result[dir_len] = '/';
-		strcpy(result + dir_len + needs_slash, base);
-		return memcpy(result, dir, dir_len);
-	}
-}
-
 static void
-dolink(char const *fromfield, char const *tofield)
+dolink(char const *fromfield, char const *tofield, bool staysymlink)
 {
-	char *	fromname;
-	char *	toname;
 	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) {
+	  const char *s = fromfield;
+	  const char *t;
+	  char *p;
+	  size_t dotdots = 0;
+	  char *symlinkcontents;
+	  int symlink_errno;
+
+	  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_errno = symlink(symlinkcontents, tofield) == 0 ? 0 : errno;
+	  if (symlink_errno == ENOENT && !todirs_made) {
+	    mkdirs(tofield, true);
+	    symlink_errno = symlink(symlinkcontents, 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 = zic_malloc(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(symlinkcontents);
+	  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
@@ -902,21 +914,26 @@ static const zic_t early_time = (WORK_AR
 				 ? 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;
 }
@@ -1090,7 +1107,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"));
 }
@@ -1640,9 +1657,9 @@ writezone(const char *const name, const 
 	int			leapcnt32, leapi32;
 	int			timecnt32, timei32;
 	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;
@@ -1675,8 +1692,9 @@ writezone(const char *const name, const 
 						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;
@@ -1741,27 +1759,31 @@ writezone(const char *const name, const 
 		--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) {
 		int	thistimei, thistimecnt;
@@ -1957,9 +1979,8 @@ writezone(const char *const name, const 
 				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 *
@@ -2303,6 +2324,7 @@ outzone(const struct zone *zpfirst, int 
 	int			compat;
 	bool			do_extend;
 	int			version;
+	int lastatmax = -1;
 
 	max_abbr_len = 2 + max_format_len + max_abbrvar_len;
 	max_envvar_len = 2 * max_abbr_len + 5 * 9;
@@ -2539,6 +2561,10 @@ outzone(const struct zone *zpfirst, int 
 				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);
 			}
 		}
@@ -2571,6 +2597,8 @@ error(_("can't determine time zone abbre
 				starttime = tadd(starttime, -gmtoff);
 		}
 	}
+	if (0 <= lastatmax)
+	  attypes[lastatmax].dontmerge = true;
 	if (do_extend) {
 		/*
 		** If we're extending the explicitly listed observations
@@ -2593,21 +2621,8 @@ error(_("can't determine time zone abbre
 			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);
@@ -2635,6 +2650,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;
 }
@@ -3041,45 +3057,46 @@ mp = _("time zone abbreviation differs f
 	strncpy(&chars[charcnt], string, sizeof(chars) - charcnt - 1);
 	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)
 {
 	char *	name;
 	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;
 }

Reply via email to