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 × 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 & 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> </td></tr> - -<tr><td>TV episode title</td><td>Time Tunnel</td> -<tr><td>TV series</td><td><em>The Adventures of Pete & 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> </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> </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> </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> </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> </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 × 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 “man page” 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 ‘g’, ‘u’, or ‘z’, 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>. ‘g’ stands for “<a href="https://en.wikipedia.org/wiki/Greenwich_Mean_Time">GMT</a>”; ‘u’ stands for “<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 – 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 – 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 – +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 – 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 – 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 – Reference Systems – 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 +– 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 −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; }