Welcome to tzcode 2013e: Changes affecting API The 'zic' command now outputs a dummy transition when far-future data can't be summarized using a TZ string, and uses a 402-year window rather than a 400-year window. For the current data, this affects only the Asia/Tehran file. It does not affect any of the time stamps that this file represents, so zdump outputs the same information as before. (Thanks to Andrew Main (Zefram).) The 'date' command has a new '-r' option, which lets you specify the integer time to display, a la FreeBSD. The 'tzselect' command has two new options '-c' and '-n', which lets you select a zone based on latitude and longitude. The 'zic' command's '-v' option now warns about constructs that require the new version-3 binary file format. (Thanks to Arthur David Olson for the suggestion.) Support for floating-point time_t has been removed. It was always dicey, and POSIX no longer requires it. (Thanks to Eric Blake for suggesting to the POSIX committee to remove it, and thanks to Alan Barrett, Clive D.W. Feather, Andy Heninger, Arthur David Olson, and Alois Treindl, for reporting bugs and elucidating some of the corners of the old floating-point implementation.) The signatures of 'offtime', 'timeoff', and 'gtime' have been changed back to the old practice of using 'long' to represent UT offsets. This had been inadvertently and mistakenly changed to 'int_fast32_t'. (Thanks to Christos Zoulos.) The code avoids undefined behavior on integer overflow in some more places, including gmtime, localtime, mktime and zdump. Changes affecting the zdump utility zdump now outputs "UT" when referring to Universal Time, not "UTC". "UTC" does not make sense for time stamps that predate the introduction of UTC, whereas "UT", a more-generic term, does. (Thanks to Steve Allen for clarifying UT vs UTC.) Data changes affecting behavior of tzselect and similar programs Country code BQ is now called the more-common name "Caribbean Netherlands" rather than the more-official "Bonaire, St Eustatius & Saba". Remove from zone.tab the names America/Montreal, America/Shiprock, and Antarctica/South_Pole, as they are equivalent to existing same-country-code zones for post-1970 time stamps. The data for these names are unchanged, so the names continue to work as before. Changes affecting code internals zic -c now runs way faster on 64-bit hosts when given large numbers. zic now uses vfprintf to avoid allocating and freeing some memory. tzselect now computes the list of continents from the data, rather than have it hard-coded. Minor changes pacify GCC 4.7.3 and GCC 4.8.1. Changes affecting the build procedure The 'leapseconds' file is now generated automatically from a new file 'leap-seconds.list', which is a copy of <ftp://time.nist.gov/pub/leap-seconds.list>. A new source file 'leapseconds.awk' implements this. The goal is simplification of the future maintenance of 'leapseconds'. When building the 'posix' or 'right' subdirectories, if the subdirectory would be a copy of the default subdirectory, it is now made a symbolic link if that is supported. This saves about 2 MB of file system space. The links America/Shiprock and Antarctica/South_Pole have been moved to the 'backward' file. This affects only nondefault builds that omit 'backward'. Changes affecting documentation and commentary Changes to the 'tzfile' man page It now mentions that the binary file format may be extended in future versions by appending data. It now refers to the 'zdump' and 'zic' man pages. Changes to the 'zic' man page It lists conditions that elicit a warning with '-v'. It says that the behavior is unspecified when duplicate names are given, or if the source of one link is the target of another. Its examples are updated to match the latest data. The definition of white space has been clarified slightly. (Thanks to Michael Deckers.) Changes to the 'Theory' file There is a new section about the accuracy of the tz database, describing the many ways that errors can creep in, and explaining why so many of the pre-1970 time stamps are wrong or misleading (thanks to Steve Allen, Lester Caine, and Garrett Wollman for discussions that contributed to this). The 'Theory' file describes LMT better (this follows a suggestion by Guy Harris). It refers to the 2013 edition of POSIX rather than the 2004 edition. It's mentioned that excluding 'backward' should not affect the other data, and it suggests at least one zone.tab name per inhabited country (thanks to Stephen Colebourne). Some longstanding restrictions on names are documented, e.g., 'America/New_York' precludes 'America/New_York/Bronx'. It gives more reasons for the 1970 cutoff. It now mentions which time_t variants are supported, such as signed integer time_t. (Thanks to Paul Goyette for reporting typos in an experimental version of this change.) (Thanks to Philip Newton for correcting typos in these changes.) Documentation and commentary is more careful to distinguish UT in general from UTC in particular. (Thanks to Steve Allen.) Add a better source for the Zurich 1894 transition. (Thanks to Pierre-Yves Berger.) Update shapefile citations in tz-link.htm. (Thanks to Guy Harris.)diff -r1.14 -r1.15 src/lib/libc/time/Makefile
(christos)
--- src/lib/libc/time/Makefile 2013/07/17 20:13:04 1.14
+++ src/lib/libc/time/Makefile 2013/09/20 19:06:54 1.15
@@ -1,67 +1,68 @@ | @@ -1,67 +1,68 @@ | |||
1 | # <pre> | 1 | # <pre> | |
2 | # This file is in the public domain, so clarified as of | 2 | # This file is in the public domain, so clarified as of | |
3 | # 2009-05-17 by Arthur David Olson. | 3 | # 2009-05-17 by Arthur David Olson. | |
4 | 4 | |||
5 | # Package name for the code distribution. | 5 | # Package name for the code distribution. | |
6 | PACKAGE= tzcode | 6 | PACKAGE= tzcode | |
7 | 7 | |||
8 | # Version numbers of the code and data distributions. | 8 | # Version numbers of the code and data distributions. | |
9 | VERSION= 2013d | 9 | VERSION= 2013e | |
10 | 10 | |||
11 | # Email address for bug reports. | 11 | # Email address for bug reports. | |
12 | BUGEMAIL= tz@iana.org | 12 | BUGEMAIL= tz@iana.org | |
13 | 13 | |||
14 | # Change the line below for your time zone (after finding the zone you want in | 14 | # Change the line below for your time zone (after finding the zone you want in | |
15 | # the time zone files, or adding it to a time zone file). | 15 | # the time zone files, or adding it to a time zone file). | |
16 | # Alternately, if you discover you've got the wrong time zone, you can just | 16 | # Alternately, if you discover you've got the wrong time zone, you can just | |
17 | # zic -l rightzone | 17 | # zic -l rightzone | |
18 | # to correct things. | 18 | # to correct things. | |
19 | # Use the command | 19 | # Use the command | |
20 | # make zonenames | 20 | # make zonenames | |
21 | # to get a list of the values you can use for LOCALTIME. | 21 | # to get a list of the values you can use for LOCALTIME. | |
22 | 22 | |||
23 | LOCALTIME= GMT | 23 | LOCALTIME= GMT | |
24 | 24 | |||
25 | # If you want something other than Eastern United States time as a template | 25 | # If you want something other than Eastern United States time as a template | |
26 | # for handling POSIX-style time zone environment variables, | 26 | # for handling POSIX-style time zone environment variables, | |
27 | # change the line below (after finding the zone you want in the | 27 | # change the line below (after finding the zone you want in the | |
28 | # time zone files, or adding it to a time zone file). | 28 | # time zone files, or adding it to a time zone file). | |
29 | # (When a POSIX-style environment variable is handled, the rules in the | 29 | # (When a POSIX-style environment variable is handled, the rules in the | |
30 | # template file are used to determine "spring forward" and "fall back" days and | 30 | # template file are used to determine "spring forward" and "fall back" days and | |
31 | # times; the environment variable itself specifies UTC offsets of standard and | 31 | # times; the environment variable itself specifies UT offsets of standard and | |
32 | # summer time.) | 32 | # summer time.) | |
33 | # Alternately, if you discover you've got the wrong time zone, you can just | 33 | # Alternately, if you discover you've got the wrong time zone, you can just | |
34 | # zic -p rightzone | 34 | # zic -p rightzone | |
35 | # to correct things. | 35 | # to correct things. | |
36 | # Use the command | 36 | # Use the command | |
37 | # make zonenames | 37 | # make zonenames | |
38 | # to get a list of the values you can use for POSIXRULES. | 38 | # to get a list of the values you can use for POSIXRULES. | |
39 | # If you want POSIX compatibility, use "America/New_York". | 39 | # If you want POSIX compatibility, use "America/New_York". | |
40 | 40 | |||
41 | POSIXRULES= America/New_York | 41 | POSIXRULES= America/New_York | |
42 | 42 | |||
43 | # Also see TZDEFRULESTRING below, which takes effect only | 43 | # Also see TZDEFRULESTRING below, which takes effect only | |
44 | # if the time zone files cannot be accessed. | 44 | # if the time zone files cannot be accessed. | |
45 | 45 | |||
46 | # Everything gets put in subdirectories of. . . | 46 | # Everything gets put in subdirectories of. . . | |
47 | 47 | |||
48 | TOPDIR= /usr/local | 48 | TOPDIR= /usr/local | |
49 | 49 | |||
50 | # "Compiled" time zone information is placed in the "TZDIR" directory | 50 | # "Compiled" time zone information is placed in the "TZDIR" directory | |
51 | # (and subdirectories). | 51 | # (and subdirectories). | |
52 | # Use an absolute path name for TZDIR unless you're just testing the software. | 52 | # Use an absolute path name for TZDIR unless you're just testing the software. | |
53 | 53 | |||
54 | TZDIR= $(TOPDIR)/etc/zoneinfo | 54 | TZDIR_BASENAME= zoneinfo | |
55 | TZDIR= $(TOPDIR)/etc/$(TZDIR_BASENAME) | |||
55 | 56 | |||
56 | # Types to try, as an alternative to time_t. int64_t should be first. | 57 | # Types to try, as an alternative to time_t. int64_t should be first. | |
57 | TIME_T_ALTERNATIVES= int64_t int32_t uint32_t uint64_t | 58 | TIME_T_ALTERNATIVES= int64_t int32_t uint32_t uint64_t | |
58 | 59 | |||
59 | # The "tzselect", "zic", and "zdump" commands get installed in. . . | 60 | # The "tzselect", "zic", and "zdump" commands get installed in. . . | |
60 | 61 | |||
61 | ETCDIR= $(TOPDIR)/etc | 62 | ETCDIR= $(TOPDIR)/etc | |
62 | 63 | |||
63 | # If you "make INSTALL", the "date" command gets installed in. . . | 64 | # If you "make INSTALL", the "date" command gets installed in. . . | |
64 | 65 | |||
65 | BINDIR= $(TOPDIR)/bin | 66 | BINDIR= $(TOPDIR)/bin | |
66 | 67 | |||
67 | # Manual pages go in subdirectories of. . . | 68 | # Manual pages go in subdirectories of. . . | |
@@ -110,27 +111,26 @@ LDLIBS= | @@ -110,27 +111,26 @@ LDLIBS= | |||
110 | # -DHAVE_SETTIMEOFDAY=1 if settimeofday has just 1 arg (SVR4) | 111 | # -DHAVE_SETTIMEOFDAY=1 if settimeofday has just 1 arg (SVR4) | |
111 | # -DHAVE_SETTIMEOFDAY=2 if settimeofday uses 2nd arg (4.3BSD) | 112 | # -DHAVE_SETTIMEOFDAY=2 if settimeofday uses 2nd arg (4.3BSD) | |
112 | # -DHAVE_SETTIMEOFDAY=3 if settimeofday ignores 2nd arg (4.4BSD) | 113 | # -DHAVE_SETTIMEOFDAY=3 if settimeofday ignores 2nd arg (4.4BSD) | |
113 | # -DHAVE_STDINT_H=1 if you have a pre-C99 compiler with "stdint.h" | 114 | # -DHAVE_STDINT_H=1 if you have a pre-C99 compiler with "stdint.h" | |
114 | # -DHAVE_SYMLINK=0 if your system lacks the symlink function | 115 | # -DHAVE_SYMLINK=0 if your system lacks the symlink function | |
115 | # -DHAVE_SYS_STAT_H=0 if your compiler lacks a "sys/stat.h" | 116 | # -DHAVE_SYS_STAT_H=0 if your compiler lacks a "sys/stat.h" | |
116 | # -DHAVE_SYS_WAIT_H=0 if your compiler lacks a "sys/wait.h" | 117 | # -DHAVE_SYS_WAIT_H=0 if your compiler lacks a "sys/wait.h" | |
117 | # -DHAVE_UNISTD_H=0 if your compiler lacks a "unistd.h" (Microsoft C++ 7?) | 118 | # -DHAVE_UNISTD_H=0 if your compiler lacks a "unistd.h" (Microsoft C++ 7?) | |
118 | # -DHAVE_UTMPX_H=1 if your compiler has a "utmpx.h" | 119 | # -DHAVE_UTMPX_H=1 if your compiler has a "utmpx.h" | |
119 | # -DLOCALE_HOME=\"path\" if locales are in "path", not "/usr/lib/locale" | 120 | # -DLOCALE_HOME=\"path\" if locales are in "path", not "/usr/lib/locale" | |
120 | # -DNO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU=1 | 121 | # -DNO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU=1 | |
121 | # if you do not want run time warnings about formats that may cause | 122 | # if you do not want run time warnings about formats that may cause | |
122 | # year 2000 grief | 123 | # year 2000 grief | |
123 | # -DTIME_T_FLOATING=1 if your time_t (or time_tz) is floating point | |||
124 | # -Dtime_tz=\"T\" to use T as the time_t type, rather than the system time_t | 124 | # -Dtime_tz=\"T\" to use T as the time_t type, rather than the system time_t | |
125 | # -DTZ_DOMAIN=\"foo\" to use "foo" for gettext domain name; default is "tz" | 125 | # -DTZ_DOMAIN=\"foo\" to use "foo" for gettext domain name; default is "tz" | |
126 | # -TTZ_DOMAINDIR=\"/path\" to use "/path" for gettext directory; | 126 | # -TTZ_DOMAINDIR=\"/path\" to use "/path" for gettext directory; | |
127 | # the default is system-supplied, typically "/usr/lib/locale" | 127 | # the default is system-supplied, typically "/usr/lib/locale" | |
128 | # -DTZDEFRULESTRING=\",date/time,date/time\" to default to the specified | 128 | # -DTZDEFRULESTRING=\",date/time,date/time\" to default to the specified | |
129 | # -DNO_ERROR_IN_DST_GAP=1 | 129 | # -DNO_ERROR_IN_DST_GAP=1 | |
130 | # if you want mktime() not to return an error in the DST gap. | 130 | # if you want mktime() not to return an error in the DST gap. | |
131 | # -DZIC_MAX_ABBR_LEN_WO_WARN=3 | 131 | # -DZIC_MAX_ABBR_LEN_WO_WARN=3 | |
132 | # (or some other number) to set the maximum time zone abbreviation length | 132 | # (or some other number) to set the maximum time zone abbreviation length | |
133 | # that zic will accept without a warning (the default is 6) | 133 | # that zic will accept without a warning (the default is 6) | |
134 | # $(GCC_DEBUG_FLAGS) if you are using GCC and want lots of checking | 134 | # $(GCC_DEBUG_FLAGS) if you are using GCC and want lots of checking | |
135 | GCC_DEBUG_FLAGS = -Dlint -g3 -O3 -fno-common -fstrict-aliasing \ | 135 | GCC_DEBUG_FLAGS = -Dlint -g3 -O3 -fno-common -fstrict-aliasing \ | |
136 | -Wall -Wextra \ | 136 | -Wall -Wextra \ | |
@@ -178,27 +178,27 @@ GCC_DEBUG_FLAGS = -Dlint -g3 -O3 -fno-co | @@ -178,27 +178,27 @@ GCC_DEBUG_FLAGS = -Dlint -g3 -O3 -fno-co | |||
178 | # If you want functions that were inspired by early versions of X3J11's work, | 178 | # If you want functions that were inspired by early versions of X3J11's work, | |
179 | # add | 179 | # add | |
180 | # -DSTD_INSPIRED | 180 | # -DSTD_INSPIRED | |
181 | # to the end of the "CFLAGS=" line. This arranges for the functions | 181 | # to the end of the "CFLAGS=" line. This arranges for the functions | |
182 | # "tzsetwall", "offtime", "timelocal", "timegm", "timeoff", | 182 | # "tzsetwall", "offtime", "timelocal", "timegm", "timeoff", | |
183 | # "posix2time", and "time2posix" to be added to the time conversion library. | 183 | # "posix2time", and "time2posix" to be added to the time conversion library. | |
184 | # "tzsetwall" is like "tzset" except that it arranges for local wall clock | 184 | # "tzsetwall" is like "tzset" except that it arranges for local wall clock | |
185 | # time (rather than the time specified in the TZ environment variable) | 185 | # time (rather than the time specified in the TZ environment variable) | |
186 | # to be used. | 186 | # to be used. | |
187 | # "offtime" is like "gmtime" except that it accepts a second (long) argument | 187 | # "offtime" is like "gmtime" except that it accepts a second (long) argument | |
188 | # that gives an offset to add to the time_t when converting it. | 188 | # that gives an offset to add to the time_t when converting it. | |
189 | # "timelocal" is equivalent to "mktime". | 189 | # "timelocal" is equivalent to "mktime". | |
190 | # "timegm" is like "timelocal" except that it turns a struct tm into | 190 | # "timegm" is like "timelocal" except that it turns a struct tm into | |
191 | # a time_t using UTC (rather than local time as "timelocal" does). | 191 | # a time_t using UT (rather than local time as "timelocal" does). | |
192 | # "timeoff" is like "timegm" except that it accepts a second (long) argument | 192 | # "timeoff" is like "timegm" except that it accepts a second (long) argument | |
193 | # that gives an offset to use when converting to a time_t. | 193 | # that gives an offset to use when converting to a time_t. | |
194 | # "posix2time" and "time2posix" are described in an included manual page. | 194 | # "posix2time" and "time2posix" are described in an included manual page. | |
195 | # X3J11's work does not describe any of these functions. | 195 | # X3J11's work does not describe any of these functions. | |
196 | # Sun has provided "tzsetwall", "timelocal", and "timegm" in SunOS 4.0. | 196 | # Sun has provided "tzsetwall", "timelocal", and "timegm" in SunOS 4.0. | |
197 | # These functions may well disappear in future releases of the time | 197 | # These functions may well disappear in future releases of the time | |
198 | # conversion package. | 198 | # conversion package. | |
199 | # | 199 | # | |
200 | # If you'll never want to handle solar-time-based time zones, add | 200 | # If you'll never want to handle solar-time-based time zones, add | |
201 | # -DNOSOLAR | 201 | # -DNOSOLAR | |
202 | # to the end of the "CFLAGS=" line | 202 | # to the end of the "CFLAGS=" line | |
203 | # (and comment out the "SDATA=" line below). | 203 | # (and comment out the "SDATA=" line below). | |
204 | # This reduces (slightly) the run-time data-space requirements of | 204 | # This reduces (slightly) the run-time data-space requirements of | |
@@ -232,26 +232,28 @@ GCC_DEBUG_FLAGS = -Dlint -g3 -O3 -fno-co | @@ -232,26 +232,28 @@ GCC_DEBUG_FLAGS = -Dlint -g3 -O3 -fno-co | |||
232 | # before the first Monday in January when a "%V" format is used and January 1 | 232 | # before the first Monday in January when a "%V" format is used and January 1 | |
233 | # falls on a Friday, Saturday, or Sunday. | 233 | # falls on a Friday, Saturday, or Sunday. | |
234 | 234 | |||
235 | CFLAGS= | 235 | CFLAGS= | |
236 | 236 | |||
237 | # Linker flags. Default to $(LFLAGS) for backwards compatibility | 237 | # Linker flags. Default to $(LFLAGS) for backwards compatibility | |
238 | # to tzcode2012h and earlier. | 238 | # to tzcode2012h and earlier. | |
239 | 239 | |||
240 | LDFLAGS= $(LFLAGS) | 240 | LDFLAGS= $(LFLAGS) | |
241 | 241 | |||
242 | zic= ./zic | 242 | zic= ./zic | |
243 | ZIC= $(zic) $(ZFLAGS) | 243 | ZIC= $(zic) $(ZFLAGS) | |
244 | 244 | |||
245 | ZFLAGS= | |||
246 | ||||
245 | # The name of a Posix-compliant `awk' on your system. | 247 | # The name of a Posix-compliant `awk' on your system. | |
246 | AWK= awk | 248 | AWK= awk | |
247 | 249 | |||
248 | # The full path name of a Posix-compliant shell that supports the Korn shell's | 250 | # The full path name of a Posix-compliant shell that supports the Korn shell's | |
249 | # 'select' statement, as an extension. These days, Bash is the most popular. | 251 | # 'select' statement, as an extension. These days, Bash is the most popular. | |
250 | KSHELL= /bin/bash | 252 | KSHELL= /bin/bash | |
251 | 253 | |||
252 | # The path where SGML DTDs are kept. | 254 | # The path where SGML DTDs are kept. | |
253 | # The default is appropriate for Ubuntu 12.10. | 255 | # The default is appropriate for Ubuntu 12.10. | |
254 | SGML_TOPDIR= /usr | 256 | SGML_TOPDIR= /usr | |
255 | SGML_DTDDIR= $(SGML_TOPDIR)/share/xml/w3c-sgml-lib/schema/dtd | 257 | SGML_DTDDIR= $(SGML_TOPDIR)/share/xml/w3c-sgml-lib/schema/dtd | |
256 | SGML_SEARCH_PATH= $(SGML_DTDDIR)/REC-html401-19991224 | 258 | SGML_SEARCH_PATH= $(SGML_DTDDIR)/REC-html401-19991224 | |
257 | 259 | |||
@@ -309,111 +311,128 @@ NONLIBSRCS= zic.c zdump.c scheck.c iallo | @@ -309,111 +311,128 @@ NONLIBSRCS= zic.c zdump.c scheck.c iallo | |||
309 | NEWUCBSRCS= date.c strftime.c | 311 | NEWUCBSRCS= date.c strftime.c | |
310 | SOURCES= $(HEADERS) $(LIBSRCS) $(NONLIBSRCS) $(NEWUCBSRCS) tzselect.ksh | 312 | SOURCES= $(HEADERS) $(LIBSRCS) $(NONLIBSRCS) $(NEWUCBSRCS) tzselect.ksh | |
311 | MANS= newctime.3 newstrftime.3 newtzset.3 time2posix.3 \ | 313 | MANS= newctime.3 newstrftime.3 newtzset.3 time2posix.3 \ | |
312 | tzfile.5 tzselect.8 zic.8 zdump.8 | 314 | tzfile.5 tzselect.8 zic.8 zdump.8 | |
313 | COMMON= Makefile | 315 | COMMON= Makefile | |
314 | DOCS= README Theory $(MANS) date.1 | 316 | DOCS= README Theory $(MANS) date.1 | |
315 | PRIMARY_YDATA= africa antarctica asia australasia \ | 317 | PRIMARY_YDATA= africa antarctica asia australasia \ | |
316 | europe northamerica southamerica | 318 | europe northamerica southamerica | |
317 | YDATA= $(PRIMARY_YDATA) pacificnew etcetera backward | 319 | YDATA= $(PRIMARY_YDATA) pacificnew etcetera backward | |
318 | NDATA= systemv factory | 320 | NDATA= systemv factory | |
319 | SDATA= solar87 solar88 solar89 | 321 | SDATA= solar87 solar88 solar89 | |
320 | TDATA= $(YDATA) $(NDATA) $(SDATA) | 322 | TDATA= $(YDATA) $(NDATA) $(SDATA) | |
321 | TABDATA= iso3166.tab zone.tab | 323 | TABDATA= iso3166.tab zone.tab | |
322 | DATA= $(YDATA) $(NDATA) $(SDATA) $(TABDATA) leapseconds yearistype.sh | 324 | DATA= $(YDATA) $(NDATA) $(SDATA) $(TABDATA) \ | |
325 | leap-seconds.list yearistype.sh | |||
323 | WEB_PAGES= tz-art.htm tz-link.htm | 326 | WEB_PAGES= tz-art.htm tz-link.htm | |
327 | AWK_SCRIPTS= checktab.awk leapseconds.awk | |||
324 | MISC= usno1988 usno1989 usno1989a usno1995 usno1997 usno1998 \ | 328 | MISC= usno1988 usno1989 usno1989a usno1995 usno1997 usno1998 \ | |
325 | $(WEB_PAGES) checktab.awk workman.sh \ | 329 | $(WEB_PAGES) $(AWK_SCRIPTS) workman.sh \ | |
326 | zoneinfo2tdf.pl | 330 | zoneinfo2tdf.pl | |
327 | ENCHILADA= $(COMMON) $(DOCS) $(SOURCES) $(DATA) $(MISC) | 331 | ENCHILADA= $(COMMON) $(DOCS) $(SOURCES) $(DATA) $(MISC) | |
328 | 332 | |||
329 | # And for the benefit of csh users on systems that assume the user | 333 | # And for the benefit of csh users on systems that assume the user | |
330 | # shell should be used to handle commands in Makefiles. . . | 334 | # shell should be used to handle commands in Makefiles. . . | |
331 | 335 | |||
332 | SHELL= /bin/sh | 336 | SHELL= /bin/sh | |
333 | 337 | |||
334 | all: tzselect zic zdump $(LIBOBJS) | 338 | all: tzselect zic zdump $(LIBOBJS) $(TABDATA) | |
335 | 339 | |||
336 | ALL: all date | 340 | ALL: all date | |
337 | 341 | |||
338 | install: all $(DATA) $(REDO) $(TZLIB) $(MANS) $(TABDATA) | 342 | install: all $(DATA) $(REDO) $(DESTDIR)$(TZLIB) $(MANS) | |
339 | $(ZIC) -y $(YEARISTYPE) \ | 343 | $(ZIC) -y $(YEARISTYPE) \ | |
340 | -d $(TZDIR) -l $(LOCALTIME) -p $(POSIXRULES) | 344 | -d $(DESTDIR)$(TZDIR) -l $(LOCALTIME) -p $(POSIXRULES) | |
341 | -rm -f $(TZDIR)/iso3166.tab $(TZDIR)/zone.tab | 345 | -rm -f $(DESTDIR)$(TZDIR)/iso3166.tab \ | |
342 | cp iso3166.tab zone.tab $(TZDIR)/. | 346 | $(DESTDIR)$(TZDIR)/zone.tab | |
343 | -mkdir $(TOPDIR) $(ETCDIR) | 347 | cp iso3166.tab zone.tab $(DESTDIR)$(TZDIR)/. | |
344 | cp tzselect zic zdump $(ETCDIR)/. | 348 | -mkdir $(DESTDIR)$(TOPDIR) $(DESTDIR)$(ETCDIR) | |
345 | -mkdir $(TOPDIR) $(MANDIR) \ | 349 | cp tzselect zic zdump $(DESTDIR)$(ETCDIR)/. | |
346 | $(MANDIR)/man3 $(MANDIR)/man5 $(MANDIR)/man8 | 350 | -mkdir $(DESTDIR)$(TOPDIR) $(DESTDIR)$(MANDIR) \ | |
347 | -rm -f $(MANDIR)/man3/newctime.3 \ | 351 | $(DESTDIR)$(MANDIR)/man3 $(DESTDIR)$(MANDIR)/man5 \ | |
348 | $(MANDIR)/man3/newtzset.3 \ | 352 | $(DESTDIR)$(MANDIR)/man8 | |
349 | $(MANDIR)/man5/tzfile.5 \ | 353 | -rm -f $(DESTDIR)$(MANDIR)/man3/newctime.3 \ | |
350 | $(MANDIR)/man8/tzselect.8 \ | 354 | $(DESTDIR)$(MANDIR)/man3/newtzset.3 \ | |
351 | $(MANDIR)/man8/zdump.8 \ | 355 | $(DESTDIR)$(MANDIR)/man5/tzfile.5 \ | |
352 | $(MANDIR)/man8/zic.8 | 356 | $(DESTDIR)$(MANDIR)/man8/tzselect.8 \ | |
353 | cp newctime.3 newtzset.3 $(MANDIR)/man3/. | 357 | $(DESTDIR)$(MANDIR)/man8/zdump.8 \ | |
354 | cp tzfile.5 $(MANDIR)/man5/. | 358 | $(DESTDIR)$(MANDIR)/man8/zic.8 | |
355 | cp tzselect.8 zdump.8 zic.8 $(MANDIR)/man8/. | 359 | cp newctime.3 newtzset.3 $(DESTDIR)$(MANDIR)/man3/. | |
360 | cp tzfile.5 $(DESTDIR)$(MANDIR)/man5/. | |||
361 | cp tzselect.8 zdump.8 zic.8 $(DESTDIR)$(MANDIR)/man8/. | |||
356 | 362 | |||
357 | INSTALL: ALL install date.1 | 363 | INSTALL: ALL install date.1 | |
358 | -mkdir $(TOPDIR) $(BINDIR) | 364 | -mkdir $(DESTDIR)$(TOPDIR) $(DESTDIR)$(BINDIR) | |
359 | cp date $(BINDIR)/. | 365 | cp date $(DESTDIR)$(BINDIR)/. | |
360 | -mkdir $(TOPDIR) $(MANDIR) $(MANDIR)/man1 | 366 | -mkdir $(DESTDIR)$(TOPDIR) $(DESTDIR)$(MANDIR) \ | |
361 | -rm -f $(MANDIR)/man1/date.1 | 367 | $(DESTDIR)$(MANDIR)/man1 | |
362 | cp date.1 $(MANDIR)/man1/. | 368 | -rm -f $(DESTDIR)$(MANDIR)/man1/date.1 | |
369 | cp date.1 $(DESTDIR)$(MANDIR)/man1/. | |||
363 | 370 | |||
364 | version.h: | 371 | version.h: | |
365 | (echo 'static char const PKGVERSION[]="($(PACKAGE)) ";' && \ | 372 | (echo 'static char const PKGVERSION[]="($(PACKAGE)) ";' && \ | |
366 | echo 'static char const TZVERSION[]="$(VERSION)";' && \ | 373 | echo 'static char const TZVERSION[]="$(VERSION)";' && \ | |
367 | echo 'static char const REPORT_BUGS_TO[]="$(BUGEMAIL)";') >$@ | 374 | echo 'static char const REPORT_BUGS_TO[]="$(BUGEMAIL)";') >$@ | |
368 | 375 | |||
369 | zdump: $(TZDOBJS) | 376 | zdump: $(TZDOBJS) | |
370 | $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $(TZDOBJS) $(LDLIBS) | 377 | $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $(TZDOBJS) $(LDLIBS) | |
371 | 378 | |||
372 | zic: $(TZCOBJS) yearistype | 379 | zic: $(TZCOBJS) yearistype | |
373 | $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $(TZCOBJS) $(LDLIBS) | 380 | $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $(TZCOBJS) $(LDLIBS) | |
374 | 381 | |||
375 | yearistype: yearistype.sh | 382 | yearistype: yearistype.sh | |
376 | cp yearistype.sh yearistype | 383 | cp yearistype.sh yearistype | |
377 | chmod +x yearistype | 384 | chmod +x yearistype | |
378 | 385 | |||
386 | leapseconds: leapseconds.awk leap-seconds.list | |||
387 | $(AWK) -f leapseconds.awk leap-seconds.list >$@ | |||
388 | ||||
379 | posix_only: zic $(TDATA) | 389 | posix_only: zic $(TDATA) | |
380 | $(ZIC) -y $(YEARISTYPE) -d $(TZDIR) -L /dev/null $(TDATA) | 390 | $(ZIC) -y $(YEARISTYPE) -d $(DESTDIR)$(TZDIR) \ | |
391 | -L /dev/null $(TDATA) | |||
381 | 392 | |||
382 | right_only: zic leapseconds $(TDATA) | 393 | right_only: zic leapseconds $(TDATA) | |
383 | $(ZIC) -y $(YEARISTYPE) -d $(TZDIR) -L leapseconds $(TDATA) | 394 | $(ZIC) -y $(YEARISTYPE) -d $(DESTDIR)$(TZDIR) \ | |
395 | -L leapseconds $(TDATA) | |||
384 | 396 | |||
385 | # In earlier versions of this makefile, the other two directories were | 397 | # In earlier versions of this makefile, the other two directories were | |
386 | # subdirectories of $(TZDIR). However, this led to configuration errors. | 398 | # subdirectories of $(TZDIR). However, this led to configuration errors. | |
387 | # For example, with posix_right under the earlier scheme, | 399 | # For example, with posix_right under the earlier scheme, | |
388 | # TZ='right/Australia/Adelaide' got you localtime with leap seconds, | 400 | # TZ='right/Australia/Adelaide' got you localtime with leap seconds, | |
389 | # but gmtime without leap seconds, which led to problems with applications | 401 | # but gmtime without leap seconds, which led to problems with applications | |
390 | # like sendmail that subtract gmtime from localtime. | 402 | # like sendmail that subtract gmtime from localtime. | |
391 | # Therefore, the other two directories are now siblings of $(TZDIR). | 403 | # Therefore, the other two directories are now siblings of $(TZDIR). | |
392 | # You must replace all of $(TZDIR) to switch from not using leap seconds | 404 | # You must replace all of $(TZDIR) to switch from not using leap seconds | |
393 | # to using them, or vice versa. | 405 | # to using them, or vice versa. | |
394 | other_two: zic leapseconds $(TDATA) | 406 | right_posix: right_only leapseconds | |
395 | $(ZIC) -y $(YEARISTYPE) -d $(TZDIR)-posix -L /dev/null $(TDATA) | 407 | rm -fr $(DESTDIR)$(TZDIR)-leaps | |
396 | $(ZIC) -y $(YEARISTYPE) \ | 408 | ln -s $(TZDIR_BASENAME) $(DESTDIR)$(TZDIR)-leaps || \ | |
397 | -d $(TZDIR)-leaps -L leapseconds $(TDATA) | 409 | $(ZIC) -y $(YEARISTYPE) -d $(DESTDIR)$(TZDIR)-leaps \ | |
398 | 410 | -L leapseconds $(TDATA) | ||
399 | posix_right: posix_only other_two | 411 | $(ZIC) -y $(YEARISTYPE) -d $(DESTDIR)$(TZDIR)-posix \ | |
400 | 412 | -L /dev/null $(TDATA) | ||
401 | right_posix: right_only other_two | 413 | ||
414 | posix_right: posix_only leapseconds | |||
415 | rm -fr $(DESTDIR)$(TZDIR)-posix | |||
416 | ln -s $(TZDIR_BASENAME) $(DESTDIR)$(TZDIR)-posix || \ | |||
417 | $(ZIC) -y $(YEARISTYPE) -d $(DESTDIR)$(TZDIR)-posix \ | |||
418 | -L /dev/null $(TDATA) | |||
419 | $(ZIC) -y $(YEARISTYPE) -d $(DESTDIR)$(TZDIR)-leaps \ | |||
420 | -L leapseconds $(TDATA) | |||
402 | 421 | |||
403 | zones: $(REDO) | 422 | zones: $(REDO) | |
404 | 423 | |||
405 | $(TZLIB): $(LIBOBJS) | 424 | $(DESTDIR)$(TZLIB): $(LIBOBJS) | |
406 | -mkdir $(TOPDIR) $(LIBDIR) | 425 | -mkdir -p $(DESTDIR)$(TOPDIR) $(DESTDIR)$(LIBDIR) | |
407 | ar ru $@ $(LIBOBJS) | 426 | ar ru $@ $(LIBOBJS) | |
408 | if [ -x /usr/ucb/ranlib ] || [ -x /usr/bin/ranlib ]; \ | 427 | if [ -x /usr/ucb/ranlib ] || [ -x /usr/bin/ranlib ]; \ | |
409 | then ranlib $@ ; fi | 428 | then ranlib $@ ; fi | |
410 | 429 | |||
411 | date: $(DATEOBJS) | 430 | date: $(DATEOBJS) | |
412 | $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $(DATEOBJS) $(LDLIBS) | 431 | $(CC) -o $@ $(CFLAGS) $(LDFLAGS) $(DATEOBJS) $(LDLIBS) | |
413 | 432 | |||
414 | tzselect: tzselect.ksh | 433 | tzselect: tzselect.ksh | |
415 | sed \ | 434 | sed \ | |
416 | -e 's|#!/bin/bash|#!$(KSHELL)|g' \ | 435 | -e 's|#!/bin/bash|#!$(KSHELL)|g' \ | |
417 | -e 's|AWK=[^}]*|AWK=$(AWK)|g' \ | 436 | -e 's|AWK=[^}]*|AWK=$(AWK)|g' \ | |
418 | -e 's|\(PKGVERSION\)=.*|\1='\''($(PACKAGE)) '\''|' \ | 437 | -e 's|\(PKGVERSION\)=.*|\1='\''($(PACKAGE)) '\''|' \ | |
419 | -e 's|\(REPORT_BUGS_TO\)=.*|\1=$(BUGEMAIL)|' \ | 438 | -e 's|\(REPORT_BUGS_TO\)=.*|\1=$(BUGEMAIL)|' \ | |
@@ -425,27 +444,27 @@ tzselect: tzselect.ksh | @@ -425,27 +444,27 @@ tzselect: tzselect.ksh | |||
425 | check: check_character_set check_tables check_web | 444 | check: check_character_set check_tables check_web | |
426 | 445 | |||
427 | check_character_set: $(ENCHILADA) | 446 | check_character_set: $(ENCHILADA) | |
428 | sharp='#'; ! grep -n $(INVALID_CHAR) $(ENCHILADA) | 447 | sharp='#'; ! grep -n $(INVALID_CHAR) $(ENCHILADA) | |
429 | 448 | |||
430 | check_tables: checktab.awk $(PRIMARY_YDATA) | 449 | check_tables: checktab.awk $(PRIMARY_YDATA) | |
431 | $(AWK) -f checktab.awk $(PRIMARY_YDATA) | 450 | $(AWK) -f checktab.awk $(PRIMARY_YDATA) | |
432 | 451 | |||
433 | check_web: $(WEB_PAGES) | 452 | check_web: $(WEB_PAGES) | |
434 | $(VALIDATE_ENV) $(VALIDATE) $(VALIDATE_FLAGS) $(WEB_PAGES) | 453 | $(VALIDATE_ENV) $(VALIDATE) $(VALIDATE_FLAGS) $(WEB_PAGES) | |
435 | 454 | |||
436 | clean_misc: | 455 | clean_misc: | |
437 | rm -f core *.o *.out \ | 456 | rm -f core *.o *.out \ | |
438 | date tzselect version.h zdump zic yearistype | 457 | date leapseconds tzselect version.h zdump zic yearistype | |
439 | clean: clean_misc | 458 | clean: clean_misc | |
440 | rm -f -r tzpublic | 459 | rm -f -r tzpublic | |
441 | 460 | |||
442 | maintainer-clean: clean | 461 | maintainer-clean: clean | |
443 | @echo 'This command is intended for maintainers to use; it' | 462 | @echo 'This command is intended for maintainers to use; it' | |
444 | @echo 'deletes files that may need special tools to rebuild.' | 463 | @echo 'deletes files that may need special tools to rebuild.' | |
445 | rm -f *.[1-8].txt *.asc *.tar.gz | 464 | rm -f *.[1-8].txt *.asc *.tar.gz | |
446 | 465 | |||
447 | names: | 466 | names: | |
448 | @echo $(ENCHILADA) | 467 | @echo $(ENCHILADA) | |
449 | 468 | |||
450 | public: check check_public check_time_t_alternatives \ | 469 | public: check check_public check_time_t_alternatives \ | |
451 | set-timestamps tarballs signatures | 470 | set-timestamps tarballs signatures | |
@@ -525,27 +544,27 @@ tzdata$(VERSION).tar.gz: $(COMMON) $(DAT | @@ -525,27 +544,27 @@ tzdata$(VERSION).tar.gz: $(COMMON) $(DAT | |||
525 | tar $(TARFLAGS) -cf - $(COMMON) $(DATA) | \ | 544 | tar $(TARFLAGS) -cf - $(COMMON) $(DATA) | \ | |
526 | gzip $(GZIPFLAGS) > $@ | 545 | gzip $(GZIPFLAGS) > $@ | |
527 | 546 | |||
528 | signatures: tzcode$(VERSION).tar.gz.asc tzdata$(VERSION).tar.gz.asc | 547 | signatures: tzcode$(VERSION).tar.gz.asc tzdata$(VERSION).tar.gz.asc | |
529 | 548 | |||
530 | tzcode$(VERSION).tar.gz.asc: tzcode$(VERSION).tar.gz | 549 | tzcode$(VERSION).tar.gz.asc: tzcode$(VERSION).tar.gz | |
531 | gpg --armor --detach-sign $? | 550 | gpg --armor --detach-sign $? | |
532 | 551 | |||
533 | tzdata$(VERSION).tar.gz.asc: tzdata$(VERSION).tar.gz | 552 | tzdata$(VERSION).tar.gz.asc: tzdata$(VERSION).tar.gz | |
534 | gpg --armor --detach-sign $? | 553 | gpg --armor --detach-sign $? | |
535 | 554 | |||
536 | typecheck: | 555 | typecheck: | |
537 | make clean | 556 | make clean | |
538 | for i in "long long" unsigned double; \ | 557 | for i in "long long" unsigned; \ | |
539 | do \ | 558 | do \ | |
540 | make CFLAGS="-DTYPECHECK -D__time_t_defined -D_TIME_T \"-Dtime_t=$$i\"" ; \ | 559 | make CFLAGS="-DTYPECHECK -D__time_t_defined -D_TIME_T \"-Dtime_t=$$i\"" ; \ | |
541 | ./zdump -v Europe/Rome ; \ | 560 | ./zdump -v Europe/Rome ; \ | |
542 | make clean ; \ | 561 | make clean ; \ | |
543 | done | 562 | done | |
544 | 563 | |||
545 | zonenames: $(TDATA) | 564 | zonenames: $(TDATA) | |
546 | @$(AWK) '/^Zone/ { print $$2 } /^Link/ { print $$3 }' $(TDATA) | 565 | @$(AWK) '/^Zone/ { print $$2 } /^Link/ { print $$3 }' $(TDATA) | |
547 | 566 | |||
548 | asctime.o: private.h tzfile.h | 567 | asctime.o: private.h tzfile.h | |
549 | date.o: private.h | 568 | date.o: private.h | |
550 | difftime.o: private.h | 569 | difftime.o: private.h | |
551 | ialloc.o: private.h | 570 | ialloc.o: private.h |
--- src/lib/libc/time/difftime.c 2013/07/17 20:13:04 1.14
+++ src/lib/libc/time/difftime.c 2013/09/20 19:06:54 1.15
@@ -1,63 +1,54 @@ | @@ -1,63 +1,54 @@ | |||
1 | /* $NetBSD: difftime.c,v 1.14 2013/07/17 20:13:04 christos Exp $ */ | 1 | /* $NetBSD: difftime.c,v 1.15 2013/09/20 19:06:54 christos Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | ** This file is in the public domain, so clarified as of | 4 | ** This file is in the public domain, so clarified as of | |
5 | ** 1996-06-05 by Arthur David Olson. | 5 | ** 1996-06-05 by Arthur David Olson. | |
6 | */ | 6 | */ | |
7 | 7 | |||
8 | #include <sys/cdefs.h> | 8 | #include <sys/cdefs.h> | |
9 | #if defined(LIBC_SCCS) && !defined(lint) | 9 | #if defined(LIBC_SCCS) && !defined(lint) | |
10 | #if 0 | 10 | #if 0 | |
11 | static char elsieid[] = "@(#)difftime.c 8.1"; | 11 | static char elsieid[] = "@(#)difftime.c 8.1"; | |
12 | #else | 12 | #else | |
13 | __RCSID("$NetBSD: difftime.c,v 1.14 2013/07/17 20:13:04 christos Exp $"); | 13 | __RCSID("$NetBSD: difftime.c,v 1.15 2013/09/20 19:06:54 christos Exp $"); | |
14 | #endif | 14 | #endif | |
15 | #endif /* LIBC_SCCS and not lint */ | 15 | #endif /* LIBC_SCCS and not lint */ | |
16 | 16 | |||
17 | /*LINTLIBRARY*/ | 17 | /*LINTLIBRARY*/ | |
18 | 18 | |||
19 | #include "private.h" /* for time_t, TYPE_INTEGRAL, and TYPE_SIGNED */ | 19 | #include "private.h" /* for time_t and TYPE_SIGNED */ | |
20 | 20 | |||
21 | double ATTRIBUTE_CONST | 21 | double ATTRIBUTE_CONST | |
22 | difftime(const time_t time1, const time_t time0) | 22 | difftime(const time_t time1, const time_t time0) | |
23 | { | 23 | { | |
24 | /* | 24 | /* | |
25 | ** If (sizeof (double) > sizeof (time_t)) simply convert and subtract | 25 | ** If (sizeof (double) > sizeof (time_t)) simply convert and subtract | |
26 | ** (assuming that the larger type has more precision). | 26 | ** (assuming that the larger type has more precision). | |
27 | */ | 27 | */ | |
28 | /*CONSTCOND*/ | 28 | /*CONSTCOND*/ | |
29 | if (sizeof (double) > sizeof (time_t)) | 29 | if (sizeof (double) > sizeof (time_t)) | |
30 | return (double) time1 - (double) time0; | 30 | return (double) time1 - (double) time0; | |
31 | /*LINTED const not */ | 31 | /*LINTED const not */ | |
32 | if (!TYPE_INTEGRAL(time_t)) { | |||
33 | /* | |||
34 | ** time_t is floating. | |||
35 | */ | |||
36 | return time1 - time0; | |||
37 | } | |||
38 | /*LINTED const not */ | |||
39 | if (!TYPE_SIGNED(time_t)) { | 32 | if (!TYPE_SIGNED(time_t)) { | |
40 | /* | 33 | /* | |
41 | ** time_t is integral and unsigned. | |||
42 | ** The difference of two unsigned values can't overflow | 34 | ** The difference of two unsigned values can't overflow | |
43 | ** if the minuend is greater than or equal to the subtrahend. | 35 | ** if the minuend is greater than or equal to the subtrahend. | |
44 | */ | 36 | */ | |
45 | if (time1 >= time0) | 37 | if (time1 >= time0) | |
46 | return time1 - time0; | 38 | return time1 - time0; | |
47 | else return -(double) (time0 - time1); | 39 | else return -(double) (time0 - time1); | |
48 | } | 40 | } | |
49 | /* | 41 | /* | |
50 | ** time_t is integral and signed. | |||
51 | ** Handle cases where both time1 and time0 have the same sign | 42 | ** Handle cases where both time1 and time0 have the same sign | |
52 | ** (meaning that their difference cannot overflow). | 43 | ** (meaning that their difference cannot overflow). | |
53 | */ | 44 | */ | |
54 | if ((time1 < 0) == (time0 < 0)) | 45 | if ((time1 < 0) == (time0 < 0)) | |
55 | return time1 - time0; | 46 | return time1 - time0; | |
56 | /* | 47 | /* | |
57 | ** time1 and time0 have opposite signs. | 48 | ** time1 and time0 have opposite signs. | |
58 | ** Punt if uintmax_t is too narrow. | 49 | ** Punt if uintmax_t is too narrow. | |
59 | ** This suffers from double rounding; attempt to lessen that | 50 | ** This suffers from double rounding; attempt to lessen that | |
60 | ** by using long double temporaries. | 51 | ** by using long double temporaries. | |
61 | */ | 52 | */ | |
62 | /* CONSTCOND */ | 53 | /* CONSTCOND */ | |
63 | if (sizeof (uintmax_t) < sizeof (time_t)) | 54 | if (sizeof (uintmax_t) < sizeof (time_t)) |
--- src/lib/libc/time/Theory 2013/07/17 20:13:04 1.13
+++ src/lib/libc/time/Theory 2013/09/20 19:06:54 1.14
@@ -2,79 +2,80 @@ This file is in the public domain, so cl | @@ -2,79 +2,80 @@ This file is in the public domain, so cl | |||
2 | 2009-05-17 by Arthur David Olson. | 2 | 2009-05-17 by Arthur David Olson. | |
3 | 3 | |||
4 | ----- Outline ----- | 4 | ----- Outline ----- | |
5 | 5 | |||
6 | Time and date functions | 6 | Time and date functions | |
7 | Scope of the tz database | 7 | Scope of the tz database | |
8 | Names of time zone rule files | 8 | Names of time zone rule files | |
9 | Time zone abbreviations | 9 | Time zone abbreviations | |
10 | Calendrical issues | 10 | Calendrical issues | |
11 | Time and time zones on Mars | 11 | Time and time zones on Mars | |
12 | 12 | |||
13 | ----- Time and date functions ----- | 13 | ----- Time and date functions ----- | |
14 | 14 | |||
15 | These time and date functions are upwards compatible with POSIX, | 15 | These time and date functions are upwards compatible with those of POSIX, | |
16 | an international standard for UNIX-like systems. | 16 | an international standard for UNIX-like systems. | |
17 | As of this writing, the current edition of POSIX is: | 17 | As of this writing, the current edition of POSIX is: | |
18 | 18 | |||
19 | Standard for Information technology | 19 | The Open Group Base Specifications Issue 7 | |
20 | -- Portable Operating System Interface (POSIX (R)) | 20 | IEEE Std 1003.1, 2013 Edition | |
21 | -- System Interfaces | 21 | <http://pubs.opengroup.org/onlinepubs/9699919799/> | |
22 | IEEE Std 1003.1, 2004 Edition | |||
23 | <http://www.opengroup.org/online-pubs?DOC=7999959899> | |||
24 | <http://www.opengroup.org/pubs/catalog/t041.htm> | |||
25 | 22 | |||
26 | POSIX has the following properties and limitations. | 23 | POSIX has the following properties and limitations. | |
27 | 24 | |||
28 | * In POSIX, time display in a process is controlled by the | 25 | * In POSIX, time display in a process is controlled by the | |
29 | environment variable TZ. Unfortunately, the POSIX TZ string takes | 26 | environment variable TZ. Unfortunately, the POSIX TZ string takes | |
30 | a form that is hard to describe and is error-prone in practice. | 27 | a form that is hard to describe and is error-prone in practice. | |
31 | Also, POSIX TZ strings can't deal with other (for example, Israeli) | 28 | Also, POSIX TZ strings can't deal with other (for example, Israeli) | |
32 | daylight saving time rules, or situations where more than two | 29 | daylight saving time rules, or situations where more than two | |
33 | time zone abbreviations are used in an area. | 30 | time zone abbreviations are used in an area. | |
34 | 31 | |||
35 | The POSIX TZ string takes the following form: | 32 | The POSIX TZ string takes the following form: | |
36 | 33 | |||
37 | stdoffset[dst[offset],date[/time],date[/time]] | 34 | stdoffset[dst[offset][,date[/time],date[/time]]] | |
38 | 35 | |||
39 | where: | 36 | where: | |
40 | 37 | |||
41 | std and dst | 38 | std and dst | |
42 | are 3 or more characters specifying the standard | 39 | are 3 or more characters specifying the standard | |
43 | and daylight saving time (DST) zone names. | 40 | and daylight saving time (DST) zone names. | |
44 | Starting with POSIX.1-2001, std and dst may also be | 41 | Starting with POSIX.1-2001, std and dst may also be | |
45 | in a quoted form like "<UTC+10>"; this allows | 42 | in a quoted form like "<UTC+10>"; this allows | |
46 | "+" and "-" in the names. | 43 | "+" and "-" in the names. | |
47 | offset | 44 | offset | |
48 | is of the form `[-]hh:[mm[:ss]]' and specifies the | 45 | is of the form '[+-]hh:[mm[:ss]]' and specifies the | |
49 | offset west of UTC. The default DST offset is one hour | 46 | offset west of UT. 'hh' may be a single digit; 0<=hh<=24. | |
50 | ahead of standard time. | 47 | The default DST offset is one hour ahead of standard time. | |
51 | date[/time],date[/time] | 48 | date[/time],date[/time] | |
52 | specifies the beginning and end of DST. If this is absent, | 49 | specifies the beginning and end of DST. If this is absent, | |
53 | the system supplies its own rules for DST, and these can | 50 | the system supplies its own rules for DST, and these can | |
54 | differ from year to year; typically US DST rules are used. | 51 | differ from year to year; typically US DST rules are used. | |
55 | time | 52 | time | |
56 | takes the form `hh:[mm[:ss]]' and defaults to 02:00. | 53 | takes the form 'hh:[mm[:ss]]' and defaults to 02:00. | |
54 | This is the same format as the offset, except that a | |||
55 | leading '+' or '-' is not allowed. | |||
57 | date | 56 | date | |
58 | takes one of the following forms: | 57 | takes one of the following forms: | |
59 | Jn (1<=n<=365) | 58 | Jn (1<=n<=365) | |
60 | origin-1 day number not counting February 29 | 59 | origin-1 day number not counting February 29 | |
61 | n (0<=n<=365) | 60 | n (0<=n<=365) | |
62 | origin-0 day number counting February 29 if present | 61 | origin-0 day number counting February 29 if present | |
63 | Mm.n.d (0[Sunday]<=d<=6[Saturday], 1<=n<=5, 1<=m<=12) | 62 | Mm.n.d (0[Sunday]<=d<=6[Saturday], 1<=n<=5, 1<=m<=12) | |
64 | for the dth day of week n of month m of the year, | 63 | for the dth day of week n of month m of the year, | |
65 | where week 1 is the first week in which day d appears, | 64 | where week 1 is the first week in which day d appears, | |
66 | and `5' stands for the last week in which day d appears | 65 | and '5' stands for the last week in which day d appears | |
67 | (which may be either the 4th or 5th week). | 66 | (which may be either the 4th or 5th week). | |
67 | Typically, this is the only useful form; | |||
68 | the n and Jn forms are rarely used. | |||
68 | 69 | |||
69 | Here is an example POSIX TZ string, for US Pacific time using rules | 70 | Here is an example POSIX TZ string, for US Pacific time using rules | |
70 | appropriate from 1987 through 2006: | 71 | appropriate from 1987 through 2006: | |
71 | 72 | |||
72 | TZ='PST8PDT,M4.1.0/02:00,M10.5.0/02:00' | 73 | TZ='PST8PDT,M4.1.0/02:00,M10.5.0/02:00' | |
73 | 74 | |||
74 | This POSIX TZ string is hard to remember, and mishandles time stamps | 75 | This POSIX TZ string is hard to remember, and mishandles time stamps | |
75 | before 1987 and after 2006. With this package you can use this | 76 | before 1987 and after 2006. With this package you can use this | |
76 | instead: | 77 | instead: | |
77 | 78 | |||
78 | TZ='America/Los_Angeles' | 79 | TZ='America/Los_Angeles' | |
79 | 80 | |||
80 | * POSIX does not define the exact meaning of TZ values like "EST5EDT". | 81 | * POSIX does not define the exact meaning of TZ values like "EST5EDT". | |
@@ -85,26 +86,39 @@ POSIX has the following properties and l | @@ -85,26 +86,39 @@ POSIX has the following properties and l | |||
85 | do time conversion must be recompiled to ensure proper results. | 86 | do time conversion must be recompiled to ensure proper results. | |
86 | 87 | |||
87 | * In POSIX, there's no tamper-proof way for a process to learn the | 88 | * In POSIX, there's no tamper-proof way for a process to learn the | |
88 | system's best idea of local wall clock. (This is important for | 89 | system's best idea of local wall clock. (This is important for | |
89 | applications that an administrator wants used only at certain times-- | 90 | applications that an administrator wants used only at certain times-- | |
90 | without regard to whether the user has fiddled the "TZ" environment | 91 | without regard to whether the user has fiddled the "TZ" environment | |
91 | variable. While an administrator can "do everything in UTC" to get | 92 | variable. While an administrator can "do everything in UTC" to get | |
92 | around the problem, doing so is inconvenient and precludes handling | 93 | around the problem, doing so is inconvenient and precludes handling | |
93 | daylight saving time shifts--as might be required to limit phone | 94 | daylight saving time shifts--as might be required to limit phone | |
94 | calls to off-peak hours.) | 95 | calls to off-peak hours.) | |
95 | 96 | |||
96 | * POSIX requires that systems ignore leap seconds. | 97 | * POSIX requires that systems ignore leap seconds. | |
97 | 98 | |||
99 | * The tz code attempts attempts to support all the time_t implementations | |||
100 | allowed by POSIX. The time_t type represents a nonnegative count of | |||
101 | seconds since 1970-01-01 00:00:00 UTC, ignoring leap seconds. | |||
102 | In practice, time_t is usually a signed 64- or 32-bit integer; 32-bit | |||
103 | signed time_t values stop working after 2038-01-19 03:14:07 UTC, so | |||
104 | new implementations these days typically use a signed 64-bit integer. | |||
105 | Unsigned 32-bit integers are used on one or two platforms, | |||
106 | and 36-bit integers are also used occasionally. | |||
107 | Although earlier POSIX versions allowed time_t to be a | |||
108 | floating-point type, this was not supported by any practical | |||
109 | systems, and POSIX.1-2013 and the tz code both require time_t | |||
110 | to be an integer type. | |||
111 | ||||
98 | These are the extensions that have been made to the POSIX functions: | 112 | These are the extensions that have been made to the POSIX functions: | |
99 | 113 | |||
100 | * The "TZ" environment variable is used in generating the name of a file | 114 | * The "TZ" environment variable is used in generating the name of a file | |
101 | from which time zone information is read (or is interpreted a la | 115 | from which time zone information is read (or is interpreted a la | |
102 | POSIX); "TZ" is no longer constrained to be a three-letter time zone | 116 | POSIX); "TZ" is no longer constrained to be a three-letter time zone | |
103 | name followed by a number of hours and an optional three-letter | 117 | name followed by a number of hours and an optional three-letter | |
104 | daylight time zone name. The daylight saving time rules to be used | 118 | daylight time zone name. The daylight saving time rules to be used | |
105 | for a particular time zone are encoded in the time zone file; | 119 | for a particular time zone are encoded in the time zone file; | |
106 | the format of the file allows U.S., Australian, and other rules to be | 120 | the format of the file allows U.S., Australian, and other rules to be | |
107 | encoded, and allows for situations where more than two time zone | 121 | encoded, and allows for situations where more than two time zone | |
108 | abbreviations are used. | 122 | abbreviations are used. | |
109 | 123 | |||
110 | It was recognized that allowing the "TZ" environment variable to | 124 | It was recognized that allowing the "TZ" environment variable to | |
@@ -136,96 +150,223 @@ These are the extensions that have been | @@ -136,96 +150,223 @@ These are the extensions that have been | |||
136 | source code tells how to get compatibly wrong results). | 150 | source code tells how to get compatibly wrong results). | |
137 | 151 | |||
138 | * A function "tzsetwall" has been added to arrange for the system's | 152 | * A function "tzsetwall" has been added to arrange for the system's | |
139 | best approximation to local wall clock time to be delivered by | 153 | best approximation to local wall clock time to be delivered by | |
140 | subsequent calls to "localtime." Source code for portable | 154 | subsequent calls to "localtime." Source code for portable | |
141 | applications that "must" run on local wall clock time should call | 155 | applications that "must" run on local wall clock time should call | |
142 | "tzsetwall();" if such code is moved to "old" systems that don't | 156 | "tzsetwall();" if such code is moved to "old" systems that don't | |
143 | provide tzsetwall, you won't be able to generate an executable program. | 157 | provide tzsetwall, you won't be able to generate an executable program. | |
144 | (These time zone functions also arrange for local wall clock time to be | 158 | (These time zone functions also arrange for local wall clock time to be | |
145 | used if tzset is called--directly or indirectly--and there's no "TZ" | 159 | used if tzset is called--directly or indirectly--and there's no "TZ" | |
146 | environment variable; portable applications should not, however, rely | 160 | environment variable; portable applications should not, however, rely | |
147 | on this behavior since it's not the way SVR2 systems behave.) | 161 | on this behavior since it's not the way SVR2 systems behave.) | |
148 | 162 | |||
163 | * Negative time_t values are supported, on systems where time_t is signed. | |||
164 | ||||
149 | * These functions can account for leap seconds, thanks to Bradley White. | 165 | * These functions can account for leap seconds, thanks to Bradley White. | |
150 | 166 | |||
151 | Points of interest to folks with other systems: | 167 | Points of interest to folks with other systems: | |
152 | 168 | |||
153 | * This package is already part of many POSIX-compliant hosts, | 169 | * This package is already part of many POSIX-compliant hosts, | |
154 | including BSD, HP, Linux, Network Appliance, SCO, SGI, and Sun. | 170 | including BSD, HP, Linux, Network Appliance, SCO, SGI, and Sun. | |
155 | On such hosts, the primary use of this package | 171 | On such hosts, the primary use of this package | |
156 | is to update obsolete time zone rule tables. | 172 | is to update obsolete time zone rule tables. | |
157 | To do this, you may need to compile the time zone compiler | 173 | To do this, you may need to compile the time zone compiler | |
158 | `zic' supplied with this package instead of using the system `zic', | 174 | 'zic' supplied with this package instead of using the system 'zic', | |
159 | since the format of zic's input changed slightly in late 1994, | 175 | since the format of zic's input changed slightly in late 1994, | |
160 | and many vendors still do not support the new input format. | 176 | and many vendors still do not support the new input format. | |
161 | 177 | |||
162 | * The UNIX Version 7 "timezone" function is not present in this package; | 178 | * The UNIX Version 7 "timezone" function is not present in this package; | |
163 | it's impossible to reliably map timezone's arguments (a "minutes west | 179 | it's impossible to reliably map timezone's arguments (a "minutes west | |
164 | of GMT" value and a "daylight saving time in effect" flag) to a | 180 | of GMT" value and a "daylight saving time in effect" flag) to a | |
165 | time zone abbreviation, and we refuse to guess. | 181 | time zone abbreviation, and we refuse to guess. | |
166 | Programs that in the past used the timezone function may now examine | 182 | Programs that in the past used the timezone function may now examine | |
167 | tzname[localtime(&clock)->tm_isdst] to learn the correct time | 183 | tzname[localtime(&clock)->tm_isdst] to learn the correct time | |
168 | zone abbreviation to use. Alternatively, use | 184 | zone abbreviation to use. Alternatively, use | |
169 | localtime(&clock)->tm_zone if this has been enabled. | 185 | localtime(&clock)->tm_zone if this has been enabled. | |
170 | 186 | |||
171 | * The 4.2BSD gettimeofday function is not used in this package. | 187 | * The 4.2BSD gettimeofday function is not used in this package. | |
172 | This formerly let users obtain the current UTC offset and DST flag, | 188 | This formerly let users obtain the current UTC offset and DST flag, | |
173 | but this functionality was removed in later versions of BSD. | 189 | but this functionality was removed in later versions of BSD. | |
174 | 190 | |||
175 | * In SVR2, time conversion fails for near-minimum or near-maximum | 191 | * In SVR2, time conversion fails for near-minimum or near-maximum | |
176 | time_t values when doing conversions for places that don't use UTC. | 192 | time_t values when doing conversions for places that don't use UT. | |
177 | This package takes care to do these conversions correctly. | 193 | This package takes care to do these conversions correctly. | |
178 | 194 | |||
179 | The functions that are conditionally compiled if STD_INSPIRED is defined | 195 | The functions that are conditionally compiled if STD_INSPIRED is defined | |
180 | should, at this point, be looked on primarily as food for thought. They are | 196 | should, at this point, be looked on primarily as food for thought. They are | |
181 | not in any sense "standard compatible"--some are not, in fact, specified in | 197 | not in any sense "standard compatible"--some are not, in fact, specified in | |
182 | *any* standard. They do, however, represent responses of various authors to | 198 | *any* standard. They do, however, represent responses of various authors to | |
183 | standardization proposals. | 199 | standardization proposals. | |
184 | 200 | |||
185 | Other time conversion proposals, in particular the one developed by folks at | 201 | Other time conversion proposals, in particular the one developed by folks at | |
186 | Hewlett Packard, offer a wider selection of functions that provide capabilities | 202 | Hewlett Packard, offer a wider selection of functions that provide capabilities | |
187 | beyond those provided here. The absence of such functions from this package | 203 | beyond those provided here. The absence of such functions from this package | |
188 | is not meant to discourage the development, standardization, or use of such | 204 | is not meant to discourage the development, standardization, or use of such | |
189 | functions. Rather, their absence reflects the decision to make this package | 205 | functions. Rather, their absence reflects the decision to make this package | |
190 | contain valid extensions to POSIX, to ensure its broad acceptability. If | 206 | contain valid extensions to POSIX, to ensure its broad acceptability. If | |
191 | more powerful time conversion functions can be standardized, so much the | 207 | more powerful time conversion functions can be standardized, so much the | |
192 | better. | 208 | better. | |
193 | 209 | |||
194 | 210 | |||
195 | ----- Scope of the tz database ----- | 211 | ----- Scope of the tz database ----- | |
196 | 212 | |||
197 | The tz database attempts to record the history and predicted future of | 213 | The tz database attempts to record the history and predicted future of | |
198 | all computer-based clocks that track civil time. To represent this | 214 | all computer-based clocks that track civil time. To represent this | |
199 | data, the world is partitioned into regions whose clocks all agree | 215 | data, the world is partitioned into regions whose clocks all agree | |
200 | about time stamps that occur after the somewhat-arbitrary cutoff point | 216 | about time stamps that occur after the somewhat-arbitrary cutoff point | |
201 | of the POSIX Epoch (1970-01-01 00:00:00 UTC). For each such region, | 217 | of the POSIX Epoch (1970-01-01 00:00:00 UTC). For each such region, | |
202 | the database records all known clock transitions, and labels the region | 218 | the database records all known clock transitions, and labels the region | |
203 | with a notable location. | 219 | with a notable location. Although 1970 is a somewhat-arbitrary | |
220 | cutoff, there are significant challenges to moving the cutoff earlier | |||
221 | even by a decade or two, due to the wide variety of local practices | |||
222 | before computer timekeeping became prevalent. | |||
204 | 223 | |||
205 | Clock transitions before 1970 are recorded for each such location, | 224 | Clock transitions before 1970 are recorded for each such location, | |
206 | because most POSIX-compatible systems support negative time stamps and | 225 | because most POSIX-compatible systems support negative time stamps and | |
207 | could misbehave if data were omitted for pre-1970 transitions. | 226 | could misbehave if data were omitted for pre-1970 transitions. | |
208 | However, the database is not designed for and does not suffice for | 227 | However, the database is not designed for and does not suffice for | |
209 | applications requiring accurate handling of all past times everywhere, | 228 | applications requiring accurate handling of all past times everywhere, | |
210 | as it would take far too much effort and guesswork to record all | 229 | as it would take far too much effort and guesswork to record all | |
211 | details of pre-1970 civil timekeeping. | 230 | details of pre-1970 civil timekeeping. | |
212 | 231 | |||
213 | As noted in the README file, the tz database is not authoritative | 232 | ||
214 | (particularly not for pre-1970 time stamps), and it surely has errors. | 233 | ----- Accuracy of the tz database ----- | |
234 | ||||
235 | The tz database is not authoritative, and it surely has errors. | |||
215 | Corrections are welcome and encouraged. Users requiring authoritative | 236 | Corrections are welcome and encouraged. Users requiring authoritative | |
216 | data should consult national standards bodies and the references cited | 237 | data should consult national standards bodies and the references cited | |
217 | in the database's comments. | 238 | in the database's comments. | |
218 | 239 | |||
240 | Errors in the tz database arise from many sources: | |||
241 | ||||
242 | * The tz database predicts future time stamps, and current predictions | |||
243 | will be incorrect after future governments change the rules. | |||
244 | For example, if today someone schedules a meeting for 13:00 next | |||
245 | October 1, Casablanca time, and tomorrow Morocco changes its | |||
246 | daylight saving rules, software can mess up after the rule change | |||
247 | if it blithely relies on conversions made before the change. | |||
248 | ||||
249 | * The pre-1970 data in this database cover only a tiny sliver of how | |||
250 | clocks actually behaved; the vast majority of the necessary | |||
251 | information was lost or never recorded. Thousands more zones would | |||
252 | be needed if the tz database's scope were extended to cover even | |||
253 | just the known or guessed history of standard time; for example, | |||
254 | the current single entry for France would need to split into dozens | |||
255 | of entries, perhaps hundreds. | |||
256 | ||||
257 | * Most of the pre-1970 data comes from unreliable sources, often | |||
258 | astrology books that lack citations and whose compilers evidently | |||
259 | invented entries when the true facts were unknown, without | |||
260 | reporting which entries were known and which were invented. | |||
261 | These books often contradict each other or give implausible entries, | |||
262 | and on the rare occasions when their old data are checked they are | |||
263 | typically found to be incorrect. | |||
264 | ||||
265 | * For the UK the tz database relies on years of first-class work done by | |||
266 | Joseph Myers and others; see <http://www.polyomino.org.uk/british-time/>. | |||
267 | Other countries are not done nearly as well. | |||
268 | ||||
269 | * Sometimes, different people in the same city would maintain clocks | |||
270 | that differed significantly. Railway time was used by railroad | |||
271 | companies (which did not always agree with each other), | |||
272 | church-clock time was used for birth certificates, etc. | |||
273 | Often this was merely common practice, but sometimes it was set by law. | |||
274 | For example, from 1891 to 1911 the UT offset in France was legally | |||
275 | 0:09:21 outside train stations and 0:04:21 inside. | |||
276 | ||||
277 | * Although a named location in the tz database stands for the | |||
278 | containing region, its pre-1970 data entries are often accurate for | |||
279 | only a small subset of that region. For example, Europe/London | |||
280 | stands for the United Kingdom, but its pre-1847 times are valid | |||
281 | only for locations that have London's exact meridian, and its 1847 | |||
282 | transition to GMT is known to be valid only for the L&NW and the | |||
283 | Caledonian railways. | |||
284 | ||||
285 | * The tz database does not record the earliest time for which a | |||
286 | zone's data is thereafter valid for every location in the region. | |||
287 | For example, Europe/London is valid for all locations in its | |||
288 | region after GMT was made the standard time, but the date of | |||
289 | standardization (1880-08-02) is not in the tz database, other than | |||
290 | in commentary. For many zones the earliest time of validity is | |||
291 | unknown. | |||
292 | ||||
293 | * The tz database does not record a region's boundaries, and in many | |||
294 | cases the boundaries are not known. For example, the zone | |||
295 | America/Kentucky/Louisville represents a region around the city of | |||
296 | Louisville, the boundaries of which are unclear. | |||
297 | ||||
298 | * Changes that are modeled as instantaneous transitions in the tz | |||
299 | database were often spread out over hours, days, or even decades. | |||
300 | ||||
301 | * Even if the time is specified by law, locations sometimes | |||
302 | deliberately flout the law. | |||
303 | ||||
304 | * Early timekeeping practices, even assuming perfect clocks, were | |||
305 | often not specified to the accuracy that the tz database requires. | |||
306 | ||||
307 | * Sometimes historical timekeeping was specified more precisely | |||
308 | than what the tz database can handle. For example, from 1909 to | |||
309 | 1937 Netherlands clocks were legally UT+00:19:32.13, but the tz | |||
310 | database cannot represent the fractional second. | |||
311 | ||||
312 | * Even when all the timestamp transitions recorded by the tz database | |||
313 | are correct, the tz rules that generate them may not faithfully | |||
314 | reflect the historical rules. For example, from 1922 until World | |||
315 | War II the UK moved clocks forward the day following the third | |||
316 | Saturday in April unless that was Easter, in which case it moved | |||
317 | clocks forward the previous Sunday. Because the tz database has no | |||
318 | way to specify Easter, these exceptional years are entered as | |||
319 | separate tz Rule lines, even though the legal rules did not change. | |||
320 | ||||
321 | * The tz database models pre-standard time using the Gregorian | |||
322 | calendar and local mean time (LMT), but many people used other | |||
323 | calendars and other timescales. For example, the Roman Empire used | |||
324 | the Julian calendar, and had 12 varying-length daytime hours with a | |||
325 | non-hour-based system at night. | |||
326 | ||||
327 | * Early clocks were less reliable, and the data do not represent this | |||
328 | unreliability. | |||
329 | ||||
330 | * As for leap seconds, civil time was not based on atomic time before | |||
331 | 1972, and we don't know the history of earth's rotation accurately | |||
332 | enough to map SI seconds to historical solar time to more than | |||
333 | about one-hour accuracy. See: Morrison LV, Stephenson FR. | |||
334 | Historical values of the Earth's clock error Delta T and the | |||
335 | calculation of eclipses. J Hist Astron. 2004;35:327-36 | |||
336 | <http://adsabs.harvard.edu/full/2004JHA....35..327M>; | |||
337 | Historical values of the Earth's clock error. J Hist Astron. 2005;36:339 | |||
338 | <http://adsabs.harvard.edu/full/2005JHA....36..339M>. | |||
339 | ||||
340 | * The relationship between POSIX time (that is, UTC but ignoring leap | |||
341 | seconds) and UTC is not agreed upon after 1972. Although the POSIX | |||
342 | clock officially stops during an inserted leap second, at least one | |||
343 | proposed standard has it jumping back a second instead; and in | |||
344 | practice POSIX clocks more typically either progress glacially during | |||
345 | a leap second, or are slightly slowed while near a leap second. | |||
346 | ||||
347 | * The tz database does not represent how uncertain its information is. | |||
348 | Ideally it would contain information about when the data are | |||
349 | incomplete or dicey. Partial temporal knowledge is a field of | |||
350 | active research, though, and it's not clear how to apply it here. | |||
351 | ||||
352 | In short, many, perhaps most, of the tz database's pre-1970 and future | |||
353 | time stamps are either wrong or misleading. Any attempt to pass the | |||
354 | tz database off as the definition of time should be unacceptable to | |||
355 | anybody who cares about the facts. In particular, the tz database's | |||
356 | LMT offsets should not be considered meaningful, and should not prompt | |||
357 | creation of zones merely because two locations differ in LMT or | |||
358 | transitioned to standard time at different dates. | |||
359 | ||||
219 | 360 | |||
220 | ----- Names of time zone rule files ----- | 361 | ----- Names of time zone rule files ----- | |
221 | 362 | |||
222 | The time zone rule file naming conventions attempt to strike a balance | 363 | The time zone rule file naming conventions attempt to strike a balance | |
223 | among the following goals: | 364 | among the following goals: | |
224 | 365 | |||
225 | * Uniquely identify every national region where clocks have all | 366 | * Uniquely identify every national region where clocks have all | |
226 | agreed since 1970. This is essential for the intended use: static | 367 | agreed since 1970. This is essential for the intended use: static | |
227 | clocks keeping local civil time. | 368 | clocks keeping local civil time. | |
228 | 369 | |||
229 | * Indicate to humans as to where that region is. This simplifies use. | 370 | * Indicate to humans as to where that region is. This simplifies use. | |
230 | 371 | |||
231 | * Be robust in the presence of political changes. This reduces the | 372 | * Be robust in the presence of political changes. This reduces the | |
@@ -241,177 +382,193 @@ among the following goals: | @@ -241,177 +382,193 @@ among the following goals: | |||
241 | * Use a consistent naming convention over the entire world. | 382 | * Use a consistent naming convention over the entire world. | |
242 | This simplifies both use and maintenance. | 383 | This simplifies both use and maintenance. | |
243 | 384 | |||
244 | This naming convention is not intended for use by inexperienced users | 385 | This naming convention is not intended for use by inexperienced users | |
245 | to select TZ values by themselves (though they can of course examine | 386 | to select TZ values by themselves (though they can of course examine | |
246 | and reuse existing settings). Distributors should provide | 387 | and reuse existing settings). Distributors should provide | |
247 | documentation and/or a simple selection interface that explains the | 388 | documentation and/or a simple selection interface that explains the | |
248 | names; see the 'tzselect' program supplied with this distribution for | 389 | names; see the 'tzselect' program supplied with this distribution for | |
249 | one example. | 390 | one example. | |
250 | 391 | |||
251 | Names normally have the form AREA/LOCATION, where AREA is the name | 392 | Names normally have the form AREA/LOCATION, where AREA is the name | |
252 | of a continent or ocean, and LOCATION is the name of a specific | 393 | of a continent or ocean, and LOCATION is the name of a specific | |
253 | location within that region. North and South America share the same | 394 | location within that region. North and South America share the same | |
254 | area, `America'. Typical names are `Africa/Cairo', `America/New_York', | 395 | area, 'America'. Typical names are 'Africa/Cairo', 'America/New_York', | |
255 | and `Pacific/Honolulu'. | 396 | and 'Pacific/Honolulu'. | |
256 | 397 | |||
257 | Here are the general rules used for choosing location names, | 398 | Here are the general rules used for choosing location names, | |
258 | in decreasing order of importance: | 399 | in decreasing order of importance: | |
259 | 400 | |||
260 | Use only valid POSIX file name components (i.e., the parts of | 401 | Use only valid POSIX file name components (i.e., the parts of | |
261 | names other than `/'). Within a file name component, | 402 | names other than '/'). Do not use the file name | |
262 | use only ASCII letters, `.', `-' and `_'. Do not use | 403 | components '.' and '..'. Within a file name component, | |
404 | use only ASCII letters, '.', '-' and '_'. Do not use | |||
263 | digits, as that might create an ambiguity with POSIX | 405 | digits, as that might create an ambiguity with POSIX | |
264 | TZ strings. A file name component must not exceed 14 | 406 | TZ strings. A file name component must not exceed 14 | |
265 | characters or start with `-'. E.g., prefer `Brunei' | 407 | characters or start with '-'. E.g., prefer 'Brunei' | |
266 | to `Bandar_Seri_Begawan'. | 408 | to 'Bandar_Seri_Begawan'. | |
409 | A name must not be empty, or contain '//', or start or end with '/'. | |||
267 | Do not use names that differ only in case. Although the reference | 410 | Do not use names that differ only in case. Although the reference | |
268 | implementation is case-sensitive, some other implementations | 411 | implementation is case-sensitive, some other implementations | |
269 | are not, and they would mishandle names differing only in case. | 412 | are not, and they would mishandle names differing only in case. | |
413 | If one name A is an initial prefix of another name AB (ignoring case), | |||
414 | then B must not start with '/', as a regular file cannot have | |||
415 | the same name as a directory in POSIX. For example, | |||
416 | 'America/New_York' precludes 'America/New_York/Bronx'. | |||
270 | Uninhabited regions like the North Pole and Bouvet Island | 417 | Uninhabited regions like the North Pole and Bouvet Island | |
271 | do not need locations, since local time is not defined there. | 418 | do not need locations, since local time is not defined there. | |
419 | There should typically be at least one name for each ISO 3166-1 | |||
420 | officially assigned two-letter code for an inhabited country | |||
421 | or territory. | |||
272 | If all the clocks in a region have agreed since 1970, | 422 | If all the clocks in a region have agreed since 1970, | |
273 | don't bother to include more than one location | 423 | don't bother to include more than one location | |
274 | even if subregions' clocks disagreed before 1970. | 424 | even if subregions' clocks disagreed before 1970. | |
275 | Otherwise these tables would become annoyingly large. | 425 | Otherwise these tables would become annoyingly large. | |
276 | If a name is ambiguous, use a less ambiguous alternative; | 426 | If a name is ambiguous, use a less ambiguous alternative; | |
277 | e.g. many cities are named San Jose and Georgetown, so | 427 | e.g. many cities are named San Jose and Georgetown, so | |
278 | prefer `Costa_Rica' to `San_Jose' and `Guyana' to `Georgetown'. | 428 | prefer 'Costa_Rica' to 'San_Jose' and 'Guyana' to 'Georgetown'. | |
279 | Keep locations compact. Use cities or small islands, not countries | 429 | Keep locations compact. Use cities or small islands, not countries | |
280 | or regions, so that any future time zone changes do not split | 430 | or regions, so that any future time zone changes do not split | |
281 | locations into different time zones. E.g. prefer `Paris' | 431 | locations into different time zones. E.g. prefer 'Paris' | |
282 | to `France', since France has had multiple time zones. | 432 | to 'France', since France has had multiple time zones. | |
283 | Use mainstream English spelling, e.g. prefer `Rome' to `Roma', and | 433 | Use mainstream English spelling, e.g. prefer 'Rome' to 'Roma', and | |
284 | prefer `Athens' to the true name (which uses Greek letters). | 434 | prefer 'Athens' to the true name (which uses Greek letters). | |
285 | The POSIX file name restrictions encourage this rule. | 435 | The POSIX file name restrictions encourage this rule. | |
286 | Use the most populous among locations in a zone, | 436 | Use the most populous among locations in a zone, | |
287 | e.g. prefer `Shanghai' to `Beijing'. Among locations with | 437 | e.g. prefer 'Shanghai' to 'Beijing'. Among locations with | |
288 | similar populations, pick the best-known location, | 438 | similar populations, pick the best-known location, | |
289 | e.g. prefer `Rome' to `Milan'. | 439 | e.g. prefer 'Rome' to 'Milan'. | |
290 | Use the singular form, e.g. prefer `Canary' to `Canaries'. | 440 | Use the singular form, e.g. prefer 'Canary' to 'Canaries'. | |
291 | Omit common suffixes like `_Islands' and `_City', unless that | 441 | Omit common suffixes like '_Islands' and '_City', unless that | |
292 | would lead to ambiguity. E.g. prefer `Cayman' to | 442 | would lead to ambiguity. E.g. prefer 'Cayman' to | |
293 | `Cayman_Islands' and `Guatemala' to `Guatemala_City', | 443 | 'Cayman_Islands' and 'Guatemala' to 'Guatemala_City', | |
294 | but prefer `Mexico_City' to `Mexico' because the country | 444 | but prefer 'Mexico_City' to 'Mexico' because the country | |
295 | of Mexico has several time zones. | 445 | of Mexico has several time zones. | |
296 | Use `_' to represent a space. | 446 | Use '_' to represent a space. | |
297 | Omit `.' from abbreviations in names, e.g. prefer `St_Helena' | 447 | Omit '.' from abbreviations in names, e.g. prefer 'St_Helena' | |
298 | to `St._Helena'. | 448 | to 'St._Helena'. | |
299 | Do not change established names if they only marginally | 449 | Do not change established names if they only marginally | |
300 | violate the above rules. For example, don't change | 450 | violate the above rules. For example, don't change | |
301 | the existing name `Rome' to `Milan' merely because | 451 | the existing name 'Rome' to 'Milan' merely because | |
302 | Milan's population has grown to be somewhat greater | 452 | Milan's population has grown to be somewhat greater | |
303 | than Rome's. | 453 | than Rome's. | |
304 | If a name is changed, put its old spelling in the `backward' file. | 454 | If a name is changed, put its old spelling in the 'backward' file. | |
305 | This means old spellings will continue to work. | 455 | This means old spellings will continue to work. | |
306 | 456 | |||
307 | The file `zone.tab' lists the geographical locations used to name | 457 | The file 'zone.tab' lists geographical locations used to name time | |
308 | time zone rule files. It is intended to be an exhaustive list | 458 | zone rule files. It is intended to be an exhaustive list of names | |
309 | of names for geographic regions as described above. | 459 | for geographic regions as described above; this is a subset of the | |
460 | names in the data. Although a 'zone.tab' location's longitude | |||
461 | corresponds to its LMT offset with one hour for every 15 degrees east | |||
462 | longitude, this relationship is not exact. | |||
310 | 463 | |||
311 | Older versions of this package used a different naming scheme, | 464 | Older versions of this package used a different naming scheme, | |
312 | and these older names are still supported. | 465 | and these older names are still supported. | |
313 | See the file `backward' for most of these older names | 466 | See the file 'backward' for most of these older names | |
314 | (e.g. `US/Eastern' instead of `America/New_York'). | 467 | (e.g. 'US/Eastern' instead of 'America/New_York'); | |
468 | excluding 'backward' should not affect the other data. | |||
315 | The other old-fashioned names still supported are | 469 | The other old-fashioned names still supported are | |
316 | `WET', `CET', `MET', and `EET' (see the file `europe'). | 470 | 'WET', 'CET', 'MET', and 'EET' (see the file 'europe'). | |
317 | 471 | |||
318 | 472 | |||
319 | ----- Time zone abbreviations ----- | 473 | ----- Time zone abbreviations ----- | |
320 | 474 | |||
321 | When this package is installed, it generates time zone abbreviations | 475 | When this package is installed, it generates time zone abbreviations | |
322 | like `EST' to be compatible with human tradition and POSIX. | 476 | like 'EST' to be compatible with human tradition and POSIX. | |
323 | Here are the general rules used for choosing time zone abbreviations, | 477 | Here are the general rules used for choosing time zone abbreviations, | |
324 | in decreasing order of importance: | 478 | in decreasing order of importance: | |
325 | 479 | |||
326 | Use abbreviations that consist of three or more ASCII letters. | 480 | Use abbreviations that consist of three or more ASCII letters. | |
327 | Previous editions of this database also used characters like | 481 | Previous editions of this database also used characters like | |
328 | ' ' and '?', but these characters have a special meaning to | 482 | ' ' and '?', but these characters have a special meaning to | |
329 | the shell and cause commands like | 483 | the shell and cause commands like | |
330 | set `date` | 484 | set `date` | |
331 | to have unexpected effects. | 485 | to have unexpected effects. | |
332 | Previous editions of this rule required upper-case letters, | 486 | Previous editions of this rule required upper-case letters, | |
333 | but the Congressman who introduced Chamorro Standard Time | 487 | but the Congressman who introduced Chamorro Standard Time | |
334 | preferred "ChST", so the rule has been relaxed. | 488 | preferred "ChST", so the rule has been relaxed. | |
335 | 489 | |||
336 | This rule guarantees that all abbreviations could have | 490 | This rule guarantees that all abbreviations could have | |
337 | been specified by a POSIX TZ string. POSIX | 491 | been specified by a POSIX TZ string. POSIX | |
338 | requires at least three characters for an | 492 | requires at least three characters for an | |
339 | abbreviation. POSIX through 2000 says that an abbreviation | 493 | abbreviation. POSIX through 2000 says that an abbreviation | |
340 | cannot start with ':', and cannot contain ',', '-', | 494 | cannot start with ':', and cannot contain ',', '-', | |
341 | '+', NUL, or a digit. POSIX from 2001 on changes this | 495 | '+', NUL, or a digit. POSIX from 2001 on changes this | |
342 | rule to say that an abbreviation can contain only '-', '+', | 496 | rule to say that an abbreviation can contain only '-', '+', | |
343 | and alphanumeric characters from the portable character set | 497 | and alphanumeric characters from the portable character set | |
344 | in the current locale. To be portable to both sets of | 498 | in the current locale. To be portable to both sets of | |
345 | rules, an abbreviation must therefore use only ASCII | 499 | rules, an abbreviation must therefore use only ASCII | |
346 | letters. | 500 | letters. | |
347 | 501 | |||
348 | Use abbreviations that are in common use among English-speakers, | 502 | Use abbreviations that are in common use among English-speakers, | |
349 | e.g. `EST' for Eastern Standard Time in North America. | 503 | e.g. 'EST' for Eastern Standard Time in North America. | |
350 | We assume that applications translate them to other languages | 504 | We assume that applications translate them to other languages | |
351 | as part of the normal localization process; for example, | 505 | as part of the normal localization process; for example, | |
352 | a French application might translate `EST' to `HNE'. | 506 | a French application might translate 'EST' to 'HNE'. | |
353 | 507 | |||
354 | For zones whose times are taken from a city's longitude, use the | 508 | For zones whose times are taken from a city's longitude, use the | |
355 | traditional xMT notation, e.g. `PMT' for Paris Mean Time. | 509 | traditional xMT notation, e.g. 'PMT' for Paris Mean Time. | |
356 | The only name like this in current use is `GMT'. | 510 | The only name like this in current use is 'GMT'. | |
357 | 511 | |||
358 | If there is no common English abbreviation, abbreviate the English | 512 | If there is no common English abbreviation, abbreviate the English | |
359 | translation of the usual phrase used by native speakers. | 513 | translation of the usual phrase used by native speakers. | |
360 | If this is not available or is a phrase mentioning the country | 514 | If this is not available or is a phrase mentioning the country | |
361 | (e.g. ``Cape Verde Time''), then: | 515 | (e.g. "Cape Verde Time"), then: | |
362 | 516 | |||
363 | When a country is identified with a single or principal zone, | 517 | When a country is identified with a single or principal zone, | |
364 | append `T' to the country's ISO code, e.g. `CVT' for | 518 | append 'T' to the country's ISO code, e.g. 'CVT' for | |
365 | Cape Verde Time. For summer time append `ST'; | 519 | Cape Verde Time. For summer time append 'ST'; | |
366 | for double summer time append `DST'; etc. | 520 | for double summer time append 'DST'; etc. | |
367 | Otherwise, take the first three letters of an English place | 521 | Otherwise, take the first three letters of an English place | |
368 | name identifying each zone and append 'T', 'ST', etc. | 522 | name identifying each zone and append 'T', 'ST', etc. | |
369 | as before; e.g. 'VLAST' for VLAdivostok Summer Time. | 523 | as before; e.g. 'VLAST' for VLAdivostok Summer Time. | |
370 | 524 | |||
371 | Use UTC (with time zone abbreviation "zzz") for locations while | 525 | Use 'LMT' for local mean time of locations before the introduction | |
372 | uninhabited. The "zzz" mnemonic is that these locations are, | 526 | of standard time; see "Scope of the tz database". | |
527 | ||||
528 | Use UT (with time zone abbreviation 'zzz') for locations while | |||
529 | uninhabited. The 'zzz' mnemonic is that these locations are, | |||
373 | in some sense, asleep. | 530 | in some sense, asleep. | |
374 | 531 | |||
375 | Application writers should note that these abbreviations are ambiguous | 532 | Application writers should note that these abbreviations are ambiguous | |
376 | in practice: e.g. `EST' has a different meaning in Australia than | 533 | in practice: e.g. 'EST' has a different meaning in Australia than | |
377 | it does in the United States. In new applications, it's often better | 534 | it does in the United States. In new applications, it's often better | |
378 | to use numeric UTC offsets like `-0500' instead of time zone | 535 | to use numeric UT offsets like '-0500' instead of time zone | |
379 | abbreviations like `EST'; this avoids the ambiguity. | 536 | abbreviations like 'EST'; this avoids the ambiguity. | |
380 | 537 | |||
381 | 538 | |||
382 | ----- Calendrical issues ----- | 539 | ----- Calendrical issues ----- | |
383 | 540 | |||
384 | Calendrical issues are a bit out of scope for a time zone database, | 541 | Calendrical issues are a bit out of scope for a time zone database, | |
385 | but they indicate the sort of problems that we would run into if we | 542 | but they indicate the sort of problems that we would run into if we | |
386 | extended the time zone database further into the past. An excellent | 543 | extended the time zone database further into the past. An excellent | |
387 | resource in this area is Nachum Dershowitz and Edward M. Reingold, | 544 | resource in this area is Nachum Dershowitz and Edward M. Reingold, | |
388 | <a href="http://emr.cs.iit.edu/home/reingold/calendar-book/third-edition/"> | 545 | <a href="http://emr.cs.iit.edu/home/reingold/calendar-book/third-edition/"> | |
389 | Calendrical Calculations: Third Edition | 546 | Calendrical Calculations: Third Edition | |
390 | </a>, Cambridge University Press (2008). Other information and | 547 | </a>, Cambridge University Press (2008). Other information and | |
391 | sources are given below. They sometimes disagree. | 548 | sources are given below. They sometimes disagree. | |
392 | 549 | |||
393 | 550 | |||
394 | France | 551 | France | |
395 | 552 | |||
396 | Gregorian calendar adopted 1582-12-20. | 553 | Gregorian calendar adopted 1582-12-20. | |
397 | French Revolutionary calendar used 1793-11-24 through 1805-12-31, | 554 | French Revolutionary calendar used 1793-11-24 through 1805-12-31, | |
398 | and (in Paris only) 1871-05-06 through 1871-05-23. | 555 | and (in Paris only) 1871-05-06 through 1871-05-23. | |
399 | 556 | |||
400 | 557 | |||
401 | Russia | 558 | Russia | |
402 | 559 | |||
403 | From Chris Carrier (1996-12-02): | 560 | From Chris Carrier (1996-12-02): | |
404 | On 1929-10-01 the Soviet Union instituted an ``Eternal Calendar'' | 561 | On 1929-10-01 the Soviet Union instituted an "Eternal Calendar" | |
405 | with 30-day months plus 5 holidays, with a 5-day week. | 562 | with 30-day months plus 5 holidays, with a 5-day week. | |
406 | On 1931-12-01 it changed to a 6-day week; in 1934 it reverted to the | 563 | On 1931-12-01 it changed to a 6-day week; in 1934 it reverted to the | |
407 | Gregorian calendar while retaining the 6-day week; on 1940-06-27 it | 564 | Gregorian calendar while retaining the 6-day week; on 1940-06-27 it | |
408 | reverted to the 7-day week. With the 6-day week the usual days | 565 | reverted to the 7-day week. With the 6-day week the usual days | |
409 | off were the 6th, 12th, 18th, 24th and 30th of the month. | 566 | off were the 6th, 12th, 18th, 24th and 30th of the month. | |
410 | (Source: Evitiar Zerubavel, _The Seven Day Circle_) | 567 | (Source: Evitiar Zerubavel, _The Seven Day Circle_) | |
411 | 568 | |||
412 | 569 | |||
413 | Mark Brader reported a similar story in "The Book of Calendars", edited | 570 | Mark Brader reported a similar story in "The Book of Calendars", edited | |
414 | by Frank Parise (1982, Facts on File, ISBN 0-8719-6467-8), page 377. But: | 571 | by Frank Parise (1982, Facts on File, ISBN 0-8719-6467-8), page 377. But: | |
415 | 572 | |||
416 | From: Petteri Sulonen (via Usenet) | 573 | From: Petteri Sulonen (via Usenet) | |
417 | Date: 14 Jan 1999 00:00:00 GMT | 574 | Date: 14 Jan 1999 00:00:00 GMT |
--- src/lib/libc/time/checktab.awk 2012/08/09 12:38:25 1.5
+++ src/lib/libc/time/checktab.awk 2013/09/20 19:06:54 1.6
@@ -1,26 +1,29 @@ | @@ -1,26 +1,29 @@ | |||
1 | # $NetBSD: checktab.awk,v 1.5 2012/08/09 12:38:25 christos Exp $ | 1 | # $NetBSD: checktab.awk,v 1.6 2013/09/20 19:06:54 christos Exp $ | |
2 | 2 | |||
3 | # Check tz tables for consistency. | 3 | # Check tz tables for consistency. | |
4 | 4 | |||
5 | # Contributed by Paul Eggert. | 5 | # Contributed by Paul Eggert. | |
6 | 6 | |||
7 | BEGIN { | 7 | BEGIN { | |
8 | FS = "\t" | 8 | FS = "\t" | |
9 | 9 | |||
10 | if (!iso_table) iso_table = "iso3166.tab" | 10 | if (!iso_table) iso_table = "iso3166.tab" | |
11 | if (!zone_table) zone_table = "zone.tab" | 11 | if (!zone_table) zone_table = "zone.tab" | |
12 | if (!want_warnings) want_warnings = -1 | 12 | if (!want_warnings) want_warnings = -1 | |
13 | 13 | |||
14 | # A special (and we hope temporary) case. | |||
15 | tztab["America/Montreal"] = 1 | |||
16 | ||||
14 | while (getline <iso_table) { | 17 | while (getline <iso_table) { | |
15 | iso_NR++ | 18 | iso_NR++ | |
16 | if ($0 ~ /^#/) continue | 19 | if ($0 ~ /^#/) continue | |
17 | if (NF != 2) { | 20 | if (NF != 2) { | |
18 | printf "%s:%d: wrong number of columns\n", \ | 21 | printf "%s:%d: wrong number of columns\n", \ | |
19 | iso_table, iso_NR >>"/dev/stderr" | 22 | iso_table, iso_NR >>"/dev/stderr" | |
20 | status = 1 | 23 | status = 1 | |
21 | } | 24 | } | |
22 | cc = $1 | 25 | cc = $1 | |
23 | name = $2 | 26 | name = $2 | |
24 | if (cc !~ /^[A-Z][A-Z]$/) { | 27 | if (cc !~ /^[A-Z][A-Z]$/) { | |
25 | printf "%s:%d: invalid country code `%s'\n", \ | 28 | printf "%s:%d: invalid country code `%s'\n", \ | |
26 | iso_table, iso_NR, cc >>"/dev/stderr" | 29 | iso_table, iso_NR, cc >>"/dev/stderr" | |
@@ -61,83 +64,83 @@ BEGIN { | @@ -61,83 +64,83 @@ BEGIN { | |||
61 | zone_table, zone_NR >>"/dev/stderr" | 64 | zone_table, zone_NR >>"/dev/stderr" | |
62 | status = 1 | 65 | status = 1 | |
63 | } | 66 | } | |
64 | cc = $1 | 67 | cc = $1 | |
65 | coordinates = $2 | 68 | coordinates = $2 | |
66 | tz = $3 | 69 | tz = $3 | |
67 | comments = $4 | 70 | comments = $4 | |
68 | if (cc < cc0) { | 71 | if (cc < cc0) { | |
69 | printf "%s:%d: country code `%s' is out of order\n", \ | 72 | printf "%s:%d: country code `%s' is out of order\n", \ | |
70 | zone_table, zone_NR, cc >>"/dev/stderr" | 73 | zone_table, zone_NR, cc >>"/dev/stderr" | |
71 | status = 1 | 74 | status = 1 | |
72 | } | 75 | } | |
73 | cc0 = cc | 76 | cc0 = cc | |
74 | if (tz2cc[tz]) { | 77 | cctz = cc tz | |
75 | printf "%s:%d: %s: duplicate TZ column\n", \ | 78 | cctztab[cctz] = 1 | |
76 | zone_table, zone_NR, tz >>"/dev/stderr" | 79 | tztab[tz] = 1 | |
77 | status = 1 | 80 | tz2comments[cctz] = comments | |
78 | } | |||
79 | tz2cc[tz] = cc | |||
80 | tz2comments[tz] = comments | |||
81 | tz2NR[tz] = zone_NR | 81 | tz2NR[tz] = zone_NR | |
82 | if (cc2name[cc]) { | 82 | if (cc2name[cc]) { | |
83 | cc_used[cc]++ | 83 | cc_used[cc]++ | |
84 | } else { | 84 | } else { | |
85 | printf "%s:%d: %s: unknown country code\n", \ | 85 | printf "%s:%d: %s: unknown country code\n", \ | |
86 | zone_table, zone_NR, cc >>"/dev/stderr" | 86 | zone_table, zone_NR, cc >>"/dev/stderr" | |
87 | status = 1 | 87 | status = 1 | |
88 | } | 88 | } | |
89 | if (coordinates !~ /^[-+][0-9][0-9][0-5][0-9][-+][01][0-9][0-9][0-5][0-9]$/ \ | 89 | if (coordinates !~ /^[-+][0-9][0-9][0-5][0-9][-+][01][0-9][0-9][0-5][0-9]$/ \ | |
90 | && coordinates !~ /^[-+][0-9][0-9][0-5][0-9][0-5][0-9][-+][01][0-9][0-9][0-5][0-9][0-5][0-9]$/) { | 90 | && coordinates !~ /^[-+][0-9][0-9][0-5][0-9][0-5][0-9][-+][01][0-9][0-9][0-5][0-9][0-5][0-9]$/) { | |
91 | printf "%s:%d: %s: invalid coordinates\n", \ | 91 | printf "%s:%d: %s: invalid coordinates\n", \ | |
92 | zone_table, zone_NR, coordinates >>"/dev/stderr" | 92 | zone_table, zone_NR, coordinates >>"/dev/stderr" | |
93 | status = 1 | 93 | status = 1 | |
94 | } | 94 | } | |
95 | } | 95 | } | |
96 | 96 | |||
97 | for (tz in tz2cc) { | 97 | for (cctz in cctztab) { | |
98 | if (cc_used[tz2cc[tz]] == 1) { | 98 | cc = substr (cctz, 1, 2) | |
99 | if (tz2comments[tz]) { | 99 | tz = substr (cctz, 3) | |
100 | if (cc_used[cc] == 1) { | |||
101 | if (tz2comments[cctz]) { | |||
100 | printf "%s:%d: unnecessary comment `%s'\n", \ | 102 | printf "%s:%d: unnecessary comment `%s'\n", \ | |
101 | zone_table, tz2NR[tz], tz2comments[tz] \ | 103 | zone_table, tz2NR[tz], \ | |
104 | tz2comments[cctz] \ | |||
102 | >>"/dev/stderr" | 105 | >>"/dev/stderr" | |
103 | status = 1 | 106 | status = 1 | |
104 | } | 107 | } | |
105 | } else { | 108 | } else { | |
106 | if (!tz2comments[tz]) { | 109 | if (!tz2comments[cctz]) { | |
107 | printf "%s:%d: missing comment\n", \ | 110 | printf "%s:%d: missing comment\n", \ | |
108 | zone_table, tz2NR[tz] >>"/dev/stderr" | 111 | zone_table, tz2NR[tz] >>"/dev/stderr" | |
109 | status = 1 | 112 | status = 1 | |
110 | } | 113 | } | |
111 | } | 114 | } | |
112 | } | 115 | } | |
113 | 116 | |||
114 | FS = " " | 117 | FS = " " | |
115 | } | 118 | } | |
116 | 119 | |||
117 | { | 120 | { | |
118 | tz = "" | 121 | tz = "" | |
119 | if ($1 == "Zone") tz = $2 | 122 | if ($1 == "Zone") tz = $2 | |
120 | if ($1 == "Link") { | 123 | if ($1 == "Link") { | |
121 | # Ignore Link commands if source and destination basenames | 124 | # Ignore Link commands if source and destination basenames | |
122 | # are identical, e.g. Europe/Istanbul versus Asia/Istanbul. | 125 | # are identical, e.g. Europe/Istanbul versus Asia/Istanbul. | |
123 | src = $2 | 126 | src = $2 | |
124 | dst = $3 | 127 | dst = $3 | |
125 | while ((i = index(src, "/"))) src = substr(src, i+1) | 128 | while ((i = index(src, "/"))) src = substr(src, i+1) | |
126 | while ((i = index(dst, "/"))) dst = substr(dst, i+1) | 129 | while ((i = index(dst, "/"))) dst = substr(dst, i+1) | |
127 | if (src != dst) tz = $3 | 130 | if (src != dst) tz = $3 | |
128 | } | 131 | } | |
129 | if (tz && tz ~ /\//) { | 132 | if (tz && tz ~ /\//) { | |
130 | if (!tz2cc[tz]) { | 133 | if (!tztab[tz]) { | |
131 | printf "%s: no data for `%s'\n", zone_table, tz \ | 134 | printf "%s: no data for `%s'\n", zone_table, tz \ | |
132 | >>"/dev/stderr" | 135 | >>"/dev/stderr" | |
133 | status = 1 | 136 | status = 1 | |
134 | } | 137 | } | |
135 | zoneSeen[tz] = 1 | 138 | zoneSeen[tz] = 1 | |
136 | } | 139 | } | |
137 | } | 140 | } | |
138 | 141 | |||
139 | END { | 142 | END { | |
140 | for (tz in tz2cc) { | 143 | for (tz in tz2cc) { | |
141 | if (!zoneSeen[tz]) { | 144 | if (!zoneSeen[tz]) { | |
142 | printf "%s:%d: no Zone table for `%s'\n", \ | 145 | printf "%s:%d: no Zone table for `%s'\n", \ | |
143 | zone_table, tz2NR[tz], tz >>"/dev/stderr" | 146 | zone_table, tz2NR[tz], tz >>"/dev/stderr" |
--- src/lib/libc/time/ctime.3 2013/01/19 11:56:17 1.47
+++ src/lib/libc/time/ctime.3 2013/09/20 19:06:54 1.48
@@ -1,18 +1,18 @@ | @@ -1,18 +1,18 @@ | |||
1 | .\" $NetBSD: ctime.3,v 1.47 2013/01/19 11:56:17 apb Exp $ | 1 | .\" $NetBSD: ctime.3,v 1.48 2013/09/20 19:06:54 christos Exp $ | |
2 | .\" | 2 | .\" | |
3 | .\" XXX: License missing? | 3 | .\" XXX: License missing? | |
4 | .\" | 4 | .\" | |
5 | .Dd January 19, 2013 | 5 | .Dd September 20, 2013 | |
6 | .Dt CTIME 3 | 6 | .Dt CTIME 3 | |
7 | .Os | 7 | .Os | |
8 | .Sh NAME | 8 | .Sh NAME | |
9 | .Nm asctime , | 9 | .Nm asctime , | |
10 | .Nm asctime_r , | 10 | .Nm asctime_r , | |
11 | .Nm ctime , | 11 | .Nm ctime , | |
12 | .Nm ctime_r , | 12 | .Nm ctime_r , | |
13 | .Nm ctime_rz , | 13 | .Nm ctime_rz , | |
14 | .Nm difftime , | 14 | .Nm difftime , | |
15 | .Nm gmtime , | 15 | .Nm gmtime , | |
16 | .Nm gmtime_r , | 16 | .Nm gmtime_r , | |
17 | .Nm localtime , | 17 | .Nm localtime , | |
18 | .Nm localtime_r , | 18 | .Nm localtime_r , | |
@@ -86,38 +86,48 @@ The | @@ -86,38 +86,48 @@ The | |||
86 | .Fn asctime_r | 86 | .Fn asctime_r | |
87 | has the same behavior as | 87 | has the same behavior as | |
88 | .Fn asctime , | 88 | .Fn asctime , | |
89 | but the result is stored to | 89 | but the result is stored to | |
90 | .Fa buf , | 90 | .Fa buf , | |
91 | which should have a size of at least 26 bytes. | 91 | which should have a size of at least 26 bytes. | |
92 | .It Fn ctime "clock" | 92 | .It Fn ctime "clock" | |
93 | The | 93 | The | |
94 | .Fn ctime | 94 | .Fn ctime | |
95 | function converts a | 95 | function converts a | |
96 | .Vt time_t , | 96 | .Vt time_t , | |
97 | pointed to by | 97 | pointed to by | |
98 | .Fa clock , | 98 | .Fa clock , | |
99 | representing the time in seconds since 00:00:00 UTC, 1970-01-01, | |||
100 | and returns a pointer to a string with the format described above. | 99 | and returns a pointer to a string with the format described above. | |
101 | Years requiring fewer than four characters are padded with leading zeroes. | 100 | Years requiring fewer than four characters are padded with leading zeroes. | |
102 | For years longer than four characters, the string is of the form | 101 | For years longer than four characters, the string is of the form | |
103 | .Bd -literal -offset indent | 102 | .Bd -literal -offset indent | |
104 | .D1 "Thu Nov 24 18:22:48 81986\en\e0" | 103 | .D1 "Thu Nov 24 18:22:48 81986\en\e0" | |
105 | .Ed | 104 | .Ed | |
106 | .Pp | 105 | .Pp | |
107 | with five spaces before the year. | 106 | with five spaces before the year. | |
108 | These unusual formats are designed to make it less likely that older | 107 | These unusual formats are designed to make it less likely that older | |
109 | software that expects exactly 26 bytes of output will mistakenly output | 108 | software that expects exactly 26 bytes of output will mistakenly output | |
110 | misleading values for out-of-range years. | 109 | misleading values for out-of-range years. | |
110 | .Pp | |||
111 | The | |||
112 | .Fa clock | |||
113 | time stamp represents the time in seconds since 1970-01-01 00:00:00 | |||
114 | Coordinated Universal Time (UTC). | |||
115 | The POSIX standard says that time stamps must be nonnegative | |||
116 | and must ignore leap seconds. | |||
117 | Many implementations extend POSIX by allowing negative time stamps, | |||
118 | and can therefore represent time stamps that predate the | |||
119 | introduction of UTC and are some other flavor of Universal Time (UT). | |||
120 | Some implementations support leap seconds, in contradiction to POSIX. | |||
111 | .It Fn ctime_r "clock" "buf" | 121 | .It Fn ctime_r "clock" "buf" | |
112 | The | 122 | The | |
113 | .Fn ctime_r | 123 | .Fn ctime_r | |
114 | is similar to | 124 | is similar to | |
115 | .Fn ctime , | 125 | .Fn ctime , | |
116 | except it places the result of the conversion on the | 126 | except it places the result of the conversion on the | |
117 | .Fa buf | 127 | .Fa buf | |
118 | argument, which should be 26 or more bytes long, | 128 | argument, which should be 26 or more bytes long, | |
119 | instead of using a global static buffer. | 129 | instead of using a global static buffer. | |
120 | .It Fn ctime_rz "tz" "clock" "buf" | 130 | .It Fn ctime_rz "tz" "clock" "buf" | |
121 | The | 131 | The | |
122 | .Fn ctime_rz | 132 | .Fn ctime_rz | |
123 | function is similar to | 133 | function is similar to | |
@@ -319,26 +329,68 @@ returns the name for the given | @@ -319,26 +329,68 @@ returns the name for the given | |||
319 | If | 329 | If | |
320 | .Fa isdst | 330 | .Fa isdst | |
321 | is | 331 | is | |
322 | .Va 0 , | 332 | .Va 0 , | |
323 | the call is equivalent to | 333 | the call is equivalent to | |
324 | .Va tzname[0] . | 334 | .Va tzname[0] . | |
325 | If | 335 | If | |
326 | .Fa isdst | 336 | .Fa isdst | |
327 | is set to | 337 | is set to | |
328 | .Va 1 | 338 | .Va 1 | |
329 | the call is equivalent to | 339 | the call is equivalent to | |
330 | .Va tzname[1] . | 340 | .Va tzname[1] . | |
331 | .El | 341 | .El | |
342 | .Pp | |||
343 | Declarations of all the functions and externals, and the | |||
344 | .Ft tm | |||
345 | structure, are in the | |||
346 | .In time.h | |||
347 | header file. | |||
348 | The structure (of type) | |||
349 | .Ft struct tm | |||
350 | includes the following fields: | |||
351 | .Bd -literal | |||
352 | int tm_sec; /* seconds (0 - 60) */ | |||
353 | int tm_min; /* minutes (0 - 59) */ | |||
354 | int tm_hour; /* hours (0 - 23) */ | |||
355 | int tm_mday; /* day of month (1 - 31) */ | |||
356 | int tm_mon; /* month of year (0 - 11) */ | |||
357 | int tm_year; /* year - 1900 */ | |||
358 | int tm_wday; /* day of week (Sunday = 0) */ | |||
359 | int tm_yday; /* day of year (0 - 365) */ | |||
360 | int tm_isdst; /* is summer time in effect? */ | |||
361 | char *tm_zone; /* abbreviation of timezone name */ | |||
362 | long tm_gmtoff; /* offset from UT in seconds */ | |||
363 | .Ed | |||
364 | .Pp | |||
365 | The | |||
366 | .Fa tm_zone | |||
367 | and | |||
368 | .Fa tm_gmtoff | |||
369 | fields exist, and are filled in, only if | |||
370 | arrangements to do so were made when the library containing these functions | |||
371 | was created. | |||
372 | There is no guarantee that these fields will continue to exist in this form | |||
373 | in future releases of this code. | |||
374 | .Bl -bullet | |||
375 | .It | |||
376 | .Va tm_isdst | |||
377 | is non-zero if summer time is in effect. | |||
378 | .It | |||
379 | .Va tm_gmtoff | |||
380 | is the offset (in seconds) of the time represented from UT, | |||
381 | with positive values indicating east of the Prime Meridian. | |||
382 | The field's name is derived from Greenwich Mean Time, a precursor of UT. | |||
383 | .El | |||
332 | .Sh RETURN VALUES | 384 | .Sh RETURN VALUES | |
333 | .Bl -bullet | 385 | .Bl -bullet | |
334 | .It | 386 | .It | |
335 | On success the | 387 | On success the | |
336 | .Fn asctime | 388 | .Fn asctime | |
337 | and | 389 | and | |
338 | .Fn ctime | 390 | .Fn ctime | |
339 | functions return a pointer to a static character buffer, and the | 391 | functions return a pointer to a static character buffer, and the | |
340 | .Fn asctime_r , | 392 | .Fn asctime_r , | |
341 | .Fn ctime_r , | 393 | .Fn ctime_r , | |
342 | and | 394 | and | |
343 | .Fn ctime_rz | 395 | .Fn ctime_rz | |
344 | function return a pointer to the user-supplied buffer. | 396 | function return a pointer to the user-supplied buffer. |
--- src/lib/libc/time/localtime.c 2013/07/30 15:30:37 1.77
+++ src/lib/libc/time/localtime.c 2013/09/20 19:06:54 1.78
@@ -1,49 +1,48 @@ | @@ -1,49 +1,48 @@ | |||
1 | /* $NetBSD: localtime.c,v 1.77 2013/07/30 15:30:37 joerg Exp $ */ | 1 | /* $NetBSD: localtime.c,v 1.78 2013/09/20 19:06:54 christos Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | ** This file is in the public domain, so clarified as of | 4 | ** This file is in the public domain, so clarified as of | |
5 | ** 1996-06-05 by Arthur David Olson. | 5 | ** 1996-06-05 by Arthur David Olson. | |
6 | */ | 6 | */ | |
7 | 7 | |||
8 | #include <sys/cdefs.h> | 8 | #include <sys/cdefs.h> | |
9 | #if defined(LIBC_SCCS) && !defined(lint) | 9 | #if defined(LIBC_SCCS) && !defined(lint) | |
10 | #if 0 | 10 | #if 0 | |
11 | static char elsieid[] = "@(#)localtime.c 8.17"; | 11 | static char elsieid[] = "@(#)localtime.c 8.17"; | |
12 | #else | 12 | #else | |
13 | __RCSID("$NetBSD: localtime.c,v 1.77 2013/07/30 15:30:37 joerg Exp $"); | 13 | __RCSID("$NetBSD: localtime.c,v 1.78 2013/09/20 19:06:54 christos Exp $"); | |
14 | #endif | 14 | #endif | |
15 | #endif /* LIBC_SCCS and not lint */ | 15 | #endif /* LIBC_SCCS and not lint */ | |
16 | 16 | |||
17 | /* | 17 | /* | |
18 | ** Leap second handling from Bradley White. | 18 | ** Leap second handling from Bradley White. | |
19 | ** POSIX-style TZ environment variable handling from Guy Harris. | 19 | ** POSIX-style TZ environment variable handling from Guy Harris. | |
20 | */ | 20 | */ | |
21 | 21 | |||
22 | /*LINTLIBRARY*/ | 22 | /*LINTLIBRARY*/ | |
23 | 23 | |||
24 | #include "namespace.h" | 24 | #include "namespace.h" | |
25 | #include <assert.h> | |||
25 | #include "private.h" | 26 | #include "private.h" | |
26 | #include "tzfile.h" | 27 | #include "tzfile.h" | |
27 | #include "fcntl.h" | 28 | #include "fcntl.h" | |
28 | #include "reentrant.h" | 29 | #include "reentrant.h" | |
29 | 30 | |||
30 | #if defined(__weak_alias) | 31 | #if defined(__weak_alias) | |
31 | __weak_alias(daylight,_daylight) | 32 | __weak_alias(daylight,_daylight) | |
32 | __weak_alias(tzname,_tzname) | 33 | __weak_alias(tzname,_tzname) | |
33 | #endif | 34 | #endif | |
34 | 35 | |||
35 | #include "float.h" /* for FLT_MAX and DBL_MAX */ | |||
36 | ||||
37 | #ifndef TZ_ABBR_MAX_LEN | 36 | #ifndef TZ_ABBR_MAX_LEN | |
38 | #define TZ_ABBR_MAX_LEN 16 | 37 | #define TZ_ABBR_MAX_LEN 16 | |
39 | #endif /* !defined TZ_ABBR_MAX_LEN */ | 38 | #endif /* !defined TZ_ABBR_MAX_LEN */ | |
40 | 39 | |||
41 | #ifndef TZ_ABBR_CHAR_SET | 40 | #ifndef TZ_ABBR_CHAR_SET | |
42 | #define TZ_ABBR_CHAR_SET \ | 41 | #define TZ_ABBR_CHAR_SET \ | |
43 | "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._" | 42 | "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._" | |
44 | #endif /* !defined TZ_ABBR_CHAR_SET */ | 43 | #endif /* !defined TZ_ABBR_CHAR_SET */ | |
45 | 44 | |||
46 | #ifndef TZ_ABBR_ERR_CHAR | 45 | #ifndef TZ_ABBR_ERR_CHAR | |
47 | #define TZ_ABBR_ERR_CHAR '_' | 46 | #define TZ_ABBR_ERR_CHAR '_' | |
48 | #endif /* !defined TZ_ABBR_ERR_CHAR */ | 47 | #endif /* !defined TZ_ABBR_ERR_CHAR */ | |
49 | 48 | |||
@@ -87,31 +86,31 @@ static const char gmt[] = "GMT"; | @@ -87,31 +86,31 @@ static const char gmt[] = "GMT"; | |||
87 | 86 | |||
88 | /* | 87 | /* | |
89 | ** The DST rules to use if TZ has no rules and we can't load TZDEFRULES. | 88 | ** The DST rules to use if TZ has no rules and we can't load TZDEFRULES. | |
90 | ** We default to US rules as of 1999-08-17. | 89 | ** We default to US rules as of 1999-08-17. | |
91 | ** POSIX 1003.1 section 8.1.1 says that the default DST rules are | 90 | ** POSIX 1003.1 section 8.1.1 says that the default DST rules are | |
92 | ** implementation dependent; for historical reasons, US rules are a | 91 | ** implementation dependent; for historical reasons, US rules are a | |
93 | ** common default. | 92 | ** common default. | |
94 | */ | 93 | */ | |
95 | #ifndef TZDEFRULESTRING | 94 | #ifndef TZDEFRULESTRING | |
96 | #define TZDEFRULESTRING ",M4.1.0,M10.5.0" | 95 | #define TZDEFRULESTRING ",M4.1.0,M10.5.0" | |
97 | #endif /* !defined TZDEFDST */ | 96 | #endif /* !defined TZDEFDST */ | |
98 | 97 | |||
99 | struct ttinfo { /* time type information */ | 98 | struct ttinfo { /* time type information */ | |
100 | int_fast32_t tt_gmtoff; /* UTC offset in seconds */ | 99 | int_fast32_t tt_gmtoff; /* UT offset in seconds */ | |
101 | int tt_isdst; /* used to set tm_isdst */ | 100 | int tt_isdst; /* used to set tm_isdst */ | |
102 | int tt_abbrind; /* abbreviation list index */ | 101 | int tt_abbrind; /* abbreviation list index */ | |
103 | int tt_ttisstd; /* TRUE if transition is std time */ | 102 | int tt_ttisstd; /* TRUE if transition is std time */ | |
104 | int tt_ttisgmt; /* TRUE if transition is UTC */ | 103 | int tt_ttisgmt; /* TRUE if transition is UT */ | |
105 | }; | 104 | }; | |
106 | 105 | |||
107 | struct lsinfo { /* leap second information */ | 106 | struct lsinfo { /* leap second information */ | |
108 | time_t ls_trans; /* transition time */ | 107 | time_t ls_trans; /* transition time */ | |
109 | int_fast64_t ls_corr; /* correction to apply */ | 108 | int_fast64_t ls_corr; /* correction to apply */ | |
110 | }; | 109 | }; | |
111 | 110 | |||
112 | #define BIGGEST(a, b) (((a) > (b)) ? (a) : (b)) | 111 | #define BIGGEST(a, b) (((a) > (b)) ? (a) : (b)) | |
113 | 112 | |||
114 | #ifdef TZNAME_MAX | 113 | #ifdef TZNAME_MAX | |
115 | #define MY_TZNAME_MAX TZNAME_MAX | 114 | #define MY_TZNAME_MAX TZNAME_MAX | |
116 | #endif /* defined TZNAME_MAX */ | 115 | #endif /* defined TZNAME_MAX */ | |
117 | #ifndef TZNAME_MAX | 116 | #ifndef TZNAME_MAX | |
@@ -347,29 +346,28 @@ settzname(void) | @@ -347,29 +346,28 @@ settzname(void) | |||
347 | timezone = -(ttisp->tt_gmtoff); | 346 | timezone = -(ttisp->tt_gmtoff); | |
348 | #endif /* defined USG_COMPAT */ | 347 | #endif /* defined USG_COMPAT */ | |
349 | #ifdef ALTZONE | 348 | #ifdef ALTZONE | |
350 | if (ttisp->tt_isdst) | 349 | if (ttisp->tt_isdst) | |
351 | altzone = -(ttisp->tt_gmtoff); | 350 | altzone = -(ttisp->tt_gmtoff); | |
352 | #endif /* defined ALTZONE */ | 351 | #endif /* defined ALTZONE */ | |
353 | } | 352 | } | |
354 | settzname_z(sp); | 353 | settzname_z(sp); | |
355 | } | 354 | } | |
356 | 355 | |||
357 | static int | 356 | static int | |
358 | differ_by_repeat(const time_t t1, const time_t t0) | 357 | differ_by_repeat(const time_t t1, const time_t t0) | |
359 | { | 358 | { | |
360 | if (TYPE_INTEGRAL(time_t) && | 359 | if (TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS) | |
361 | TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS) | 360 | return 0; | |
362 | return 0; | |||
363 | return (int_fast64_t)t1 - (int_fast64_t)t0 == SECSPERREPEAT; | 361 | return (int_fast64_t)t1 - (int_fast64_t)t0 == SECSPERREPEAT; | |
364 | } | 362 | } | |
365 | 363 | |||
366 | static int | 364 | static int | |
367 | tzload(timezone_t sp, const char *name, const int doextend) | 365 | tzload(timezone_t sp, const char *name, const int doextend) | |
368 | { | 366 | { | |
369 | const char * p; | 367 | const char * p; | |
370 | int i; | 368 | int i; | |
371 | int fid; | 369 | int fid; | |
372 | int stored; | 370 | int stored; | |
373 | ssize_t nread; | 371 | ssize_t nread; | |
374 | typedef union { | 372 | typedef union { | |
375 | struct tzhead tzhead; | 373 | struct tzhead tzhead; | |
@@ -556,31 +554,29 @@ tzload(timezone_t sp, const char *name, | @@ -556,31 +554,29 @@ tzload(timezone_t sp, const char *name, | |||
556 | sp->timecnt = j; | 554 | sp->timecnt = j; | |
557 | } | 555 | } | |
558 | break; | 556 | break; | |
559 | } | 557 | } | |
560 | /* | 558 | /* | |
561 | ** If this is an old file, we're done. | 559 | ** If this is an old file, we're done. | |
562 | */ | 560 | */ | |
563 | if (up->tzhead.tzh_version[0] == '\0') | 561 | if (up->tzhead.tzh_version[0] == '\0') | |
564 | break; | 562 | break; | |
565 | nread -= p - up->buf; | 563 | nread -= p - up->buf; | |
566 | for (i = 0; i < nread; ++i) | 564 | for (i = 0; i < nread; ++i) | |
567 | up->buf[i] = p[i]; | 565 | up->buf[i] = p[i]; | |
568 | /* | 566 | /* | |
569 | ** If this is a narrow integer time_t system, we're done. | 567 | ** If this is a narrow time_t system, we're done. | |
570 | */ | 568 | */ | |
571 | if (stored >= (int) sizeof(time_t) | 569 | if (stored >= (int) sizeof(time_t)) | |
572 | /* CONSTCOND */ | |||
573 | && TYPE_INTEGRAL(time_t)) | |||
574 | break; | 570 | break; | |
575 | } | 571 | } | |
576 | if (doextend && nread > 2 && | 572 | if (doextend && nread > 2 && | |
577 | up->buf[0] == '\n' && up->buf[nread - 1] == '\n' && | 573 | up->buf[0] == '\n' && up->buf[nread - 1] == '\n' && | |
578 | sp->typecnt + 2 <= TZ_MAX_TYPES) { | 574 | sp->typecnt + 2 <= TZ_MAX_TYPES) { | |
579 | struct __state ts; | 575 | struct __state ts; | |
580 | int result; | 576 | int result; | |
581 | 577 | |||
582 | up->buf[nread - 1] = '\0'; | 578 | up->buf[nread - 1] = '\0'; | |
583 | result = tzparse(&ts, &up->buf[1], FALSE); | 579 | result = tzparse(&ts, &up->buf[1], FALSE); | |
584 | if (result == 0 && ts.typecnt == 2 && | 580 | if (result == 0 && ts.typecnt == 2 && | |
585 | sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) { | 581 | sp->charcnt + ts.charcnt <= TZ_MAX_CHARS) { | |
586 | for (i = 0; i < 2; ++i) | 582 | for (i = 0; i < 2; ++i) | |
@@ -870,34 +866,34 @@ getrule(const char *strp, struct rule *c | @@ -870,34 +866,34 @@ getrule(const char *strp, struct rule *c | |||
870 | /* | 866 | /* | |
871 | ** Day of year. | 867 | ** Day of year. | |
872 | */ | 868 | */ | |
873 | rulep->r_type = DAY_OF_YEAR; | 869 | rulep->r_type = DAY_OF_YEAR; | |
874 | strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1); | 870 | strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1); | |
875 | } else return NULL; /* invalid format */ | 871 | } else return NULL; /* invalid format */ | |
876 | if (strp == NULL) | 872 | if (strp == NULL) | |
877 | return NULL; | 873 | return NULL; | |
878 | if (*strp == '/') { | 874 | if (*strp == '/') { | |
879 | /* | 875 | /* | |
880 | ** Time specified. | 876 | ** Time specified. | |
881 | */ | 877 | */ | |
882 | ++strp; | 878 | ++strp; | |
883 | strp = getsecs(strp, &rulep->r_time); | 879 | strp = getoffset(strp, &rulep->r_time); | |
884 | } else rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */ | 880 | } else rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */ | |
885 | return strp; | 881 | return strp; | |
886 | } | 882 | } | |
887 | 883 | |||
888 | /* | 884 | /* | |
889 | ** Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the | 885 | ** Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the | |
890 | ** year, a rule, and the offset from UTC at the time that rule takes effect, | 886 | ** year, a rule, and the offset from UT at the time that rule takes effect, | |
891 | ** calculate the Epoch-relative time that rule takes effect. | 887 | ** calculate the Epoch-relative time that rule takes effect. | |
892 | */ | 888 | */ | |
893 | 889 | |||
894 | static time_t | 890 | static time_t | |
895 | transtime(const time_t janfirst, const int year, const struct rule *const rulep, | 891 | transtime(const time_t janfirst, const int year, const struct rule *const rulep, | |
896 | const int_fast32_t offset) | 892 | const int_fast32_t offset) | |
897 | { | 893 | { | |
898 | int leapyear; | 894 | int leapyear; | |
899 | time_t value; | 895 | time_t value; | |
900 | int i; | 896 | int i; | |
901 | int d, m1, yy0, yy1, yy2, dow; | 897 | int d, m1, yy0, yy1, yy2, dow; | |
902 | 898 | |||
903 | INITIALIZE(value); | 899 | INITIALIZE(value); | |
@@ -960,30 +956,30 @@ transtime(const time_t janfirst, const i | @@ -960,30 +956,30 @@ transtime(const time_t janfirst, const i | |||
960 | mon_lengths[leapyear][rulep->r_mon - 1]) | 956 | mon_lengths[leapyear][rulep->r_mon - 1]) | |
961 | break; | 957 | break; | |
962 | d += DAYSPERWEEK; | 958 | d += DAYSPERWEEK; | |
963 | } | 959 | } | |
964 | 960 | |||
965 | /* | 961 | /* | |
966 | ** "d" is the day-of-month (zero-origin) of the day we want. | 962 | ** "d" is the day-of-month (zero-origin) of the day we want. | |
967 | */ | 963 | */ | |
968 | value += (time_t)(d * SECSPERDAY); | 964 | value += (time_t)(d * SECSPERDAY); | |
969 | break; | 965 | break; | |
970 | } | 966 | } | |
971 | 967 | |||
972 | /* | 968 | /* | |
973 | ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in | 969 | ** "value" is the Epoch-relative time of 00:00:00 UT on the day in | |
974 | ** question. To get the Epoch-relative time of the specified local | 970 | ** question. To get the Epoch-relative time of the specified local | |
975 | ** time on that day, add the transition time and the current offset | 971 | ** time on that day, add the transition time and the current offset | |
976 | ** from UTC. | 972 | ** from UT. | |
977 | */ | 973 | */ | |
978 | return (time_t)(value + rulep->r_time + offset); | 974 | return (time_t)(value + rulep->r_time + offset); | |
979 | } | 975 | } | |
980 | 976 | |||
981 | /* | 977 | /* | |
982 | ** Given a POSIX section 8-style TZ string, fill in the rule tables as | 978 | ** Given a POSIX section 8-style TZ string, fill in the rule tables as | |
983 | ** appropriate. | 979 | ** appropriate. | |
984 | */ | 980 | */ | |
985 | 981 | |||
986 | static int | 982 | static int | |
987 | tzparse(timezone_t sp, const char *name, const int lastditch) | 983 | tzparse(timezone_t sp, const char *name, const int lastditch) | |
988 | { | 984 | { | |
989 | const char * stdname; | 985 | const char * stdname; | |
@@ -1040,28 +1036,29 @@ tzparse(timezone_t sp, const char *name, | @@ -1040,28 +1036,29 @@ tzparse(timezone_t sp, const char *name, | |||
1040 | name = getzname(name); | 1036 | name = getzname(name); | |
1041 | dstlen = name - dstname; /* length of DST zone name */ | 1037 | dstlen = name - dstname; /* length of DST zone name */ | |
1042 | } | 1038 | } | |
1043 | if (*name != '\0' && *name != ',' && *name != ';') { | 1039 | if (*name != '\0' && *name != ',' && *name != ';') { | |
1044 | name = getoffset(name, &dstoffset); | 1040 | name = getoffset(name, &dstoffset); | |
1045 | if (name == NULL) | 1041 | if (name == NULL) | |
1046 | return -1; | 1042 | return -1; | |
1047 | } else dstoffset = stdoffset - SECSPERHOUR; | 1043 | } else dstoffset = stdoffset - SECSPERHOUR; | |
1048 | if (*name == '\0' && load_result != 0) | 1044 | if (*name == '\0' && load_result != 0) | |
1049 | name = TZDEFRULESTRING; | 1045 | name = TZDEFRULESTRING; | |
1050 | if (*name == ',' || *name == ';') { | 1046 | if (*name == ',' || *name == ';') { | |
1051 | struct rule start; | 1047 | struct rule start; | |
1052 | struct rule end; | 1048 | struct rule end; | |
1053 | int year; | 1049 | int year; | |
1054 | time_t janfirst; | 1050 | int yearlim; | |
1051 | time_t janfirst; | |||
1055 | time_t starttime; | 1052 | time_t starttime; | |
1056 | time_t endtime; | 1053 | time_t endtime; | |
1057 | 1054 | |||
1058 | ++name; | 1055 | ++name; | |
1059 | if ((name = getrule(name, &start)) == NULL) | 1056 | if ((name = getrule(name, &start)) == NULL) | |
1060 | return -1; | 1057 | return -1; | |
1061 | if (*name++ != ',') | 1058 | if (*name++ != ',') | |
1062 | return -1; | 1059 | return -1; | |
1063 | if ((name = getrule(name, &end)) == NULL) | 1060 | if ((name = getrule(name, &end)) == NULL) | |
1064 | return -1; | 1061 | return -1; | |
1065 | if (*name != '\0') | 1062 | if (*name != '\0') | |
1066 | return -1; | 1063 | return -1; | |
1067 | sp->typecnt = 2; /* standard time and DST */ | 1064 | sp->typecnt = 2; /* standard time and DST */ | |
@@ -1069,54 +1066,64 @@ tzparse(timezone_t sp, const char *name, | @@ -1069,54 +1066,64 @@ tzparse(timezone_t sp, const char *name, | |||
1069 | ** Two transitions per year, from EPOCH_YEAR forward. | 1066 | ** Two transitions per year, from EPOCH_YEAR forward. | |
1070 | */ | 1067 | */ | |
1071 | memset(sp->ttis, 0, sizeof(sp->ttis)); | 1068 | memset(sp->ttis, 0, sizeof(sp->ttis)); | |
1072 | sp->ttis[0].tt_gmtoff = -dstoffset; | 1069 | sp->ttis[0].tt_gmtoff = -dstoffset; | |
1073 | sp->ttis[0].tt_isdst = 1; | 1070 | sp->ttis[0].tt_isdst = 1; | |
1074 | sp->ttis[0].tt_abbrind = (int)(stdlen + 1); | 1071 | sp->ttis[0].tt_abbrind = (int)(stdlen + 1); | |
1075 | sp->ttis[1].tt_gmtoff = -stdoffset; | 1072 | sp->ttis[1].tt_gmtoff = -stdoffset; | |
1076 | sp->ttis[1].tt_isdst = 0; | 1073 | sp->ttis[1].tt_isdst = 0; | |
1077 | sp->ttis[1].tt_abbrind = 0; | 1074 | sp->ttis[1].tt_abbrind = 0; | |
1078 | atp = sp->ats; | 1075 | atp = sp->ats; | |
1079 | typep = sp->types; | 1076 | typep = sp->types; | |
1080 | janfirst = 0; | 1077 | janfirst = 0; | |
1081 | sp->timecnt = 0; | 1078 | sp->timecnt = 0; | |
1082 | for (year = EPOCH_YEAR; | 1079 | yearlim = EPOCH_YEAR + YEARSPERREPEAT; | |
1083 | sp->timecnt + 2 <= TZ_MAX_TIMES; | 1080 | for (year = EPOCH_YEAR; year < yearlim; year++) { | |
1084 | ++year) { | 1081 | int_fast32_t yearsecs; | |
1085 | time_t newfirst; | |||
1086 | 1082 | |||
1087 | starttime = transtime(janfirst, year, &start, | 1083 | starttime = transtime(janfirst, year, &start, | |
1088 | stdoffset); | 1084 | stdoffset); | |
1089 | endtime = transtime(janfirst, year, &end, | 1085 | endtime = transtime(janfirst, year, &end, | |
1090 | dstoffset); | 1086 | dstoffset); | |
1091 | if (starttime > endtime) { | 1087 | yearsecs = (year_lengths[isleap(year)] | |
1092 | *atp++ = endtime; | 1088 | * SECSPERDAY); | |
1093 | *typep++ = 1; /* DST ends */ | 1089 | if (starttime > endtime | |
1094 | *atp++ = starttime; | 1090 | || (starttime < endtime | |
1095 | *typep++ = 0; /* DST begins */ | 1091 | && (endtime - starttime | |
1096 | } else { | 1092 | < (yearsecs | |
1097 | *atp++ = starttime; | 1093 | + (stdoffset - dstoffset))))) { | |
1098 | *typep++ = 0; /* DST begins */ | 1094 | if (&sp->ats[TZ_MAX_TIMES - 2] < atp) | |
1099 | *atp++ = endtime; | 1095 | break; | |
1100 | *typep++ = 1; /* DST ends */ | 1096 | yearlim = year + YEARSPERREPEAT + 1; | |
1097 | if (starttime > endtime) { | |||
1098 | *atp++ = endtime; | |||
1099 | *typep++ = 1; /* DST ends */ | |||
1100 | *atp++ = starttime; | |||
1101 | *typep++ = 0; /* DST begins */ | |||
1102 | } else { | |||
1103 | *atp++ = starttime; | |||
1104 | *typep++ = 0; /* DST begins */ | |||
1105 | *atp++ = endtime; | |||
1106 | *typep++ = 1; /* DST ends */ | |||
1107 | } | |||
1101 | } | 1108 | } | |
1102 | sp->timecnt += 2; | 1109 | if (time_t_max - janfirst < yearsecs) | |
1103 | newfirst = janfirst; | |||
1104 | newfirst += (time_t) | |||
1105 | (year_lengths[isleap(year)] * SECSPERDAY); | |||
1106 | if (newfirst <= janfirst) | |||
1107 | break; | 1110 | break; | |
1108 | janfirst = newfirst; | 1111 | janfirst += yearsecs; | |
1109 | } | 1112 | } | |
1113 | _DIAGASSERT(__type_fit(int, atp - sp->ats)); | |||
1114 | sp->timecnt = (int)(atp - sp->ats); | |||
1115 | if (!sp->timecnt) | |||
1116 | sp->typecnt = 1; /* Perpetual DST. */ | |||
1110 | } else { | 1117 | } else { | |
1111 | int_fast32_t theirstdoffset; | 1118 | int_fast32_t theirstdoffset; | |
1112 | int_fast32_t theirdstoffset; | 1119 | int_fast32_t theirdstoffset; | |
1113 | int_fast32_t theiroffset; | 1120 | int_fast32_t theiroffset; | |
1114 | int isdst; | 1121 | int isdst; | |
1115 | int i; | 1122 | int i; | |
1116 | int j; | 1123 | int j; | |
1117 | 1124 | |||
1118 | if (*name != '\0') | 1125 | if (*name != '\0') | |
1119 | return -1; | 1126 | return -1; | |
1120 | /* | 1127 | /* | |
1121 | ** Initial values of theirstdoffset and theirdstoffset. | 1128 | ** Initial values of theirstdoffset and theirdstoffset. | |
1122 | */ | 1129 | */ | |
@@ -1352,56 +1359,48 @@ tzset(void) | @@ -1352,56 +1359,48 @@ tzset(void) | |||
1352 | static struct tm * | 1359 | static struct tm * | |
1353 | localsub(const timezone_t sp, const time_t * const timep, const int_fast32_t offset, | 1360 | localsub(const timezone_t sp, const time_t * const timep, const int_fast32_t offset, | |
1354 | struct tm *const tmp) | 1361 | struct tm *const tmp) | |
1355 | { | 1362 | { | |
1356 | const struct ttinfo * ttisp; | 1363 | const struct ttinfo * ttisp; | |
1357 | int i; | 1364 | int i; | |
1358 | struct tm * result; | 1365 | struct tm * result; | |
1359 | const time_t t = *timep; | 1366 | const time_t t = *timep; | |
1360 | 1367 | |||
1361 | if ((sp->goback && t < sp->ats[0]) || | 1368 | if ((sp->goback && t < sp->ats[0]) || | |
1362 | (sp->goahead && t > sp->ats[sp->timecnt - 1])) { | 1369 | (sp->goahead && t > sp->ats[sp->timecnt - 1])) { | |
1363 | time_t newt = t; | 1370 | time_t newt = t; | |
1364 | time_t seconds; | 1371 | time_t seconds; | |
1365 | time_t tcycles; | 1372 | time_t years; | |
1366 | int_fast64_t icycles; | |||
1367 | 1373 | |||
1368 | if (t < sp->ats[0]) | 1374 | if (t < sp->ats[0]) | |
1369 | seconds = sp->ats[0] - t; | 1375 | seconds = sp->ats[0] - t; | |
1370 | else seconds = t - sp->ats[sp->timecnt - 1]; | 1376 | else seconds = t - sp->ats[sp->timecnt - 1]; | |
1371 | --seconds; | 1377 | --seconds; | |
1372 | tcycles = (time_t) | 1378 | years = (time_t)((seconds / SECSPERREPEAT + 1) * YEARSPERREPEAT); | |
1373 | (seconds / YEARSPERREPEAT / AVGSECSPERYEAR); | 1379 | seconds = (time_t)(years * AVGSECSPERYEAR); | |
1374 | ++tcycles; | |||
1375 | icycles = tcycles; | |||
1376 | if (tcycles - icycles >= 1 || icycles - tcycles >= 1) | |||
1377 | return NULL; | |||
1378 | seconds = (time_t) icycles; | |||
1379 | seconds *= YEARSPERREPEAT; | |||
1380 | seconds *= AVGSECSPERYEAR; | |||
1381 | if (t < sp->ats[0]) | 1380 | if (t < sp->ats[0]) | |
1382 | newt += seconds; | 1381 | newt += seconds; | |
1383 | else newt -= seconds; | 1382 | else newt -= seconds; | |
1384 | if (newt < sp->ats[0] || | 1383 | if (newt < sp->ats[0] || | |
1385 | newt > sp->ats[sp->timecnt - 1]) | 1384 | newt > sp->ats[sp->timecnt - 1]) | |
1386 | return NULL; /* "cannot happen" */ | 1385 | return NULL; /* "cannot happen" */ | |
1387 | result = localsub(sp, &newt, offset, tmp); | 1386 | result = localsub(sp, &newt, offset, tmp); | |
1388 | if (result == tmp) { | 1387 | if (result == tmp) { | |
1389 | time_t newy; | 1388 | time_t newy; | |
1390 | 1389 | |||
1391 | newy = tmp->tm_year; | 1390 | newy = tmp->tm_year; | |
1392 | if (t < sp->ats[0]) | 1391 | if (t < sp->ats[0]) | |
1393 | newy -= (time_t)icycles * YEARSPERREPEAT; | 1392 | newy -= years; | |
1394 | else newy += (time_t)icycles * YEARSPERREPEAT; | 1393 | else newy += years; | |
1395 | tmp->tm_year = (int)newy; | 1394 | tmp->tm_year = (int)newy; | |
1396 | if (tmp->tm_year != newy) | 1395 | if (tmp->tm_year != newy) | |
1397 | return NULL; | 1396 | return NULL; | |
1398 | } | 1397 | } | |
1399 | return result; | 1398 | return result; | |
1400 | } | 1399 | } | |
1401 | if (sp->timecnt == 0 || t < sp->ats[0]) { | 1400 | if (sp->timecnt == 0 || t < sp->ats[0]) { | |
1402 | i = sp->defaulttype; | 1401 | i = sp->defaulttype; | |
1403 | } else { | 1402 | } else { | |
1404 | int lo = 1; | 1403 | int lo = 1; | |
1405 | int hi = sp->timecnt; | 1404 | int hi = sp->timecnt; | |
1406 | 1405 | |||
1407 | while (lo < hi) { | 1406 | while (lo < hi) { | |
@@ -1480,27 +1479,27 @@ gmtsub(const timezone_t sp, const time_t | @@ -1480,27 +1479,27 @@ gmtsub(const timezone_t sp, const time_t | |||
1480 | int saveerrno; | 1479 | int saveerrno; | |
1481 | gmt_is_set = TRUE; | 1480 | gmt_is_set = TRUE; | |
1482 | saveerrno = errno; | 1481 | saveerrno = errno; | |
1483 | gmtptr = calloc(1, sizeof *gmtptr); | 1482 | gmtptr = calloc(1, sizeof *gmtptr); | |
1484 | errno = saveerrno; | 1483 | errno = saveerrno; | |
1485 | if (gmtptr != NULL) | 1484 | if (gmtptr != NULL) | |
1486 | gmtload(gmtptr); | 1485 | gmtload(gmtptr); | |
1487 | } | 1486 | } | |
1488 | mutex_unlock(&gmt_mutex); | 1487 | mutex_unlock(&gmt_mutex); | |
1489 | result = timesub(gmtptr, timep, offset, tmp); | 1488 | result = timesub(gmtptr, timep, offset, tmp); | |
1490 | #ifdef TM_ZONE | 1489 | #ifdef TM_ZONE | |
1491 | /* | 1490 | /* | |
1492 | ** Could get fancy here and deliver something such as | 1491 | ** Could get fancy here and deliver something such as | |
1493 | ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero, | 1492 | ** "UT+xxxx" or "UT-xxxx" if offset is non-zero, | |
1494 | ** but this is no time for a treasure hunt. | 1493 | ** but this is no time for a treasure hunt. | |
1495 | */ | 1494 | */ | |
1496 | if (offset != 0) | 1495 | if (offset != 0) | |
1497 | tmp->TM_ZONE = (__aconst char *)__UNCONST(wildabbr); | 1496 | tmp->TM_ZONE = (__aconst char *)__UNCONST(wildabbr); | |
1498 | else { | 1497 | else { | |
1499 | if (gmtptr == NULL) | 1498 | if (gmtptr == NULL) | |
1500 | tmp->TM_ZONE = (__aconst char *)__UNCONST(gmt); | 1499 | tmp->TM_ZONE = (__aconst char *)__UNCONST(gmt); | |
1501 | else tmp->TM_ZONE = gmtptr->chars; | 1500 | else tmp->TM_ZONE = gmtptr->chars; | |
1502 | } | 1501 | } | |
1503 | #endif /* defined TM_ZONE */ | 1502 | #endif /* defined TM_ZONE */ | |
1504 | return result; | 1503 | return result; | |
1505 | } | 1504 | } | |
1506 | 1505 | |||
@@ -1617,45 +1616,45 @@ timesub(const timezone_t sp, const time_ | @@ -1617,45 +1616,45 @@ timesub(const timezone_t sp, const time_ | |||
1617 | break; | 1616 | break; | |
1618 | } | 1617 | } | |
1619 | } | 1618 | } | |
1620 | y = EPOCH_YEAR; | 1619 | y = EPOCH_YEAR; | |
1621 | tdays = (time_t)(*timep / SECSPERDAY); | 1620 | tdays = (time_t)(*timep / SECSPERDAY); | |
1622 | rem = (int_fast64_t) (*timep - tdays * SECSPERDAY); | 1621 | rem = (int_fast64_t) (*timep - tdays * SECSPERDAY); | |
1623 | while (tdays < 0 || tdays >= year_lengths[isleap(y)]) { | 1622 | while (tdays < 0 || tdays >= year_lengths[isleap(y)]) { | |
1624 | int newy; | 1623 | int newy; | |
1625 | time_t tdelta; | 1624 | time_t tdelta; | |
1626 | int idelta; | 1625 | int idelta; | |
1627 | int leapdays; | 1626 | int leapdays; | |
1628 | 1627 | |||
1629 | tdelta = tdays / DAYSPERLYEAR; | 1628 | tdelta = tdays / DAYSPERLYEAR; | |
1630 | idelta = (int) tdelta; | 1629 | if (! ((! TYPE_SIGNED(time_t) || INT_MIN <= tdelta) | |
1631 | if (tdelta - idelta >= 1 || idelta - tdelta >= 1) | 1630 | && tdelta <= INT_MAX)) | |
1632 | return NULL; | 1631 | return NULL; | |
1632 | idelta = tdelta; | |||
1633 | if (idelta == 0) | 1633 | if (idelta == 0) | |
1634 | idelta = (tdays < 0) ? -1 : 1; | 1634 | idelta = (tdays < 0) ? -1 : 1; | |
1635 | newy = y; | 1635 | newy = y; | |
1636 | if (increment_overflow(&newy, idelta)) | 1636 | if (increment_overflow(&newy, idelta)) | |
1637 | return NULL; | 1637 | return NULL; | |
1638 | leapdays = leaps_thru_end_of(newy - 1) - | 1638 | leapdays = leaps_thru_end_of(newy - 1) - | |
1639 | leaps_thru_end_of(y - 1); | 1639 | leaps_thru_end_of(y - 1); | |
1640 | tdays -= ((time_t) newy - y) * DAYSPERNYEAR; | 1640 | tdays -= ((time_t) newy - y) * DAYSPERNYEAR; | |
1641 | tdays -= leapdays; | 1641 | tdays -= leapdays; | |
1642 | y = newy; | 1642 | y = newy; | |
1643 | } | 1643 | } | |
1644 | { | 1644 | { | |
1645 | int_fast32_t seconds; | 1645 | int_fast32_t seconds; | |
1646 | const time_t half_second = (time_t)0.5; | |||
1647 | 1646 | |||
1648 | seconds = (int_fast32_t)(tdays * SECSPERDAY + half_second); | 1647 | seconds = (int_fast32_t)(tdays * SECSPERDAY); | |
1649 | tdays = (time_t)(seconds / SECSPERDAY); | 1648 | tdays = (time_t)(seconds / SECSPERDAY); | |
1650 | rem += (int_fast64_t)(seconds - tdays * SECSPERDAY); | 1649 | rem += (int_fast64_t)(seconds - tdays * SECSPERDAY); | |
1651 | } | 1650 | } | |
1652 | /* | 1651 | /* | |
1653 | ** Given the range, we can now fearlessly cast... | 1652 | ** Given the range, we can now fearlessly cast... | |
1654 | */ | 1653 | */ | |
1655 | idays = (int) tdays; | 1654 | idays = (int) tdays; | |
1656 | rem += offset - corr; | 1655 | rem += offset - corr; | |
1657 | while (rem < 0) { | 1656 | while (rem < 0) { | |
1658 | rem += SECSPERDAY; | 1657 | rem += SECSPERDAY; | |
1659 | --idays; | 1658 | --idays; | |
1660 | } | 1659 | } | |
1661 | while (rem >= SECSPERDAY) { | 1660 | while (rem >= SECSPERDAY) { | |
@@ -1809,28 +1808,29 @@ normalize_overflow32(int_fast32_t *const | @@ -1809,28 +1808,29 @@ normalize_overflow32(int_fast32_t *const | |||
1809 | 1808 | |||
1810 | tensdelta = (*unitsptr >= 0) ? | 1809 | tensdelta = (*unitsptr >= 0) ? | |
1811 | (*unitsptr / base) : | 1810 | (*unitsptr / base) : | |
1812 | (-1 - (-1 - *unitsptr) / base); | 1811 | (-1 - (-1 - *unitsptr) / base); | |
1813 | *unitsptr -= tensdelta * base; | 1812 | *unitsptr -= tensdelta * base; | |
1814 | return increment_overflow32(tensptr, tensdelta); | 1813 | return increment_overflow32(tensptr, tensdelta); | |
1815 | } | 1814 | } | |
1816 | 1815 | |||
1817 | static int | 1816 | static int | |
1818 | tmcomp(const struct tm *const atmp, const struct tm *const btmp) | 1817 | tmcomp(const struct tm *const atmp, const struct tm *const btmp) | |
1819 | { | 1818 | { | |
1820 | int result; | 1819 | int result; | |
1821 | 1820 | |||
1822 | if ((result = (atmp->tm_year - btmp->tm_year)) == 0 && | 1821 | if (atmp->tm_year != btmp->tm_year) | |
1823 | (result = (atmp->tm_mon - btmp->tm_mon)) == 0 && | 1822 | return atmp->tm_year < btmp->tm_year ? -1 : 1; | |
1823 | if ((result = (atmp->tm_mon - btmp->tm_mon)) == 0 && | |||
1824 | (result = (atmp->tm_mday - btmp->tm_mday)) == 0 && | 1824 | (result = (atmp->tm_mday - btmp->tm_mday)) == 0 && | |
1825 | (result = (atmp->tm_hour - btmp->tm_hour)) == 0 && | 1825 | (result = (atmp->tm_hour - btmp->tm_hour)) == 0 && | |
1826 | (result = (atmp->tm_min - btmp->tm_min)) == 0) | 1826 | (result = (atmp->tm_min - btmp->tm_min)) == 0) | |
1827 | result = atmp->tm_sec - btmp->tm_sec; | 1827 | result = atmp->tm_sec - btmp->tm_sec; | |
1828 | return result; | 1828 | return result; | |
1829 | } | 1829 | } | |
1830 | 1830 | |||
1831 | static time_t | 1831 | static time_t | |
1832 | time2sub(const timezone_t sp, struct tm *const tmp, subfun_t funcp, | 1832 | time2sub(const timezone_t sp, struct tm *const tmp, subfun_t funcp, | |
1833 | const int_fast32_t offset, int *const okayp, const int do_norm_secs) | 1833 | const int_fast32_t offset, int *const okayp, const int do_norm_secs) | |
1834 | { | 1834 | { | |
1835 | int dir; | 1835 | int dir; | |
1836 | int i, j; | 1836 | int i, j; | |
@@ -1913,68 +1913,59 @@ again: | @@ -1913,68 +1913,59 @@ again: | |||
1913 | saved_seconds = yourtm.tm_sec; | 1913 | saved_seconds = yourtm.tm_sec; | |
1914 | yourtm.tm_sec = SECSPERMIN - 1; | 1914 | yourtm.tm_sec = SECSPERMIN - 1; | |
1915 | } else { | 1915 | } else { | |
1916 | saved_seconds = yourtm.tm_sec; | 1916 | saved_seconds = yourtm.tm_sec; | |
1917 | yourtm.tm_sec = 0; | 1917 | yourtm.tm_sec = 0; | |
1918 | } | 1918 | } | |
1919 | /* | 1919 | /* | |
1920 | ** Do a binary search (this works whatever time_t's type is). | 1920 | ** Do a binary search (this works whatever time_t's type is). | |
1921 | */ | 1921 | */ | |
1922 | /* LINTED const not */ | 1922 | /* LINTED const not */ | |
1923 | if (!TYPE_SIGNED(time_t)) { | 1923 | if (!TYPE_SIGNED(time_t)) { | |
1924 | lo = 0; | 1924 | lo = 0; | |
1925 | hi = lo - 1; | 1925 | hi = lo - 1; | |
1926 | /* LINTED const not */ | |||
1927 | } else if (!TYPE_INTEGRAL(time_t)) { | |||
1928 | /* CONSTCOND */ | |||
1929 | if (sizeof(time_t) > sizeof(float)) | |||
1930 | /* LINTED assumed double */ | |||
1931 | hi = (time_t) DBL_MAX; | |||
1932 | /* LINTED assumed float */ | |||
1933 | else hi = (time_t) FLT_MAX; | |||
1934 | lo = -hi; | |||
1935 | } else { | 1926 | } else { | |
1936 | lo = 1; | 1927 | lo = 1; | |
1937 | for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i) | 1928 | for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i) | |
1938 | lo *= 2; | 1929 | lo *= 2; | |
1939 | hi = -(lo + 1); | 1930 | hi = -(lo + 1); | |
1940 | } | 1931 | } | |
1941 | #ifdef NO_ERROR_IN_DST_GAP | 1932 | #ifdef NO_ERROR_IN_DST_GAP | |
1942 | ilo = lo; | 1933 | ilo = lo; | |
1943 | #endif | 1934 | #endif | |
1944 | for ( ; ; ) { | 1935 | for ( ; ; ) { | |
1945 | t = lo / 2 + hi / 2; | 1936 | t = lo / 2 + hi / 2; | |
1946 | if (t < lo) | 1937 | if (t < lo) | |
1947 | t = lo; | 1938 | t = lo; | |
1948 | else if (t > hi) | 1939 | else if (t > hi) | |
1949 | t = hi; | 1940 | t = hi; | |
1950 | if ((*funcp)(sp, &t, offset, &mytm) == NULL) { | 1941 | if ((*funcp)(sp, &t, offset, &mytm) == NULL) { | |
1951 | /* | 1942 | /* | |
1952 | ** Assume that t is too extreme to be represented in | 1943 | ** Assume that t is too extreme to be represented in | |
1953 | ** a struct tm; arrange things so that it is less | 1944 | ** a struct tm; arrange things so that it is less | |
1954 | ** extreme on the next pass. | 1945 | ** extreme on the next pass. | |
1955 | */ | 1946 | */ | |
1956 | dir = (t > 0) ? 1 : -1; | 1947 | dir = (t > 0) ? 1 : -1; | |
1957 | } else dir = tmcomp(&mytm, &yourtm); | 1948 | } else dir = tmcomp(&mytm, &yourtm); | |
1958 | if (dir != 0) { | 1949 | if (dir != 0) { | |
1959 | if (t == lo) { | 1950 | if (t == lo) { | |
1960 | ++t; | 1951 | if (t == time_t_max) | |
1961 | if (t <= lo) | |||
1962 | goto overflow; | 1952 | goto overflow; | |
1953 | ++t; | |||
1963 | ++lo; | 1954 | ++lo; | |
1964 | } else if (t == hi) { | 1955 | } else if (t == hi) { | |
1965 | --t; | 1956 | if (t == time_t_min) | |
1966 | if (t >= hi) | |||
1967 | goto overflow; | 1957 | goto overflow; | |
1958 | --t; | |||
1968 | --hi; | 1959 | --hi; | |
1969 | } | 1960 | } | |
1970 | #ifdef NO_ERROR_IN_DST_GAP | 1961 | #ifdef NO_ERROR_IN_DST_GAP | |
1971 | if (ilo != lo && lo - 1 == hi && yourtm.tm_isdst < 0 && | 1962 | if (ilo != lo && lo - 1 == hi && yourtm.tm_isdst < 0 && | |
1972 | do_norm_secs) { | 1963 | do_norm_secs) { | |
1973 | for (i = sp->typecnt - 1; i >= 0; --i) { | 1964 | for (i = sp->typecnt - 1; i >= 0; --i) { | |
1974 | for (j = sp->typecnt - 1; j >= 0; --j) { | 1965 | for (j = sp->typecnt - 1; j >= 0; --j) { | |
1975 | time_t off; | 1966 | time_t off; | |
1976 | if (sp->ttis[j].tt_isdst == | 1967 | if (sp->ttis[j].tt_isdst == | |
1977 | sp->ttis[i].tt_isdst) | 1968 | sp->ttis[i].tt_isdst) | |
1978 | continue; | 1969 | continue; | |
1979 | off = sp->ttis[j].tt_gmtoff - | 1970 | off = sp->ttis[j].tt_gmtoff - | |
1980 | sp->ttis[i].tt_gmtoff; | 1971 | sp->ttis[i].tt_gmtoff; | |
@@ -2198,27 +2189,27 @@ timeoff(struct tm *const tmp, long offse | @@ -2198,27 +2189,27 @@ timeoff(struct tm *const tmp, long offse | |||
2198 | t = time1(gmtptr, tmp, gmtsub, (int_fast32_t)offset); | 2189 | t = time1(gmtptr, tmp, gmtsub, (int_fast32_t)offset); | |
2199 | return t; | 2190 | return t; | |
2200 | } | 2191 | } | |
2201 | 2192 | |||
2202 | #endif /* defined STD_INSPIRED */ | 2193 | #endif /* defined STD_INSPIRED */ | |
2203 | 2194 | |||
2204 | #ifdef CMUCS | 2195 | #ifdef CMUCS | |
2205 | 2196 | |||
2206 | /* | 2197 | /* | |
2207 | ** The following is supplied for compatibility with | 2198 | ** The following is supplied for compatibility with | |
2208 | ** previous versions of the CMUCS runtime library. | 2199 | ** previous versions of the CMUCS runtime library. | |
2209 | */ | 2200 | */ | |
2210 | 2201 | |||
2211 | int_fast32_t | 2202 | long | |
2212 | gtime(struct tm *const tmp) | 2203 | gtime(struct tm *const tmp) | |
2213 | { | 2204 | { | |
2214 | const time_t t = mktime(tmp); | 2205 | const time_t t = mktime(tmp); | |
2215 | 2206 | |||
2216 | if (t == WRONG) | 2207 | if (t == WRONG) | |
2217 | return -1; | 2208 | return -1; | |
2218 | return t; | 2209 | return t; | |
2219 | } | 2210 | } | |
2220 | 2211 | |||
2221 | #endif /* defined CMUCS */ | 2212 | #endif /* defined CMUCS */ | |
2222 | 2213 | |||
2223 | /* | 2214 | /* | |
2224 | ** XXX--is the below the right way to conditionalize?? | 2215 | ** XXX--is the below the right way to conditionalize?? |
--- src/lib/libc/time/private.h 2013/07/17 20:13:04 1.29
+++ src/lib/libc/time/private.h 2013/09/20 19:06:54 1.30
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: private.h,v 1.29 2013/07/17 20:13:04 christos Exp $ */ | 1 | /* $NetBSD: private.h,v 1.30 2013/09/20 19:06:54 christos Exp $ */ | |
2 | 2 | |||
3 | #ifndef PRIVATE_H | 3 | #ifndef PRIVATE_H | |
4 | #define PRIVATE_H | 4 | #define PRIVATE_H | |
5 | 5 | |||
6 | /* NetBSD defaults */ | 6 | /* NetBSD defaults */ | |
7 | #define TM_GMTOFF tm_gmtoff | 7 | #define TM_GMTOFF tm_gmtoff | |
8 | #define TM_ZONE tm_zone | 8 | #define TM_ZONE tm_zone | |
9 | #define STD_INSPIRED 1 | 9 | #define STD_INSPIRED 1 | |
10 | #define HAVE_LONG_DOUBLE 1 | 10 | #define HAVE_LONG_DOUBLE 1 | |
11 | 11 | |||
12 | /* For when we build zic as a host tool. */ | 12 | /* For when we build zic as a host tool. */ | |
13 | #if HAVE_NBTOOL_CONFIG_H | 13 | #if HAVE_NBTOOL_CONFIG_H | |
14 | #include "nbtool_config.h" | 14 | #include "nbtool_config.h" | |
@@ -168,56 +168,69 @@ typedef long int_fast64_t; | @@ -168,56 +168,69 @@ typedef long int_fast64_t; | |||
168 | #endif /* !defined INT_FAST64_MAX */ | 168 | #endif /* !defined INT_FAST64_MAX */ | |
169 | 169 | |||
170 | #ifndef INT_FAST32_MAX | 170 | #ifndef INT_FAST32_MAX | |
171 | # if INT_MAX >> 31 == 0 | 171 | # if INT_MAX >> 31 == 0 | |
172 | typedef long int_fast32_t; | 172 | typedef long int_fast32_t; | |
173 | # else | 173 | # else | |
174 | typedef int int_fast32_t; | 174 | typedef int int_fast32_t; | |
175 | # endif | 175 | # endif | |
176 | #endif | 176 | #endif | |
177 | 177 | |||
178 | #ifndef INTMAX_MAX | 178 | #ifndef INTMAX_MAX | |
179 | # if defined LLONG_MAX || defined __LONG_LONG_MAX__ | 179 | # if defined LLONG_MAX || defined __LONG_LONG_MAX__ | |
180 | typedef long long intmax_t; | 180 | typedef long long intmax_t; | |
181 | # define strtoimax strtoll | |||
181 | # define PRIdMAX "lld" | 182 | # define PRIdMAX "lld" | |
183 | # ifdef LLONG_MAX | |||
184 | # define INTMAX_MAX LLONG_MAX | |||
185 | # define INTMAX_MIN LLONG_MIN | |||
186 | # else | |||
187 | # define INTMAX_MAX __LONG_LONG_MAX__ | |||
188 | # define INTMAX_MIN __LONG_LONG_MIN__ | |||
189 | # endif | |||
182 | # else | 190 | # else | |
183 | typedef long intmax_t; | 191 | typedef long intmax_t; | |
192 | # define strtoimax strtol | |||
184 | # define PRIdMAX "ld" | 193 | # define PRIdMAX "ld" | |
194 | # define INTMAX_MAX LONG_MAX | |||
195 | # define INTMAX_MIN LONG_MIN | |||
185 | # endif | 196 | # endif | |
186 | #endif | 197 | #endif | |
187 | 198 | |||
188 | #ifndef UINTMAX_MAX | 199 | #ifndef UINTMAX_MAX | |
189 | # if defined ULLONG_MAX || defined __LONG_LONG_MAX__ | 200 | # if defined ULLONG_MAX || defined __LONG_LONG_MAX__ | |
190 | typedef unsigned long long uintmax_t; | 201 | typedef unsigned long long uintmax_t; | |
191 | # define PRIuMAX "llu" | 202 | # define PRIuMAX "llu" | |
192 | # else | 203 | # else | |
193 | typedef unsigned long uintmax_t; | 204 | typedef unsigned long uintmax_t; | |
194 | # define PRIuMAX "lu" | 205 | # define PRIuMAX "lu" | |
195 | # endif | 206 | # endif | |
196 | #endif | 207 | #endif | |
197 | 208 | |||
198 | #ifndef INT32_MAX | 209 | #ifndef INT32_MAX | |
199 | #define INT32_MAX 0x7fffffff | 210 | #define INT32_MAX 0x7fffffff | |
200 | #endif /* !defined INT32_MAX */ | 211 | #endif /* !defined INT32_MAX */ | |
201 | #ifndef INT32_MIN | 212 | #ifndef INT32_MIN | |
202 | #define INT32_MIN (-1 - INT32_MAX) | 213 | #define INT32_MIN (-1 - INT32_MAX) | |
203 | #endif /* !defined INT32_MIN */ | 214 | #endif /* !defined INT32_MIN */ | |
204 | 215 | |||
205 | #if 2 < __GNUC__ + (96 <= __GNUC_MINOR__) | 216 | #if 2 < __GNUC__ + (96 <= __GNUC_MINOR__) | |
206 | # define ATTRIBUTE_CONST __attribute__ ((__const__)) | 217 | # define ATTRIBUTE_CONST __attribute__ ((__const__)) | |
207 | # define ATTRIBUTE_PURE __attribute__ ((__pure__)) | 218 | # define ATTRIBUTE_PURE __attribute__ ((__pure__)) | |
219 | # define ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec)) | |||
208 | #else | 220 | #else | |
209 | # define ATTRIBUTE_CONST /* empty */ | 221 | # define ATTRIBUTE_CONST /* empty */ | |
210 | # define ATTRIBUTE_PURE /* empty */ | 222 | # define ATTRIBUTE_PURE /* empty */ | |
223 | # define ATTRIBUTE_FORMAT(spec) /* empty */ | |||
211 | #endif | 224 | #endif | |
212 | 225 | |||
213 | #if !defined _Noreturn && __STDC_VERSION__ < 201112 | 226 | #if !defined _Noreturn && __STDC_VERSION__ < 201112 | |
214 | # if 2 < __GNUC__ + (8 <= __GNUC_MINOR__) | 227 | # if 2 < __GNUC__ + (8 <= __GNUC_MINOR__) | |
215 | # define _Noreturn __attribute__ ((__noreturn__)) | 228 | # define _Noreturn __attribute__ ((__noreturn__)) | |
216 | # else | 229 | # else | |
217 | # define _Noreturn | 230 | # define _Noreturn | |
218 | # endif | 231 | # endif | |
219 | #endif | 232 | #endif | |
220 | 233 | |||
221 | #if __STDC_VERSION__ < 199901 && !defined restrict | 234 | #if __STDC_VERSION__ < 199901 && !defined restrict | |
222 | # define restrict /* empty */ | 235 | # define restrict /* empty */ | |
223 | #endif | 236 | #endif | |
@@ -306,34 +319,36 @@ const char * scheck(const char * string, | @@ -306,34 +319,36 @@ const char * scheck(const char * string, | |||
306 | 319 | |||
307 | #ifndef FALSE | 320 | #ifndef FALSE | |
308 | #define FALSE 0 | 321 | #define FALSE 0 | |
309 | #endif /* !defined FALSE */ | 322 | #endif /* !defined FALSE */ | |
310 | 323 | |||
311 | #ifndef TYPE_BIT | 324 | #ifndef TYPE_BIT | |
312 | #define TYPE_BIT(type) (sizeof (type) * CHAR_BIT) | 325 | #define TYPE_BIT(type) (sizeof (type) * CHAR_BIT) | |
313 | #endif /* !defined TYPE_BIT */ | 326 | #endif /* !defined TYPE_BIT */ | |
314 | 327 | |||
315 | #ifndef TYPE_SIGNED | 328 | #ifndef TYPE_SIGNED | |
316 | #define TYPE_SIGNED(type) (/*CONSTCOND*/((type) -1) < 0) | 329 | #define TYPE_SIGNED(type) (/*CONSTCOND*/((type) -1) < 0) | |
317 | #endif /* !defined TYPE_SIGNED */ | 330 | #endif /* !defined TYPE_SIGNED */ | |
318 | 331 | |||
319 | /* | 332 | /* The minimum and maximum finite time values. */ | |
320 | ** Since the definition of TYPE_INTEGRAL contains floating point numbers, | 333 | static time_t const time_t_min = | |
321 | ** it cannot be used in preprocessor directives. | 334 | (TYPE_SIGNED(time_t) | |
322 | */ | 335 | ? (time_t) -1 << (int)(CHAR_BIT * sizeof (time_t) - 1) | |
323 | 336 | /*###336 [lint] warning semantics of 'p << p' change in ANSI C; use explicit cast [118]%%%*/ | ||
324 | #ifndef TYPE_INTEGRAL | 337 | : 0); | |
325 | #define TYPE_INTEGRAL(type) (/*CONSTCOND*/((type) 0.5) != 0.5) | 338 | static time_t const time_t_max = | |
326 | #endif /* !defined TYPE_INTEGRAL */ | 339 | (TYPE_SIGNED(time_t) | |
340 | ? - (~ 0 < 0) - ((time_t) -1 << (int)(CHAR_BIT * sizeof (time_t) - 1)) | |||
341 | : -1); | |||
327 | 342 | |||
328 | #ifndef INT_STRLEN_MAXIMUM | 343 | #ifndef INT_STRLEN_MAXIMUM | |
329 | /* | 344 | /* | |
330 | ** 302 / 1000 is log10(2.0) rounded up. | 345 | ** 302 / 1000 is log10(2.0) rounded up. | |
331 | ** Subtract one for the sign bit if the type is signed; | 346 | ** Subtract one for the sign bit if the type is signed; | |
332 | ** add one for integer division truncation; | 347 | ** add one for integer division truncation; | |
333 | ** add one more for a minus sign if the type is signed. | 348 | ** add one more for a minus sign if the type is signed. | |
334 | */ | 349 | */ | |
335 | #define INT_STRLEN_MAXIMUM(type) \ | 350 | #define INT_STRLEN_MAXIMUM(type) \ | |
336 | ((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + \ | 351 | ((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + \ | |
337 | 1 + TYPE_SIGNED(type)) | 352 | 1 + TYPE_SIGNED(type)) | |
338 | #endif /* !defined INT_STRLEN_MAXIMUM */ | 353 | #endif /* !defined INT_STRLEN_MAXIMUM */ | |
339 | 354 |
--- src/lib/libc/time/strftime.3 2012/04/06 11:35:39 1.29
+++ src/lib/libc/time/strftime.3 2013/09/20 19:06:54 1.30
@@ -20,27 +20,27 @@ | @@ -20,27 +20,27 @@ | |||
20 | .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | 20 | .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
21 | .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 21 | .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
22 | .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 22 | .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
23 | .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | 23 | .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
24 | .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 24 | .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
25 | .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 25 | .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
26 | .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 26 | .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
27 | .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 27 | .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
28 | .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 28 | .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
29 | .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 29 | .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
30 | .\" SUCH DAMAGE. | 30 | .\" SUCH DAMAGE. | |
31 | .\" | 31 | .\" | |
32 | .\" from: @(#)strftime.3 5.12 (Berkeley) 6/29/91 | 32 | .\" from: @(#)strftime.3 5.12 (Berkeley) 6/29/91 | |
33 | .\" $NetBSD: strftime.3,v 1.29 2012/04/06 11:35:39 wiz Exp $ | 33 | .\" $NetBSD: strftime.3,v 1.30 2013/09/20 19:06:54 christos Exp $ | |
34 | .\" | 34 | .\" | |
35 | .Dd April 14, 2011 | 35 | .Dd April 14, 2011 | |
36 | .Dt STRFTIME 3 | 36 | .Dt STRFTIME 3 | |
37 | .Os | 37 | .Os | |
38 | .Sh NAME | 38 | .Sh NAME | |
39 | .Nm strftime , | 39 | .Nm strftime , | |
40 | .Nm strftime_z | 40 | .Nm strftime_z | |
41 | .Nd format date and time | 41 | .Nd format date and time | |
42 | .Sh LIBRARY | 42 | .Sh LIBRARY | |
43 | .Lb libc | 43 | .Lb libc | |
44 | .Sh SYNOPSIS | 44 | .Sh SYNOPSIS | |
45 | .In time.h | 45 | .In time.h | |
46 | .Ft size_t | 46 | .Ft size_t | |
@@ -139,28 +139,28 @@ or | @@ -139,28 +139,28 @@ or | |||
139 | .Dq Tn PM . | 139 | .Dq Tn PM . | |
140 | .It Cm \&%R | 140 | .It Cm \&%R | |
141 | is replaced by the time in the format | 141 | is replaced by the time in the format | |
142 | .Dq Li %H:%M . | 142 | .Dq Li %H:%M . | |
143 | .It Cm \&%r | 143 | .It Cm \&%r | |
144 | is replaced by the locale's representation of 12-hour clock time | 144 | is replaced by the locale's representation of 12-hour clock time | |
145 | using AM/PM notation. | 145 | using AM/PM notation. | |
146 | .It Cm \&%S | 146 | .It Cm \&%S | |
147 | is replaced by the second as a decimal number [00,61]. | 147 | is replaced by the second as a decimal number [00,61]. | |
148 | The range of | 148 | The range of | |
149 | seconds is (00-61) instead of (00-59) to allow for the periodic occurrence | 149 | seconds is (00-61) instead of (00-59) to allow for the periodic occurrence | |
150 | of leap seconds and double leap seconds. | 150 | of leap seconds and double leap seconds. | |
151 | .It Cm %s | 151 | .It Cm %s | |
152 | is replaced by the number of seconds since the Epoch, UTC (see | 152 | is replaced by the number of seconds since the Epoch (see | |
153 | .Xr mktime 3 ) . | 153 | .Xr ctime 3 ) . | |
154 | .It Cm \&%T | 154 | .It Cm \&%T | |
155 | is replaced by the time in the format | 155 | is replaced by the time in the format | |
156 | .Dq Li %H:%M:%S . | 156 | .Dq Li %H:%M:%S . | |
157 | .It Cm \&%t | 157 | .It Cm \&%t | |
158 | is replaced by a tab. | 158 | is replaced by a tab. | |
159 | .It Cm \&%U | 159 | .It Cm \&%U | |
160 | is replaced by the week number of the year (Sunday as the first day of | 160 | is replaced by the week number of the year (Sunday as the first day of | |
161 | the week) as a decimal number [00,53]. | 161 | the week) as a decimal number [00,53]. | |
162 | .It Cm \&%u | 162 | .It Cm \&%u | |
163 | is replaced by the weekday (Monday as the first day of the week) | 163 | is replaced by the weekday (Monday as the first day of the week) | |
164 | as a decimal number [1,7]. | 164 | as a decimal number [1,7]. | |
165 | .It Cm \&%V | 165 | .It Cm \&%V | |
166 | is replaced by the week number of the year (Monday as the first day of | 166 | is replaced by the week number of the year (Monday as the first day of | |
@@ -180,27 +180,30 @@ the week) as a decimal number [00,53]. | @@ -180,27 +180,30 @@ the week) as a decimal number [00,53]. | |||
180 | is replaced by the weekday (Sunday as the first day of the week) | 180 | is replaced by the weekday (Sunday as the first day of the week) | |
181 | as a decimal number [0,6]. | 181 | as a decimal number [0,6]. | |
182 | .It Cm \&%X | 182 | .It Cm \&%X | |
183 | is replaced by the locale's appropriate time representation. | 183 | is replaced by the locale's appropriate time representation. | |
184 | .It Cm \&%x | 184 | .It Cm \&%x | |
185 | is replaced by the locale's appropriate date representation. | 185 | is replaced by the locale's appropriate date representation. | |
186 | .It Cm \&%Y | 186 | .It Cm \&%Y | |
187 | is replaced by the year with century as a decimal number. | 187 | is replaced by the year with century as a decimal number. | |
188 | .It Cm \&%y | 188 | .It Cm \&%y | |
189 | is replaced by the year without century as a decimal number [00,99]. | 189 | is replaced by the year without century as a decimal number [00,99]. | |
190 | .It Cm \&%Z | 190 | .It Cm \&%Z | |
191 | is replaced by the time zone name. | 191 | is replaced by the time zone name. | |
192 | .It Cm \&%z | 192 | .It Cm \&%z | |
193 | is replaced by the offset from UTC in the ISO 8601 format | 193 | is replaced by the offset from the Prime Meridian in the format | |
194 | +HHMM or -HHMM (ISO 8601) as appropriate, with positive values representing | |||
195 | locations east of Greenwich, or by the empty string if this is | |||
196 | not determinable. | |||
194 | .Dq Li [-]hhmm . | 197 | .Dq Li [-]hhmm . | |
195 | .It Cm %% | 198 | .It Cm %% | |
196 | is replaced by | 199 | is replaced by | |
197 | .Ql % . | 200 | .Ql % . | |
198 | .El | 201 | .El | |
199 | .Pp | 202 | .Pp | |
200 | The | 203 | The | |
201 | .Fn strftime_z | 204 | .Fn strftime_z | |
202 | function is similar to | 205 | function is similar to | |
203 | .Fn strftime , | 206 | .Fn strftime , | |
204 | but it also takes a | 207 | but it also takes a | |
205 | .Ft "const timezone_t" | 208 | .Ft "const timezone_t" | |
206 | .Fa tz | 209 | .Fa tz |
--- src/lib/libc/time/strftime.c 2013/07/17 23:09:26 1.28
+++ src/lib/libc/time/strftime.c 2013/09/20 19:06:54 1.29
@@ -1,22 +1,22 @@ | @@ -1,22 +1,22 @@ | |||
1 | /* $NetBSD: strftime.c,v 1.28 2013/07/17 23:09:26 christos Exp $ */ | 1 | /* $NetBSD: strftime.c,v 1.29 2013/09/20 19:06:54 christos Exp $ */ | |
2 | 2 | |||
3 | #include <sys/cdefs.h> | 3 | #include <sys/cdefs.h> | |
4 | #if defined(LIBC_SCCS) && !defined(lint) | 4 | #if defined(LIBC_SCCS) && !defined(lint) | |
5 | #if 0 | 5 | #if 0 | |
6 | static char elsieid[] = "@(#)strftime.c 7.64"; | 6 | static char elsieid[] = "@(#)strftime.c 7.64"; | |
7 | static char elsieid[] = "@(#)strftime.c 8.3"; | 7 | static char elsieid[] = "@(#)strftime.c 8.3"; | |
8 | #else | 8 | #else | |
9 | __RCSID("$NetBSD: strftime.c,v 1.28 2013/07/17 23:09:26 christos Exp $"); | 9 | __RCSID("$NetBSD: strftime.c,v 1.29 2013/09/20 19:06:54 christos Exp $"); | |
10 | #endif | 10 | #endif | |
11 | #endif /* LIBC_SCCS and not lint */ | 11 | #endif /* LIBC_SCCS and not lint */ | |
12 | 12 | |||
13 | #include "namespace.h" | 13 | #include "namespace.h" | |
14 | 14 | |||
15 | #include <stddef.h> | 15 | #include <stddef.h> | |
16 | #include <locale.h> | 16 | #include <locale.h> | |
17 | #include "setlocale_local.h" | 17 | #include "setlocale_local.h" | |
18 | 18 | |||
19 | /* | 19 | /* | |
20 | ** Based on the UCB version with the copyright notice and sccsid | 20 | ** Based on the UCB version with the copyright notice and sccsid | |
21 | ** appearing below. | 21 | ** appearing below. | |
22 | ** | 22 | ** | |
@@ -494,27 +494,27 @@ label: | @@ -494,27 +494,27 @@ label: | |||
494 | */ | 494 | */ | |
495 | continue; | 495 | continue; | |
496 | case 'z': | 496 | case 'z': | |
497 | { | 497 | { | |
498 | int diff; | 498 | int diff; | |
499 | char const * sign; | 499 | char const * sign; | |
500 | 500 | |||
501 | if (t->tm_isdst < 0) | 501 | if (t->tm_isdst < 0) | |
502 | continue; | 502 | continue; | |
503 | #ifdef TM_GMTOFF | 503 | #ifdef TM_GMTOFF | |
504 | diff = (int)t->TM_GMTOFF; | 504 | diff = (int)t->TM_GMTOFF; | |
505 | #else /* !defined TM_GMTOFF */ | 505 | #else /* !defined TM_GMTOFF */ | |
506 | /* | 506 | /* | |
507 | ** C99 says that the UTC offset must | 507 | ** C99 says that the UT offset must | |
508 | ** be computed by looking only at | 508 | ** be computed by looking only at | |
509 | ** tm_isdst. This requirement is | 509 | ** tm_isdst. This requirement is | |
510 | ** incorrect, since it means the code | 510 | ** incorrect, since it means the code | |
511 | ** must rely on magic (in this case | 511 | ** must rely on magic (in this case | |
512 | ** altzone and timezone), and the | 512 | ** altzone and timezone), and the | |
513 | ** magic might not have the correct | 513 | ** magic might not have the correct | |
514 | ** offset. Doing things correctly is | 514 | ** offset. Doing things correctly is | |
515 | ** tricky and requires disobeying C99; | 515 | ** tricky and requires disobeying C99; | |
516 | ** see GNU C strftime for details. | 516 | ** see GNU C strftime for details. | |
517 | ** For now, punt and conform to the | 517 | ** For now, punt and conform to the | |
518 | ** standard, even though it's incorrect. | 518 | ** standard, even though it's incorrect. | |
519 | ** | 519 | ** | |
520 | ** C99 says that %z must be replaced by the | 520 | ** C99 says that %z must be replaced by the |
--- src/lib/libc/time/Attic/tz-link.htm 2013/07/17 20:13:04 1.11
+++ src/lib/libc/time/Attic/tz-link.htm 2013/09/20 19:06:54 1.12
@@ -1,24 +1,24 @@ | @@ -1,24 +1,24 @@ | |||
1 | <!DOCTYPE html | 1 | <!DOCTYPE html | |
2 | PUBLIC "-//W3C//DTD HTML 4.01//EN" | 2 | PUBLIC "-//W3C//DTD HTML 4.01//EN" | |
3 | "http://www.w3.org/TR/html4/strict.dtd"> | 3 | "http://www.w3.org/TR/html4/strict.dtd"> | |
4 | <html> | 4 | <html> | |
5 | <head> | 5 | <head> | |
6 | <title>Sources for Time Zone and Daylight Saving Time Data</title> | 6 | <title>Sources for Time Zone and Daylight Saving Time Data</title> | |
7 | <link rel="schema.DC" href="http://purl.org/DC/elements/1.1/"> | 7 | <link rel="schema.DC" href="http://purl.org/DC/elements/1.1/"> | |
8 | <meta http-equiv="Content-type" content='text/html; charset="US-ASCII"'> | 8 | <meta http-equiv="Content-type" content='text/html; charset="US-ASCII"'> | |
9 | <meta name="DC.Creator" content="Eggert, Paul"> | 9 | <meta name="DC.Creator" content="Eggert, Paul"> | |
10 | <meta name="DC.Contributor" content="Olson, Arthur David"> | 10 | <meta name="DC.Contributor" content="Olson, Arthur David"> | |
11 | <meta name="DC.Date" content="2013-07-03"> | 11 | <meta name="DC.Date" content="2013-09-05"> | |
12 | <meta name="DC.Description" | 12 | <meta name="DC.Description" | |
13 | content="Sources of information about time zones and daylight saving time"> | 13 | content="Sources of information about time zones and daylight saving time"> | |
14 | <meta name="DC.Identifier" | 14 | <meta name="DC.Identifier" | |
15 | content="http://www.iana.org/time-zones/repository/tz-link.htm"> | 15 | content="http://www.iana.org/time-zones/repository/tz-link.htm"> | |
16 | <meta name="Keywords" | 16 | <meta name="Keywords" | |
17 | content="database,daylight saving,DST,time zone,timezone,tz,zoneinfo"> | 17 | content="database,daylight saving,DST,time zone,timezone,tz,zoneinfo"> | |
18 | </head> | 18 | </head> | |
19 | <body> | 19 | <body> | |
20 | <h1>Sources for Time Zone and Daylight Saving Time Data</h1> | 20 | <h1>Sources for Time Zone and Daylight Saving Time Data</h1> | |
21 | <h2>The <code>tz</code> database</h2> | 21 | <h2>The <code>tz</code> database</h2> | |
22 | <p> | 22 | <p> | |
23 | The <a href="http://en.wikipedia.org/wiki/Public_domain">public-domain</a> | 23 | The <a href="http://en.wikipedia.org/wiki/Public_domain">public-domain</a> | |
24 | time zone database contains code and data | 24 | time zone database contains code and data | |
@@ -384,32 +384,35 @@ of the University of Texas at Austin has | @@ -384,32 +384,35 @@ of the University of Texas at Austin has | |||
384 | recent editions. | 384 | recent editions. | |
385 | The pictorial quality is good, | 385 | The pictorial quality is good, | |
386 | but the maps do not indicate summer time, | 386 | but the maps do not indicate summer time, | |
387 | and parts of the data are a few years out of date.</li> | 387 | and parts of the data are a few years out of date.</li> | |
388 | <li><a href="http://worldtimezone.com/">Current time around the world | 388 | <li><a href="http://worldtimezone.com/">Current time around the world | |
389 | and standard time zones map of the world</a> | 389 | and standard time zones map of the world</a> | |
390 | has several fancy time zone maps; it covers Russia particularly well. | 390 | has several fancy time zone maps; it covers Russia particularly well. | |
391 | The maps' pictorial quality is not quite as good as the | 391 | The maps' pictorial quality is not quite as good as the | |
392 | <abbr>CIA</abbr>'s | 392 | <abbr>CIA</abbr>'s | |
393 | but the maps are more up to date.</li> | 393 | but the maps are more up to date.</li> | |
394 | </ul> | 394 | </ul> | |
395 | <h2>Time zone boundaries</h2> | 395 | <h2>Time zone boundaries</h2> | |
396 | <ul> | 396 | <ul> | |
397 | <li><a href="http://efele.net/maps/tz/">TZ timezone maps</a> contains a <a | 397 | <li><a href="http://efele.net/maps/tz/">TZ timezones maps</a> contains <a | |
398 | href="http://en.wikipedia.org/wiki/Shapefile">shapefile</a> of the | 398 | href="http://en.wikipedia.org/wiki/Shapefile">shapefiles</a> of | |
399 | <code>tz</code> regions in the world.</li> | 399 | sets of <code>tz</code> regions.</li> | |
400 | <li><a href="http://statoids.com/statoids.html">Administrative Divisions | 400 | <li><a href="http://derickrethans.nl/what-time-is-it.html">What Time | |
401 | of Countries ("Statoids")</a> contains detailed lists of | 401 | is It Here?</a> applies <a href="http://www.mongodb.org/">MongoDB</a> | |
402 | <code>tz</code>-related zone subdivision data.</li> | 402 | geospatial query operators to shapefiles' data.</li> | |
403 | <li><a href="http://statoids.com/statoids.html">Administrative | |||
404 | Divisions of Countries ("Statoids")</a> contains lists of | |||
405 | political subdivision data related to time zones.</li> | |||
403 | <li><a href="http://home.tiscali.nl/~t876506/Multizones.html">Time | 406 | <li><a href="http://home.tiscali.nl/~t876506/Multizones.html">Time | |
404 | zone boundaries for multizone countries</a> summarizes legal | 407 | zone boundaries for multizone countries</a> summarizes legal | |
405 | boundaries between time zones within countries.</li> | 408 | boundaries between time zones within countries.</li> | |
406 | <li>Manifold.net's <a | 409 | <li>Manifold.net's <a | |
407 | href="http://manifold.net/info/freestuff.shtml">Free Stuff for | 410 | href="http://manifold.net/info/freestuff.shtml">Free Stuff for | |
408 | Manifold System Users</a> includes a Manifold-format map of | 411 | Manifold System Users</a> includes a Manifold-format map of | |
409 | world time zone boundaries distributed under the | 412 | world time zone boundaries distributed under the | |
410 | <abbr>GPL</abbr>.</li> | 413 | <abbr>GPL</abbr>.</li> | |
411 | <li>The <abbr>US</abbr> Geological Survey's National Atlas of | 414 | <li>The <abbr>US</abbr> Geological Survey's National Atlas of | |
412 | the United States | 415 | the United States | |
413 | publishes the <a href="http://nationalatlas.gov/mld/timeznp.html">Time | 416 | publishes the <a href="http://nationalatlas.gov/mld/timeznp.html">Time | |
414 | Zones of the United States</a> in the public domain.</li> | 417 | Zones of the United States</a> in the public domain.</li> | |
415 | <li>The GeoCommunity lists several commercial sources for <a | 418 | <li>The GeoCommunity lists several commercial sources for <a |
--- src/lib/libc/time/Attic/tzfile.h 2013/07/17 20:13:04 1.11
+++ src/lib/libc/time/Attic/tzfile.h 2013/09/20 19:06:54 1.12
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: tzfile.h,v 1.11 2013/07/17 20:13:04 christos Exp $ */ | 1 | /* $NetBSD: tzfile.h,v 1.12 2013/09/20 19:06:54 christos Exp $ */ | |
2 | 2 | |||
3 | #ifndef TZFILE_H | 3 | #ifndef TZFILE_H | |
4 | #define TZFILE_H | 4 | #define TZFILE_H | |
5 | 5 | |||
6 | /* | 6 | /* | |
7 | ** This file is in the public domain, so clarified as of | 7 | ** This file is in the public domain, so clarified as of | |
8 | ** 1996-06-05 by Arthur David Olson. | 8 | ** 1996-06-05 by Arthur David Olson. | |
9 | */ | 9 | */ | |
10 | 10 | |||
11 | /* | 11 | /* | |
12 | ** This header is for use ONLY with the time conversion code. | 12 | ** This header is for use ONLY with the time conversion code. | |
13 | ** There is no guarantee that it will remain unchanged, | 13 | ** There is no guarantee that it will remain unchanged, | |
14 | ** or that it will remain at all. | 14 | ** or that it will remain at all. | |
@@ -30,69 +30,76 @@ | @@ -30,69 +30,76 @@ | |||
30 | 30 | |||
31 | #ifndef TZDEFRULES | 31 | #ifndef TZDEFRULES | |
32 | #define TZDEFRULES "posixrules" | 32 | #define TZDEFRULES "posixrules" | |
33 | #endif /* !defined TZDEFRULES */ | 33 | #endif /* !defined TZDEFRULES */ | |
34 | 34 | |||
35 | /* | 35 | /* | |
36 | ** Each file begins with. . . | 36 | ** Each file begins with. . . | |
37 | */ | 37 | */ | |
38 | 38 | |||
39 | #define TZ_MAGIC "TZif" | 39 | #define TZ_MAGIC "TZif" | |
40 | 40 | |||
41 | struct tzhead { | 41 | struct tzhead { | |
42 | char tzh_magic[4]; /* TZ_MAGIC */ | 42 | char tzh_magic[4]; /* TZ_MAGIC */ | |
43 | char tzh_version[1]; /* '\0' or '2' as of 2005 */ | 43 | char tzh_version[1]; /* '\0' or '2' or '3' as of 2013 */ | |
44 | char tzh_reserved[15]; /* reserved--must be zero */ | 44 | char tzh_reserved[15]; /* reserved--must be zero */ | |
45 | char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */ | 45 | char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */ | |
46 | char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */ | 46 | char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */ | |
47 | char tzh_leapcnt[4]; /* coded number of leap seconds */ | 47 | char tzh_leapcnt[4]; /* coded number of leap seconds */ | |
48 | char tzh_timecnt[4]; /* coded number of transition times */ | 48 | char tzh_timecnt[4]; /* coded number of transition times */ | |
49 | char tzh_typecnt[4]; /* coded number of local time types */ | 49 | char tzh_typecnt[4]; /* coded number of local time types */ | |
50 | char tzh_charcnt[4]; /* coded number of abbr. chars */ | 50 | char tzh_charcnt[4]; /* coded number of abbr. chars */ | |
51 | }; | 51 | }; | |
52 | 52 | |||
53 | /* | 53 | /* | |
54 | ** . . .followed by. . . | 54 | ** . . .followed by. . . | |
55 | ** | 55 | ** | |
56 | ** tzh_timecnt (char [4])s coded transition times a la time(2) | 56 | ** tzh_timecnt (char [4])s coded transition times a la time(2) | |
57 | ** tzh_timecnt (unsigned char)s types of local time starting at above | 57 | ** tzh_timecnt (unsigned char)s types of local time starting at above | |
58 | ** tzh_typecnt repetitions of | 58 | ** tzh_typecnt repetitions of | |
59 | ** one (char [4]) coded UTC offset in seconds | 59 | ** one (char [4]) coded UT offset in seconds | |
60 | ** one (unsigned char) used to set tm_isdst | 60 | ** one (unsigned char) used to set tm_isdst | |
61 | ** one (unsigned char) that's an abbreviation list index | 61 | ** one (unsigned char) that's an abbreviation list index | |
62 | ** tzh_charcnt (char)s '\0'-terminated zone abbreviations | 62 | ** tzh_charcnt (char)s '\0'-terminated zone abbreviations | |
63 | ** tzh_leapcnt repetitions of | 63 | ** tzh_leapcnt repetitions of | |
64 | ** one (char [4]) coded leap second transition times | 64 | ** one (char [4]) coded leap second transition times | |
65 | ** one (char [4]) total correction after above | 65 | ** one (char [4]) total correction after above | |
66 | ** tzh_ttisstdcnt (char)s indexed by type; if TRUE, transition | 66 | ** tzh_ttisstdcnt (char)s indexed by type; if TRUE, transition | |
67 | ** time is standard time, if FALSE, | 67 | ** time is standard time, if FALSE, | |
68 | ** transition time is wall clock time | 68 | ** transition time is wall clock time | |
69 | ** if absent, transition times are | 69 | ** if absent, transition times are | |
70 | ** assumed to be wall clock time | 70 | ** assumed to be wall clock time | |
71 | ** tzh_ttisgmtcnt (char)s indexed by type; if TRUE, transition | 71 | ** tzh_ttisgmtcnt (char)s indexed by type; if TRUE, transition | |
72 | ** time is UTC, if FALSE, | 72 | ** time is UT, if FALSE, | |
73 | ** transition time is local time | 73 | ** transition time is local time | |
74 | ** if absent, transition times are | 74 | ** if absent, transition times are | |
75 | ** assumed to be local time | 75 | ** assumed to be local time | |
76 | */ | 76 | */ | |
77 | 77 | |||
78 | /* | 78 | /* | |
79 | ** If tzh_version is '2' or greater, the above is followed by a second instance | 79 | ** If tzh_version is '2' or greater, the above is followed by a second instance | |
80 | ** of tzhead and a second instance of the data in which each coded transition | 80 | ** of tzhead and a second instance of the data in which each coded transition | |
81 | ** time uses 8 rather than 4 chars, | 81 | ** time uses 8 rather than 4 chars, | |
82 | ** then a POSIX-TZ-environment-variable-style string for use in handling | 82 | ** then a POSIX-TZ-environment-variable-style string for use in handling | |
83 | ** instants after the last transition time stored in the file | 83 | ** instants after the last transition time stored in the file | |
84 | ** (with nothing between the newlines if there is no POSIX representation for | 84 | ** (with nothing between the newlines if there is no POSIX representation for | |
85 | ** such instants). | 85 | ** such instants). | |
86 | ** | |||
87 | ** If tz_version is '3' or greater, the above is extended as follows. | |||
88 | ** First, the POSIX TZ string's hour offset may range from -167 | |||
89 | ** through 167 as compared to the POSIX-required 0 through 24. | |||
90 | ** Second, its DST start time may be January 1 at 00:00 and its stop | |||
91 | ** time December 31 at 24:00 plus the difference between DST and | |||
92 | ** standard time, indicating DST all year. | |||
86 | */ | 93 | */ | |
87 | 94 | |||
88 | /* | 95 | /* | |
89 | ** In the current implementation, "tzset()" refuses to deal with files that | 96 | ** In the current implementation, "tzset()" refuses to deal with files that | |
90 | ** exceed any of the limits below. | 97 | ** exceed any of the limits below. | |
91 | */ | 98 | */ | |
92 | 99 | |||
93 | #ifndef TZ_MAX_TIMES | 100 | #ifndef TZ_MAX_TIMES | |
94 | #define TZ_MAX_TIMES 1200 | 101 | #define TZ_MAX_TIMES 1200 | |
95 | #endif /* !defined TZ_MAX_TIMES */ | 102 | #endif /* !defined TZ_MAX_TIMES */ | |
96 | 103 | |||
97 | #ifndef TZ_MAX_TYPES | 104 | #ifndef TZ_MAX_TYPES | |
98 | #ifndef NOSOLAR | 105 | #ifndef NOSOLAR |
--- src/lib/libc/time/tzfile.5 2013/03/02 21:24:28 1.19
+++ src/lib/libc/time/tzfile.5 2013/09/20 19:06:54 1.20
@@ -1,103 +1,99 @@ | @@ -1,103 +1,99 @@ | |||
1 | .\" $NetBSD: tzfile.5,v 1.19 2013/03/02 21:24:28 christos Exp $ | 1 | .\" $NetBSD: tzfile.5,v 1.20 2013/09/20 19:06:54 christos Exp $ | |
2 | .\" | 2 | .\" | |
3 | .\" This file is in the public domain, so clarified as of | 3 | .\" This file is in the public domain, so clarified as of | |
4 | .\" 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov). | 4 | .\" 1996-06-05 by Arthur David Olson (arthur_david_olson@nih.gov). | |
5 | .Dd September 16, 2001 | 5 | .Dd September 20, 2013 | |
6 | .Dt TZFILE 5 | 6 | .Dt TZFILE 5 | |
7 | .Os | 7 | .Os | |
8 | .Sh NAME | 8 | .Sh NAME | |
9 | .Nm tzfile | 9 | .Nm tzfile | |
10 | .Nd time zone information | 10 | .Nd time zone information | |
11 | .Sh SYNOPSIS | 11 | .Sh SYNOPSIS | |
12 | .In tzfile.h | 12 | .In tzfile.h | |
13 | .Sh DESCRIPTION | 13 | .Sh DESCRIPTION | |
14 | The time zone information files used by | 14 | The time zone information files used by | |
15 | .Xr tzset 3 | 15 | .Xr tzset 3 | |
16 | begin with the magic characters | 16 | begin with the magic characters | |
17 | .Dq TZif | 17 | .Dq TZif | |
18 | to identify them as time zone information files, | 18 | to identify them as time zone information files, | |
19 | followed by a character identifying the version of the file's format | 19 | followed by a character identifying the version of the file's format | |
20 | (as of 2005, either an ASCII NUL or a '2') | 20 | (as of 2013, either an ASCII NUL or a '2', or '3') | |
21 | followed by fifteen bytes containing zeroes reserved for future use, | 21 | followed by fifteen bytes containing zeroes reserved for future use, | |
22 | followed by six four-byte values of type | 22 | followed by six four-byte values of type | |
23 | .Fa long , | 23 | .Fa long , | |
24 | written in a | 24 | followed by six four-byte integer values written in a | |
25 | .Dq standard | 25 | .Dq standard | |
26 | byte order (the high-order byte of the value is written first). | 26 | byte order (the high-order byte of the value is written first). | |
27 | These values are, in order: | 27 | These values are, in order: | |
28 | .Bl -tag -width XXXXXX -compact | 28 | .Bl -tag -width XXXXXX -compact | |
29 | .It Va tzh_ttisgmtcnt | 29 | .It Va tzh_ttisgmtcnt | |
30 | The number of UTC/local indicators stored in the file. | 30 | The number of UT/local indicators stored in the file. | |
31 | .It Va tzh_ttisstdcnt | 31 | .It Va tzh_ttisstdcnt | |
32 | The number of standard/wall indicators stored in the file. | 32 | The number of standard/wall indicators stored in the file. | |
33 | .It Va tzh_leapcnt | 33 | .It Va tzh_leapcnt | |
34 | The number of leap seconds for which data is stored in the file. | 34 | The number of leap seconds for which data is stored in the file. | |
35 | .It Va tzh_timecnt | 35 | .It Va tzh_timecnt | |
36 | The number of | 36 | The number of | |
37 | .Dq transition times | 37 | .Dq transition times | |
38 | for which data is stored in the file. | 38 | for which data is stored in the file. | |
39 | .It Va tzh_typecnt | 39 | .It Va tzh_typecnt | |
40 | The number of | 40 | The number of | |
41 | .Dq local time types | 41 | .Dq local time types | |
42 | for which data is stored in the file (must not be zero). | 42 | for which data is stored in the file (must not be zero). | |
43 | .It Va tzh_charcnt | 43 | .It Va tzh_charcnt | |
44 | The number of characters of "time zone abbreviation strings" | 44 | The number of characters of "time zone abbreviation strings" | |
45 | stored in the file. | 45 | stored in the file. | |
46 | .El | 46 | .El | |
47 | .Pp | 47 | .Pp | |
48 | The above header is followed by | 48 | The above header is followed by | |
49 | .Va tzh_timecnt | 49 | .Va tzh_timecnt | |
50 | four-byte values of type | 50 | four-byte signed integer values sorted in ascending order. | |
51 | .Fa long , | 51 | These values are written in | |
52 | sorted in ascending order. | |||
53 | These values are written in | 52 | These values are written in | |
54 | .Dq standard | 53 | .Dq standard | |
55 | byte order. | 54 | byte order. | |
56 | Each is used as a transition time (as returned by | 55 | Each is used as a transition time (as returned by | |
57 | .Xr time 3 ) | 56 | .Xr time 3 ) | |
58 | at which the rules for computing local time change. | 57 | at which the rules for computing local time change. | |
59 | Next come | 58 | Next come | |
60 | .Va tzh_timecnt | 59 | .Va tzh_timecnt | |
61 | one-byte values of type | 60 | one-byte unsigned integer values; | |
62 | .Fa unsigned char ; | |||
63 | each one tells which of the different types of | 61 | each one tells which of the different types of | |
64 | .Dq local time | 62 | .Dq local time | |
65 | types described in the file is associated with the same-indexed | 63 | types described in the file is associated with the same-indexed | |
66 | transition time. | 64 | transition time. | |
67 | These values serve as indices into an array of | 65 | These values serve as indices into an array of | |
68 | .Fa ttinfo | 66 | .Fa ttinfo | |
69 | structures (with | 67 | structures (with | |
70 | .Va tzh_typecnt | 68 | .Va tzh_typecnt | |
71 | entries) that appears next in the file; | 69 | entries) that appears next in the file; | |
72 | these structures are defined as follows: | 70 | these structures are defined as follows: | |
73 | .Bd -literal | 71 | .Bd -literal | |
74 | struct ttinfo { | 72 | struct ttinfo { | |
75 | long tt_gmtoff; | 73 | int32_t tt_gmtoff; | |
76 | int tt_isdst; | 74 | unsigned char tt_isdst; | |
77 | unsigned int tt_abbrind; | 75 | unsigned char tt_abbrind; | |
78 | }; | 76 | }; | |
79 | .Ed | 77 | .Ed | |
80 | Each structure is written as a four-byte value for | 78 | Each structure is written as a four-byte signed integer value for | |
81 | .Va tt_gmtoff | 79 | .Va tt_gmtoff | |
82 | of type | |||
83 | .Fa long , | |||
84 | in a standard byte order, followed by a one-byte value for | 80 | in a standard byte order, followed by a one-byte value for | |
85 | .Va tt_isdst | 81 | .Va tt_isdst | |
86 | and a one-byte value for | 82 | and a one-byte value for | |
87 | .Va tt_abbrind . | 83 | .Va tt_abbrind . | |
88 | In each structure, | 84 | In each structure, | |
89 | .Va tt_gmtoff | 85 | .Va tt_gmtoff | |
90 | gives the number of seconds to be added to UTC, | 86 | gives the number of seconds to be added to UT, | |
91 | .Va tt_isdst | 87 | .Va tt_isdst | |
92 | tells whether | 88 | tells whether | |
93 | .Va tm_isdst | 89 | .Va tm_isdst | |
94 | should be set by | 90 | should be set by | |
95 | .Xr localtime 3 | 91 | .Xr localtime 3 | |
96 | and | 92 | and | |
97 | .Va tt_abbrind | 93 | .Va tt_abbrind | |
98 | serves as an index into the array of time zone abbreviation characters | 94 | serves as an index into the array of time zone abbreviation characters | |
99 | that follow the | 95 | that follow the | |
100 | .Va ttinfo | 96 | .Va ttinfo | |
101 | structure(s) in the file. | 97 | structure(s) in the file. | |
102 | .Pp | 98 | .Pp | |
103 | Then there are | 99 | Then there are | |
@@ -112,48 +108,62 @@ the second gives the | @@ -112,48 +108,62 @@ the second gives the | |||
112 | number of leap seconds to be applied after the given time. | 108 | number of leap seconds to be applied after the given time. | |
113 | The pairs of values are sorted in ascending order by time. | 109 | The pairs of values are sorted in ascending order by time. | |
114 | .Pp | 110 | .Pp | |
115 | Then there are | 111 | Then there are | |
116 | .Va tzh_ttisstdcnt | 112 | .Va tzh_ttisstdcnt | |
117 | standard/wall indicators, each stored as a one-byte value; | 113 | standard/wall indicators, each stored as a one-byte value; | |
118 | they tell whether the transition times associated with local time types | 114 | they tell whether the transition times associated with local time types | |
119 | were specified as standard time or wall clock time, | 115 | were specified as standard time or wall clock time, | |
120 | and are used when a time zone file is used in handling POSIX-style | 116 | and are used when a time zone file is used in handling POSIX-style | |
121 | time zone environment variables. | 117 | time zone environment variables. | |
122 | .Pp | 118 | .Pp | |
123 | Finally there are | 119 | Finally there are | |
124 | .Va tzh_ttisgmtcnt | 120 | .Va tzh_ttisgmtcnt | |
125 | UTC/local indicators, each stored as a one-byte value; | 121 | UT/local indicators, each stored as a one-byte value; | |
126 | they tell whether the transition times associated with local time types | 122 | they tell whether the transition times associated with local time types | |
127 | were specified as UTC or local time, | 123 | were specified as UT or local time, | |
128 | and are used when a time zone file is used in handling POSIX-style | 124 | and are used when a time zone file is used in handling POSIX-style | |
129 | time zone environment variables. | 125 | time zone environment variables. | |
130 | .Pp | 126 | .Pp | |
131 | .Xr localtime 3 | 127 | .Xr localtime 3 | |
132 | uses the first standard-time | 128 | uses the first standard-time | |
133 | .Fa ttinfo | 129 | .Fa ttinfo | |
134 | structure in the file | 130 | structure in the file | |
135 | (or simply the first | 131 | (or simply the first | |
136 | .Fa ttinfo | 132 | .Fa ttinfo | |
137 | structure in the absence of a standard-time structure) | 133 | structure in the absence of a standard-time structure) | |
138 | if either | 134 | if either | |
139 | .Va tzh_timecnt | 135 | .Va tzh_timecnt | |
140 | is zero or the time argument is less than the first transition time recorded | 136 | is zero or the time argument is less than the first transition time recorded | |
141 | in the file. | 137 | in the file. | |
142 | .Pp | 138 | .Pp | |
143 | For version-2-format time zone files, | 139 | For version-2-format time zone files, | |
144 | the above header and data are followed by a second header and data, | 140 | the above header and data are followed by a second header and data, | |
145 | identical in format except that | 141 | identical in format except that | |
146 | eight bytes are used for each transition time or leap second time. | 142 | eight bytes are used for each transition time or leap second time. | |
147 | After the second header and data comes a newline-enclosed, | 143 | After the second header and data comes a newline-enclosed, | |
148 | POSIX-TZ-environment-variable-style string for use in handling instants | 144 | POSIX-TZ-environment-variable-style string for use in handling instants | |
149 | after the last transition time stored in the file | 145 | after the last transition time stored in the file | |
150 | (with nothing between the newlines if there is no POSIX representation for | 146 | (with nothing between the newlines if there is no POSIX representation for | |
151 | such instants). | 147 | such instants). | |
148 | .Pp | |||
149 | For version-3-format time zone files, the POSIX-TZ-style string may | |||
150 | use two minor extensions to the POSIX TZ format, as described in | |||
151 | .Xr tzset 3 . | |||
152 | First, the hours part of its transition times may be signed and range from | |||
153 | \(mi167 through 167 instead of the POSIX-required unsigned values | |||
154 | from 0 through 24. | |||
155 | Second, DST is in effect all year if it starts | |||
156 | January 1 at 00:00 and ends December 31 at 24:00 plus the difference | |||
157 | between daylight saving and standard time. | |||
158 | .Pp | |||
159 | Future changes to the format may append more data. | |||
152 | .Sh SEE ALSO | 160 | .Sh SEE ALSO | |
153 | .Xr ctime 3 , | 161 | .Xr ctime 3 , | |
154 | .Xr localtime 3 , | 162 | .Xr localtime 3 , | |
155 | .Xr time 3 , | 163 | .Xr time 3 , | |
164 | .Xr tzset 3 , | |||
156 | .Xr zdump 8 | 165 | .Xr zdump 8 | |
166 | .Xr zic 8 | |||
157 | .\" @(#)tzfile.5 8.3 | 167 | .\" @(#)tzfile.5 8.3 | |
158 | .\" This file is in the public domain, so clarified as of | 168 | .\" This file is in the public domain, so clarified as of | |
159 | .\" 1996-06-05 by Arthur David Olson. | 169 | .\" 1996-06-05 by Arthur David Olson. |
--- src/lib/libc/time/tzselect.8 2009/12/31 22:49:16 1.4
+++ src/lib/libc/time/tzselect.8 2013/09/20 19:06:54 1.5
@@ -1,45 +1,115 @@ | @@ -1,45 +1,115 @@ | |||
1 | .\" $NetBSD: tzselect.8,v 1.4 2009/12/31 22:49:16 mlelstv Exp $ | 1 | .\" $NetBSD: tzselect.8,v 1.5 2013/09/20 19:06:54 christos Exp $ | |
2 | .\" | 2 | .\" | |
3 | .TH TZSELECT 8 | 3 | .TH TZSELECT 8 | |
4 | .SH NAME | 4 | .SH NAME | |
5 | tzselect \- select a time zone | 5 | tzselect \- select a time zone | |
6 | .SH SYNOPSIS | 6 | .SH SYNOPSIS | |
7 | .B tzselect | 7 | .B tzselect | |
8 | [ | |||
9 | .B \-c | |||
10 | .I coord | |||
11 | ] [ | |||
12 | .B \-n | |||
13 | .I limit | |||
14 | ] [ | |||
15 | .B \-\-help | |||
16 | ] [ | |||
17 | .B \-\-version | |||
18 | ] | |||
8 | .SH DESCRIPTION | 19 | .SH DESCRIPTION | |
9 | The | 20 | The | |
10 | .B tzselect | 21 | .B tzselect | |
11 | program asks the user for information about the current location, | 22 | program asks the user for information about the current location, | |
12 | and outputs the resulting time zone description to standard output. | 23 | and outputs the resulting time zone description to standard output. | |
13 | The output is suitable as a value for the TZ environment variable. | 24 | The output is suitable as a value for the TZ environment variable. | |
14 | .PP | 25 | .PP | |
15 | All interaction with the user is done via standard input and standard error. | 26 | All interaction with the user is done via standard input and standard error. | |
27 | .SH OPTIONS | |||
28 | .TP | |||
29 | .BI "\-c " coord | |||
30 | Instead of asking for continent and then country and then city, | |||
31 | ask for selection from time zones whose largest cities | |||
32 | are closest to the location with geographical coordinates | |||
33 | .I coord. | |||
34 | Use ISO 6709 notation for | |||
35 | .I coord, | |||
36 | that is, a latitude immediately followed by a longitude. The latitude | |||
37 | and longitude should be signed integers followed by an optional | |||
38 | decimal point and fraction: positive numbers represent north and east, | |||
39 | negative south and west. Latitudes with two and longitudes with three | |||
40 | integer digits are treated as degrees; latitudes with four or six and | |||
41 | longitudes with five or seven integer digits are treated as | |||
42 | .I "DDMM, DDDMM, DDMMSS," | |||
43 | or | |||
44 | .I DDDMMSS | |||
45 | representing | |||
46 | .I DD | |||
47 | or | |||
48 | .I DDD | |||
49 | degrees, | |||
50 | .I MM | |||
51 | minutes, | |||
52 | and zero or | |||
53 | .I SS | |||
54 | seconds, with any trailing fractions represent fractional minutes or | |||
55 | (if | |||
56 | .I SS | |||
57 | is present) seconds. The decimal point is that of the current locale. | |||
58 | For example, in the (default) C locale, | |||
59 | .B "\-c\ +40.689\-074.045" | |||
60 | specifies 40.689\(de\|N, 74.045\(de\|W, | |||
61 | .B "\-c\ +4041.4\-07402.7" | |||
62 | specifies 40\(de\|41.4\(fm\|N, 74\(de\|2.7\(fm\|W, and | |||
63 | .B "\-c\ +404121\-0740240" | |||
64 | specifies 40\(de\|41\(fm\|21\(sd\|N, 74\(de\|2\(fm\|40\(sd\|W. | |||
65 | If | |||
66 | .I coord | |||
67 | is not one of the documented forms, the resulting behavior is unspecified. | |||
68 | .TP | |||
69 | .BI "\-n " limit | |||
70 | When | |||
71 | .B \-c | |||
72 | is used, display the closest | |||
73 | .I limit | |||
74 | locations (default 10). | |||
75 | .PP | |||
76 | Applications should not assume that | |||
77 | .BR tzselect 's | |||
78 | output matches the user's political preferences. | |||
79 | .RE | |||
80 | .TP | |||
81 | .B "\-\-help" | |||
82 | Output help information and exit. | |||
83 | .TP | |||
84 | .B "\-\-version" | |||
85 | Output version information and exit. | |||
16 | .SH "ENVIRONMENT VARIABLES" | 86 | .SH "ENVIRONMENT VARIABLES" | |
17 | .TP | 87 | .TP | |
18 | \f3AWK\fP | 88 | \f3AWK\fP | |
19 | Name of a Posix-compliant | 89 | Name of a Posix-compliant | |
20 | .I awk | 90 | .I awk | |
21 | program (default: | 91 | program (default: | |
22 | .BR awk ). | 92 | .BR awk ). | |
23 | .TP | 93 | .TP | |
24 | \f3TZDIR\fP | 94 | \f3TZDIR\fP | |
25 | Name of the directory containing time zone data files (default: | 95 | Name of the directory containing time zone data files (default: | |
26 | .BR /usr/local/etc/zoneinfo ). | 96 | .BR /usr/local/etc/zoneinfo ). | |
27 | .SH FILES | 97 | .SH FILES | |
28 | .TP | 98 | .TP | |
29 | \f2TZDIR\fP\f3/iso3166.tab\fP | 99 | \f2TZDIR\fP\f3/iso3166.tab\fP | |
30 | Table of ISO 3166 2-letter country codes and country names. | 100 | Table of ISO 3166 2-letter country codes and country names. | |
31 | .TP | 101 | .TP | |
32 | \f2TZDIR\fP\f3/zone.tab\fP | 102 | \f2TZDIR\fP\f3/zone.tab\fP | |
33 | Table of country codes, latitude and longitude, TZ values, and | 103 | Tables of country codes, latitude and longitude, zone names, and | |
34 | descriptive comments. | 104 | descriptive comments. | |
35 | .TP | 105 | .TP | |
36 | \f2TZDIR\fP\f3/\fP\f2TZ\fP | 106 | \f2TZDIR\fP\f3/\fP\f2TZ\fP | |
37 | Time zone data file for time zone \f2TZ\fP. | 107 | Time zone data file for time zone \f2TZ\fP. | |
38 | .SH "EXIT STATUS" | 108 | .SH "EXIT STATUS" | |
39 | The exit status is zero if a time zone was successfully obtained from the user, | 109 | The exit status is zero if a time zone was successfully obtained from the user, | |
40 | nonzero otherwise. | 110 | nonzero otherwise. | |
41 | .SH "SEE ALSO" | 111 | .SH "SEE ALSO" | |
42 | newctime(3), tzfile(5), zdump(8), zic(8) | 112 | newctime(3), tzfile(5), zdump(8), zic(8) | |
43 | .\" @(#)tzselect.8 8.2 | 113 | .\" @(#)tzselect.8 8.2 | |
44 | .\" This file is in the public domain, so clarified as of | 114 | .\" This file is in the public domain, so clarified as of | |
45 | .\" 2009-05-17 by Arthur David Olson. | 115 | .\" 2009-05-17 by Arthur David Olson. |
--- src/lib/libc/time/tzselect.ksh 2013/03/02 21:24:28 1.8
+++ src/lib/libc/time/tzselect.ksh 2013/09/20 19:06:54 1.9
@@ -1,16 +1,16 @@ | @@ -1,16 +1,16 @@ | |||
1 | #! /bin/bash | 1 | #! /bin/bash | |
2 | # | 2 | # | |
3 | # $NetBSD: tzselect.ksh,v 1.8 2013/03/02 21:24:28 christos Exp $ | 3 | # $NetBSD: tzselect.ksh,v 1.9 2013/09/20 19:06:54 christos Exp $ | |
4 | # | 4 | # | |
5 | PKGVERSION='(tzcode) ' | 5 | PKGVERSION='(tzcode) ' | |
6 | TZVERSION=see_Makefile | 6 | TZVERSION=see_Makefile | |
7 | REPORT_BUGS_TO=tz@iana.org | 7 | REPORT_BUGS_TO=tz@iana.org | |
8 | 8 | |||
9 | # Ask the user about the time zone, and output the resulting TZ value to stdout. | 9 | # Ask the user about the time zone, and output the resulting TZ value to stdout. | |
10 | # Interact with the user via stderr and stdin. | 10 | # Interact with the user via stderr and stdin. | |
11 | 11 | |||
12 | # Contributed by Paul Eggert. | 12 | # Contributed by Paul Eggert. | |
13 | 13 | |||
14 | # Porting notes: | 14 | # Porting notes: | |
15 | # | 15 | # | |
16 | # This script requires a Posix-like shell with the extension of a | 16 | # This script requires a Posix-like shell with the extension of a | |
@@ -32,130 +32,279 @@ REPORT_BUGS_TO=tz@iana.org | @@ -32,130 +32,279 @@ REPORT_BUGS_TO=tz@iana.org | |||
32 | 32 | |||
33 | 33 | |||
34 | # Specify default values for environment variables if they are unset. | 34 | # Specify default values for environment variables if they are unset. | |
35 | : ${AWK=awk} | 35 | : ${AWK=awk} | |
36 | : ${TZDIR=$(pwd)} | 36 | : ${TZDIR=$(pwd)} | |
37 | 37 | |||
38 | # Check for awk Posix compliance. | 38 | # Check for awk Posix compliance. | |
39 | ($AWK -v x=y 'BEGIN { exit 123 }') </dev/null >/dev/null 2>&1 | 39 | ($AWK -v x=y 'BEGIN { exit 123 }') </dev/null >/dev/null 2>&1 | |
40 | [ $? = 123 ] || { | 40 | [ $? = 123 ] || { | |
41 | echo >&2 "$0: Sorry, your \`$AWK' program is not Posix compatible." | 41 | echo >&2 "$0: Sorry, your \`$AWK' program is not Posix compatible." | |
42 | exit 1 | 42 | exit 1 | |
43 | } | 43 | } | |
44 | 44 | |||
45 | if [ "$1" = "--help" ]; then | 45 | coord= | |
46 | cat <<EOF | 46 | location_limit=10 | |
47 | Usage: tzselect | 47 | ||
48 | usage="Usage: tzselect [--version] [--help] [-c COORD] [-n LIMIT] | |||
48 | Select a time zone interactively. | 49 | Select a time zone interactively. | |
49 | 50 | |||
50 | Report bugs to $REPORT_BUGS_TO. | 51 | Options: | |
51 | EOF | 52 | ||
52 | exit | 53 | -c COORD | |
53 | elif [ "$1" = "--version" ]; then | 54 | Instead of asking for continent and then country and then city, | |
54 | cat <<EOF | 55 | ask for selection from time zones whose largest cities | |
55 | tzselect $TZVERSION | 56 | are closest to the location with geographical coordinates COORD. | |
56 | EOF | 57 | COORD should use ISO 6709 notation, for example, '-c +4852+00220' | |
57 | exit | 58 | for Paris (in degrees and minutes, North and East), or | |
58 | fi | 59 | '-c -35-058' for Buenos Aires (in degrees, South and West). | |
60 | ||||
61 | -n LIMIT | |||
62 | Display at most LIMIT locations when -c is used (default $location_limit). | |||
63 | ||||
64 | --version | |||
65 | Output version information. | |||
66 | ||||
67 | --help | |||
68 | Output this help. | |||
69 | ||||
70 | Report bugs to $REPORT_BUGS_TO." | |||
71 | ||||
72 | while getopts c:n:-: opt | |||
73 | do | |||
74 | case $opt$OPTARG in | |||
75 | c*) | |||
76 | coord=$OPTARG ;; | |||
77 | n*) | |||
78 | location_limit=$OPTARG ;; | |||
79 | -help) | |||
80 | exec echo "$usage" ;; | |||
81 | -version) | |||
82 | exec echo "tzselect $PKGVERSION$TZVERSION" ;; | |||
83 | -*) | |||
84 | echo >&2 "$0: -$opt$OPTARG: unknown option; try '$0 --help'"; exit 1 ;; | |||
85 | *) | |||
86 | echo >&2 "$0: try '$0 --help'"; exit 1 ;; | |||
87 | esac | |||
88 | done | |||
89 | ||||
90 | shift $((OPTIND-1)) | |||
91 | case $# in | |||
92 | 0) ;; | |||
93 | *) echo >&2 "$0: $1: unknown argument"; exit 1 ;; | |||
94 | esac | |||
59 | 95 | |||
60 | # Make sure the tables are readable. | 96 | # Make sure the tables are readable. | |
61 | TZ_COUNTRY_TABLE=$TZDIR/iso3166.tab | 97 | TZ_COUNTRY_TABLE=$TZDIR/iso3166.tab | |
62 | TZ_ZONE_TABLE=$TZDIR/zone.tab | 98 | TZ_ZONE_TABLE=$TZDIR/zone.tab | |
63 | for f in $TZ_COUNTRY_TABLE $TZ_ZONE_TABLE | 99 | for f in $TZ_COUNTRY_TABLE $TZ_ZONE_TABLE | |
64 | do | 100 | do | |
65 | <$f || { | 101 | <$f || { | |
66 | echo >&2 "$0: time zone files are not set up correctly" | 102 | echo >&2 "$0: time zone files are not set up correctly" | |
67 | exit 1 | 103 | exit 1 | |
68 | } | 104 | } | |
69 | done | 105 | done | |
70 | 106 | |||
71 | newline=' | 107 | newline=' | |
72 | ' | 108 | ' | |
73 | IFS=$newline | 109 | IFS=$newline | |
74 | 110 | |||
75 | 111 | |||
76 | # Work around a bug in bash 1.14.7 and earlier, where $PS3 is sent to stdout. | 112 | # Work around a bug in bash 1.14.7 and earlier, where $PS3 is sent to stdout. | |
77 | case $(echo 1 | (select x in x; do break; done) 2>/dev/null) in | 113 | case $(echo 1 | (select x in x; do break; done) 2>/dev/null) in | |
78 | ?*) PS3= | 114 | ?*) PS3= | |
79 | esac | 115 | esac | |
80 | 116 | |||
117 | # Awk script to read a time zone table and output the same table, | |||
118 | # with each column preceded by its distance from 'here'. | |||
119 | output_distances=' | |||
120 | BEGIN { | |||
121 | FS = "\t" | |||
122 | while (getline <TZ_COUNTRY_TABLE) | |||
123 | if ($0 ~ /^[^#]/) | |||
124 | country[$1] = $2 | |||
125 | country["US"] = "US" # Otherwise the strings get too long. | |||
126 | } | |||
127 | function convert_coord(coord, deg, min, ilen, sign, sec) { | |||
128 | if (coord ~ /^[-+]?[0-9]?[0-9][0-9][0-9][0-9][0-9][0-9]([^0-9]|$)/) { | |||
129 | degminsec = coord | |||
130 | intdeg = degminsec < 0 ? -int(-degminsec / 10000) : int(degminsec / 10000) | |||
131 | minsec = degminsec - intdeg * 10000 | |||
132 | intmin = minsec < 0 ? -int(-minsec / 100) : int(minsec / 100) | |||
133 | sec = minsec - intmin * 100 | |||
134 | deg = (intdeg * 3600 + intmin * 60 + sec) / 3600 | |||
135 | } else if (coord ~ /^[-+]?[0-9]?[0-9][0-9][0-9][0-9]([^0-9]|$)/) { | |||
136 | degmin = coord | |||
137 | intdeg = degmin < 0 ? -int(-degmin / 100) : int(degmin / 100) | |||
138 | min = degmin - intdeg * 100 | |||
139 | deg = (intdeg * 60 + min) / 60 | |||
140 | } else | |||
141 | deg = coord | |||
142 | return deg * 0.017453292519943296 | |||
143 | } | |||
144 | function convert_latitude(coord) { | |||
145 | match(coord, /..*[-+]/) | |||
146 | return convert_coord(substr(coord, 1, RLENGTH - 1)) | |||
147 | } | |||
148 | function convert_longitude(coord) { | |||
149 | match(coord, /..*[-+]/) | |||
150 | return convert_coord(substr(coord, RLENGTH)) | |||
151 | } | |||
152 | # Great-circle distance between points with given latitude and longitude. | |||
153 | # Inputs and output are in radians. This uses the great-circle special | |||
154 | # case of the Vicenty formula for distances on ellipsoids. | |||
155 | function dist(lat1, long1, lat2, long2, dlong, x, y, num, denom) { | |||
156 | dlong = long2 - long1 | |||
157 | x = cos (lat2) * sin (dlong) | |||
158 | y = cos (lat1) * sin (lat2) - sin (lat1) * cos (lat2) * cos (dlong) | |||
159 | num = sqrt (x * x + y * y) | |||
160 | denom = sin (lat1) * sin (lat2) + cos (lat1) * cos (lat2) * cos (dlong) | |||
161 | return atan2(num, denom) | |||
162 | } | |||
163 | BEGIN { | |||
164 | coord_lat = convert_latitude(coord) | |||
165 | coord_long = convert_longitude(coord) | |||
166 | } | |||
167 | /^[^#]/ { | |||
168 | here_lat = convert_latitude($2) | |||
169 | here_long = convert_longitude($2) | |||
170 | line = $1 "\t" $2 "\t" $3 "\t" country[$1] | |||
171 | if (NF == 4) | |||
172 | line = line " - " $4 | |||
173 | printf "%g\t%s\n", dist(coord_lat, coord_long, here_lat, here_long), line | |||
174 | } | |||
175 | ' | |||
81 | 176 | |||
82 | # Begin the main loop. We come back here if the user wants to retry. | 177 | # Begin the main loop. We come back here if the user wants to retry. | |
83 | while | 178 | while | |
84 | 179 | |||
85 | echo >&2 'Please identify a location' \ | 180 | echo >&2 'Please identify a location' \ | |
86 | 'so that time zone rules can be set correctly.' | 181 | 'so that time zone rules can be set correctly.' | |
87 | 182 | |||
88 | continent= | 183 | continent= | |
89 | country= | 184 | country= | |
90 | region= | 185 | region= | |
91 | 186 | |||
187 | case $coord in | |||
188 | ?*) | |||
189 | continent=coord;; | |||
190 | '') | |||
92 | 191 | |||
93 | # Ask the user for continent or ocean. | 192 | # Ask the user for continent or ocean. | |
94 | 193 | |||
95 | echo >&2 'Please select a continent or ocean.' | 194 | echo >&2 'Please select a continent, ocean, "coord", or "TZ".' | |
96 | 195 | |||
97 | select continent in \ | 196 | quoted_continents=$( | |
98 | Africa \ | 197 | $AWK -F'\t' ' | |
99 | Americas \ | 198 | /^[^#]/ { | |
100 | Antarctica \ | 199 | entry = substr($3, 1, index($3, "/") - 1) | |
101 | 'Arctic Ocean' \ | 200 | if (entry == "America") | |
102 | Asia \ | 201 | entry = entry "s" | |
103 | 'Atlantic Ocean' \ | 202 | if (entry ~ /^(Arctic|Atlantic|Indian|Pacific)$/) | |
104 | Australia \ | 203 | entry = entry " Ocean" | |
105 | Europe \ | 204 | printf "'\''%s'\''\n", entry | |
106 | 'Indian Ocean' \ | 205 | } | |
107 | 'Pacific Ocean' \ | 206 | ' $TZ_ZONE_TABLE | | |
108 | 'none - I want to specify the time zone using the Posix TZ format.' | 207 | sort -u | | |
109 | do | 208 | tr '\n' ' ' | |
110 | case $continent in | 209 | echo '' | |
111 | '') | 210 | ) | |
112 | echo >&2 'Please enter a number in range.';; | 211 | ||
113 | ?*) | 212 | eval ' | |
213 | select continent in '"$quoted_continents"' \ | |||
214 | "coord - I want to use geographical coordinates." \ | |||
215 | "TZ - I want to specify the time zone using the Posix TZ format." | |||
216 | do | |||
114 | case $continent in | 217 | case $continent in | |
115 | Americas) continent=America;; | 218 | "") | |
116 | *' '*) continent=$(expr "$continent" : '\([^ ]*\)') | 219 | echo >&2 "Please enter a number in range.";; | |
220 | ?*) | |||
221 | case $continent in | |||
222 | Americas) continent=America;; | |||
223 | *" "*) continent=$(expr "$continent" : '\''\([^ ]*\)'\'') | |||
224 | esac | |||
225 | break | |||
117 | esac | 226 | esac | |
118 | break | 227 | done | |
119 | esac | 228 | ' | |
120 | done | 229 | esac | |
230 | ||||
121 | case $continent in | 231 | case $continent in | |
122 | '') | 232 | '') | |
123 | exit 1;; | 233 | exit 1;; | |
124 | none) | 234 | TZ) | |
125 | # Ask the user for a Posix TZ string. Check that it conforms. | 235 | # Ask the user for a Posix TZ string. Check that it conforms. | |
126 | while | 236 | while | |
127 | echo >&2 'Please enter the desired value' \ | 237 | echo >&2 'Please enter the desired value' \ | |
128 | 'of the TZ environment variable.' | 238 | 'of the TZ environment variable.' | |
129 | echo >&2 'For example, GST-10 is a zone named GST' \ | 239 | echo >&2 'For example, GST-10 is a zone named GST' \ | |
130 | 'that is 10 hours ahead (east) of UTC.' | 240 | 'that is 10 hours ahead (east) of UTC.' | |
131 | read TZ | 241 | read TZ | |
132 | $AWK -v TZ="$TZ" 'BEGIN { | 242 | $AWK -v TZ="$TZ" 'BEGIN { | |
133 | tzname = "[^-+,0-9][^-+,0-9][^-+,0-9]+" | 243 | tzname = "[^-+,0-9][^-+,0-9][^-+,0-9]+" | |
134 | time = "[0-2]?[0-9](:[0-5][0-9](:[0-5][0-9])?)?" | 244 | time = "[0-2]?[0-9](:[0-5][0-9](:[0-5][0-9])?)?" | |
135 | offset = "[-+]?" time | 245 | offset = "[-+]?" time | |
136 | date = "(J?[0-9]+|M[0-9]+\.[0-9]+\.[0-9]+)" | 246 | date = "(J?[0-9]+|M[0-9]+\.[0-9]+\.[0-9]+)" | |
137 | datetime = "," date "(/" time ")?" | 247 | datetime = "," date "(/" time ")?" | |
138 | tzpattern = "^(:.*|" tzname offset "(" tzname \ | 248 | tzpattern = "^(:.*|" tzname offset "(" tzname \ | |
139 | "(" offset ")?(" datetime datetime ")?)?)$" | 249 | "(" offset ")?(" datetime datetime ")?)?)$" | |
140 | if (TZ ~ tzpattern) exit 1 | 250 | if (TZ ~ tzpattern) exit 1 | |
141 | exit 0 | 251 | exit 0 | |
142 | }' | 252 | }' | |
143 | do | 253 | do | |
144 | echo >&2 "\`$TZ' is not a conforming" \ | 254 | echo >&2 "\`$TZ' is not a conforming" \ | |
145 | 'Posix time zone string.' | 255 | 'Posix time zone string.' | |
146 | done | 256 | done | |
147 | TZ_for_date=$TZ;; | 257 | TZ_for_date=$TZ;; | |
148 | *) | 258 | *) | |
259 | case $continent in | |||
260 | coord) | |||
261 | case $coord in | |||
262 | '') | |||
263 | echo >&2 'Please enter coordinates' \ | |||
264 | 'in ISO 6709 notation.' | |||
265 | echo >&2 'For example, +4042-07403 stands for' | |||
266 | echo >&2 '40 degrees 42 minutes north,' \ | |||
267 | '74 degrees 3 minutes west.' | |||
268 | read coord;; | |||
269 | esac | |||
270 | distance_table=$($AWK \ | |||
271 | -v coord="$coord" \ | |||
272 | -v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \ | |||
273 | "$output_distances" <$TZ_ZONE_TABLE | | |||
274 | sort -n | | |||
275 | sed "${location_limit}q" | |||
276 | ) | |||
277 | regions=$(echo "$distance_table" | $AWK ' | |||
278 | BEGIN { FS = "\t" } | |||
279 | { print $NF } | |||
280 | ') | |||
281 | echo >&2 'Please select one of the following' \ | |||
282 | 'time zone regions,' | |||
283 | echo >&2 'listed roughly in increasing order' \ | |||
284 | "of distance from $coord". | |||
285 | select region in $regions | |||
286 | do | |||
287 | case $region in | |||
288 | '') echo >&2 'Please enter a number in range.';; | |||
289 | ?*) break;; | |||
290 | esac | |||
291 | done | |||
292 | TZ=$(echo "$distance_table" | $AWK -v region="$region" ' | |||
293 | BEGIN { FS="\t" } | |||
294 | $NF == region { print $4 } | |||
295 | ') | |||
296 | ;; | |||
297 | *) | |||
149 | # Get list of names of countries in the continent or ocean. | 298 | # Get list of names of countries in the continent or ocean. | |
150 | countries=$($AWK -F'\t' \ | 299 | countries=$($AWK -F'\t' \ | |
151 | -v continent="$continent" \ | 300 | -v continent="$continent" \ | |
152 | -v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \ | 301 | -v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \ | |
153 | ' | 302 | ' | |
154 | /^#/ { next } | 303 | /^#/ { next } | |
155 | $3 ~ ("^" continent "/") { | 304 | $3 ~ ("^" continent "/") { | |
156 | if (!cc_seen[$1]++) cc_list[++ccs] = $1 | 305 | if (!cc_seen[$1]++) cc_list[++ccs] = $1 | |
157 | } | 306 | } | |
158 | END { | 307 | END { | |
159 | while (getline <TZ_COUNTRY_TABLE) { | 308 | while (getline <TZ_COUNTRY_TABLE) { | |
160 | if ($0 !~ /^#/) cc_name[$1] = $2 | 309 | if ($0 !~ /^#/) cc_name[$1] = $2 | |
161 | } | 310 | } | |
@@ -163,27 +312,28 @@ while | @@ -163,27 +312,28 @@ while | |||
163 | country = cc_list[i] | 312 | country = cc_list[i] | |
164 | if (cc_name[country]) { | 313 | if (cc_name[country]) { | |
165 | country = cc_name[country] | 314 | country = cc_name[country] | |
166 | } | 315 | } | |
167 | print country | 316 | print country | |
168 | } | 317 | } | |
169 | } | 318 | } | |
170 | ' <$TZ_ZONE_TABLE | sort -f) | 319 | ' <$TZ_ZONE_TABLE | sort -f) | |
171 | 320 | |||
172 | 321 | |||
173 | # If there's more than one country, ask the user which one. | 322 | # If there's more than one country, ask the user which one. | |
174 | case $countries in | 323 | case $countries in | |
175 | *"$newline"*) | 324 | *"$newline"*) | |
176 | echo >&2 'Please select a country.' | 325 | echo >&2 'Please select a country' \ | |
326 | 'whose clocks agree with yours.' | |||
177 | select country in $countries | 327 | select country in $countries | |
178 | do | 328 | do | |
179 | case $country in | 329 | case $country in | |
180 | '') echo >&2 'Please enter a number in range.';; | 330 | '') echo >&2 'Please enter a number in range.';; | |
181 | ?*) break | 331 | ?*) break | |
182 | esac | 332 | esac | |
183 | done | 333 | done | |
184 | 334 | |||
185 | case $country in | 335 | case $country in | |
186 | '') exit 1 | 336 | '') exit 1 | |
187 | esac;; | 337 | esac;; | |
188 | *) | 338 | *) | |
189 | country=$countries | 339 | country=$countries | |
@@ -234,26 +384,27 @@ while | @@ -234,26 +384,27 @@ while | |||
234 | -v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \ | 384 | -v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \ | |
235 | ' | 385 | ' | |
236 | BEGIN { | 386 | BEGIN { | |
237 | cc = country | 387 | cc = country | |
238 | while (getline <TZ_COUNTRY_TABLE) { | 388 | while (getline <TZ_COUNTRY_TABLE) { | |
239 | if ($0 !~ /^#/ && country == $2) { | 389 | if ($0 !~ /^#/ && country == $2) { | |
240 | cc = $1 | 390 | cc = $1 | |
241 | break | 391 | break | |
242 | } | 392 | } | |
243 | } | 393 | } | |
244 | } | 394 | } | |
245 | $1 == cc && $4 == region { print $3 } | 395 | $1 == cc && $4 == region { print $3 } | |
246 | ' <$TZ_ZONE_TABLE) | 396 | ' <$TZ_ZONE_TABLE) | |
397 | esac | |||
247 | 398 | |||
248 | # Make sure the corresponding zoneinfo file exists. | 399 | # Make sure the corresponding zoneinfo file exists. | |
249 | TZ_for_date=$TZDIR/$TZ | 400 | TZ_for_date=$TZDIR/$TZ | |
250 | <$TZ_for_date || { | 401 | <$TZ_for_date || { | |
251 | echo >&2 "$0: time zone files are not set up correctly" | 402 | echo >&2 "$0: time zone files are not set up correctly" | |
252 | exit 1 | 403 | exit 1 | |
253 | } | 404 | } | |
254 | esac | 405 | esac | |
255 | 406 | |||
256 | 407 | |||
257 | # Use the proposed TZ to output the current date relative to UTC. | 408 | # Use the proposed TZ to output the current date relative to UTC. | |
258 | # Loop until they agree in seconds. | 409 | # Loop until they agree in seconds. | |
259 | # Give up after 8 unsuccessful tries. | 410 | # Give up after 8 unsuccessful tries. | |
@@ -270,48 +421,50 @@ while | @@ -270,48 +421,50 @@ while | |||
270 | extra_info=" | 421 | extra_info=" | |
271 | Local time is now: $TZdate. | 422 | Local time is now: $TZdate. | |
272 | Universal Time is now: $UTdate." | 423 | Universal Time is now: $UTdate." | |
273 | break | 424 | break | |
274 | esac | 425 | esac | |
275 | done | 426 | done | |
276 | 427 | |||
277 | 428 | |||
278 | # Output TZ info and ask the user to confirm. | 429 | # Output TZ info and ask the user to confirm. | |
279 | 430 | |||
280 | echo >&2 "" | 431 | echo >&2 "" | |
281 | echo >&2 "The following information has been given:" | 432 | echo >&2 "The following information has been given:" | |
282 | echo >&2 "" | 433 | echo >&2 "" | |
283 | case $country+$region in | 434 | case $country%$region%$coord in | |
284 | ?*+?*) echo >&2 " $country$newline $region";; | 435 | ?*%?*%) echo >&2 " $country$newline $region";; | |
285 | ?*+) echo >&2 " $country";; | 436 | ?*%%) echo >&2 " $country";; | |
437 | %?*%?*) echo >&2 " coord $coord$newline $region";; | |||
438 | %%?*) echo >&2 " coord $coord";; | |||
286 | +) echo >&2 " TZ='$TZ'" | 439 | +) echo >&2 " TZ='$TZ'" | |
287 | esac | 440 | esac | |
288 | echo >&2 "" | 441 | echo >&2 "" | |
289 | echo >&2 "Therefore TZ='$TZ' will be used.$extra_info" | 442 | echo >&2 "Therefore TZ='$TZ' will be used.$extra_info" | |
290 | echo >&2 "Is the above information OK?" | 443 | echo >&2 "Is the above information OK?" | |
291 | 444 | |||
292 | ok= | 445 | ok= | |
293 | select ok in Yes No | 446 | select ok in Yes No | |
294 | do | 447 | do | |
295 | case $ok in | 448 | case $ok in | |
296 | '') echo >&2 'Please enter 1 for Yes, or 2 for No.';; | 449 | '') echo >&2 'Please enter 1 for Yes, or 2 for No.';; | |
297 | ?*) break | 450 | ?*) break | |
298 | esac | 451 | esac | |
299 | done | 452 | done | |
300 | case $ok in | 453 | case $ok in | |
301 | '') exit 1;; | 454 | '') exit 1;; | |
302 | Yes) break | 455 | Yes) break | |
303 | esac | 456 | esac | |
304 | do : | 457 | do coord= | |
305 | done | 458 | done | |
306 | 459 | |||
307 | case $SHELL in | 460 | case $SHELL in | |
308 | *csh) file=.login line="setenv TZ '$TZ'";; | 461 | *csh) file=.login line="setenv TZ '$TZ'";; | |
309 | *) file=.profile line="TZ='$TZ'; export TZ" | 462 | *) file=.profile line="TZ='$TZ'; export TZ" | |
310 | esac | 463 | esac | |
311 | 464 | |||
312 | echo >&2 " | 465 | echo >&2 " | |
313 | You can make this change permanent for yourself by appending the line | 466 | You can make this change permanent for yourself by appending the line | |
314 | $line | 467 | $line | |
315 | to the file '$file' in your home directory; then log out and log in again. | 468 | to the file '$file' in your home directory; then log out and log in again. | |
316 | 469 | |||
317 | Here is that TZ value again, this time on standard output so that you | 470 | Here is that TZ value again, this time on standard output so that you |
--- src/lib/libc/time/tzset.3 2010/12/17 01:29:45 1.25
+++ src/lib/libc/time/tzset.3 2013/09/20 19:06:54 1.26
@@ -1,15 +1,15 @@ | @@ -1,15 +1,15 @@ | |||
1 | .\" $NetBSD: tzset.3,v 1.25 2010/12/17 01:29:45 wiz Exp $ | 1 | .\" $NetBSD: tzset.3,v 1.26 2013/09/20 19:06:54 christos Exp $ | |
2 | .Dd April 1, 2001 | 2 | .Dd September 20, 2013 | |
3 | .Dt TZSET 3 | 3 | .Dt TZSET 3 | |
4 | .Os | 4 | .Os | |
5 | .Sh NAME | 5 | .Sh NAME | |
6 | .Nm tzset | 6 | .Nm tzset | |
7 | .Nd initialize time conversion information | 7 | .Nd initialize time conversion information | |
8 | .Sh LIBRARY | 8 | .Sh LIBRARY | |
9 | .Lb libc | 9 | .Lb libc | |
10 | .Sh SYNOPSIS | 10 | .Sh SYNOPSIS | |
11 | .In time.h | 11 | .In time.h | |
12 | .Ft void | 12 | .Ft void | |
13 | .Fn tzset "void" | 13 | .Fn tzset "void" | |
14 | .Sh DESCRIPTION | 14 | .Sh DESCRIPTION | |
15 | The | 15 | The | |
@@ -21,28 +21,30 @@ to set time conversion information used | @@ -21,28 +21,30 @@ to set time conversion information used | |||
21 | If | 21 | If | |
22 | .Ev TZ | 22 | .Ev TZ | |
23 | does not appear in the environment, | 23 | does not appear in the environment, | |
24 | the best available approximation to local wall clock time, as | 24 | the best available approximation to local wall clock time, as | |
25 | specified by the | 25 | specified by the | |
26 | .Xr tzfile 5 | 26 | .Xr tzfile 5 | |
27 | format file | 27 | format file | |
28 | .Pa /etc/localtime | 28 | .Pa /etc/localtime | |
29 | is used by | 29 | is used by | |
30 | .Xr localtime 3 . | 30 | .Xr localtime 3 . | |
31 | If | 31 | If | |
32 | .Ev TZ | 32 | .Ev TZ | |
33 | appears in the environment but its value is a null string, | 33 | appears in the environment but its value is a null string, | |
34 | Coordinated Universal Time (UTC) is used (without leap second | 34 | Universal Time (UT) is used, with the abbreviation | |
35 | correction). | 35 | .Dq UTC | |
36 | and without leap second correction; please see | |||
37 | .Xr ctime 3 . | |||
36 | If | 38 | If | |
37 | .Ev TZ | 39 | .Ev TZ | |
38 | appears in the environment and its value is not a null string: | 40 | appears in the environment and its value is not a null string: | |
39 | .Bl -dash | 41 | .Bl -dash | |
40 | .It | 42 | .It | |
41 | if the value begins with a colon, it is used as a pathname of a file | 43 | if the value begins with a colon, it is used as a pathname of a file | |
42 | from which to read the time conversion information; | 44 | from which to read the time conversion information; | |
43 | .It | 45 | .It | |
44 | if the value does not begin with a colon, it is first used as the | 46 | if the value does not begin with a colon, it is first used as the | |
45 | pathname of a file from which to read the time conversion information, | 47 | pathname of a file from which to read the time conversion information, | |
46 | and, if that file cannot be read, is used directly as a specification | 48 | and, if that file cannot be read, is used directly as a specification | |
47 | of the time conversion information. | 49 | of the time conversion information. | |
48 | .El | 50 | .El | |
@@ -141,26 +143,30 @@ has the form: | @@ -141,26 +143,30 @@ has the form: | |||
141 | .Ed | 143 | .Ed | |
142 | .Sm on | 144 | .Sm on | |
143 | .Pp | 145 | .Pp | |
144 | where the first | 146 | where the first | |
145 | .Cm date | 147 | .Cm date | |
146 | describes when the change from standard to summer time occurs and the | 148 | describes when the change from standard to summer time occurs and the | |
147 | second | 149 | second | |
148 | .Cm date | 150 | .Cm date | |
149 | describes when the change back happens. | 151 | describes when the change back happens. | |
150 | Each | 152 | Each | |
151 | .Cm time | 153 | .Cm time | |
152 | field describes when, in current local time, the change to the other | 154 | field describes when, in current local time, the change to the other | |
153 | time is made. | 155 | time is made. | |
156 | As an extension to POSIX, daylight saving is assumed to be in effect | |||
157 | all year if it begins January 1 at 00:00 and ends December 31 at | |||
158 | 24:00 plus the difference between daylight saving and standard time, | |||
159 | leaving no room for standard time in the calendar. | |||
154 | The format of | 160 | The format of | |
155 | .Fa date | 161 | .Fa date | |
156 | is one of the following: | 162 | is one of the following: | |
157 | .Bl -tag -width "The Julian day" -compact | 163 | .Bl -tag -width "The Julian day" -compact | |
158 | .It Cm J Ns Ar n | 164 | .It Cm J Ns Ar n | |
159 | The Julian day | 165 | The Julian day | |
160 | .Ar n | 166 | .Ar n | |
161 | (1 \*[Le] | 167 | (1 \*[Le] | |
162 | .Ar n | 168 | .Ar n | |
163 | \*[Le] 365). | 169 | \*[Le] 365). | |
164 | Leap days are not counted; that is, in all years \(em including leap | 170 | Leap days are not counted; that is, in all years \(em including leap | |
165 | years \(em February 28 is day 59 and March 1 is day 60. | 171 | years \(em February 28 is day 59 and March 1 is day 60. | |
166 | It is impossible to explicitly refer to the occasional February 29. | 172 | It is impossible to explicitly refer to the occasional February 29. | |
@@ -189,36 +195,77 @@ of the year | @@ -189,36 +195,77 @@ of the year | |||
189 | .Ar m | 195 | .Ar m | |
190 | \*[Le]\ 12, where week 5 means | 196 | \*[Le]\ 12, where week 5 means | |
191 | .Dq the\ last Ar d No day\ in\ month Ar m | 197 | .Dq the\ last Ar d No day\ in\ month Ar m | |
192 | which may occur in either the fourth or the fifth week). | 198 | which may occur in either the fourth or the fifth week). | |
193 | Week 1 is the first week in which the | 199 | Week 1 is the first week in which the | |
194 | .Ar d Ns 'th | 200 | .Ar d Ns 'th | |
195 | day occurs. | 201 | day occurs. | |
196 | Day zero is Sunday. | 202 | Day zero is Sunday. | |
197 | .El | 203 | .El | |
198 | The | 204 | The | |
199 | .Cm time | 205 | .Cm time | |
200 | has the same format as | 206 | has the same format as | |
201 | .Cm offset | 207 | .Cm offset | |
202 | except that no leading sign | 208 | except that POSIX does not allow a leading sign | |
203 | .Dq - | 209 | .Dq - | |
204 | or | 210 | or | |
205 | .Dq + | 211 | .Dq + | |
206 | is allowed. | 212 | is allowed. | |
213 | As an extension to POSIX, the hours part of | |||
214 | .Cm time | |||
215 | can range from \(mi167 through 167; this allows for unusual rules such as | |||
216 | .Dq the Saturday before the first Sunday of March . | |||
207 | The default, if | 217 | The default, if | |
208 | .Cm time | 218 | .Cm time | |
209 | is not given, is | 219 | is not given, is | |
210 | .Cm 02:00:00 . | 220 | .Cm 02:00:00 . | |
211 | .El | 221 | .El | |
222 | .Pp | |||
223 | Here are some examples of | |||
224 | .Va TZ | |||
225 | values that directly specify the time zone rules; they use some of the | |||
226 | extensions to POSIX. | |||
227 | .Bl -tag | |||
228 | .It EST5 | |||
229 | stands for US eastern | |||
230 | time (EST), 5 hours behind UTC, without daylight saving. | |||
231 | .It FJT\(mi12FJST,M10.3.1/146,M1.3.4/75 | |||
232 | stands for Fiji Time (FJT) and Fiji Summer Time (FJST), 12 hours ahead | |||
233 | of UTC, springing forward on October's third Monday at | |||
234 | 146:00 (i.e., 02:00 on the first Sunday on or after October 21), and | |||
235 | falling back on January's third Thursday at 75:00 (i.e., 03:00 on the | |||
236 | first Sunday on or after January 18). | |||
237 | .It IST\(mi2IDT,M3.4.4/26,M10.5.0 | |||
238 | stands for Israel Standard Time (IST) and Israel Daylight Time (IDT), | |||
239 | 2 hours ahead of UTC, springing forward on March's fourth | |||
240 | Tuesday at 26:00 (i.e., 02:00 on the first Friday on or after March | |||
241 | 23), and falling back on October's last Sunday at 02:00. | |||
242 | .It WART4WARST,J1/0,J365/25 | |||
243 | stands for Western Argentina Summer Time (WARST), 3 hours behind UTC. | |||
244 | There is a dummy fall-back transition on December 31 at 25:00 daylight | |||
245 | saving time (i.e., 24:00 standard time, equivalent to January 1 at | |||
246 | 00:00 standard time), and a simultaneous spring-forward transition on | |||
247 | January 1 at 00:00 standard time, so daylight saving time is in effect | |||
248 | all year and the initial | |||
249 | .Em WART | |||
250 | is a placeholder. | |||
251 | .It WGT3WGST,M3.5.0/\(mi2,M10.5.0/\(mi1 | |||
252 | stands for Western Greenland time (WGT) and Western Greenland Summer | |||
253 | Time (WGST), 3 hours behind UTC, where clocks follow the EU rules of | |||
254 | springing forward on March's last Sunday at 01:00 UTC (\(mi02:00 local | |||
255 | time) and falling back on October's last Sunday at 01:00 UTC | |||
256 | (\(mi01:00 local time). | |||
257 | .El | |||
258 | .Pp | |||
212 | If no | 259 | If no | |
213 | .Cm rule | 260 | .Cm rule | |
214 | is present in | 261 | is present in | |
215 | .Ev TZ , | 262 | .Ev TZ , | |
216 | the rules specified by the | 263 | the rules specified by the | |
217 | .Xr tzfile 5 | 264 | .Xr tzfile 5 | |
218 | format file | 265 | format file | |
219 | .Pa posixrules | 266 | .Pa posixrules | |
220 | in | 267 | in | |
221 | .Pa /usr/share/zoneinfo | 268 | .Pa /usr/share/zoneinfo | |
222 | are used, with the standard and summer time offsets from UTC replaced | 269 | are used, with the standard and summer time offsets from UTC replaced | |
223 | by those specified by the | 270 | by those specified by the | |
224 | .Cm offset | 271 | .Cm offset |
--- src/lib/libc/time/Attic/version.h 2012/08/09 12:38:26 1.1
+++ src/lib/libc/time/Attic/version.h 2013/09/20 19:06:54 1.2
--- src/lib/libc/time/zdump.8 2013/07/17 20:13:04 1.10
+++ src/lib/libc/time/zdump.8 2013/09/20 19:06:54 1.11
@@ -1,15 +1,15 @@ | @@ -1,15 +1,15 @@ | |||
1 | .\" $NetBSD: zdump.8,v 1.10 2013/07/17 20:13:04 christos Exp $ | 1 | .\" $NetBSD: zdump.8,v 1.11 2013/09/20 19:06:54 christos Exp $ | |
2 | .Dd July 17, 2013 | 2 | .Dd September 20, 2013 | |
3 | .Dt ZDUMP 8 | 3 | .Dt ZDUMP 8 | |
4 | .Os | 4 | .Os | |
5 | .Sh NAME | 5 | .Sh NAME | |
6 | .Nm zdump | 6 | .Nm zdump | |
7 | .Nd time zone dumper | 7 | .Nd time zone dumper | |
8 | .Sh SYNOPSIS | 8 | .Sh SYNOPSIS | |
9 | .Nm zdump | 9 | .Nm zdump | |
10 | .Op Fl \-version | 10 | .Op Fl \-version | |
11 | .Op Fl v | 11 | .Op Fl v | |
12 | .Op Fl V | 12 | .Op Fl V | |
13 | .Op Fl c Ar [loyear,]highyear | 13 | .Op Fl c Ar [loyear,]highyear | |
14 | .Op Ar zonename ... | 14 | .Op Ar zonename ... | |
15 | .Nm zdump | 15 | .Nm zdump | |
@@ -46,31 +46,37 @@ Cut off the verbose output near the star | @@ -46,31 +46,37 @@ Cut off the verbose output near the star | |||
46 | By default, | 46 | By default, | |
47 | the program cuts off verbose output near the starts of the years \-500 and 2500. | 47 | the program cuts off verbose output near the starts of the years \-500 and 2500. | |
48 | .It Fl t Ar [loyear,]highyear | 48 | .It Fl t Ar [loyear,]highyear | |
49 | Cut off verbose output at the start of the given time(s), | 49 | Cut off verbose output at the start of the given time(s), | |
50 | given in decimal seconds since 1970-01-01 00:00:00 UTC. | 50 | given in decimal seconds since 1970-01-01 00:00:00 UTC. | |
51 | .It Fl V | 51 | .It Fl V | |
52 | Like | 52 | Like | |
53 | .Fl v , | 53 | .Fl v , | |
54 | except omit the times relative to the extreme time values. | 54 | except omit the times relative to the extreme time values. | |
55 | This generates output that is easier to compare to that of | 55 | This generates output that is easier to compare to that of | |
56 | implementations with different time representations. | 56 | implementations with different time representations. | |
57 | .El | 57 | .El | |
58 | .Sh LIMITATIONS | 58 | .Sh LIMITATIONS | |
59 | The | |||
60 | .Fl v | |||
61 | and | |||
62 | .Fl V | |||
63 | options may not be used on systems with floating-point time_t values | |||
64 | that are neither float nor double. | |||
65 | .Pp | |||
66 | Time discontinuities are found by sampling the results returned by localtime | 59 | Time discontinuities are found by sampling the results returned by localtime | |
67 | at twelve-hour intervals. | 60 | at twelve-hour intervals. | |
68 | This works in all real-world cases; | 61 | This works in all real-world cases; | |
69 | one can construct artificial time zones for which this fails. | 62 | one can construct artificial time zones for which this fails. | |
63 | .Pp | |||
64 | In the output, | |||
65 | .Dq UT | |||
66 | denotes the value returned by | |||
67 | .Xr gmtime 3 , | |||
68 | which uses UTC for modern time stamps and some other UT flavor for | |||
69 | time stamps that predate the introduction of UTC. | |||
70 | No attempt is currently made to have the output use | |||
71 | .Dq UTC | |||
72 | for newer and | |||
73 | .Dq UT | |||
74 | for older time stamps, | |||
75 | partly because the exact date of the introduction of UTC is problematic. | |||
70 | .Sh SEE ALSO | 76 | .Sh SEE ALSO | |
71 | .Xr ctime 3 , | 77 | .Xr ctime 3 , | |
72 | .Xr tzfile 5 , | 78 | .Xr tzfile 5 , | |
73 | .Xr zic 8 | 79 | .Xr zic 8 | |
74 | .\" @(#)zdump.8 8.2 | 80 | .\" @(#)zdump.8 8.2 | |
75 | .\" This file is in the public domain, so clarified as of | 81 | .\" This file is in the public domain, so clarified as of | |
76 | .\" 2009-05-17 by Arthur David Olson. | 82 | .\" 2009-05-17 by Arthur David Olson. |
--- src/lib/libc/time/zdump.c 2013/07/17 23:09:26 1.30
+++ src/lib/libc/time/zdump.c 2013/09/20 19:06:54 1.31
@@ -1,43 +1,42 @@ | @@ -1,43 +1,42 @@ | |||
1 | /* $NetBSD: zdump.c,v 1.30 2013/07/17 23:09:26 christos Exp $ */ | 1 | /* $NetBSD: zdump.c,v 1.31 2013/09/20 19:06:54 christos Exp $ */ | |
2 | /* | 2 | /* | |
3 | ** This file is in the public domain, so clarified as of | 3 | ** This file is in the public domain, so clarified as of | |
4 | ** 2009-05-17 by Arthur David Olson. | 4 | ** 2009-05-17 by Arthur David Olson. | |
5 | */ | 5 | */ | |
6 | 6 | |||
7 | #include <sys/cdefs.h> | 7 | #include <sys/cdefs.h> | |
8 | #ifndef lint | 8 | #ifndef lint | |
9 | __RCSID("$NetBSD: zdump.c,v 1.30 2013/07/17 23:09:26 christos Exp $"); | 9 | __RCSID("$NetBSD: zdump.c,v 1.31 2013/09/20 19:06:54 christos Exp $"); | |
10 | #endif /* !defined lint */ | 10 | #endif /* !defined lint */ | |
11 | 11 | |||
12 | #include "version.h" | 12 | #include "version.h" | |
13 | /* | 13 | /* | |
14 | ** This code has been made independent of the rest of the time | 14 | ** This code has been made independent of the rest of the time | |
15 | ** conversion package to increase confidence in the verification it provides. | 15 | ** conversion package to increase confidence in the verification it provides. | |
16 | ** You can use this code to help in verifying other implementations. | 16 | ** You can use this code to help in verifying other implementations. | |
17 | ** | 17 | ** | |
18 | ** However, include private.h when debugging, so that it overrides | 18 | ** However, include private.h when debugging, so that it overrides | |
19 | ** time_t consistently with the rest of the package. | 19 | ** time_t consistently with the rest of the package. | |
20 | */ | 20 | */ | |
21 | 21 | |||
22 | #include "private.h" | 22 | #include "private.h" | |
23 | 23 | |||
24 | #include "stdio.h" /* for stdout, stderr */ | 24 | #include "stdio.h" /* for stdout, stderr */ | |
25 | #include "string.h" /* for strcpy */ | 25 | #include "string.h" /* for strcpy */ | |
26 | #include "sys/types.h" /* for time_t */ | 26 | #include "sys/types.h" /* for time_t */ | |
27 | #include "time.h" /* for struct tm */ | 27 | #include "time.h" /* for struct tm */ | |
28 | #include "stdlib.h" /* for exit, malloc, atoi */ | 28 | #include "stdlib.h" /* for exit, malloc, atoi */ | |
29 | #include <err.h> | 29 | #include <err.h> | |
30 | #include "float.h" /* for FLT_MAX and DBL_MAX */ | |||
31 | #include "ctype.h" /* for isalpha et al. */ | 30 | #include "ctype.h" /* for isalpha et al. */ | |
32 | #ifndef isascii | 31 | #ifndef isascii | |
33 | #define isascii(x) 1 | 32 | #define isascii(x) 1 | |
34 | #endif /* !defined isascii */ | 33 | #endif /* !defined isascii */ | |
35 | 34 | |||
36 | /* | 35 | /* | |
37 | ** Substitutes for pre-C99 compilers. | 36 | ** Substitutes for pre-C99 compilers. | |
38 | ** Much of this section of code is stolen from private.h. | 37 | ** Much of this section of code is stolen from private.h. | |
39 | */ | 38 | */ | |
40 | 39 | |||
41 | #ifndef HAVE_STDINT_H | 40 | #ifndef HAVE_STDINT_H | |
42 | # define HAVE_STDINT_H \ | 41 | # define HAVE_STDINT_H \ | |
43 | (199901 <= __STDC_VERSION__ || 2 < (__GLIBC__ + (0 < __GLIBC_MINOR__))) | 42 | (199901 <= __STDC_VERSION__ || 2 < (__GLIBC__ + (0 < __GLIBC_MINOR__))) | |
@@ -54,29 +53,35 @@ __RCSID("$NetBSD: zdump.c,v 1.30 2013/07 | @@ -54,29 +53,35 @@ __RCSID("$NetBSD: zdump.c,v 1.30 2013/07 | |||
54 | 53 | |||
55 | #ifndef INT_FAST32_MAX | 54 | #ifndef INT_FAST32_MAX | |
56 | # if INT_MAX >> 31 == 0 | 55 | # if INT_MAX >> 31 == 0 | |
57 | typedef long int_fast32_t; | 56 | typedef long int_fast32_t; | |
58 | # else | 57 | # else | |
59 | typedef int int_fast32_t; | 58 | typedef int int_fast32_t; | |
60 | # endif | 59 | # endif | |
61 | #endif | 60 | #endif | |
62 | 61 | |||
63 | #ifndef INTMAX_MAX | 62 | #ifndef INTMAX_MAX | |
64 | # if defined LLONG_MAX || defined __LONG_LONG_MAX__ | 63 | # if defined LLONG_MAX || defined __LONG_LONG_MAX__ | |
65 | typedef long long intmax_t; | 64 | typedef long long intmax_t; | |
66 | # define PRIdMAX "lld" | 65 | # define PRIdMAX "lld" | |
66 | # ifdef LLONG_MAX | |||
67 | # define INTMAX_MAX LLONG_MAX | |||
68 | # else | |||
69 | # define INTMAX_MAX __LONG_LONG_MAX__ | |||
70 | # endif | |||
67 | # else | 71 | # else | |
68 | typedef long intmax_t; | 72 | typedef long intmax_t; | |
69 | # define PRIdMAX "ld" | 73 | # define PRIdMAX "ld" | |
74 | # define INTMAX_MAX LONG_MAX | |||
70 | # endif | 75 | # endif | |
71 | #endif | 76 | #endif | |
72 | #ifndef SCNdMAX | 77 | #ifndef SCNdMAX | |
73 | # define SCNdMAX PRIdMAX | 78 | # define SCNdMAX PRIdMAX | |
74 | #endif | 79 | #endif | |
75 | 80 | |||
76 | 81 | |||
77 | #ifndef ZDUMP_LO_YEAR | 82 | #ifndef ZDUMP_LO_YEAR | |
78 | #define ZDUMP_LO_YEAR (-500) | 83 | #define ZDUMP_LO_YEAR (-500) | |
79 | #endif /* !defined ZDUMP_LO_YEAR */ | 84 | #endif /* !defined ZDUMP_LO_YEAR */ | |
80 | 85 | |||
81 | #ifndef ZDUMP_HI_YEAR | 86 | #ifndef ZDUMP_HI_YEAR | |
82 | #define ZDUMP_HI_YEAR 2500 | 87 | #define ZDUMP_HI_YEAR 2500 | |
@@ -134,26 +139,37 @@ typedef long intmax_t; | @@ -134,26 +139,37 @@ typedef long intmax_t; | |||
134 | #define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0)) | 139 | #define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0)) | |
135 | #endif /* !defined isleap */ | 140 | #endif /* !defined isleap */ | |
136 | 141 | |||
137 | #ifndef isleap_sum | 142 | #ifndef isleap_sum | |
138 | /* | 143 | /* | |
139 | ** See tzfile.h for details on isleap_sum. | 144 | ** See tzfile.h for details on isleap_sum. | |
140 | */ | 145 | */ | |
141 | #define isleap_sum(a, b) isleap((a) % 400 + (b) % 400) | 146 | #define isleap_sum(a, b) isleap((a) % 400 + (b) % 400) | |
142 | #endif /* !defined isleap_sum */ | 147 | #endif /* !defined isleap_sum */ | |
143 | 148 | |||
144 | #define SECSPERDAY ((int_fast32_t) SECSPERHOUR * HOURSPERDAY) | 149 | #define SECSPERDAY ((int_fast32_t) SECSPERHOUR * HOURSPERDAY) | |
145 | #define SECSPERNYEAR (SECSPERDAY * DAYSPERNYEAR) | 150 | #define SECSPERNYEAR (SECSPERDAY * DAYSPERNYEAR) | |
146 | #define SECSPERLYEAR (SECSPERNYEAR + SECSPERDAY) | 151 | #define SECSPERLYEAR (SECSPERNYEAR + SECSPERDAY) | |
152 | #define SECSPER400YEARS (SECSPERNYEAR * (intmax_t) (300 + 3) \ | |||
153 | + SECSPERLYEAR * (intmax_t) (100 - 3)) | |||
154 | ||||
155 | /* | |||
156 | ** True if SECSPER400YEARS is known to be representable as an | |||
157 | ** intmax_t. It's OK that SECSPER400YEARS_FITS can in theory be false | |||
158 | ** even if SECSPER400YEARS is representable, because when that happens | |||
159 | ** the code merely runs a bit more slowly, and this slowness doesn't | |||
160 | ** occur on any practical platform. | |||
161 | */ | |||
162 | enum { SECSPER400YEARS_FITS = SECSPERLYEAR <= INTMAX_MAX / 400 }; | |||
147 | 163 | |||
148 | #ifndef HAVE_GETTEXT | 164 | #ifndef HAVE_GETTEXT | |
149 | #define HAVE_GETTEXT 0 | 165 | #define HAVE_GETTEXT 0 | |
150 | #endif | 166 | #endif | |
151 | #if HAVE_GETTEXT | 167 | #if HAVE_GETTEXT | |
152 | #include "locale.h" /* for setlocale */ | 168 | #include "locale.h" /* for setlocale */ | |
153 | #include "libintl.h" | 169 | #include "libintl.h" | |
154 | #endif /* HAVE_GETTEXT */ | 170 | #endif /* HAVE_GETTEXT */ | |
155 | 171 | |||
156 | #ifndef GNUC_or_lint | 172 | #ifndef GNUC_or_lint | |
157 | #ifdef lint | 173 | #ifdef lint | |
158 | #define GNUC_or_lint | 174 | #define GNUC_or_lint | |
159 | #else /* !defined lint */ | 175 | #else /* !defined lint */ | |
@@ -195,77 +211,62 @@ typedef long intmax_t; | @@ -195,77 +211,62 @@ typedef long intmax_t; | |||
195 | 211 | |||
196 | #ifndef TZ_DOMAIN | 212 | #ifndef TZ_DOMAIN | |
197 | #define TZ_DOMAIN "tz" | 213 | #define TZ_DOMAIN "tz" | |
198 | #endif /* !defined TZ_DOMAIN */ | 214 | #endif /* !defined TZ_DOMAIN */ | |
199 | 215 | |||
200 | extern char ** environ; | 216 | extern char ** environ; | |
201 | extern int getopt(int argc, char * const argv[], | 217 | extern int getopt(int argc, char * const argv[], | |
202 | const char * options); | 218 | const char * options); | |
203 | extern char * optarg; | 219 | extern char * optarg; | |
204 | extern int optind; | 220 | extern int optind; | |
205 | 221 | |||
206 | /* The minimum and maximum finite time values. */ | 222 | /* The minimum and maximum finite time values. */ | |
207 | static time_t absolute_min_time = | 223 | static time_t absolute_min_time = | |
208 | ((time_t) 0.5 == 0.5 | 224 | ((time_t) -1 < 0 | |
209 | ? (sizeof (time_t) == sizeof (float) ? (time_t) -FLT_MAX | |||
210 | : sizeof (time_t) == sizeof (double) ? (time_t) -DBL_MAX | |||
211 | : sizeof (time_t) == sizeof (long double) ? (time_t) -LDBL_MAX | |||
212 | : 0) | |||
213 | #ifndef TIME_T_FLOATING | |||
214 | : (time_t) -1 < 0 | |||
215 | ? (time_t) -1 << (CHAR_BIT * sizeof (time_t) - 1) | 225 | ? (time_t) -1 << (CHAR_BIT * sizeof (time_t) - 1) | |
216 | #endif | |||
217 | : 0); | 226 | : 0); | |
218 | static time_t absolute_max_time = | 227 | static time_t absolute_max_time = | |
219 | ((time_t) 0.5 == 0.5 | 228 | ((time_t) -1 < 0 | |
220 | ? (sizeof (time_t) == sizeof (float) ? (time_t) FLT_MAX | 229 | ? - (~ 0 < 0) - ((time_t) -1 << (CHAR_BIT * sizeof (time_t) - 1)) | |
221 | : sizeof (time_t) == sizeof (double) ? (time_t) DBL_MAX | |||
222 | : sizeof (time_t) == sizeof (long double) ? (time_t) LDBL_MAX | |||
223 | : -1) | |||
224 | #ifndef TIME_T_FLOATING | |||
225 | : (time_t) -1 < 0 | |||
226 | ? - (~ 0 < 0) - ((time_t) -1 << (CHAR_BIT * sizeof (time_t) - 1)) | |||
227 | #endif | |||
228 | : -1); | 230 | : -1); | |
229 | static size_t longest; | 231 | static size_t longest; | |
230 | static char * progname; | 232 | static char * progname; | |
231 | static int warned; | 233 | static int warned; | |
232 | 234 | |||
233 | static const char * abbr(struct tm * tmp); | 235 | static const char * abbr(struct tm * tmp); | |
234 | static void abbrok(const char * abbrp, const char * zone); | 236 | static void abbrok(const char * abbrp, const char * zone); | |
235 | static intmax_t delta(struct tm * newp, struct tm * oldp) ATTRIBUTE_PURE; | 237 | static intmax_t delta(struct tm * newp, struct tm * oldp) ATTRIBUTE_PURE; | |
236 | static void dumptime(const struct tm * tmp); | 238 | static void dumptime(const struct tm * tmp); | |
237 | static time_t hunt(char * name, time_t lot, time_t hit); | 239 | static time_t hunt(char * name, time_t lot, time_t hit); | |
238 | static void checkabsolutes(void); | |||
239 | static void show(char * zone, time_t t, int v); | 240 | static void show(char * zone, time_t t, int v); | |
240 | static const char * tformat(void); | 241 | static const char * tformat(void); | |
241 | static time_t yeartot(long y) ATTRIBUTE_PURE; | 242 | static time_t yeartot(long y) ATTRIBUTE_PURE; | |
242 | 243 | |||
243 | #ifndef TYPECHECK | 244 | #ifndef TYPECHECK | |
244 | #define my_localtime localtime | 245 | #define my_localtime localtime | |
245 | #else /* !defined TYPECHECK */ | 246 | #else /* !defined TYPECHECK */ | |
246 | static struct tm * | 247 | static struct tm * | |
247 | my_localtime(time_t *tp) | 248 | my_localtime(time_t *tp) | |
248 | { | 249 | { | |
249 | struct tm *tmp; | 250 | struct tm *tmp; | |
250 | 251 | |||
251 | tmp = localtime(tp); | 252 | tmp = localtime(tp); | |
252 | if (tp != NULL && tmp != NULL) { | 253 | if (tp != NULL && tmp != NULL) { | |
253 | struct tm tm; | 254 | struct tm tm; | |
254 | time_t t; | 255 | time_t t; | |
255 | 256 | |||
256 | tm = *tmp; | 257 | tm = *tmp; | |
257 | t = mktime(&tm); | 258 | t = mktime(&tm); | |
258 | if (t - *tp >= 1 || *tp - t >= 1) { | 259 | if (t != *tp) { | |
259 | (void) fflush(stdout); | 260 | (void) fflush(stdout); | |
260 | (void) fprintf(stderr, "\n%s: ", progname); | 261 | (void) fprintf(stderr, "\n%s: ", progname); | |
261 | (void) fprintf(stderr, tformat(), *tp); | 262 | (void) fprintf(stderr, tformat(), *tp); | |
262 | (void) fprintf(stderr, " ->"); | 263 | (void) fprintf(stderr, " ->"); | |
263 | (void) fprintf(stderr, " year=%d", tmp->tm_year); | 264 | (void) fprintf(stderr, " year=%d", tmp->tm_year); | |
264 | (void) fprintf(stderr, " mon=%d", tmp->tm_mon); | 265 | (void) fprintf(stderr, " mon=%d", tmp->tm_mon); | |
265 | (void) fprintf(stderr, " mday=%d", tmp->tm_mday); | 266 | (void) fprintf(stderr, " mday=%d", tmp->tm_mday); | |
266 | (void) fprintf(stderr, " hour=%d", tmp->tm_hour); | 267 | (void) fprintf(stderr, " hour=%d", tmp->tm_hour); | |
267 | (void) fprintf(stderr, " min=%d", tmp->tm_min); | 268 | (void) fprintf(stderr, " min=%d", tmp->tm_min); | |
268 | (void) fprintf(stderr, " sec=%d", tmp->tm_sec); | 269 | (void) fprintf(stderr, " sec=%d", tmp->tm_sec); | |
269 | (void) fprintf(stderr, " isdst=%d", tmp->tm_isdst); | 270 | (void) fprintf(stderr, " isdst=%d", tmp->tm_isdst); | |
270 | (void) fprintf(stderr, " -> "); | 271 | (void) fprintf(stderr, " -> "); | |
271 | (void) fprintf(stderr, tformat(), t); | 272 | (void) fprintf(stderr, tformat(), t); | |
@@ -385,27 +386,26 @@ main(int argc, char *argv[]) | @@ -385,27 +386,26 @@ main(int argc, char *argv[]) | |||
385 | if (cutarg != NULL) { | 386 | if (cutarg != NULL) { | |
386 | if (sscanf(cutarg, "%"SCNdMAX"%c", &hi, &dummy) == 1) { | 387 | if (sscanf(cutarg, "%"SCNdMAX"%c", &hi, &dummy) == 1) { | |
387 | cuthiyear = hi; | 388 | cuthiyear = hi; | |
388 | } else if (sscanf(cutarg, "%"SCNdMAX",%"SCNdMAX"%c", | 389 | } else if (sscanf(cutarg, "%"SCNdMAX",%"SCNdMAX"%c", | |
389 | &lo, &hi, &dummy) == 2) { | 390 | &lo, &hi, &dummy) == 2) { | |
390 | cutloyear = lo; | 391 | cutloyear = lo; | |
391 | cuthiyear = hi; | 392 | cuthiyear = hi; | |
392 | } else { | 393 | } else { | |
393 | (void) fprintf(stderr, _("%s: wild -c argument %s\n"), | 394 | (void) fprintf(stderr, _("%s: wild -c argument %s\n"), | |
394 | progname, cutarg); | 395 | progname, cutarg); | |
395 | exit(EXIT_FAILURE); | 396 | exit(EXIT_FAILURE); | |
396 | } | 397 | } | |
397 | } | 398 | } | |
398 | checkabsolutes(); | |||
399 | if (cutarg != NULL || cuttimes == NULL) { | 399 | if (cutarg != NULL || cuttimes == NULL) { | |
400 | cutlotime = yeartot(cutloyear); | 400 | cutlotime = yeartot(cutloyear); | |
401 | cuthitime = yeartot(cuthiyear); | 401 | cuthitime = yeartot(cuthiyear); | |
402 | } | 402 | } | |
403 | if (cuttimes != NULL) { | 403 | if (cuttimes != NULL) { | |
404 | if (sscanf(cuttimes, "%"SCNdMAX"%c", &hi, &dummy) == 1) { | 404 | if (sscanf(cuttimes, "%"SCNdMAX"%c", &hi, &dummy) == 1) { | |
405 | if (hi < cuthitime) { | 405 | if (hi < cuthitime) { | |
406 | if (hi < absolute_min_time) | 406 | if (hi < absolute_min_time) | |
407 | hi = absolute_min_time; | 407 | hi = absolute_min_time; | |
408 | cuthitime = hi; | 408 | cuthitime = hi; | |
409 | } | 409 | } | |
410 | } else if (sscanf(cuttimes, "%"SCNdMAX",%"SCNdMAX"%c", | 410 | } else if (sscanf(cuttimes, "%"SCNdMAX",%"SCNdMAX"%c", | |
411 | &lo, &hi, &dummy) == 2) { | 411 | &lo, &hi, &dummy) == 2) { | |
@@ -454,114 +454,117 @@ main(int argc, char *argv[]) | @@ -454,114 +454,117 @@ main(int argc, char *argv[]) | |||
454 | } | 454 | } | |
455 | for (i = optind; i < argc; ++i) { | 455 | for (i = optind; i < argc; ++i) { | |
456 | static char buf[MAX_STRING_LENGTH]; | 456 | static char buf[MAX_STRING_LENGTH]; | |
457 | 457 | |||
458 | (void) strcpy(&fakeenv[0][3], argv[i]); /* XXX strcpy is safe */ | 458 | (void) strcpy(&fakeenv[0][3], argv[i]); /* XXX strcpy is safe */ | |
459 | if (! (vflag | Vflag)) { | 459 | if (! (vflag | Vflag)) { | |
460 | show(argv[i], now, FALSE); | 460 | show(argv[i], now, FALSE); | |
461 | continue; | 461 | continue; | |
462 | } | 462 | } | |
463 | warned = FALSE; | 463 | warned = FALSE; | |
464 | t = absolute_min_time; | 464 | t = absolute_min_time; | |
465 | if (!Vflag) { | 465 | if (!Vflag) { | |
466 | show(argv[i], t, TRUE); | 466 | show(argv[i], t, TRUE); | |
467 | t += SECSPERHOUR * HOURSPERDAY; | 467 | t += SECSPERDAY; | |
468 | show(argv[i], t, TRUE); | 468 | show(argv[i], t, TRUE); | |
469 | } | 469 | } | |
470 | if (t < cutlotime) | 470 | if (t < cutlotime) | |
471 | t = cutlotime; | 471 | t = cutlotime; | |
472 | tmp = my_localtime(&t); | 472 | tmp = my_localtime(&t); | |
473 | if (tmp != NULL) { | 473 | if (tmp != NULL) { | |
474 | tm = *tmp; | 474 | tm = *tmp; | |
475 | (void) strncpy(buf, abbr(&tm), (sizeof buf) - 1); | 475 | (void) strncpy(buf, abbr(&tm), (sizeof buf) - 1); | |
476 | } | 476 | } | |
477 | for ( ; ; ) { | 477 | for ( ; ; ) { | |
478 | if (t >= cuthitime || t >= cuthitime - SECSPERHOUR * 12) | 478 | newt = (t < absolute_max_time - SECSPERDAY / 2 | |
479 | ? t + SECSPERDAY / 2 | |||
480 | : absolute_max_time); | |||
481 | if (cuthitime <= newt) | |||
479 | break; | 482 | break; | |
480 | newt = t + SECSPERHOUR * 12; | |||
481 | newtmp = localtime(&newt); | 483 | newtmp = localtime(&newt); | |
482 | if (newtmp != NULL) | 484 | if (newtmp != NULL) | |
483 | newtm = *newtmp; | 485 | newtm = *newtmp; | |
484 | if ((tmp == NULL || newtmp == NULL) ? (tmp != newtmp) : | 486 | if ((tmp == NULL || newtmp == NULL) ? (tmp != newtmp) : | |
485 | (delta(&newtm, &tm) != (newt - t) || | 487 | (delta(&newtm, &tm) != (newt - t) || | |
486 | newtm.tm_isdst != tm.tm_isdst || | 488 | newtm.tm_isdst != tm.tm_isdst || | |
487 | strcmp(abbr(&newtm), buf) != 0)) { | 489 | strcmp(abbr(&newtm), buf) != 0)) { | |
488 | newt = hunt(argv[i], t, newt); | 490 | newt = hunt(argv[i], t, newt); | |
489 | newtmp = localtime(&newt); | 491 | newtmp = localtime(&newt); | |
490 | if (newtmp != NULL) { | 492 | if (newtmp != NULL) { | |
491 | newtm = *newtmp; | 493 | newtm = *newtmp; | |
492 | (void) strncpy(buf, | 494 | (void) strncpy(buf, | |
493 | abbr(&newtm), | 495 | abbr(&newtm), | |
494 | (sizeof buf) - 1); | 496 | (sizeof buf) - 1); | |
495 | } | 497 | } | |
496 | } | 498 | } | |
497 | t = newt; | 499 | t = newt; | |
498 | tm = newtm; | 500 | tm = newtm; | |
499 | tmp = newtmp; | 501 | tmp = newtmp; | |
500 | } | 502 | } | |
501 | if (!Vflag) { | 503 | if (!Vflag) { | |
502 | t = absolute_max_time; | 504 | t = absolute_max_time; | |
503 | t -= SECSPERHOUR * HOURSPERDAY; | 505 | t -= SECSPERDAY; | |
504 | show(argv[i], t, TRUE); | 506 | show(argv[i], t, TRUE); | |
505 | t += SECSPERHOUR * HOURSPERDAY; | 507 | t += SECSPERDAY; | |
506 | show(argv[i], t, TRUE); | 508 | show(argv[i], t, TRUE); | |
507 | } | 509 | } | |
508 | } | 510 | } | |
509 | if (fflush(stdout) || ferror(stdout)) { | 511 | if (fflush(stdout) || ferror(stdout)) { | |
510 | err(EXIT_FAILURE, _("Error writing standard output")); | 512 | err(EXIT_FAILURE, _("Error writing standard output")); | |
511 | } | 513 | } | |
512 | exit(EXIT_SUCCESS); | 514 | exit(EXIT_SUCCESS); | |
513 | /* If exit fails to exit... */ | 515 | /* If exit fails to exit... */ | |
514 | return EXIT_FAILURE; | 516 | return EXIT_FAILURE; | |
515 | } | 517 | } | |
516 | 518 | |||
517 | static void | |||
518 | checkabsolutes(void) | |||
519 | { | |||
520 | if (absolute_max_time < absolute_min_time) { | |||
521 | (void) fprintf(stderr, | |||
522 | _("%s: use of -v on system with floating time_t other than float or double\n"), | |||
523 | progname); | |||
524 | exit(EXIT_FAILURE); | |||
525 | } | |||
526 | } | |||
527 | ||||
528 | static time_t | 519 | static time_t | |
529 | yeartot(const long y) | 520 | yeartot(const long y) | |
530 | { | 521 | { | |
531 | intmax_t myy; | 522 | intmax_t myy, seconds, years; | |
532 | int_fast32_t seconds; | |||
533 | time_t t; | 523 | time_t t; | |
534 | 524 | |||
535 | myy = EPOCH_YEAR; | 525 | myy = EPOCH_YEAR; | |
536 | t = 0; | 526 | t = 0; | |
537 | while (myy != y) { | 527 | while (myy < y) { | |
538 | if (myy < y) { | 528 | if (SECSPER400YEARS_FITS && 400 <= y - myy) { | |
529 | intmax_t diff400 = (y - myy) / 400; | |||
530 | if (INTMAX_MAX / SECSPER400YEARS < diff400) | |||
531 | return absolute_max_time; | |||
532 | seconds = diff400 * SECSPER400YEARS; | |||
533 | years = diff400 * 400; | |||
534 | } else { | |||
539 | seconds = isleap(myy) ? SECSPERLYEAR : SECSPERNYEAR; | 535 | seconds = isleap(myy) ? SECSPERLYEAR : SECSPERNYEAR; | |
540 | ++myy; | 536 | years = 1; | |
541 | if (t > absolute_max_time - seconds) { | 537 | } | |
542 | t = absolute_max_time; | 538 | myy += years; | |
543 | break; | 539 | if (t > absolute_max_time - seconds) | |
544 | } | 540 | return absolute_max_time; | |
545 | t += seconds; | 541 | t += seconds; | |
542 | } | |||
543 | while (y < myy) { | |||
544 | if (SECSPER400YEARS_FITS && y + 400 <= myy && myy < 0) { | |||
545 | intmax_t diff400 = (myy - y) / 400; | |||
546 | if (INTMAX_MAX / SECSPER400YEARS < diff400) | |||
547 | return absolute_min_time; | |||
548 | seconds = diff400 * SECSPER400YEARS; | |||
549 | years = diff400 * 400; | |||
546 | } else { | 550 | } else { | |
547 | --myy; | 551 | seconds = isleap(myy - 1) ? SECSPERLYEAR : SECSPERNYEAR; | |
548 | seconds = isleap(myy) ? SECSPERLYEAR : SECSPERNYEAR; | 552 | years = 1; | |
549 | if (t < absolute_min_time + seconds) { | |||
550 | t = absolute_min_time; | |||
551 | break; | |||
552 | } | |||
553 | t -= seconds; | |||
554 | } | 553 | } | |
554 | myy -= years; | |||
555 | if (t < absolute_min_time + seconds) | |||
556 | return absolute_min_time; | |||
557 | t -= seconds; | |||
555 | } | 558 | } | |
556 | return t; | 559 | return t; | |
557 | } | 560 | } | |
558 | 561 | |||
559 | static time_t | 562 | static time_t | |
560 | hunt(char *name, time_t lot, time_t hit) | 563 | hunt(char *name, time_t lot, time_t hit) | |
561 | { | 564 | { | |
562 | time_t t; | 565 | time_t t; | |
563 | struct tm lotm; | 566 | struct tm lotm; | |
564 | struct tm * lotmp; | 567 | struct tm * lotmp; | |
565 | struct tm tm; | 568 | struct tm tm; | |
566 | struct tm * tmp; | 569 | struct tm * tmp; | |
567 | char loab[MAX_STRING_LENGTH]; | 570 | char loab[MAX_STRING_LENGTH]; | |
@@ -625,27 +628,27 @@ delta(struct tm *newp, struct tm *oldp) | @@ -625,27 +628,27 @@ delta(struct tm *newp, struct tm *oldp) | |||
625 | 628 | |||
626 | static void | 629 | static void | |
627 | show(char *zone, time_t t, int v) | 630 | show(char *zone, time_t t, int v) | |
628 | { | 631 | { | |
629 | struct tm * tmp; | 632 | struct tm * tmp; | |
630 | 633 | |||
631 | (void) printf("%-*s ", (int) longest, zone); | 634 | (void) printf("%-*s ", (int) longest, zone); | |
632 | if (v) { | 635 | if (v) { | |
633 | tmp = gmtime(&t); | 636 | tmp = gmtime(&t); | |
634 | if (tmp == NULL) { | 637 | if (tmp == NULL) { | |
635 | (void) printf(tformat(), t); | 638 | (void) printf(tformat(), t); | |
636 | } else { | 639 | } else { | |
637 | dumptime(tmp); | 640 | dumptime(tmp); | |
638 | (void) printf(" UTC"); | 641 | (void) printf(" UT"); | |
639 | } | 642 | } | |
640 | (void) printf(" = "); | 643 | (void) printf(" = "); | |
641 | } | 644 | } | |
642 | tmp = my_localtime(&t); | 645 | tmp = my_localtime(&t); | |
643 | dumptime(tmp); | 646 | dumptime(tmp); | |
644 | if (tmp != NULL) { | 647 | if (tmp != NULL) { | |
645 | if (*abbr(tmp) != '\0') | 648 | if (*abbr(tmp) != '\0') | |
646 | (void) printf(" %s", abbr(tmp)); | 649 | (void) printf(" %s", abbr(tmp)); | |
647 | if (v) { | 650 | if (v) { | |
648 | (void) printf(" isdst=%d", tmp->tm_isdst); | 651 | (void) printf(" isdst=%d", tmp->tm_isdst); | |
649 | #ifdef TM_GMTOFF | 652 | #ifdef TM_GMTOFF | |
650 | (void) printf(" gmtoff=%ld", tmp->TM_GMTOFF); | 653 | (void) printf(" gmtoff=%ld", tmp->TM_GMTOFF); | |
651 | #endif /* defined TM_GMTOFF */ | 654 | #endif /* defined TM_GMTOFF */ | |
@@ -666,31 +669,26 @@ abbr(struct tm *tmp) | @@ -666,31 +669,26 @@ abbr(struct tm *tmp) | |||
666 | return &nada; | 669 | return &nada; | |
667 | result = tzname[tmp->tm_isdst]; | 670 | result = tzname[tmp->tm_isdst]; | |
668 | return (result == NULL) ? &nada : result; | 671 | return (result == NULL) ? &nada : result; | |
669 | } | 672 | } | |
670 | 673 | |||
671 | /* | 674 | /* | |
672 | ** The code below can fail on certain theoretical systems; | 675 | ** The code below can fail on certain theoretical systems; | |
673 | ** it works on all known real-world systems as of 2004-12-30. | 676 | ** it works on all known real-world systems as of 2004-12-30. | |
674 | */ | 677 | */ | |
675 | 678 | |||
676 | static const char * | 679 | static const char * | |
677 | tformat(void) | 680 | tformat(void) | |
678 | { | 681 | { | |
679 | if (0.5 == (time_t) 0.5) { /* floating */ | |||
680 | if (sizeof (time_t) > sizeof (double)) | |||
681 | return "%Lg"; | |||
682 | return "%g"; | |||
683 | } | |||
684 | if (0 > (time_t) -1) { /* signed */ | 682 | if (0 > (time_t) -1) { /* signed */ | |
685 | if (sizeof (time_t) == sizeof (intmax_t)) | 683 | if (sizeof (time_t) == sizeof (intmax_t)) | |
686 | return "%"PRIdMAX; | 684 | return "%"PRIdMAX; | |
687 | if (sizeof (time_t) > sizeof (long)) | 685 | if (sizeof (time_t) > sizeof (long)) | |
688 | return "%lld"; | 686 | return "%lld"; | |
689 | if (sizeof (time_t) > sizeof (int)) | 687 | if (sizeof (time_t) > sizeof (int)) | |
690 | return "%ld"; | 688 | return "%ld"; | |
691 | return "%d"; | 689 | return "%d"; | |
692 | } | 690 | } | |
693 | #ifdef PRIuMAX | 691 | #ifdef PRIuMAX | |
694 | if (sizeof (time_t) == sizeof (uintmax_t)) | 692 | if (sizeof (time_t) == sizeof (uintmax_t)) | |
695 | return "%"PRIuMAX; | 693 | return "%"PRIuMAX; | |
696 | #endif | 694 | #endif |
--- src/lib/libc/time/zic.8 2012/08/09 12:38:26 1.20
+++ src/lib/libc/time/zic.8 2013/09/20 19:06:54 1.21
@@ -1,15 +1,15 @@ | @@ -1,15 +1,15 @@ | |||
1 | .\" $NetBSD: zic.8,v 1.20 2012/08/09 12:38:26 christos Exp $ | 1 | .\" $NetBSD: zic.8,v 1.21 2013/09/20 19:06:54 christos Exp $ | |
2 | .Dd December 20, 2003 | 2 | .Dd September 20, 2013 | |
3 | .Dt ZIC 8 | 3 | .Dt ZIC 8 | |
4 | .Os | 4 | .Os | |
5 | .Sh NAME | 5 | .Sh NAME | |
6 | .Nm zic | 6 | .Nm zic | |
7 | .Nd time zone compiler | 7 | .Nd time zone compiler | |
8 | .Sh SYNOPSIS | 8 | .Sh SYNOPSIS | |
9 | .Nm | 9 | .Nm | |
10 | .Op Fl \-version | 10 | .Op Fl \-version | |
11 | .Op Fl d Ar directory | 11 | .Op Fl d Ar directory | |
12 | .Op Fl L Ar leapsecondfilename | 12 | .Op Fl L Ar leapsecondfilename | |
13 | .Op Fl l Ar localtime | 13 | .Op Fl l Ar localtime | |
14 | .Op Fl p Ar posixrules | 14 | .Op Fl p Ar posixrules | |
15 | .Op Fl s | 15 | .Op Fl s | |
@@ -43,42 +43,63 @@ Use the given time zone as local time. | @@ -43,42 +43,63 @@ Use the given time zone as local time. | |||
43 | will act as if the input contained a link line of the form | 43 | will act as if the input contained a link line of the form | |
44 | .Dl Link timezone localtime | 44 | .Dl Link timezone localtime | |
45 | .It Fl p Ar timezone | 45 | .It Fl p Ar timezone | |
46 | Use the given time zone's rules when handling POSIX-format | 46 | Use the given time zone's rules when handling POSIX-format | |
47 | time zone environment variables. | 47 | time zone environment variables. | |
48 | .Nm | 48 | .Nm | |
49 | will act as if the input contained a link line of the form | 49 | will act as if the input contained a link line of the form | |
50 | .Dl Link timezone posixrules | 50 | .Dl Link timezone posixrules | |
51 | .It Fl s | 51 | .It Fl s | |
52 | Limit time values stored in output files to values that are the same | 52 | Limit time values stored in output files to values that are the same | |
53 | whether they're taken to be signed or unsigned. | 53 | whether they're taken to be signed or unsigned. | |
54 | You can use this option to generate SVVS-compatible files. | 54 | You can use this option to generate SVVS-compatible files. | |
55 | .It Fl v | 55 | .It Fl v | |
56 | Complain if a year that appears in a data file is outside the range | 56 | Be more verbose, and complain about the following situations: | |
57 | of years representable by | 57 | .Bl -dash | |
58 | .Xr time 3 | 58 | .It The input data specifies a link to a link. | |
59 | values. | 59 | .It A year that appears in a data file is outside the range | |
60 | Also complain if a time of 24:00 | 60 | .It A time of 24:00 or more appears in the input. | |
61 | .Pq which cannot be handled by pre-1998 versions of Nm | 61 | Pre-1998 versions of | |
62 | appears in the input. | 62 | .Xr zic 8 | |
63 | prohibit 24:00, and pre-2007 versions prohibit times greater than 24:00. | |||
64 | .It A rule goes past the start or end of the month. | |||
65 | Pre-2004 versions of | |||
66 | .Xr zic 8 | |||
67 | prohibit this. | |||
68 | .It The output file does not contain all the information about the | |||
69 | long-term future of a zone, because the future cannot be summarized as | |||
70 | an extended POSIX TZ string. | |||
71 | For example, as of 2013 this problem | |||
72 | occurs for Iran's daylight-saving rules for the predicted future, as | |||
73 | these rules are based on the Iranian calendar, which cannot be | |||
74 | represented. | |||
75 | .It The output contains data that may not be handled properly by client | |||
76 | code designed for older | |||
77 | .Xr zic 8 | |||
78 | output formats. | |||
79 | These compatibility issues affect only time stamps | |||
80 | before 1970 or after the start of 2038. | |||
81 | .It A time zone abbreviation has fewer than 3 characters. | |||
82 | POSIX requires at least 3. | |||
83 | .El | |||
63 | .It Fl y Ar command | 84 | .It Fl y Ar command | |
64 | Use the given | 85 | Use the given | |
65 | .Ar command | 86 | .Ar command | |
66 | rather than | 87 | rather than | |
67 | .Em yearistype | 88 | .Em yearistype | |
68 | when checking year types (see below). | 89 | when checking year types (see below). | |
69 | .Pp | 90 | .Pp | |
70 | Input lines are made up of fields. | 91 | Input lines are made up of fields. | |
71 | Fields are separated from one another by any number of white space characters. | 92 | Fields are separated from one another by one or more white space characters. | |
72 | Leading and trailing white space on input lines is ignored. | 93 | Leading and trailing white space on input lines is ignored. | |
73 | An unquoted sharp character (#) in the input introduces a comment which extends | 94 | An unquoted sharp character (#) in the input introduces a comment which extends | |
74 | to the end of the line the sharp character appears on. | 95 | to the end of the line the sharp character appears on. | |
75 | White space characters and sharp characters may be enclosed in double | 96 | White space characters and sharp characters may be enclosed in double | |
76 | quotes | 97 | quotes | |
77 | .Pq \&" | 98 | .Pq \&" | |
78 | .\" XXX " | 99 | .\" XXX " | |
79 | if they're to be used as part of a field. | 100 | if they're to be used as part of a field. | |
80 | Any line that is blank (after comment stripping) is ignored. | 101 | Any line that is blank (after comment stripping) is ignored. | |
81 | Non-blank lines are expected to be of one of three types: | 102 | Non-blank lines are expected to be of one of three types: | |
82 | rule lines, zone lines, and link lines. | 103 | rule lines, zone lines, and link lines. | |
83 | .Pp | 104 | .Pp | |
84 | Names (such as month names) must be in English and are case insensitive. | 105 | Names (such as month names) must be in English and are case insensitive. | |
@@ -225,55 +246,55 @@ the variable part is null. | @@ -225,55 +246,55 @@ the variable part is null. | |||
225 | .Pp | 246 | .Pp | |
226 | A zone line has the form | 247 | A zone line has the form | |
227 | .sp | 248 | .sp | |
228 | .Dl Zone NAME GMTOFF RULES/SAVE FORMAT [UNTILYEAR [MONTH [DAY [TIME]]]] | 249 | .Dl Zone NAME GMTOFF RULES/SAVE FORMAT [UNTILYEAR [MONTH [DAY [TIME]]]] | |
229 | For example: | 250 | For example: | |
230 | .Dl Zone Australia/Adelaide 9:30 Aus CST 1971 Oct 31 2:00 | 251 | .Dl Zone Australia/Adelaide 9:30 Aus CST 1971 Oct 31 2:00 | |
231 | The fields that make up a zone line are: | 252 | The fields that make up a zone line are: | |
232 | .Bl -tag -width "RULES/SAVE" -compact | 253 | .Bl -tag -width "RULES/SAVE" -compact | |
233 | .It NAME | 254 | .It NAME | |
234 | The name of the time zone. | 255 | The name of the time zone. | |
235 | This is the name used in creating the time conversion information file for the | 256 | This is the name used in creating the time conversion information file for the | |
236 | zone. | 257 | zone. | |
237 | .It GMTOFF | 258 | .It GMTOFF | |
238 | The amount of time to add to UTC to get standard time in this zone. | 259 | The amount of time to add to UT to get standard time in this zone. | |
239 | This field has the same format as the | 260 | This field has the same format as the | |
240 | .Em AT | 261 | .Em AT | |
241 | and | 262 | and | |
242 | .Em SAVE | 263 | .Em SAVE | |
243 | fields of rule lines; | 264 | fields of rule lines; | |
244 | begin the field with a minus sign if time must be subtracted from UTC. | 265 | begin the field with a minus sign if time must be subtracted from UT. | |
245 | .It RULES/SAVE | 266 | .It RULES/SAVE | |
246 | The name of the rule(s) that apply in the time zone or, | 267 | The name of the rule(s) that apply in the time zone or, | |
247 | alternatively, an amount of time to add to local standard time. | 268 | alternatively, an amount of time to add to local standard time. | |
248 | If this field is | 269 | If this field is | |
249 | .Em \&- | 270 | .Em \&- | |
250 | then standard time always applies in the time zone. | 271 | then standard time always applies in the time zone. | |
251 | .It FORMAT | 272 | .It FORMAT | |
252 | The format for time zone abbreviations in this time zone. | 273 | The format for time zone abbreviations in this time zone. | |
253 | The pair of characters | 274 | The pair of characters | |
254 | .Em %s | 275 | .Em %s | |
255 | is used to show where the | 276 | is used to show where the | |
256 | .Dq variable part | 277 | .Dq variable part | |
257 | of the time zone abbreviation goes. | 278 | of the time zone abbreviation goes. | |
258 | Alternatively, | 279 | Alternatively, | |
259 | a slash | 280 | a slash | |
260 | .Pq \&/ | 281 | .Pq \&/ | |
261 | separates standard and daylight abbreviations. | 282 | separates standard and daylight abbreviations. | |
262 | .It UNTILYEAR [MONTH [DAY [TIME]]] | 283 | .It UNTILYEAR [MONTH [DAY [TIME]]] | |
263 | The time at which the UTC offset or the rule(s) change for a location. | 284 | The time at which the UT offset or the rule(s) change for a location. | |
264 | It is specified as a year, a month, a day, and a time of day. | 285 | It is specified as a year, a month, a day, and a time of day. | |
265 | If this is specified, | 286 | If this is specified, | |
266 | the time zone information is generated from the given UTC offset | 287 | the time zone information is generated from the given UT offset | |
267 | and rule change until the time specified. | 288 | and rule change until the time specified. | |
268 | The month, day, and time of day have the same format as the IN, ON, and AT | 289 | The month, day, and time of day have the same format as the IN, ON, and AT | |
269 | fields of a rule; trailing fields can be omitted, and default to the | 290 | fields of a rule; trailing fields can be omitted, and default to the | |
270 | earliest possible value for the missing fields. | 291 | earliest possible value for the missing fields. | |
271 | .El | 292 | .El | |
272 | The next line must be a | 293 | The next line must be a | |
273 | .Dq continuation | 294 | .Dq continuation | |
274 | line; this has the same form as a zone line except that the | 295 | line; this has the same form as a zone line except that the | |
275 | string | 296 | string | |
276 | .Dq Zone | 297 | .Dq Zone | |
277 | and the name are omitted, as the continuation line will | 298 | and the name are omitted, as the continuation line will | |
278 | place information starting at the time specified as the | 299 | place information starting at the time specified as the | |
279 | .Em until | 300 | .Em until | |
@@ -288,26 +309,29 @@ A link line has the form | @@ -288,26 +309,29 @@ A link line has the form | |||
288 | For example: | 309 | For example: | |
289 | .Dl Link Europe/Istanbul Asia/Istanbul | 310 | .Dl Link Europe/Istanbul Asia/Istanbul | |
290 | The | 311 | The | |
291 | .Em LINK-FROM | 312 | .Em LINK-FROM | |
292 | field should appear as the | 313 | field should appear as the | |
293 | .Em NAME | 314 | .Em NAME | |
294 | field in some zone line; | 315 | field in some zone line; | |
295 | the | 316 | the | |
296 | .Em LINK-TO | 317 | .Em LINK-TO | |
297 | field is used as an alternative name for that zone. | 318 | field is used as an alternative name for that zone. | |
298 | .Pp | 319 | .Pp | |
299 | Except for continuation lines, | 320 | Except for continuation lines, | |
300 | lines may appear in any order in the input. | 321 | lines may appear in any order in the input. | |
322 | However, the behavior is unspecified if multiple zone or link lines | |||
323 | define the same name, or if the source of one link line is the target | |||
324 | of another. | |||
301 | .Pp | 325 | .Pp | |
302 | Lines in the file that describes leap seconds have the following form: | 326 | Lines in the file that describes leap seconds have the following form: | |
303 | .Dl Leap YEAR MONTH DAY HH:MM:SS CORR R/S | 327 | .Dl Leap YEAR MONTH DAY HH:MM:SS CORR R/S | |
304 | For example: | 328 | For example: | |
305 | .Dl Leap 1974 Dec 31 23:59:60 + S | 329 | .Dl Leap 1974 Dec 31 23:59:60 + S | |
306 | The | 330 | The | |
307 | .Em YEAR , | 331 | .Em YEAR , | |
308 | .Em MONTH , | 332 | .Em MONTH , | |
309 | .Em DAY , | 333 | .Em DAY , | |
310 | and | 334 | and | |
311 | .Em HH:MM:SS | 335 | .Em HH:MM:SS | |
312 | fields tell when the leap second happened. | 336 | fields tell when the leap second happened. | |
313 | The | 337 | The | |
@@ -338,91 +362,88 @@ should be (an abbreviation of) | @@ -338,91 +362,88 @@ should be (an abbreviation of) | |||
338 | if the leap second time given by the other fields should be interpreted as UTC | 362 | if the leap second time given by the other fields should be interpreted as UTC | |
339 | or | 363 | or | |
340 | (an abbreviation of) | 364 | (an abbreviation of) | |
341 | .Dq Rolling | 365 | .Dq Rolling | |
342 | if the leap second time given by the other fields should be interpreted as | 366 | if the leap second time given by the other fields should be interpreted as | |
343 | local wall clock time. | 367 | local wall clock time. | |
344 | .El | 368 | .El | |
345 | .Sh EXTENDED EXAMPLE | 369 | .Sh EXTENDED EXAMPLE | |
346 | Here is an extended example of | 370 | Here is an extended example of | |
347 | .Ic zic | 371 | .Ic zic | |
348 | input, intended to illustrate many of its features. | 372 | input, intended to illustrate many of its features. | |
349 | .Bl -column -compact "# Rule" "Swiss" "FROM" "1995" "TYPE" "Oct" "lastSun" "1:00u" "SAVE" "LETTER/S" | 373 | .Bl -column -compact "# Rule" "Swiss" "FROM" "1995" "TYPE" "Oct" "lastSun" "1:00u" "SAVE" "LETTER/S" | |
350 | .It # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S | 374 | .It # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S | |
351 | .It Rule Swiss 1940 only - Nov 2 0:00 1:00 S | 375 | .It Rule Swiss 1941 1942 - May Mon>=1 1:00 1:00 S | |
352 | .It Rule Swiss 1940 only - Dec 31 0:00 0 - | 376 | .It Rule Swiss 1941 1942 - Oct Mon>=1 2:00 0 - | |
353 | .It Rule Swiss 1941 1942 - May Sun>=1 2:00 1:00 S | |||
354 | .It Rule Swiss 1941 1942 - Oct Sun>=1 0:00 0 | |||
355 | .Pp | 377 | .Pp | |
356 | .It Rule EU 1977 1980 - Apr Sun>=1 1:00u 1:00 S | 378 | .It Rule EU 1977 1980 - Apr Sun>=1 1:00u 1:00 S | |
357 | .It Rule EU 1977 only - Sep lastSun 1:00u 0 - | 379 | .It Rule EU 1977 only - Sep lastSun 1:00u 0 - | |
358 | .It Rule EU 1978 only - Oct 1 1:00u 0 - | 380 | .It Rule EU 1978 only - Oct 1 1:00u 0 - | |
359 | .It Rule EU 1979 1995 - Sep lastSun 1:00u 0 - | 381 | .It Rule EU 1979 1995 - Sep lastSun 1:00u 0 - | |
360 | .It Rule EU 1981 max - Mar lastSun 1:00u 1:00 S | 382 | .It Rule EU 1981 max - Mar lastSun 1:00u 1:00 S | |
361 | .It Rule EU 1996 max - Oct lastSun 1:00u 0 - | 383 | .It Rule EU 1996 max - Oct lastSun 1:00u 0 - | |
362 | .El | 384 | .El | |
363 | .Pp | 385 | .Pp | |
364 | .Bl -column -compact "# Zone" "Europe/Zurich" "0:29:44" "RULES" "FORMAT" "UNTIL" | 386 | .Bl -column -compact "# Zone" "Europe/Zurich" "0:34:08" "RULES/SAVE" "FORMAT" "UNTIL" | |
365 | .It # Zone NAME GMTOFF RULES FORMAT UNTIL | 387 | .It # Zone NAME GMTOFF RULES/SAVE FORMAT UNTIL | |
366 | .It Zone Europe/Zurich 0:34:08 - LMT 1848 Sep 12 | 388 | .It Zone Europe/Zurich 0:34:08 - LMT 1853 Jul 16 | |
367 | .It 0:29:44 - BMT 1894 Jun | 389 | .It 0:29:44 - BMT 1894 Jun | |
368 | .It 1:00 Swiss CE%sT 1981 | 390 | .It 1:00 Swiss CE%sT 1981 | |
369 | .It 1:00 EU CE%sT | 391 | .It 1:00 EU CE%sT | |
370 | .It Link Europe/Zurich Switzerland | 392 | .It Link Europe/Zurich Switzerland | |
371 | .El | 393 | .El | |
372 | .Pp | 394 | .Pp | |
373 | In this example, the zone is named Europe/Zurich but it has an alias | 395 | In this example, the zone is named Europe/Zurich but it has an alias | |
374 | as Switzerland. | 396 | as Switzerland. | |
375 | Zurich was 34 minutes and 8 seconds west of GMT until | 397 | This example says that Zurich was 34 minutes and 8 | |
376 | 1848-09-12 at 00:00, when the offset changed to 29 minutes and 44 | 398 | seconds west of UT until 1853-07-16 at 00:00, when the legal offset | |
377 | seconds. | 399 | was changed to 7\(de\|26\(fm\|22.50\(sd; although this works out to | |
378 | After 1894-06-01 at 00:00 Swiss daylight saving rules (defined | 400 | 0:29:45.50, the input format cannot represent fractional seconds so it | |
379 | with lines beginning with "Rule Swiss") apply, and the GMT offset | 401 | is rounded here. | |
402 | After 1894-06-01 at 00:00 Swiss daylight saving rules | |||
403 | (defined with lines beginning with "Rule Swiss") apply, and the UT offset | |||
380 | became one hour. | 404 | became one hour. | |
381 | From 1981 to the present, EU daylight saving rules have | 405 | From 1981 to the present, EU daylight saving rules have | |
382 | applied, and the UTC offset has remained at one hour. | 406 | applied, and the UTC offset has remained at one hour. | |
383 | .Pp | 407 | .Pp | |
384 | In 1940, daylight saving time applied from November 2 at 00:00 to | 408 | In 1941 and 1942, daylight saving time applied from the first Monday | |
385 | December 31 at 00:00. | 409 | in May at 01:00 to the first Monday in October at 02:00. | |
386 | In 1941 and 1942, daylight saving time applied | |||
387 | from the first Sunday in May at 02:00 to the first Sunday in October | |||
388 | at 00:00. | |||
389 | The pre-1981 EU daylight-saving rules have no effect | 410 | The pre-1981 EU daylight-saving rules have no effect | |
390 | here, but are included for completeness. | 411 | here, but are included for completeness. | |
391 | Since 1981, daylight | 412 | Since 1981, daylight | |
392 | saving has begun on the last Sunday in March at 01:00 UTC. | 413 | saving has begun on the last Sunday in March at 01:00 UTC. | |
393 | Until 1995 it ended the last Sunday in September at 01:00 UTC, | 414 | Until 1995 it ended the last Sunday in September at 01:00 UTC, | |
394 | but this changed to the last Sunday in October starting in 1996. | 415 | but this changed to the last Sunday in October starting in 1996. | |
395 | .Pp | 416 | .Pp | |
396 | For purposes of | 417 | For purposes of | |
397 | display, "LMT" and "BMT" were initially used, respectively. | 418 | display, "LMT" and "BMT" were initially used, respectively. | |
398 | Since | 419 | Since | |
399 | Swiss rules and later EU rules were applied, the display name for the | 420 | Swiss rules and later EU rules were applied, the display name for the | |
400 | timezone has been CET for standard time and CEST for daylight saving | 421 | timezone has been CET for standard time and CEST for daylight saving | |
401 | time. | 422 | time. | |
402 | .Sh NOTES | 423 | .Sh NOTES | |
403 | For areas with more than two types of local time, | 424 | For areas with more than two types of local time, | |
404 | you may need to use local standard time in the | 425 | you may need to use local standard time in the | |
405 | .Em AT | 426 | .Em AT | |
406 | field of the earliest transition time's rule to ensure that | 427 | field of the earliest transition time's rule to ensure that | |
407 | the earliest transition time recorded in the compiled file is correct. | 428 | the earliest transition time recorded in the compiled file is correct. | |
408 | .Pp | 429 | .Pp | |
409 | If, | 430 | If, | |
410 | for a particular zone, | 431 | for a particular zone, | |
411 | a clock advance caused by the start of daylight saving | 432 | a clock advance caused by the start of daylight saving | |
412 | coincides with and is equal to | 433 | coincides with and is equal to | |
413 | a clock retreat caused by a change in UTC offset, | 434 | a clock retreat caused by a change in UT offset, | |
414 | .Ic zic | 435 | .Ic zic | |
415 | produces a single transition to daylight saving at the new UTC offset | 436 | produces a single transition to daylight saving at the new UT offset | |
416 | (without any change in wall clock time). | 437 | (without any change in wall clock time). | |
417 | To get separate transitions | 438 | To get separate transitions | |
418 | use multiple zone continuation lines | 439 | use multiple zone continuation lines | |
419 | specifying transition instants using universal time. | 440 | specifying transition instants using universal time. | |
420 | .Sh FILES | 441 | .Sh FILES | |
421 | .Pa /usr/share/zoneinfo | 442 | .Pa /usr/share/zoneinfo | |
422 | - standard directory used for created files | 443 | - standard directory used for created files | |
423 | .Sh SEE ALSO | 444 | .Sh SEE ALSO | |
424 | .Xr ctime 3 , | 445 | .Xr ctime 3 , | |
425 | .Xr tzfile 5 , | 446 | .Xr tzfile 5 , | |
426 | .Xr zdump 8 | 447 | .Xr zdump 8 | |
427 | .\" @(#)zic.8 8.6 | 448 | .\" @(#)zic.8 8.6 | |
428 | .\" This file is in the public domain, so clarified as of | 449 | .\" This file is in the public domain, so clarified as of |
--- src/lib/libc/time/zic.c 2013/08/06 05:48:39 1.42
+++ src/lib/libc/time/zic.c 2013/09/20 19:06:54 1.43
@@ -1,55 +1,57 @@ | @@ -1,55 +1,57 @@ | |||
1 | /* $NetBSD: zic.c,v 1.42 2013/08/06 05:48:39 christos Exp $ */ | 1 | /* $NetBSD: zic.c,v 1.43 2013/09/20 19:06:54 christos Exp $ */ | |
2 | /* | 2 | /* | |
3 | ** This file is in the public domain, so clarified as of | 3 | ** This file is in the public domain, so clarified as of | |
4 | ** 2006-07-17 by Arthur David Olson. | 4 | ** 2006-07-17 by Arthur David Olson. | |
5 | */ | 5 | */ | |
6 | 6 | |||
7 | #if HAVE_NBTOOL_CONFIG_H | 7 | #if HAVE_NBTOOL_CONFIG_H | |
8 | #include "nbtool_config.h" | 8 | #include "nbtool_config.h" | |
9 | #endif | 9 | #endif | |
10 | 10 | |||
11 | #include <sys/cdefs.h> | 11 | #include <sys/cdefs.h> | |
12 | #ifndef lint | 12 | #ifndef lint | |
13 | __RCSID("$NetBSD: zic.c,v 1.42 2013/08/06 05:48:39 christos Exp $"); | 13 | __RCSID("$NetBSD: zic.c,v 1.43 2013/09/20 19:06:54 christos Exp $"); | |
14 | #endif /* !defined lint */ | 14 | #endif /* !defined lint */ | |
15 | 15 | |||
16 | #include "version.h" | 16 | #include "version.h" | |
17 | #include "private.h" | 17 | #include "private.h" | |
18 | #include "locale.h" | 18 | #include "locale.h" | |
19 | #include "tzfile.h" | 19 | #include "tzfile.h" | |
20 | 20 | |||
21 | #define ZIC_VERSION '2' | 21 | #include <stdarg.h> | |
22 | #include <unistd.h> | |||
23 | ||||
24 | #define ZIC_VERSION_PRE_2013 '2' | |||
25 | #define ZIC_VERSION '3' | |||
22 | 26 | |||
23 | typedef int_fast64_t zic_t; | 27 | typedef int_fast64_t zic_t; | |
24 | #define ZIC_MIN INT_FAST64_MIN | 28 | #define ZIC_MIN INT_FAST64_MIN | |
25 | #define ZIC_MAX INT_FAST64_MAX | 29 | #define ZIC_MAX INT_FAST64_MAX | |
26 | #define SCNdZIC SCNdFAST64 | 30 | #define SCNdZIC SCNdFAST64 | |
27 | 31 | |||
28 | #ifndef ZIC_MAX_ABBR_LEN_WO_WARN | 32 | #ifndef ZIC_MAX_ABBR_LEN_WO_WARN | |
29 | #define ZIC_MAX_ABBR_LEN_WO_WARN 6 | 33 | #define ZIC_MAX_ABBR_LEN_WO_WARN 6 | |
30 | #endif /* !defined ZIC_MAX_ABBR_LEN_WO_WARN */ | 34 | #endif /* !defined ZIC_MAX_ABBR_LEN_WO_WARN */ | |
31 | 35 | |||
32 | #if HAVE_SYS_STAT_H | 36 | #if HAVE_SYS_STAT_H | |
33 | #include "sys/stat.h" | 37 | #include "sys/stat.h" | |
34 | #endif | 38 | #endif | |
35 | #ifdef S_IRUSR | 39 | #ifdef S_IRUSR | |
36 | #define MKDIR_UMASK (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) | 40 | #define MKDIR_UMASK (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) | |
37 | #else | 41 | #else | |
38 | #define MKDIR_UMASK 0755 | 42 | #define MKDIR_UMASK 0755 | |
39 | #endif | 43 | #endif | |
40 | 44 | |||
41 | #include "unistd.h" | |||
42 | ||||
43 | /* | 45 | /* | |
44 | ** On some ancient hosts, predicates like `isspace(C)' are defined | 46 | ** On some ancient hosts, predicates like `isspace(C)' are defined | |
45 | ** only if isascii(C) || C == EOF. Modern hosts obey the C Standard, | 47 | ** only if isascii(C) || C == EOF. Modern hosts obey the C Standard, | |
46 | ** which says they are defined only if C == ((unsigned char) C) || C == EOF. | 48 | ** which says they are defined only if C == ((unsigned char) C) || C == EOF. | |
47 | ** Neither the C Standard nor Posix require that `isascii' exist. | 49 | ** Neither the C Standard nor Posix require that `isascii' exist. | |
48 | ** For portability, we check both ancient and modern requirements. | 50 | ** For portability, we check both ancient and modern requirements. | |
49 | ** If isascii is not defined, the isascii check succeeds trivially. | 51 | ** If isascii is not defined, the isascii check succeeds trivially. | |
50 | */ | 52 | */ | |
51 | #include "ctype.h" | 53 | #include "ctype.h" | |
52 | #ifndef isascii | 54 | #ifndef isascii | |
53 | #define isascii(x) 1 | 55 | #define isascii(x) 1 | |
54 | #endif | 56 | #endif | |
55 | 57 | |||
@@ -125,27 +127,26 @@ static void associate(void); | @@ -125,27 +127,26 @@ static void associate(void); | |||
125 | static void dolink(const char * fromfield, const char * tofield); | 127 | static void dolink(const char * fromfield, const char * tofield); | |
126 | static char ** getfields(char * buf); | 128 | static char ** getfields(char * buf); | |
127 | static zic_t gethms(const char * string, const char * errstrng, | 129 | static zic_t gethms(const char * string, const char * errstrng, | |
128 | int signable); | 130 | int signable); | |
129 | static void infile(const char * filename); | 131 | static void infile(const char * filename); | |
130 | static void inleap(char ** fields, int nfields); | 132 | static void inleap(char ** fields, int nfields); | |
131 | static void inlink(char ** fields, int nfields); | 133 | static void inlink(char ** fields, int nfields); | |
132 | static void inrule(char ** fields, int nfields); | 134 | static void inrule(char ** fields, int nfields); | |
133 | static int inzcont(char ** fields, int nfields); | 135 | static int inzcont(char ** fields, int nfields); | |
134 | static int inzone(char ** fields, int nfields); | 136 | static int inzone(char ** fields, int nfields); | |
135 | static int inzsub(char ** fields, int nfields, int iscont); | 137 | static int inzsub(char ** fields, int nfields, int iscont); | |
136 | static int itsdir(const char * name); | 138 | static int itsdir(const char * name); | |
137 | static int lowerit(int c); | 139 | static int lowerit(int c); | |
138 | int main(int, char **); | |||
139 | static int mkdirs(char * filename); | 140 | static int mkdirs(char * filename); | |
140 | static void newabbr(const char * abbr); | 141 | static void newabbr(const char * abbr); | |
141 | static zic_t oadd(zic_t t1, zic_t t2); | 142 | static zic_t oadd(zic_t t1, zic_t t2); | |
142 | static void outzone(const struct zone * zp, int ntzones); | 143 | static void outzone(const struct zone * zp, int ntzones); | |
143 | static int rcomp(const void * leftp, const void * rightp); | 144 | static int rcomp(const void * leftp, const void * rightp); | |
144 | static zic_t rpytime(const struct rule * rp, zic_t wantedy); | 145 | static zic_t rpytime(const struct rule * rp, zic_t wantedy); | |
145 | static void rulesub(struct rule * rp, | 146 | static void rulesub(struct rule * rp, | |
146 | const char * loyearp, const char * hiyearp, | 147 | const char * loyearp, const char * hiyearp, | |
147 | const char * typep, const char * monthp, | 148 | const char * typep, const char * monthp, | |
148 | const char * dayp, const char * timep); | 149 | const char * dayp, const char * timep); | |
149 | static zic_t tadd(zic_t t1, zic_t t2); | 150 | static zic_t tadd(zic_t t1, zic_t t2); | |
150 | static int yearistype(int year, const char * type); | 151 | static int yearistype(int year, const char * type); | |
151 | static int atcomp(const void *avp, const void *bvp); | 152 | static int atcomp(const void *avp, const void *bvp); | |
@@ -395,52 +396,60 @@ eats(const char *const name, const int n | @@ -395,52 +396,60 @@ eats(const char *const name, const int n | |||
395 | { | 396 | { | |
396 | filename = name; | 397 | filename = name; | |
397 | linenum = num; | 398 | linenum = num; | |
398 | rfilename = rname; | 399 | rfilename = rname; | |
399 | rlinenum = rnum; | 400 | rlinenum = rnum; | |
400 | } | 401 | } | |
401 | 402 | |||
402 | static void | 403 | static void | |
403 | eat(const char *const name, const int num) | 404 | eat(const char *const name, const int num) | |
404 | { | 405 | { | |
405 | eats(name, num, NULL, -1); | 406 | eats(name, num, NULL, -1); | |
406 | } | 407 | } | |
407 | 408 | |||
408 | static void | 409 | static void ATTRIBUTE_FORMAT((printf, 1, 0)) | |
409 | error(const char *const string) | 410 | verror(const char *const string, va_list args) | |
410 | { | 411 | { | |
411 | /* | 412 | /* | |
412 | ** Match the format of "cc" to allow sh users to | 413 | ** Match the format of "cc" to allow sh users to | |
413 | ** zic ... 2>&1 | error -t "*" -v | 414 | ** zic ... 2>&1 | error -t "*" -v | |
414 | ** on BSD systems. | 415 | ** on BSD systems. | |
415 | */ | 416 | */ | |
416 | (void) fprintf(stderr, _("\"%s\", line %d: %s"), | 417 | fprintf(stderr, _("\"%s\", line %d: "), filename, linenum); | |
417 | filename, linenum, string); | 418 | vfprintf(stderr, string, args); | |
418 | if (rfilename != NULL) | 419 | if (rfilename != NULL) | |
419 | (void) fprintf(stderr, _(" (rule from \"%s\", line %d)"), | 420 | (void) fprintf(stderr, _(" (rule from \"%s\", line %d)"), | |
420 | rfilename, rlinenum); | 421 | rfilename, rlinenum); | |
421 | (void) fprintf(stderr, "\n"); | 422 | (void) fprintf(stderr, "\n"); | |
422 | ++errors; | 423 | ++errors; | |
423 | } | 424 | } | |
424 | 425 | |||
425 | static void | 426 | static void ATTRIBUTE_FORMAT((printf, 1, 2)) | |
426 | warning(const char *const string) | 427 | error(const char *const string, ...) | |
427 | { | 428 | { | |
428 | char * cp; | 429 | va_list args; | |
429 | 430 | va_start(args, string); | ||
430 | cp = ecpyalloc(_("warning: ")); | 431 | verror(string, args); | |
431 | cp = ecatalloc(cp, string); | 432 | va_end(args); | |
432 | error(cp); | 433 | } | |
433 | free(cp); | 434 | ||
435 | static void ATTRIBUTE_FORMAT((printf, 1, 2)) | |||
436 | warning(const char *const string, ...) | |||
437 | { | |||
438 | va_list args; | |||
439 | fprintf(stderr, _("warning: ")); | |||
440 | va_start(args, string); | |||
441 | verror(string, args); | |||
442 | va_end(args); | |||
434 | --errors; | 443 | --errors; | |
435 | } | 444 | } | |
436 | 445 | |||
437 | static _Noreturn void | 446 | static _Noreturn void | |
438 | usage(FILE *stream, int status) | 447 | usage(FILE *stream, int status) | |
439 | { | 448 | { | |
440 | (void) fprintf(stream, _("%s: usage is %s \ | 449 | (void) fprintf(stream, _("%s: usage is %s \ | |
441 | [ --version ] [ --help ] [ -v ] [ -l localtime ] [ -p posixrules ] \\\n\ | 450 | [ --version ] [ --help ] [ -v ] [ -l localtime ] [ -p posixrules ] \\\n\ | |
442 | \t[ -d directory ] [ -L leapseconds ] [ -y yearistype ] [ filename ... ]\n\ | 451 | \t[ -d directory ] [ -L leapseconds ] [ -y yearistype ] [ filename ... ]\n\ | |
443 | \n\ | 452 | \n\ | |
444 | Report bugs to %s.\n"), | 453 | Report bugs to %s.\n"), | |
445 | progname, progname, REPORT_BUGS_TO); | 454 | progname, progname, REPORT_BUGS_TO); | |
446 | exit(status); | 455 | exit(status); | |
@@ -749,27 +758,27 @@ associate(void) | @@ -749,27 +758,27 @@ associate(void) | |||
749 | zp = &zones[i]; | 758 | zp = &zones[i]; | |
750 | if (zp->z_nrules == 0) { | 759 | if (zp->z_nrules == 0) { | |
751 | /* | 760 | /* | |
752 | ** Maybe we have a local standard time offset. | 761 | ** Maybe we have a local standard time offset. | |
753 | */ | 762 | */ | |
754 | eat(zp->z_filename, zp->z_linenum); | 763 | eat(zp->z_filename, zp->z_linenum); | |
755 | zp->z_stdoff = gethms(zp->z_rule, _("unruly zone"), | 764 | zp->z_stdoff = gethms(zp->z_rule, _("unruly zone"), | |
756 | TRUE); | 765 | TRUE); | |
757 | /* | 766 | /* | |
758 | ** Note, though, that if there's no rule, | 767 | ** Note, though, that if there's no rule, | |
759 | ** a '%s' in the format is a bad thing. | 768 | ** a '%s' in the format is a bad thing. | |
760 | */ | 769 | */ | |
761 | if (strchr(zp->z_format, '%') != 0) | 770 | if (strchr(zp->z_format, '%') != 0) | |
762 | error(_("%s in ruleless zone")); | 771 | error("%s", _("%s in ruleless zone")); | |
763 | } | 772 | } | |
764 | } | 773 | } | |
765 | if (errors) | 774 | if (errors) | |
766 | exit(EXIT_FAILURE); | 775 | exit(EXIT_FAILURE); | |
767 | } | 776 | } | |
768 | 777 | |||
769 | static void | 778 | static void | |
770 | infile(const char *name) | 779 | infile(const char *name) | |
771 | { | 780 | { | |
772 | FILE * fp; | 781 | FILE * fp; | |
773 | char ** fields; | 782 | char ** fields; | |
774 | char * cp; | 783 | char * cp; | |
775 | const struct lookup * lp; | 784 | const struct lookup * lp; | |
@@ -879,33 +888,33 @@ gethms(const char *string, const char *c | @@ -879,33 +888,33 @@ gethms(const char *string, const char *c | |||
879 | return 0; | 888 | return 0; | |
880 | if (!signable) | 889 | if (!signable) | |
881 | sign = 1; | 890 | sign = 1; | |
882 | else if (*string == '-') { | 891 | else if (*string == '-') { | |
883 | sign = -1; | 892 | sign = -1; | |
884 | ++string; | 893 | ++string; | |
885 | } else sign = 1; | 894 | } else sign = 1; | |
886 | if (sscanf(string, scheck(string, "%"SCNdZIC), &hh) == 1) | 895 | if (sscanf(string, scheck(string, "%"SCNdZIC), &hh) == 1) | |
887 | mm = ss = 0; | 896 | mm = ss = 0; | |
888 | else if (sscanf(string, scheck(string, "%"SCNdZIC":%d"), &hh, &mm) == 2) | 897 | else if (sscanf(string, scheck(string, "%"SCNdZIC":%d"), &hh, &mm) == 2) | |
889 | ss = 0; | 898 | ss = 0; | |
890 | else if (sscanf(string, scheck(string, "%"SCNdZIC":%d:%d"), | 899 | else if (sscanf(string, scheck(string, "%"SCNdZIC":%d:%d"), | |
891 | &hh, &mm, &ss) != 3) { | 900 | &hh, &mm, &ss) != 3) { | |
892 | error(errstring); | 901 | error("%s", errstring); | |
893 | return 0; | 902 | return 0; | |
894 | } | 903 | } | |
895 | if (hh < 0 || | 904 | if (hh < 0 || | |
896 | mm < 0 || mm >= MINSPERHOUR || | 905 | mm < 0 || mm >= MINSPERHOUR || | |
897 | ss < 0 || ss > SECSPERMIN) { | 906 | ss < 0 || ss > SECSPERMIN) { | |
898 | error(errstring); | 907 | error("%s", errstring); | |
899 | return 0; | 908 | return 0; | |
900 | } | 909 | } | |
901 | if (ZIC_MAX / SECSPERHOUR < hh) { | 910 | if (ZIC_MAX / SECSPERHOUR < hh) { | |
902 | error(_("time overflow")); | 911 | error(_("time overflow")); | |
903 | return 0; | 912 | return 0; | |
904 | } | 913 | } | |
905 | if (noise && hh == HOURSPERDAY && mm == 0 && ss == 0) | 914 | if (noise && hh == HOURSPERDAY && mm == 0 && ss == 0) | |
906 | warning(_("24:00 not handled by pre-1998 versions of zic")); | 915 | warning(_("24:00 not handled by pre-1998 versions of zic")); | |
907 | if (noise && (hh > HOURSPERDAY || | 916 | if (noise && (hh > HOURSPERDAY || | |
908 | (hh == HOURSPERDAY && (mm != 0 || ss != 0)))) | 917 | (hh == HOURSPERDAY && (mm != 0 || ss != 0)))) | |
909 | warning(_("values over 24 hours not handled by pre-2007 versions of zic")); | 918 | warning(_("values over 24 hours not handled by pre-2007 versions of zic")); | |
910 | return oadd(sign * hh * SECSPERHOUR, | 919 | return oadd(sign * hh * SECSPERHOUR, | |
911 | sign * (mm * SECSPERMIN + ss)); | 920 | sign * (mm * SECSPERMIN + ss)); | |
@@ -931,60 +940,51 @@ inrule(char **const fields, const int nf | @@ -931,60 +940,51 @@ inrule(char **const fields, const int nf | |||
931 | fields[RF_MONTH], fields[RF_DAY], fields[RF_TOD]); | 940 | fields[RF_MONTH], fields[RF_DAY], fields[RF_TOD]); | |
932 | r.r_name = ecpyalloc(fields[RF_NAME]); | 941 | r.r_name = ecpyalloc(fields[RF_NAME]); | |
933 | r.r_abbrvar = ecpyalloc(fields[RF_ABBRVAR]); | 942 | r.r_abbrvar = ecpyalloc(fields[RF_ABBRVAR]); | |
934 | if (max_abbrvar_len < strlen(r.r_abbrvar)) | 943 | if (max_abbrvar_len < strlen(r.r_abbrvar)) | |
935 | max_abbrvar_len = strlen(r.r_abbrvar); | 944 | max_abbrvar_len = strlen(r.r_abbrvar); | |
936 | rules = erealloc(rules, (nrules + 1) * sizeof *rules); | 945 | rules = erealloc(rules, (nrules + 1) * sizeof *rules); | |
937 | rules[nrules++] = r; | 946 | rules[nrules++] = r; | |
938 | } | 947 | } | |
939 | 948 | |||
940 | static int | 949 | static int | |
941 | inzone(char **const fields, const int nfields) | 950 | inzone(char **const fields, const int nfields) | |
942 | { | 951 | { | |
943 | int i; | 952 | int i; | |
944 | static char * buf; | |||
945 | 953 | |||
946 | if (nfields < ZONE_MINFIELDS || nfields > ZONE_MAXFIELDS) { | 954 | if (nfields < ZONE_MINFIELDS || nfields > ZONE_MAXFIELDS) { | |
947 | error(_("wrong number of fields on Zone line")); | 955 | error(_("wrong number of fields on Zone line")); | |
948 | return FALSE; | 956 | return FALSE; | |
949 | } | 957 | } | |
950 | if (strcmp(fields[ZF_NAME], TZDEFAULT) == 0 && lcltime != NULL) { | 958 | if (strcmp(fields[ZF_NAME], TZDEFAULT) == 0 && lcltime != NULL) { | |
951 | buf = erealloc(buf, 132 + strlen(TZDEFAULT)); | 959 | error( | |
952 | (void)sprintf(buf, /* XXX: sprintf is safe */ | |||
953 | _("\"Zone %s\" line and -l option are mutually exclusive"), | 960 | _("\"Zone %s\" line and -l option are mutually exclusive"), | |
954 | TZDEFAULT); | 961 | TZDEFAULT); | |
955 | error(buf); | |||
956 | return FALSE; | 962 | return FALSE; | |
957 | } | 963 | } | |
958 | if (strcmp(fields[ZF_NAME], TZDEFRULES) == 0 && psxrules != NULL) { | 964 | if (strcmp(fields[ZF_NAME], TZDEFRULES) == 0 && psxrules != NULL) { | |
959 | buf = erealloc(buf, 132 + strlen(TZDEFRULES)); | 965 | error( | |
960 | (void)sprintf(buf, /* XXX: sprintf is safe */ | |||
961 | _("\"Zone %s\" line and -p option are mutually exclusive"), | 966 | _("\"Zone %s\" line and -p option are mutually exclusive"), | |
962 | TZDEFRULES); | 967 | TZDEFRULES); | |
963 | error(buf); | |||
964 | return FALSE; | 968 | return FALSE; | |
965 | } | 969 | } | |
966 | for (i = 0; i < nzones; ++i) | 970 | for (i = 0; i < nzones; ++i) | |
967 | if (zones[i].z_name != NULL && | 971 | if (zones[i].z_name != NULL && | |
968 | strcmp(zones[i].z_name, fields[ZF_NAME]) == 0) { | 972 | strcmp(zones[i].z_name, fields[ZF_NAME]) == 0) { | |
969 | buf = erealloc(buf, 132 + | 973 | error( | |
970 | strlen(fields[ZF_NAME]) + | |||
971 | strlen(zones[i].z_filename)); | |||
972 | (void)sprintf(buf, /* XXX: sprintf is safe */ | |||
973 | _("duplicate zone name %s (file \"%s\", line %d)"), | 974 | _("duplicate zone name %s (file \"%s\", line %d)"), | |
974 | fields[ZF_NAME], | 975 | fields[ZF_NAME], | |
975 | zones[i].z_filename, | 976 | zones[i].z_filename, | |
976 | zones[i].z_linenum); | 977 | zones[i].z_linenum); | |
977 | error(buf); | |||
978 | return FALSE; | 978 | return FALSE; | |
979 | } | 979 | } | |
980 | return inzsub(fields, nfields, FALSE); | 980 | return inzsub(fields, nfields, FALSE); | |
981 | } | 981 | } | |
982 | 982 | |||
983 | static int | 983 | static int | |
984 | inzcont(char **const fields, const int nfields) | 984 | inzcont(char **const fields, const int nfields) | |
985 | { | 985 | { | |
986 | if (nfields < ZONEC_MINFIELDS || nfields > ZONEC_MAXFIELDS) { | 986 | if (nfields < ZONEC_MINFIELDS || nfields > ZONEC_MAXFIELDS) { | |
987 | error(_("wrong number of fields on Zone continuation line")); | 987 | error(_("wrong number of fields on Zone continuation line")); | |
988 | return FALSE; | 988 | return FALSE; | |
989 | } | 989 | } | |
990 | return inzsub(fields, nfields, TRUE); | 990 | return inzsub(fields, nfields, TRUE); | |
@@ -1011,27 +1011,27 @@ inzsub(char **const fields, const int nf | @@ -1011,27 +1011,27 @@ inzsub(char **const fields, const int nf | |||
1011 | z.z_name = NULL; | 1011 | z.z_name = NULL; | |
1012 | } else { | 1012 | } else { | |
1013 | i_gmtoff = ZF_GMTOFF; | 1013 | i_gmtoff = ZF_GMTOFF; | |
1014 | i_rule = ZF_RULE; | 1014 | i_rule = ZF_RULE; | |
1015 | i_format = ZF_FORMAT; | 1015 | i_format = ZF_FORMAT; | |
1016 | i_untilyear = ZF_TILYEAR; | 1016 | i_untilyear = ZF_TILYEAR; | |
1017 | i_untilmonth = ZF_TILMONTH; | 1017 | i_untilmonth = ZF_TILMONTH; | |
1018 | i_untilday = ZF_TILDAY; | 1018 | i_untilday = ZF_TILDAY; | |
1019 | i_untiltime = ZF_TILTIME; | 1019 | i_untiltime = ZF_TILTIME; | |
1020 | z.z_name = ecpyalloc(fields[ZF_NAME]); | 1020 | z.z_name = ecpyalloc(fields[ZF_NAME]); | |
1021 | } | 1021 | } | |
1022 | z.z_filename = filename; | 1022 | z.z_filename = filename; | |
1023 | z.z_linenum = linenum; | 1023 | z.z_linenum = linenum; | |
1024 | z.z_gmtoff = gethms(fields[i_gmtoff], _("invalid UTC offset"), TRUE); | 1024 | z.z_gmtoff = gethms(fields[i_gmtoff], _("invalid UT offset"), TRUE); | |
1025 | if ((cp = strchr(fields[i_format], '%')) != 0) { | 1025 | if ((cp = strchr(fields[i_format], '%')) != 0) { | |
1026 | if (*++cp != 's' || strchr(cp, '%') != 0) { | 1026 | if (*++cp != 's' || strchr(cp, '%') != 0) { | |
1027 | error(_("invalid abbreviation format")); | 1027 | error(_("invalid abbreviation format")); | |
1028 | return FALSE; | 1028 | return FALSE; | |
1029 | } | 1029 | } | |
1030 | } | 1030 | } | |
1031 | z.z_rule = ecpyalloc(fields[i_rule]); | 1031 | z.z_rule = ecpyalloc(fields[i_rule]); | |
1032 | z.z_format = ecpyalloc(fields[i_format]); | 1032 | z.z_format = ecpyalloc(fields[i_format]); | |
1033 | if (max_format_len < strlen(z.z_format)) | 1033 | if (max_format_len < strlen(z.z_format)) | |
1034 | max_format_len = strlen(z.z_format); | 1034 | max_format_len = strlen(z.z_format); | |
1035 | hasuntil = nfields > i_untilyear; | 1035 | hasuntil = nfields > i_untilyear; | |
1036 | if (hasuntil) { | 1036 | if (hasuntil) { | |
1037 | z.z_untilrule.r_filename = filename; | 1037 | z.z_untilrule.r_filename = filename; | |
@@ -1387,27 +1387,27 @@ atcomp(const void *avp, const void *bvp) | @@ -1387,27 +1387,27 @@ atcomp(const void *avp, const void *bvp) | |||
1387 | const zic_t a = ((const struct attype *) avp)->at; | 1387 | const zic_t a = ((const struct attype *) avp)->at; | |
1388 | const zic_t b = ((const struct attype *) bvp)->at; | 1388 | const zic_t b = ((const struct attype *) bvp)->at; | |
1389 | 1389 | |||
1390 | return (a < b) ? -1 : (a > b); | 1390 | return (a < b) ? -1 : (a > b); | |
1391 | } | 1391 | } | |
1392 | 1392 | |||
1393 | static int | 1393 | static int | |
1394 | is32(const zic_t x) | 1394 | is32(const zic_t x) | |
1395 | { | 1395 | { | |
1396 | return INT32_MIN <= x && x <= INT32_MAX; | 1396 | return INT32_MIN <= x && x <= INT32_MAX; | |
1397 | } | 1397 | } | |
1398 | 1398 | |||
1399 | static void | 1399 | static void | |
1400 | writezone(const char *const name, const char *const string) | 1400 | writezone(const char *const name, const char *const string, char version) | |
1401 | { | 1401 | { | |
1402 | FILE * fp; | 1402 | FILE * fp; | |
1403 | int i, j; | 1403 | int i, j; | |
1404 | int leapcnt32, leapi32; | 1404 | int leapcnt32, leapi32; | |
1405 | int timecnt32, timei32; | 1405 | int timecnt32, timei32; | |
1406 | int pass; | 1406 | int pass; | |
1407 | static char * fullname; | 1407 | static char * fullname; | |
1408 | static const struct tzhead tzh0; | 1408 | static const struct tzhead tzh0; | |
1409 | static struct tzhead tzh; | 1409 | static struct tzhead tzh; | |
1410 | zic_t ats[TZ_MAX_TIMES]; | 1410 | zic_t ats[TZ_MAX_TIMES]; | |
1411 | unsigned char types[TZ_MAX_TIMES]; | 1411 | unsigned char types[TZ_MAX_TIMES]; | |
1412 | 1412 | |||
1413 | /* | 1413 | /* | |
@@ -1645,27 +1645,27 @@ writezone(const char *const name, const | @@ -1645,27 +1645,27 @@ writezone(const char *const name, const | |||
1645 | if (strcmp(&thischars[j], thisabbr) == 0) | 1645 | if (strcmp(&thischars[j], thisabbr) == 0) | |
1646 | break; | 1646 | break; | |
1647 | if (j == thischarcnt) { | 1647 | if (j == thischarcnt) { | |
1648 | (void) strcpy(&thischars[(int) thischarcnt], | 1648 | (void) strcpy(&thischars[(int) thischarcnt], | |
1649 | thisabbr); | 1649 | thisabbr); | |
1650 | thischarcnt += strlen(thisabbr) + 1; | 1650 | thischarcnt += strlen(thisabbr) + 1; | |
1651 | } | 1651 | } | |
1652 | indmap[abbrinds[i]] = j; | 1652 | indmap[abbrinds[i]] = j; | |
1653 | } | 1653 | } | |
1654 | #define DO(field) (void) fwrite(tzh.field, \ | 1654 | #define DO(field) (void) fwrite(tzh.field, \ | |
1655 | sizeof tzh.field, (size_t) 1, fp) | 1655 | sizeof tzh.field, (size_t) 1, fp) | |
1656 | tzh = tzh0; | 1656 | tzh = tzh0; | |
1657 | (void) strncpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic); | 1657 | (void) strncpy(tzh.tzh_magic, TZ_MAGIC, sizeof tzh.tzh_magic); | |
1658 | tzh.tzh_version[0] = ZIC_VERSION; | 1658 | tzh.tzh_version[0] = version; | |
1659 | convert(thistypecnt, tzh.tzh_ttisgmtcnt); | 1659 | convert(thistypecnt, tzh.tzh_ttisgmtcnt); | |
1660 | convert(thistypecnt, tzh.tzh_ttisstdcnt); | 1660 | convert(thistypecnt, tzh.tzh_ttisstdcnt); | |
1661 | convert(thisleapcnt, tzh.tzh_leapcnt); | 1661 | convert(thisleapcnt, tzh.tzh_leapcnt); | |
1662 | convert(thistimecnt, tzh.tzh_timecnt); | 1662 | convert(thistimecnt, tzh.tzh_timecnt); | |
1663 | convert(thistypecnt, tzh.tzh_typecnt); | 1663 | convert(thistypecnt, tzh.tzh_typecnt); | |
1664 | convert(thischarcnt, tzh.tzh_charcnt); | 1664 | convert(thischarcnt, tzh.tzh_charcnt); | |
1665 | DO(tzh_magic); | 1665 | DO(tzh_magic); | |
1666 | DO(tzh_version); | 1666 | DO(tzh_version); | |
1667 | DO(tzh_reserved); | 1667 | DO(tzh_reserved); | |
1668 | DO(tzh_ttisgmtcnt); | 1668 | DO(tzh_ttisgmtcnt); | |
1669 | DO(tzh_ttisstdcnt); | 1669 | DO(tzh_ttisstdcnt); | |
1670 | DO(tzh_leapcnt); | 1670 | DO(tzh_leapcnt); | |
1671 | DO(tzh_timecnt); | 1671 | DO(tzh_timecnt); | |
@@ -1783,196 +1783,261 @@ stringoffset(char *result, zic_t offset) | @@ -1783,196 +1783,261 @@ stringoffset(char *result, zic_t offset) | |||
1783 | int minutes; | 1783 | int minutes; | |
1784 | int seconds; | 1784 | int seconds; | |
1785 | 1785 | |||
1786 | result[0] = '\0'; | 1786 | result[0] = '\0'; | |
1787 | if (offset < 0) { | 1787 | if (offset < 0) { | |
1788 | (void) strcpy(result, "-"); | 1788 | (void) strcpy(result, "-"); | |
1789 | offset = -offset; | 1789 | offset = -offset; | |
1790 | } | 1790 | } | |
1791 | seconds = offset % SECSPERMIN; | 1791 | seconds = offset % SECSPERMIN; | |
1792 | offset /= SECSPERMIN; | 1792 | offset /= SECSPERMIN; | |
1793 | minutes = offset % MINSPERHOUR; | 1793 | minutes = offset % MINSPERHOUR; | |
1794 | offset /= MINSPERHOUR; | 1794 | offset /= MINSPERHOUR; | |
1795 | hours = offset; | 1795 | hours = offset; | |
1796 | if (hours > HOURSPERDAY) { | 1796 | if (hours >= HOURSPERDAY * DAYSPERWEEK) { | |
1797 | result[0] = '\0'; | 1797 | result[0] = '\0'; | |
1798 | return -1; | 1798 | return -1; | |
1799 | } | 1799 | } | |
1800 | (void) sprintf(end(result), "%d", hours); | 1800 | (void) sprintf(end(result), "%d", hours); | |
1801 | if (minutes != 0 || seconds != 0) { | 1801 | if (minutes != 0 || seconds != 0) { | |
1802 | (void) sprintf(end(result), ":%02d", minutes); | 1802 | (void) sprintf(end(result), ":%02d", minutes); | |
1803 | if (seconds != 0) | 1803 | if (seconds != 0) | |
1804 | (void) sprintf(end(result), ":%02d", seconds); | 1804 | (void) sprintf(end(result), ":%02d", seconds); | |
1805 | } | 1805 | } | |
1806 | return 0; | 1806 | return 0; | |
1807 | } | 1807 | } | |
1808 | 1808 | |||
1809 | static int | 1809 | static int | |
1810 | stringrule(char *result, const struct rule *const rp, const zic_t dstoff, | 1810 | stringrule(char *result, const struct rule *const rp, const zic_t dstoff, | |
1811 | const zic_t gmtoff) | 1811 | const zic_t gmtoff) | |
1812 | { | 1812 | { | |
1813 | zic_t tod; | 1813 | zic_t tod = rp->r_tod; | |
1814 | int compat = 0; | |||
1814 | 1815 | |||
1815 | result = end(result); | 1816 | result = end(result); | |
1816 | if (rp->r_dycode == DC_DOM) { | 1817 | if (rp->r_dycode == DC_DOM) { | |
1817 | int month, total; | 1818 | int month, total; | |
1818 | 1819 | |||
1819 | if (rp->r_dayofmonth == 29 && rp->r_month == TM_FEBRUARY) | 1820 | if (rp->r_dayofmonth == 29 && rp->r_month == TM_FEBRUARY) | |
1820 | return -1; | 1821 | return -1; | |
1821 | total = 0; | 1822 | total = 0; | |
1822 | for (month = 0; month < rp->r_month; ++month) | 1823 | for (month = 0; month < rp->r_month; ++month) | |
1823 | total += len_months[0][month]; | 1824 | total += len_months[0][month]; | |
1824 | (void) sprintf(result, "J%d", total + rp->r_dayofmonth); | 1825 | /* Omit the "J" in Jan and Feb, as that's shorter. */ | |
1826 | if (rp->r_month <= 1) | |||
1827 | (void) sprintf(result, "%d", total + rp->r_dayofmonth - 1); | |||
1828 | else | |||
1829 | (void) sprintf(result, "J%d", total + rp->r_dayofmonth); | |||
1825 | } else { | 1830 | } else { | |
1826 | int week; | 1831 | int week; | |
1832 | int wday = rp->r_wday; | |||
1833 | int wdayoff; | |||
1827 | 1834 | |||
1828 | if (rp->r_dycode == DC_DOWGEQ) { | 1835 | if (rp->r_dycode == DC_DOWGEQ) { | |
1829 | if ((rp->r_dayofmonth % DAYSPERWEEK) != 1) | 1836 | wdayoff = (rp->r_dayofmonth - 1) % DAYSPERWEEK; | |
1830 | return -1; | 1837 | if (wdayoff) | |
1831 | week = 1 + rp->r_dayofmonth / DAYSPERWEEK; | 1838 | compat = 2013; | |
1839 | wday -= wdayoff; | |||
1840 | tod += wdayoff * SECSPERDAY; | |||
1841 | week = 1 + (rp->r_dayofmonth - 1) / DAYSPERWEEK; | |||
1832 | } else if (rp->r_dycode == DC_DOWLEQ) { | 1842 | } else if (rp->r_dycode == DC_DOWLEQ) { | |
1833 | if (rp->r_dayofmonth == len_months[1][rp->r_month]) | 1843 | if (rp->r_dayofmonth == len_months[1][rp->r_month]) | |
1834 | week = 5; | 1844 | week = 5; | |
1835 | else { | 1845 | else { | |
1836 | if ((rp->r_dayofmonth % DAYSPERWEEK) != 0) | 1846 | wdayoff = rp->r_dayofmonth % DAYSPERWEEK; | |
1837 | return -1; | 1847 | if (wdayoff) | |
1848 | compat = 2013; | |||
1849 | wday -= wdayoff; | |||
1850 | tod += wdayoff * SECSPERDAY; | |||
1838 | week = rp->r_dayofmonth / DAYSPERWEEK; | 1851 | week = rp->r_dayofmonth / DAYSPERWEEK; | |
1839 | } | 1852 | } | |
1840 | } else return -1; /* "cannot happen" */ | 1853 | } else return -1; /* "cannot happen" */ | |
1854 | if (wday < 0) | |||
1855 | wday += DAYSPERWEEK; | |||
1841 | (void) sprintf(result, "M%d.%d.%d", | 1856 | (void) sprintf(result, "M%d.%d.%d", | |
1842 | rp->r_month + 1, week, rp->r_wday); | 1857 | rp->r_month + 1, week, wday); | |
1843 | } | 1858 | } | |
1844 | tod = rp->r_tod; | |||
1845 | if (rp->r_todisgmt) | 1859 | if (rp->r_todisgmt) | |
1846 | tod += gmtoff; | 1860 | tod += gmtoff; | |
1847 | if (rp->r_todisstd && rp->r_stdoff == 0) | 1861 | if (rp->r_todisstd && rp->r_stdoff == 0) | |
1848 | tod += dstoff; | 1862 | tod += dstoff; | |
1849 | if (tod < 0) { | |||
1850 | result[0] = '\0'; | |||
1851 | return -1; | |||
1852 | } | |||
1853 | if (tod != 2 * SECSPERMIN * MINSPERHOUR) { | 1863 | if (tod != 2 * SECSPERMIN * MINSPERHOUR) { | |
1854 | (void) strcat(result, "/"); | 1864 | (void) strcat(result, "/"); | |
1855 | if (stringoffset(end(result), tod) != 0) | 1865 | if (stringoffset(end(result), tod) != 0) | |
1856 | return -1; | 1866 | return -1; | |
1867 | if (tod < 0) { | |||
1868 | if (compat < 2013) | |||
1869 | compat = 2013; | |||
1870 | } else if (SECSPERDAY <= tod) { | |||
1871 | if (compat < 1994) | |||
1872 | compat = 1994; | |||
1873 | } | |||
1857 | } | 1874 | } | |
1858 | return 0; | 1875 | return compat; | |
1859 | } | 1876 | } | |
1860 | 1877 | |||
1861 | static void | 1878 | static int | |
1879 | rule_cmp(struct rule const *a, struct rule const *b) | |||
1880 | { | |||
1881 | if (!a) | |||
1882 | return -!!b; | |||
1883 | if (!b) | |||
1884 | return 1; | |||
1885 | if (a->r_hiyear != b->r_hiyear) | |||
1886 | return a->r_hiyear < b->r_hiyear ? -1 : 1; | |||
1887 | if (a->r_month - b->r_month != 0) | |||
1888 | return a->r_month - b->r_month; | |||
1889 | return a->r_dayofmonth - b->r_dayofmonth; | |||
1890 | } | |||
1891 | ||||
1892 | enum { YEAR_BY_YEAR_ZONE = 1 }; | |||
1893 | ||||
1894 | static int | |||
1862 | stringzone(char *result, const int resultlen, const struct zone *const zpfirst, | 1895 | stringzone(char *result, const int resultlen, const struct zone *const zpfirst, | |
1863 | const int zonecount) | 1896 | const int zonecount) | |
1864 | { | 1897 | { | |
1865 | const struct zone * zp; | 1898 | const struct zone * zp; | |
1866 | struct rule * rp; | 1899 | struct rule * rp; | |
1867 | struct rule * stdrp; | 1900 | struct rule * stdrp; | |
1868 | struct rule * dstrp; | 1901 | struct rule * dstrp; | |
1869 | int i; | 1902 | int i; | |
1870 | const char * abbrvar; | 1903 | const char * abbrvar; | |
1904 | int compat = 0; | |||
1905 | int c; | |||
1906 | struct rule stdr, dstr; | |||
1871 | 1907 | |||
1872 | result[0] = '\0'; | 1908 | result[0] = '\0'; | |
1873 | zp = zpfirst + zonecount - 1; | 1909 | zp = zpfirst + zonecount - 1; | |
1874 | stdrp = dstrp = NULL; | 1910 | stdrp = dstrp = NULL; | |
1875 | for (i = 0; i < zp->z_nrules; ++i) { | 1911 | for (i = 0; i < zp->z_nrules; ++i) { | |
1876 | rp = &zp->z_rules[i]; | 1912 | rp = &zp->z_rules[i]; | |
1877 | if (rp->r_hiwasnum || rp->r_hiyear != ZIC_MAX) | 1913 | if (rp->r_hiwasnum || rp->r_hiyear != ZIC_MAX) | |
1878 | continue; | 1914 | continue; | |
1879 | if (rp->r_yrtype != NULL) | 1915 | if (rp->r_yrtype != NULL) | |
1880 | continue; | 1916 | continue; | |
1881 | if (rp->r_stdoff == 0) { | 1917 | if (rp->r_stdoff == 0) { | |
1882 | if (stdrp == NULL) | 1918 | if (stdrp == NULL) | |
1883 | stdrp = rp; | 1919 | stdrp = rp; | |
1884 | else return; | 1920 | else return -1; | |
1885 | } else { | 1921 | } else { | |
1886 | if (dstrp == NULL) | 1922 | if (dstrp == NULL) | |
1887 | dstrp = rp; | 1923 | dstrp = rp; | |
1888 | else return; | 1924 | else return -1; | |
1889 | } | 1925 | } | |
1890 | } | 1926 | } | |
1891 | if (stdrp == NULL && dstrp == NULL) { | 1927 | if (stdrp == NULL && dstrp == NULL) { | |
1892 | /* | 1928 | /* | |
1893 | ** There are no rules running through "max". | 1929 | ** There are no rules running through "max". | |
1894 | ** Let's find the latest rule. | 1930 | ** Find the latest std rule in stdabbrrp | |
1931 | ** and latest rule of any type in stdrp. | |||
1895 | */ | 1932 | */ | |
1933 | struct rule *stdabbrrp = NULL; | |||
1896 | for (i = 0; i < zp->z_nrules; ++i) { | 1934 | for (i = 0; i < zp->z_nrules; ++i) { | |
1897 | rp = &zp->z_rules[i]; | 1935 | rp = &zp->z_rules[i]; | |
1898 | if (stdrp == NULL || rp->r_hiyear > stdrp->r_hiyear || | 1936 | if (rp->r_stdoff == 0 && rule_cmp(stdabbrrp, rp) < 0) | |
1899 | (rp->r_hiyear == stdrp->r_hiyear && | 1937 | stdabbrrp = rp; | |
1900 | (rp->r_month > stdrp->r_month || | 1938 | if (rule_cmp(stdrp, rp) < 0) | |
1901 | (rp->r_month == stdrp->r_month && | 1939 | stdrp = rp; | |
1902 | rp->r_dayofmonth > stdrp->r_dayofmonth)))) | |||
1903 | stdrp = rp; | |||
1904 | } | 1940 | } | |
1905 | if (stdrp != NULL && stdrp->r_stdoff != 0) | |||
1906 | return; /* We end up in DST (a POSIX no-no). */ | |||
1907 | /* | 1941 | /* | |
1908 | ** Horrid special case: if year is 2037, | 1942 | ** Horrid special case: if year is 2037, | |
1909 | ** presume this is a zone handled on a year-by-year basis; | 1943 | ** presume this is a zone handled on a year-by-year basis; | |
1910 | ** do not try to apply a rule to the zone. | 1944 | ** do not try to apply a rule to the zone. | |
1911 | */ | 1945 | */ | |
1912 | if (stdrp != NULL && stdrp->r_hiyear == 2037) | 1946 | if (stdrp != NULL && stdrp->r_hiyear == 2037) | |
1913 | return; | 1947 | return YEAR_BY_YEAR_ZONE; | |
1948 | ||||
1949 | if (stdrp != NULL && stdrp->r_stdoff != 0) { | |||
1950 | /* Perpetual DST. */ | |||
1951 | dstr.r_month = TM_JANUARY; | |||
1952 | dstr.r_dycode = DC_DOM; | |||
1953 | dstr.r_dayofmonth = 1; | |||
1954 | dstr.r_tod = 0; | |||
1955 | dstr.r_todisstd = dstr.r_todisgmt = FALSE; | |||
1956 | dstr.r_stdoff = stdrp->r_stdoff; | |||
1957 | dstr.r_abbrvar = stdrp->r_abbrvar; | |||
1958 | stdr.r_month = TM_DECEMBER; | |||
1959 | stdr.r_dycode = DC_DOM; | |||
1960 | stdr.r_dayofmonth = 31; | |||
1961 | stdr.r_tod = SECSPERDAY + stdrp->r_stdoff; | |||
1962 | stdr.r_todisstd = stdr.r_todisgmt = FALSE; | |||
1963 | stdr.r_stdoff = 0; | |||
1964 | stdr.r_abbrvar | |||
1965 | = (stdabbrrp ? stdabbrrp->r_abbrvar : ""); | |||
1966 | dstrp = &dstr; | |||
1967 | stdrp = &stdr; | |||
1968 | } | |||
1914 | } | 1969 | } | |
1915 | if (stdrp == NULL && (zp->z_nrules != 0 || zp->z_stdoff != 0)) | 1970 | if (stdrp == NULL && (zp->z_nrules != 0 || zp->z_stdoff != 0)) | |
1916 | return; | 1971 | return -1; | |
1917 | abbrvar = (stdrp == NULL) ? "" : stdrp->r_abbrvar; | 1972 | abbrvar = (stdrp == NULL) ? "" : stdrp->r_abbrvar; | |
1918 | doabbr(result, resultlen, zp->z_format, abbrvar, FALSE, TRUE); | 1973 | doabbr(result, resultlen, zp->z_format, abbrvar, FALSE, TRUE); | |
1919 | if (stringoffset(end(result), -zp->z_gmtoff) != 0) { | 1974 | if (stringoffset(end(result), -zp->z_gmtoff) != 0) { | |
1920 | result[0] = '\0'; | 1975 | result[0] = '\0'; | |
1921 | return; | 1976 | return -1; | |
1922 | } | 1977 | } | |
1923 | if (dstrp == NULL) | 1978 | if (dstrp == NULL) | |
1924 | return; | 1979 | return compat; | |
1925 | doabbr(end(result), resultlen - strlen(result), | 1980 | doabbr(end(result), resultlen - strlen(result), | |
1926 | zp->z_format, dstrp->r_abbrvar, TRUE, TRUE); | 1981 | zp->z_format, dstrp->r_abbrvar, TRUE, TRUE); | |
1927 | if (dstrp->r_stdoff != SECSPERMIN * MINSPERHOUR) | 1982 | if (dstrp->r_stdoff != SECSPERMIN * MINSPERHOUR) | |
1928 | if (stringoffset(end(result), | 1983 | if (stringoffset(end(result), | |
1929 | -(zp->z_gmtoff + dstrp->r_stdoff)) != 0) { | 1984 | -(zp->z_gmtoff + dstrp->r_stdoff)) != 0) { | |
1930 | result[0] = '\0'; | 1985 | result[0] = '\0'; | |
1931 | return; | 1986 | return -1; | |
1932 | } | 1987 | } | |
1933 | (void) strcat(result, ","); | 1988 | (void) strcat(result, ","); | |
1934 | if (stringrule(result, dstrp, dstrp->r_stdoff, zp->z_gmtoff) != 0) { | 1989 | c = stringrule(result, dstrp, dstrp->r_stdoff, zp->z_gmtoff); | |
1990 | if (c < 0) { | |||
1935 | result[0] = '\0'; | 1991 | result[0] = '\0'; | |
1936 | return; | 1992 | return -1; | |
1937 | } | 1993 | } | |
1994 | if (compat < c) | |||
1995 | compat = c; | |||
1938 | (void) strcat(result, ","); | 1996 | (void) strcat(result, ","); | |
1939 | if (stringrule(result, stdrp, dstrp->r_stdoff, zp->z_gmtoff) != 0) { | 1997 | c = stringrule(result, stdrp, dstrp->r_stdoff, zp->z_gmtoff); | |
1998 | if (c < 0) { | |||
1940 | result[0] = '\0'; | 1999 | result[0] = '\0'; | |
1941 | return; | 2000 | return -1; | |
1942 | } | 2001 | } | |
2002 | if (compat < c) | |||
2003 | compat = c; | |||
2004 | return compat; | |||
1943 | } | 2005 | } | |
1944 | 2006 | |||
1945 | static void | 2007 | static void | |
1946 | outzone(const struct zone *const zpfirst, const int zonecount) | 2008 | outzone(const struct zone *const zpfirst, const int zonecount) | |
1947 | { | 2009 | { | |
1948 | const struct zone * zp; | 2010 | const struct zone * zp; | |
1949 | struct rule * rp; | 2011 | struct rule * rp; | |
1950 | int i, j; | 2012 | int i, j; | |
1951 | int usestart, useuntil; | 2013 | int usestart, useuntil; | |
1952 | zic_t starttime, untiltime; | 2014 | zic_t starttime, untiltime; | |
1953 | zic_t gmtoff; | 2015 | zic_t gmtoff; | |
1954 | zic_t stdoff; | 2016 | zic_t stdoff; | |
1955 | zic_t year; | 2017 | zic_t year; | |
1956 | zic_t startoff; | 2018 | zic_t startoff; | |
1957 | int startttisstd; | 2019 | int startttisstd; | |
1958 | int startttisgmt; | 2020 | int startttisgmt; | |
1959 | int type; | 2021 | int type; | |
1960 | char * startbuf; | 2022 | char * startbuf; | |
1961 | char * ab; | 2023 | char * ab; | |
1962 | char * envvar; | 2024 | char * envvar; | |
1963 | size_t max_abbr_len; | 2025 | size_t max_abbr_len; | |
1964 | size_t max_envvar_len; | 2026 | size_t max_envvar_len; | |
1965 | int prodstic; /* all rules are min to max */ | 2027 | int prodstic; /* all rules are min to max */ | |
2028 | int compat; | |||
2029 | int do_extend; | |||
2030 | int version; | |||
1966 | 2031 | |||
1967 | max_abbr_len = 2 + max_format_len + max_abbrvar_len; | 2032 | max_abbr_len = 2 + max_format_len + max_abbrvar_len; | |
1968 | max_envvar_len = 2 * max_abbr_len + 5 * 9; | 2033 | max_envvar_len = 2 * max_abbr_len + 5 * 9; | |
1969 | startbuf = emalloc(max_abbr_len + 1); | 2034 | startbuf = emalloc(max_abbr_len + 1); | |
1970 | ab = emalloc(max_abbr_len + 1); | 2035 | ab = emalloc(max_abbr_len + 1); | |
1971 | envvar = emalloc(max_envvar_len + 1); | 2036 | envvar = emalloc(max_envvar_len + 1); | |
1972 | INITIALIZE(untiltime); | 2037 | INITIALIZE(untiltime); | |
1973 | INITIALIZE(starttime); | 2038 | INITIALIZE(starttime); | |
1974 | /* | 2039 | /* | |
1975 | ** Now. . .finally. . .generate some useful data! | 2040 | ** Now. . .finally. . .generate some useful data! | |
1976 | */ | 2041 | */ | |
1977 | timecnt = 0; | 2042 | timecnt = 0; | |
1978 | typecnt = 0; | 2043 | typecnt = 0; | |
@@ -2001,52 +2066,74 @@ outzone(const struct zone *const zpfirst | @@ -2001,52 +2066,74 @@ outzone(const struct zone *const zpfirst | |||
2001 | for (j = 0; j < zp->z_nrules; ++j) { | 2066 | for (j = 0; j < zp->z_nrules; ++j) { | |
2002 | rp = &zp->z_rules[j]; | 2067 | rp = &zp->z_rules[j]; | |
2003 | if (rp->r_lowasnum) | 2068 | if (rp->r_lowasnum) | |
2004 | updateminmax(rp->r_loyear); | 2069 | updateminmax(rp->r_loyear); | |
2005 | if (rp->r_hiwasnum) | 2070 | if (rp->r_hiwasnum) | |
2006 | updateminmax(rp->r_hiyear); | 2071 | updateminmax(rp->r_hiyear); | |
2007 | if (rp->r_lowasnum || rp->r_hiwasnum) | 2072 | if (rp->r_lowasnum || rp->r_hiwasnum) | |
2008 | prodstic = FALSE; | 2073 | prodstic = FALSE; | |
2009 | } | 2074 | } | |
2010 | } | 2075 | } | |
2011 | /* | 2076 | /* | |
2012 | ** Generate lots of data if a rule can't cover all future times. | 2077 | ** Generate lots of data if a rule can't cover all future times. | |
2013 | */ | 2078 | */ | |
2014 | stringzone(envvar, max_envvar_len+1, zpfirst, zonecount); | 2079 | compat = stringzone(envvar, max_envvar_len + 1, zpfirst, zonecount); | |
2015 | if (noise && envvar[0] == '\0') { | 2080 | version = compat < 2013 ? ZIC_VERSION_PRE_2013 : ZIC_VERSION; | |
2016 | char * wp; | 2081 | do_extend = compat < 0 || compat == YEAR_BY_YEAR_ZONE; | |
2017 | 2082 | if (noise && compat != 0 && compat != YEAR_BY_YEAR_ZONE) { | ||
2018 | wp = ecpyalloc(_("no POSIX environment variable for zone")); | 2083 | if (compat < 0) | |
2019 | wp = ecatalloc(wp, " "); | 2084 | warning("%s %s", | |
2020 | wp = ecatalloc(wp, zpfirst->z_name); | 2085 | _("no POSIX environment variable for zone"), | |
2021 | warning(wp); | 2086 | zpfirst->z_name); | |
2022 | free(wp); | 2087 | else { | |
2023 | } | 2088 | /* Circa-COMPAT clients, and earlier clients, might | |
2024 | if (envvar[0] == '\0') { | 2089 | not work for this zone when given dates before | |
2025 | if (min_year >= ZIC_MIN + YEARSPERREPEAT) | 2090 | 1970 or after 2038. */ | |
2026 | min_year -= YEARSPERREPEAT; | 2091 | warning(_("%s: pre-%d clients may mishandle" | |
2092 | " distant timestamps"), | |||
2093 | zpfirst->z_name, compat); | |||
2094 | } | |||
2095 | } | |||
2096 | if (do_extend) { | |||
2097 | /* | |||
2098 | ** Search through a couple of extra years past the obvious | |||
2099 | ** 400, to avoid edge cases. For example, suppose a non-POSIX | |||
2100 | ** rule applies from 2012 onwards and has transitions in March | |||
2101 | ** and September, plus some one-off transitions in November | |||
2102 | ** 2013. If zic looked only at the last 400 years, it would | |||
2103 | ** set max_year=2413, with the intent that the 400 years 2014 | |||
2104 | ** through 2413 will be repeated. The last transition listed | |||
2105 | ** in the tzfile would be in 2413-09, less than 400 years | |||
2106 | ** after the last one-off transition in 2013-11. Two years | |||
2107 | ** might be overkill, but with the kind of edge cases | |||
2108 | ** available we're not sure that one year would suffice. | |||
2109 | */ | |||
2110 | enum { years_of_observations = YEARSPERREPEAT + 2 }; | |||
2111 | ||||
2112 | if (min_year >= ZIC_MIN + years_of_observations) | |||
2113 | min_year -= years_of_observations; | |||
2027 | else min_year = ZIC_MIN; | 2114 | else min_year = ZIC_MIN; | |
2028 | if (max_year <= ZIC_MAX - YEARSPERREPEAT) | 2115 | if (max_year <= ZIC_MAX - years_of_observations) | |
2029 | max_year += YEARSPERREPEAT; | 2116 | max_year += years_of_observations; | |
2030 | else max_year = ZIC_MAX; | 2117 | else max_year = ZIC_MAX; | |
2031 | /* | 2118 | /* | |
2032 | ** Regardless of any of the above, | 2119 | ** Regardless of any of the above, | |
2033 | ** for a "proDSTic" zone which specifies that its rules | 2120 | ** for a "proDSTic" zone which specifies that its rules | |
2034 | ** always have and always will be in effect, | 2121 | ** always have and always will be in effect, | |
2035 | ** we only need one cycle to define the zone. | 2122 | ** we only need one cycle to define the zone. | |
2036 | */ | 2123 | */ | |
2037 | if (prodstic) { | 2124 | if (prodstic) { | |
2038 | min_year = 1900; | 2125 | min_year = 1900; | |
2039 | max_year = min_year + YEARSPERREPEAT; | 2126 | max_year = min_year + years_of_observations; | |
2040 | } | 2127 | } | |
2041 | } | 2128 | } | |
2042 | /* | 2129 | /* | |
2043 | ** For the benefit of older systems, | 2130 | ** For the benefit of older systems, | |
2044 | ** generate data from 1900 through 2037. | 2131 | ** generate data from 1900 through 2037. | |
2045 | */ | 2132 | */ | |
2046 | if (min_year > 1900) | 2133 | if (min_year > 1900) | |
2047 | min_year = 1900; | 2134 | min_year = 1900; | |
2048 | if (max_year < 2037) | 2135 | if (max_year < 2037) | |
2049 | max_year = 2037; | 2136 | max_year = 2037; | |
2050 | for (i = 0; i < zonecount; ++i) { | 2137 | for (i = 0; i < zonecount; ++i) { | |
2051 | /* | 2138 | /* | |
2052 | ** A guess that may well be corrected later. | 2139 | ** A guess that may well be corrected later. | |
@@ -2088,27 +2175,27 @@ outzone(const struct zone *const zpfirst | @@ -2088,27 +2175,27 @@ outzone(const struct zone *const zpfirst | |||
2088 | year <= rp->r_hiyear && | 2175 | year <= rp->r_hiyear && | |
2089 | yearistype(year, rp->r_yrtype); | 2176 | yearistype(year, rp->r_yrtype); | |
2090 | if (rp->r_todo) | 2177 | if (rp->r_todo) | |
2091 | rp->r_temp = rpytime(rp, year); | 2178 | rp->r_temp = rpytime(rp, year); | |
2092 | } | 2179 | } | |
2093 | for ( ; ; ) { | 2180 | for ( ; ; ) { | |
2094 | int k; | 2181 | int k; | |
2095 | zic_t jtime, ktime; | 2182 | zic_t jtime, ktime; | |
2096 | zic_t offset; | 2183 | zic_t offset; | |
2097 | 2184 | |||
2098 | INITIALIZE(ktime); | 2185 | INITIALIZE(ktime); | |
2099 | if (useuntil) { | 2186 | if (useuntil) { | |
2100 | /* | 2187 | /* | |
2101 | ** Turn untiltime into UTC | 2188 | ** Turn untiltime into UT | |
2102 | ** assuming the current gmtoff and | 2189 | ** assuming the current gmtoff and | |
2103 | ** stdoff values. | 2190 | ** stdoff values. | |
2104 | */ | 2191 | */ | |
2105 | untiltime = zp->z_untiltime; | 2192 | untiltime = zp->z_untiltime; | |
2106 | if (!zp->z_untilrule.r_todisgmt) | 2193 | if (!zp->z_untilrule.r_todisgmt) | |
2107 | untiltime = tadd(untiltime, | 2194 | untiltime = tadd(untiltime, | |
2108 | -gmtoff); | 2195 | -gmtoff); | |
2109 | if (!zp->z_untilrule.r_todisstd) | 2196 | if (!zp->z_untilrule.r_todisstd) | |
2110 | untiltime = tadd(untiltime, | 2197 | untiltime = tadd(untiltime, | |
2111 | -stdoff); | 2198 | -stdoff); | |
2112 | } | 2199 | } | |
2113 | /* | 2200 | /* | |
2114 | ** Find the rule (of those to do, if any) | 2201 | ** Find the rule (of those to do, if any) | |
@@ -2196,27 +2283,65 @@ error(_("can't determine time zone abbre | @@ -2196,27 +2283,65 @@ error(_("can't determine time zone abbre | |||
2196 | /* | 2283 | /* | |
2197 | ** Now we may get to set starttime for the next zone line. | 2284 | ** Now we may get to set starttime for the next zone line. | |
2198 | */ | 2285 | */ | |
2199 | if (useuntil) { | 2286 | if (useuntil) { | |
2200 | startttisstd = zp->z_untilrule.r_todisstd; | 2287 | startttisstd = zp->z_untilrule.r_todisstd; | |
2201 | startttisgmt = zp->z_untilrule.r_todisgmt; | 2288 | startttisgmt = zp->z_untilrule.r_todisgmt; | |
2202 | starttime = zp->z_untiltime; | 2289 | starttime = zp->z_untiltime; | |
2203 | if (!startttisstd) | 2290 | if (!startttisstd) | |
2204 | starttime = tadd(starttime, -stdoff); | 2291 | starttime = tadd(starttime, -stdoff); | |
2205 | if (!startttisgmt) | 2292 | if (!startttisgmt) | |
2206 | starttime = tadd(starttime, -gmtoff); | 2293 | starttime = tadd(starttime, -gmtoff); | |
2207 | } | 2294 | } | |
2208 | } | 2295 | } | |
2209 | writezone(zpfirst->z_name, envvar); | 2296 | if (do_extend) { | |
2297 | /* | |||
2298 | ** If we're extending the explicitly listed observations | |||
2299 | ** for 400 years because we can't fill the POSIX-TZ field, | |||
2300 | ** check whether we actually ended up explicitly listing | |||
2301 | ** observations through that period. If there aren't any | |||
2302 | ** near the end of the 400-year period, add a redundant | |||
2303 | ** one at the end of the final year, to make it clear | |||
2304 | ** that we are claiming to have definite knowledge of | |||
2305 | ** the lack of transitions up to that point. | |||
2306 | */ | |||
2307 | struct rule xr; | |||
2308 | struct attype *lastat; | |||
2309 | xr.r_month = TM_JANUARY; | |||
2310 | xr.r_dycode = DC_DOM; | |||
2311 | xr.r_dayofmonth = 1; | |||
2312 | xr.r_tod = 0; | |||
2313 | for (lastat = &attypes[0], i = 1; i < timecnt; i++) | |||
2314 | if (attypes[i].at > lastat->at) | |||
2315 | lastat = &attypes[i]; | |||
2316 | if (lastat->at < rpytime(&xr, max_year - 1)) { | |||
2317 | /* | |||
2318 | ** Create new type code for the redundant entry, | |||
2319 | ** to prevent it being optimised away. | |||
2320 | */ | |||
2321 | if (typecnt >= TZ_MAX_TYPES) { | |||
2322 | error(_("too many local time types")); | |||
2323 | exit(EXIT_FAILURE); | |||
2324 | } | |||
2325 | gmtoffs[typecnt] = gmtoffs[lastat->type]; | |||
2326 | isdsts[typecnt] = isdsts[lastat->type]; | |||
2327 | ttisstds[typecnt] = ttisstds[lastat->type]; | |||
2328 | ttisgmts[typecnt] = ttisgmts[lastat->type]; | |||
2329 | abbrinds[typecnt] = abbrinds[lastat->type]; | |||
2330 | ++typecnt; | |||
2331 | addtt(rpytime(&xr, max_year + 1), typecnt-1); | |||
2332 | } | |||
2333 | } | |||
2334 | writezone(zpfirst->z_name, envvar, version); | |||
2210 | free(startbuf); | 2335 | free(startbuf); | |
2211 | free(ab); | 2336 | free(ab); | |
2212 | free(envvar); | 2337 | free(envvar); | |
2213 | } | 2338 | } | |
2214 | 2339 | |||
2215 | static void | 2340 | static void | |
2216 | addtt(const zic_t starttime, int type) | 2341 | addtt(const zic_t starttime, int type) | |
2217 | { | 2342 | { | |
2218 | if (starttime <= min_time || | 2343 | if (starttime <= min_time || | |
2219 | (timecnt == 1 && attypes[0].at < min_time)) { | 2344 | (timecnt == 1 && attypes[0].at < min_time)) { | |
2220 | gmtoffs[0] = gmtoffs[type]; | 2345 | gmtoffs[0] = gmtoffs[type]; | |
2221 | isdsts[0] = isdsts[type]; | 2346 | isdsts[0] = isdsts[type]; | |
2222 | ttisstds[0] = ttisstds[type]; | 2347 | ttisstds[0] = ttisstds[type]; | |
@@ -2266,27 +2391,27 @@ addtype(const zic_t gmtoff, const char * | @@ -2266,27 +2391,27 @@ addtype(const zic_t gmtoff, const char * | |||
2266 | ttisstd == ttisstds[i] && | 2391 | ttisstd == ttisstds[i] && | |
2267 | ttisgmt == ttisgmts[i]) | 2392 | ttisgmt == ttisgmts[i]) | |
2268 | return i; | 2393 | return i; | |
2269 | } | 2394 | } | |
2270 | /* | 2395 | /* | |
2271 | ** There isn't one; add a new one, unless there are already too | 2396 | ** There isn't one; add a new one, unless there are already too | |
2272 | ** many. | 2397 | ** many. | |
2273 | */ | 2398 | */ | |
2274 | if (typecnt >= TZ_MAX_TYPES) { | 2399 | if (typecnt >= TZ_MAX_TYPES) { | |
2275 | error(_("too many local time types")); | 2400 | error(_("too many local time types")); | |
2276 | exit(EXIT_FAILURE); | 2401 | exit(EXIT_FAILURE); | |
2277 | } | 2402 | } | |
2278 | if (! (-1L - 2147483647L <= gmtoff && gmtoff <= 2147483647L)) { | 2403 | if (! (-1L - 2147483647L <= gmtoff && gmtoff <= 2147483647L)) { | |
2279 | error(_("UTC offset out of range")); | 2404 | error(_("UT offset out of range")); | |
2280 | exit(EXIT_FAILURE); | 2405 | exit(EXIT_FAILURE); | |
2281 | } | 2406 | } | |
2282 | gmtoffs[i] = gmtoff; | 2407 | gmtoffs[i] = gmtoff; | |
2283 | isdsts[i] = isdst; | 2408 | isdsts[i] = isdst; | |
2284 | ttisstds[i] = ttisstd; | 2409 | ttisstds[i] = ttisstd; | |
2285 | ttisgmts[i] = ttisgmt; | 2410 | ttisgmts[i] = ttisgmt; | |
2286 | 2411 | |||
2287 | for (j = 0; j < charcnt; ++j) | 2412 | for (j = 0; j < charcnt; ++j) | |
2288 | if (strcmp(&chars[j], abbr) == 0) | 2413 | if (strcmp(&chars[j], abbr) == 0) | |
2289 | break; | 2414 | break; | |
2290 | if (j == charcnt) | 2415 | if (j == charcnt) | |
2291 | newabbr(abbr); | 2416 | newabbr(abbr); | |
2292 | abbrinds[i] = j; | 2417 | abbrinds[i] = j; | |
@@ -2461,27 +2586,27 @@ getfields(char *cp) | @@ -2461,27 +2586,27 @@ getfields(char *cp) | |||
2461 | return array; | 2586 | return array; | |
2462 | } | 2587 | } | |
2463 | 2588 | |||
2464 | static ATTRIBUTE_PURE zic_t | 2589 | static ATTRIBUTE_PURE zic_t | |
2465 | oadd(const zic_t t1, const zic_t t2) | 2590 | oadd(const zic_t t1, const zic_t t2) | |
2466 | { | 2591 | { | |
2467 | if (t1 < 0 ? t2 < ZIC_MIN - t1 : ZIC_MAX - t1 < t2) { | 2592 | if (t1 < 0 ? t2 < ZIC_MIN - t1 : ZIC_MAX - t1 < t2) { | |
2468 | error(_("time overflow")); | 2593 | error(_("time overflow")); | |
2469 | exit(EXIT_FAILURE); | 2594 | exit(EXIT_FAILURE); | |
2470 | } | 2595 | } | |
2471 | return t1 + t2; | 2596 | return t1 + t2; | |
2472 | } | 2597 | } | |
2473 | 2598 | |||
2474 | static zic_t | 2599 | static ATTRIBUTE_PURE zic_t | |
2475 | tadd(const zic_t t1, const zic_t t2) | 2600 | tadd(const zic_t t1, const zic_t t2) | |
2476 | { | 2601 | { | |
2477 | if (t1 == max_time && t2 > 0) | 2602 | if (t1 == max_time && t2 > 0) | |
2478 | return max_time; | 2603 | return max_time; | |
2479 | if (t1 == min_time && t2 < 0) | 2604 | if (t1 == min_time && t2 < 0) | |
2480 | return min_time; | 2605 | return min_time; | |
2481 | if (t1 < 0 ? t2 < min_time - t1 : max_time - t1 < t2) { | 2606 | if (t1 < 0 ? t2 < min_time - t1 : max_time - t1 < t2) { | |
2482 | error(_("time overflow")); | 2607 | error(_("time overflow")); | |
2483 | exit(EXIT_FAILURE); | 2608 | exit(EXIT_FAILURE); | |
2484 | } | 2609 | } | |
2485 | return t1 + t2; | 2610 | return t1 + t2; | |
2486 | } | 2611 | } | |
2487 | 2612 | |||
@@ -2595,34 +2720,28 @@ mp = _("time zone abbreviation lacks alp | @@ -2595,34 +2720,28 @@ mp = _("time zone abbreviation lacks alp | |||
2595 | mp = _("time zone abbreviation has fewer than 3 alphabetics"); | 2720 | mp = _("time zone abbreviation has fewer than 3 alphabetics"); | |
2596 | if (cp - string > ZIC_MAX_ABBR_LEN_WO_WARN) | 2721 | if (cp - string > ZIC_MAX_ABBR_LEN_WO_WARN) | |
2597 | mp = _("time zone abbreviation has too many alphabetics"); | 2722 | mp = _("time zone abbreviation has too many alphabetics"); | |
2598 | if (mp == NULL && (*cp == '+' || *cp == '-')) { | 2723 | if (mp == NULL && (*cp == '+' || *cp == '-')) { | |
2599 | ++cp; | 2724 | ++cp; | |
2600 | if (isascii((unsigned char) *cp) && | 2725 | if (isascii((unsigned char) *cp) && | |
2601 | isdigit((unsigned char) *cp)) | 2726 | isdigit((unsigned char) *cp)) | |
2602 | if (*cp++ == '1' && | 2727 | if (*cp++ == '1' && | |
2603 | *cp >= '0' && *cp <= '4') | 2728 | *cp >= '0' && *cp <= '4') | |
2604 | ++cp; | 2729 | ++cp; | |
2605 | } | 2730 | } | |
2606 | if (*cp != '\0') | 2731 | if (*cp != '\0') | |
2607 | mp = _("time zone abbreviation differs from POSIX standard"); | 2732 | mp = _("time zone abbreviation differs from POSIX standard"); | |
2608 | if (mp != NULL) { | 2733 | if (mp != NULL) | |
2609 | char *wp = ecpyalloc(mp); | 2734 | warning("%s (%s)", mp, string); | |
2610 | wp = ecatalloc(wp, " ("); | |||
2611 | wp = ecatalloc(wp, string); | |||
2612 | wp = ecatalloc(wp, ")"); | |||
2613 | warning(wp); | |||
2614 | free(wp); | |||
2615 | } | |||
2616 | } | 2735 | } | |
2617 | i = strlen(string) + 1; | 2736 | i = strlen(string) + 1; | |
2618 | if (charcnt + i > TZ_MAX_CHARS) { | 2737 | if (charcnt + i > TZ_MAX_CHARS) { | |
2619 | error(_("too many, or too long, time zone abbreviations")); | 2738 | error(_("too many, or too long, time zone abbreviations")); | |
2620 | exit(EXIT_FAILURE); | 2739 | exit(EXIT_FAILURE); | |
2621 | } | 2740 | } | |
2622 | (void)strncpy(&chars[charcnt], string, sizeof(chars) - charcnt - 1); | 2741 | (void)strncpy(&chars[charcnt], string, sizeof(chars) - charcnt - 1); | |
2623 | charcnt += i; | 2742 | charcnt += i; | |
2624 | } | 2743 | } | |
2625 | 2744 | |||
2626 | static int | 2745 | static int | |
2627 | mkdirs(char *argname) | 2746 | mkdirs(char *argname) | |
2628 | { | 2747 | { |