Bring our tzcode up to date.

* Replay 2010[acflm] which had been merged but not recorded.
* Merge 2010n.
* Reorganize (unsplit) the code to match the upstream layout.
* Merge 2022[cdefg].

MFC after:      1 week
Sponsored by:   Klara, Inc.
This commit is contained in:
Dag-Erling Smørgrav 2023-01-10 16:14:27 +01:00
commit bc42155199
62 changed files with 25079 additions and 8326 deletions

View File

@ -0,0 +1,97 @@
# Contributing to the tz code and data
Please do not create issues or pull requests on GitHub, as the
proper procedure for proposing and distributing patches is via
email as described below.
The time zone database is by no means authoritative: governments
change timekeeping rules erratically and sometimes with little
warning, the data entries do not cover all of civil time before
1970, and undoubtedly errors remain in the code and data. Feel
free to fill gaps or fix mistakes, and please email improvements
to <tz@iana.org> for use in the future. In your email, please give
reliable sources that reviewers can check.
## Contributing technical changes
To email small changes, please run a POSIX shell command like
'diff -u old/europe new/europe >myfix.patch', and attach
'myfix.patch' to the email.
For more-elaborate or possibly-controversial changes,
such as renaming, adding or removing zones, please read
"Theory and pragmatics of the tz code and data"
<https://www.iana.org/time-zones/repository/theory.html>.
It is also good to browse the mailing list archives
<https://mm.icann.org/pipermail/tz/> for examples of patches that tend
to work well. Additions to data should contain commentary citing
reliable sources as justification. Citations should use "https:" URLs
if available.
For changes that fix sensitive security-related bugs, please see the
distribution's 'SECURITY' file.
Please submit changes against either the latest release
<https://www.iana.org/time-zones> or the main branch of the development
repository. The latter is preferred.
## Sample Git workflow for developing contributions
If you use Git the following workflow may be helpful:
* Copy the development repository.
git clone https://github.com/eggert/tz.git
cd tz
* Get current with the main branch.
git checkout main
git pull
* Switch to a new branch for the changes. Choose a different
branch name for each change set.
git checkout -b mybranch
* Sleuth by using 'git blame'. For example, when fixing data for
Africa/Sao_Tome, if the command 'git blame africa' outputs a line
'2951fa3b (Paul Eggert 2018-01-08 09:03:13 -0800 1068) Zone
Africa/Sao_Tome 0:26:56 - LMT 1884', commit 2951fa3b should
provide some justification for the 'Zone Africa/Sao_Tome' line.
* Edit source files. Include commentary that justifies the
changes by citing reliable sources.
* Debug the changes, e.g.:
make check
make install
./zdump -v America/Los_Angeles
* For each separable change, commit it in the new branch, e.g.:
git add northamerica
git commit
See recent 'git log' output for the commit-message style.
* Create patch files 0001-..., 0002-..., ...
git format-patch main
* After reviewing the patch files, send the patches to <tz@iana.org>
for others to review.
git send-email main
For an archived example of such an email, see
"[PROPOSED] Fix off-by-1 error for Jamaica and T&C before 1913"
<https://mm.icann.org/pipermail/tz/2018-February/026122.html>.
* Start anew by getting current with the main branch again
(the second step above).
-----
This file is in the public domain.

5
contrib/tzcode/LICENSE Normal file
View File

@ -0,0 +1,5 @@
Unless specified below, all files in the tz code and data (including
this LICENSE file) are in the public domain.
If the files date.c, newstrftime.3, and strftime.c are present, they
contain material derived from BSD and use the BSD 3-clause license.

1250
contrib/tzcode/Makefile Normal file

File diff suppressed because it is too large Load Diff

5902
contrib/tzcode/NEWS Normal file

File diff suppressed because it is too large Load Diff

52
contrib/tzcode/README Normal file
View File

@ -0,0 +1,52 @@
README for the tz distribution
"Where do I set the hands of the clock?" -- Les Tremayne as The King
"Oh that--you can set them any place you want." -- Frank Baxter as The Scientist
(from the Bell System film "About Time")
The Time Zone Database (called tz, tzdb or zoneinfo) contains code and
data that represent the history of local time for many representative
locations around the globe. It is updated periodically to reflect
changes made by political bodies to time zone boundaries, UTC offsets,
and daylight-saving rules.
See <https://www.iana.org/time-zones/repository/tz-link.html> or the
file tz-link.html for how to acquire the code and data. Once acquired,
read the comments in the file 'Makefile' and make any changes needed
to make things right for your system, especially if you are using some
platform other than GNU/Linux. Then run the following commands,
substituting your desired installation directory for "$HOME/tzdir":
make TOPDIR=$HOME/tzdir install
$HOME/tzdir/usr/bin/zdump -v America/Los_Angeles
See the file tz-how-to.html for examples of how to read the data files.
This database of historical local time information has several goals:
* Provide a compendium of data about the history of civil time that
is useful even if not 100% accurate.
* Give an idea of the variety of local time rules that have existed
in the past and thus may be expected in the future.
* Test the generality of the local time rule description system.
The information in the time zone data files is by no means authoritative;
fixes and enhancements are welcome. Please see the file CONTRIBUTING
for details.
Thanks to these Time Zone Caballeros who've made major contributions to the
time conversion package: Keith Bostic; Bob Devine; Paul Eggert; Robert Elz;
Guy Harris; Mark Horton; John Mackin; and Bradley White. Thanks also to
Michael Bloom, Art Neilson, Stephen Prince, John Sovereign, and Frank Wales
for testing work, and to Gwillim Law for checking local mean time data.
Thanks in particular to Arthur David Olson, the project's founder and first
maintainer, to whom the time zone community owes the greatest debt of all.
None of them are responsible for remaining errors.
-----
This file is in the public domain, so clarified as of 2009-05-17 by
Arthur David Olson. The other files in this distribution are either
public domain or BSD licensed; see the file LICENSE for details.

15
contrib/tzcode/SECURITY Normal file
View File

@ -0,0 +1,15 @@
Please report any sensitive security-related bugs via email to the
tzdb designated coordinators, currently Paul Eggert
<eggert@cs.ucla.edu> and Tim Parenti <tim@timtimeonline.com>.
Put "tzdb security" at the start of your email's subject line.
We prefer communications to be in English.
You should receive a response within a week. If not, please follow up
via email to make sure we received your original message.
If we confirm the bug, we plan to notify affected third-party services
or software that we know about, prepare an advisory, commit fixes to
the main development branch as quickly as is practical, and finally
publish the advisory on tz@iana.org. As with all tzdb contributions,
we give credit to security contributors unless they wish to remain
anonymous.

View File

@ -1,3 +1,5 @@
/* asctime and asctime_r a la POSIX and ISO C, except pad years before 1000. */
/*
** This file is in the public domain, so clarified as of
** 1996-06-05 by Arthur David Olson.
@ -9,27 +11,13 @@
** whereas the output of asctime is supposed to be constant.
*/
#include <sys/cdefs.h>
#ifndef lint
#ifndef NOID
static char elsieid[] __unused = "@(#)asctime.c 8.5";
#endif /* !defined NOID */
#endif /* !defined lint */
__FBSDID("$FreeBSD$");
/*LINTLIBRARY*/
#include "namespace.h"
#include "private.h"
#include "un-namespace.h"
#include "tzfile.h"
#include <stdio.h>
/*
** Some systems only handle "%.2d"; others only handle "%02d";
** "%02.2d" makes (most) everybody happy.
** At least some versions of gcc warn about the %02.2d;
** we conditionalize below to avoid the warning.
*/
/*
** All years associated with 32-bit time_t values are exactly four digits long;
** some years associated with 64-bit time_t values are not.
@ -39,61 +27,45 @@ __FBSDID("$FreeBSD$");
** leading zeroes to get the newline in the traditional place.
** The -4 ensures that we get four characters of output even if
** we call a strftime variant that produces fewer characters for some years.
** The ISO C 1999 and POSIX 1003.1-2004 standards prohibit padding the year,
** The ISO C and POSIX standards prohibit padding the year,
** but many implementations pad anyway; most likely the standards are buggy.
*/
#ifdef __GNUC__
#define ASCTIME_FMT "%.3s %.3s%3d %2.2d:%2.2d:%2.2d %-4s\n"
#else /* !defined __GNUC__ */
#define ASCTIME_FMT "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %-4s\n"
#endif /* !defined __GNUC__ */
static char const ASCTIME_FMT[] = "%s %s%3d %.2d:%.2d:%.2d %-4s\n";
/*
** For years that are more than four digits we put extra spaces before the year
** so that code trying to overwrite the newline won't end up overwriting
** a digit within a year and truncating the year (operating on the assumption
** that no output is better than wrong output).
*/
#ifdef __GNUC__
#define ASCTIME_FMT_B "%.3s %.3s%3d %2.2d:%2.2d:%2.2d %s\n"
#else /* !defined __GNUC__ */
#define ASCTIME_FMT_B "%.3s %.3s%3d %02.2d:%02.2d:%02.2d %s\n"
#endif /* !defined __GNUC__ */
static char const ASCTIME_FMT_B[] = "%s %s%3d %.2d:%.2d:%.2d %s\n";
#define STD_ASCTIME_BUF_SIZE 26
enum { STD_ASCTIME_BUF_SIZE = 26 };
/*
** Big enough for something such as
** ??? ???-2147483648 -2147483648:-2147483648:-2147483648 -2147483648\n
** (two three-character abbreviations, five strings denoting integers,
** seven explicit spaces, two explicit colons, a newline,
** and a trailing ASCII nul).
** and a trailing NUL byte).
** The values above are for systems where an int is 32 bits and are provided
** as an example; the define below calculates the maximum for the system at
** as an example; the size expression below is a bound for the system at
** hand.
*/
#define MAX_ASCTIME_BUF_SIZE (2*3+5*INT_STRLEN_MAXIMUM(int)+7+2+1+1)
static char buf_asctime[MAX_ASCTIME_BUF_SIZE];
/*
** A la ISO/IEC 9945-1, ANSI/IEEE Std 1003.1, 2004 Edition.
*/
static char buf_asctime[2*3 + 5*INT_STRLEN_MAXIMUM(int) + 7 + 2 + 1 + 1];
char *
asctime_r(timeptr, buf)
const struct tm * timeptr;
char * buf;
asctime_r(register const struct tm *timeptr, char *buf)
{
static const char wday_name[][3] = {
static const char wday_name[][4] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
static const char mon_name[][3] = {
static const char mon_name[][4] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
const char * wn;
const char * mn;
char year[INT_STRLEN_MAXIMUM(int) + 2];
char result[MAX_ASCTIME_BUF_SIZE];
char result[sizeof buf_asctime];
if (timeptr == NULL) {
errno = EINVAL;
@ -111,11 +83,11 @@ char * buf;
** Assume that strftime is unaffected by other out-of-range members
** (e.g., timeptr->tm_mday) when processing "%Y".
*/
(void) strftime(year, sizeof year, "%Y", timeptr);
strftime(year, sizeof year, "%Y", timeptr);
/*
** We avoid using snprintf since it's not available on all systems.
*/
(void) sprintf(result,
sprintf(result,
((strlen(year) <= 4) ? ASCTIME_FMT : ASCTIME_FMT_B),
wn, mn,
timeptr->tm_mday, timeptr->tm_hour,
@ -124,22 +96,13 @@ char * buf;
if (strlen(result) < STD_ASCTIME_BUF_SIZE || buf == buf_asctime)
return strcpy(buf, result);
else {
#ifdef EOVERFLOW
errno = EOVERFLOW;
#else /* !defined EOVERFLOW */
errno = EINVAL;
#endif /* !defined EOVERFLOW */
return NULL;
}
}
/*
** A la ISO/IEC 9945-1, ANSI/IEEE Std 1003.1, 2004 Edition.
*/
char *
asctime(timeptr)
const struct tm * timeptr;
asctime(register const struct tm *timeptr)
{
return asctime_r(timeptr, buf_asctime);
}

173
contrib/tzcode/calendars Normal file
View File

@ -0,0 +1,173 @@
----- Calendrical issues -----
As mentioned in Theory.html, although calendrical issues are out of
scope for tzdb, they indicate the sort of problems that we would run
into if we extended tzdb further into the past. The following
information and sources go beyond Theory.html's brief discussion.
They sometimes disagree.
France
Gregorian calendar adopted 1582-12-20.
French Revolutionary calendar used 1793-11-24 through 1805-12-31,
and (in Paris only) 1871-05-06 through 1871-05-23.
Russia
From Chris Carrier (1996-12-02):
On 1929-10-01 the Soviet Union instituted an "Eternal Calendar"
with 30-day months plus 5 holidays, with a 5-day week.
On 1931-12-01 it changed to a 6-day week; in 1934 it reverted to the
Gregorian calendar while retaining the 6-day week; on 1940-06-27 it
reverted to the 7-day week. With the 6-day week the usual days
off were the 6th, 12th, 18th, 24th and 30th of the month.
(Source: Evitiar Zerubavel, _The Seven Day Circle_)
Mark Brader reported a similar story in "The Book of Calendars", edited
by Frank Parise (1982, Facts on File, ISBN 0-8719-6467-8), page 377. But:
From: Petteri Sulonen (via Usenet)
Date: 14 Jan 1999 00:00:00 GMT
...
If your source is correct, how come documents between 1929 and 1940 were
still dated using the conventional, Gregorian calendar?
I can post a scan of a document dated December 1, 1934, signed by
Yenukidze, the secretary, on behalf of Kalinin, the President of the
Executive Committee of the Supreme Soviet, if you like.
Sweden (and Finland)
From: Mark Brader
Subject: Re: Gregorian reform - a part of locale?
<news:1996Jul6.012937.29190@sq.com>
Date: 1996-07-06
In 1700, Denmark made the transition from Julian to Gregorian. Sweden
decided to *start* a transition in 1700 as well, but rather than have one of
those unsightly calendar gaps :-), they simply decreed that the next leap
year after 1696 would be in 1744 - putting the whole country on a calendar
different from both Julian and Gregorian for a period of 40 years.
However, in 1704 something went wrong and the plan was not carried through;
they did, after all, have a leap year that year. And one in 1708. In 1712
they gave it up and went back to Julian, putting 30 days in February that
year!...
Then in 1753, Sweden made the transition to Gregorian in the usual manner,
getting there only 13 years behind the original schedule.
(A previous posting of this story was challenged, and Swedish readers
produced the following references to support it: "Tideräkning och historia"
by Natanael Beckman (1924) and "Tid, en bok om tideräkning och
kalenderväsen" by Lars-Olof Lodén (1968).
Grotefend's data
From: "Michael Palmer" [with two obvious typos fixed]
Subject: Re: Gregorian Calendar (was Re: Another FHC related question
Newsgroups: soc.genealogy.german
Date: Tue, 9 Feb 1999 02:32:48 -800
...
The following is a(n incomplete) listing, arranged chronologically, of
European states, with the date they converted from the Julian to the
Gregorian calendar:
04/15 Oct 1582 - Italy (with exceptions), Spain, Portugal, Poland (Roman
Catholics and Danzig only)
09/20 Dec 1582 - France, Lorraine
21 Dec 1582/
01 Jan 1583 - Holland, Brabant, Flanders, Hennegau
10/21 Feb 1583 - bishopric of Liege (Lüttich)
13/24 Feb 1583 - bishopric of Augsburg
04/15 Oct 1583 - electorate of Trier
05/16 Oct 1583 - Bavaria, bishoprics of Freising, Eichstedt, Regensburg,
Salzburg, Brixen
13/24 Oct 1583 - Austrian Oberelsaß and Breisgau
20/31 Oct 1583 - bishopric of Basel
02/13 Nov 1583 - duchy of Jülich-Berg
02/13 Nov 1583 - electorate and city of Köln
04/15 Nov 1583 - bishopric of Würzburg
11/22 Nov 1583 - electorate of Mainz
16/27 Nov 1583 - bishopric of Strassburg and the margraviate of Baden
17/28 Nov 1583 - bishopric of Münster and duchy of Cleve
14/25 Dec 1583 - Steiermark
06/17 Jan 1584 - Austria and Bohemia
11/22 Jan 1584 - Lucerne, Uri, Schwyz, Zug, Freiburg, Solothurn
12/23 Jan 1584 - Silesia and the Lausitz
22 Jan/
02 Feb 1584 - Hungary (legally on 21 Oct 1587)
Jun 1584 - Unterwalden
01/12 Jul 1584 - duchy of Westfalen
16/27 Jun 1585 - bishopric of Paderborn
14/25 Dec 1590 - Transylvania
22 Aug/
02 Sep 1612 - duchy of Prussia
13/24 Dec 1614 - Pfalz-Neuburg
1617 - duchy of Kurland (reverted to the Julian calendar in
1796)
1624 - bishopric of Osnabrück
1630 - bishopric of Minden
15/26 Mar 1631 - bishopric of Hildesheim
1655 - Kanton Wallis
05/16 Feb 1682 - city of Strassburg
18 Feb/
01 Mar 1700 - Protestant Germany (including Swedish possessions in
Germany), Denmark, Norway
30 Jun/
12 Jul 1700 - Gelderland, Zutphen
10 Nov/
12 Dec 1700 - Utrecht, Overijssel
31 Dec 1700/
12 Jan 1701 - Friesland, Groningen, Zürich, Bern, Basel, Geneva,
Thurgau, and Schaffhausen
1724 - Glarus, Appenzell, and the city of St. Gallen
01 Jan 1750 - Pisa and Florence
02/14 Sep 1752 - Great Britain
17 Feb/
01 Mar 1753 - Sweden
1760-1812 - Graubünden
The Russian empire (including Finland and the Baltic states) did not
convert to the Gregorian calendar until the Soviet revolution of 1917.
Source: H. Grotefend, _Taschenbuch der Zeitrechnung des deutschen
Mittelalters und der Neuzeit_, herausgegeben von Dr. O. Grotefend
(Hannover: Hahnsche Buchhandlung, 1941), pp. 26-28.
-----
This file is in the public domain, so clarified as of 2009-05-17 by
Arthur David Olson.
-----
Local Variables:
coding: utf-8
End:

167
contrib/tzcode/date.1 Normal file
View File

@ -0,0 +1,167 @@
.\" This file is in the public domain, so clarified as of
.\" 2009-05-17 by Arthur David Olson.
.TH date 1
.SH NAME
date \- show and set date and time
.SH SYNOPSIS
.if n .nh
.if n .na
.ie \n(.g .ds - \f(CR-\fP
.el .ds - \-
.B date
[
.B \*-u
] [
.B \*-c
] [
.B \*-r
.I seconds
] [
.BI + format
] [
\fR[\fIyyyy\fR]\fImmddhhmm\fR[\fIyy\fR][\fB.\fIss\fR]
]
.SH DESCRIPTION
.ie '\(lq'' .ds lq \&"\"
.el .ds lq \(lq\"
.ie '\(rq'' .ds rq \&"\"
.el .ds rq \(rq\"
.de q
\\$3\*(lq\\$1\*(rq\\$2
..
The
.B date
command
without arguments writes the date and time to the standard output in
the form
.ce 1
Wed Mar 8 14:54:40 EST 1989
.br
with
.B EST
replaced by the local time zone's abbreviation
(or by the abbreviation for the time zone specified in the
.B TZ
environment variable if set).
The exact output format depends on the locale.
.PP
If a command-line argument starts with a plus sign (\c
.q "\fB+\fP" ),
the rest of the argument is used as a
.I format
that controls what appears in the output.
In the format, when a percent sign (\c
.q "\fB%\fP"
appears,
it and the character after it are not output,
but rather identify part of the date or time
to be output in a particular way
(or identify a special character to output):
.nf
.sp
.if t .in +.5i
.if n .in +2
.ta \w'%M\0\0'u +\w'Wed Mar 8 14:54:40 EST 1989\0\0'u
Sample output Explanation
%a Wed Abbreviated weekday name*
%A Wednesday Full weekday name*
%b Mar Abbreviated month name*
%B March Full month name*
%c Wed Mar 08 14:54:40 1989 Date and time*
%C 19 Century
%d 08 Day of month (always two digits)
%D 03/08/89 Month/day/year (eight characters)
%e 8 Day of month (leading zero blanked)
%h Mar Abbreviated month name*
%H 14 24-hour-clock hour (two digits)
%I 02 12-hour-clock hour (two digits)
%j 067 Julian day number (three digits)
%k 2 12-hour-clock hour (leading zero blanked)
%l 14 24-hour-clock hour (leading zero blanked)
%m 03 Month number (two digits)
%M 54 Minute (two digits)
%n \\n newline character
%p PM AM/PM designation
%r 02:54:40 PM Hour:minute:second AM/PM designation
%R 14:54 Hour:minute
%S 40 Second (two digits)
%t \\t tab character
%T 14:54:40 Hour:minute:second
%U 10 Sunday-based week number (two digits)
%w 3 Day number (one digit, Sunday is 0)
%W 10 Monday-based week number (two digits)
%x 03/08/89 Date*
%X 14:54:40 Time*
%y 89 Last two digits of year
%Y 1989 Year in full
%z -0500 Numeric time zone
%Z EST Time zone abbreviation
%+ Wed Mar 8 14:54:40 EST 1989 Default output format*
.if t .in -.5i
.if n .in -2
* The exact output depends on the locale.
.sp
.fi
If a character other than one of those shown above appears after
a percent sign in the format,
that following character is output.
All other characters in the format are copied unchanged to the output;
a newline character is always added at the end of the output.
.PP
In Sunday-based week numbering,
the first Sunday of the year begins week 1;
days preceding it are part of
.q "week 0" .
In Monday-based week numbering,
the first Monday of the year begins week 1.
.PP
To set the date, use a command line argument with one of the following forms:
.nf
.if t .in +.5i
.if n .in +2
.ta \w'198903081454\0'u
1454 24-hour-clock hours (first two digits) and minutes
081454 Month day (first two digits), hours, and minutes
03081454 Month (two digits, January is 01), month day, hours, minutes
8903081454 Year, month, month day, hours, minutes
0308145489 Month, month day, hours, minutes, year
(on System V-compatible systems)
030814541989 Month, month day, hours, minutes, four-digit year
198903081454 Four-digit year, month, month day, hours, minutes
.if t .in -.5i
.if n .in -2
.fi
If the century, year, month, or month day is not given,
the current value is used.
Any of the above forms may be followed by a period and two digits that give
the seconds part of the new time; if no seconds are given, zero is assumed.
.PP
These options are available:
.TP
.BR \*-u " or " \*-c
Use Universal Time when setting and showing the date and time.
.TP
.BI "\*-r " seconds
Output the date that corresponds to
.I seconds
past the epoch of 1970-01-01 00:00:00 UTC, where
.I seconds
should be an integer, either decimal, octal (leading 0), or
hexadecimal (leading 0x), preceded by an optional sign.
.SH FILES
.ta \w'/usr/share/zoneinfo/posixrules\0\0'u
/etc/localtime local timezone file
.br
/usr/lib/locale/\f2L\fP/LC_TIME description of time locale \f2L\fP
.br
/usr/share/zoneinfo timezone information directory
.br
/usr/share/zoneinfo/posixrules used with POSIX-style TZ's
.br
/usr/share/zoneinfo/GMT for UTC leap seconds
.sp
If
.B /usr/share/zoneinfo/GMT
is absent,
UTC leap seconds are loaded from
.BR /usr/share/zoneinfo/posixrules .

216
contrib/tzcode/date.c Normal file
View File

@ -0,0 +1,216 @@
/* Display or set the current time and date. */
/* Copyright 1985, 1987, 1988 The Regents of the University of California.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE. */
#include "private.h"
#include <locale.h>
#include <stdio.h>
#if !HAVE_POSIX_DECLS
extern char * optarg;
extern int optind;
#endif
static int retval = EXIT_SUCCESS;
static void display(const char *, time_t);
static void dogmt(void);
static void errensure(void);
static void timeout(FILE *, const char *, const struct tm *);
static ATTRIBUTE_NORETURN void usage(void);
int
main(const int argc, char *argv[])
{
register const char * format = "+%+";
register int ch;
register bool rflag = false;
time_t t;
intmax_t secs;
char * endarg;
#ifdef LC_ALL
setlocale(LC_ALL, "");
#endif /* defined(LC_ALL) */
#if HAVE_GETTEXT
# ifdef TZ_DOMAINDIR
bindtextdomain(TZ_DOMAIN, TZ_DOMAINDIR);
# endif /* defined(TEXTDOMAINDIR) */
textdomain(TZ_DOMAIN);
#endif /* HAVE_GETTEXT */
t = time(NULL);
while ((ch = getopt(argc, argv, "ucr:")) != EOF && ch != -1) {
switch (ch) {
default:
usage();
case 'u': /* do it in UT */
case 'c':
dogmt();
break;
case 'r': /* seconds since 1970 */
if (rflag) {
fprintf(stderr,
_("date: error: multiple -r's used"));
usage();
}
rflag = true;
errno = 0;
secs = strtoimax(optarg, &endarg, 0);
if (*endarg || optarg == endarg)
errno = EINVAL;
else if (! (TIME_T_MIN <= secs && secs <= TIME_T_MAX))
errno = ERANGE;
if (errno) {
perror(optarg);
errensure();
exit(retval);
}
t = secs;
break;
}
}
if (optind < argc) {
if (argc - optind != 1) {
fprintf(stderr,
_("date: error: multiple operands in command line\n"));
usage();
}
format = argv[optind];
if (*format != '+') {
fprintf(stderr, _("date: unknown operand: %s\n"), format);
usage();
}
}
display(format, t);
return retval;
}
static void
dogmt(void)
{
static char ** fakeenv;
if (fakeenv == NULL) {
static char tzeutc0[] = "TZ=UTC0";
ptrdiff_t from, to, n;
for (n = 0; environ[n] != NULL; ++n)
continue;
#if defined ckd_add && defined ckd_mul
if (!ckd_add(&n, n, 2) && !ckd_mul(&n, n, sizeof *fakeenv)
&& n <= SIZE_MAX)
fakeenv = malloc(n);
#else
if (n <= min(PTRDIFF_MAX, SIZE_MAX) / sizeof *fakeenv - 2)
fakeenv = malloc((n + 2) * sizeof *fakeenv);
#endif
if (fakeenv == NULL) {
fprintf(stderr, _("date: Memory exhausted\n"));
errensure();
exit(retval);
}
to = 0;
fakeenv[to++] = tzeutc0;
for (from = 1; environ[from] != NULL; ++from)
if (strncmp(environ[from], "TZ=", 3) != 0)
fakeenv[to++] = environ[from];
fakeenv[to] = NULL;
environ = fakeenv;
}
}
static void
errensure(void)
{
if (retval == EXIT_SUCCESS)
retval = EXIT_FAILURE;
}
static void
usage(void)
{
fprintf(stderr,
_("date: usage: date [-u] [-c] [-r seconds]"
" [+format]\n"));
errensure();
exit(retval);
}
static void
display(char const *format, time_t now)
{
struct tm *tmp;
tmp = localtime(&now);
if (!tmp) {
fprintf(stderr,
_("date: error: time out of range\n"));
errensure();
return;
}
timeout(stdout, format, tmp);
putchar('\n');
fflush(stdout);
fflush(stderr);
if (ferror(stdout) || ferror(stderr)) {
fprintf(stderr,
_("date: error: couldn't write results\n"));
errensure();
}
}
static void
timeout(FILE *fp, char const *format, struct tm const *tmp)
{
char *cp = NULL;
ptrdiff_t result;
ptrdiff_t size = 1024 / 2;
for ( ; ; ) {
#ifdef ckd_mul
bool bigger = !ckd_mul(&size, size, 2) && size <= SIZE_MAX;
#else
bool bigger = (size <= min(PTRDIFF_MAX, SIZE_MAX) / 2
&& (size *= 2, true));
#endif
char *newcp = bigger ? realloc(cp, size) : NULL;
if (!newcp) {
fprintf(stderr,
_("date: error: can't get memory\n"));
errensure();
exit(retval);
}
cp = newcp;
result = strftime(cp, size, format, tmp);
if (result != 0)
break;
}
fwrite(cp + 1, 1, result - 1, fp);
free(cp);
}

62
contrib/tzcode/difftime.c Normal file
View File

@ -0,0 +1,62 @@
/* Return the difference between two timestamps. */
/*
** This file is in the public domain, so clarified as of
** 1996-06-05 by Arthur David Olson.
*/
/*LINTLIBRARY*/
#include "namespace.h"
#include "private.h" /* for time_t and TYPE_SIGNED */
#include "un-namespace.h"
/* Return -X as a double. Using this avoids casting to 'double'. */
static double
dminus(double x)
{
return -x;
}
double
difftime(time_t time1, time_t time0)
{
/*
** If double is large enough, simply convert and subtract
** (assuming that the larger type has more precision).
*/
if (sizeof(time_t) < sizeof(double)) {
double t1 = time1, t0 = time0;
return t1 - t0;
}
/*
** The difference of two unsigned values can't overflow
** if the minuend is greater than or equal to the subtrahend.
*/
if (!TYPE_SIGNED(time_t))
return time0 <= time1 ? time1 - time0 : dminus(time0 - time1);
/* Use uintmax_t if wide enough. */
if (sizeof(time_t) <= sizeof(uintmax_t)) {
uintmax_t t1 = time1, t0 = time0;
return time0 <= time1 ? t1 - t0 : dminus(t0 - t1);
}
/*
** Handle cases where both time1 and time0 have the same sign
** (meaning that their difference cannot overflow).
*/
if ((time1 < 0) == (time0 < 0))
return time1 - time0;
/*
** The values have opposite signs and uintmax_t is too narrow.
** This suffers from double rounding; attempt to lessen that
** by using long double temporaries.
*/
{
long double t1 = time1, t0 = time0;
return t1 - t0;
}
}

2669
contrib/tzcode/localtime.c Normal file

File diff suppressed because it is too large Load Diff

344
contrib/tzcode/newctime.3 Normal file
View File

@ -0,0 +1,344 @@
.\" This file is in the public domain, so clarified as of
.\" 2009-05-17 by Arthur David Olson.
.TH NEWCTIME 3
.SH NAME
asctime, ctime, difftime, gmtime, localtime, mktime \- convert date and time
.SH SYNOPSIS
.nf
.ie \n(.g .ds - \f(CR-\fP
.el .ds - \-
.B #include <time.h>
.PP
.BR "extern char *tzname[];" " /\(** (optional) \(**/"
.PP
.B char *ctime(time_t const *clock);
.PP
.B char *ctime_r(time_t const *clock, char *buf);
.PP
.B double difftime(time_t time1, time_t time0);
.PP
.B char *asctime(struct tm const *tm);
.PP
.B "char *asctime_r(struct tm const *restrict tm,"
.B " char *restrict result);"
.PP
.B struct tm *localtime(time_t const *clock);
.PP
.B "struct tm *localtime_r(time_t const *restrict clock,"
.B " struct tm *restrict result);"
.PP
.B "struct tm *localtime_rz(timezone_t restrict zone,"
.B " time_t const *restrict clock,"
.B " struct tm *restrict result);"
.PP
.B struct tm *gmtime(time_t const *clock);
.PP
.B "struct tm *gmtime_r(time_t const *restrict clock,"
.B " struct tm *restrict result);"
.PP
.B time_t mktime(struct tm *tm);
.PP
.B "time_t mktime_z(timezone_t restrict zone,"
.B " struct tm *restrict tm);"
.PP
.B cc ... \*-ltz
.fi
.SH DESCRIPTION
.ie '\(en'' .ds en \-
.el .ds en \(en
.ie '\(lq'' .ds lq \&"\"
.el .ds lq \(lq\"
.ie '\(rq'' .ds rq \&"\"
.el .ds rq \(rq\"
.de q
\\$3\*(lq\\$1\*(rq\\$2
..
The
.B ctime
function
converts a long integer, pointed to by
.IR clock ,
and returns a pointer to a
string of the form
.br
.ce
.eo
Thu Nov 24 18:22:48 1986\n\0
.br
.ec
Years requiring fewer than four characters are padded with leading zeroes.
For years longer than four characters, the string is of the form
.br
.ce
.eo
Thu Nov 24 18:22:48 81986\n\0
.ec
.br
with five spaces before the year.
These unusual formats are designed to make it less likely that older
software that expects exactly 26 bytes of output will mistakenly output
misleading values for out-of-range years.
.PP
The
.BI * clock
timestamp represents the time in seconds since 1970-01-01 00:00:00
Coordinated Universal Time (UTC).
The POSIX standard says that timestamps must be nonnegative
and must ignore leap seconds.
Many implementations extend POSIX by allowing negative timestamps,
and can therefore represent timestamps that predate the
introduction of UTC and are some other flavor of Universal Time (UT).
Some implementations support leap seconds, in contradiction to POSIX.
.PP
The
.B localtime
and
.B gmtime
functions
return pointers to
.q "tm"
structures, described below.
The
.B localtime
function
corrects for the time zone and any time zone adjustments
(such as Daylight Saving Time in the United States).
After filling in the
.q "tm"
structure,
.B localtime
sets the
.BR tm_isdst 'th
element of
.B tzname
to a pointer to a string that's the time zone abbreviation to be used with
.BR localtime 's
return value.
.PP
The
.B gmtime
function
converts to Coordinated Universal Time.
.PP
The
.B asctime
function
converts a time value contained in a
.q "tm"
structure to a string,
as shown in the above example,
and returns a pointer to the string.
.PP
The
.B mktime
function
converts the broken-down time,
expressed as local time,
in the structure pointed to by
.I tm
into a calendar time value with the same encoding as that of the values
returned by the
.B time
function.
The original values of the
.B tm_wday
and
.B tm_yday
components of the structure are ignored,
and the original values of the other components are not restricted
to their normal ranges.
(A positive or zero value for
.B tm_isdst
causes
.B mktime
to presume initially that daylight saving time
respectively,
is or is not in effect for the specified time.
A negative value for
.B tm_isdst
causes the
.B mktime
function to attempt to divine whether daylight saving time is in effect
for the specified time; in this case it does not use a consistent
rule and may give a different answer when later
presented with the same argument.)
On successful completion, the values of the
.B tm_wday
and
.B tm_yday
components of the structure are set appropriately,
and the other components are set to represent the specified calendar time,
but with their values forced to their normal ranges; the final value of
.B tm_mday
is not set until
.B tm_mon
and
.B tm_year
are determined.
The
.B mktime
function
returns the specified calendar time;
If the calendar time cannot be represented,
it returns \-1.
.PP
The
.B difftime
function
returns the difference between two calendar times,
.RI ( time1
\-
.IR time0 ),
expressed in seconds.
.PP
The
.BR ctime_r ,
.BR localtime_r ,
.BR gmtime_r ,
and
.B asctime_r
functions
are like their unsuffixed counterparts, except that they accept an
additional argument specifying where to store the result if successful.
.PP
The
.B localtime_rz
and
.B mktime_z
functions
are like their unsuffixed counterparts, except that they accept an
extra initial
.B zone
argument specifying the timezone to be used for conversion.
If
.B zone
is null, UT is used; otherwise,
.B zone
should be have been allocated by
.B tzalloc
and should not be freed until after all uses (e.g., by calls to
.BR strftime )
of the filled-in
.B tm_zone
fields.
.PP
Declarations of all the functions and externals, and the
.q "tm"
structure,
are in the
.B <time.h>
header file.
The structure (of type)
.B struct tm
includes the following fields:
.RS
.PP
.nf
.ta 2n +\w'long tm_gmtoff;nn'u
int tm_sec; /\(** seconds (0\*(en60) \(**/
int tm_min; /\(** minutes (0\*(en59) \(**/
int tm_hour; /\(** hours (0\*(en23) \(**/
int tm_mday; /\(** day of month (1\*(en31) \(**/
int tm_mon; /\(** month of year (0\*(en11) \(**/
int tm_year; /\(** year \- 1900 \(**/
int tm_wday; /\(** day of week (Sunday = 0) \(**/
int tm_yday; /\(** day of year (0\*(en365) \(**/
int tm_isdst; /\(** is daylight saving time in effect? \(**/
char \(**tm_zone; /\(** time zone abbreviation (optional) \(**/
long tm_gmtoff; /\(** offset from UT in seconds (optional) \(**/
.fi
.RE
.PP
The
.B tm_isdst
field
is non-zero if daylight saving time is in effect.
.PP
The
.B tm_gmtoff
field
is the offset (in seconds) of the time represented
from UT, with positive values indicating east
of the Prime Meridian.
The field's name is derived from Greenwich Mean Time, a precursor of UT.
.PP
In
.B "struct tm"
the
.B tm_zone
and
.B tm_gmtoff
fields exist, and are filled in, only if arrangements to do
so were made when the library containing these functions was
created.
Similarly, the
.B tzname
variable is optional; also, there is no guarantee that
.B tzname
will
continue to exist in this form in future releases of this code.
.SH FILES
.ta \w'/usr/share/zoneinfo/posixrules\0\0'u
/usr/share/zoneinfo timezone information directory
.br
/usr/share/zoneinfo/localtime local timezone file
.br
/usr/share/zoneinfo/posixrules used with POSIX-style TZ's
.br
/usr/share/zoneinfo/GMT for UTC leap seconds
.sp
If
.B /usr/share/zoneinfo/GMT
is absent,
UTC leap seconds are loaded from
.BR /usr/share/zoneinfo/posixrules .
.SH SEE ALSO
getenv(3),
newstrftime(3),
newtzset(3),
time(2),
tzfile(5)
.SH NOTES
The return values of
.BR asctime ,
.BR ctime ,
.BR gmtime ,
and
.B localtime
point to static data
overwritten by each call.
The
.B tzname
variable (once set) and the
.B tm_zone
field of a returned
.B "struct tm"
both point to an array of characters that
can be freed or overwritten by later calls to the functions
.BR localtime ,
.BR tzfree ,
and
.BR tzset ,
if these functions affect the timezone information that specifies the
abbreviation in question.
The remaining functions and data are thread-safe.
.PP
The
.BR asctime ,
.BR asctime_r ,
.BR ctime ,
and
.B ctime_r
functions
behave strangely for years before 1000 or after 9999.
The 1989 and 1999 editions of the C Standard say
that years from \-99 through 999 are converted without
extra spaces, but this conflicts with longstanding
tradition and with this implementation.
The 2011 edition says that the behavior
is undefined if the year is before 1000 or after 9999.
Traditional implementations of these two functions are
restricted to years in the range 1900 through 2099.
To avoid this portability mess, new programs should use
.B strftime
instead.

View File

@ -0,0 +1,290 @@
.\" strftime man page
.\"
.\" Based on the UCB file whose corrected copyright information appears below.
.\" Copyright 1989, 1991 The Regents of the University of California.
.\" All rights reserved.
.\"
.\" This code is derived from software contributed to Berkeley by
.\" the American National Standards Committee X3, on Information
.\" Processing Systems.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" from: @(#)strftime.3 5.12 (Berkeley) 6/29/91
.\" $Id: strftime.3,v 1.4 1993/12/15 20:33:00 jtc Exp $
.\"
.TH NEWSTRFTIME 3
.SH NAME
strftime \- format date and time
.SH SYNOPSIS
.nf
.ie \n(.g .ds - \f(CR-\fP
.el .ds - \-
.B #include <time.h>
.PP
.B "size_t strftime(char *restrict buf, size_t maxsize,"
.B " char const *restrict format, struct tm const *restrict timeptr);"
.PP
.B cc ... \-ltz
.fi
.SH DESCRIPTION
.ie '\(lq'' .ds lq \&"\"
.el .ds lq \(lq\"
.ie '\(rq'' .ds rq \&"\"
.el .ds rq \(rq\"
.de c
.ie \n(.g \f(CR\\$1\fP\\$2
.el \\$1\\$2
..
.de q
\\$3\*(lq\\$1\*(rq\\$2
..
The
.B strftime
function formats the information from
.I timeptr
into the array pointed to by
.I buf
according to the string pointed to by
.IR format .
.PP
The
.I format
string consists of zero or more conversion specifications and
ordinary characters.
All ordinary characters are copied directly into the array.
A conversion specification consists of a percent sign
.Ql %
and one other character.
.PP
No more than
.I maxsize
bytes are placed into the array.
.PP
Each conversion specification is replaced by the characters as
follows which are then copied into the array.
.TP
%A
is replaced by the locale's full weekday name.
.TP
%a
is replaced by the locale's abbreviated weekday name.
.TP
%B
is replaced by the locale's full month name.
.TP
%b or %h
is replaced by the locale's abbreviated month name.
.TP
%C
is replaced by the century (a year divided by 100 and truncated to an integer)
as a decimal number [00,99].
.TP
%c
is replaced by the locale's appropriate date and time representation.
.TP
%D
is equivalent to
.c %m/%d/%y .
.TP
%d
is replaced by the day of the month as a decimal number [01,31].
.TP
%e
is replaced by the day of month as a decimal number [1,31];
single digits are preceded by a blank.
.TP
%F
is equivalent to
.c %Y-%m-%d
(the ISO 8601 date format).
.TP
%G
is replaced by the ISO 8601 year with century as a decimal number.
See also the
.c %V
conversion specification.
.TP
%g
is replaced by the ISO 8601 year without century as a decimal number [00,99].
This is the year that includes the greater part of the week.
(Monday as the first day of a week).
See also the
.c %V
conversion specification.
.TP
%H
is replaced by the hour (24-hour clock) as a decimal number [00,23].
.TP
%I
is replaced by the hour (12-hour clock) as a decimal number [01,12].
.TP
%j
is replaced by the day of the year as a decimal number [001,366].
.TP
%k
is replaced by the hour (24-hour clock) as a decimal number [0,23];
single digits are preceded by a blank.
.TP
%l
is replaced by the hour (12-hour clock) as a decimal number [1,12];
single digits are preceded by a blank.
.TP
%M
is replaced by the minute as a decimal number [00,59].
.TP
%m
is replaced by the month as a decimal number [01,12].
.TP
%n
is replaced by a newline.
.TP
%p
is replaced by the locale's equivalent of either
.q AM
or
.q PM .
.TP
%R
is replaced by the time in the format
.c %H:%M .
.TP
%r
is replaced by the locale's representation of 12-hour clock time
using AM/PM notation.
.TP
%S
is replaced by the second as a decimal number [00,60].
The range of
seconds is [00,60] instead of [00,59] to allow for the periodic occurrence
of leap seconds.
.TP
%s
is replaced by the number of seconds since the Epoch (see
.BR ctime (3)).
.TP
%T
is replaced by the time in the format
.c %H:%M:%S .
.TP
%t
is replaced by a tab.
.TP
%U
is replaced by the week number of the year (Sunday as the first day of
the week) as a decimal number [00,53].
.TP
%u
is replaced by the weekday (Monday as the first day of the week)
as a decimal number [1,7].
.TP
%V
is replaced by the week number of the year (Monday as the first day of
the week) as a decimal number [01,53]. If the week containing January
1 has four or more days in the new year, then it is week 1; otherwise
it is week 53 of the previous year, and the next week is week 1.
The year is given by the
.c %G
conversion specification.
.TP
%W
is replaced by the week number of the year (Monday as the first day of
the week) as a decimal number [00,53].
.TP
%w
is replaced by the weekday (Sunday as the first day of the week)
as a decimal number [0,6].
.TP
%X
is replaced by the locale's appropriate time representation.
.TP
%x
is replaced by the locale's appropriate date representation.
.TP
%Y
is replaced by the year with century as a decimal number.
.TP
%y
is replaced by the year without century as a decimal number [00,99].
.TP
%Z
is replaced by the time zone abbreviation,
or by the empty string if this is not determinable.
.TP
%z
is replaced by the offset from the Prime Meridian
in the format +HHMM or \*-HHMM (ISO 8601) as appropriate,
with positive values representing locations east of Greenwich,
or by the empty string if this is not determinable.
The numeric time zone abbreviation \*-0000 is used when the time is
Universal Time
but local time is indeterminate; by convention this is used for
locations while uninhabited, and corresponds to a zero offset when the
time zone abbreviation begins with
.q "\*-" .
.TP
%%
is replaced by a single %.
.TP
%+
is replaced by the locale's date and time in
.BR date (1)
format.
.SH "RETURN VALUE"
If the conversion is successful,
.B strftime
returns the number of bytes placed into the array, not counting the
terminating NUL;
.B errno
is unchanged if the returned value is zero.
Otherwise,
.B errno
is set to indicate the error, zero is returned,
and the array contents are unspecified.
.SH ERRORS
This function fails if:
.TP
[ERANGE]
The total number of resulting bytes, including the terminating
NUL character, is more than
.IR maxsize .
.PP
This function may fail if:
.TP
[EOVERFLOW]
The format includes an
.c %s
conversion and the number of seconds since the Epoch cannot be represented
in a
.c time_t .
.SH SEE ALSO
date(1),
getenv(3),
newctime(3),
newtzset(3),
time(2),
tzfile(5)
.SH BUGS
There is no conversion specification for the phase of the moon.

350
contrib/tzcode/newtzset.3 Normal file
View File

@ -0,0 +1,350 @@
.\" This file is in the public domain, so clarified as of
.\" 2009-05-17 by Arthur David Olson.
.TH NEWTZSET 3
.SH NAME
tzset \- initialize time conversion information
.SH SYNOPSIS
.nf
.ie \n(.g .ds - \f(CR-\fP
.el .ds - \-
.B #include <time.h>
.PP
.B timezone_t tzalloc(char const *TZ);
.PP
.B void tzfree(timezone_t tz);
.PP
.B void tzset(void);
.PP
.B cc ... \*-ltz
.fi
.SH DESCRIPTION
.ie '\(en'' .ds en \-
.el .ds en \(en
.ie '\(lq'' .ds lq \&"\"
.el .ds lq \(lq\"
.ie '\(rq'' .ds rq \&"\"
.el .ds rq \(rq\"
.de q
\\$3\*(lq\\$1\*(rq\\$2
..
The
.B tzalloc
function
allocates and returns a timezone object described by
.BR TZ .
If
.B TZ
is not a valid timezone description, or if the object cannot be allocated,
.B tzalloc
returns a null pointer and sets
.BR errno .
.PP
The
.B tzfree
function
frees a timezone object
.BR tz ,
which should have been successfully allocated by
.BR tzalloc .
This invalidates any
.B tm_zone
pointers that
.B tz
was used to set.
.PP
The
.B tzset
function
acts like
.BR tzalloc(getenv("TZ")) ,
except it saves any resulting timezone object into internal
storage that is accessed by
.BR localtime ,
.BR localtime_r ,
and
.BR mktime .
The anonymous shared timezone object is freed by the next call to
.BR tzset .
If the implied call to
.B tzalloc
fails,
.B tzset
falls back on Universal Time (UT).
.PP
If
.B TZ
is null, the best available approximation to local (wall
clock) time, as specified by the
.BR tzfile (5)-format
file
.B localtime
in the system time conversion information directory, is used.
If
.B TZ
is the empty string,
UT is used, with the abbreviation "UTC"
and without leap second correction; please see
.BR newctime (3)
for more about UT, UTC, and leap seconds. If
.B TZ
is nonnull and nonempty:
.IP
if the value begins with a colon, it is used as a pathname of a file
from which to read the time conversion information;
.IP
if the value does not begin with a colon, it is first used as the
pathname of a file from which to read the time conversion information,
and, if that file cannot be read, is used directly as a specification of
the time conversion information.
.PP
When
.B TZ
is used as a pathname, if it begins with a slash,
it is used as an absolute pathname; otherwise,
it is used as a pathname relative to a system time conversion information
directory.
The file must be in the format specified in
.BR tzfile (5).
.PP
When
.B TZ
is used directly as a specification of the time conversion information,
it must have the following syntax (spaces inserted for clarity):
.IP
\fIstd\|offset\fR[\fIdst\fR[\fIoffset\fR][\fB,\fIrule\fR]]
.PP
Where:
.RS
.TP 15
.IR std " and " dst
Three or more bytes that are the designation for the standard
.RI ( std )
or the alternative
.RI ( dst ,
such as daylight saving time)
time zone. Only
.I std
is required; if
.I dst
is missing, then daylight saving time does not apply in this locale.
Upper- and lowercase letters are explicitly allowed. Any characters
except a leading colon
.RB ( : ),
digits, comma
.RB ( , ),
ASCII minus
.RB ( \*- ),
ASCII plus
.RB ( + ),
and NUL bytes are allowed.
Alternatively, a designation can be surrounded by angle brackets
.B <
and
.BR > ;
in this case, the designation can contain any characters other than
.B >
and NUL.
.TP
.I offset
Indicates the value one must add to the local time to arrive at
Coordinated Universal Time. The
.I offset
has the form:
.RS
.IP
\fIhh\fR[\fB:\fImm\fR[\fB:\fIss\fR]]
.RE
.IP
The minutes
.RI ( mm )
and seconds
.RI ( ss )
are optional. The hour
.RI ( hh )
is required and may be a single digit. The
.I offset
following
.I std
is required. If no
.I offset
follows
.IR dst ,
daylight saving time is assumed to be one hour ahead of standard time. One or
more digits may be used; the value is always interpreted as a decimal
number. The hour must be between zero and 24, and the minutes (and
seconds) \*(en if present \*(en between zero and 59. If preceded by a
.q "\*-" ,
the time zone shall be east of the Prime Meridian; otherwise it shall be
west (which may be indicated by an optional preceding
.q "+" .
.TP
.I rule
Indicates when to change to and back from daylight saving time. The
.I rule
has the form:
.RS
.IP
\fIdate\fB/\fItime\fB,\fIdate\fB/\fItime\fR
.RE
.IP
where the first
.I date
describes when the change from standard to daylight saving time occurs and the
second
.I date
describes when the change back happens. Each
.I time
field describes when, in current local time, the change to the other
time is made.
As an extension to POSIX, daylight saving is assumed to be in effect
all year if it begins January 1 at 00:00 and ends December 31 at
24:00 plus the difference between daylight saving and standard time,
leaving no room for standard time in the calendar.
.IP
The format of
.I date
is one of the following:
.RS
.TP 10
.BI J n
The Julian day
.I n
.RI "(1\ \(<=" "\ n\ " "\(<=\ 365).
Leap days are not counted; that is, in all years \*(en including leap
years \*(en February 28 is day 59 and March 1 is day 60. It is
impossible to explicitly refer to the occasional February 29.
.TP
.I n
The zero-based Julian day
.RI "(0\ \(<=" "\ n\ " "\(<=\ 365).
Leap days are counted, and it is possible to refer to February 29.
.TP
.BI M m . n . d
The
.IR d' th
day
.RI "(0\ \(<=" "\ d\ " "\(<=\ 6)
of week
.I n
of month
.I m
of the year
.RI "(1\ \(<=" "\ n\ " "\(<=\ 5,
.RI "1\ \(<=" "\ m\ " "\(<=\ 12,
where week 5 means
.q "the last \fId\fP day in month \fIm\fP"
which may occur in either the fourth or the fifth week). Week 1 is the
first week in which the
.IR d' th
day occurs. Day zero is Sunday.
.RE
.IP "" 15
The
.I time
has the same format as
.I offset
except that POSIX does not allow a leading sign (\c
.q "\*-"
or
.q "+" ).
As an extension to POSIX, the hours part of
.I time
can range from \-167 through 167; this allows for unusual rules such
as
.q "the Saturday before the first Sunday of March" .
The default, if
.I time
is not given, is
.BR 02:00:00 .
.RE
.LP
Here are some examples of
.B TZ
values that directly specify the timezone; they use some of the
extensions to POSIX.
.TP
.B EST5
stands for US Eastern Standard
Time (EST), 5 hours behind UT, without daylight saving.
.TP
.B <+12>\*-12<+13>,M11.1.0,M1.2.1/147
stands for Fiji time, 12 hours ahead
of UT, springing forward on November's first Sunday at 02:00, and
falling back on January's second Monday at 147:00 (i.e., 03:00 on the
first Sunday on or after January 14). The abbreviations for standard
and daylight saving time are
.q "+12"
and
.q "+13".
.TP
.B IST\*-2IDT,M3.4.4/26,M10.5.0
stands for Israel Standard Time (IST) and Israel Daylight Time (IDT),
2 hours ahead of UT, springing forward on March's fourth
Thursday at 26:00 (i.e., 02:00 on the first Friday on or after March
23), and falling back on October's last Sunday at 02:00.
.TP
.B <\*-04>4<\*-03>,J1/0,J365/25
stands for permanent daylight saving time, 3 hours behind UT with
abbreviation
.q "\*-03".
There is a dummy fall-back transition on December 31 at 25:00 daylight
saving time (i.e., 24:00 standard time, equivalent to January 1 at
00:00 standard time), and a simultaneous spring-forward transition on
January 1 at 00:00 standard time, so daylight saving time is in effect
all year and the initial
.B <\*-04>
is a placeholder.
.TP
.B <\*-03>3<\*-02>,M3.5.0/\*-2,M10.5.0/\*-1
stands for time in western Greenland, 3 hours behind UT, where clocks
follow the EU rules of
springing forward on March's last Sunday at 01:00 UT (\-02:00 local
time, i.e., 22:00 the previous day) and falling back on October's last
Sunday at 01:00 UT (\-01:00 local time, i.e., 23:00 the previous day).
The abbreviations for standard and daylight saving time are
.q "\*-03"
and
.q "\*-02".
.PP
If no
.I rule
is present in
.BR TZ ,
the rules specified
by the
.BR tzfile (5)-format
file
.B posixrules
in the system time conversion information directory are used, with the
standard and daylight saving time offsets from UT replaced by those specified by
the
.I offset
values in
.BR TZ .
.PP
For compatibility with System V Release 3.1, a semicolon
.RB ( ; )
may be used to separate the
.I rule
from the rest of the specification.
.SH FILES
.ta \w'/usr/share/zoneinfo/posixrules\0\0'u
/usr/share/zoneinfo timezone information directory
.br
/usr/share/zoneinfo/localtime local timezone file
.br
/usr/share/zoneinfo/posixrules used with POSIX-style TZ
.br
/usr/share/zoneinfo/GMT for UTC leap seconds
.sp
If
.B /usr/share/zoneinfo/GMT
is absent,
UTC leap seconds are loaded from
.BR /usr/share/zoneinfo/posixrules .
.SH SEE ALSO
getenv(3),
newctime(3),
newstrftime(3),
time(2),
tzfile(5)

957
contrib/tzcode/private.h Normal file
View File

@ -0,0 +1,957 @@
/* Private header for tzdb code. */
#ifndef PRIVATE_H
#define PRIVATE_H
/*
** This file is in the public domain, so clarified as of
** 1996-06-05 by Arthur David Olson.
**
** $FreeBSD$
*/
/* Stuff moved from Makefile.inc to reduce clutter */
#ifndef TM_GMTOFF
#define TM_GMTOFF tm_gmtoff
#define TM_ZONE tm_zone
#define PCTS 1
#define HAVE_LONG_DOUBLE 1
#define HAVE_UNISTD_H 1
#define LOCALE_HOME _PATH_LOCALE
#define TZDIR "/usr/share/zoneinfo"
#endif /* ndef TM_GMTOFF */
/*
** This header is for use ONLY with the time conversion code.
** There is no guarantee that it will remain unchanged,
** or that it will remain at all.
** Do NOT copy it to any system include directory.
** Thank you!
*/
#ifndef __STDC_VERSION__
# define __STDC_VERSION__ 0
#endif
/* Define true, false and bool if they don't work out of the box. */
#if __STDC_VERSION__ < 199901
# define true 1
# define false 0
# define bool int
#elif __STDC_VERSION__ < 202311
# include <stdbool.h>
#endif
/*
** zdump has been made independent of the rest of the time
** conversion package to increase confidence in the verification it provides.
** You can use zdump to help in verifying other implementations.
** To do this, compile with -DUSE_LTZ=0 and link without the tz library.
*/
#ifndef USE_LTZ
# define USE_LTZ 1
#endif
/* This string was in the Factory zone through version 2016f. */
#define GRANDPARENTED "Local time zone must be set--use tzsetup"
/*
** Defaults for preprocessor symbols.
** You can override these in your C compiler options, e.g. '-DHAVE_GETTEXT=1'.
*/
#ifndef HAVE_DECL_ASCTIME_R
# define HAVE_DECL_ASCTIME_R 1
#endif
#if !defined HAVE_GENERIC && defined __has_extension
# if __has_extension(c_generic_selections)
# define HAVE_GENERIC 1
# else
# define HAVE_GENERIC 0
# endif
#endif
/* _Generic is buggy in pre-4.9 GCC. */
#if !defined HAVE_GENERIC && defined __GNUC__ && !defined __STRICT_ANSI__
# define HAVE_GENERIC (4 < __GNUC__ + (9 <= __GNUC_MINOR__))
#endif
#ifndef HAVE_GENERIC
# define HAVE_GENERIC (201112 <= __STDC_VERSION__)
#endif
#if !defined HAVE_GETTEXT && defined __has_include
# if __has_include(<libintl.h>)
# define HAVE_GETTEXT true
# endif
#endif
#ifndef HAVE_GETTEXT
# define HAVE_GETTEXT false
#endif
#ifndef HAVE_INCOMPATIBLE_CTIME_R
# define HAVE_INCOMPATIBLE_CTIME_R 0
#endif
#ifndef HAVE_LINK
# define HAVE_LINK 1
#endif /* !defined HAVE_LINK */
#ifndef HAVE_MALLOC_ERRNO
# define HAVE_MALLOC_ERRNO 1
#endif
#ifndef HAVE_POSIX_DECLS
# define HAVE_POSIX_DECLS 1
#endif
#ifndef HAVE_SETENV
# define HAVE_SETENV 1
#endif
#ifndef HAVE_STRDUP
# define HAVE_STRDUP 1
#endif
#ifndef HAVE_STRTOLL
# define HAVE_STRTOLL 1
#endif
#ifndef HAVE_SYMLINK
# define HAVE_SYMLINK 1
#endif /* !defined HAVE_SYMLINK */
#if !defined HAVE_SYS_STAT_H && defined __has_include
# if !__has_include(<sys/stat.h>)
# define HAVE_SYS_STAT_H false
# endif
#endif
#ifndef HAVE_SYS_STAT_H
# define HAVE_SYS_STAT_H true
#endif
#if !defined HAVE_UNISTD_H && defined __has_include
# if !__has_include(<unistd.h>)
# define HAVE_UNISTD_H false
# endif
#endif
#ifndef HAVE_UNISTD_H
# define HAVE_UNISTD_H true
#endif
#ifndef NETBSD_INSPIRED
# define NETBSD_INSPIRED 1
#endif
#if HAVE_INCOMPATIBLE_CTIME_R
# define asctime_r _incompatible_asctime_r
# define ctime_r _incompatible_ctime_r
#endif /* HAVE_INCOMPATIBLE_CTIME_R */
/* Enable tm_gmtoff, tm_zone, and environ on GNUish systems. */
#define _GNU_SOURCE 1
/* Fix asctime_r on Solaris 11. */
#define _POSIX_PTHREAD_SEMANTICS 1
/* Enable strtoimax on pre-C99 Solaris 11. */
#define __EXTENSIONS__ 1
/* On GNUish systems where time_t might be 32 or 64 bits, use 64.
On these platforms _FILE_OFFSET_BITS must also be 64; otherwise
setting _TIME_BITS to 64 does not work. The code does not
otherwise rely on _FILE_OFFSET_BITS being 64, since it does not
use off_t or functions like 'stat' that depend on off_t. */
#ifndef _FILE_OFFSET_BITS
# define _FILE_OFFSET_BITS 64
#endif
#if !defined _TIME_BITS && _FILE_OFFSET_BITS == 64
# define _TIME_BITS 64
#endif
/*
** Nested includes
*/
/* Avoid clashes with NetBSD by renaming NetBSD's declarations.
If defining the 'timezone' variable, avoid a clash with FreeBSD's
'timezone' function by renaming its declaration. */
#define localtime_rz sys_localtime_rz
#define mktime_z sys_mktime_z
#define posix2time_z sys_posix2time_z
#define time2posix_z sys_time2posix_z
#if defined USG_COMPAT && USG_COMPAT == 2
# define timezone sys_timezone
#endif
#define timezone_t sys_timezone_t
#define tzalloc sys_tzalloc
#define tzfree sys_tzfree
#include <time.h>
#undef localtime_rz
#undef mktime_z
#undef posix2time_z
#undef time2posix_z
#if defined USG_COMPAT && USG_COMPAT == 2
# undef timezone
#endif
#undef timezone_t
#undef tzalloc
#undef tzfree
#include <stddef.h>
#include <string.h>
#include <limits.h> /* for CHAR_BIT et al. */
#include <stdlib.h>
#include <errno.h>
#ifndef EINVAL
# define EINVAL ERANGE
#endif
#ifndef ELOOP
# define ELOOP EINVAL
#endif
#ifndef ENAMETOOLONG
# define ENAMETOOLONG EINVAL
#endif
#ifndef ENOMEM
# define ENOMEM EINVAL
#endif
#ifndef ENOTSUP
# define ENOTSUP EINVAL
#endif
#ifndef EOVERFLOW
# define EOVERFLOW EINVAL
#endif
#if HAVE_GETTEXT
# include <libintl.h>
#endif /* HAVE_GETTEXT */
#if HAVE_UNISTD_H
# include <unistd.h> /* for R_OK, and other POSIX goodness */
#endif /* HAVE_UNISTD_H */
#ifndef HAVE_STRFTIME_L
# if _POSIX_VERSION < 200809
# define HAVE_STRFTIME_L 0
# else
# define HAVE_STRFTIME_L 1
# endif
#endif
#ifndef USG_COMPAT
# ifndef _XOPEN_VERSION
# define USG_COMPAT 0
# else
# define USG_COMPAT 1
# endif
#endif
#ifndef HAVE_TZNAME
# if _POSIX_VERSION < 198808 && !USG_COMPAT
# define HAVE_TZNAME 0
# else
# define HAVE_TZNAME 1
# endif
#endif
#ifndef ALTZONE
# if defined __sun || defined _M_XENIX
# define ALTZONE 1
# else
# define ALTZONE 0
# endif
#endif
#ifndef R_OK
# define R_OK 4
#endif /* !defined R_OK */
/*
** Define HAVE_STDINT_H's default value here, rather than at the
** start, since __GLIBC__ and INTMAX_MAX's values depend on
** previously-included files. glibc 2.1 and Solaris 10 and later have
** stdint.h, even with pre-C99 compilers.
*/
#if !defined HAVE_STDINT_H && defined __has_include
# define HAVE_STDINT_H true /* C23 __has_include implies C99 stdint.h. */
#endif
#ifndef HAVE_STDINT_H
# define HAVE_STDINT_H \
(199901 <= __STDC_VERSION__ \
|| 2 < __GLIBC__ + (1 <= __GLIBC_MINOR__) \
|| __CYGWIN__ || INTMAX_MAX)
#endif /* !defined HAVE_STDINT_H */
#if HAVE_STDINT_H
# include <stdint.h>
#endif /* !HAVE_STDINT_H */
#ifndef HAVE_INTTYPES_H
# define HAVE_INTTYPES_H HAVE_STDINT_H
#endif
#if HAVE_INTTYPES_H
# include <inttypes.h>
#endif
/* Pre-C99 GCC compilers define __LONG_LONG_MAX__ instead of LLONG_MAX. */
#if defined __LONG_LONG_MAX__ && !defined __STRICT_ANSI__
# ifndef LLONG_MAX
# define LLONG_MAX __LONG_LONG_MAX__
# endif
# ifndef LLONG_MIN
# define LLONG_MIN (-1 - LLONG_MAX)
# endif
# ifndef ULLONG_MAX
# define ULLONG_MAX (LLONG_MAX * 2ull + 1)
# endif
#endif
#ifndef INT_FAST64_MAX
# if 1 <= LONG_MAX >> 31 >> 31
typedef long int_fast64_t;
# define INT_FAST64_MIN LONG_MIN
# define INT_FAST64_MAX LONG_MAX
# else
/* If this fails, compile with -DHAVE_STDINT_H or with a better compiler. */
typedef long long int_fast64_t;
# define INT_FAST64_MIN LLONG_MIN
# define INT_FAST64_MAX LLONG_MAX
# endif
#endif
#ifndef PRIdFAST64
# if INT_FAST64_MAX == LONG_MAX
# define PRIdFAST64 "ld"
# else
# define PRIdFAST64 "lld"
# endif
#endif
#ifndef SCNdFAST64
# define SCNdFAST64 PRIdFAST64
#endif
#ifndef INT_FAST32_MAX
# if INT_MAX >> 31 == 0
typedef long int_fast32_t;
# define INT_FAST32_MAX LONG_MAX
# define INT_FAST32_MIN LONG_MIN
# else
typedef int int_fast32_t;
# define INT_FAST32_MAX INT_MAX
# define INT_FAST32_MIN INT_MIN
# endif
#endif
#ifndef INTMAX_MAX
# ifdef LLONG_MAX
typedef long long intmax_t;
# if HAVE_STRTOLL
# define strtoimax strtoll
# endif
# define INTMAX_MAX LLONG_MAX
# define INTMAX_MIN LLONG_MIN
# else
typedef long intmax_t;
# define INTMAX_MAX LONG_MAX
# define INTMAX_MIN LONG_MIN
# endif
# ifndef strtoimax
# define strtoimax strtol
# endif
#endif
#ifndef PRIdMAX
# if INTMAX_MAX == LLONG_MAX
# define PRIdMAX "lld"
# else
# define PRIdMAX "ld"
# endif
#endif
#ifndef PTRDIFF_MAX
# define PTRDIFF_MAX MAXVAL(ptrdiff_t, TYPE_BIT(ptrdiff_t))
#endif
#ifndef UINT_FAST32_MAX
typedef unsigned long uint_fast32_t;
#endif
#ifndef UINT_FAST64_MAX
# if 3 <= ULONG_MAX >> 31 >> 31
typedef unsigned long uint_fast64_t;
# define UINT_FAST64_MAX ULONG_MAX
# else
/* If this fails, compile with -DHAVE_STDINT_H or with a better compiler. */
typedef unsigned long long uint_fast64_t;
# define UINT_FAST64_MAX ULLONG_MAX
# endif
#endif
#ifndef UINTMAX_MAX
# ifdef ULLONG_MAX
typedef unsigned long long uintmax_t;
# else
typedef unsigned long uintmax_t;
# endif
#endif
#ifndef PRIuMAX
# ifdef ULLONG_MAX
# define PRIuMAX "llu"
# else
# define PRIuMAX "lu"
# endif
#endif
#ifndef SIZE_MAX
# define SIZE_MAX ((size_t) -1)
#endif
/* Support ckd_add, ckd_sub, ckd_mul on C23 or recent-enough GCC-like
hosts, unless compiled with -DHAVE_STDCKDINT_H=0 or with pre-C23 EDG. */
#if !defined HAVE_STDCKDINT_H && defined __has_include
# if __has_include(<stdckdint.h>)
# define HAVE_STDCKDINT_H true
# endif
#endif
#ifdef HAVE_STDCKDINT_H
# if HAVE_STDCKDINT_H
# include <stdckdint.h>
# endif
#elif defined __EDG__
/* Do nothing, to work around EDG bug <https://bugs.gnu.org/53256>. */
#elif defined __has_builtin
# if __has_builtin(__builtin_add_overflow)
# define ckd_add(r, a, b) __builtin_add_overflow(a, b, r)
# endif
# if __has_builtin(__builtin_sub_overflow)
# define ckd_sub(r, a, b) __builtin_sub_overflow(a, b, r)
# endif
# if __has_builtin(__builtin_mul_overflow)
# define ckd_mul(r, a, b) __builtin_mul_overflow(a, b, r)
# endif
#elif 7 <= __GNUC__
# define ckd_add(r, a, b) __builtin_add_overflow(a, b, r)
# define ckd_sub(r, a, b) __builtin_sub_overflow(a, b, r)
# define ckd_mul(r, a, b) __builtin_mul_overflow(a, b, r)
#endif
#if 3 <= __GNUC__
# define ATTRIBUTE_MALLOC __attribute__((malloc))
# define ATTRIBUTE_FORMAT(spec) __attribute__((format spec))
#else
# define ATTRIBUTE_MALLOC /* empty */
# define ATTRIBUTE_FORMAT(spec) /* empty */
#endif
#if (defined __has_c_attribute \
&& (202311 <= __STDC_VERSION__ || !defined __STRICT_ANSI__))
# define HAVE_HAS_C_ATTRIBUTE true
#else
# define HAVE_HAS_C_ATTRIBUTE false
#endif
#if HAVE_HAS_C_ATTRIBUTE
# if __has_c_attribute(fallthrough)
# define ATTRIBUTE_FALLTHROUGH [[fallthrough]]
# endif
#endif
#ifndef ATTRIBUTE_FALLTHROUGH
# if 7 <= __GNUC__
# define ATTRIBUTE_FALLTHROUGH __attribute__((fallthrough))
# else
# define ATTRIBUTE_FALLTHROUGH ((void) 0)
# endif
#endif
#if HAVE_HAS_C_ATTRIBUTE
# if __has_c_attribute(maybe_unused)
# define ATTRIBUTE_MAYBE_UNUSED [[maybe_unused]]
# endif
#endif
#ifndef ATTRIBUTE_MAYBE_UNUSED
# if 2 < __GNUC__ + (7 <= __GNUC_MINOR__)
# define ATTRIBUTE_MAYBE_UNUSED __attribute__((unused))
# else
# define ATTRIBUTE_MAYBE_UNUSED /* empty */
# endif
#endif
#if HAVE_HAS_C_ATTRIBUTE
# if __has_c_attribute(noreturn)
# define ATTRIBUTE_NORETURN [[noreturn]]
# endif
#endif
#ifndef ATTRIBUTE_NORETURN
# if 201112 <= __STDC_VERSION__
# define ATTRIBUTE_NORETURN _Noreturn
# elif 2 < __GNUC__ + (8 <= __GNUC_MINOR__)
# define ATTRIBUTE_NORETURN __attribute__((noreturn))
# else
# define ATTRIBUTE_NORETURN /* empty */
# endif
#endif
#if HAVE_HAS_C_ATTRIBUTE
# if __has_c_attribute(reproducible)
# define ATTRIBUTE_REPRODUCIBLE [[reproducible]]
# endif
#endif
#ifndef ATTRIBUTE_REPRODUCIBLE
# if 3 <= __GNUC__
# define ATTRIBUTE_REPRODUCIBLE __attribute__((pure))
# else
# define ATTRIBUTE_REPRODUCIBLE /* empty */
# endif
#endif
#if HAVE_HAS_C_ATTRIBUTE
# if __has_c_attribute(unsequenced)
# define ATTRIBUTE_UNSEQUENCED [[unsequenced]]
# endif
#endif
#ifndef ATTRIBUTE_UNSEQUENCED
# if 3 <= __GNUC__
# define ATTRIBUTE_UNSEQUENCED __attribute__((const))
# else
# define ATTRIBUTE_UNSEQUENCED /* empty */
# endif
#endif
#if __STDC_VERSION__ < 199901 && !defined restrict
# define restrict /* empty */
#endif
#if 2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__)
# define ATTRIBUTE_PURE __attribute__ ((__pure__))
#else
# define ATTRIBUTE_PURE /* empty */
#endif
/*
** Workarounds for compilers/systems.
*/
#ifndef EPOCH_LOCAL
# define EPOCH_LOCAL 0
#endif
#ifndef EPOCH_OFFSET
# define EPOCH_OFFSET 0
#endif
#ifndef RESERVE_STD_EXT_IDS
# define RESERVE_STD_EXT_IDS 0
#endif
/* If standard C identifiers with external linkage (e.g., localtime)
are reserved and are not already being renamed anyway, rename them
as if compiling with '-Dtime_tz=time_t'. */
#if !defined time_tz && RESERVE_STD_EXT_IDS && USE_LTZ
# define time_tz time_t
#endif
/*
** Compile with -Dtime_tz=T to build the tz package with a private
** time_t type equivalent to T rather than the system-supplied time_t.
** This debugging feature can test unusual design decisions
** (e.g., time_t wider than 'long', or unsigned time_t) even on
** typical platforms.
*/
#if defined time_tz || EPOCH_LOCAL || EPOCH_OFFSET != 0
# define TZ_TIME_T 1
#else
# define TZ_TIME_T 0
#endif
#if defined LOCALTIME_IMPLEMENTATION && TZ_TIME_T
static time_t sys_time(time_t *x) { return time(x); }
#endif
#if TZ_TIME_T
typedef time_tz tz_time_t;
# undef asctime
# define asctime tz_asctime
# undef asctime_r
# define asctime_r tz_asctime_r
# undef ctime
# define ctime tz_ctime
# undef ctime_r
# define ctime_r tz_ctime_r
# undef difftime
# define difftime tz_difftime
# undef gmtime
# define gmtime tz_gmtime
# undef gmtime_r
# define gmtime_r tz_gmtime_r
# undef localtime
# define localtime tz_localtime
# undef localtime_r
# define localtime_r tz_localtime_r
# undef localtime_rz
# define localtime_rz tz_localtime_rz
# undef mktime
# define mktime tz_mktime
# undef mktime_z
# define mktime_z tz_mktime_z
# undef offtime
# define offtime tz_offtime
# undef posix2time
# define posix2time tz_posix2time
# undef posix2time_z
# define posix2time_z tz_posix2time_z
# undef strftime
# define strftime tz_strftime
# undef time
# define time tz_time
# undef time2posix
# define time2posix tz_time2posix
# undef time2posix_z
# define time2posix_z tz_time2posix_z
# undef time_t
# define time_t tz_time_t
# undef timegm
# define timegm tz_timegm
# undef timelocal
# define timelocal tz_timelocal
# undef timeoff
# define timeoff tz_timeoff
# undef tzalloc
# define tzalloc tz_tzalloc
# undef tzfree
# define tzfree tz_tzfree
# undef tzset
# define tzset tz_tzset
# if HAVE_STRFTIME_L
# undef strftime_l
# define strftime_l tz_strftime_l
# endif
# if HAVE_TZNAME
# undef tzname
# define tzname tz_tzname
# endif
# if USG_COMPAT
# undef daylight
# define daylight tz_daylight
# undef timezone
# define timezone tz_timezone
# endif
# if ALTZONE
# undef altzone
# define altzone tz_altzone
# endif
char *asctime(struct tm const *);
char *asctime_r(struct tm const *restrict, char *restrict);
char *ctime(time_t const *);
char *ctime_r(time_t const *, char *);
double difftime(time_t, time_t) ATTRIBUTE_UNSEQUENCED;
size_t strftime(char *restrict, size_t, char const *restrict,
struct tm const *restrict);
# if HAVE_STRFTIME_L
size_t strftime_l(char *restrict, size_t, char const *restrict,
struct tm const *restrict, locale_t);
# endif
struct tm *gmtime(time_t const *);
struct tm *gmtime_r(time_t const *restrict, struct tm *restrict);
struct tm *localtime(time_t const *);
struct tm *localtime_r(time_t const *restrict, struct tm *restrict);
time_t mktime(struct tm *);
time_t time(time_t *);
time_t timegm(struct tm *);
void tzset(void);
#endif
#ifndef HAVE_DECL_TIMEGM
# if (202311 <= __STDC_VERSION__ \
|| defined __GLIBC__ || defined __tm_zone /* musl */ \
|| defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ \
|| (defined __APPLE__ && defined __MACH__))
# define HAVE_DECL_TIMEGM true
# else
# define HAVE_DECL_TIMEGM false
# endif
#endif
#if !HAVE_DECL_TIMEGM && !defined timegm
time_t timegm(struct tm *);
#endif
#if !HAVE_DECL_ASCTIME_R && !defined asctime_r
extern char *asctime_r(struct tm const *restrict, char *restrict);
#endif
#ifndef HAVE_DECL_ENVIRON
# if defined environ || defined __USE_GNU
# define HAVE_DECL_ENVIRON 1
# else
# define HAVE_DECL_ENVIRON 0
# endif
#endif
#if !HAVE_DECL_ENVIRON
extern char **environ;
#endif
#if 2 <= HAVE_TZNAME + (TZ_TIME_T || !HAVE_POSIX_DECLS)
extern char *tzname[];
#endif
#if 2 <= USG_COMPAT + (TZ_TIME_T || !HAVE_POSIX_DECLS)
extern long timezone;
extern int daylight;
#endif
#if 2 <= ALTZONE + (TZ_TIME_T || !HAVE_POSIX_DECLS)
extern long altzone;
#endif
/*
** The STD_INSPIRED functions are similar, but most also need
** declarations if time_tz is defined.
*/
#ifdef STD_INSPIRED
# if TZ_TIME_T || !defined offtime
struct tm *offtime(time_t const *, long);
# endif
# if TZ_TIME_T || !defined timelocal
time_t timelocal(struct tm *);
# endif
# if TZ_TIME_T || !defined timeoff
time_t timeoff(struct tm *, long);
# endif
# if TZ_TIME_T || !defined time2posix
time_t time2posix(time_t);
# endif
# if TZ_TIME_T || !defined posix2time
time_t posix2time(time_t);
# endif
#endif
/* Infer TM_ZONE on systems where this information is known, but suppress
guessing if NO_TM_ZONE is defined. Similarly for TM_GMTOFF. */
#if (defined __GLIBC__ \
|| defined __tm_zone /* musl */ \
|| defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ \
|| (defined __APPLE__ && defined __MACH__))
# if !defined TM_GMTOFF && !defined NO_TM_GMTOFF
# define TM_GMTOFF tm_gmtoff
# endif
# if !defined TM_ZONE && !defined NO_TM_ZONE
# define TM_ZONE tm_zone
# endif
#endif
/*
** Define functions that are ABI compatible with NetBSD but have
** better prototypes. NetBSD 6.1.4 defines a pointer type timezone_t
** and labors under the misconception that 'const timezone_t' is a
** pointer to a constant. This use of 'const' is ineffective, so it
** is not done here. What we call 'struct state' NetBSD calls
** 'struct __state', but this is a private name so it doesn't matter.
*/
#if NETBSD_INSPIRED
typedef struct state *timezone_t;
struct tm *localtime_rz(timezone_t restrict, time_t const *restrict,
struct tm *restrict);
time_t mktime_z(timezone_t restrict, struct tm *restrict);
timezone_t tzalloc(char const *);
void tzfree(timezone_t);
# ifdef STD_INSPIRED
# if TZ_TIME_T || !defined posix2time_z
time_t posix2time_z(timezone_t, time_t) ATTRIBUTE_REPRODUCIBLE;
# endif
# if TZ_TIME_T || !defined time2posix_z
time_t time2posix_z(timezone_t, time_t) ATTRIBUTE_REPRODUCIBLE;
# endif
# endif
#endif
/*
** Finally, some convenience items.
*/
#define TYPE_BIT(type) (sizeof(type) * CHAR_BIT)
#define TYPE_SIGNED(type) (((type) -1) < 0)
#define TWOS_COMPLEMENT(t) ((t) ~ (t) 0 < 0)
/* Minimum and maximum of two values. Use lower case to avoid
naming clashes with standard include files. */
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
/* Max and min values of the integer type T, of which only the bottom
B bits are used, and where the highest-order used bit is considered
to be a sign bit if T is signed. */
#define MAXVAL(t, b) \
((t) (((t) 1 << ((b) - 1 - TYPE_SIGNED(t))) \
- 1 + ((t) 1 << ((b) - 1 - TYPE_SIGNED(t)))))
#define MINVAL(t, b) \
((t) (TYPE_SIGNED(t) ? - TWOS_COMPLEMENT(t) - MAXVAL(t, b) : 0))
/* The extreme time values, assuming no padding. */
#define TIME_T_MIN_NO_PADDING MINVAL(time_t, TYPE_BIT(time_t))
#define TIME_T_MAX_NO_PADDING MAXVAL(time_t, TYPE_BIT(time_t))
/* The extreme time values. These are macros, not constants, so that
any portability problems occur only when compiling .c files that use
the macros, which is safer for applications that need only zdump and zic.
This implementation assumes no padding if time_t is signed and
either the compiler lacks support for _Generic or time_t is not one
of the standard signed integer types. */
#if HAVE_GENERIC
# define TIME_T_MIN \
_Generic((time_t) 0, \
signed char: SCHAR_MIN, short: SHRT_MIN, \
int: INT_MIN, long: LONG_MIN, long long: LLONG_MIN, \
default: TIME_T_MIN_NO_PADDING)
# define TIME_T_MAX \
(TYPE_SIGNED(time_t) \
? _Generic((time_t) 0, \
signed char: SCHAR_MAX, short: SHRT_MAX, \
int: INT_MAX, long: LONG_MAX, long long: LLONG_MAX, \
default: TIME_T_MAX_NO_PADDING) \
: (time_t) -1)
#else
# define TIME_T_MIN TIME_T_MIN_NO_PADDING
# define TIME_T_MAX TIME_T_MAX_NO_PADDING
#endif
/*
** 302 / 1000 is log10(2.0) rounded up.
** Subtract one for the sign bit if the type is signed;
** add one for integer division truncation;
** add one more for a minus sign if the type is signed.
*/
#define INT_STRLEN_MAXIMUM(type) \
((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + \
1 + TYPE_SIGNED(type))
/*
** INITIALIZE(x)
*/
#ifdef GCC_LINT
# define INITIALIZE(x) ((x) = 0)
#else
# define INITIALIZE(x)
#endif
/* Whether memory access must strictly follow the C standard.
If 0, it's OK to read uninitialized storage so long as the value is
not relied upon. Defining it to 0 lets mktime access parts of
struct tm that might be uninitialized, as a heuristic when the
standard doesn't say what to return and when tm_gmtoff can help
mktime likely infer a better value. */
#ifndef UNINIT_TRAP
# define UNINIT_TRAP 0
#endif
#ifdef DEBUG
# undef unreachable
# define unreachable() abort()
#elif !defined unreachable
# ifdef __has_builtin
# if __has_builtin(__builtin_unreachable)
# define unreachable() __builtin_unreachable()
# endif
# elif 4 < __GNUC__ + (5 <= __GNUC_MINOR__)
# define unreachable() __builtin_unreachable()
# endif
# ifndef unreachable
# define unreachable() ((void) 0)
# endif
#endif
/*
** For the benefit of GNU folk...
** '_(MSGID)' uses the current locale's message library string for MSGID.
** The default is to use gettext if available, and use MSGID otherwise.
*/
#if HAVE_GETTEXT
#define _(msgid) gettext(msgid)
#else /* !HAVE_GETTEXT */
#define _(msgid) msgid
#endif /* !HAVE_GETTEXT */
#if !defined TZ_DOMAIN && defined HAVE_GETTEXT
# define TZ_DOMAIN "tz"
#endif
#if HAVE_INCOMPATIBLE_CTIME_R
#undef asctime_r
#undef ctime_r
char *asctime_r(struct tm const *, char *);
char *ctime_r(time_t const *, char *);
#endif /* HAVE_INCOMPATIBLE_CTIME_R */
/* Handy macros that are independent of tzfile implementation. */
enum {
SECSPERMIN = 60,
MINSPERHOUR = 60,
SECSPERHOUR = SECSPERMIN * MINSPERHOUR,
HOURSPERDAY = 24,
DAYSPERWEEK = 7,
DAYSPERNYEAR = 365,
DAYSPERLYEAR = DAYSPERNYEAR + 1,
MONSPERYEAR = 12,
YEARSPERREPEAT = 400 /* years before a Gregorian repeat */
};
#define SECSPERDAY ((int_fast32_t) SECSPERHOUR * HOURSPERDAY)
#define DAYSPERREPEAT ((int_fast32_t) 400 * 365 + 100 - 4 + 1)
#define SECSPERREPEAT ((int_fast64_t) DAYSPERREPEAT * SECSPERDAY)
#define AVGSECSPERYEAR (SECSPERREPEAT / YEARSPERREPEAT)
enum {
TM_SUNDAY,
TM_MONDAY,
TM_TUESDAY,
TM_WEDNESDAY,
TM_THURSDAY,
TM_FRIDAY,
TM_SATURDAY
};
enum {
TM_JANUARY,
TM_FEBRUARY,
TM_MARCH,
TM_APRIL,
TM_MAY,
TM_JUNE,
TM_JULY,
TM_AUGUST,
TM_SEPTEMBER,
TM_OCTOBER,
TM_NOVEMBER,
TM_DECEMBER
};
enum {
TM_YEAR_BASE = 1900,
TM_WDAY_BASE = TM_MONDAY,
EPOCH_YEAR = 1970,
EPOCH_WDAY = TM_THURSDAY
};
#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
/*
** Since everything in isleap is modulo 400 (or a factor of 400), we know that
** isleap(y) == isleap(y % 400)
** and so
** isleap(a + b) == isleap((a + b) % 400)
** or
** isleap(a + b) == isleap(a % 400 + b % 400)
** This is true even if % means modulo rather than Fortran remainder
** (which is allowed by C89 but not by C99 or later).
** We use this to avoid addition overflow problems.
*/
#define isleap_sum(a, b) isleap((a) % 400 + (b) % 400)
#endif /* !defined PRIVATE_H */

View File

@ -1,67 +0,0 @@
/*
** This file is in the public domain, so clarified as of
** 1996-06-05 by Arthur David Olson.
*/
#include <sys/cdefs.h>
#ifndef lint
#ifndef NOID
static char elsieid[] __unused = "@(#)difftime.c 8.1";
#endif /* !defined NOID */
#endif /* !defined lint */
__FBSDID("$FreeBSD$");
/*LINTLIBRARY*/
#include "namespace.h"
#include "private.h" /* for time_t, TYPE_INTEGRAL, and TYPE_SIGNED */
#include "un-namespace.h"
double
difftime(const time_t time1, const time_t time0)
{
/*
** If (sizeof (double) > sizeof (time_t)) simply convert and subtract
** (assuming that the larger type has more precision).
** This is the common real-world case circa 2004.
*/
if (sizeof (double) > sizeof (time_t))
return (double) time1 - (double) time0;
if (!TYPE_INTEGRAL(time_t)) {
/*
** time_t is floating.
*/
return time1 - time0;
}
if (!TYPE_SIGNED(time_t)) {
/*
** time_t is integral and unsigned.
** The difference of two unsigned values can't overflow
** if the minuend is greater than or equal to the subtrahend.
*/
if (time1 >= time0)
return time1 - time0;
else return -((double) (time0 - time1));
}
/*
** time_t is integral and signed.
** Handle cases where both time1 and time0 have the same sign
** (meaning that their difference cannot overflow).
*/
if ((time1 < 0) == (time0 < 0))
return time1 - time0;
/*
** time1 and time0 have opposite signs.
** Punt if unsigned long is too narrow.
*/
if (sizeof (unsigned long) < sizeof (time_t))
return (double) time1 - (double) time0;
/*
** Stay calm...decent optimizers will eliminate the complexity below.
*/
if (time1 >= 0 /* && time0 < 0 */)
return (unsigned long) time1 +
(unsigned long) (-(time0 + 1)) + 1;
return -(double) ((unsigned long) time0 +
(unsigned long) (-(time1 + 1)) + 1);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,318 +0,0 @@
#ifndef PRIVATE_H
#define PRIVATE_H
/*
** This file is in the public domain, so clarified as of
** 1996-06-05 by Arthur David Olson.
**
** $FreeBSD$
*/
/* Stuff moved from Makefile.inc to reduce clutter */
#ifndef TM_GMTOFF
#define TM_GMTOFF tm_gmtoff
#define TM_ZONE tm_zone
#define STD_INSPIRED 1
#define PCTS 1
#define HAVE_LONG_DOUBLE 1
#define HAVE_STRERROR 1
#define HAVE_UNISTD_H 1
#define LOCALE_HOME _PATH_LOCALE
#define TZDIR "/usr/share/zoneinfo"
#endif /* ndef TM_GMTOFF */
/*
** This header is for use ONLY with the time conversion code.
** There is no guarantee that it will remain unchanged,
** or that it will remain at all.
** Do NOT copy it to any system include directory.
** Thank you!
*/
/*
** ID
*/
#ifndef lint
#ifndef NOID
/*
static char privatehid[] = "@(#)private.h 8.6";
*/
#endif /* !defined NOID */
#endif /* !defined lint */
#define GRANDPARENTED "Local time zone must be set--see zic manual page"
/*
** Defaults for preprocessor symbols.
** You can override these in your C compiler options, e.g. `-DHAVE_ADJTIME=0'.
*/
#ifndef HAVE_ADJTIME
#define HAVE_ADJTIME 1
#endif /* !defined HAVE_ADJTIME */
#ifndef HAVE_GETTEXT
#define HAVE_GETTEXT 0
#endif /* !defined HAVE_GETTEXT */
#ifndef HAVE_INCOMPATIBLE_CTIME_R
#define HAVE_INCOMPATIBLE_CTIME_R 0
#endif /* !defined INCOMPATIBLE_CTIME_R */
#ifndef HAVE_SETTIMEOFDAY
#define HAVE_SETTIMEOFDAY 3
#endif /* !defined HAVE_SETTIMEOFDAY */
#ifndef HAVE_SYMLINK
#define HAVE_SYMLINK 1
#endif /* !defined HAVE_SYMLINK */
#ifndef HAVE_SYS_STAT_H
#define HAVE_SYS_STAT_H 1
#endif /* !defined HAVE_SYS_STAT_H */
#ifndef HAVE_SYS_WAIT_H
#define HAVE_SYS_WAIT_H 1
#endif /* !defined HAVE_SYS_WAIT_H */
#ifndef HAVE_UNISTD_H
#define HAVE_UNISTD_H 1
#endif /* !defined HAVE_UNISTD_H */
#ifndef HAVE_UTMPX_H
#define HAVE_UTMPX_H 0
#endif /* !defined HAVE_UTMPX_H */
#ifndef LOCALE_HOME
#define LOCALE_HOME "/usr/lib/locale"
#endif /* !defined LOCALE_HOME */
#if HAVE_INCOMPATIBLE_CTIME_R
#define asctime_r _incompatible_asctime_r
#define ctime_r _incompatible_ctime_r
#endif /* HAVE_INCOMPATIBLE_CTIME_R */
/*
** Nested includes
*/
#include "sys/types.h" /* for time_t */
#include "stdio.h"
#include "errno.h"
#include "string.h"
#include "limits.h" /* for CHAR_BIT et al. */
#include "time.h"
#include "stdlib.h"
#if HAVE_GETTEXT
#include "libintl.h"
#endif /* HAVE_GETTEXT */
#if HAVE_SYS_WAIT_H
#include <sys/wait.h> /* for WIFEXITED and WEXITSTATUS */
#endif /* HAVE_SYS_WAIT_H */
#ifndef WIFEXITED
#define WIFEXITED(status) (((status) & 0xff) == 0)
#endif /* !defined WIFEXITED */
#ifndef WEXITSTATUS
#define WEXITSTATUS(status) (((status) >> 8) & 0xff)
#endif /* !defined WEXITSTATUS */
#if HAVE_UNISTD_H
#include "unistd.h" /* for F_OK, R_OK, and other POSIX goodness */
#endif /* HAVE_UNISTD_H */
#if !(HAVE_UNISTD_H)
#ifndef F_OK
#define F_OK 0
#endif /* !defined F_OK */
#ifndef R_OK
#define R_OK 4
#endif /* !defined R_OK */
#endif /* !(HAVE_UNISTD_H) */
/* Unlike <ctype.h>'s isdigit, this also works if c < 0 | c > UCHAR_MAX. */
#define is_digit(c) ((unsigned)(c) - '0' <= 9)
/*
** Define HAVE_STDINT_H's default value here, rather than at the
** start, since __GLIBC__'s value depends on previously-included
** files.
** (glibc 2.1 and later have stdint.h, even with pre-C99 compilers.)
*/
#ifndef HAVE_STDINT_H
#define HAVE_STDINT_H \
(199901 <= __STDC_VERSION__ || \
2 < (__GLIBC__ + (0 < __GLIBC_MINOR__)))
#endif /* !defined HAVE_STDINT_H */
#if HAVE_STDINT_H
#include "stdint.h"
#endif /* !HAVE_STDINT_H */
#ifndef INT_FAST64_MAX
/* Pre-C99 GCC compilers define __LONG_LONG_MAX__ instead of LLONG_MAX. */
#if defined LLONG_MAX || defined __LONG_LONG_MAX__
typedef long long int_fast64_t;
#else /* ! (defined LLONG_MAX || defined __LONG_LONG_MAX__) */
#if (LONG_MAX >> 31) < 0xffffffff
Please use a compiler that supports a 64-bit integer type (or wider);
you may need to compile with "-DHAVE_STDINT_H".
#endif /* (LONG_MAX >> 31) < 0xffffffff */
typedef long int_fast64_t;
#endif /* ! (defined LLONG_MAX || defined __LONG_LONG_MAX__) */
#endif /* !defined INT_FAST64_MAX */
#ifndef INT32_MAX
#define INT32_MAX 0x7fffffff
#endif /* !defined INT32_MAX */
#ifndef INT32_MIN
#define INT32_MIN (-1 - INT32_MAX)
#endif /* !defined INT32_MIN */
#if 2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__)
# define ATTRIBUTE_PURE __attribute__ ((__pure__))
#else
# define ATTRIBUTE_PURE /* empty */
#endif
/*
** Workarounds for compilers/systems.
*/
/*
** Some time.h implementations don't declare asctime_r.
** Others might define it as a macro.
** Fix the former without affecting the latter.
*/
#ifndef asctime_r
extern char * asctime_r(struct tm const *, char *);
#endif
/*
** Private function declarations.
*/
char * icatalloc(char * old, const char * new);
char * icpyalloc(const char * string);
const char * scheck(const char * string, const char * format);
/*
** Finally, some convenience items.
*/
#ifndef TRUE
#define TRUE 1
#endif /* !defined TRUE */
#ifndef FALSE
#define FALSE 0
#endif /* !defined FALSE */
#ifndef TYPE_BIT
#define TYPE_BIT(type) (sizeof (type) * CHAR_BIT)
#endif /* !defined TYPE_BIT */
#ifndef TYPE_SIGNED
#define TYPE_SIGNED(type) (((type) -1) < 0)
#endif /* !defined TYPE_SIGNED */
/*
** Since the definition of TYPE_INTEGRAL contains floating point numbers,
** it cannot be used in preprocessor directives.
*/
#ifndef TYPE_INTEGRAL
#define TYPE_INTEGRAL(type) (((type) 0.5) != 0.5)
#endif /* !defined TYPE_INTEGRAL */
#ifndef INT_STRLEN_MAXIMUM
/*
** 302 / 1000 is log10(2.0) rounded up.
** Subtract one for the sign bit if the type is signed;
** add one for integer division truncation;
** add one more for a minus sign if the type is signed.
*/
#define INT_STRLEN_MAXIMUM(type) \
((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + \
1 + TYPE_SIGNED(type))
#endif /* !defined INT_STRLEN_MAXIMUM */
/*
** INITIALIZE(x)
*/
#ifndef GNUC_or_lint
#ifdef lint
#define GNUC_or_lint
#endif /* defined lint */
#ifndef lint
#ifdef __GNUC__
#define GNUC_or_lint
#endif /* defined __GNUC__ */
#endif /* !defined lint */
#endif /* !defined GNUC_or_lint */
#ifndef INITIALIZE
#ifdef GNUC_or_lint
#define INITIALIZE(x) ((x) = 0)
#endif /* defined GNUC_or_lint */
#ifndef GNUC_or_lint
#define INITIALIZE(x)
#endif /* !defined GNUC_or_lint */
#endif /* !defined INITIALIZE */
/*
** For the benefit of GNU folk...
** `_(MSGID)' uses the current locale's message library string for MSGID.
** The default is to use gettext if available, and use MSGID otherwise.
*/
#ifndef _
#if HAVE_GETTEXT
#define _(msgid) gettext(msgid)
#else /* !HAVE_GETTEXT */
#define _(msgid) msgid
#endif /* !HAVE_GETTEXT */
#endif /* !defined _ */
#ifndef TZ_DOMAIN
#define TZ_DOMAIN "tz"
#endif /* !defined TZ_DOMAIN */
#if HAVE_INCOMPATIBLE_CTIME_R
#undef asctime_r
#undef ctime_r
char *asctime_r(struct tm const *, char *);
char *ctime_r(time_t const *, char *);
#endif /* HAVE_INCOMPATIBLE_CTIME_R */
#ifndef YEARSPERREPEAT
#define YEARSPERREPEAT 400 /* years before a Gregorian repeat */
#endif /* !defined YEARSPERREPEAT */
/*
** The Gregorian year averages 365.2425 days, which is 31556952 seconds.
*/
#ifndef AVGSECSPERYEAR
#define AVGSECSPERYEAR 31556952L
#endif /* !defined AVGSECSPERYEAR */
#ifndef SECSPERREPEAT
#define SECSPERREPEAT ((int_fast64_t) YEARSPERREPEAT * (int_fast64_t) AVGSECSPERYEAR)
#endif /* !defined SECSPERREPEAT */
#ifndef SECSPERREPEAT_BITS
#define SECSPERREPEAT_BITS 34 /* ceil(log2(SECSPERREPEAT)) */
#endif /* !defined SECSPERREPEAT_BITS */
/*
** UNIX was a registered trademark of The Open Group in 2003.
*/
#endif /* !defined PRIVATE_H */

View File

@ -1,152 +0,0 @@
.\" $FreeBSD$
.Dd September 13, 1994
.Dt TZFILE 5
.Os
.Sh NAME
.Nm tzfile
.Nd timezone information
.Sh SYNOPSIS
.Fd #include \&"/usr/src/contrib/tzcode/stdtime/tzfile.h\&"
.Sh DESCRIPTION
The time zone information files used by
.Xr tzset 3
begin with the magic characters
.Dq Li TZif
to identify them as
time zone information files,
followed by a character identifying the version of the file's format
(as of 2005, either an ASCII NUL or a '2')
followed by fifteen bytes containing zeroes reserved for future use,
followed by four four-byte values
written in a ``standard'' byte order
(the high-order byte of the value is written first).
These values are,
in order:
.Pp
.Bl -tag -compact -width tzh_ttisstdcnt
.It Va tzh_ttisgmtcnt
The number of UTC/local indicators stored in the file.
.It Va tzh_ttisstdcnt
The number of standard/wall indicators stored in the file.
.It Va tzh_leapcnt
The number of leap seconds for which data is stored in the file.
.It Va tzh_timecnt
The number of ``transition times'' for which data is stored
in the file.
.It Va tzh_typecnt
The number of ``local time types'' for which data is stored
in the file (must not be zero).
.It Va tzh_charcnt
The number of characters of ``time zone abbreviation strings''
stored in the file.
.El
.Pp
The above header is followed by
.Va tzh_timecnt
four-byte values of type
.Fa long ,
sorted in ascending order.
These values are written in ``standard'' byte order.
Each is used as a transition time (as returned by
.Xr time 3 )
at which the rules for computing local time change.
Next come
.Va tzh_timecnt
one-byte values of type
.Fa "unsigned char" ;
each one tells which of the different types of ``local time'' types
described in the file is associated with the same-indexed transition time.
These values serve as indices into an array of
.Fa ttinfo
structures (with
.Fa tzh_typecnt
entries) that appears next in the file;
these structures are defined as follows:
.Pp
.Bd -literal -offset indent
struct ttinfo {
long tt_gmtoff;
int tt_isdst;
unsigned int tt_abbrind;
};
.Ed
.Pp
Each structure is written as a four-byte value for
.Va tt_gmtoff
of type
.Fa long ,
in a standard byte order, followed by a one-byte value for
.Va tt_isdst
and a one-byte value for
.Va tt_abbrind .
In each structure,
.Va tt_gmtoff
gives the number of seconds to be added to UTC,
.Li tt_isdst
tells whether
.Li tm_isdst
should be set by
.Xr localtime 3
and
.Va tt_abbrind
serves as an index into the array of time zone abbreviation characters
that follow the
.Li ttinfo
structure(s) in the file.
.Pp
Then there are
.Va tzh_leapcnt
pairs of four-byte values, written in standard byte order;
the first value of each pair gives the time
(as returned by
.Xr time 3 )
at which a leap second occurs;
the second gives the
.Em total
number of leap seconds to be applied after the given time.
The pairs of values are sorted in ascending order by time.
.Pp
Then there are
.Va tzh_ttisstdcnt
standard/wall indicators, each stored as a one-byte value;
they tell whether the transition times associated with local time types
were specified as standard time or wall clock time,
and are used when a time zone file is used in handling POSIX-style
time zone environment variables.
.Pp
Finally there are
.Va tzh_ttisgmtcnt
UTC/local indicators, each stored as a one-byte value;
they tell whether the transition times associated with local time types
were specified as UTC or local time,
and are used when a time zone file is used in handling POSIX-style
time zone environment variables.
.Pp
.Nm localtime
uses the first standard-time
.Li ttinfo
structure in the file
(or simply the first
.Li ttinfo
structure in the absence of a standard-time structure)
if either
.Li tzh_timecnt
is zero or the time argument is less than the first transition time recorded
in the file.
.Pp
For version-2-format time zone files,
the above header and data is followed by a second header and data,
identical in format except that eight bytes are used for each
transition time or leap second time.
After the second header and data comes a newline-enclosed,
POSIX-TZ-environment-variable-style string for use in handling instants
after the last transition time stored in the file
(with nothing between the newlines if there is no POSIX representation for
such instants).
.Sh SEE ALSO
.Xr ctime 3 ,
.Xr time2posix 3 ,
.Xr zic 8
.\" @(#)tzfile.5 8.3
.\" This file is in the public domain, so clarified as of
.\" 1996-06-05 by Arthur David Olson.

View File

@ -1,184 +0,0 @@
#ifndef TZFILE_H
#define TZFILE_H
/*
** This file is in the public domain, so clarified as of
** 1996-06-05 by Arthur David Olson.
**
** $FreeBSD$
*/
/*
** This header is for use ONLY with the time conversion code.
** There is no guarantee that it will remain unchanged,
** or that it will remain at all.
** Do NOT copy it to any system include directory.
** Thank you!
*/
/*
** ID
*/
#ifndef lint
#ifndef NOID
/*
static char tzfilehid[] = "@(#)tzfile.h 8.1";
*/
#endif /* !defined NOID */
#endif /* !defined lint */
/*
** Information about time zone files.
*/
#ifndef TZDIR
#define TZDIR "/usr/share/zoneinfo" /* Time zone object file directory */
#endif /* !defined TZDIR */
#ifndef TZDEFAULT
#define TZDEFAULT "/etc/localtime"
#endif /* !defined TZDEFAULT */
#ifndef TZDEFRULES
#define TZDEFRULES "posixrules"
#endif /* !defined TZDEFRULES */
/*
** Each file begins with. . .
*/
#define TZ_MAGIC "TZif"
struct tzhead {
char tzh_magic[4]; /* TZ_MAGIC */
char tzh_version[1]; /* '\0' or '2' as of 2005 */
char tzh_reserved[15]; /* reserved--must be zero */
char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */
char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */
char tzh_leapcnt[4]; /* coded number of leap seconds */
char tzh_timecnt[4]; /* coded number of transition times */
char tzh_typecnt[4]; /* coded number of local time types */
char tzh_charcnt[4]; /* coded number of abbr. chars */
};
/*
** . . .followed by. . .
**
** tzh_timecnt (char [4])s coded transition times a la time(2)
** tzh_timecnt (unsigned char)s types of local time starting at above
** tzh_typecnt repetitions of
** one (char [4]) coded UTC offset in seconds
** one (unsigned char) used to set tm_isdst
** one (unsigned char) that's an abbreviation list index
** tzh_charcnt (char)s '\0'-terminated zone abbreviations
** tzh_leapcnt repetitions of
** one (char [4]) coded leap second transition times
** one (char [4]) total correction after above
** tzh_ttisstdcnt (char)s indexed by type; if TRUE, transition
** time is standard time, if FALSE,
** transition time is wall clock time
** if absent, transition times are
** assumed to be wall clock time
** tzh_ttisgmtcnt (char)s indexed by type; if TRUE, transition
** time is UTC, if FALSE,
** transition time is local time
** if absent, transition times are
** assumed to be local time
*/
/*
** If tzh_version is '2' or greater, the above is followed by a second instance
** of tzhead and a second instance of the data in which each coded transition
** time uses 8 rather than 4 chars,
** then a POSIX-TZ-environment-variable-style string for use in handling
** instants after the last transition time stored in the file
** (with nothing between the newlines if there is no POSIX representation for
** such instants).
*/
/*
** In the current implementation, "tzset()" refuses to deal with files that
** exceed any of the limits below.
*/
#ifndef TZ_MAX_TIMES
#define TZ_MAX_TIMES 1200
#endif /* !defined TZ_MAX_TIMES */
#ifndef TZ_MAX_TYPES
#ifndef NOSOLAR
#define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */
#endif /* !defined NOSOLAR */
#ifdef NOSOLAR
/*
** Must be at least 14 for Europe/Riga as of Jan 12 1995,
** as noted by Earl Chew.
*/
#define TZ_MAX_TYPES 20 /* Maximum number of local time types */
#endif /* !defined NOSOLAR */
#endif /* !defined TZ_MAX_TYPES */
#ifndef TZ_MAX_CHARS
#define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */
/* (limited by what unsigned chars can hold) */
#endif /* !defined TZ_MAX_CHARS */
#ifndef TZ_MAX_LEAPS
#define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */
#endif /* !defined TZ_MAX_LEAPS */
#define SECSPERMIN 60
#define MINSPERHOUR 60
#define HOURSPERDAY 24
#define DAYSPERWEEK 7
#define DAYSPERNYEAR 365
#define DAYSPERLYEAR 366
#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
#define SECSPERDAY ((long) SECSPERHOUR * HOURSPERDAY)
#define MONSPERYEAR 12
#define TM_SUNDAY 0
#define TM_MONDAY 1
#define TM_TUESDAY 2
#define TM_WEDNESDAY 3
#define TM_THURSDAY 4
#define TM_FRIDAY 5
#define TM_SATURDAY 6
#define TM_JANUARY 0
#define TM_FEBRUARY 1
#define TM_MARCH 2
#define TM_APRIL 3
#define TM_MAY 4
#define TM_JUNE 5
#define TM_JULY 6
#define TM_AUGUST 7
#define TM_SEPTEMBER 8
#define TM_OCTOBER 9
#define TM_NOVEMBER 10
#define TM_DECEMBER 11
#define TM_YEAR_BASE 1900
#define EPOCH_YEAR 1970
#define EPOCH_WDAY TM_THURSDAY
#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
/*
** Since everything in isleap is modulo 400 (or a factor of 400), we know that
** isleap(y) == isleap(y % 400)
** and so
** isleap(a + b) == isleap((a + b) % 400)
** or
** isleap(a + b) == isleap(a % 400 + b % 400)
** This is true even if % means modulo rather than Fortran remainder
** (which is allowed by C89 but not C99).
** We use this to avoid addition overflow problems.
*/
#define isleap_sum(a, b) isleap((a) % 400 + (b) % 400)
#endif /* !defined TZFILE_H */

657
contrib/tzcode/strftime.c Normal file
View File

@ -0,0 +1,657 @@
/* Convert a broken-down timestamp to a string. */
/* Copyright 1989 The Regents of the University of California.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE. */
/*
** Based on the UCB version with the copyright notice appearing above.
**
** This is ANSIish only when "multibyte character == plain character".
*/
#include "private.h"
#include <fcntl.h>
#include <locale.h>
#include <stdio.h>
#ifndef DEPRECATE_TWO_DIGIT_YEARS
# define DEPRECATE_TWO_DIGIT_YEARS false
#endif
struct lc_time_T {
const char * mon[MONSPERYEAR];
const char * month[MONSPERYEAR];
const char * wday[DAYSPERWEEK];
const char * weekday[DAYSPERWEEK];
const char * X_fmt;
const char * x_fmt;
const char * c_fmt;
const char * am;
const char * pm;
const char * date_fmt;
};
static const struct lc_time_T C_time_locale = {
{
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
}, {
"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"
}, {
"Sun", "Mon", "Tue", "Wed",
"Thu", "Fri", "Sat"
}, {
"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"
},
/* X_fmt */
"%H:%M:%S",
/*
** x_fmt
** C99 and later require this format.
** Using just numbers (as here) makes Quakers happier;
** it's also compatible with SVR4.
*/
"%m/%d/%y",
/*
** c_fmt
** C99 and later require this format.
** Previously this code used "%D %X", but we now conform to C99.
** Note that
** "%a %b %d %H:%M:%S %Y"
** is used by Solaris 2.3.
*/
"%a %b %e %T %Y",
/* am */
"AM",
/* pm */
"PM",
/* date_fmt */
"%a %b %e %H:%M:%S %Z %Y"
};
enum warn { IN_NONE, IN_SOME, IN_THIS, IN_ALL };
static char * _add(const char *, char *, const char *);
static char * _conv(int, const char *, char *, const char *);
static char * _fmt(const char *, const struct tm *, char *, const char *,
enum warn *);
static char * _yconv(int, int, bool, bool, char *, char const *);
#ifndef YEAR_2000_NAME
# define YEAR_2000_NAME "CHECK_STRFTIME_FORMATS_FOR_TWO_DIGIT_YEARS"
#endif /* !defined YEAR_2000_NAME */
#if HAVE_STRFTIME_L
size_t
strftime_l(char *s, size_t maxsize, char const *format, struct tm const *t,
ATTRIBUTE_MAYBE_UNUSED locale_t locale)
{
/* Just call strftime, as only the C locale is supported. */
return strftime(s, maxsize, format, t);
}
#endif
size_t
strftime(char *s, size_t maxsize, const char *format, const struct tm *t)
{
char * p;
int saved_errno = errno;
enum warn warn = IN_NONE;
tzset();
p = _fmt(format, t, s, s + maxsize, &warn);
if (!p) {
errno = EOVERFLOW;
return 0;
}
if (DEPRECATE_TWO_DIGIT_YEARS
&& warn != IN_NONE && getenv(YEAR_2000_NAME)) {
fprintf(stderr, "\n");
fprintf(stderr, "strftime format \"%s\" ", format);
fprintf(stderr, "yields only two digits of years in ");
if (warn == IN_SOME)
fprintf(stderr, "some locales");
else if (warn == IN_THIS)
fprintf(stderr, "the current locale");
else fprintf(stderr, "all locales");
fprintf(stderr, "\n");
}
if (p == s + maxsize) {
errno = ERANGE;
return 0;
}
*p = '\0';
errno = saved_errno;
return p - s;
}
static char *
_fmt(const char *format, const struct tm *t, char *pt,
const char *ptlim, enum warn *warnp)
{
struct lc_time_T const *Locale = &C_time_locale;
for ( ; *format; ++format) {
if (*format == '%') {
label:
switch (*++format) {
case '\0':
--format;
break;
case 'A':
pt = _add((t->tm_wday < 0 ||
t->tm_wday >= DAYSPERWEEK) ?
"?" : Locale->weekday[t->tm_wday],
pt, ptlim);
continue;
case 'a':
pt = _add((t->tm_wday < 0 ||
t->tm_wday >= DAYSPERWEEK) ?
"?" : Locale->wday[t->tm_wday],
pt, ptlim);
continue;
case 'B':
pt = _add((t->tm_mon < 0 ||
t->tm_mon >= MONSPERYEAR) ?
"?" : Locale->month[t->tm_mon],
pt, ptlim);
continue;
case 'b':
case 'h':
pt = _add((t->tm_mon < 0 ||
t->tm_mon >= MONSPERYEAR) ?
"?" : Locale->mon[t->tm_mon],
pt, ptlim);
continue;
case 'C':
/*
** %C used to do a...
** _fmt("%a %b %e %X %Y", t);
** ...whereas now POSIX 1003.2 calls for
** something completely different.
** (ado, 1993-05-24)
*/
pt = _yconv(t->tm_year, TM_YEAR_BASE,
true, false, pt, ptlim);
continue;
case 'c':
{
enum warn warn2 = IN_SOME;
pt = _fmt(Locale->c_fmt, t, pt, ptlim, &warn2);
if (warn2 == IN_ALL)
warn2 = IN_THIS;
if (warn2 > *warnp)
*warnp = warn2;
}
continue;
case 'D':
pt = _fmt("%m/%d/%y", t, pt, ptlim, warnp);
continue;
case 'd':
pt = _conv(t->tm_mday, "%02d", pt, ptlim);
continue;
case 'E':
case 'O':
/*
** Locale modifiers of C99 and later.
** The sequences
** %Ec %EC %Ex %EX %Ey %EY
** %Od %oe %OH %OI %Om %OM
** %OS %Ou %OU %OV %Ow %OW %Oy
** are supposed to provide alternative
** representations.
*/
goto label;
case 'e':
pt = _conv(t->tm_mday, "%2d", pt, ptlim);
continue;
case 'F':
pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp);
continue;
case 'H':
pt = _conv(t->tm_hour, "%02d", pt, ptlim);
continue;
case 'I':
pt = _conv((t->tm_hour % 12) ?
(t->tm_hour % 12) : 12,
"%02d", pt, ptlim);
continue;
case 'j':
pt = _conv(t->tm_yday + 1, "%03d", pt, ptlim);
continue;
case 'k':
/*
** This used to be...
** _conv(t->tm_hour % 12 ?
** t->tm_hour % 12 : 12, 2, ' ');
** ...and has been changed to the below to
** match SunOS 4.1.1 and Arnold Robbins'
** strftime version 3.0. That is, "%k" and
** "%l" have been swapped.
** (ado, 1993-05-24)
*/
pt = _conv(t->tm_hour, "%2d", pt, ptlim);
continue;
#ifdef KITCHEN_SINK
case 'K':
/*
** After all this time, still unclaimed!
*/
pt = _add("kitchen sink", pt, ptlim);
continue;
#endif /* defined KITCHEN_SINK */
case 'l':
/*
** This used to be...
** _conv(t->tm_hour, 2, ' ');
** ...and has been changed to the below to
** match SunOS 4.1.1 and Arnold Robbin's
** strftime version 3.0. That is, "%k" and
** "%l" have been swapped.
** (ado, 1993-05-24)
*/
pt = _conv((t->tm_hour % 12) ?
(t->tm_hour % 12) : 12,
"%2d", pt, ptlim);
continue;
case 'M':
pt = _conv(t->tm_min, "%02d", pt, ptlim);
continue;
case 'm':
pt = _conv(t->tm_mon + 1, "%02d", pt, ptlim);
continue;
case 'n':
pt = _add("\n", pt, ptlim);
continue;
case 'p':
pt = _add((t->tm_hour >= (HOURSPERDAY / 2)) ?
Locale->pm :
Locale->am,
pt, ptlim);
continue;
case 'R':
pt = _fmt("%H:%M", t, pt, ptlim, warnp);
continue;
case 'r':
pt = _fmt("%I:%M:%S %p", t, pt, ptlim, warnp);
continue;
case 'S':
pt = _conv(t->tm_sec, "%02d", pt, ptlim);
continue;
case 's':
{
struct tm tm;
char buf[INT_STRLEN_MAXIMUM(
time_t) + 1];
time_t mkt;
tm.tm_sec = t->tm_sec;
tm.tm_min = t->tm_min;
tm.tm_hour = t->tm_hour;
tm.tm_mday = t->tm_mday;
tm.tm_mon = t->tm_mon;
tm.tm_year = t->tm_year;
tm.tm_isdst = t->tm_isdst;
#if defined TM_GMTOFF && ! UNINIT_TRAP
tm.TM_GMTOFF = t->TM_GMTOFF;
#endif
mkt = mktime(&tm);
/* If mktime fails, %s expands to the
value of (time_t) -1 as a failure
marker; this is better in practice
than strftime failing. */
if (TYPE_SIGNED(time_t)) {
intmax_t n = mkt;
sprintf(buf, "%"PRIdMAX, n);
} else {
uintmax_t n = mkt;
sprintf(buf, "%"PRIuMAX, n);
}
pt = _add(buf, pt, ptlim);
}
continue;
case 'T':
pt = _fmt("%H:%M:%S", t, pt, ptlim, warnp);
continue;
case 't':
pt = _add("\t", pt, ptlim);
continue;
case 'U':
pt = _conv((t->tm_yday + DAYSPERWEEK -
t->tm_wday) / DAYSPERWEEK,
"%02d", pt, ptlim);
continue;
case 'u':
/*
** From Arnold Robbins' strftime version 3.0:
** "ISO 8601: Weekday as a decimal number
** [1 (Monday) - 7]"
** (ado, 1993-05-24)
*/
pt = _conv((t->tm_wday == 0) ?
DAYSPERWEEK : t->tm_wday,
"%d", pt, ptlim);
continue;
case 'V': /* ISO 8601 week number */
case 'G': /* ISO 8601 year (four digits) */
case 'g': /* ISO 8601 year (two digits) */
/*
** From Arnold Robbins' strftime version 3.0: "the week number of the
** year (the first Monday as the first day of week 1) as a decimal number
** (01-53)."
** (ado, 1993-05-24)
**
** From <https://www.cl.cam.ac.uk/~mgk25/iso-time.html> by Markus Kuhn:
** "Week 01 of a year is per definition the first week which has the
** Thursday in this year, which is equivalent to the week which contains
** the fourth day of January. In other words, the first week of a new year
** is the week which has the majority of its days in the new year. Week 01
** might also contain days from the previous year and the week before week
** 01 of a year is the last week (52 or 53) of the previous year even if
** it contains days from the new year. A week starts with Monday (day 1)
** and ends with Sunday (day 7). For example, the first week of the year
** 1997 lasts from 1996-12-30 to 1997-01-05..."
** (ado, 1996-01-02)
*/
{
int year;
int base;
int yday;
int wday;
int w;
year = t->tm_year;
base = TM_YEAR_BASE;
yday = t->tm_yday;
wday = t->tm_wday;
for ( ; ; ) {
int len;
int bot;
int top;
len = isleap_sum(year, base) ?
DAYSPERLYEAR :
DAYSPERNYEAR;
/*
** What yday (-3 ... 3) does
** the ISO year begin on?
*/
bot = ((yday + 11 - wday) %
DAYSPERWEEK) - 3;
/*
** What yday does the NEXT
** ISO year begin on?
*/
top = bot -
(len % DAYSPERWEEK);
if (top < -3)
top += DAYSPERWEEK;
top += len;
if (yday >= top) {
++base;
w = 1;
break;
}
if (yday >= bot) {
w = 1 + ((yday - bot) /
DAYSPERWEEK);
break;
}
--base;
yday += isleap_sum(year, base) ?
DAYSPERLYEAR :
DAYSPERNYEAR;
}
#ifdef XPG4_1994_04_09
if ((w == 52 &&
t->tm_mon == TM_JANUARY) ||
(w == 1 &&
t->tm_mon == TM_DECEMBER))
w = 53;
#endif /* defined XPG4_1994_04_09 */
if (*format == 'V')
pt = _conv(w, "%02d",
pt, ptlim);
else if (*format == 'g') {
*warnp = IN_ALL;
pt = _yconv(year, base,
false, true,
pt, ptlim);
} else pt = _yconv(year, base,
true, true,
pt, ptlim);
}
continue;
case 'v':
/*
** From Arnold Robbins' strftime version 3.0:
** "date as dd-bbb-YYYY"
** (ado, 1993-05-24)
*/
pt = _fmt("%e-%b-%Y", t, pt, ptlim, warnp);
continue;
case 'W':
pt = _conv((t->tm_yday + DAYSPERWEEK -
(t->tm_wday ?
(t->tm_wday - 1) :
(DAYSPERWEEK - 1))) / DAYSPERWEEK,
"%02d", pt, ptlim);
continue;
case 'w':
pt = _conv(t->tm_wday, "%d", pt, ptlim);
continue;
case 'X':
pt = _fmt(Locale->X_fmt, t, pt, ptlim, warnp);
continue;
case 'x':
{
enum warn warn2 = IN_SOME;
pt = _fmt(Locale->x_fmt, t, pt, ptlim, &warn2);
if (warn2 == IN_ALL)
warn2 = IN_THIS;
if (warn2 > *warnp)
*warnp = warn2;
}
continue;
case 'y':
*warnp = IN_ALL;
pt = _yconv(t->tm_year, TM_YEAR_BASE,
false, true,
pt, ptlim);
continue;
case 'Y':
pt = _yconv(t->tm_year, TM_YEAR_BASE,
true, true,
pt, ptlim);
continue;
case 'Z':
#ifdef TM_ZONE
pt = _add(t->TM_ZONE, pt, ptlim);
#elif HAVE_TZNAME
if (t->tm_isdst >= 0)
pt = _add(tzname[t->tm_isdst != 0],
pt, ptlim);
#endif
/*
** C99 and later say that %Z must be
** replaced by the empty string if the
** time zone abbreviation is not
** determinable.
*/
continue;
case 'z':
#if defined TM_GMTOFF || USG_COMPAT || ALTZONE
{
long diff;
char const * sign;
bool negative;
# ifdef TM_GMTOFF
diff = t->TM_GMTOFF;
# else
/*
** C99 and later say that the UT offset must
** be computed by looking only at
** tm_isdst. This requirement is
** incorrect, since it means the code
** must rely on magic (in this case
** altzone and timezone), and the
** magic might not have the correct
** offset. Doing things correctly is
** tricky and requires disobeying the standard;
** see GNU C strftime for details.
** For now, punt and conform to the
** standard, even though it's incorrect.
**
** C99 and later say that %z must be replaced by
** the empty string if the time zone is not
** determinable, so output nothing if the
** appropriate variables are not available.
*/
if (t->tm_isdst < 0)
continue;
if (t->tm_isdst == 0)
# if USG_COMPAT
diff = -timezone;
# else
continue;
# endif
else
# if ALTZONE
diff = -altzone;
# else
continue;
# endif
# endif
negative = diff < 0;
if (diff == 0) {
# ifdef TM_ZONE
negative = t->TM_ZONE[0] == '-';
# else
negative = t->tm_isdst < 0;
# if HAVE_TZNAME
if (tzname[t->tm_isdst != 0][0] == '-')
negative = true;
# endif
# endif
}
if (negative) {
sign = "-";
diff = -diff;
} else sign = "+";
pt = _add(sign, pt, ptlim);
diff /= SECSPERMIN;
diff = (diff / MINSPERHOUR) * 100 +
(diff % MINSPERHOUR);
pt = _conv(diff, "%04d", pt, ptlim);
}
#endif
continue;
case '+':
pt = _fmt(Locale->date_fmt, t, pt, ptlim,
warnp);
continue;
case '%':
/*
** X311J/88-090 (4.12.3.5): if conversion char is
** undefined, behavior is undefined. Print out the
** character itself as printf(3) also does.
*/
default:
break;
}
}
if (pt == ptlim)
break;
*pt++ = *format;
}
return pt;
}
static char *
_conv(int n, const char *format, char *pt, const char *ptlim)
{
char buf[INT_STRLEN_MAXIMUM(int) + 1];
sprintf(buf, format, n);
return _add(buf, pt, ptlim);
}
static char *
_add(const char *str, char *pt, const char *ptlim)
{
while (pt < ptlim && (*pt = *str++) != '\0')
++pt;
return pt;
}
/*
** POSIX and the C Standard are unclear or inconsistent about
** what %C and %y do if the year is negative or exceeds 9999.
** Use the convention that %C concatenated with %y yields the
** same output as %Y, and that %Y contains at least 4 bytes,
** with more only if necessary.
*/
static char *
_yconv(int a, int b, bool convert_top, bool convert_yy,
char *pt, const char *ptlim)
{
register int lead;
register int trail;
int DIVISOR = 100;
trail = a % DIVISOR + b % DIVISOR;
lead = a / DIVISOR + b / DIVISOR + trail / DIVISOR;
trail %= DIVISOR;
if (trail < 0 && lead > 0) {
trail += DIVISOR;
--lead;
} else if (lead < 0 && trail > 0) {
trail -= DIVISOR;
++lead;
}
if (convert_top) {
if (lead == 0 && trail < 0)
pt = _add("-0", pt, ptlim);
else pt = _conv(lead, "%02d", pt, ptlim);
}
if (convert_yy)
pt = _conv(((trail < 0) ? -trail : trail), "%02d", pt, ptlim);
return pt;
}

1479
contrib/tzcode/theory.html Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,9 @@
.\" This file is in the public domain, so clarified as of
.\" 1996-06-05 by Arthur David Olson.
.\"
.\" $FreeBSD$
.\"
.Dd September 11, 2005
.Dd December 15, 2022
.Dt TIME2POSIX 3
.Os
.Sh NAME
@ -17,9 +20,10 @@
.Fn posix2time "time_t t"
.Sh DESCRIPTION
.St -p1003.1-88
legislates that a time_t value of
536457599 shall correspond to "Wed Dec 31 23:59:59 GMT 1986."
This effectively implies that POSIX time_t's cannot include leap
requires the time_t value 536457599 to stand for 1986-12-31 23:59:59 UTC.
This effectively implies that POSIX
.Vt time_t
values cannot include leap
seconds and,
therefore,
that the system time must be adjusted as each leap occurs.
@ -28,15 +32,22 @@ If the time package is configured with leap-second support
enabled,
however,
no such adjustment is needed and
time_t values continue to increase over leap events
(as a true `seconds since...' value).
.Vt time_t
values continue to increase over leap events
(as a true
.Dq "seconds since..."
value).
This means that these values will differ from those required by POSIX
by the net number of leap seconds inserted since the Epoch.
.Pp
Typically this is not a problem as the type time_t is intended
Typically this is not a problem as the type
.Vt time_t
is intended
to be
(mostly)
opaque\(emtime_t values should only be obtained-from and
opaque \(em
.Vt time_t
values should only be obtained-from and
passed-to functions such as
.Xr time 3 ,
.Xr localtime 3 ,
@ -46,11 +57,15 @@ and
However,
.St -p1003.1-88
gives an arithmetic
expression for directly computing a time_t value from a given date/time,
expression for directly computing a
.Vt time_t
value from a given date/time,
and the same relationship is assumed by some
(usually older)
applications.
Any programs creating/dissecting time_t's
Any programs creating/dissecting
.Vt time_t
values
using such a relationship will typically not handle intervals
over leap seconds correctly.
.Pp
@ -58,8 +73,12 @@ The
.Fn time2posix
and
.Fn posix2time
functions are provided to address this time_t mismatch by converting
between local time_t values and their POSIX equivalents.
functions are provided to address this
.Vt time_t
mismatch by converting
between local
.Vt time_t
values and their POSIX equivalents.
This is done by accounting for the number of time-base changes that
would have taken place on a POSIX system as leap seconds were inserted
or deleted.
@ -69,21 +88,27 @@ or when communicating with POSIX-compliant systems.
.Pp
The
.Fn time2posix
function is single-valued.
function
is single-valued.
That is,
every local time_t
corresponds to a single POSIX time_t.
every local
.Vt time_t
corresponds to a single POSIX
.Vt time_t .
The
.Fn posix2time
function is less well-behaved:
function
is less well-behaved:
for a positive leap second hit the result is not unique,
and for a negative leap second hit the corresponding
POSIX time_t does not exist so an adjacent value is returned.
POSIX
.Vt time_t
does not exist so an adjacent value is returned.
Both of these are good indicators of the inferiority of the
POSIX representation.
.Pp
The following table summarizes the relationship between time_t
and its conversion to,
The following table summarizes the relationship between a time
T and its conversion to,
and back from,
the POSIX representation over the leap second inserted at the end of June,
1993.
@ -106,8 +131,12 @@ A leap second deletion would look like...
.D1 No "[Note: posix2time(B+1) => A+0 or A+1]"
.Pp
If leap-second support is not enabled,
local time_t's and
POSIX time_t's are equivalent,
local
.Vt time_t
and
POSIX
.Vt time_t
values are equivalent,
and both
.Fn time2posix
and
@ -118,6 +147,3 @@ degenerate to the identity function.
.Xr localtime 3 ,
.Xr mktime 3 ,
.Xr time 3
.\" @(#)time2posix.3 8.2
.\" This file is in the public domain, so clarified as of
.\" 1996-06-05 by Arthur David Olson.

636
contrib/tzcode/tz-art.html Normal file
View File

@ -0,0 +1,636 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Time and the Arts</title>
</head>
<body>
<h1>Time and the Arts</h1>
<h2>Documentaries</h2>
<ul>
<li>
"<a href="https://www.youtube.com/watch?v=84aWtseb2-4">Daylight
Saving Time Explained</a>" (2011; 6:39) lightly covers daylight saving
time's theory, history, pros and cons. Among other things, it explains
Arizona's daylight-saving enclaves quite well.</li>
<li>
"<a href="https://www.youtube.com/watch?v=-5wpm-gesOY">The Problem
with Time &amp; Timezones &ndash; Computerphile</a>" (2013; 10:12) delves
into problems that programmers have with timekeeping.</li>
<li>
"<a href="https://www.rferl.org/a/28375932.html">All The Time In The World:
Explaining The Mysteries Of Time Zones</a>" (2017; 2:15)
briefly says why France has more time zones than Russia.
<li>
"<a href="https://www.youtube.com/watch?v=yRz-Dl60Lfc">Why Denmark is
.17 Seconds Behind The World</a>" (2019; 6:29) explains why Denmark and
the United Kingdom don't exactly follow their own law about civil time.
<li>
"About Time" (1962; 59 minutes) is part of the
Bell Science extravaganza, with Frank Baxter, Richard Deacon, and Les Tremayne.
Its advisor was Richard Feynman, and it was voiced by Mel Blanc.
(<a href="https://www.imdb.com/title/tt0154110/">IMDb entry</a>.)</li>
</ul>
<h2>Movies</h2>
<ul>
<li>
In the 1946 movie <em>A Matter of Life and Death</em>
(U.S. title <em>Stairway to Heaven</em>)
there is a reference to British Double Summer Time.
The time does not play a large part in the plot;
it's just a passing reference to the time when one of the
characters was supposed to have died (but didn't).
(<a href="https://www.imdb.com/title/tt0038733/">IMDb entry.</a>)
(Dave Cantor)
<li>
The 1953 railway comedy movie <em>The Titfield Thunderbolt</em> includes a
play on words on British Double Summer Time. Valentine's wife wants
him to leave the pub and asks him, "Do you know what time it is?"
And he, happy where he is, replies: "Yes, my love. Summer double time."
(<a href="https://www.imdb.com/title/tt0046436/">IMDb entry.</a>)
(Mark Brader, 2009-10-02)
</li>
<li>
The premise of the 1999 caper movie <em>Entrapment</em> involves computers
in an international banking network being shut down briefly at
midnight in each time zone to avoid any problems at the transition
from the year 1999 to 2000 in that zone. (Hmmmm.) If this shutdown
is extended by 10 seconds, it will create a one-time opportunity for
a gigantic computerized theft. To achieve this, at one location the
crooks interfere with the microwave system supplying time signals to
the computer, advancing the time by 0.1 second each minute over the
last hour of 1999. (So this movie teaches us that 0.1 &times; 60 = 10.)
(<a href="https://www.imdb.com/title/tt0137494/">IMDb entry.</a>)
(Mark Brader, 2009-10-02)
</li>
<li>
One mustn't forget the
<a href="https://www.youtube.com/watch?v=k4EUTMPuvHo">trailer</a>
(2014; 2:23) for the movie <em>Daylight Saving</em>.
</li>
</ul>
<h2>TV episodes</h2>
<ul>
<li>
An episode of <em>The Adventures of Superman</em> entitled "The Mysterious
Cube," first aired 1958-02-24, had Superman convincing the controllers
of the Arlington Time Signal to broadcast ahead of actual time;
doing so got a crook trying to be declared dead to
emerge a bit too early from the titular enclosure.
(<a href="https://www.imdb.com/title/tt0506628/">IMDb entry</a>.)
</li>
<li>
"<a href="https://en.wikipedia.org/wiki/The_Chimes_of_Big_Ben">The Chimes
of Big Ben</a>", <em>The Prisoner</em>, episode 2, ITC, 1967-10-06.
Our protagonist tumbles to
the fraudulent nature of a Poland-to-England escape upon hearing "Big
Ben" chiming on Polish local time.
(<a href="https://www.imdb.com/title/tt0679185/">IMDb entry.</a>)
</li>
<li>
"The Susie", <em>Seinfeld</em>, season 8, episode 15, NBC, 1997-02-13.
Kramer decides that daylight saving time
isn't coming fast enough, so he sets his watch ahead an hour.
</li>
<li>
"20 Hours in America", <em>The West Wing</em>, season 4, episodes 1&ndash;2,
2002-09-25, contained a <a
href="https://www.youtube.com/watch?v=-J1NHzQ1sgc">scene</a> that
saw White House staffers stranded in Indiana; they thought they had time to
catch Air Force One but were done in by intra-Indiana local time changes.
</li>
<li>
"In what time zone would you find New York City?" was a $200 question on
the 1999-11-13 United States airing of <em>Who Wants to Be a Millionaire?</em>,
and "In 1883, what industry led the movement to divide the U.S. into four time
zones?" was a $32,000 question on the 2001-05-23 United States airing of
the same show. At this rate, the million-dollar time-zone
question should have been asked 2002-06-04.
</li>
<li>
A private jet's mid-flight change of time zones distorts Alison Dubois'
premonition in the "We Had a Dream" episode of <em>Medium</em>
(originally aired 2007-02-28).
</li>
<li>
A criminal's failure to account for the start of daylight saving is pivotal
in "<a href="https://monk.fandom.com/wiki/Mr._Monk_and_the_Rapper">Mr. Monk
and the Rapper</a>" (first aired 2007-07-20).
</li>
<li>
In the <em>30 Rock</em> episode "Anna Howard Shaw Day"
(first broadcast 2010-02-11),
Jack Donaghy's date realizes that a Geneva-to-New-York business phone call
received in the evening must be fake given the difference in local times.
</li>
<li>
In the "Run by the Monkeys" episode of <em>Da Vinci's Inquest</em>
(first broadcast 2002-11-17),
a witness in a five-year-old fire case realizes they may not have set
their clock back when daylight saving ended on the day of the fire,
introducing the possibility of an hour when arson might have occurred.
</li>
<li>
In "The Todd Couple" episode of <em>Outsourced</em> (first aired 2011-02-10),
Manmeet sets up Valentine's Day teledates for 6:00 and 9:00pm;
since one is with a New Yorker and the other with a San Franciscan,
hilarity ensues.
(Never mind that this should be 7:30am in Mumbai, yet for some reason the show
proceeds as though it's also mid-evening there.)
</li>
<li>
In the "14 Days to Go"/"T Minus..." episode of
<em>You, Me and the Apocalypse</em>
(first aired 2015-11-11 in the UK, 2016-03-10 in the US),
the success of a mission to deal with a comet
hinges on whether or not Russia observes daylight saving time.
(In the US,
the episode first aired in the week before the switch to <abbr>DST</abbr>.)
</li>
<li>
"The Lost Hour", <em>Eerie, Indiana</em>, episode 10, NBC, 1991-12-01.
Despite Indiana's then-lack of <abbr>DST</abbr>,
Marshall changes his clock with unusual consequences.
See "<a
href="https://www.avclub.com/eerie-indiana-was-a-few-dimensions-ahead-of-its-time-1819833380"><em>Eerie,
Indiana</em> was a few dimensions ahead of its time</a>".
</li>
<li>
"Time Tunnel", <em>The Adventures of Pete &amp; Pete</em>, season 2, episode 5,
Nickelodeon, 1994-10-23.
The two Petes travel back in time an hour
on the day that <abbr>DST</abbr> ends.
</li>
<li>
"King-Size Homer", <em>The Simpsons</em>, episode 135, Fox, 1995-11-05.
Homer, working from home, remarks "8:58, first
time I've ever been early for work. Except for all those daylight
savings days. Lousy farmers."
</li>
<li>
<em>Last Week Tonight with John Oliver</em>, season 2, episode 5, 2015-03-08,
asked, "<a href="https://www.youtube.com/watch?v=br0NW9ufUUw">Daylight Saving
Time &ndash; How Is This Still A Thing?</a>"
</li>
<li>
"Tracks", <em>The Good Wife</em>, season 7, episode 12,
CBS, 2016-01-17.
The applicability of a contract hinges on the
time zone associated with a video timestamp.
</li>
<li>
"Justice", <em>Veep</em>, season 6, episode 4, HBO, 2017-05-07.
Jonah's inability to understand <abbr>DST</abbr> ends up impressing a wealthy
backer who sets him up for a 2020 presidential run.
</li>
</ul>
<h2>Books, plays, and magazines</h2>
<ul>
<li>
Jules Verne, <em>Around the World in Eighty Days</em>
(<em>Le tour du monde en quatre-vingts jours</em>), 1873.
Wall-clock time plays a central role in the plot.
European readers of the 1870s clearly held the U.S. press in
deep contempt; the protagonists cross the U.S. without once
reading a paper.
Available versions include
<a href="https://www.gutenberg.org/ebooks/103">an English
translation</a>, and
<a href="https://fourmilab.ch/etexts/www/tdm80j">the original French</a>
"with illustrations from the original 1873 French-language edition".
</li>
<li>
Nick Enright, <em>Daylight Saving</em>, 1989.
A fast-paced comedy about love and loneliness as the clocks turn back.
</li>
<li>
Umberto Eco,
<a href="https://en.wikipedia.org/wiki/The_Island_of_the_Day_Before"><em>The
Island of the Day Before</em></a>
(<em>L'isola del giorno prima</em>), 1994.
"...the story of a 17th century Italian nobleman trapped near an island
on the International Date Line. Time and time zones play an integral
part in the novel." (Paul Eggert, 2006-04-22)
</li>
<li>
John Dunning, <a
href="https://www.simonandschuster.com/books/Two-OClock-Eastern-Wartime/John-Dunning/9781439171530"><em>Two
O'Clock, Eastern Wartime</em></a>, 2001.
Mystery, history, daylight saving time, and old-time radio.
</li>
<li>
Surrealist artist Guy Billout's work "Date Line" appeared on page 103
of the 1999-11 <em>Atlantic Monthly</em>.
</li>
<li>
"Gloom, Gloom, Go Away" by Walter Kirn appeared on page 106 of <em>Time</em>
magazine's 2002-11-11 issue; among other things, it proposed
year-round <abbr>DST</abbr> as a way of lessening wintertime despair.
</li>
</ul>
<h2>Music</h2>
<p>
Data on recordings of "Save That Time," Russ Long, Serrob Publishing, BMI:</p>
<table>
<tr><td>Artist</td><td>Karrin Allyson</td></tr>
<tr><td>CD</td><td>I Didn't Know About You</td></tr>
<tr><td>Copyright Date</td><td>1993</td></tr>
<tr><td>Label</td><td>Concord Jazz, Inc.</td></tr>
<tr><td>ID</td><td>CCD-4543</td></tr>
<tr><td>Track Time</td><td>3:44</td></tr>
<tr><td>Personnel</td><td>Karrin Allyson, vocal;
Russ Long, piano;
Gerald Spaits, bass;
Todd Strait, drums</td></tr>
<tr><td>Notes</td><td>CD notes "additional lyric by Karrin Allyson;
arranged by Russ Long and Karrin Allyson"</td></tr>
<tr><td>ADO Rating</td><td>1 star</td></tr>
<tr><td><a href="https://www.allmusic.com/album/i-didnt-know-about-you-mw0000618657">AMG Rating</a></td><td>4 stars</td></tr>
<tr><td>Penguin Rating</td><td>3.5 stars</td></tr>
<tr><td>&nbsp;</td><td></td></tr>
<tr><td>Artist</td><td>Kevin Mahogany</td></tr>
<tr><td>CD</td><td>Double Rainbow</td></tr>
<tr><td>Copyright Date</td><td>1993</td></tr>
<tr><td>Label</td><td>Enja Records</td></tr>
<tr><td>ID</td><td>ENJ-7097 2</td></tr>
<tr><td>Track Time</td><td>6:27</td></tr>
<tr><td>Personnel</td><td>Kevin Mahogany, vocal;
Kenny Barron, piano;
Ray Drummond, bass;
Ralph Moore, tenor saxophone;
Lewis Nash, drums</td></tr>
<tr><td>ADO Rating</td><td>1.5 stars</td></tr>
<tr><td><a href="https://www.allmusic.com/album/double-rainbow-mw0000620371">AMG Rating</a></td><td>3 stars</td></tr>
<tr><td>Penguin Rating</td><td>3 stars</td></tr>
<tr><td>&nbsp;</td><td></td></tr>
<tr><td>Artist</td><td>Joe Williams</td></tr>
<tr><td>CD</td><td>Here's to Life</td></tr>
<tr><td>Copyright Date</td><td>1994</td></tr>
<tr><td>Label</td><td>Telarc International Corporation</td></tr>
<tr><td>ID</td><td>CD-83357</td></tr>
<tr><td>Track Time</td><td>3:58</td></tr>
<tr><td>Personnel</td><td>Joe Williams, vocal
The Robert Farnon [39 piece] Orchestra</td></tr>
<tr><td>Notes</td><td>This CD is also available as part of a 3-CD package from
Telarc, "Triple Play" (CD-83461)</td></tr>
<tr><td>ADO Rating</td><td>black dot</td></tr>
<tr><td><a href="https://www.allmusic.com/album/heres-to-life-mw0000623648">AMG Rating</a></td><td>2 stars</td></tr>
<tr><td>Penguin Rating</td><td>3 stars</td></tr>
<tr><td>&nbsp;</td><td></td></tr>
<tr><td>Artist</td><td>Charles Fambrough</td></tr>
<tr><td>CD</td><td>Keeper of the Spirit</td></tr>
<tr><td>Copyright Date</td><td>1995</td></tr>
<tr><td>Label</td><td>AudioQuest Music</td></tr>
<tr><td>ID</td><td>AQ-CD1033</td></tr>
<tr><td>Track Time</td><td>7:07</td></tr>
<tr><td>Personnel</td><td>Charles Fambrough, bass;
Joel Levine, tenor recorder;
Edward Simon, piano;
Lenny White, drums;
Marion Simon, percussion</td></tr>
<tr><td>ADO Rating</td><td>2 stars</td></tr>
<tr><td><a href="https://www.allmusic.com/album/keeper-of-the-spirit-mw0000176559">AMG Rating</a></td><td>unrated</td></tr>
<tr><td>Penguin Rating</td><td>3 stars</td></tr>
</table>
<hr>
<p>Also of note:</p>
<table>
<tr><td>Artist</td><td>Holly Cole Trio</td></tr>
<tr><td>CD</td><td>Blame It On My Youth</td></tr>
<tr><td>Copyright Date</td><td>1992</td></tr>
<tr><td>Label</td><td>Manhattan</td></tr>
<tr><td>ID</td><td>CDP 7 97349 2</td></tr>
<tr><td>Total Time</td><td>37:45</td></tr>
<tr><td>Personnel</td><td>Holly Cole, voice;
Aaron Davis, piano;
David Piltch, string bass</td></tr>
<tr><td>Notes</td><td>Lyrical reference to "Eastern Standard Time" in
Tom Waits' "Purple Avenue"</td></tr>
<tr><td>ADO Rating</td><td>2.5 stars</td></tr>
<tr><td><a href="https://www.allmusic.com/album/blame-it-on-my-youth-mw0000274303">AMG Rating</a></td><td>3 stars</td></tr>
<tr><td>Penguin Rating</td><td>unrated</td></tr>
<tr><td>&nbsp;</td><td></td></tr>
<tr><td>Artist</td><td>Milt Hinton</td></tr>
<tr><td>CD</td><td>Old Man Time</td></tr>
<tr><td>Copyright Date</td><td>1990</td></tr>
<tr><td>Label</td><td>Chiaroscuro</td></tr>
<tr><td>ID</td><td>CR(D) 310</td></tr>
<tr><td>Total Time</td><td>149:38 (two CDs)</td></tr>
<tr><td>Personnel</td><td>Milt Hinton, bass;
Doc Cheatham, Dizzy Gillespie, Clark Terry, trumpet;
Al Grey, trombone;
Eddie Barefield, Joe Camel (Flip Phillips), Buddy Tate,
clarinet and saxophone;
John Bunch, Red Richards, Norman Simmons, Derek Smith,
Ralph Sutton, piano;
Danny Barker, Al Casey, guitar;
Gus Johnson, Gerryck King, Bob Rosengarden, Jackie Williams,
drums;
Lionel Hampton, vibraphone;
Cab Calloway, Joe Williams, vocal;
Buck Clayton, arrangements</td></tr>
<tr><td>Notes</td><td>tunes include Old Man Time, Time After Time,
Sometimes I'm Happy,
A Hot Time in the Old Town Tonight,
Four or Five Times, Now's the Time,
Time on My Hands, This Time It's Us,
and Good Time Charlie.
<a href="http://www.chiaroscurojazz.com/album.php?C=310">Album info</a>
is available.</td></tr>
<tr><td>ADO Rating</td><td>3 stars</td></tr>
<tr><td><a href="https://www.allmusic.com/album/old-man-time-mw0000269353">AMG Rating</a></td><td>4.5 stars</td></tr>
<tr><td>Penguin Rating</td><td>3 stars</td></tr>
<tr><td>&nbsp;</td><td></td></tr>
<tr><td>Artist</td><td>Alan Broadbent</td></tr>
<tr><td>CD</td><td>Pacific Standard Time</td></tr>
<tr><td>Copyright Date</td><td>1995</td></tr>
<tr><td>Label</td><td>Concord Jazz, Inc.</td></tr>
<tr><td>ID</td><td>CCD-4664</td></tr>
<tr><td>Total Time</td><td>62:42</td></tr>
<tr><td>Personnel</td><td>Alan Broadbent, piano;
Putter Smith, Bass;
Frank Gibson, Jr., drums</td></tr>
<tr><td>Notes</td><td>The CD cover features an analemma for equation-of-time fans</td></tr>
<tr><td>ADO Rating</td><td>1 star</td></tr>
<tr><td><a href="https://www.allmusic.com/album/pacific-standard-time-mw0000645433">AMG Rating</a></td><td>4 stars</td></tr>
<tr><td>Penguin Rating</td><td>3.5 stars</td></tr>
<tr><td>&nbsp;</td><td></td></tr>
<tr><td>Artist</td><td>Anthony Braxton/Richard Teitelbaum</td></tr>
<tr><td>CD</td><td>Silence/Time Zones</td></tr>
<tr><td>Copyright Date</td><td>1996</td></tr>
<tr><td>Label</td><td>Black Lion</td></tr>
<tr><td>ID</td><td>BLCD 760221</td></tr>
<tr><td>Total Time</td><td>72:58</td></tr>
<tr><td>Personnel</td><td>Anthony Braxton, sopranino and alto saxophones,
contrebasse clarinet, miscellaneous instruments;
Leo Smith, trumpet and miscellaneous instruments;
Leroy Jenkins, violin and miscellaneous instruments;
Richard Teitelbaum, modular moog and micromoog synthesizer</td></tr>
<tr><td>ADO Rating</td><td>black dot</td></tr>
<tr><td><a href="https://www.allmusic.com/album/silence-time-zones-mw0000595735">AMG Rating</a></td><td>4 stars</td></tr>
<tr><td>&nbsp;</td><td></td></tr>
<tr><td>Artist</td><td>Charles Gayle</td></tr>
<tr><td>CD</td><td>Time Zones</td></tr>
<tr><td>Copyright Date</td><td>2006</td></tr>
<tr><td>Label</td><td>Tompkins Square</td></tr>
<tr><td>ID</td><td>TSQ2839</td></tr>
<tr><td>Total Time</td><td>49:06</td></tr>
<tr><td>Personnel</td><td>Charles Gayle, piano</td></tr>
<tr><td>ADO Rating</td><td>1 star</td></tr>
<tr><td><a href="https://www.allmusic.com/album/time-zones-mw0000349642">AMG Rating</a></td><td>4.5 stars</td></tr>
<tr><td>&nbsp;</td><td></td></tr>
<tr><td>Artist</td><td>The Get Up Kids</td></tr>
<tr><td>CD</td><td>Eudora</td></tr>
<tr><td>Copyright Date</td><td>2001</td></tr>
<tr><td>Label</td><td>Vagrant</td></tr>
<tr><td>ID</td><td>357</td></tr>
<tr><td>Total Time</td><td>65:12</td></tr>
<tr><td>Notes</td><td>Includes the song "Central Standard Time." Thanks to Colin Bowern for this information.</td></tr>
<tr><td><a href="https://www.allmusic.com/album/eudora-mw0000592063">AMG Rating</a></td><td>2.5 stars</td></tr>
<tr><td>&nbsp;</td><td></td></tr>
<tr><td>Artist</td><td>Coldplay</td></tr>
<tr><td>Song</td><td>Clocks</td></tr>
<tr><td>Copyright Date</td><td>2003</td></tr>
<tr><td>Label</td><td>Capitol Records</td></tr>
<tr><td>ID</td><td>52608</td></tr>
<tr><td>Total Time</td><td>4:13</td></tr>
<tr><td>Notes</td><td>Won the 2004 Record of the Year honor at the
Grammy Awards. Co-written and performed by Chris Martin,
great-great-grandson of <abbr>DST</abbr> inventor William Willett.
The song's first line is "Lights go out and I can't be saved".</td></tr>
<tr><td>&nbsp;</td><td></td></tr>
<tr><td>Artist</td><td>Jaime Guevara</td></tr>
<tr><td>Song</td><td><a
href="https://www.youtube.com/watch?v=ZfN4Fe_A50U">Qu&eacute;
hora es</a></td></tr>
<tr><td>Date</td><td>1993</td></tr>
<tr><td>Total Time</td><td>3:04</td></tr>
<tr><td>Notes</td><td>The song protested "Sixto Hour" in Ecuador
(1992&ndash;3). Its lyrics include "Amanec&iacute;a en mitad de la noche, los
guaguas iban a clase sin sol" ("It was dawning in the middle of the
night, the buses went to class without sun").
<tr><td>&nbsp;</td><td></td></tr>
<tr><td>Artist</td><td>Irving Kahal and Harry Richman</td></tr>
<tr><td>Song</td><td>There Ought to be a Moonlight Saving Time</td></tr>
<tr><td>Copyright Date</td><td>1931</td>
<tr><td>Notes</td><td>This musical standard was a No. 1 hit for Guy Lombardo
in 1931, and was also performed by Maurice Chevalier, Blossom Dearie
and many others. The phrase "Moonlight saving time" also appears in
the 1995 country song "Not Enough Hours in the Night" written by Aaron
Barker, Kim Williams and Rob Harbin and performed by Doug
Supernaw.</td></tr>
<tr><td>&nbsp;</td><td></td></tr>
<tr><td>Artist</td><td>The Microscopic Septet</td></tr>
<tr><td>CD</td><td>Lobster Leaps In</td></tr>
<tr><td>Copyright Date</td><td>2008</td></tr>
<tr><td>Label</td><td>Cuneiform</td></tr>
<tr><td>ID</td><td>272</td></tr>
<tr><td>Total Time</td><td>73:05</td></tr>
<tr><td>Notes</td><td>Includes the song "Twilight Time Zone."</td></tr>
<tr><td><a href="https://www.allmusic.com/album/lobster-leaps-in-mw0000794929">AMG Rating</a></td><td>3.5 stars</td></tr>
<tr><td>ADO Rating</td><td>2 stars</td></tr>
<tr><td>&nbsp;</td><td></td></tr>
<tr><td>Artist</td><td>Bob Dylan</td></tr>
<tr><td>CD</td><td>The Times They Are a-Changin'</td></tr>
<tr><td>Copyright Date</td><td>1964</td></tr>
<tr><td>Label</td><td>Columbia</td></tr>
<tr><td>ID</td><td>CK-8905</td></tr>
<tr><td>Total Time</td><td>45:36</td></tr>
<tr><td><a href="https://www.allmusic.com/album/the-times-they-a-changin-mw0000202344">AMG Rating</a></td><td>4.5 stars</td></tr>
<tr><td>ADO Rating</td><td>1.5 stars</td></tr>
<tr><td>Notes<td>The title song is also available on "Bob Dylan's Greatest Hits" and "The Essential Bob Dylan."</td></tr>
<tr><td>&nbsp;</td><td></td></tr>
<tr><td>Artist</td><td>Luciana Souza</td></tr>
<tr><td>CD</td><td>Tide</td></tr>
<tr><td>Copyright Date</td><td>2009</td></tr>
<tr><td>Label</td><td>Universal Jazz France</td></tr>
<tr><td>ID</td><td>B0012688-02</td></tr>
<tr><td>Total Time</td><td>42:31</td></tr>
<tr><td><a href="https://www.allmusic.com/album/tide-mw0000815692">AMG Rating</a></td><td>3.5 stars</td></tr>
<tr><td>ADO Rating</td><td>2.5 stars</td></tr>
<tr><td>Notes<td>Includes the song "Fire and Wood" with the lyric
"The clocks were turned back you remember/Think it's still November."
</td></tr>
<tr><td>&nbsp;</td><td></td></tr>
<tr><td>Artist</td><td>Ken Nordine</td></tr>
<tr><td>CD</td><td>You're Getting Better: The Word Jazz Dot Masters</td></tr>
<tr><td>Copyright Date</td><td>2005</td></tr>
<tr><td>Label</td><td>Geffen</td></tr>
<tr><td>ID</td><td>B0005171-02</td></tr>
<tr><td>Total Time</td><td>156:22</td></tr>
<tr><td>ADO Rating</td><td>1 star</td></tr>
<tr><td><a href="https://www.allmusic.com/album/youre-getting-better-the-word-jazz-dot-masters-mw0000736197">AMG Rating</a></td><td>4.5 stars</td></tr>
<tr><td>Notes</td><td>Includes the piece "What Time Is It"
("He knew what time it was everywhere...that counted").</td></tr>
<tr><td>&nbsp;</td><td></td></tr>
<tr><td>Artist</td><td>Chicago</td></tr>
<tr><td>CD</td><td>Chicago Transit Authority</td></tr>
<tr><td>Copyright Date</td><td>1969</td></tr>
<tr><td>Label</td><td>Columbia</td></tr>
<tr><td>ID</td><td>64409</td></tr>
<tr><td>Total Time</td><td>1:16:20</td></tr>
<tr><td><a href="https://www.allmusic.com/album/chicago-transit-authority-mw0000189364">AMG Rating</a></td><td>4 stars</td></tr>
<tr><td>Notes</td><td>Includes the song "Does Anybody Really Know What Time It Is?"</td></tr>
</table>
<h2>Comics</h2>
<ul>
<li>
The webcomic <em>xkcd</em> has the strip
"<a href="https://xkcd.com/673/">The Sun</a>" (2009-12-09) and the panels
"<a href="https://xkcd.com/1017/">Backward in Time</a>" (2012-02-14),
"<a href="https://xkcd.com/1061/">EST</a>" (2012-05-28),
"<a href="https://xkcd.com/1179/">ISO 8601</a>" (2013-02-27),
"<a href="https://xkcd.com/1335/">Now</a>" (2014-02-26),
"<a href="https://xkcd.com/1655/">Doomsday Clock</a>" (2016-03-14),
"<a href="https://xkcd.com/1799/">Bad Map Projection: Time Zones</a>"
(2017-02-15),
"<a href="https://xkcd.com/1883/">Supervillain Plan</a>" (2017-08-30),
"<a href="https://xkcd.com/2050/">6/6 Time</a>" (2018-09-24),
and "<a href="https://xkcd.com/2266/">Leap Smearing</a>" (2020-02-10).
The related book <em>What If?</em> has an entry
"<a href="https://what-if.xkcd.com/26/">Leap Seconds</a>" (2012-12-31).
</li>
<li>
Pig kills time in <a
href="https://www.gocomics.com/pearlsbeforeswine/2016/11/06"><em>Pearls
Before Swine</em> (2016-11-06)</a>.
</li>
<li>
Stonehenge is abandoned in <a
href="https://www.gocomics.com/nonsequitur/2017/03/12"><em>Non Sequitur</em>
(2017-03-12)</a>.
<li>
The boss freaks out in <a
href="https://dilbert.com/strip/1998-03-14"><em>Dilbert</em> (1998-03-14)</a>.
</li>
<li>
Peppermint Patty: "What if the world comes to an end tonight, Marcie?"
<br>
Marcie: "I promise there'll be a tomorrow, sir ... in fact,
it's already tomorrow in Australia!"
<br>
(Charles M. Schulz, <a href="https://www.gocomics.com/peanuts/1980/06/13"><em>Peanuts</em>, 1980-06-13</a>)
</li>
</ul>
<h2>Jokes</h2>
<ul>
<li>
The idea behind daylight saving time was first proposed as a joke by
Benjamin Franklin. To enforce it, he suggested, "Every
morning, as soon as the sun rises, let all the bells in every church
be set ringing; and if that is not sufficient, let cannon be fired in
every street, to wake the sluggards effectually, and make them open
their eyes to see their true interest. All the difficulty will be in
the first two or three days: after which the reformation will be as
natural and easy as the present irregularity; for, <em>ce n'est que le
premier pas qui co&ucirc;te</em>."
<a href="http://www.webexhibits.org/daylightsaving/franklin3.html">Franklin's
joke</a> was first published on 1784-04-26 by the
<em>Journal de Paris</em> as <a
href="https://en.wikipedia.org/wiki/File:Franklin-Benjamin-Journal-de-Paris-1784.jpg">an
anonymous letter translated into French</a>.
</li>
<li>
"We've been using the five-cent nickel in this country since 1492.
Now that's pretty near 100 years, daylight saving."
(Groucho Marx as Captain Spaulding in <em>Animal Crackers</em>, 1930,
as noted by Will Fitzgerald)
</li>
<li>
BRADY. ...[Bishop Usher] determined that the Lord began the Creation
on the 23rd of October in the Year 4,004 B.C. at &ndash; uh, 9 A.M.!
<br>
DRUMMOND. That Eastern Standard Time? (<em>Laughter.</em>) Or Rocky Mountain
Time? (<em>More laughter.</em>) It wasn't daylight-saving time, was it? Because
the Lord didn't make the sun until the fourth day!
<br>
(From the play <em>Inherit the Wind</em> by Jerome Lawrence and Robert E. Lee,
filmed in 1960 with Spencer Tracy as Drummond and Fredric March as
Brady, and several other times. Thanks to Mark Brader.)
</li>
<li>
"Good news."
"What did they do? Extend Daylight Saving Time year round?"
(Professional tanner George Hamilton, in dialog from a
May, 1999 episode of the syndicated television series <em>Baywatch</em>)
</li>
<li>
"A fundamental belief held by Americans is that if you are on land, you
cannot be killed by a fish...So most Americans remain on land, believing
they're safe. Unfortunately, this belief &ndash; like so many myths, such as that
there's a reason for 'Daylight Saving Time' &ndash; is false."
(Dave Barry column, 2000-07-02)
</li>
<li>
"I once had sex for an hour and five minutes, but that was on the day
when you turn the clocks ahead."
(Garry Shandling, 52nd Annual Emmys, 2000-09-10)
</li>
<li>
"Would it impress you if I told you I invented Daylight Savings Time?"
("Sahjhan" to "Lilah" in dialog from the "Loyalty" episode of <em>Angel</em>,
originally aired 2002-02-25)
</li>
<li>
"I thought you said Tulsa was a three-hour flight."
"Well, you're forgetting about the time difference."
("Joey" and "Chandler" in dialog from the episode of <em>Friends</em>
entitled "The One With Rachel's Phone Number," originally aired 2002-12-05)
</li>
<li>
"Is that a pertinent fact,
or are you just trying to dazzle me with your command of time zones?"
(Kelsey Grammer as "Frasier Crane" to "Roz" from the episode of <em>Frasier</em>
entitled "The Kid," originally aired 1997-11-04)
</li>
<li>
"I put myself and my staff through this crazy, huge ordeal, all because
I refused to go on at midnight, okay? And so I work, you know, and
then I get this job at eleven, supposed to be a big deal. Then
yesterday daylight [saving] time ended. Right now it's basically
midnight." (Conan O'Brien on the 2010-11-08 premiere of <em>Conan</em>.)
</li>
<li>
"The best method, I told folks, was to hang a large clock high on a
barn wall where all the cows could see it. If you have Holsteins, you
will need to use an analog clock." (Jerry Nelson, <a
href="http://www.agriculture.com/family/farm-humor/how-to-adjust-dairy-cows-to-daylight-savings-time">How
to adjust dairy cows to daylight saving time</a>", <em>Successful Farming</em>,
2017-10-09.)
</li>
<li>
"And now, driving to California, I find that I must enter a password
in order to change the time zone on my laptop clock. Evidently,
someone is out to mess up my schedule and my clock must be secured."
(Garrison Keillor,
"<a href="http://www.garrisonkeillor.com/weve-never-been-here-before/">We've
never been here before</a>", 2017-08-22)
</li>
<li>
"Well, in my time zone that's all the time I have,
but maybe in your time zone I haven't finished yet. So stay tuned!"
(Goldie Hawn, <em>Rowan &amp; Martin's Laugh-In</em> No. 65, 1970-03-09)
</li>
</ul>
<h2>See also</h2>
<ul>
<li><a href="tz-link.html">Time Zone and Daylight Saving
Time Data</a></li>
</ul>
<hr>
<address>
This web page is in the public domain, so clarified as of
2009-05-17 by Arthur David Olson.
<br>
Please send corrections to this web page to the
<a href="mailto:tz@iana.org">time zone mailing list</a>.
</address>
</body>
</html>

View File

@ -0,0 +1,719 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>How to Read the tz Database</title>
<meta charset="UTF-8">
<style>
pre {margin-left: 2em; white-space: pre-wrap;}
pre.td {margin-left: 0;}
td {text-align: center;}
table {border: 1px outset;}
th, td {border: 1px inset;}
table.rule {border: none; margin: auto;}
td.footnote {text-align: left;}
</style>
</head>
<body>
<h2>How to Read the <a href="https://en.wikipedia.org/wiki/Tz_database">tz
Database</a> Source Files</h2>
<h3>by Bill Seymour</h3>
<p>This guide uses the <code>America/Chicago</code> and
<code>Pacific/Honolulu</code> zones as examples of how to infer
times of day from the <a href="tz-link.html">tz database</a>
source files. It might be helpful, but not absolutely necessary,
for the reader to have already downloaded the
latest release of the database and become familiar with the basic layout
of the data files. The format is explained in the &ldquo;man
page&rdquo; for the zic compiler, <code>zic.8.txt</code>, in
the <code>code</code> subdirectory.
Although this guide covers many of the common cases, it is not a
complete summary of what zic accepts; the man page is the
authoritative reference.</p>
<p>We&rsquo;ll begin by talking about the rules for changing between standard
and daylight saving time since we&rsquo;ll need that information when we talk
about the zones.</p>
<p>First, let&rsquo;s consider the special daylight saving time rules
for Chicago (from the <code>northamerica</code> file in
the <code>data</code> subdirectory):</p>
<table>
<tr>
<th colspan="6">From the Source File</th>
</tr>
<tr>
<td colspan="6">
<table class="rule">
<tr><td style="border:none;text-align:left">
<pre class="td">
#Rule NAME FROM TO - IN ON AT SAVE LETTER
Rule Chicago 1920 only - Jun 13 2:00 1:00 D
Rule Chicago 1920 1921 - Oct lastSun 2:00 0 S
Rule Chicago 1921 only - Mar lastSun 2:00 1:00 D
Rule Chicago 1922 1966 - Apr lastSun 2:00 1:00 D
Rule Chicago 1922 1954 - Sep lastSun 2:00 0 S
Rule Chicago 1955 1966 - Oct lastSun 2:00 0 S
</pre>
</td></tr></table></td>
</tr>
<tr>
<th colspan="6">Reformatted a Bit</th>
</tr>
<tr>
<th>From</th>
<th>To</th>
<th colspan="2">On</th>
<th>At</th>
<th>Action</th>
</tr>
<tr>
<td colspan="2">1920 only</td>
<td colspan="2">June 13<small><sup>th</sup></small></td>
<td rowspan="6">02:00 local</td>
<td>go to daylight saving time</td>
</tr>
<tr>
<td>1920</td>
<td>1921</td>
<td rowspan="5">last Sunday</td>
<td>in October</td>
<td>return to standard time</td>
</tr>
<tr>
<td colspan="2">1921 only</td>
<td>in March</td>
<td rowspan="2">go to daylight saving time</td>
</tr>
<tr>
<td rowspan="2">1922</td>
<td>1966</td>
<td>in April</td>
</tr>
<tr>
<td>1954</td>
<td>in September</td>
<td rowspan="2">return to standard time</td>
</tr>
<tr>
<td>1955</td>
<td>1966</td>
<td>in October</td>
</tr>
</table>
<p>The <code>FROM</code> and <code>TO</code> columns, respectively, specify the
first and last calendar years defining a contiguous range over which a specific
Rule line is to apply. The keyword <code>only</code> can be used in the
<code>TO</code> field to repeat the value of the <code>FROM</code> field in the
event that a rule should only apply to a single year. Often, the keyword
<code>max</code> is used to extend a rule&rsquo;s application into the
indefinite future; it is a platform-agnostic stand-in for the largest
representable year.
<p>The next column, <code>-</code>, is reserved; for compatibility with earlier
releases, it always contains a hyphen, which acts as a kind of null value.
Prior to the 2020b release, it was called the <code>TYPE</code> field, though
it had not been used in the main data since the 2000e release.
An obsolescent supplementary file used the
field as a proof-of-concept to allow <code>zic</code> to apply a given Rule
line only to certain &ldquo;types&rdquo; of years within the specified range as
dictated by the output of a separate script, such as: only years which would
have a US presidential election, or only years which wouldn&rsquo;t.
<p>The <code>SAVE</code> column contains the local (wall clock) offset from
local standard time.
This is usually either zero for standard time or one hour for daylight
saving time; but there&rsquo;s no reason, in principle, why it can&rsquo;t
take on other values.
<p>The <code>LETTER</code> (sometimes called <code>LETTER/S</code>)
column can contain a variable
part of the usual abbreviation of the time zone&rsquo;s name, or it can just
be a hyphen if there&rsquo;s no variable part. For example, the abbreviation
used in the central time zone will be either &ldquo;CST&rdquo; or
&ldquo;CDT&rdquo;. The variable part is &lsquo;S&rsquo; or &lsquo;D&rsquo;;
and, sure enough, that&rsquo;s just what we find in
the <code>LETTER</code> column
in the <code>Chicago</code> rules. More about this when we talk about
&ldquo;Zone&rdquo; lines.
<p>One important thing to notice is that &ldquo;Rule&rdquo; lines
want at once to be both <i>transitions</i> and <i>steady states</i>:
<ul>
<li>On the one hand, they represent transitions between standard and
daylight saving time; and any number of Rule lines can be in effect
during a given period (which will always be a non-empty set of
contiguous calendar years).</li>
<li>On the other hand, the <code>SAVE</code> and <code>LETTER</code>
columns contain state that exists between transitions. More about this
when we talk about the US rules.</li>
</ul>
<p>In the example above, the transition to daylight saving time
happened on the 13<small><sup>th</sup></small> of June in 1920, and on
the last Sunday in March in 1921; but the return to standard time
happened on the last Sunday in October in both of those
years. Similarly, the rule for changing to daylight saving time was
the same from 1922 to 1966; but the rule for returning to standard
time changed in 1955. Got it?</p>
<p>OK, now for the somewhat more interesting &ldquo;US&rdquo; rules:</p>
<table>
<tr>
<th colspan="6">From the Source File</th>
</tr>
<tr>
<td colspan="6">
<table class="rule">
<tr><td style="border:none;text-align:left">
<pre class="td">
#Rule NAME FROM TO - IN ON AT SAVE LETTER/S
Rule US 1918 1919 - Mar lastSun 2:00 1:00 D
Rule US 1918 1919 - Oct lastSun 2:00 0 S
Rule US 1942 only - Feb 9 2:00 1:00 W # War
Rule US 1945 only - Aug 14 23:00u 1:00 P # Peace
Rule US 1945 only - Sep 30 2:00 0 S
Rule US 1967 2006 - Oct lastSun 2:00 0 S
Rule US 1967 1973 - Apr lastSun 2:00 1:00 D
Rule US 1974 only - Jan 6 2:00 1:00 D
Rule US 1975 only - Feb 23 2:00 1:00 D
Rule US 1976 1986 - Apr lastSun 2:00 1:00 D
Rule US 1987 2006 - Apr Sun&gt;=1 2:00 1:00 D
Rule US 2007 max - Mar Sun&gt;=8 2:00 1:00 D
Rule US 2007 max - Nov Sun&gt;=1 2:00 0 S
</pre>
</td></tr></table></td>
</tr>
<tr>
<th colspan="6">Reformatted a Bit</th>
</tr>
<tr>
<th>From</th>
<th>To</th>
<th colspan="2">On</th>
<th>At</th>
<th>Action</th>
</tr>
<tr>
<td rowspan="2">1918</td>
<td rowspan="2">1919</td>
<td rowspan="2">last Sunday</td>
<td>in March</td>
<td rowspan="3">02:00 local</td>
<td>go to daylight saving time</td>
</tr>
<tr>
<td>in October</td>
<td>return to standard time</td>
</tr>
<tr>
<td colspan="2">1942 only</td>
<td colspan="2">February 9<small><sup>th</sup></small></td>
<td>go to &ldquo;war time&rdquo;</td>
</tr>
<tr>
<td colspan="2" rowspan="2">1945 only</td>
<td colspan="2">August 14<small><sup>th</sup></small></td>
<td>23:00 <a href="https://en.wikipedia.org/wiki/Universal_Time">UT</a></td>
<td>
rename &ldquo;war time&rdquo; to &ldquo;peace<br>time;&rdquo;
clocks don&rsquo;t change
</td>
</tr>
<tr>
<td colspan="2">September 30<small><sup>th</sup></small></td>
<td rowspan="9">02:00 local</td>
<td rowspan="2">return to standard time</td>
</tr>
<tr>
<td rowspan="2">1967</td>
<td>2006</td>
<td rowspan="2">last Sunday</td>
<td>in October</td>
</tr>
<tr>
<td>1973</td>
<td>in April</td>
<td rowspan="6">go to daylight saving time</td>
</tr>
<tr>
<td colspan="2">1974 only</td>
<td colspan="2">January 6<small><sup>th</sup></small></td>
</tr>
<tr>
<td colspan="2">1975 only</td>
<td colspan="2">February 23<small><sup>rd</sup></small></td>
</tr>
<tr>
<td>1976</td>
<td>1986</td>
<td>last Sunday</td>
<td rowspan="2">in April</td>
</tr>
<tr>
<td>1987</td>
<td>2006</td>
<td>first Sunday</td>
</tr>
<tr>
<td rowspan="2">2007</td>
<td rowspan="2">present</td>
<td colspan="2">second Sunday in March</td>
</tr>
<tr>
<td colspan="2">first Sunday in November</td>
<td>return to standard time</td>
</tr>
</table>
<p>There are two interesting things to note here.</p>
<p>First, the time that something happens (in the <code>AT</code>
column) is not necessarily the local (wall clock) time. The time can be
suffixed with &lsquo;s&rsquo; (for &ldquo;standard&rdquo;) to mean
local standard time, different from local (wall clock) time when observing
daylight saving time; or it can be suffixed with &lsquo;g&rsquo;,
&lsquo;u&rsquo;, or &lsquo;z&rsquo;, all three of which mean the
standard time at the
<a href="https://en.wikipedia.org/wiki/Prime_Meridian">prime meridian</a>.
&lsquo;g&rsquo; stands for &ldquo;<a
href="https://en.wikipedia.org/wiki/Greenwich_Mean_Time">GMT</a>&rdquo;;
&lsquo;u&rsquo; stands for &ldquo;<a
href="https://en.wikipedia.org/wiki/Universal_Time">UT</a>&rdquo; or &ldquo;<a
href="https://en.wikipedia.org/wiki/Coordinated_Universal_Time">UTC</a>&rdquo;
(whichever was official at the time); &lsquo;z&rsquo; stands for the
<a href="https://en.wikipedia.org/wiki/Nautical_time">nautical time zone</a>
Z (a.k.a. &ldquo;Zulu&rdquo; which, in turn, stands for &lsquo;Z&rsquo;).
The time can also be suffixed with &lsquo;w&rsquo; meaning local (wall
clock) time; but it usually isn&rsquo;t because that&rsquo;s the
default.</p>
<p>Second, the day in the <code>ON</code> column, in addition to
&ldquo;<code>lastSun</code>&rdquo; or a particular day of the month,
can have the form, &ldquo;<code>Sun&gt;=</code><i>x</i>&rdquo; or
&ldquo;<code>Sun&lt;=</code><i>x</i>,&rdquo; where <i>x</i> is a day
of the month. For example, &ldquo;<code>Sun&gt;=8</code>&rdquo; means
&ldquo;the first Sunday on or after the eighth of the month,&rdquo; in
other words, the second Sunday of the month. Furthermore, although
there are no examples above, the weekday needn&rsquo;t be
&ldquo;<code>Sun</code>&rdquo; in either form, but can be the usual
three-character English abbreviation for any day of the week.</p>
<p>And the US rules give us more examples of a couple of things
already mentioned:</p>
<ul>
<li>The rules for changing to and from daylight saving time are
actually <i>different sets</i> of rules; and the two sets can change
independently. Consider, for example, that the rule for the return to
standard time stayed the same from 1967 to 2006; but the rule for the
transition to daylight saving time changed several times in the same
period. There can also be periods, 1946 to 1966 for example, when no
rule from this group is in effect, and so either no transition
happened in those years, or some other rule is in effect (perhaps a
state or other more local rule).</li>
<li>The <code>SAVE</code> and <code>LETTER</code> columns
contain <i>steady state</i>, not transitions. Consider, for example,
the transition from &ldquo;war time&rdquo; to &ldquo;peace time&rdquo;
that happened on August 14, 1945. The &ldquo;1:00&rdquo; in
the <code>SAVE</code> column is <i>not</i> an instruction to advance
the clock an hour. It means that clocks should <i>be</i> one hour
ahead of standard time, which they already are because of the previous
rule, so there should be no change.</li>
</ul>
<p>OK, now let&rsquo;s look at a Zone record:</p>
<table>
<tr>
<th colspan="5">From the Source File</th>
</tr>
<tr>
<td colspan="5">
<table class="rule">
<tr><td style="border:none;text-align:left">
<pre class="td">
#Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Chicago -5:50:36 - LMT 1883 Nov 18 12:09:24
-6:00 US C%sT 1920
-6:00 Chicago C%sT 1936 Mar 1 2:00
-5:00 - EST 1936 Nov 15 2:00
-6:00 Chicago C%sT 1942
-6:00 US C%sT 1946
-6:00 Chicago C%sT 1967
-6:00 US C%sT
</pre>
</td></tr></table></td>
</tr>
<tr>
<th colspan="5">Columns Renamed</th>
</tr>
<tr>
<th rowspan="2">Standard Offset<br>
from <a href="https://en.wikipedia.org/wiki/Prime_Meridian">Prime
Meridian</a></th>
<th rowspan="2">Daylight<br>Saving Time</th>
<th rowspan="2">Abbreviation(s)</th>
<th colspan="2">Ending at Local Time</th>
</tr>
<tr>
<th>Date</th>
<th>Time</th>
</tr>
<tr>
<td>&minus;5:50:36</td>
<td>not observed</td>
<td>LMT</td>
<td>1883-11-18</td>
<td>12:09:24</td>
</tr>
<tr>
<td rowspan="2">&minus;6:00:00</td>
<td>US rules</td>
<td rowspan="2">CST or CDT</td>
<td>1920-01-01</td>
<td>00:00:00</td>
</tr>
<tr>
<td>Chicago rules</td>
<td>1936-03-01</td>
<td rowspan="2">02:00:00</td>
</tr>
<tr>
<td>&minus;5:00:00</td>
<td>not observed</td>
<td>EST</td>
<td>1936-11-15</td>
</tr>
<tr>
<td rowspan="4">&minus;6:00:00</td>
<td>Chicago rules</td>
<td>CST or CDT</td>
<td>1942-01-01</td>
<td rowspan="3">00:00:00</td>
</tr>
<tr>
<td>US rules</td>
<td>CST, CWT or CPT</td>
<td>1946-01-01</td>
</tr>
<tr>
<td>Chicago rules</td>
<td rowspan="2">CST or CDT</td>
<td>1967-01-01</td>
</tr>
<tr>
<td>US rules</td>
<td colspan="2">&mdash;</td>
</tr>
</table>
<p>There are a couple of interesting differences between Zones and Rules.</p>
<p>First, and somewhat trivially, whereas Rules are considered to
contain one or more records, a Zone is considered to be a single
record with zero or more <i>continuation lines</i>. Thus, the keyword,
&ldquo;<code>Zone</code>,&rdquo; and the zone name are not
repeated. The last line is the one without anything in
the <code>[UNTIL]</code> column.</p>
<p>Second, and more fundamentally, each line of a Zone represents a
steady state, not a transition between states. The state exists from
the date and time in the previous line&rsquo;s <code>[UNTIL]</code>
column up to the date and time in the current
line&rsquo;s <code>[UNTIL]</code> column. In other words, the date and
time in the <code>[UNTIL]</code> column is the instant that separates
this state from the next. Where that would be ambiguous because
we&rsquo;re setting our clocks back, the <code>[UNTIL]</code> column
specifies the first occurrence of the instant. The state specified by
the last line, the one without anything in the <code>[UNTIL]</code>
column, continues to the present.</p>
<p>The first line typically specifies the mean solar time observed
before the introduction of standard time. Since there&rsquo;s no line before
that, it has no beginning. <code>8-) </code> For some places near the <a
href="https://en.wikipedia.org/wiki/International_Date_Line">International
Date Line</a>, the first <i>two</i> lines will show solar times
differing by 24 hours; this corresponds to a movement of the Date
Line. For example:</p>
<pre>
#Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Juneau 15:02:19 - LMT 1867 Oct 18
-8:57:41 - LMT ...
</pre>
<p>When Alaska was purchased from Russia in 1867, the Date Line moved
from the Alaska/Canada border to the Bering Strait; and the time in
Alaska was then 24 hours earlier than it had
been. <code>&lt;aside&gt;</code>(6 October in the Julian calendar,
which Russia was still using then for religious reasons, was followed
by <i>a second instance of the same day with a different name</i>, 18
October in the Gregorian calendar. Isn&rsquo;t civil time
wonderful? <code>8-)</code>)<code>&lt;/aside&gt;</code></p>
<p>The abbreviation, &ldquo;LMT&rdquo; stands for &ldquo;local mean
time&rdquo;, which is an invention of
the <a href="https://en.wikipedia.org/wiki/Tz_database">tz
database</a> and was probably never actually used during the
period. Furthermore, the value is almost certainly wrong except in the
archetypal place after which the zone is named. (The tz database
usually doesn&rsquo;t provide a separate Zone record for places where
nothing significant happened after 1970.)</p>
<p>The <code>RULES</code> column tells us whether daylight saving time is being observed:
<ul>
<li>A hyphen, a kind of null value, means that we have not set our
clocks ahead of standard time.</li>
<li>An amount of time (usually but not necessarily &ldquo;1:00&rdquo;
meaning one hour) means that we have set our clocks ahead by that
amount.</li>
<li>Some alphabetic string means that we <i>might have</i> set our
clocks ahead; and we need to check the rule the name of which is the
given alphabetic string.</li>
</ul>
<p>An example of a specific amount of time is:</p>
<pre>
#Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Pacific/Honolulu ... 1933 Apr 30 2:00
-10:30 1:00 HDT 1933 May 21 12:00
...
</pre>
<p>Hawaii tried daylight saving time for three weeks in 1933 and
decided they didn&rsquo;t like it. <code>8-) </code>Note that
the <code>STDOFF</code> column always contains the standard time
offset, so the local (wall clock) time during this period was GMT &minus;
10:30 + 1:00 = GMT &minus; 9:30.</p>
<p>The <code>FORMAT</code> column specifies the usual abbreviation of
the time zone name. It should have one of four forms:</p>
<ul>
<li>a time zone abbreviation that is a string of three or more
characters that are either ASCII alphanumerics,
&ldquo;<code>+</code>&rdquo;, or &ldquo;<code>-</code>&rdquo;</li>
<li>the string &ldquo;%z&rdquo;, in which case the
&ldquo;<code>%z</code>&rdquo; will be replaced by a numeric time zone
abbreviation</li>
<li>a pair of time zone abbreviations separated by a slash
(&lsquo;<code>/</code>&rsquo;), in which case the first string is the
abbreviation for the standard time name and the second string is the
abbreviation for the daylight saving time name</li>
<li>a string containing &ldquo;<code>%s</code>&rdquo;, in which case
the &ldquo;<code>%s</code>&rdquo; will be replaced by the text in the
appropriate Rule&rsquo;s <code>LETTER</code> column, and the resulting
string should be a time zone abbreviation</li>
</ul>
<p>The last two make sense only if there&rsquo;s a named rule in effect.</p>
<p>An example of a slash is:</p>
<pre>
#Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Europe/London ... 1996
0:00 EU GMT/BST
</pre>
<p>The current time in the UK is called either Greenwich mean time or
British summer time.</p>
<p>One wrinkle, not fully explained in <code>zic.8.txt</code>, is what
happens when switching to a named rule. To what values should
the <code>SAVE</code> and <code>LETTER</code> data be initialized?</p>
<ul>
<li>If at least one transition has happened, use
the <code>SAVE</code> and <code>LETTER</code> data from the most
recent.</li>
<li>If switching to a named rule before any transition has happened,
assume standard time (<code>SAVE</code> zero), and use
the <code>LETTER</code> data from the earliest transition with
a <code>SAVE</code> of zero.
</ul>
<p>And three last things about the <code>FORMAT</code> column:</p>
<ul>
<li>The <a href="https://en.wikipedia.org/wiki/Tz_database">tz
database</a> gives abbreviations for time zones in <i>popular
usage</i>, which is not necessarily &ldquo;correct&rdquo; by law. For
example, the last line in
<code>Zone</code> <code>Pacific/Honolulu</code> (shown below) gives
&ldquo;HST&rdquo; for &ldquo;Hawaii standard time&rdquo; even though the
<a href="https://www.law.cornell.edu/uscode/text/15/263">legal</a>
name for that time zone is &ldquo;Hawaii-Aleutian standard time.&rdquo;
This author has read that there are also some places in Australia where
popular time zone names differ from the legal ones.
<li>No attempt is made to <a
href="https://en.wikipedia.org/wiki/Internationalization_and_localization">localize</a>
the abbreviations. They are intended to be the values returned through the
<code>"%Z"</code> format specifier to
<a href="https://en.wikipedia.org/wiki/C_(programming_language)">C</a>&rsquo;s
<a href="https://pubs.opengroup.org/onlinepubs/9699919799/functions/strftime.html"><code>strftime</code></a>
function in the
<a href="https://kirste.userpage.fu-berlin.de/chemnet/use/info/libc/libc_19.html#SEC324">&ldquo;C&rdquo; locale</a>.
<li>If there is no generally-accepted abbreviation for a time zone,
a numeric offset is used instead, e.g., <code>+07</code> for 7 hours
ahead of Greenwich. By convention, <code>-00</code> is used in a
zone while uninhabited, where the offset is zero but in some sense
the true offset is undefined.
</ul>
<p>As a final example, here&rsquo;s the complete history for Hawaii:</p>
<table>
<tr>
<th colspan="6">Relevant Excerpts from the US Rules</th>
</tr>
<tr>
<td colspan="6">
<table class="rule">
<tr><td style="border:none;text-align:left">
<pre class="td">
#Rule NAME FROM TO - IN ON AT SAVE LETTER/S
Rule US 1918 1919 - Oct lastSun 2:00 0 S
Rule US 1942 only - Feb 9 2:00 1:00 W # War
Rule US 1945 only - Aug 14 23:00u 1:00 P # Peace
Rule US 1945 only - Sep lastSun 2:00 0 S
</pre>
</td></tr></table></td>
</tr>
<tr>
<th colspan="6">The Zone Record</th>
</tr>
<tr>
<td colspan="6">
<table class="rule">
<tr><td style="border:none;text-align:left">
<pre class="td">
#Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Pacific/Honolulu -10:31:26 - LMT 1896 Jan 13 12:00
-10:30 - HST 1933 Apr 30 2:00
-10:30 1:00 HDT 1933 May 21 2:00
-10:30 US H%sT 1947 Jun 8 2:00
-10:00 - HST
</pre>
</td></tr></table></td>
</tr>
<tr>
<th colspan="6">What We Infer</th>
</tr>
<tr>
<th rowspan="2">Wall-Clock<br>Offset from<br>Prime Meridian</th>
<th rowspan="2">Adjust<br>Clocks</th>
<th colspan="2">Time Zone</th>
<th colspan="2">Ending at Local Time</th>
</tr>
<tr>
<th>Abbrv.</th>
<th>Name</th>
<th>Date</th>
<th>Time</th>
</tr>
<tr>
<td>&minus;10:31:26</td>
<td>&mdash;</td>
<td>LMT</td>
<td>local mean time</td>
<td>1896-01-13</td>
<td>12:00</td>
</tr>
<tr>
<td>&minus;10:30</td>
<td>+0:01:26</td>
<td>HST</td>
<td>Hawaii standard time</td>
<td>1933-04-30</td>
<td>02:00</td>
</tr>
<tr>
<td>&minus;9:30</td>
<td>+1:00</td>
<td>HDT</td>
<td>Hawaii daylight time</td>
<td>1933-05-21</td>
<td>12:00</td>
</tr>
<tr>
<td>&minus;10:30&sup1;</td>
<td>&minus;1:00&sup1;</td>
<td>HST&sup1;</td>
<td>Hawaii standard time</td>
<td>1942-02-09</td>
<td>02:00</td>
</tr>
<tr>
<td rowspan="2">&minus;9:30</td>
<td>+1:00</td>
<td>HWT</td>
<td>Hawaii war time</td>
<td>1945-08-14</td>
<td>13:30&sup2;</td>
</tr>
<tr>
<td>0</td>
<td>HPT</td>
<td>Hawaii peace time</td>
<td>1945-09-30</td>
<td rowspan="2">02:00</td>
</tr>
<tr>
<td>&minus;10:30</td>
<td>&minus;1:00</td>
<td rowspan="2">HST</td>
<td rowspan="2">Hawaii standard time</td>
<td>1947-06-08</td>
</tr>
<tr>
<td>&minus;10:00&sup3;</td>
<td>+0:30&sup3;</td>
<td colspan="2">&mdash;</td>
</tr>
<tr>
<td colspan="6" class="footnote">
&sup1;Switching to US rules&hellip;most recent transition (in 1919) was to standard time
</td>
</tr>
<tr>
<td colspan="6" class="footnote">
&sup2;23:00 <a href="https://en.wikipedia.org/wiki/Universal_Time">UT</a>
+ (&minus;9:30) = 13:30 local
</td>
</tr>
<tr>
<td colspan="6" class="footnote">
&sup3;Since <a href="https://en.wikipedia.org/wiki/ISO_8601">1947&ndash;06&ndash;08T12:30Z</a>,
the civil time in Hawaii has been
<a href="https://en.wikipedia.org/wiki/Universal_Time">UT</a>/<a href="https://en.wikipedia.org/wiki/Coordinated_Universal_Time">UTC</a>
&minus; 10:00 year-round.
</td>
</tr>
</table>
<p>There will be a short quiz later. <code>8-)</code></p>
<hr>
<address>
This web page is in the public domain, so clarified as of
2015-10-20 by Bill Seymour.
<br>
All suggestions and corrections will be welcome; all flames will be amusing.
Mail to was at pobox dot com.
</address>
</body>
</html>

1175
contrib/tzcode/tz-link.html Normal file

File diff suppressed because it is too large Load Diff

492
contrib/tzcode/tzfile.5 Normal file
View File

@ -0,0 +1,492 @@
.\" This file is in the public domain, so clarified as of
.\" 1996-06-05 by Arthur David Olson.
.\"
.\" $FreeBSD$
.\"
.Dd December 15, 2022
.Dt TZFILE 5
.Os
.Sh NAME
.Nm tzfile
.Nd timezone information
.Sh DESCRIPTION
The timezone information files used by
.Xr tzset 3
are found under
.Pa /usr/share/zoneinfo .
These files use the format described in Internet RFC 8536.
Each file is a sequence of 8-bit bytes.
In a file, a binary integer is represented by a sequence of one or
more bytes in network order (bigendian, or high-order byte first),
with all bits significant,
a signed binary integer is represented using two's complement,
and a boolean is represented by a one-byte binary integer that is
either 0 (false) or 1 (true).
The format begins with a 44-byte header containing the following fields:
.Pp
.Bl -bullet
.It
The magic four-byte ASCII sequence
.Dq "TZif"
identifies the file as a timezone information file.
.It
A byte identifying the version of the file's format
(as of 2021, either an ASCII NUL,
.Dq "2" ,
.Dq "3" ,
or
.Dq "4" ) .
.It
Fifteen bytes containing zeros reserved for future use.
.It
Six four-byte integer values, in the following order:
.Pp
.Bl -tag -compat -width tzh_ttisstdcnt
.It Va tzh_ttisutcnt
The number of UT/local indicators stored in the file.
(UT is Universal Time.)
.It Va tzh_ttisstdcnt
The number of standard/wall indicators stored in the file.
.It Va tzh_leapcnt
The number of leap seconds for which data entries are stored in the file.
.It Va tzh_timecnt
The number of transition times for which data entries are stored
in the file.
.It Va tzh_typecnt
The number of local time types for which data entries are stored
in the file (must not be zero).
.It Va tzh_charcnt
The number of bytes of time zone abbreviation strings
stored in the file.
.El
.El
.Pp
The above header is followed by the following fields, whose lengths
depend on the contents of the header:
.Bl -tag -compat -width tzh_timecnt
.It Va tzh_timecnt
four-byte signed integer values sorted in ascending order.
These values are written in network byte order.
Each is used as a transition time (as returned by
.Xt time 2 )
at which the rules for computing local time change.
.It Va tzh_timecnt
one-byte unsigned integer values;
each one but the last tells which of the different types of local time types
described in the file is associated with the time period
starting with the same-indexed transition time
and continuing up to but not including the next transition time.
(The last time type is present only for consistency checking with the
POSIX-style TZ string described below.)
These values serve as indices into the next field.
.It Va tzh_typecnt
.Vt ttinfo
entries, each defined as follows:
.Pp
.Bd -literal -offset indent
struct ttinfo {
int32_t tt_utoff;
unsigned char tt_isdst;
unsigned char tt_desigidx;
};
.Ed
.Pp
Each structure is written as a four-byte signed integer value for
.Va tt_utoff ,
in network byte order, followed by a one-byte boolean for
.Va tt_isdst
and a one-byte value for
.Va tt_desigidx .
In each structure,
.Va tt_utoff
gives the number of seconds to be added to UT,
.Va tt_isdst
tells whether
.Va tm_isdst
should be set by
.Xr localtime 3
and
.Va tt_desigidx
serves as an index into the array of time zone abbreviation bytes
that follow the
.Vt ttinfo
entries in the file; if the designated string is "\*-00", the
.Vt ttinfo
entry is a placeholder indicating that local time is unspecified.
The
.Va tt_utoff
value is never equal to \-2**31, to let 32-bit clients negate it without
overflow.
Also, in realistic applications
.Va tt_utoff
is in the range [\-89999, 93599] (i.e., more than \-25 hours and less
than 26 hours); this allows easy support by implementations that
already support the POSIX-required range [\-24:59:59, 25:59:59].
.It Va tzh_charcnt
bytes that represent time zone designations,
which are null-terminated byte strings, each indexed by the
.Va tt_desigidx
values mentioned above.
The byte strings can overlap if one is a suffix of the other.
The encoding of these strings is not specified.
.It Va tzh_leapcnt
pairs of four-byte values, written in network byte order;
the first value of each pair gives the nonnegative time
(as returned by
.Xr time 3 )
at which a leap second occurs or at which the leap second table expires;
the second is a signed integer specifying the correction, which is the
.Em total
number of leap seconds to be applied during the time period
starting at the given time.
The pairs of values are sorted in strictly ascending order by time.
Each pair denotes one leap second, either positive or negative,
except that if the last pair has the same correction as the previous one,
the last pair denotes the leap second table's expiration time.
Each leap second is at the end of a UTC calendar month.
The first leap second has a nonnegative occurrence time,
and is a positive leap second if and only if its correction is positive;
the correction for each leap second after the first differs
from the previous leap second by either 1 for a positive leap second,
or \-1 for a negative leap second.
If the leap second table is empty, the leap-second correction is zero
for all timestamps;
otherwise, for timestamps before the first occurrence time,
the leap-second correction is zero if the first pair's correction is 1 or \-1,
and is unspecified otherwise (which can happen only in files
truncated at the start).
.It Va tzh_ttisstdcnt
standard/wall indicators, each stored as a one-byte boolean;
they tell whether the transition times associated with local time types
were specified as standard time or local (wall clock) time.
.It Va tzh_ttisutcnt
UT/local indicators, each stored as a one-byte boolean;
they tell whether the transition times associated with local time types
were specified as UT or local time.
If a UT/local indicator is set, the corresponding standard/wall indicator
must also be set.
.El
.Pp
The standard/wall and UT/local indicators were designed for
transforming a TZif file's transition times into transitions appropriate
for another time zone specified via a POSIX-style TZ string that lacks rules.
For example, when TZ="EET\*-2EEST" and there is no TZif file "EET\*-2EEST",
the idea was to adapt the transition times from a TZif file with the
well-known name "posixrules" that is present only for this purpose and
is a copy of the file "Europe/Brussels", a file with a different UT offset.
POSIX does not specify this obsolete transformational behavior,
the default rules are installation-dependent, and no implementation
is known to support this feature for timestamps past 2037,
so users desiring (say) Greek time should instead specify
TZ="Europe/Athens" for better historical coverage, falling back on
TZ="EET\*-2EEST,M3.5.0/3,M10.5.0/4" if POSIX conformance is required
and older timestamps need not be handled accurately.
.Pp
The
.Xr localtime 3
function
normally uses the first
.Vt ttinfo
structure in the file
if either
.Va tzh_timecnt
is zero or the time argument is less than the first transition time recorded
in the file.
.Ss Version 2 format
For version-2-format timezone files,
the above header and data are followed by a second header and data,
identical in format except that
eight bytes are used for each transition time or leap second time.
(Leap second counts remain four bytes.)
After the second header and data comes a newline-enclosed,
POSIX-TZ-environment-variable-style string for use in handling instants
after the last transition time stored in the file
or for all instants if the file has no transitions.
The POSIX-style TZ string is empty (i.e., nothing between the newlines)
if there is no POSIX-style representation for such instants.
If nonempty, the POSIX-style TZ string must agree with the local time
type after the last transition time if present in the eight-byte data;
for example, given the string
.Dq "WET0WEST,M3.5.0,M10.5.0/3"
then if a last transition time is in July, the transition's local time
type must specify a daylight-saving time abbreviated
.Dq "WEST"
that is one hour east of UT.
Also, if there is at least one transition, time type 0 is associated
with the time period from the indefinite past up to but not including
the earliest transition time.
.Ss Version 3 format
For version-3-format timezone files, the POSIX-TZ-style string may
use two minor extensions to the POSIX TZ format, as described in
.Xr newtzset 3 .
First, the hours part of its transition times may be signed and range from
\-167 through 167 instead of the POSIX-required unsigned values
from 0 through 24.
Second, DST is in effect all year if it starts
January 1 at 00:00 and ends December 31 at 24:00 plus the difference
between daylight saving and standard time.
.Ss Version 4 format
For version-4-format TZif files,
the first leap second record can have a correction that is neither
+1 nor \-1, to represent truncation of the TZif file at the start.
Also, if two or more leap second transitions are present and the last
entry's correction equals the previous one, the last entry
denotes the expiration of the leap second table instead of a leap second;
timestamps after this expiration are unreliable in that future
releases will likely add leap second entries after the expiration, and
the added leap seconds will change how post-expiration timestamps are treated.
.Ss Interoperability considerations
Future changes to the format may append more data.
.Pp
Version 1 files are considered a legacy format and
should not be generated, as they do not support transition
times after the year 2038.
Readers that understand only Version 1 must ignore
any data that extends beyond the calculated end of the version
1 data block.
.Pp
Other than version 1, writers should generate
the lowest version number needed by a file's data.
For example, a writer should generate a version 4 file
only if its leap second table either expires or is truncated at the start.
Likewise, a writer not generating a version 4 file
should generate a version 3 file only if
TZ string extensions are necessary to accurately
model transition times.
.Pp
The sequence of time changes defined by the version 1
header and data block should be a contiguous sub-sequence
of the time changes defined by the version 2+ header and data
block, and by the footer.
This guideline helps obsolescent version 1 readers
agree with current readers about timestamps within the
contiguous sub-sequence.
It also lets writers not
supporting obsolescent readers use a
.Va tzh_timecnt
of zero
in the version 1 data block to save space.
.Pp
When a TZif file contains a leap second table expiration
time, TZif readers should either refuse to process
post-expiration timestamps, or process them as if the expiration
time did not exist (possibly with an error indication).
.Pp
Time zone designations should consist of at least three (3)
and no more than six (6) ASCII characters from the set of
alphanumerics,
.Dq "\*-" ,
and
.Dq "+" .
This is for compatibility with POSIX requirements for
time zone abbreviations.
.Pp
When reading a version 2 or higher file, readers
should ignore the version 1 header and data block except for
the purpose of skipping over them.
.Pp
Readers should calculate the total lengths of the
headers and data blocks and check that they all fit within
the actual file size, as part of a validity check for the file.
.Pp
When a positive leap second occurs, readers should append an extra
second to the local minute containing the second just before the leap
second.
If this occurs when the UTC offset is not a multiple of 60
seconds, the leap second occurs earlier than the last second of the
local minute and the minute's remaining local seconds are numbered
through 60 instead of the usual 59; the UTC offset is unaffected.
.Ss Common interoperability issues
This section documents common problems in reading or writing TZif files.
Most of these are problems in generating TZif files for use by
older readers.
The goals of this section are:
.Bl -bullet
.It
to help TZif writers output files that avoid common
pitfalls in older or buggy TZif readers,
.It
to help TZif readers avoid common pitfalls when reading
files generated by future TZif writers, and
.It
to help any future specification authors see what sort of
problems arise when the TZif format is changed.
.El
.Pp
When new versions of the TZif format have been defined, a
design goal has been that a reader can successfully use a TZif
file even if the file is of a later TZif version than what the
reader was designed for.
When complete compatibility was not achieved, an attempt was
made to limit glitches to rarely used timestamps and allow
simple partial workarounds in writers designed to generate
new-version data useful even for older-version readers.
This section attempts to document these compatibility issues and
workarounds, as well as to document other common bugs in
readers.
.Pp
Interoperability problems with TZif include the following:
.Bl -bullet
.It
Some readers examine only version 1 data.
As a partial workaround, a writer can output as much version 1
data as possible.
However, a reader should ignore version 1 data, and should use
version 2+ data even if the reader's native timestamps have only
32 bits.
.It
Some readers designed for version 2 might mishandle
timestamps after a version 3 or higher file's last transition, because
they cannot parse extensions to POSIX in the TZ-like string.
As a partial workaround, a writer can output more transitions
than necessary, so that only far-future timestamps are
mishandled by version 2 readers.
.It
Some readers designed for version 2 do not support
permanent daylight saving time with transitions after 24:00
\(en e.g., a TZ string
.Dq "EST5EDT,0/0,J365/25"
denoting permanent Eastern Daylight Time
(\-04).
As a workaround, a writer can substitute standard time
for two time zones east, e.g.,
.Dq "XXX3EDT4,0/0,J365/23"
for a time zone with a never-used standard time (XXX, \-03)
and negative daylight saving time (EDT, \-04) all year.
Alternatively,
as a partial workaround a writer can substitute standard time
for the next time zone east \(en e.g.,
.Dq "AST4"
for permanent
Atlantic Standard Time (\-04).
.It
Some readers designed for version 2 or 3, and that require strict
conformance to RFC 8536, reject version 4 files whose leap second
tables are truncated at the start or that end in expiration times.
.It
Some readers ignore the footer, and instead predict future
timestamps from the time type of the last transition.
As a partial workaround, a writer can output more transitions
than necessary.
.It
Some readers do not use time type 0 for timestamps before
the first transition, in that they infer a time type using a
heuristic that does not always select time type 0.
As a partial workaround, a writer can output a dummy (no-op)
first transition at an early time.
.It
Some readers mishandle timestamps before the first
transition that has a timestamp not less than \-2**31.
Readers that support only 32-bit timestamps are likely to be
more prone to this problem, for example, when they process
64-bit transitions only some of which are representable in 32
bits.
As a partial workaround, a writer can output a dummy
transition at timestamp \-2**31.
.It
Some readers mishandle a transition if its timestamp has
the minimum possible signed 64-bit value.
Timestamps less than \-2**59 are not recommended.
.It
Some readers mishandle POSIX-style TZ strings that
contain
.Dq "<"
or
.Dq ">".
As a partial workaround, a writer can avoid using
.Dq "<"
or
.Dq ">"
for time zone abbreviations containing only alphabetic
characters.
.It
Many readers mishandle time zone abbreviations that contain
non-ASCII characters.
These characters are not recommended.
.It
Some readers may mishandle time zone abbreviations that
contain fewer than 3 or more than 6 characters, or that
contain ASCII characters other than alphanumerics,
.Dq "\*-",
and
.Dq "+".
These abbreviations are not recommended.
.It
Some readers mishandle TZif files that specify
daylight-saving time UT offsets that are less than the UT
offsets for the corresponding standard time.
These readers do not support locations like Ireland, which
uses the equivalent of the POSIX TZ string
.Dq "IST\*-1GMT0,M10.5.0,M3.5.0/1" ,
observing standard time
(IST, +01) in summer and daylight saving time (GMT, +00) in winter.
As a partial workaround, a writer can output data for the
equivalent of the POSIX TZ string
.Dq "GMT0IST,M3.5.0/1,M10.5.0" ,
thus swapping standard and daylight saving time.
Although this workaround misidentifies which part of the year
uses daylight saving time, it records UT offsets and time zone
abbreviations correctly.
.It
Some readers generate ambiguous timestamps for positive leap seconds
that occur when the UTC offset is not a multiple of 60 seconds.
For example, in a timezone with UTC offset +01:23:45 and with
a positive leap second 78796801 (1972-06-30 23:59:60 UTC), some readers will
map both 78796800 and 78796801 to 01:23:45 local time the next day
instead of mapping the latter to 01:23:46, and they will map 78796815 to
01:23:59 instead of to 01:23:60.
This has not yet been a practical problem, since no civil authority
has observed such UTC offsets since leap seconds were
introduced in 1972.
.El
.Pp
Some interoperability problems are reader bugs that
are listed here mostly as warnings to developers of readers.
.Bl -bullet
.It
Some readers do not support negative timestamps.
Developers of distributed applications should keep this
in mind if they need to deal with pre-1970 data.
.It
Some readers mishandle timestamps before the first
transition that has a nonnegative timestamp.
Readers that do not support negative timestamps are likely to
be more prone to this problem.
.It
Some readers mishandle time zone abbreviations like
.Dq "\*-08"
that contain
.Dq "+" ,
.Dq "\*-" ,
or digits.
.It
Some readers mishandle UT offsets that are out of the
traditional range of \-12 through +12 hours, and so do not
support locations like Kiritimati that are outside this
range.
.It
Some readers mishandle UT offsets in the range [\-3599, \-1]
seconds from UT, because they integer-divide the offset by
3600 to get 0 and then display the hour part as
.Dq "+00" .
.It
Some readers mishandle UT offsets that are not a multiple
of one hour, or of 15 minutes, or of 1 minute.
.El
.Sh SEE ALSO
.Xr time 3 ,
.Xr localtime 3 ,
.Xr tzset 3 ,
.Xr tzsetup 8 ,
.Xr zic 8 ,
.Xr zdump 8
.Rs
.%A A. Olson
.%A P. Eggert
.%A K. Murchison
.%T "The Time Zone Information Format (TZif)"
.%R RFC 8536
.%D February 2019
.%U https://datatracker.ietf.org/doc/html/rfc8536
.%U https://doi.org/10.17487/RFC8536
.Re

125
contrib/tzcode/tzfile.h Normal file
View File

@ -0,0 +1,125 @@
/* Layout and location of TZif files. */
#ifndef TZFILE_H
#define TZFILE_H
/*
** This file is in the public domain, so clarified as of
** 1996-06-05 by Arthur David Olson.
**
** $FreeBSD$
*/
/*
** This header is for use ONLY with the time conversion code.
** There is no guarantee that it will remain unchanged,
** or that it will remain at all.
** Do NOT copy it to any system include directory.
** Thank you!
*/
/*
** Information about time zone files.
*/
#ifndef TZDIR
# define TZDIR "/usr/share/zoneinfo" /* Time zone object file directory */
#endif /* !defined TZDIR */
#ifndef TZDEFAULT
# define TZDEFAULT "/etc/localtime"
#endif /* !defined TZDEFAULT */
#ifndef TZDEFRULES
# define TZDEFRULES "posixrules"
#endif /* !defined TZDEFRULES */
/* See Internet RFC 8536 for more details about the following format. */
/*
** Each file begins with. . .
*/
#define TZ_MAGIC "TZif"
struct tzhead {
char tzh_magic[4]; /* TZ_MAGIC */
char tzh_version[1]; /* '\0' or '2'-'4' as of 2021 */
char tzh_reserved[15]; /* reserved; must be zero */
char tzh_ttisutcnt[4]; /* coded number of trans. time flags */
char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */
char tzh_leapcnt[4]; /* coded number of leap seconds */
char tzh_timecnt[4]; /* coded number of transition times */
char tzh_typecnt[4]; /* coded number of local time types */
char tzh_charcnt[4]; /* coded number of abbr. chars */
};
/*
** . . .followed by. . .
**
** tzh_timecnt (char [4])s coded transition times a la time(2)
** tzh_timecnt (unsigned char)s types of local time starting at above
** tzh_typecnt repetitions of
** one (char [4]) coded UT offset in seconds
** one (unsigned char) used to set tm_isdst
** one (unsigned char) that's an abbreviation list index
** tzh_charcnt (char)s '\0'-terminated zone abbreviations
** tzh_leapcnt repetitions of
** one (char [4]) coded leap second transition times
** one (char [4]) total correction after above
** tzh_ttisstdcnt (char)s indexed by type; if 1, transition
** time is standard time, if 0,
** transition time is local (wall clock)
** time; if absent, transition times are
** assumed to be local time
** tzh_ttisutcnt (char)s indexed by type; if 1, transition
** time is UT, if 0, transition time is
** local time; if absent, transition
** times are assumed to be local time.
** When this is 1, the corresponding
** std/wall indicator must also be 1.
*/
/*
** If tzh_version is '2' or greater, the above is followed by a second instance
** of tzhead and a second instance of the data in which each coded transition
** time uses 8 rather than 4 chars,
** then a POSIX-TZ-environment-variable-style string for use in handling
** instants after the last transition time stored in the file
** (with nothing between the newlines if there is no POSIX representation for
** such instants).
**
** If tz_version is '3' or greater, the above is extended as follows.
** First, the POSIX TZ string's hour offset may range from -167
** through 167 as compared to the POSIX-required 0 through 24.
** Second, its DST start time may be January 1 at 00:00 and its stop
** time December 31 at 24:00 plus the difference between DST and
** standard time, indicating DST all year.
*/
/*
** In the current implementation, "tzset()" refuses to deal with files that
** exceed any of the limits below.
*/
#ifndef TZ_MAX_TIMES
# define TZ_MAX_TIMES 2000
#endif /* !defined TZ_MAX_TIMES */
#ifndef TZ_MAX_TYPES
/* This must be at least 17 for Europe/Samara and Europe/Vilnius. */
# define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */
#endif /* !defined TZ_MAX_TYPES */
#ifndef TZ_MAX_CHARS
# define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */
/* (limited by what unsigned chars can hold) */
#endif /* !defined TZ_MAX_CHARS */
#ifndef TZ_MAX_LEAPS
# define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */
#endif /* !defined TZ_MAX_LEAPS */
#endif /* !defined TZFILE_H */

125
contrib/tzcode/tzselect.8 Normal file
View File

@ -0,0 +1,125 @@
.\" This file is in the public domain, so clarified as of
.\" 2009-05-17 by Arthur David Olson.
.TH TZSELECT 8
.SH NAME
tzselect \- select a timezone
.SH SYNOPSIS
.ie \n(.g .ds - \f(CR-\fP
.el .ds - \-
.ds d " degrees
.ds m " minutes
.ds s " seconds
.ds _ " \&
.if t \{\
. if \n(.g .if c \(de .if c \(fm .if c \(sd \{\
. ds d \(de
. ds m \(fm
. ds s \(sd
. ds _ \|
. \}
.\}
.B tzselect
[
.B \*-c
.I coord
] [
.B \*-n
.I limit
] [
.B \*-\*-help
] [
.B \*-\*-version
]
.SH DESCRIPTION
The
.B tzselect
program asks the user for information about the current location,
and outputs the resulting timezone to standard output.
The output is suitable as a value for the TZ environment variable.
.PP
All interaction with the user is done via standard input and standard error.
.SH OPTIONS
.TP
.BI "\*-c " coord
Instead of asking for continent and then country and then city,
ask for selection from time zones whose largest cities
are closest to the location with geographical coordinates
.I coord.
Use ISO 6709 notation for
.I coord,
that is, a latitude immediately followed by a longitude. The latitude
and longitude should be signed integers followed by an optional
decimal point and fraction: positive numbers represent north and east,
negative south and west. Latitudes with two and longitudes with three
integer digits are treated as degrees; latitudes with four or six and
longitudes with five or seven integer digits are treated as
.I "DDMM, DDDMM, DDMMSS,"
or
.I DDDMMSS
representing
.I DD
or
.I DDD
degrees,
.I MM
minutes,
and zero or
.I SS
seconds, with any trailing fractions represent fractional minutes or
(if
.I SS
is present) seconds. The decimal point is that of the current locale.
For example, in the (default) C locale,
.B "\*-c\ +40.689\*-074.045"
specifies 40.689\*d\*_N, 74.045\*d\*_W,
.B "\*-c\ +4041.4\*-07402.7"
specifies 40\*d\*_41.4\*m\*_N, 74\*d\*_2.7\*m\*_W, and
.B "\*-c\ +404121\*-0740240"
specifies 40\*d\*_41\*m\*_21\*s\*_N, 74\*d\*_2\*m\*_40\*s\*_W.
If
.I coord
is not one of the documented forms, the resulting behavior is unspecified.
.TP
.BI "\*-n " limit
When
.B \*-c
is used, display the closest
.I limit
locations (default 10).
.TP
.B "\*-\*-help"
Output help information and exit.
.TP
.B "\*-\*-version"
Output version information and exit.
.SH "ENVIRONMENT VARIABLES"
.TP
\f3AWK\fP
Name of a Posix-compliant
.B awk
program (default:
.BR awk ).
.TP
\f3TZDIR\fP
Name of the directory containing timezone data files (default:
.BR /usr/share/zoneinfo ).
.SH FILES
.TP
\f2TZDIR\fP\f3/iso3166.tab\fP
Table of ISO 3166 2-letter country codes and country names.
.TP
\f2TZDIR\fP\f3/zone1970.tab\fP
Table of country codes, latitude and longitude, timezones, and
descriptive comments.
.TP
\f2TZDIR\fP\f3/\fP\f2TZ\fP
Timezone data file for timezone \f2TZ\fP.
.SH "EXIT STATUS"
The exit status is zero if a timezone was successfully obtained from the user,
nonzero otherwise.
.SH "SEE ALSO"
newctime(3), tzfile(5), zdump(8), zic(8)
.SH NOTES
Applications should not assume that
.BR tzselect 's
output matches the user's political preferences.

586
contrib/tzcode/tzselect.ksh Normal file
View File

@ -0,0 +1,586 @@
#!/bin/bash
# Ask the user about the time zone, and output the resulting TZ value to stdout.
# Interact with the user via stderr and stdin.
PKGVERSION='(tzcode) '
TZVERSION=see_Makefile
REPORT_BUGS_TO=tz@iana.org
# Contributed by Paul Eggert. This file is in the public domain.
# Porting notes:
#
# This script requires a Posix-like shell and prefers the extension of a
# 'select' statement. The 'select' statement was introduced in the
# Korn shell and is available in Bash and other shell implementations.
# If your host lacks both Bash and the Korn shell, you can get their
# source from one of these locations:
#
# Bash <https://www.gnu.org/software/bash/>
# Korn Shell <http://www.kornshell.com/>
# MirBSD Korn Shell <http://www.mirbsd.org/mksh.htm>
#
# For portability to Solaris 10 /bin/sh (supported by Oracle through
# January 2024) this script avoids some POSIX features and common
# extensions, such as $(...) (which works sometimes but not others),
# $((...)), ! CMD, ${#ID}, ${ID##PAT}, ${ID%%PAT}, and $10.
#
# This script also uses several features of modern awk programs.
# If your host lacks awk, or has an old awk that does not conform to Posix,
# you can use either of the following free programs instead:
#
# Gawk (GNU awk) <https://www.gnu.org/software/gawk/>
# mawk <https://invisible-island.net/mawk/>
# nawk <https://github.com/onetrueawk/awk>
# Specify default values for environment variables if they are unset.
: ${AWK=awk}
: ${TZDIR=`pwd`}
# Output one argument as-is to standard output.
# Safer than 'echo', which can mishandle '\' or leading '-'.
say() {
printf '%s\n' "$1"
}
# Check for awk Posix compliance.
($AWK -v x=y 'BEGIN { exit 123 }') </dev/null >/dev/null 2>&1
[ $? = 123 ] || {
say >&2 "$0: Sorry, your '$AWK' program is not Posix compatible."
exit 1
}
coord=
location_limit=10
zonetabtype=zone1970
usage="Usage: tzselect [--version] [--help] [-c COORD] [-n LIMIT]
Select a timezone interactively.
Options:
-c COORD
Instead of asking for continent and then country and then city,
ask for selection from time zones whose largest cities
are closest to the location with geographical coordinates COORD.
COORD should use ISO 6709 notation, for example, '-c +4852+00220'
for Paris (in degrees and minutes, North and East), or
'-c -35-058' for Buenos Aires (in degrees, South and West).
-n LIMIT
Display at most LIMIT locations when -c is used (default $location_limit).
--version
Output version information.
--help
Output this help.
Report bugs to $REPORT_BUGS_TO."
# Ask the user to select from the function's arguments,
# and assign the selected argument to the variable 'select_result'.
# Exit on EOF or I/O error. Use the shell's 'select' builtin if available,
# falling back on a less-nice but portable substitute otherwise.
if
case $BASH_VERSION in
?*) : ;;
'')
# '; exit' should be redundant, but Dash doesn't properly fail without it.
(eval 'set --; select x; do break; done; exit') </dev/null 2>/dev/null
esac
then
# Do this inside 'eval', as otherwise the shell might exit when parsing it
# even though it is never executed.
eval '
doselect() {
select select_result
do
case $select_result in
"") echo >&2 "Please enter a number in range." ;;
?*) break
esac
done || exit
}
'
else
doselect() {
# Field width of the prompt numbers.
select_width=`expr $# : '.*'`
select_i=
while :
do
case $select_i in
'')
select_i=0
for select_word
do
select_i=`expr $select_i + 1`
printf >&2 "%${select_width}d) %s\\n" $select_i "$select_word"
done ;;
*[!0-9]*)
echo >&2 'Please enter a number in range.' ;;
*)
if test 1 -le $select_i && test $select_i -le $#; then
shift `expr $select_i - 1`
select_result=$1
break
fi
echo >&2 'Please enter a number in range.'
esac
# Prompt and read input.
printf >&2 %s "${PS3-#? }"
read select_i || exit
done
}
fi
while getopts c:n:t:-: opt
do
case $opt$OPTARG in
c*)
coord=$OPTARG ;;
n*)
location_limit=$OPTARG ;;
t*) # Undocumented option, used for developer testing.
zonetabtype=$OPTARG ;;
-help)
exec echo "$usage" ;;
-version)
exec echo "tzselect $PKGVERSION$TZVERSION" ;;
-*)
say >&2 "$0: -$opt$OPTARG: unknown option; try '$0 --help'"; exit 1 ;;
*)
say >&2 "$0: try '$0 --help'"; exit 1 ;;
esac
done
shift `expr $OPTIND - 1`
case $# in
0) ;;
*) say >&2 "$0: $1: unknown argument"; exit 1 ;;
esac
# Make sure the tables are readable.
TZ_COUNTRY_TABLE=$TZDIR/iso3166.tab
TZ_ZONE_TABLE=$TZDIR/$zonetabtype.tab
for f in $TZ_COUNTRY_TABLE $TZ_ZONE_TABLE
do
<"$f" || {
say >&2 "$0: time zone files are not set up correctly"
exit 1
}
done
# If the current locale does not support UTF-8, convert data to current
# locale's format if possible, as the shell aligns columns better that way.
# Check the UTF-8 of U+12345 CUNEIFORM SIGN URU TIMES KI.
$AWK 'BEGIN { u12345 = "\360\222\215\205"; exit length(u12345) != 1 }' || {
{ tmp=`(mktemp -d) 2>/dev/null` || {
tmp=${TMPDIR-/tmp}/tzselect.$$ &&
(umask 77 && mkdir -- "$tmp")
};} &&
trap 'status=$?; rm -fr -- "$tmp"; exit $status' 0 HUP INT PIPE TERM &&
(iconv -f UTF-8 -t //TRANSLIT <"$TZ_COUNTRY_TABLE" >$tmp/iso3166.tab) \
2>/dev/null &&
TZ_COUNTRY_TABLE=$tmp/iso3166.tab &&
iconv -f UTF-8 -t //TRANSLIT <"$TZ_ZONE_TABLE" >$tmp/$zonetabtype.tab &&
TZ_ZONE_TABLE=$tmp/$zonetabtype.tab
}
newline='
'
IFS=$newline
# Awk script to read a time zone table and output the same table,
# with each column preceded by its distance from 'here'.
output_distances='
BEGIN {
FS = "\t"
while (getline <TZ_COUNTRY_TABLE)
if ($0 ~ /^[^#]/)
country[$1] = $2
country["US"] = "US" # Otherwise the strings get too long.
}
function abs(x) {
return x < 0 ? -x : x;
}
function min(x, y) {
return x < y ? x : y;
}
function convert_coord(coord, deg, minute, ilen, sign, sec) {
if (coord ~ /^[-+]?[0-9]?[0-9][0-9][0-9][0-9][0-9][0-9]([^0-9]|$)/) {
degminsec = coord
intdeg = degminsec < 0 ? -int(-degminsec / 10000) : int(degminsec / 10000)
minsec = degminsec - intdeg * 10000
intmin = minsec < 0 ? -int(-minsec / 100) : int(minsec / 100)
sec = minsec - intmin * 100
deg = (intdeg * 3600 + intmin * 60 + sec) / 3600
} else if (coord ~ /^[-+]?[0-9]?[0-9][0-9][0-9][0-9]([^0-9]|$)/) {
degmin = coord
intdeg = degmin < 0 ? -int(-degmin / 100) : int(degmin / 100)
minute = degmin - intdeg * 100
deg = (intdeg * 60 + minute) / 60
} else
deg = coord
return deg * 0.017453292519943296
}
function convert_latitude(coord) {
match(coord, /..*[-+]/)
return convert_coord(substr(coord, 1, RLENGTH - 1))
}
function convert_longitude(coord) {
match(coord, /..*[-+]/)
return convert_coord(substr(coord, RLENGTH))
}
# Great-circle distance between points with given latitude and longitude.
# Inputs and output are in radians. This uses the great-circle special
# case of the Vicenty formula for distances on ellipsoids.
function gcdist(lat1, long1, lat2, long2, dlong, x, y, num, denom) {
dlong = long2 - long1
x = cos(lat2) * sin(dlong)
y = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dlong)
num = sqrt(x * x + y * y)
denom = sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * cos(dlong)
return atan2(num, denom)
}
# Parallel distance between points with given latitude and longitude.
# This is the product of the longitude difference and the cosine
# of the latitude of the point that is further from the equator.
# I.e., it considers longitudes to be further apart if they are
# nearer the equator.
function pardist(lat1, long1, lat2, long2) {
return abs(long1 - long2) * min(cos(lat1), cos(lat2))
}
# The distance function is the sum of the great-circle distance and
# the parallel distance. It could be weighted.
function dist(lat1, long1, lat2, long2) {
return gcdist(lat1, long1, lat2, long2) + pardist(lat1, long1, lat2, long2)
}
BEGIN {
coord_lat = convert_latitude(coord)
coord_long = convert_longitude(coord)
}
/^[^#]/ {
here_lat = convert_latitude($2)
here_long = convert_longitude($2)
line = $1 "\t" $2 "\t" $3
sep = "\t"
ncc = split($1, cc, /,/)
for (i = 1; i <= ncc; i++) {
line = line sep country[cc[i]]
sep = ", "
}
if (NF == 4)
line = line " - " $4
printf "%g\t%s\n", dist(coord_lat, coord_long, here_lat, here_long), line
}
'
# Begin the main loop. We come back here if the user wants to retry.
while
echo >&2 'Please identify a location' \
'so that time zone rules can be set correctly.'
continent=
country=
region=
case $coord in
?*)
continent=coord;;
'')
# Ask the user for continent or ocean.
echo >&2 'Please select a continent, ocean, "coord", or "TZ".'
quoted_continents=`
$AWK '
function handle_entry(entry) {
entry = substr(entry, 1, index(entry, "/") - 1)
if (entry == "America")
entry = entry "s"
if (entry ~ /^(Arctic|Atlantic|Indian|Pacific)$/)
entry = entry " Ocean"
printf "'\''%s'\''\n", entry
}
BEGIN { FS = "\t" }
/^[^#]/ {
handle_entry($3)
}
/^#@/ {
ncont = split($2, cont, /,/)
for (ci = 1; ci <= ncont; ci++) {
handle_entry(cont[ci])
}
}
' <"$TZ_ZONE_TABLE" |
sort -u |
tr '\n' ' '
echo ''
`
eval '
doselect '"$quoted_continents"' \
"coord - I want to use geographical coordinates." \
"TZ - I want to specify the timezone using the Posix TZ format."
continent=$select_result
case $continent in
Americas) continent=America;;
*" "*) continent=`expr "$continent" : '\''\([^ ]*\)'\''`
esac
'
esac
case $continent in
TZ)
# Ask the user for a Posix TZ string. Check that it conforms.
while
echo >&2 'Please enter the desired value' \
'of the TZ environment variable.'
echo >&2 'For example, AEST-10 is abbreviated' \
'AEST and is 10 hours'
echo >&2 'ahead (east) of Greenwich,' \
'with no daylight saving time.'
read TZ
$AWK -v TZ="$TZ" 'BEGIN {
tzname = "(<[[:alnum:]+-]{3,}>|[[:alpha:]]{3,})"
time = "(2[0-4]|[0-1]?[0-9])" \
"(:[0-5][0-9](:[0-5][0-9])?)?"
offset = "[-+]?" time
mdate = "M([1-9]|1[0-2])\\.[1-5]\\.[0-6]"
jdate = "((J[1-9]|[0-9]|J?[1-9][0-9]" \
"|J?[1-2][0-9][0-9])|J?3[0-5][0-9]|J?36[0-5])"
datetime = ",(" mdate "|" jdate ")(/" time ")?"
tzpattern = "^(:.*|" tzname offset "(" tzname \
"(" offset ")?(" datetime datetime ")?)?)$"
if (TZ ~ tzpattern) exit 1
exit 0
}'
do
say >&2 "'$TZ' is not a conforming Posix timezone string."
done
TZ_for_date=$TZ;;
*)
case $continent in
coord)
case $coord in
'')
echo >&2 'Please enter coordinates' \
'in ISO 6709 notation.'
echo >&2 'For example, +4042-07403 stands for'
echo >&2 '40 degrees 42 minutes north,' \
'74 degrees 3 minutes west.'
read coord;;
esac
distance_table=`$AWK \
-v coord="$coord" \
-v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \
"$output_distances" <"$TZ_ZONE_TABLE" |
sort -n |
sed "${location_limit}q"
`
regions=`say "$distance_table" | $AWK '
BEGIN { FS = "\t" }
{ print $NF }
'`
echo >&2 'Please select one of the following timezones,' \
echo >&2 'listed roughly in increasing order' \
"of distance from $coord".
doselect $regions
region=$select_result
TZ=`say "$distance_table" | $AWK -v region="$region" '
BEGIN { FS="\t" }
$NF == region { print $4 }
'`
;;
*)
# Get list of names of countries in the continent or ocean.
countries=`$AWK \
-v continent_re="^$continent/" \
-v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \
'
BEGIN { FS = "\t" }
/^#$/ { next }
/^#[^@]/ { next }
{
commentary = $0 ~ /^#@/
if (commentary) {
col1ccs = substr($1, 3)
conts = $2
} else {
col1ccs = $1
conts = $3
}
ncc = split(col1ccs, cc, /,/)
ncont = split(conts, cont, /,/)
for (i = 1; i <= ncc; i++) {
elsewhere = commentary
for (ci = 1; ci <= ncont; ci++) {
if (cont[ci] ~ continent_re) {
if (!cc_seen[cc[i]]++) cc_list[++ccs] = cc[i]
elsewhere = 0
}
}
if (elsewhere) {
for (i = 1; i <= ncc; i++) {
cc_elsewhere[cc[i]] = 1
}
}
}
}
END {
while (getline <TZ_COUNTRY_TABLE) {
if ($0 !~ /^#/) cc_name[$1] = $2
}
for (i = 1; i <= ccs; i++) {
country = cc_list[i]
if (cc_elsewhere[country]) continue
if (cc_name[country]) {
country = cc_name[country]
}
print country
}
}
' <"$TZ_ZONE_TABLE" | sort -f`
# If there's more than one country, ask the user which one.
case $countries in
*"$newline"*)
echo >&2 'Please select a country' \
'whose clocks agree with yours.'
doselect $countries
country=$select_result;;
*)
country=$countries
esac
# Get list of timezones in the country.
regions=`$AWK \
-v country="$country" \
-v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \
'
BEGIN {
FS = "\t"
cc = country
while (getline <TZ_COUNTRY_TABLE) {
if ($0 !~ /^#/ && country == $2) {
cc = $1
break
}
}
}
/^#/ { next }
$1 ~ cc { print $4 }
' <"$TZ_ZONE_TABLE"`
# If there's more than one region, ask the user which one.
case $regions in
*"$newline"*)
echo >&2 'Please select one of the following timezones.'
doselect $regions
region=$select_result;;
*)
region=$regions
esac
# Determine TZ from country and region.
TZ=`$AWK \
-v country="$country" \
-v region="$region" \
-v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \
'
BEGIN {
FS = "\t"
cc = country
while (getline <TZ_COUNTRY_TABLE) {
if ($0 !~ /^#/ && country == $2) {
cc = $1
break
}
}
}
/^#/ { next }
$1 ~ cc && $4 == region { print $3 }
' <"$TZ_ZONE_TABLE"`
esac
# Make sure the corresponding zoneinfo file exists.
TZ_for_date=$TZDIR/$TZ
<"$TZ_for_date" || {
say >&2 "$0: time zone files are not set up correctly"
exit 1
}
esac
# Use the proposed TZ to output the current date relative to UTC.
# Loop until they agree in seconds.
# Give up after 8 unsuccessful tries.
extra_info=
for i in 1 2 3 4 5 6 7 8
do
TZdate=`LANG=C TZ="$TZ_for_date" date`
UTdate=`LANG=C TZ=UTC0 date`
TZsec=`expr "$TZdate" : '.*:\([0-5][0-9]\)'`
UTsec=`expr "$UTdate" : '.*:\([0-5][0-9]\)'`
case $TZsec in
$UTsec)
extra_info="
Selected time is now: $TZdate.
Universal Time is now: $UTdate."
break
esac
done
# Output TZ info and ask the user to confirm.
echo >&2 ""
echo >&2 "The following information has been given:"
echo >&2 ""
case $country%$region%$coord in
?*%?*%) say >&2 " $country$newline $region";;
?*%%) say >&2 " $country";;
%?*%?*) say >&2 " coord $coord$newline $region";;
%%?*) say >&2 " coord $coord";;
*) say >&2 " TZ='$TZ'"
esac
say >&2 ""
say >&2 "Therefore TZ='$TZ' will be used.$extra_info"
say >&2 "Is the above information OK?"
doselect Yes No
ok=$select_result
case $ok in
Yes) break
esac
do coord=
done
case $SHELL in
*csh) file=.login line="setenv TZ '$TZ'";;
*) file=.profile line="TZ='$TZ'; export TZ"
esac
test -t 1 && say >&2 "
You can make this change permanent for yourself by appending the line
$line
to the file '$file' in your home directory; then log out and log in again.
Here is that TZ value again, this time on standard output so that you
can use the $0 command in shell scripts:"
say "$TZ"

1
contrib/tzcode/version Normal file
View File

@ -0,0 +1 @@
2022g

3
contrib/tzcode/version.h Normal file
View File

@ -0,0 +1,3 @@
static char const PKGVERSION[]="(tzcode) ";
static char const TZVERSION[]="2022g";
static char const REPORT_BUGS_TO[]="tz@iana.org";

41
contrib/tzcode/workman.sh Normal file
View File

@ -0,0 +1,41 @@
#! /bin/sh
# Convert manual page troff stdin to formatted .txt stdout.
# This file is in the public domain, so clarified as of
# 2009-05-17 by Arthur David Olson.
if (type nroff && type perl) >/dev/null 2>&1; then
# Tell groff not to emit SGR escape sequences (ANSI color escapes).
GROFF_NO_SGR=1
export GROFF_NO_SGR
echo ".am TH
.hy 0
.na
..
.rm }H
.rm }F" | nroff -man - ${1+"$@"} | perl -ne '
binmode STDIN, '\'':encoding(utf8)'\'';
binmode STDOUT, '\'':encoding(utf8)'\'';
chomp;
s/.\010//g;
s/\s*$//;
if (/^$/) {
$sawblank = 1;
next;
} else {
if ($sawblank && $didprint) {
print "\n";
$sawblank = 0;
}
print "$_\n";
$didprint = 1;
}
'
elif (type mandoc && type col) >/dev/null 2>&1; then
mandoc -man -T ascii "$@" | col -bx
else
echo >&2 "$0: please install nroff and perl, or mandoc and col"
exit 1
fi

231
contrib/tzcode/zdump.8 Normal file
View File

@ -0,0 +1,231 @@
.\" This file is in the public domain, so clarified as of
.\" 2009-05-17 by Arthur David Olson.
.\"
.\" $FreeBSD$
.\"
.Dd December 15, 2022
.Dt ZDUMP 8
.Os
.Sh NAME
.Nm zdump
.Nd timezone dumper
.Sh SYNOPSIS
.Nm
.Op Fl -help
.Op Fl -version
.Op Fl ivV
.Oo
.Fl c
.Op Ar loyear , Ns
.Ar hiyear
.Oc
.Oo
.Fl t
.Op Ar lotime , Ns
.Ar hitime
.Oc
.Op Ar timezone ...
.Sh DESCRIPTION
The
.Nm
program prints the current time in each
.Ar timezone
named on the command line.
.Pp
The following options are available:
.Bl -tag -width indent
.It Fl -version
Output version information and exit.
.It Fl -help
Output short usage message and exit.
.It Fl i
Output a description of time intervals.
For each
.Ar timezone
on the command line, output an interval-format description of the
timezone.
See
.Sx "INTERVAL FORMAT"
below.
.It Fl v
Output a verbose description of time intervals.
For each
.Ar timezone
on the command line,
print the times at the two extreme time values,
the times (if present) at and just beyond the boundaries of years that
.Xr localtime 3
and
.Xr gmtime 3
can represent, and
the times both one second before and exactly at
each detected time discontinuity.
Each line is followed by
.Cm isdst= Ns Ar D
where
.Ar D
is positive, zero, or negative depending on whether
the given time is daylight saving time, standard time,
or an unknown time type, respectively.
Each line is also followed by
.Cm gmtoff= Ns Ar N
if the given local time is known to be
.Ar N
seconds east of Greenwich.
.It Fl V
Like
.Fl v ,
except omit output concerning extreme time and year values.
This generates output that is easier to compare to that of
implementations with different time representations.
.It Fl c Oo Ar loyear , Oc Ns Ar hiyear
Cut off interval output at the given year(s).
Cutoff times are computed using the proleptic Gregorian calendar with year 0
and with Universal Time (UT) ignoring leap seconds.
Cutoffs are at the start of each year, where the lower-bound
timestamp is inclusive and the upper is exclusive; for example,
.Ql "-c 1970,2070"
selects transitions on or after 1970-01-01 00:00:00 UTC
and before 2070-01-01 00:00:00 UTC.
The default cutoff is
.Ql -500,2500 .
.It Fl t Oo Ar lotime , Oc Ns Ar hitime
Cut off interval output at the given time(s),
given in decimal seconds since 1970-01-01 00:00:00
Coordinated Universal Time (UTC).
The
.Ar timezone
determines whether the count includes leap seconds.
As with
.Fl c ,
the cutoff's lower bound is inclusive and its upper bound is exclusive.
.El
.Sh "INTERVAL FORMAT"
The interval format is a compact text representation that is intended
to be both human- and machine-readable.
It consists of an empty line,
then a line
.Dq "TZ=\fIstring\fP"
where
.Ar string
is a double-quoted string giving the timezone, a second line
.Dq "\*- \*- \fIinterval\fP"
describing the time interval before the first transition if any, and
zero or more following lines
.Dq "\fIdate time interval\fP",
one line for each transition time and following interval.
Fields are
separated by single tabs.
.Pp
Dates are in
.Ql "yyyy - mm - dd"
format and times are in 24-hour
.Ql "hh : mm : ss"
format where
.Ql "hh <24" .
Times are in local time immediately after the transition.
A
time interval description consists of a UT offset in signed
.Ql "\(+- hhmmss"
format, a time zone abbreviation, and an isdst flag.
An abbreviation
that equals the UT offset is omitted; other abbreviations are
double-quoted strings unless they consist of one or more alphabetic
characters.
An isdst flag is omitted for standard time, and otherwise
is a decimal integer that is unsigned and positive (typically 1) for
daylight saving time and negative for unknown.
.Pp
In times and in UT offsets with absolute value less than 100 hours,
the seconds are omitted if they are zero, and
the minutes are also omitted if they are also zero.
Positive UT
offsets are east of Greenwich.
The UT offset \*-00 denotes a UT
placeholder in areas where the actual offset is unspecified; by
convention, this occurs when the UT offset is zero and the time zone
abbreviation begins with
.Dq "-"
or is
.Dq "zzz".
.Pp
In double-quoted strings, escape sequences represent unusual
characters.
The escape sequences are \es for space, and \e", \e\e,
\ef, \en, \er, \et, and \ev with their usual meaning in the C
programming language.
E.g., the double-quoted string
\*(lq"CET\es\e"\e\e"\*(rq represents the character sequence \*(lqCET
"\e\*(rq.\""
.Pp
Here is an example of the output, with the leading empty line omitted.
(This example is shown with tab stops set far enough apart so that the
tabbed columns line up.)
.Bd -literal -offset indent
TZ="Pacific/Honolulu"
- - -103126 LMT
1896-01-13 12:01:26 -1030 HST
1933-04-30 03 -0930 HDT 1
1933-05-21 11 -1030 HST
1942-02-09 03 -0930 HWT 1
1945-08-14 13:30 -0930 HPT 1
1945-09-30 01 -1030 HST
1947-06-08 02:30 -10 HST
.Ed
.Pp
Here, local time begins 10 hours, 31 minutes and 26 seconds west of
UT, and is a standard time abbreviated LMT.
Immediately after the
first transition, the date is 1896-01-13 and the time is 12:01:26, and
the following time interval is 10.5 hours west of UT, a standard time
abbreviated HST.
Immediately after the second transition, the date is
1933-04-30 and the time is 03:00:00 and the following time interval is
9.5 hours west of UT, is abbreviated HDT, and is daylight saving time.
Immediately after the last transition the date is 1947-06-08 and the
time is 02:30:00, and the following time interval is 10 hours west of
UT, a standard time abbreviated HST.
.Pp
Here are excerpts from another example:
.Bd -literal -offset indent
TZ="Europe/Astrakhan"
- - +031212 LMT
1924-04-30 23:47:48 +03
1930-06-21 01 +04
1981-04-01 01 +05 1
1981-09-30 23 +04
\&...
2014-10-26 01 +03
2016-03-27 03 +04
.Ed
.Pp
This time zone is east of UT, so its UT offsets are positive.
Also,
many of its time zone abbreviations are omitted since they duplicate
the text of the UT offset.
.Sh LIMITATIONS
Time discontinuities are found by sampling the results returned by
.Xr localtime 3
at twelve-hour intervals.
This works in all real-world cases;
one can construct artificial time zones for which this fails.
.Pp
In the
.Fl v
and
.Fl V
output,
.Dq "UT"
denotes the value returned by
.Xr gmtime 3 ,
which uses UTC for modern timestamps and some other UT flavor for
timestamps that predate the introduction of UTC.
No attempt is currently made to have the output use
.Dq "UTC"
for newer and
.Dq "UT"
for older timestamps, partly because the exact date of the
introduction of UTC is problematic.
.Sh SEE ALSO
.Xr tzfile 5 ,
.Xr zic 8

1257
contrib/tzcode/zdump.c Normal file

File diff suppressed because it is too large Load Diff

856
contrib/tzcode/zic.8 Normal file
View File

@ -0,0 +1,856 @@
.\" This file is in the public domain, so clarified as of
.\" 2009-05-17 by Arthur David Olson.
.\"
.\" $FreeBSD$
.\"
.Dd December 15, 2022
.Dt ZIC 8
.Os
.Sh NAME
.Nm zic
.Nd timezone compiler
.Sh SYNOPSIS
.Nm
.Op Fl -help
.Op Fl -version
.Op Fl Dsv
.Op Fl b Ar slim | fat
.Op Fl d Ar directory
.Op Fl g Ar gid
.Op Fl l Ar localtime
.Op Fl L Ar leapseconds
.Op Fl m Ar mode
.Op Fl p Ar posixrules
.Oo
.Fl r
.Op @ Ns Ar lo Ns
.Op /@ Ns Ar hi
.Oc
.Op Fl R @ Ns Ar hi
.Op Fl t Ar localtime-link
.Op Fl u Ar uid
.Op Ar filename ...
.Sh DESCRIPTION
The
.Nm
program reads text from the file(s) named on the command line
and creates the timezone information format (TZif) files
specified in this input.
If a
.Ar filename
is
.Dq "-" ,
standard input is read.
.Pp
The following options are available:
.Bl -tag -width indent
.It Fl -version
Output version information and exit.
.It Fl -help
Output short usage message and exit.
.It Fl b Ar bloat
Output backward-compatibility data as specified by
.Ar bloat .
If
.Ar bloat
is
.Cm fat ,
generate additional data entries that work around potential bugs or
incompatibilities in older software, such as software that mishandles
the 64-bit generated data.
If
.Ar bloat
is
.Cm slim ,
keep the output files small; this can help check for the bugs
and incompatibilities.
The default is
.Cm slim ,
as software that mishandles 64-bit data typically
mishandles timestamps after the year 2038 anyway.
Also see the
.Fl r
option for another way to alter output size.
.It Fl d Ar directory
Create time conversion information files in the named directory rather than
in the standard directory named below.
.It Fl l Ar timezone
Use
.Ar timezone
as local time.
The
.Nm
utility
will act as if the input contained a link line of the form
.Bd -literal -offset indent
Link timezone localtime
.Ed
.Pp
If
.Ar timezone
is
.Ql - ,
any already-existing link is removed.
.It Fl L Ar filename
Read leap second information from the file with the given name.
If this option is not used,
no leap second information appears in output files.
.It Fl p Ar timezone
Use
.Ar timezone 's
rules when handling nonstandard
TZ strings like
.Dq "EET\-2EEST"
that lack transition rules.
The
.Nm
utility
will act as if the input contained a link line of the form
.Bd -literal -offset indent
Link \fItimezone\fP posixrules
.Ed
.Pp
This feature is obsolete and poorly supported.
Among other things it should not be used for timestamps after the year 2037,
and it should not be combined with
.Fl b Cm slim
if
.Ar timezone 's
transitions are at standard time or Universal Time (UT) instead of local time.
.Pp
If
.Ar timezone
is
.Ql - ,
any already-existing link is removed.
.It Fl r Oo @ Ns Ar lo Oc Ns Oo /@ Ns Ar hi Oc
Limit the applicability of output files
to timestamps in the range from
.Ar lo
(inclusive) to
.Ar hi
(exclusive), where
.Ar lo
and
.Ar hi
are possibly-signed decimal counts of seconds since the Epoch
(1970-01-01 00:00:00 UTC).
Omitted counts default to extreme values.
The output files use UT offset 0 and abbreviation
.Dq "\-00"
in place of the omitted timestamp data.
For example,
.Fl r @0
omits data intended for negative timestamps (i.e., before the Epoch), and
.Fl r @0/@2147483648
outputs data intended only for nonnegative timestamps that fit into
31-bit signed integers.
Although this option typically reduces the output file's size,
the size can increase due to the need to represent the timestamp range
boundaries, particularly if
.Ar hi
causes a TZif file to contain explicit entries for
.Em pre-
.Ar hi
transitions rather than concisely representing them
with an extended POSIX TZ string.
Also see the
.Fl b Cm slim
option for another way to shrink output size.
.It Fl R @ Ns Ar hi
Generate redundant trailing explicit transitions for timestamps
that occur less than
.Ar hi
seconds since the Epoch, even though the transitions could be
more concisely represented via the extended POSIX TZ string.
This option does not affect the represented timestamps.
Although it accommodates nonstandard TZif readers
that ignore the extended POSIX TZ string,
it increases the size of the altered output files.
.It Fl t Ar file
When creating local time information, put the configuration link in
the named file rather than in the standard location.
.It Fl v
Be more verbose, and complain about the following situations:
.Bl -bullet
.It
The input specifies a link to a link,
something not supported by some older parsers, including
.Nm
itself through release 2022e.
.It
A year that appears in a data file is outside the range
of representable years.
.It
A time of 24:00 or more appears in the input.
Pre-1998 versions of
.Nm
prohibit 24:00, and pre-2007 versions prohibit times greater than 24:00.
.It
A rule goes past the start or end of the month.
Pre-2004 versions of
.Nm
prohibit this.
.It
A time zone abbreviation uses a
.Ql %z
format.
Pre-2015 versions of
.Nm
do not support this.
.It
A timestamp contains fractional seconds.
Pre-2018 versions of
.Nm
do not support this.
.It
The input contains abbreviations that are mishandled by pre-2018 versions of
.Nm
due to a longstanding coding bug.
These abbreviations include
.Dq L
for
.Dq Link ,
.Dq mi
for
.Dq min ,
.Dq Sa
for
.Dq Sat ,
and
.Dq Su
for
.Dq Sun .
.It
The output file does not contain all the information about the
long-term future of a timezone, because the future cannot be summarized as
an extended POSIX TZ string.
For example, as of 2019 this problem
occurs for Iran's daylight-saving rules for the predicted future, as
these rules are based on the Iranian calendar, which cannot be
represented.
.It
The output contains data that may not be handled properly by client
code designed for older
.Nm
output formats.
These compatibility issues affect only timestamps
before 1970 or after the start of 2038.
.It
The output contains a truncated leap second table,
which can cause some older TZif readers to misbehave.
This can occur if the
.Fl L
option is used, and either an Expires line is present or
the
.Fl r
option is also used.
.It
The output file contains more than 1200 transitions,
which may be mishandled by some clients.
The current reference client supports at most 2000 transitions;
pre-2014 versions of the reference client support at most 1200
transitions.
.It
A time zone abbreviation has fewer than 3 or more than 6 characters.
POSIX requires at least 3, and requires implementations to support
at least 6.
.It
An output file name contains a byte that is not an ASCII letter,
.Dq "\-" ,
.Dq "/" ,
or
.Dq "_" ;
or it contains a file name component that contains more than 14 bytes
or that starts with
.Dq "\-" .
.El
.El
.RE
.Sh FILES
Input files use the format described in this section; output files use
.Xr tzfile 5
format.
.Pp
Input files should be text files, that is, they should be a series of
zero or more lines, each ending in a newline byte and containing at
most 2048 bytes counting the newline, and without any NUL bytes.
The input text's encoding
is typically UTF-8 or ASCII; it should have a unibyte representation
for the POSIX Portable Character Set (PPCS)
\*<https://pubs\*:.opengroup\*:.org/\*:onlinepubs/\*:9699919799/\*:basedefs/\*:V1_chap06\*:.html\*>
and the encoding's non-unibyte characters should consist entirely of
non-PPCS bytes.
Non-PPCS characters typically occur only in comments:
although output file names and time zone abbreviations can contain
nearly any character, other software will work better if these are
limited to the restricted syntax described under the
.Fl v
option.
.Pp
Input lines are made up of fields.
Fields are separated from one another by one or more white space characters.
The white space characters are space, form feed, carriage return, newline,
tab, and vertical tab.
Leading and trailing white space on input lines is ignored.
An unquoted sharp character (\(sh) in the input introduces a comment which extends
to the end of the line the sharp character appears on.
White space characters and sharp characters may be enclosed in double quotes
(\(dq) if they're to be used as part of a field.
Any line that is blank (after comment stripping) is ignored.
Nonblank lines are expected to be of one of three types:
rule lines, zone lines, and link lines.
.Pp
Names must be in English and are case insensitive.
They appear in several contexts, and include month and weekday names
and keywords such as
.Dq "maximum" ,
.Dq "only" ,
.Dq "Rolling" ,
and
.Dq "Zone" .
A name can be abbreviated by omitting all but an initial prefix; any
abbreviation must be unambiguous in context.
.Pp
A rule line has the form
.Bd -literal -offset indent
Rule NAME FROM TO \- IN ON AT SAVE LETTER/S
.Ed
.Pp
For example:
.Bd -literal -offset indent
Rule US 1967 1973 \- Apr lastSun 2:00w 1:00d D
.Ed
.Pp
The fields that make up a rule line are:
.Bl -tag -width "LETTER/S"
.It NAME
Gives the name of the rule set that contains this line.
The name must start with a character that is neither
an ASCII digit nor
.Dq \-
nor
.Dq + .
To allow for future extensions,
an unquoted name should not contain characters from the set
.Dq Ql "!$%&'()*,/:;<=>?@[\]^`{|}~" .
.It FROM
Gives the first year in which the rule applies.
Any signed integer year can be supplied; the proleptic Gregorian calendar
is assumed, with year 0 preceding year 1.
The word
.Cm minimum
(or an abbreviation) means the indefinite past.
The word
.Cm maximum
(or an abbreviation) means the indefinite future.
Rules can describe times that are not representable as time values,
with the unrepresentable times ignored; this allows rules to be portable
among hosts with differing time value types.
.It TO
Gives the final year in which the rule applies.
In addition to
.Cm minimum
and
.Cm maximum
(as above),
the word
.Cm only
(or an abbreviation)
may be used to repeat the value of the
.Ar FROM
field.
.It \-
Is a reserved field and should always contain
.Ql \-
for compatibility with older versions of
.Nm .
It was previously known as the
.Ar TYPE
field, which could contain values to allow a
separate script to further restrict in which
.Dq types
of years the rule would apply.
.It IN
Names the month in which the rule takes effect.
Month names may be abbreviated.
.It ON
Gives the day on which the rule takes effect.
Recognized forms include:
.Bl -tag -compact -width "Sun<=25"
.It 5
the fifth of the month
.It lastSun
the last Sunday in the month
.It lastMon
the last Monday in the month
.It Sun>=8
first Sunday on or after the eighth
.It Sun<=25
last Sunday on or before the 25th
.El
.Pp
A weekday name (e.g.,
.Ql "Sunday" )
or a weekday name preceded by
.Dq "last"
(e.g.,
.Ql "lastSunday" )
may be abbreviated or spelled out in full.
There must be no white space characters within the
.Ar ON
field.
The
.Dq <=
and
.Dq >=
constructs can result in a day in the neighboring month;
for example, the IN-ON combination
.Dq "Oct Sun>=31"
stands for the first Sunday on or after October 31,
even if that Sunday occurs in November.
.It AT
Gives the time of day at which the rule takes effect,
relative to 00:00, the start of a calendar day.
Recognized forms include:
.Bl -tag -compact -width "00:19:32.13"
.It 2
time in hours
.It 2:00
time in hours and minutes
.It 01:28:14
time in hours, minutes, and seconds
.It 00:19:32.13
time with fractional seconds
.It 12:00
midday, 12 hours after 00:00
.It 15:00
3 PM, 15 hours after 00:00
.It 24:00
end of day, 24 hours after 00:00
.It 260:00
260 hours after 00:00
.It \-2:30
2.5 hours before 00:00
.It \-
equivalent to 0
.El
.Pp
Although
.Nm
rounds times to the nearest integer second
(breaking ties to the even integer), the fractions may be useful
to other applications requiring greater precision.
The source format does not specify any maximum precision.
Any of these forms may be followed by the letter
.Ql w
if the given time is local or
.Dq "wall clock"
time,
.Ql s
if the given time is standard time without any adjustment for daylight saving,
or
.Ql u
(or
.Ql g
or
.Ql z )
if the given time is universal time;
in the absence of an indicator,
local (wall clock) time is assumed.
These forms ignore leap seconds; for example,
if a leap second occurs at 00:59:60 local time,
.Ql "1:00"
stands for 3601 seconds after local midnight instead of the usual 3600 seconds.
The intent is that a rule line describes the instants when a
clock/calendar set to the type of time specified in the
.Ar AT
field would show the specified date and time of day.
.It SAVE
Gives the amount of time to be added to local standard time when the rule is in
effect, and whether the resulting time is standard or daylight saving.
This field has the same format as the
.Ar AT
field
except with a different set of suffix letters:
.Ql s
for standard time and
.Ql d
for daylight saving time.
The suffix letter is typically omitted, and defaults to
.Ql s
if the offset is zero and to
.Ql d
otherwise.
Negative offsets are allowed; in Ireland, for example, daylight saving
time is observed in winter and has a negative offset relative to
Irish Standard Time.
The offset is merely added to standard time; for example,
.Nm
does not distinguish a 10:30 standard time plus an 0:30
.Ar SAVE
from a 10:00 standard time plus a 1:00
.Ar SAVE .
.It LETTER/S
Gives the
.Dq "variable part"
(for example, the
.Dq "S"
or
.Dq "D"
in
.Dq "EST"
or
.Dq "EDT" )
of time zone abbreviations to be used when this rule is in effect.
If this field is
.Ql \- ,
the variable part is null.
.El
.Pp
A zone line has the form
.Bd -literal -offset indent
Zone NAME STDOFF RULES FORMAT [UNTIL]
.Ed
.Pp
For example:
.Bd -literal -offset indent
Zone Asia/Amman 2:00 Jordan EE%sT 2017 Oct 27 01:00
.Ed
.Pp
The fields that make up a zone line are:
.Bl -tag -width "STDOFF"
.It NAME
The name of the timezone.
This is the name used in creating the time conversion information file for the
timezone.
It should not contain a file name component
.Dq ".\&"
or
.Dq ".." ;
a file name component is a maximal substring that does not contain
.Dq "/" .
.It STDOFF
The amount of time to add to UT to get standard time,
without any adjustment for daylight saving.
This field has the same format as the
.Ar AT
and
.Ar SAVE
fields of rule lines, except without suffix letters;
begin the field with a minus sign if time must be subtracted from UT.
.It RULES
The name of the rules that apply in the timezone or,
alternatively, a field in the same format as a rule-line SAVE column,
giving the amount of time to be added to local standard time
and whether the resulting time is standard or daylight saving.
If this field is
.Ql \-
then standard time always applies.
When an amount of time is given, only the sum of standard time and
this amount matters.
.It FORMAT
The format for time zone abbreviations.
The pair of characters
.Ql %s
is used to show where the
.Dq "variable part"
of the time zone abbreviation goes.
Alternatively, a format can use the pair of characters
.Ql %z
to stand for the UT offset in the form
.Ar \(+- hh ,
.Ar \(+- hhmm ,
or
.Ar \(+- hhmmss ,
using the shortest form that does not lose information, where
.Ar hh ,
.Ar mm ,
and
.Ar ss
are the hours, minutes, and seconds east (+) or west (\-) of UT.
Alternatively,
a slash (/)
separates standard and daylight abbreviations.
To conform to POSIX, a time zone abbreviation should contain only
alphanumeric ASCII characters,
.Ql "+"
and
.Ql "\-".
By convention, the time zone abbreviation
.Ql "\-00"
is a placeholder that means local time is unspecified.
.It UNTIL
The time at which the UT offset or the rule(s) change for a location.
It takes the form of one to four fields
.Ar YEAR Op Ar MONTH Op Ar DAY Op Ar TIME .
If this is specified,
the time zone information is generated from the given UT offset
and rule change until the time specified, which is interpreted using
the rules in effect just before the transition.
The month, day, and time of day have the same format as the
.Ar IN ,
.Ar ON ,
and
.Ar AT
fields of a rule; trailing fields can be omitted, and default to the
earliest possible value for the missing fields.
.IP
The next line must be a
.Dq "continuation"
line; this has the same form as a zone line except that the
string
.Dq "Zone"
and the name are omitted, as the continuation line will
place information starting at the time specified as the
.Dq "until"
information in the previous line in the file used by the previous line.
Continuation lines may contain
.Dq "until"
information, just as zone lines do, indicating that the next line is a further
continuation.
.El
.Pp
If a zone changes at the same instant that a rule would otherwise take
effect in the earlier zone or continuation line, the rule is ignored.
A zone or continuation line
.Ar L
with a named rule set starts with standard time by default:
that is, any of
.Ar L 's
timestamps preceding
.Ar L 's
earliest rule use the rule in effect after
.Ar L 's
first transition into standard time.
In a single zone it is an error if two rules take effect at the same
instant, or if two zone changes take effect at the same instant.
.Pp
If a continuation line subtracts
.Ar N
seconds from the UT offset after a transition that would be
interpreted to be later if using the continuation line's UT offset and
rules, the
.Dq "until"
time of the previous zone or continuation line is interpreted
according to the continuation line's UT offset and rules, and any rule
that would otherwise take effect in the next
.Ar N
seconds is instead assumed to take effect simultaneously.
For example:
.Bd -literal -offset indent
# Rule NAME FROM TO \*- IN ON AT SAVE LETTER/S
Rule US 1967 2006 - Oct lastSun 2:00 0 S
Rule US 1967 1973 - Apr lastSun 2:00 1:00 D
# Zone\0\0NAME STDOFF RULES FORMAT [UNTIL]
Zone\0\0America/Menominee \*-5:00 \*- EST 1973 Apr 29 2:00
\*-6:00 US C%sT
.Ed
Here, an incorrect reading would be there were two clock changes on 1973-04-29,
the first from 02:00 EST (\-05) to 01:00 CST (\-06),
and the second an hour later from 02:00 CST (\-06) to 03:00 CDT (\-05).
However,
.Nm
interprets this more sensibly as a single transition from 02:00 CST (\-05) to
02:00 CDT (\-05).
.Pp
A link line has the form
.Bd -literal -offset indent
Link TARGET LINK-NAME
.Ed
.Pp
For example:
.Bd -literal -offset indent
Link Europe/Istanbul Asia/Istanbul
.Ed
.Pp
The
.Ar TARGET
field should appear as the
.Ar NAME
field in some zone line or as the
.Ar LINK-NAME
field in some link line.
The
.Ar LINK-NAME
field is used as an alternative name for that zone;
it has the same syntax as a zone line's
.Ar NAME
field.
Links can chain together, although the behavior is unspecified if a
chain of one or more links does not terminate in a Zone name.
A link line can appear before the line that defines the link target.
For example:
.Bd -literal -offset indent
Link Greenwich G_M_T
Link Etc/GMT Greenwich
Zone Etc/GMT\0\00\0\0\-\0\0GMT
.Ed
.Pp
The two links are chained together, and G_M_T, Greenwich, and Etc/GMT
all name the same zone.
.Pp
Except for continuation lines,
lines may appear in any order in the input.
However, the behavior is unspecified if multiple zone or link lines
define the same name.
.Pp
The file that describes leap seconds can have leap lines and an
expiration line.
Leap lines have the following form:
.Bd -literal -offset indent
Leap YEAR MONTH DAY HH:MM:SS CORR R/S
.Ed
.Pp
For example:
.Bd -literal -offset indent
Leap 2016 Dec 31 23:59:60 + S
.Ed
.Pp
The
.Ar YEAR ,
.Ar MONTH ,
.Ar DAY ,
and
.Ar HH:MM:SS
fields tell when the leap second happened.
The
.Ar CORR
field
should be
.Ql "+"
if a second was added
or
.Ql "\-"
if a second was skipped.
The
.Ar R/S
field
should be (an abbreviation of)
.Dq "Stationary"
if the leap second time given by the other fields should be interpreted as UTC
or
(an abbreviation of)
.Dq "Rolling"
if the leap second time given by the other fields should be interpreted as
local (wall clock) time.
.Pp
Rolling leap seconds were implemented back when it was not
clear whether common practice was rolling or stationary,
with concerns that one would see
Times Square ball drops where there'd be a
.Dq "3... 2... 1... leap... Happy New Year"
countdown, placing the leap second at
midnight New York time rather than midnight UTC.
However, this countdown style does not seem to have caught on,
which means rolling leap seconds are not used in practice;
also, they are not supported if the
.Fl r
option is used.
.Pp
The expiration line, if present, has the form:
.Bd -literal -offset indent
Expires YEAR MONTH DAY HH:MM:SS
.Ed
.Pp
For example:
.Bd -literal -offset indent
Expires 2020 Dec 28 00:00:00
.Ed
.Pp
The
.Ar YEAR ,
.Ar MONTH ,
.Ar DAY ,
and
.Ar HH:MM:SS
fields give the expiration timestamp in UTC for the leap second table.
.Sh "EXTENDED EXAMPLE"
Here is an extended example of
.Nm
input, intended to illustrate many of its features.
.Bd -literal -offset indent
# Rule NAME FROM TO \- IN ON AT SAVE LETTER/S
Rule Swiss 1941 1942 \- May Mon>=1 1:00 1:00 S
Rule Swiss 1941 1942 \- Oct Mon>=1 2:00 0 \-
Rule EU 1977 1980 \- Apr Sun>=1 1:00u 1:00 S
Rule EU 1977 only \- Sep lastSun 1:00u 0 \-
Rule EU 1978 only \- Oct 1 1:00u 0 \-
Rule EU 1979 1995 \- Sep lastSun 1:00u 0 \-
Rule EU 1981 max \- Mar lastSun 1:00u 1:00 S
Rule EU 1996 max \- Oct lastSun 1:00u 0 \-
# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Europe/Zurich 0:34:08 \- LMT 1853 Jul 16
0:29:45.50 \- BMT 1894 Jun
1:00 Swiss CE%sT 1981
1:00 EU CE%sT
Link Europe/Zurich Europe/Vaduz
.Ed
.Pp
In this example, the EU rules are for the European Union
and for its predecessor organization, the European Communities.
The timezone is named Europe/Zurich and it has the alias Europe/Vaduz.
This example says that Zurich was 34 minutes and 8
seconds east of UT until 1853-07-16 at 00:00, when the legal offset
was changed to
7\(de26\(fm22.50\(sd,
which works out to 0:29:45.50;
.Nm
treats this by rounding it to 0:29:46.
After 1894-06-01 at 00:00 the UT offset became one hour
and Swiss daylight saving rules (defined with lines beginning with
.Dq "Rule Swiss")
apply.
From 1981 to the present, EU daylight saving rules have
applied, and the UTC offset has remained at one hour.
.Pp
In 1941 and 1942, daylight saving time applied from the first Monday
in May at 01:00 to the first Monday in October at 02:00.
The pre-1981 EU daylight-saving rules have no effect
here, but are included for completeness.
Since 1981, daylight
saving has begun on the last Sunday in March at 01:00 UTC.
Until 1995 it ended the last Sunday in September at 01:00 UTC,
but this changed to the last Sunday in October starting in 1996.
.Pp
For purposes of display,
.Dq "LMT"
and
.Dq "BMT"
were initially used, respectively.
Since
Swiss rules and later EU rules were applied, the time zone abbreviation
has been CET for standard time and CEST for daylight saving
time.
.Sh FILES
.Bl -tag -width "/usr/share/zoneinfo"
.It Pa /etc/localtime
Default local timezone file.
.It Pa /usr/share/zoneinfo
Default timezone information directory.
.El
.Sh NOTES
For areas with more than two types of local time,
you may need to use local standard time in the
.Ar AT
field of the earliest transition time's rule to ensure that
the earliest transition time recorded in the compiled file is correct.
.Pp
If,
for a particular timezone,
a clock advance caused by the start of daylight saving
coincides with and is equal to
a clock retreat caused by a change in UT offset,
.Nm
produces a single transition to daylight saving at the new UT offset
without any change in local (wall clock) time.
To get separate transitions
use multiple zone continuation lines
specifying transition instants using universal time.
.Sh SEE ALSO
.Xr tzfile 5 ,
.Xr zdump 8

4051
contrib/tzcode/zic.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,88 +0,0 @@
@(#)README 8.3
This file is in the public domain, so clarified as of
2009-05-17 by Arthur David Olson.
$FreeBSD$
"What time is it?" -- Richard Deacon as The King
"Any time you want it to be." -- Frank Baxter as The Scientist
(from the Bell System film "About Time")
The 1989 update of the time zone package featured
* POSIXization (including interpretation of POSIX-style TZ environment
variables, provided by Guy Harris),
* ANSIfication (including versions of "mktime" and "difftime"),
* SVIDulation (an "altzone" variable)
* MACHination (the "gtime" function)
* corrections to some time zone data (including corrections to the rules
for Great Britain and New Zealand)
* reference data from the United States Naval Observatory for folks who
want to do additional time zones
* and the 1989 data for Saudi Arabia.
(Since this code will be treated as "part of the implementation" in some places
and as "part of the application" in others, there's no good way to name
functions, such as timegm, that are not part of the proposed ANSI C standard;
such functions have kept their old, underscore-free names in this update.)
And the "dysize" function has disappeared; it was present to allow compilation
of the "date" command on old BSD systems, and a version of "date" is now
provided in the package. The "date" command is not created when you "make all"
since it may lack options provided by the version distributed with your
operating system, or may not interact with the system in the same way the
native version does.
Since POSIX frowns on correct leap second handling, the default behavior of
the "zic" command (in the absence of a "-L" option) has been changed to omit
leap second information from its output files.
Here is a recipe for acquiring, building, installing, and testing the
tz distribution on a GNU/Linux or similar host.
mkdir tz
cd tz
wget 'ftp://elsie.nci.nih.gov/pub/tz*.tar.gz'
gzip -dc tzcode*.tar.gz | tar -xf -
gzip -dc tzdata*.tar.gz | tar -xf -
Be sure to read the comments in "Makefile" and make any changes needed
to make things right for your system, especially if you are using some
platform other than GNU/Linux. Then run the following commands,
substituting your desired installation directory for "$HOME/tzdir":
make TOPDIR=$HOME/tzdir install
$HOME/tzdir/etc/zdump -v America/Los_Angeles
To use the new functions, use a "-ltz" option when compiling or linking.
Historical local time information has been included here to:
* provide a compendium of data about the history of civil time
that is useful even if the data are not 100% accurate;
* give an idea of the variety of local time rules that have
existed in the past and thus an idea of the variety that may be
expected in the future;
* provide a test of the generality of the local time rule description
system.
The information in the time zone data files is by no means authoritative;
the files currently do not even attempt to cover all time stamps before
1970, and there are undoubtedly errors even for time stamps since 1970.
If you know that the rules are different from those in a file, by all means
feel free to change file (and please send the changed version to
tz@elsie.nci.nih.gov for use in the future). Europeans take note!
Thanks to these Timezone Caballeros who've made major contributions to the
time conversion package: Keith Bostic; Bob Devine; Paul Eggert; Robert Elz;
Guy Harris; Mark Horton; John Mackin; and Bradley White. Thanks also to
Michael Bloom, Art Neilson, Stephen Prince, John Sovereign, and Frank Wales
for testing work, and to Gwillim Law for checking local mean time data.
None of them are responsible for remaining errors.
Look in the ~ftp/pub directory of elsie.nci.nih.gov
for updated versions of these files.
Please send comments or information to tz@elsie.nci.nih.gov.

View File

@ -1,570 +0,0 @@
@(#)Theory 8.4
This file is in the public domain, so clarified as of
2009-05-17 by Arthur David Olson.
$FreeBSD$
----- Outline -----
Time and date functions
Names of time zone regions
Time zone abbreviations
Calendrical issues
Time and time zones on Mars
----- Time and date functions -----
These time and date functions are upwards compatible with POSIX,
an international standard for UNIX-like systems.
As of this writing, the current edition of POSIX is:
Standard for Information technology
-- Portable Operating System Interface (POSIX (R))
-- System Interfaces
IEEE Std 1003.1, 2004 Edition
<http://www.opengroup.org/online-pubs?DOC=7999959899>
<http://www.opengroup.org/pubs/catalog/t041.htm>
POSIX has the following properties and limitations.
* In POSIX, time display in a process is controlled by the
environment variable TZ. Unfortunately, the POSIX TZ string takes
a form that is hard to describe and is error-prone in practice.
Also, POSIX TZ strings can't deal with other (for example, Israeli)
daylight saving time rules, or situations where more than two
time zone abbreviations are used in an area.
The POSIX TZ string takes the following form:
stdoffset[dst[offset],date[/time],date[/time]]
where:
std and dst
are 3 or more characters specifying the standard
and daylight saving time (DST) zone names.
Starting with POSIX.1-2001, std and dst may also be
in a quoted form like "<UTC+10>"; this allows
"+" and "-" in the names.
offset
is of the form `[-]hh:[mm[:ss]]' and specifies the
offset west of UTC. The default DST offset is one hour
ahead of standard time.
date[/time],date[/time]
specifies the beginning and end of DST. If this is absent,
the system supplies its own rules for DST, and these can
differ from year to year; typically US DST rules are used.
time
takes the form `hh:[mm[:ss]]' and defaults to 02:00.
date
takes one of the following forms:
Jn (1<=n<=365)
origin-1 day number not counting February 29
n (0<=n<=365)
origin-0 day number counting February 29 if present
Mm.n.d (0[Sunday]<=d<=6[Saturday], 1<=n<=5, 1<=m<=12)
for the dth day of week n of month m of the year,
where week 1 is the first week in which day d appears,
and `5' stands for the last week in which day d appears
(which may be either the 4th or 5th week).
Here is an example POSIX TZ string, for US Pacific time using rules
appropriate from 1987 through 2006:
TZ='PST8PDT,M4.1.0/02:00,M10.5.0/02:00'
This POSIX TZ string is hard to remember, and mishandles time stamps
before 1987 and after 2006. With this package you can use this
instead:
TZ='America/Los_Angeles'
* POSIX does not define the exact meaning of TZ values like "EST5EDT".
Typically the current US DST rules are used to interpret such values,
but this means that the US DST rules are compiled into each program
that does time conversion. This means that when US time conversion
rules change (as in the United States in 1987), all programs that
do time conversion must be recompiled to ensure proper results.
* In POSIX, there's no tamper-proof way for a process to learn the
system's best idea of local wall clock. (This is important for
applications that an administrator wants used only at certain times--
without regard to whether the user has fiddled the "TZ" environment
variable. While an administrator can "do everything in UTC" to get
around the problem, doing so is inconvenient and precludes handling
daylight saving time shifts--as might be required to limit phone
calls to off-peak hours.)
* POSIX requires that systems ignore leap seconds.
These are the extensions that have been made to the POSIX functions:
* The "TZ" environment variable is used in generating the name of a file
from which time zone information is read (or is interpreted a la
POSIX); "TZ" is no longer constrained to be a three-letter time zone
name followed by a number of hours and an optional three-letter
daylight time zone name. The daylight saving time rules to be used
for a particular time zone are encoded in the time zone file;
the format of the file allows U.S., Australian, and other rules to be
encoded, and allows for situations where more than two time zone
abbreviations are used.
It was recognized that allowing the "TZ" environment variable to
take on values such as "America/New_York" might cause "old" programs
(that expect "TZ" to have a certain form) to operate incorrectly;
consideration was given to using some other environment variable
(for example, "TIMEZONE") to hold the string used to generate the
time zone information file name. In the end, however, it was decided
to continue using "TZ": it is widely used for time zone purposes;
separately maintaining both "TZ" and "TIMEZONE" seemed a nuisance;
and systems where "new" forms of "TZ" might cause problems can simply
use TZ values such as "EST5EDT" which can be used both by
"new" programs (a la POSIX) and "old" programs (as zone names and
offsets).
* To handle places where more than two time zone abbreviations are used,
the functions "localtime" and "gmtime" set tzname[tmp->tm_isdst]
(where "tmp" is the value the function returns) to the time zone
abbreviation to be used. This differs from POSIX, where the elements
of tzname are only changed as a result of calls to tzset.
* Since the "TZ" environment variable can now be used to control time
conversion, the "daylight" and "timezone" variables are no longer
needed. (These variables are defined and set by "tzset"; however, their
values will not be used by "localtime.")
* The "localtime" function has been set up to deliver correct results
for near-minimum or near-maximum time_t values. (A comment in the
source code tells how to get compatibly wrong results).
* A function "tzsetwall" has been added to arrange for the system's
best approximation to local wall clock time to be delivered by
subsequent calls to "localtime." Source code for portable
applications that "must" run on local wall clock time should call
"tzsetwall();" if such code is moved to "old" systems that don't
provide tzsetwall, you won't be able to generate an executable program.
(These time zone functions also arrange for local wall clock time to be
used if tzset is called--directly or indirectly--and there's no "TZ"
environment variable; portable applications should not, however, rely
on this behavior since it's not the way SVR2 systems behave.)
* These functions can account for leap seconds, thanks to Bradley White.
Points of interest to folks with other systems:
* This package is already part of many POSIX-compliant hosts,
including BSD, HP, Linux, Network Appliance, SCO, SGI, and Sun.
On such hosts, the primary use of this package
is to update obsolete time zone rule tables.
To do this, you may need to compile the time zone compiler
`zic' supplied with this package instead of using the system `zic',
since the format of zic's input changed slightly in late 1994,
and many vendors still do not support the new input format.
* The UNIX Version 7 "timezone" function is not present in this package;
it's impossible to reliably map timezone's arguments (a "minutes west
of GMT" value and a "daylight saving time in effect" flag) to a
time zone abbreviation, and we refuse to guess.
Programs that in the past used the timezone function may now examine
tzname[localtime(&clock)->tm_isdst] to learn the correct time
zone abbreviation to use. Alternatively, use
localtime(&clock)->tm_zone if this has been enabled.
* The 4.2BSD gettimeofday function is not used in this package.
This formerly let users obtain the current UTC offset and DST flag,
but this functionality was removed in later versions of BSD.
* In SVR2, time conversion fails for near-minimum or near-maximum
time_t values when doing conversions for places that don't use UTC.
This package takes care to do these conversions correctly.
The functions that are conditionally compiled if STD_INSPIRED is defined
should, at this point, be looked on primarily as food for thought. They are
not in any sense "standard compatible"--some are not, in fact, specified in
*any* standard. They do, however, represent responses of various authors to
standardization proposals.
Other time conversion proposals, in particular the one developed by folks at
Hewlett Packard, offer a wider selection of functions that provide capabilities
beyond those provided here. The absence of such functions from this package
is not meant to discourage the development, standardization, or use of such
functions. Rather, their absence reflects the decision to make this package
contain valid extensions to POSIX, to ensure its broad acceptability. If
more powerful time conversion functions can be standardized, so much the
better.
----- Names of time zone rule files -----
The time zone rule file naming conventions attempt to strike a balance
among the following goals:
* Uniquely identify every national region where clocks have all
agreed since 1970. This is essential for the intended use: static
clocks keeping local civil time.
* Indicate to humans as to where that region is. This simplifes use.
* Be robust in the presence of political changes. This reduces the
number of updates and backward-compatibility hacks. For example,
names of countries are ordinarily not used, to avoid
incompatibilities when countries change their name
(e.g. Zaire->Congo) or when locations change countries
(e.g. Hong Kong from UK colony to China).
* Be portable to a wide variety of implementations.
This promotes use of the technology.
* Use a consistent naming convention over the entire world.
This simplifies both use and maintenance.
This naming convention is not intended for use by inexperienced users
to select TZ values by themselves (though they can of course examine
and reuse existing settings). Distributors should provide
documentation and/or a simple selection interface that explains the
names; see the 'tzselect' program supplied with this distribution for
one example.
Names normally have the form AREA/LOCATION, where AREA is the name
of a continent or ocean, and LOCATION is the name of a specific
location within that region. North and South America share the same
area, `America'. Typical names are `Africa/Cairo', `America/New_York',
and `Pacific/Honolulu'.
Here are the general rules used for choosing location names,
in decreasing order of importance:
Use only valid POSIX file name components (i.e., the parts of
names other than `/'). Within a file name component,
use only ASCII letters, `.', `-' and `_'. Do not use
digits, as that might create an ambiguity with POSIX
TZ strings. A file name component must not exceed 14
characters or start with `-'. E.g., prefer `Brunei'
to `Bandar_Seri_Begawan'.
Include at least one location per time zone rule set per country.
One such location is enough. Use ISO 3166 (see the file
iso3166.tab) to help decide whether something is a country.
However, uninhabited ISO 3166 regions like Bouvet Island
do not need locations, since local time is not defined there.
If all the clocks in a country's region have agreed since 1970,
don't bother to include more than one location
even if subregions' clocks disagreed before 1970.
Otherwise these tables would become annoyingly large.
If a name is ambiguous, use a less ambiguous alternative;
e.g. many cities are named San Jose and Georgetown, so
prefer `Costa_Rica' to `San_Jose' and `Guyana' to `Georgetown'.
Keep locations compact. Use cities or small islands, not countries
or regions, so that any future time zone changes do not split
locations into different time zones. E.g. prefer `Paris'
to `France', since France has had multiple time zones.
Use mainstream English spelling, e.g. prefer `Rome' to `Roma', and
prefer `Athens' to the true name (which uses Greek letters).
The POSIX file name restrictions encourage this rule.
Use the most populous among locations in a country's time zone,
e.g. prefer `Shanghai' to `Beijing'. Among locations with
similar populations, pick the best-known location,
e.g. prefer `Rome' to `Milan'.
Use the singular form, e.g. prefer `Canary' to `Canaries'.
Omit common suffixes like `_Islands' and `_City', unless that
would lead to ambiguity. E.g. prefer `Cayman' to
`Cayman_Islands' and `Guatemala' to `Guatemala_City',
but prefer `Mexico_City' to `Mexico' because the country
of Mexico has several time zones.
Use `_' to represent a space.
Omit `.' from abbreviations in names, e.g. prefer `St_Helena'
to `St._Helena'.
Do not change established names if they only marginally
violate the above rules. For example, don't change
the existing name `Rome' to `Milan' merely because
Milan's population has grown to be somewhat greater
than Rome's.
If a name is changed, put its old spelling in the `backward' file.
The file `zone.tab' lists the geographical locations used to name
time zone rule files. It is intended to be an exhaustive list
of canonical names for geographic regions.
Older versions of this package used a different naming scheme,
and these older names are still supported.
See the file `backward' for most of these older names
(e.g. `US/Eastern' instead of `America/New_York').
The other old-fashioned names still supported are
`WET', `CET', `MET', `EET' (see the file `europe'),
and `Factory' (see the file `factory').
----- Time zone abbreviations -----
When this package is installed, it generates time zone abbreviations
like `EST' to be compatible with human tradition and POSIX.
Here are the general rules used for choosing time zone abbreviations,
in decreasing order of importance:
Use abbreviations that consist of three or more ASCII letters.
Previous editions of this database also used characters like
' ' and '?', but these characters have a special meaning to
the shell and cause commands like
set `date`
to have unexpected effects.
Previous editions of this rule required upper-case letters,
but the Congressman who introduced Chamorro Standard Time
preferred "ChST", so the rule has been relaxed.
This rule guarantees that all abbreviations could have
been specified by a POSIX TZ string. POSIX
requires at least three characters for an
abbreviation. POSIX through 2000 says that an abbreviation
cannot start with ':', and cannot contain ',', '-',
'+', NUL, or a digit. POSIX from 2001 on changes this
rule to say that an abbreviation can contain only '-', '+',
and alphanumeric characters from the portable character set
in the current locale. To be portable to both sets of
rules, an abbreviation must therefore use only ASCII
letters.
Use abbreviations that are in common use among English-speakers,
e.g. `EST' for Eastern Standard Time in North America.
We assume that applications translate them to other languages
as part of the normal localization process; for example,
a French application might translate `EST' to `HNE'.
For zones whose times are taken from a city's longitude, use the
traditional xMT notation, e.g. `PMT' for Paris Mean Time.
The only name like this in current use is `GMT'.
If there is no common English abbreviation, abbreviate the English
translation of the usual phrase used by native speakers.
If this is not available or is a phrase mentioning the country
(e.g. ``Cape Verde Time''), then:
When a country has a single or principal time zone region,
append `T' to the country's ISO code, e.g. `CVT' for
Cape Verde Time. For summer time append `ST';
for double summer time append `DST'; etc.
When a country has multiple time zones, take the first three
letters of an English place name identifying each zone
and then append `T', `ST', etc. as before;
e.g. `VLAST' for VLAdivostok Summer Time.
Use UTC (with time zone abbreviation "zzz") for locations while
uninhabited. The "zzz" mnemonic is that these locations are,
in some sense, asleep.
Application writers should note that these abbreviations are ambiguous
in practice: e.g. `EST' has a different meaning in Australia than
it does in the United States. In new applications, it's often better
to use numeric UTC offsets like `-0500' instead of time zone
abbreviations like `EST'; this avoids the ambiguity.
----- Calendrical issues -----
Calendrical issues are a bit out of scope for a time zone database,
but they indicate the sort of problems that we would run into if we
extended the time zone database further into the past. An excellent
resource in this area is Nachum Dershowitz and Edward M. Reingold,
<a href="http://emr.cs.iit.edu/home/reingold/calendar-book/third-edition/">
Calendrical Calculations: Third Edition
</a>, Cambridge University Press (2008). Other information and
sources are given below. They sometimes disagree.
France
Gregorian calendar adopted 1582-12-20.
French Revolutionary calendar used 1793-11-24 through 1805-12-31,
and (in Paris only) 1871-05-06 through 1871-05-23.
Russia
From Chris Carrier (1996-12-02):
On 1929-10-01 the Soviet Union instituted an ``Eternal Calendar''
with 30-day months plus 5 holidays, with a 5-day week.
On 1931-12-01 it changed to a 6-day week; in 1934 it reverted to the
Gregorian calendar while retaining the 6-day week; on 1940-06-27 it
reverted to the 7-day week. With the 6-day week the usual days
off were the 6th, 12th, 18th, 24th and 30th of the month.
(Source: Evitiar Zerubavel, _The Seven Day Circle_)
Mark Brader reported a similar story in "The Book of Calendars", edited
by Frank Parise (1982, Facts on File, ISBN 0-8719-6467-8), page 377. But:
From: Petteri Sulonen (via Usenet)
Date: 14 Jan 1999 00:00:00 GMT
...
If your source is correct, how come documents between 1929 -- 1940 were
still dated using the conventional, Gregorian calendar?
I can post a scan of a document dated December 1, 1934, signed by
Yenukidze, the secretary, on behalf of Kalinin, the President of the
Executive Committee of the Supreme Soviet, if you like.
Sweden (and Finland)
From: Mark Brader
<a href="news:1996Jul6.012937.29190@sq.com">
Subject: Re: Gregorian reform -- a part of locale?
</a>
Date: 1996-07-06
In 1700, Denmark made the transition from Julian to Gregorian. Sweden
decided to *start* a transition in 1700 as well, but rather than have one of
those unsightly calendar gaps :-), they simply decreed that the next leap
year after 1696 would be in 1744 -- putting the whole country on a calendar
different from both Julian and Gregorian for a period of 40 years.
However, in 1704 something went wrong and the plan was not carried through;
they did, after all, have a leap year that year. And one in 1708. In 1712
they gave it up and went back to Julian, putting 30 days in February that
year!...
Then in 1753, Sweden made the transition to Gregorian in the usual manner,
getting there only 13 years behind the original schedule.
(A previous posting of this story was challenged, and Swedish readers
produced the following references to support it: "Tiderakning och historia"
by Natanael Beckman (1924) and "Tid, en bok om tiderakning och
kalendervasen" by Lars-Olof Lode'n (no date was given).)
Grotefend's data
From: "Michael Palmer" [with one obvious typo fixed]
Subject: Re: Gregorian Calendar (was Re: Another FHC related question
Newsgroups: soc.genealogy.german
Date: Tue, 9 Feb 1999 02:32:48 -800
...
The following is a(n incomplete) listing, arranged chronologically, of
European states, with the date they converted from the Julian to the
Gregorian calendar:
04/15 Oct 1582 - Italy (with exceptions), Spain, Portugal, Poland (Roman
Catholics and Danzig only)
09/20 Dec 1582 - France, Lorraine
21 Dec 1582/
01 Jan 1583 - Holland, Brabant, Flanders, Hennegau
10/21 Feb 1583 - bishopric of Liege (L"uttich)
13/24 Feb 1583 - bishopric of Augsburg
04/15 Oct 1583 - electorate of Trier
05/16 Oct 1583 - Bavaria, bishoprics of Freising, Eichstedt, Regensburg,
Salzburg, Brixen
13/24 Oct 1583 - Austrian Oberelsass and Breisgau
20/31 Oct 1583 - bishopric of Basel
02/13 Nov 1583 - duchy of J"ulich-Berg
02/13 Nov 1583 - electorate and city of K"oln
04/15 Nov 1583 - bishopric of W"urzburg
11/22 Nov 1583 - electorate of Mainz
16/27 Nov 1583 - bishopric of Strassburg and the margraviate of Baden
17/28 Nov 1583 - bishopric of M"unster and duchy of Cleve
14/25 Dec 1583 - Steiermark
06/17 Jan 1584 - Austria and Bohemia
11/22 Jan 1584 - Luzern, Uri, Schwyz, Zug, Freiburg, Solothurn
12/23 Jan 1584 - Silesia and the Lausitz
22 Jan/
02 Feb 1584 - Hungary (legally on 21 Oct 1587)
Jun 1584 - Unterwalden
01/12 Jul 1584 - duchy of Westfalen
16/27 Jun 1585 - bishopric of Paderborn
14/25 Dec 1590 - Transylvania
22 Aug/
02 Sep 1612 - duchy of Prussia
13/24 Dec 1614 - Pfalz-Neuburg
1617 - duchy of Kurland (reverted to the Julian calendar in
1796)
1624 - bishopric of Osnabr"uck
1630 - bishopric of Minden
15/26 Mar 1631 - bishopric of Hildesheim
1655 - Kanton Wallis
05/16 Feb 1682 - city of Strassburg
18 Feb/
01 Mar 1700 - Protestant Germany (including Swedish possessions in
Germany), Denmark, Norway
30 Jun/
12 Jul 1700 - Gelderland, Zutphen
10 Nov/
12 Dec 1700 - Utrecht, Overijssel
31 Dec 1700/
12 Jan 1701 - Friesland, Groningen, Z"urich, Bern, Basel, Geneva,
Turgau, and Schaffhausen
1724 - Glarus, Appenzell, and the city of St. Gallen
01 Jan 1750 - Pisa and Florence
02/14 Sep 1752 - Great Britain
17 Feb/
01 Mar 1753 - Sweden
1760-1812 - Graub"unden
The Russian empire (including Finland and the Baltic states) did not
convert to the Gregorian calendar until the Soviet revolution of 1917.
Source: H. Grotefend, _Taschenbuch der Zeitrechnung des deutschen
Mittelalters und der Neuzeit_, herausgegeben von Dr. O. Grotefend
(Hannover: Hahnsche Buchhandlung, 1941), pp. 26-28.
----- Time and time zones on Mars -----
Some people have adjusted their work schedules to fit Mars time.
Dozens of special Mars watches were built for Jet Propulsion
Laboratory workers who kept Mars time during the Mars Exploration
Rovers mission (2004). These timepieces look like normal Seikos and
Citizens but use Mars seconds rather than terrestrial seconds.
A Mars solar day is called a "sol" and has a mean period equal to
about 24 hours 39 minutes 35.244 seconds in terrestrial time. It is
divided into a conventional 24-hour clock, so each Mars second equals
about 1.02749125 terrestrial seconds.
The prime meridian of Mars goes through the center of the crater
Airy-0, named in honor of the British astronomer who built the
Greenwich telescope that defines Earth's prime meridian. Mean solar
time on the Mars prime meridian is called Mars Coordinated Time (MTC).
Each landed mission on Mars has adopted a different reference for
solar time keeping, so there is no real standard for Mars time zones.
For example, the Mars Exploration Rover project (2004) defined two
time zones "Local Solar Time A" and "Local Solar Time B" for its two
missions, each zone designed so that its time equals local true solar
time at approximately the middle of the nominal mission. Such a "time
zone" is not particularly suited for any application other than the
mission itself.
Many calendars have been proposed for Mars, but none have achieved
wide acceptance. Astronomers often use Mars Sol Date (MSD) which is a
sequential count of Mars solar days elapsed since about 1873-12-29
12:00 GMT.
The tz database does not currently support Mars time, but it is
documented here in the hopes that support will be added eventually.
Sources:
Michael Allison and Robert Schmunk,
"Technical Notes on Mars Solar Time as Adopted by the Mars24 Sunclock"
<http://www.giss.nasa.gov/tools/mars24/help/notes.html> (2004-07-30).
Jia-Rui Chong, "Workdays Fit for a Martian", Los Angeles Times
(2004-01-14), pp A1, A20-A21.

View File

@ -1,91 +0,0 @@
/*
** This file is in the public domain, so clarified as of
** 2006-07-17 by Arthur David Olson.
*/
#ifndef lint
#ifndef NOID
static const char elsieid[] = "@(#)ialloc.c 8.30";
#endif /* !defined NOID */
#endif /* !defined lint */
#ifndef lint
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
/*LINTLIBRARY*/
#include "private.h"
#define nonzero(n) (((n) == 0) ? 1 : (n))
char *
imalloc(n)
const int n;
{
return malloc((size_t) nonzero(n));
}
char *
icalloc(nelem, elsize)
int nelem;
int elsize;
{
if (nelem == 0 || elsize == 0)
nelem = elsize = 1;
return calloc((size_t) nelem, (size_t) elsize);
}
void *
irealloc(pointer, size)
void * const pointer;
const int size;
{
if (pointer == NULL)
return imalloc(size);
return realloc((void *) pointer, (size_t) nonzero(size));
}
char *
icatalloc(old, new)
char * const old;
const char * const new;
{
register char * result;
register int oldsize, newsize;
newsize = (new == NULL) ? 0 : strlen(new);
if (old == NULL)
oldsize = 0;
else if (newsize == 0)
return old;
else oldsize = strlen(old);
if ((result = irealloc(old, oldsize + newsize + 1)) != NULL)
if (new != NULL)
(void) strcpy(result + oldsize, new);
return result;
}
char *
icpyalloc(string)
const char * const string;
{
return icatalloc((char *) NULL, string);
}
void
ifree(p)
char * const p;
{
if (p != NULL)
(void) free(p);
}
void
icfree(p)
char * const p;
{
if (p != NULL)
(void) free(p);
}

View File

@ -1,272 +0,0 @@
#ifndef PRIVATE_H
#define PRIVATE_H
/*
** This file is in the public domain, so clarified as of
** 1996-06-05 by Arthur David Olson.
*/
/*
* FreeBSD modifications: separate libc's privates from zic's.
* This makes it easier when we need to update one but not the other.
* I have removed all of the ifdef spaghetti which is not relevant to
* zic from this file.
*
* $FreeBSD$
*/
/*
** This header is for use ONLY with the time conversion code.
** There is no guarantee that it will remain unchanged,
** or that it will remain at all.
** Do NOT copy it to any system include directory.
** Thank you!
*/
/*
** ID
*/
#ifndef lint
#ifndef NOID
static const char privatehid[] = "@(#)private.h 8.6";
#endif /* !defined NOID */
#endif /* !defined lint */
#define GRANDPARENTED "Local time zone must be set--use tzsetup"
/*
** Defaults for preprocessor symbols.
** You can override these in your C compiler options, e.g. `-DHAVE_ADJTIME=0'.
*/
#ifndef HAVE_GETTEXT
#define HAVE_GETTEXT 0
#endif /* !defined HAVE_GETTEXT */
#ifndef HAVE_SYMLINK
#define HAVE_SYMLINK 1
#endif /* !defined HAVE_SYMLINK */
#ifndef HAVE_SYS_STAT_H
#define HAVE_SYS_STAT_H 1
#endif /* !defined HAVE_SYS_STAT_H */
#ifndef HAVE_SYS_WAIT_H
#define HAVE_SYS_WAIT_H 1
#endif /* !defined HAVE_SYS_WAIT_H */
#ifndef HAVE_UNISTD_H
#define HAVE_UNISTD_H 1
#endif /* !defined HAVE_UNISTD_H */
/*
** Nested includes
*/
#include "sys/types.h" /* for time_t */
#include "stdio.h"
#include "errno.h"
#include "string.h"
#include "limits.h" /* for CHAR_BIT et al. */
#include "time.h"
#include "stdlib.h"
#if HAVE_GETTEXT
#include "libintl.h"
#endif /* HAVE_GETTEXT */
#if HAVE_SYS_WAIT_H
#include <sys/wait.h> /* for WIFEXITED and WEXITSTATUS */
#endif /* HAVE_SYS_WAIT_H */
#if HAVE_UNISTD_H
#include "unistd.h" /* for F_OK and R_OK, and other POSIX goodness */
#endif /* HAVE_UNISTD_H */
#ifndef F_OK
#define F_OK 0
#endif /* !defined F_OK */
#ifndef R_OK
#define R_OK 4
#endif /* !defined R_OK */
/* Unlike <ctype.h>'s isdigit, this also works if c < 0 | c > UCHAR_MAX. */
#define is_digit(c) ((unsigned)(c) - '0' <= 9)
/*
** Define HAVE_STDINT_H's default value here, rather than at the
** start, since __GLIBC__'s value depends on previously-included
** files.
** (glibc 2.1 and later have stdint.h, even with pre-C99 compilers.)
*/
#ifndef HAVE_STDINT_H
#define HAVE_STDINT_H \
(199901 <= __STDC_VERSION__ || \
2 < (__GLIBC__ + (0 < __GLIBC_MINOR__)))
#endif /* !defined HAVE_STDINT_H */
#if HAVE_STDINT_H
#include "stdint.h"
#endif /* !HAVE_STDINT_H */
#ifndef INT_FAST64_MAX
/* Pre-C99 GCC compilers define __LONG_LONG_MAX__ instead of LLONG_MAX. */
#if defined LLONG_MAX || defined __LONG_LONG_MAX__
typedef long long int_fast64_t;
#else /* ! (defined LLONG_MAX || defined __LONG_LONG_MAX__) */
#if (LONG_MAX >> 31) < 0xffffffff
Please use a compiler that supports a 64-bit integer type (or wider);
you may need to compile with "-DHAVE_STDINT_H".
#endif /* (LONG_MAX >> 31) < 0xffffffff */
typedef long int_fast64_t;
#endif /* ! (defined LLONG_MAX || defined __LONG_LONG_MAX__) */
#endif /* !defined INT_FAST64_MAX */
#ifndef INT32_MAX
#define INT32_MAX 0x7fffffff
#endif /* !defined INT32_MAX */
#ifndef INT32_MIN
#define INT32_MIN (-1 - INT32_MAX)
#endif /* !defined INT32_MIN */
/*
** Workarounds for compilers/systems.
*/
/*
** Some time.h implementations don't declare asctime_r.
** Others might define it as a macro.
** Fix the former without affecting the latter.
*/
#ifndef asctime_r
extern char * asctime_r(struct tm const *, char *);
#endif
/*
** Private function declarations.
*/
char * icalloc (int nelem, int elsize);
char * icatalloc (char * old, const char * new);
char * icpyalloc (const char * string);
char * imalloc (int n);
void * irealloc (void * pointer, int size);
void icfree (char * pointer);
void ifree (char * pointer);
const char * scheck (const char *string, const char *format);
/*
** Finally, some convenience items.
*/
#ifndef TRUE
#define TRUE 1
#endif /* !defined TRUE */
#ifndef FALSE
#define FALSE 0
#endif /* !defined FALSE */
#ifndef TYPE_BIT
#define TYPE_BIT(type) (sizeof (type) * CHAR_BIT)
#endif /* !defined TYPE_BIT */
#ifndef TYPE_SIGNED
#define TYPE_SIGNED(type) (((type) -1) < 0)
#endif /* !defined TYPE_SIGNED */
/*
** Since the definition of TYPE_INTEGRAL contains floating point numbers,
** it cannot be used in preprocessor directives.
*/
#ifndef TYPE_INTEGRAL
#define TYPE_INTEGRAL(type) (((type) 0.5) != 0.5)
#endif /* !defined TYPE_INTEGRAL */
#ifndef INT_STRLEN_MAXIMUM
/*
** 302 / 1000 is log10(2.0) rounded up.
** Subtract one for the sign bit if the type is signed;
** add one for integer division truncation;
** add one more for a minus sign if the type is signed.
*/
#define INT_STRLEN_MAXIMUM(type) \
((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + \
1 + TYPE_SIGNED(type))
#endif /* !defined INT_STRLEN_MAXIMUM */
/*
** INITIALIZE(x)
*/
#ifndef GNUC_or_lint
#ifdef lint
#define GNUC_or_lint
#endif /* defined lint */
#ifndef lint
#ifdef __GNUC__
#define GNUC_or_lint
#endif /* defined __GNUC__ */
#endif /* !defined lint */
#endif /* !defined GNUC_or_lint */
#ifndef INITIALIZE
#ifdef GNUC_or_lint
#define INITIALIZE(x) ((x) = 0)
#endif /* defined GNUC_or_lint */
#ifndef GNUC_or_lint
#define INITIALIZE(x)
#endif /* !defined GNUC_or_lint */
#endif /* !defined INITIALIZE */
/*
** For the benefit of GNU folk...
** `_(MSGID)' uses the current locale's message library string for MSGID.
** The default is to use gettext if available, and use MSGID otherwise.
*/
#ifndef _
#if HAVE_GETTEXT
#define _(msgid) gettext(msgid)
#else /* !HAVE_GETTEXT */
#define _(msgid) msgid
#endif /* !HAVE_GETTEXT */
#endif /* !defined _ */
#ifndef TZ_DOMAIN
#define TZ_DOMAIN "tz"
#endif /* !defined TZ_DOMAIN */
/*
** UNIX was a registered trademark of The Open Group in 2003.
*/
#ifndef YEARSPERREPEAT
#define YEARSPERREPEAT 400 /* years before a Gregorian repeat */
#endif /* !defined YEARSPERREPEAT */
/*
** The Gregorian year averages 365.2425 days, which is 31556952 seconds.
*/
#ifndef AVGSECSPERYEAR
#define AVGSECSPERYEAR 31556952L
#endif /* !defined AVGSECSPERYEAR */
#ifndef SECSPERREPEAT
#define SECSPERREPEAT ((int_fast64_t) YEARSPERREPEAT * (int_fast64_t) AVGSECSPERYEAR)
#endif /* !defined SECSPERREPEAT */
#ifndef SECSPERREPEAT_BITS
#define SECSPERREPEAT_BITS 34 /* ceil(log2(SECSPERREPEAT)) */
#endif /* !defined SECSPERREPEAT_BITS */
/*
** UNIX was a registered trademark of The Open Group in 2003.
*/
#endif /* !defined PRIVATE_H */

View File

@ -1,68 +0,0 @@
/*
** This file is in the public domain, so clarified as of
** 2006-07-17 by Arthur David Olson.
*/
#ifndef lint
#ifndef NOID
static const char elsieid[] = "@(#)scheck.c 8.19";
#endif /* !defined lint */
#endif /* !defined NOID */
#ifndef lint
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
/*LINTLIBRARY*/
#include "private.h"
const char *
scheck(string, format)
const char * const string;
const char * const format;
{
register char * fbuf;
register const char * fp;
register char * tp;
register int c;
register const char * result;
char dummy;
result = "";
if (string == NULL || format == NULL)
return result;
fbuf = imalloc((int) (2 * strlen(format) + 4));
if (fbuf == NULL)
return result;
fp = format;
tp = fbuf;
while ((*tp++ = c = *fp++) != '\0') {
if (c != '%')
continue;
if (*fp == '%') {
*tp++ = *fp++;
continue;
}
*tp++ = '*';
if (*fp == '*')
++fp;
while (is_digit(*fp))
*tp++ = *fp++;
if (*fp == 'l' || *fp == 'h')
*tp++ = *fp++;
else if (*fp == '[')
do *tp++ = *fp++;
while (*fp != '\0' && *fp != ']');
if ((*tp++ = *fp++) == '\0')
break;
}
*(tp - 1) = '%';
*tp++ = 'c';
*tp = '\0';
if (sscanf(string, fbuf, &dummy) != 1)
result = (char *) format;
ifree(fbuf);
return result;
}

View File

@ -1,63 +0,0 @@
.\"
.\" @(#)zdump.8 8.2
.\" This file is in the public domain, so clarified as of
.\" 2009-05-17 by Arthur David Olson.
.\" $FreeBSD$
.\"
.Dd June 20, 2004
.Dt ZDUMP 8
.Os
.Sh NAME
.Nm zdump
.Nd timezone dumper
.Sh SYNOPSIS
.Nm
.Op Fl -version
.Op Fl v
.Op Fl c Ar [loyear,]hiyear
.Op Ar zonename ...
.Sh DESCRIPTION
The
.Nm
utility prints the current time in each
.Ar zonename
named on the command line.
.Pp
The following options are available:
.Bl -tag -width indent
.It Fl -version
Output version information and exit.
.It Fl v
For each
.Ar zonename
on the command line,
print the time at the lowest possible time value,
the time one day after the lowest possible time value,
the times both one second before and exactly at
each detected time discontinuity,
the time at one day less than the highest possible time value,
and the time at the highest possible time value,
Each line ends with
.Em isdst=1
if the given time is Daylight Saving Time or
.Em isdst=0
otherwise.
.It Fl c Ar loyear,hiyear
Cut off verbose output near the start of the given year(s).
By default,
the program cuts off verbose output near the starts of the years -500 and 2500.
.El
.Sh LIMITATIONS
The
.Fl v
option may not be used on systems with floating-point time_t values
that are neither float nor double.
.Pp
Time discontinuities are found by sampling the results returned by localtime
at twelve-hour intervals.
This works in all real-world cases;
one can construct artificial time zones for which this fails.
.Sh "SEE ALSO"
.Xr ctime 3 ,
.Xr tzfile 5 ,
.Xr zic 8

View File

@ -1,668 +0,0 @@
/*
** This file is in the public domain, so clarified as of
** 2009-05-17 by Arthur David Olson.
*/
#ifndef lint
static const char rcsid[] =
"$FreeBSD$";
static char elsieid[] = "@(#)zdump.c 8.10";
#endif /* not lint */
/*
** This code has been made independent of the rest of the time
** conversion package to increase confidence in the verification it provides.
** You can use this code to help in verifying other implementations.
*/
#include <err.h>
#include <stdio.h> /* for stdout, stderr */
#include <stdlib.h> /* for exit, malloc, atoi */
#include <string.h> /* for strcpy */
#include <sys/types.h> /* for time_t */
#include <time.h> /* for struct tm */
#include <unistd.h>
#include <float.h> /* for FLT_MAX and DBL_MAX */
#include <ctype.h> /* for isalpha et al. */
#ifndef isascii
#define isascii(x) 1
#endif /* !defined isascii */
#ifndef ZDUMP_LO_YEAR
#define ZDUMP_LO_YEAR (-500)
#endif /* !defined ZDUMP_LO_YEAR */
#ifndef ZDUMP_HI_YEAR
#define ZDUMP_HI_YEAR 2500
#endif /* !defined ZDUMP_HI_YEAR */
#ifndef MAX_STRING_LENGTH
#define MAX_STRING_LENGTH 1024
#endif /* !defined MAX_STRING_LENGTH */
#ifndef TRUE
#define TRUE 1
#endif /* !defined TRUE */
#ifndef FALSE
#define FALSE 0
#endif /* !defined FALSE */
#ifndef EXIT_SUCCESS
#define EXIT_SUCCESS 0
#endif /* !defined EXIT_SUCCESS */
#ifndef EXIT_FAILURE
#define EXIT_FAILURE 1
#endif /* !defined EXIT_FAILURE */
#ifndef SECSPERMIN
#define SECSPERMIN 60
#endif /* !defined SECSPERMIN */
#ifndef MINSPERHOUR
#define MINSPERHOUR 60
#endif /* !defined MINSPERHOUR */
#ifndef SECSPERHOUR
#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
#endif /* !defined SECSPERHOUR */
#ifndef HOURSPERDAY
#define HOURSPERDAY 24
#endif /* !defined HOURSPERDAY */
#ifndef EPOCH_YEAR
#define EPOCH_YEAR 1970
#endif /* !defined EPOCH_YEAR */
#ifndef TM_YEAR_BASE
#define TM_YEAR_BASE 1900
#endif /* !defined TM_YEAR_BASE */
#ifndef DAYSPERNYEAR
#define DAYSPERNYEAR 365
#endif /* !defined DAYSPERNYEAR */
#ifndef isleap
#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
#endif /* !defined isleap */
#ifndef isleap_sum
/*
** See tzfile.h for details on isleap_sum.
*/
#define isleap_sum(a, b) isleap((a) % 400 + (b) % 400)
#endif /* !defined isleap_sum */
#define SECSPERDAY ((long) SECSPERHOUR * HOURSPERDAY)
#define SECSPERNYEAR (SECSPERDAY * DAYSPERNYEAR)
#define SECSPERLYEAR (SECSPERNYEAR + SECSPERDAY)
#ifndef HAVE_GETTEXT
#define HAVE_GETTEXT 0
#endif
#if HAVE_GETTEXT
#include "locale.h" /* for setlocale */
#include "libintl.h"
#endif /* HAVE_GETTEXT */
#ifndef GNUC_or_lint
#ifdef lint
#define GNUC_or_lint
#else /* !defined lint */
#ifdef __GNUC__
#define GNUC_or_lint
#endif /* defined __GNUC__ */
#endif /* !defined lint */
#endif /* !defined GNUC_or_lint */
#ifndef INITIALIZE
#ifdef GNUC_or_lint
#define INITIALIZE(x) ((x) = 0)
#else /* !defined GNUC_or_lint */
#define INITIALIZE(x)
#endif /* !defined GNUC_or_lint */
#endif /* !defined INITIALIZE */
/*
** For the benefit of GNU folk...
** `_(MSGID)' uses the current locale's message library string for MSGID.
** The default is to use gettext if available, and use MSGID otherwise.
*/
#ifndef _
#if HAVE_GETTEXT
#define _(msgid) gettext(msgid)
#else /* !(HAVE_GETTEXT) */
#define _(msgid) msgid
#endif /* !(HAVE_GETTEXT) */
#endif /* !defined _ */
#ifndef TZ_DOMAIN
#define TZ_DOMAIN "tz"
#endif /* !defined TZ_DOMAIN */
extern char ** environ;
extern char * tzname[2];
static time_t absolute_min_time;
static time_t absolute_max_time;
static size_t longest;
static char * progname;
static int warned;
static void usage(FILE *stream, int status);
static char * abbr(struct tm * tmp);
static void abbrok(const char * abbrp, const char * zone);
static long delta(struct tm * newp, struct tm * oldp);
static void dumptime(const struct tm * tmp);
static time_t hunt(char * name, time_t lot, time_t hit);
static void setabsolutes(void);
static void show(char * zone, time_t t, int v);
static const char * tformat(void);
static time_t yeartot(long y);
#ifndef TYPECHECK
#define my_localtime localtime
#else /* !defined TYPECHECK */
static struct tm *
my_localtime(tp)
time_t * tp;
{
register struct tm * tmp;
tmp = localtime(tp);
if (tp != NULL && tmp != NULL) {
struct tm tm;
register time_t t;
tm = *tmp;
t = mktime(&tm);
if (t - *tp >= 1 || *tp - t >= 1) {
(void) fflush(stdout);
(void) fprintf(stderr, "\n%s: ", progname);
(void) fprintf(stderr, tformat(), *tp);
(void) fprintf(stderr, " ->");
(void) fprintf(stderr, " year=%d", tmp->tm_year);
(void) fprintf(stderr, " mon=%d", tmp->tm_mon);
(void) fprintf(stderr, " mday=%d", tmp->tm_mday);
(void) fprintf(stderr, " hour=%d", tmp->tm_hour);
(void) fprintf(stderr, " min=%d", tmp->tm_min);
(void) fprintf(stderr, " sec=%d", tmp->tm_sec);
(void) fprintf(stderr, " isdst=%d", tmp->tm_isdst);
(void) fprintf(stderr, " -> ");
(void) fprintf(stderr, tformat(), t);
(void) fprintf(stderr, "\n");
}
}
return tmp;
}
#endif /* !defined TYPECHECK */
static void
abbrok(abbrp, zone)
const char * const abbrp;
const char * const zone;
{
register const char * cp;
register char * wp;
if (warned)
return;
cp = abbrp;
wp = NULL;
while (isascii((unsigned char) *cp) &&
(isalnum((unsigned char)*cp) || *cp == '-' || *cp == '+'))
++cp;
if (cp - abbrp < 3)
wp = _("has fewer than 3 characters");
else if (cp - abbrp > 6)
wp = _("has more than 6 characters");
else if (*cp)
wp = "has characters other than ASCII alphanumerics, '-' or '+'";
else
return;
(void) fflush(stdout);
(void) fprintf(stderr,
_("%s: warning: zone \"%s\" abbreviation \"%s\" %s\n"),
progname, zone, abbrp, wp);
warned = TRUE;
}
int
main(argc, argv)
int argc;
char * argv[];
{
register int i;
register int c;
register int vflag;
register char * cutarg;
register long cutloyear = ZDUMP_LO_YEAR;
register long cuthiyear = ZDUMP_HI_YEAR;
register time_t cutlotime;
register time_t cuthitime;
register char ** fakeenv;
time_t now;
time_t t;
time_t newt;
struct tm tm;
struct tm newtm;
register struct tm * tmp;
register struct tm * newtmp;
progname=argv[0];
INITIALIZE(cutlotime);
INITIALIZE(cuthitime);
#if HAVE_GETTEXT
(void) setlocale(LC_MESSAGES, "");
#ifdef TZ_DOMAINDIR
(void) bindtextdomain(TZ_DOMAIN, TZ_DOMAINDIR);
#endif /* TEXTDOMAINDIR */
(void) textdomain(TZ_DOMAIN);
#endif /* HAVE_GETTEXT */
for (i = 1; i < argc; ++i)
if (strcmp(argv[i], "--version") == 0) {
errx(EXIT_SUCCESS, "%s", elsieid);
} else if (strcmp(argv[i], "--help") == 0) {
usage(stdout, EXIT_SUCCESS);
}
vflag = 0;
cutarg = NULL;
while ((c = getopt(argc, argv, "c:v")) == 'c' || c == 'v')
if (c == 'v')
vflag = 1;
else cutarg = optarg;
if ((c != -1) ||
(optind == argc - 1 && strcmp(argv[optind], "=") == 0)) {
usage(stderr, EXIT_FAILURE);
}
if (vflag) {
if (cutarg != NULL) {
long lo;
long hi;
char dummy;
if (sscanf(cutarg, "%ld%c", &hi, &dummy) == 1) {
cuthiyear = hi;
} else if (sscanf(cutarg, "%ld,%ld%c",
&lo, &hi, &dummy) == 2) {
cutloyear = lo;
cuthiyear = hi;
} else {
(void) fprintf(stderr, _("%s: wild -c argument %s\n"),
progname, cutarg);
exit(EXIT_FAILURE);
}
}
setabsolutes();
cutlotime = yeartot(cutloyear);
cuthitime = yeartot(cuthiyear);
}
(void) time(&now);
longest = 0;
for (i = optind; i < argc; ++i)
if (strlen(argv[i]) > longest)
longest = strlen(argv[i]);
{
register int from;
register int to;
for (i = 0; environ[i] != NULL; ++i)
continue;
fakeenv = (char **) malloc((size_t) ((i + 2) *
sizeof *fakeenv));
if (fakeenv == NULL ||
(fakeenv[0] = (char *) malloc((size_t) (longest +
4))) == NULL)
errx(EXIT_FAILURE,
_("malloc() failed"));
to = 0;
(void) strcpy(fakeenv[to++], "TZ=");
for (from = 0; environ[from] != NULL; ++from)
if (strncmp(environ[from], "TZ=", 3) != 0)
fakeenv[to++] = environ[from];
fakeenv[to] = NULL;
environ = fakeenv;
}
for (i = optind; i < argc; ++i) {
static char buf[MAX_STRING_LENGTH];
(void) strcpy(&fakeenv[0][3], argv[i]);
if (!vflag) {
show(argv[i], now, FALSE);
continue;
}
warned = FALSE;
t = absolute_min_time;
show(argv[i], t, TRUE);
t += SECSPERHOUR * HOURSPERDAY;
show(argv[i], t, TRUE);
if (t < cutlotime)
t = cutlotime;
tmp = my_localtime(&t);
if (tmp != NULL) {
tm = *tmp;
(void) strncpy(buf, abbr(&tm), (sizeof buf) - 1);
}
for ( ; ; ) {
if (t >= cuthitime || t >= cuthitime - SECSPERHOUR * 12)
break;
newt = t + SECSPERHOUR * 12;
newtmp = localtime(&newt);
if (newtmp != NULL)
newtm = *newtmp;
if ((tmp == NULL || newtmp == NULL) ? (tmp != newtmp) :
(delta(&newtm, &tm) != (newt - t) ||
newtm.tm_isdst != tm.tm_isdst ||
strcmp(abbr(&newtm), buf) != 0)) {
newt = hunt(argv[i], t, newt);
newtmp = localtime(&newt);
if (newtmp != NULL) {
newtm = *newtmp;
(void) strncpy(buf,
abbr(&newtm),
(sizeof buf) - 1);
}
}
t = newt;
tm = newtm;
tmp = newtmp;
}
t = absolute_max_time;
t -= SECSPERHOUR * HOURSPERDAY;
show(argv[i], t, TRUE);
t += SECSPERHOUR * HOURSPERDAY;
show(argv[i], t, TRUE);
}
if (fflush(stdout) || ferror(stdout))
errx(EXIT_FAILURE, _("error writing standard output"));
exit(EXIT_SUCCESS);
/* If exit fails to exit... */
return(EXIT_FAILURE);
}
static void
setabsolutes(void)
{
if (0.5 == (time_t) 0.5) {
/*
** time_t is floating.
*/
if (sizeof (time_t) == sizeof (float)) {
absolute_min_time = (time_t) -FLT_MAX;
absolute_max_time = (time_t) FLT_MAX;
} else if (sizeof (time_t) == sizeof (double)) {
absolute_min_time = (time_t) -DBL_MAX;
absolute_max_time = (time_t) DBL_MAX;
} else {
(void) fprintf(stderr,
_("%s: use of -v on system with floating time_t other than float or double\n"),
progname);
exit(EXIT_FAILURE);
}
} else if (0 > (time_t) -1) {
/*
** time_t is signed. Assume overflow wraps around.
*/
time_t t = 0;
time_t t1 = 1;
while (t < t1) {
t = t1;
t1 = 2 * t1 + 1;
}
absolute_max_time = t;
t = -t;
absolute_min_time = t - 1;
if (t < absolute_min_time)
absolute_min_time = t;
} else {
/*
** time_t is unsigned.
*/
absolute_min_time = 0;
absolute_max_time = absolute_min_time - 1;
}
}
static time_t
yeartot(y)
const long y;
{
register long myy;
register long seconds;
register time_t t;
myy = EPOCH_YEAR;
t = 0;
while (myy != y) {
if (myy < y) {
seconds = isleap(myy) ? SECSPERLYEAR : SECSPERNYEAR;
++myy;
if (t > absolute_max_time - seconds) {
t = absolute_max_time;
break;
}
t += seconds;
} else {
--myy;
seconds = isleap(myy) ? SECSPERLYEAR : SECSPERNYEAR;
if (t < absolute_min_time + seconds) {
t = absolute_min_time;
break;
}
t -= seconds;
}
}
return t;
}
static void
usage(FILE *stream, int status)
{
fprintf(stream,
_("usage: %s [--version] [-v] [--help] [-c [loyear,]hiyear] zonename ...\n\
\n\
Report bugs to tz@elsie.nci.nih.gov.\n"), progname);
exit(status);
}
static time_t
hunt(char *name, time_t lot, time_t hit)
{
time_t t;
long diff;
struct tm lotm;
register struct tm * lotmp;
struct tm tm;
register struct tm * tmp;
char loab[MAX_STRING_LENGTH];
lotmp = my_localtime(&lot);
if (lotmp != NULL) {
lotm = *lotmp;
(void) strncpy(loab, abbr(&lotm), (sizeof loab) - 1);
}
for ( ; ; ) {
diff = (long) (hit - lot);
if (diff < 2)
break;
t = lot;
t += diff / 2;
if (t <= lot)
++t;
else if (t >= hit)
--t;
tmp = my_localtime(&t);
if (tmp != NULL)
tm = *tmp;
if ((lotmp == NULL || tmp == NULL) ? (lotmp == tmp) :
(delta(&tm, &lotm) == (t - lot) &&
tm.tm_isdst == lotm.tm_isdst &&
strcmp(abbr(&tm), loab) == 0)) {
lot = t;
lotm = tm;
lotmp = tmp;
} else hit = t;
}
show(name, lot, TRUE);
show(name, hit, TRUE);
return hit;
}
/*
** Thanks to Paul Eggert for logic used in delta.
*/
static long
delta(newp, oldp)
struct tm * newp;
struct tm * oldp;
{
register long result;
register int tmy;
if (newp->tm_year < oldp->tm_year)
return -delta(oldp, newp);
result = 0;
for (tmy = oldp->tm_year; tmy < newp->tm_year; ++tmy)
result += DAYSPERNYEAR + isleap_sum(tmy, TM_YEAR_BASE);
result += newp->tm_yday - oldp->tm_yday;
result *= HOURSPERDAY;
result += newp->tm_hour - oldp->tm_hour;
result *= MINSPERHOUR;
result += newp->tm_min - oldp->tm_min;
result *= SECSPERMIN;
result += newp->tm_sec - oldp->tm_sec;
return result;
}
static void
show(char *zone, time_t t, int v)
{
register struct tm * tmp;
(void) printf("%-*s ", (int) longest, zone);
if (v) {
tmp = gmtime(&t);
if (tmp == NULL) {
(void) printf(tformat(), t);
} else {
dumptime(tmp);
(void) printf(" UTC");
}
(void) printf(" = ");
}
tmp = my_localtime(&t);
dumptime(tmp);
if (tmp != NULL) {
if (*abbr(tmp) != '\0')
(void) printf(" %s", abbr(tmp));
if (v) {
(void) printf(" isdst=%d", tmp->tm_isdst);
#ifdef TM_GMTOFF
(void) printf(" gmtoff=%ld", tmp->TM_GMTOFF);
#endif /* defined TM_GMTOFF */
}
}
(void) printf("\n");
if (tmp != NULL && *abbr(tmp) != '\0')
abbrok(abbr(tmp), zone);
}
static char *
abbr(tmp)
struct tm * tmp;
{
register char * result;
static char nada;
if (tmp->tm_isdst != 0 && tmp->tm_isdst != 1)
return &nada;
result = tzname[tmp->tm_isdst];
return (result == NULL) ? &nada : result;
}
/*
** The code below can fail on certain theoretical systems;
** it works on all known real-world systems as of 2004-12-30.
*/
static const char *
tformat(void)
{
if (0.5 == (time_t) 0.5) { /* floating */
if (sizeof (time_t) > sizeof (double))
return "%Lg";
return "%g";
}
if (0 > (time_t) -1) { /* signed */
if (sizeof (time_t) > sizeof (long))
return "%lld";
if (sizeof (time_t) > sizeof (int))
return "%ld";
return "%d";
}
if (sizeof (time_t) > sizeof (unsigned long))
return "%llu";
if (sizeof (time_t) > sizeof (unsigned int))
return "%lu";
return "%u";
}
static void
dumptime(timeptr)
register const struct tm * timeptr;
{
static const char wday_name[][3] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
static const char mon_name[][3] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
register const char * wn;
register const char * mn;
register int lead;
register int trail;
if (timeptr == NULL) {
(void) printf("NULL");
return;
}
/*
** The packaged versions of localtime and gmtime never put out-of-range
** values in tm_wday or tm_mon, but since this code might be compiled
** with other (perhaps experimental) versions, paranoia is in order.
*/
if (timeptr->tm_wday < 0 || timeptr->tm_wday >=
(int) (sizeof wday_name / sizeof wday_name[0]))
wn = "???";
else wn = wday_name[timeptr->tm_wday];
if (timeptr->tm_mon < 0 || timeptr->tm_mon >=
(int) (sizeof mon_name / sizeof mon_name[0]))
mn = "???";
else mn = mon_name[timeptr->tm_mon];
(void) printf("%.3s %.3s%3d %.2d:%.2d:%.2d ",
wn, mn,
timeptr->tm_mday, timeptr->tm_hour,
timeptr->tm_min, timeptr->tm_sec);
#define DIVISOR 10
trail = timeptr->tm_year % DIVISOR + TM_YEAR_BASE % DIVISOR;
lead = timeptr->tm_year / DIVISOR + TM_YEAR_BASE / DIVISOR +
trail / DIVISOR;
trail %= DIVISOR;
if (trail < 0 && lead > 0) {
trail += DIVISOR;
--lead;
} else if (lead < 0 && trail > 0) {
trail -= DIVISOR;
++lead;
}
if (lead == 0)
(void) printf("%d", trail);
else (void) printf("%d%d", lead, ((trail < 0) ? -trail : trail));
}

View File

@ -1,15 +0,0 @@
# $FreeBSD$
.PATH: ${.CURDIR}/..
PROG= zdump
MAN= zdump.8
SRCS= zdump.c ialloc.c scheck.c
CFLAGS+= -DTM_GMTOFF=tm_gmtoff -DTM_ZONE=tm_zone -DSTD_INSPIRED -DPCTS
CFLAGS+= -DHAVE_LONG_DOUBLE -DTZDIR=\"/usr/share/zoneinfo\" -Demkdir=mkdir
CFLAGS+= -I${.CURDIR}/.. -I${.CURDIR}/../../../lib/libc/stdtime
WARNS?= 2
.include <bsd.prog.mk>

View File

@ -1,468 +0,0 @@
.\" $FreeBSD$
.Dd June 20, 2004
.Dt ZIC 8
.Os
.Sh NAME
.Nm zic
.Nd timezone compiler
.Sh SYNOPSIS
.Nm
.Op Fl -version
.Op Fl Dsv
.Op Fl d Ar directory
.Op Fl g Ar group
.Op Fl L Ar leapsecondfilename
.Op Fl l Ar localtime
.Op Fl m Ar mode
.Op Fl p Ar posixrules
.Op Fl u Ar user
.Op Fl y Ar command
.Op Ar filename ...
.Sh DESCRIPTION
The
.Nm
utility reads text from the file(s) named on the command line
and creates the time conversion information files specified in this input.
If a
.Ar filename
is
.Em - ,
the standard input is read.
.Pp
The following options are available:
.Bl -tag -width indent
.It Fl -version
Output version information and exit.
.It Fl D
Do not automatically create directories.
If the input file(s) specify
an output file in a directory which does not already exist, the
default behavior is to attempt to create the directory.
If
.Fl D
is specified,
.Nm
will instead error out immediately.
.It Fl d Ar directory
Create time conversion information files in the named directory rather than
in the standard directory named below.
.It Fl g Ar group
After creating each output file, change its group ownership to the
specified
.Ar group
(which can be either a name or a numeric group ID).
.It Fl L Ar leapsecondfilename
Read leap second information from the file with the given name.
If this option is not used,
no leap second information appears in output files.
.It Fl l Ar timezone
Use the given
.Ar time zone
as local time.
The
.Nm
utility will act as if the input contained a link line of the form
.Pp
.D1 No "Link timezone localtime"
.Pp
(Note that this action has no effect on
.Fx ,
since the local time zone is specified in
.Pa /etc/localtime
and not
.Pa /usr/share/zoneinfo/localtime . )
.It Fl m Ar mode
After creating each output file, change its access mode to
.Ar mode .
Both numeric and alphabetic modes are accepted
(see
.Xr chmod 1 ) .
.It Fl p Ar timezone
Use the given
.Ar "time zone" Ns 's
rules when handling POSIX-format
time zone environment variables.
The
.Nm
utility will act as if the input contained a link line of the form
.Pp
.D1 No "Link timezone posixrules"
.It Fl u Ar user
After creating each output file, change its owner to
.Ar user
(which can be either a name or a numeric user ID).
.It Fl v
Complain if a year that appears in a data file is outside the range
of years representable by
.Xr time 3
values.
.It Fl s
Limit time values stored in output files to values that are the same
whether they are taken to be signed or unsigned.
You can use this option to generate SVVS-compatible files.
.It Fl y Ar command
Use the given
.Ar command
rather than
.Em yearistype
when checking year types (see below).
.El
.Pp
Input lines are made up of fields.
Fields are separated from one another by any number of white space characters.
Leading and trailing white space on input lines is ignored.
An unquoted sharp character (#) in the input introduces a comment which extends
to the end of the line the sharp character appears on.
White space characters and sharp characters may be enclosed in double quotes
(") if they are to be used as part of a field.
Any line that is blank (after comment stripping) is ignored.
Non-blank lines are expected to be of one of three types:
rule lines, zone lines, and link lines.
.Pp
Names (such as month names) must be in English and are case insensitive.
Abbreviations, if used, must be unambiguous in context.
.Pp
A rule line has the form:
.Dl "Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S"
For example:
.Dl "Rule US 1967 1973 \- Apr lastSun 2:00 1:00 D"
.Pp
The fields that make up a rule line are:
.Bl -tag -width "LETTER/S" -offset indent
.It NAME
Give the (arbitrary) name of the set of rules this rule is part of.
.It FROM
Give the first year in which the rule applies.
Any integer year can be supplied; the Gregorian calendar is assumed.
The word
.Em minimum
(or an abbreviation) means the minimum year representable as an integer.
The word
.Em maximum
(or an abbreviation) means the maximum year representable as an integer.
Rules can describe times that are not representable as time values,
with the unrepresentable times ignored; this allows rules to be portable
among hosts with differing time value types.
.It TO
Give the final year in which the rule applies.
In addition to
.Em minimum
and
.Em maximum
(as above),
the word
.Em only
(or an abbreviation)
may be used to repeat the value of the
.Em FROM
field.
.It TYPE
Give the type of year in which the rule applies.
If
.Em TYPE
is
.Em \-
then the rule applies in all years between
.Em FROM
and
.Em TO
inclusive.
If
.Em TYPE
is something else, then
.Nm
executes the command
.Li yearistype Ar year Ar type
to check the type of a year:
an exit status of zero is taken to mean that the year is of the given type;
an exit status of one is taken to mean that the year is not of the given type.
.It IN
Name the month in which the rule takes effect.
Month names may be abbreviated.
.It ON
Give the day on which the rule takes effect.
Recognized forms include:
.Pp
.Bl -tag -width lastSun -compact -offset indent
.It \&5
the fifth of the month
.It lastSun
the last Sunday in the month
.It lastMon
the last Monday in the month
.It Sun>=8
first Sunday on or after the eighth
.It Sun<=25
last Sunday on or before the 25th
.El
.Pp
Names of days of the week may be abbreviated or spelled out in full.
Note that there must be no spaces within the
.Em ON
field.
.It AT
Give the time of day at which the rule takes effect.
Recognized forms include:
.Pp
.Bl -tag -width "\&1:28:14" -offset indent -compact
.It 2
time in hours
.It 2:00
time in hours and minutes
.It 15:00
24-hour format time (for times after noon)
.It 1:28:14
time in hours, minutes, and seconds
.El
.Pp
where hour 0 is midnight at the start of the day,
and hour 24 is midnight at the end of the day.
Any of these forms may be followed by the letter
.Sq Li w
if the given time is local
.Dq "wall clock"
time,
.Sq Li s
if the given time is local
.Dq standard
time, or
.Sq Li u
(or
.Sq Li g
or
.Sq Li z )
if the given time is universal time;
in the absence of an indicator,
wall clock time is assumed.
.It SAVE
Give the amount of time to be added to local standard time when the rule is in
effect.
This field has the same format as the
.Em AT
field
(although, of course, the
.Sq Li w
and
.Sq Li s
suffixes are not used).
.It LETTER/S
Give the
.Dq "variable part"
(for example, the
.Dq S
or
.Dq D
in
.Dq EST
or
.Dq EDT )
of time zone abbreviations to be used when this rule is in effect.
If this field is
.Em \- ,
the variable part is null.
.El
.Pp
A zone line has the form:
.Dl "Zone NAME GMTOFF RULES/SAVE FORMAT [UNTILYEAR [MONTH [DAY [TIME]]]]"
For example:
.Dl "Zone Australia/Adelaide 9:30 Aus CST 1971 Oct 31 2:00"
The fields that make up a zone line are:
.Bl -tag -width indent
.It NAME
The name of the time zone.
This is the name used in creating the time conversion information file for the
zone.
.It GMTOFF
The amount of time to add to UTC to get standard time in this zone.
This field has the same format as the
.Em AT
and
.Em SAVE
fields of rule lines;
begin the field with a minus sign if time must be subtracted from UTC.
.It RULES/SAVE
The name of the rule(s) that apply in the time zone or,
alternately, an amount of time to add to local standard time.
If this field is
.Em \-
then standard time always applies in the time zone.
.It FORMAT
The format for time zone abbreviations in this time zone.
The pair of characters
.Em %s
is used to show where the
.Dq "variable part"
of the time zone abbreviation goes.
Alternately,
a slash (/)
separates standard and daylight abbreviations.
.It UNTILYEAR [MONTH [DAY [TIME]]]
The time at which the UTC offset or the rule(s) change for a location.
It is specified as a year, a month, a day, and a time of day.
If this is specified,
the time zone information is generated from the given UTC offset
and rule change until the time specified.
The month, day, and time of day have the same format as the IN, ON, and AT
fields of a rule; trailing fields can be omitted, and default to the
earliest possible value for the missing fields.
.Pp
The next line must be a
.Dq continuation
line; this has the same form as a zone line except that the
string
.Dq Zone
and the name are omitted, as the continuation line will
place information starting at the time specified as the
.Em until
information in the previous line in the file used by the previous line.
Continuation lines may contain
.Em until
information, just as zone lines do, indicating that the next line is a further
continuation.
.El
.Pp
A link line has the form
.Dl "Link LINK-FROM LINK-TO"
For example:
.Dl "Link Europe/Istanbul Asia/Istanbul"
The
.Em LINK-FROM
field should appear as the
.Em NAME
field in some zone line;
the
.Em LINK-TO
field is used as an alternate name for that zone.
.Pp
Except for continuation lines,
lines may appear in any order in the input.
.Pp
Lines in the file that describes leap seconds have the following form:
.Dl "Leap YEAR MONTH DAY HH:MM:SS CORR R/S"
For example:
.Dl "Leap 1974 Dec 31 23:59:60 + S"
The
.Em YEAR ,
.Em MONTH ,
.Em DAY ,
and
.Em HH:MM:SS
fields tell when the leap second happened.
The
.Em CORR
field
should be
.Dq +
if a second was added
or
.Dq -
if a second was skipped.
.\" There's no need to document the following, since it's impossible for more
.\" than one leap second to be inserted or deleted at a time.
.\" The C Standard is in error in suggesting the possibility.
.\" See Terry J Quinn, The BIPM and the accurate measure of time,
.\" Proc IEEE 79, 7 (July 1991), 894-905.
.\" or
.\" .q ++
.\" if two seconds were added
.\" or
.\" .q --
.\" if two seconds were skipped.
The
.Em R/S
field
should be (an abbreviation of)
.Dq Stationary
if the leap second time given by the other fields should be interpreted as UTC
or
(an abbreviation of)
.Dq Rolling
if the leap second time given by the other fields should be interpreted as
local wall clock time.
.Sh "EXTENDED EXAMPLE"
Here is an extended example of
.Nm
input, intended to illustrate many of its features.
.br
.ne 22
.nf
.in +2m
.ta \w'# Rule\0\0'u +\w'NAME\0\0'u +\w'FROM\0\0'u +\w'1973\0\0'u +\w'TYPE\0\0'u +\w'Apr\0\0'u +\w'lastSun\0\0'u +\w'2:00\0\0'u +\w'SAVE\0\0'u
.sp
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Swiss 1940 only - Nov 2 0:00 1:00 S
Rule Swiss 1940 only - Dec 31 0:00 0 -
Rule Swiss 1941 1942 - May Sun>=1 2:00 1:00 S
Rule Swiss 1941 1942 - Oct Sun>=1 0:00 0
.sp .5
Rule EU 1977 1980 - Apr Sun>=1 1:00u 1:00 S
Rule EU 1977 only - Sep lastSun 1:00u 0 -
Rule EU 1978 only - Oct 1 1:00u 0 -
Rule EU 1979 1995 - Sep lastSun 1:00u 0 -
Rule EU 1981 max - Mar lastSun 1:00u 1:00 S
Rule EU 1996 max - Oct lastSun 1:00u 0 -
.sp
.ta \w'# Zone\0\0'u +\w'Europe/Zurich\0\0'u +\w'0:34:08\0\0'u +\w'RULES/SAVE\0\0'u +\w'FORMAT\0\0'u
# Zone NAME GMTOFF RULES FORMAT UNTIL
Zone Europe/Zurich 0:34:08 - LMT 1848 Sep 12
0:29:44 - BMT 1894 Jun
1:00 Swiss CE%sT 1981
1:00 EU CE%sT
.sp
Link Europe/Zurich Switzerland
.sp
.in
.fi
In this example, the zone is named Europe/Zurich but it has an alias
as Switzerland.
Zurich was 34 minutes and 8 seconds west of GMT until 1848-09-12
at 00:00, when the offset changed to 29 minutes and 44 seconds.
After 1894-06-01 at 00:00 Swiss daylight saving rules (defined with
lines beginning with "Rule Swiss") apply, and the GMT offset became
one hour.
From 1981 to the present, EU daylight saving rules have applied,
and the UTC offset has remained at one hour.
.Pp
In 1940, daylight saving time applied from November 2 at 00:00 to
December 31 at 00:00.
In 1941 and 1942, daylight saving time applied from the first Sunday
in May at 02:00 to the first Sunday in October at 00:00.
The pre-1981 EU daylight-saving rules have no effect here, but are
included for completeness.
Since 1981, daylight saving has begun on the last Sunday in March
at 01:00 UTC.
Until 1995 it ended the last Sunday in September at 01:00 UTC, but
this changed to the last Sunday in October starting in 1996.
.Pp
For purposes of display, "LMT" and "BMT" were initially used,
respectively.
Since Swiss rules and later EU rules were applied, the display name
for the timezone has been CET for standard time and CEST for daylight
saving time.
.Sh NOTES
For areas with more than two types of local time,
you may need to use local standard time in the
.Em AT
field of the earliest transition time's rule to ensure that
the earliest transition time recorded in the compiled file is correct.
.Pp
If, for a particular zone, a clock advance caused by the start of
daylight saving coincides with and is equal to a clock retreat
caused by a change in UTC offset,
.Nm
produces a single transition to daylight saving at the new UTC offset
(without any change in wall clock time).
To get separate transitions use multiple zone continuation lines
specifying transition instants using universal time.
.Sh FILES
.Bl -tag -width /usr/share/zoneinfo -compact
.It /usr/share/zoneinfo
standard directory used for created files
.El
.Sh "SEE ALSO"
.Xr ctime 3 ,
.Xr tzfile 5 ,
.Xr zdump 8
.\" @(#)zic.8 8.6
.\" This file is in the public domain, so clarified as of
.\" 2009-05-17 by Arthur David Olson.

File diff suppressed because it is too large Load Diff

View File

@ -1,16 +0,0 @@
# $FreeBSD$
.PATH: ${.CURDIR}/..
PROG= zic
MAN= zic.8
SRCS= zic.c ialloc.c scheck.c
CFLAGS+= -DTM_GMTOFF=tm_gmtoff -DTM_ZONE=tm_zone -DSTD_INSPIRED -DPCTS
CFLAGS+= -DHAVE_LONG_DOUBLE -DTZDIR=\"/usr/share/zoneinfo\" -Demkdir=mkdir
CFLAGS+= -DHAVE_STRERROR -DHAVE_UNISTD_H
CFLAGS+= -I${.CURDIR}/.. -I${.CURDIR}/../../../lib/libc/stdtime
WARNS?= 2
.include <bsd.prog.mk>

View File

@ -1,19 +1,21 @@
# Makefile.inc,v 1.2 1994/09/13 21:26:01 wollman Exp
# $FreeBSD$
.PATH: ${LIBC_SRCTOP}/stdtime ${SRCTOP}/contrib/tzcode/stdtime
.PATH: ${LIBC_SRCTOP}/stdtime ${SRCTOP}/contrib/tzcode
SRCS+= asctime.c difftime.c localtime.c strftime.c strptime.c timelocal.c \
time32.c
SYM_MAPS+= ${LIBC_SRCTOP}/stdtime/Symbol.map
CFLAGS+= -I${SRCTOP}/contrib/tzcode/stdtime -I${LIBC_SRCTOP}/stdtime
CFLAGS+= -I${SRCTOP}/contrib/tzcode -I${LIBC_SRCTOP}/stdtime
CFLAGS.localtime.c= -fwrapv
CFLAGS.localtime.c+= -DALL_STATE -DTHREAD_SAFE
CFLAGS.localtime.c+= -DHAVE_TZNAME=2 -DUSG_COMPAT=0 -DALTZONE=0
CFLAGS.localtime.c+= -DNETBSD_INSPIRED=0 -DSTD_INSPIRED=1
.if ${MK_DETECT_TZ_CHANGES} != "no"
CFLAGS+= -DDETECT_TZ_CHANGES
CFLAGS.localtime.c+= -DDETECT_TZ_CHANGES
.endif
MAN+= ctime.3 strftime.3 strptime.3 time2posix.3

View File

@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
#include "tzfile.h"
#include <fcntl.h>
#include <sys/stat.h>
#include <stdio.h>
#include "un-namespace.h"
#include "timelocal.h"

View File

@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include "private.h"
#include "un-namespace.h"
#include "libc_private.h"
#include "timelocal.h"

View File

@ -101,6 +101,7 @@ SUBDIR= adduser \
wake \
watch \
watchdogd \
zdump \
zic \
zonectl

12
usr.sbin/zdump/Makefile Normal file
View File

@ -0,0 +1,12 @@
# $FreeBSD$
.PATH: ${SRCTOP}/contrib/tzcode
PROG= zdump
MAN= zdump.8
SRCS= zdump.c
CFLAGS+= -DNETBSD_INSPIRED=0 -DSTD_INSPIRED=1
CFLAGS+= -I${SRCTOP}/contrib/tzcode
.include <bsd.prog.mk>

View File

@ -1,7 +1,12 @@
# $FreeBSD$
# Vendor contact: tz@elsie.nci.nih.gov
.PATH: ${SRCTOP}/contrib/tzcode
SUBDIR= zic zdump
PROG= zic
MAN= zic.8
SRCS= zic.c
.include <bsd.subdir.mk>
CFLAGS+= -DNETBSD_INSPIRED=0 -DSTD_INSPIRED=1
CFLAGS+= -I${SRCTOP}/contrib/tzcode
.include <bsd.prog.mk>

View File

@ -1,3 +0,0 @@
# $FreeBSD$
.include "${SRCTOP}/usr.sbin/Makefile.inc"

View File

@ -1,88 +0,0 @@
@(#)README 8.3
This file is in the public domain, so clarified as of
2009-05-17 by Arthur David Olson.
$FreeBSD$
"What time is it?" -- Richard Deacon as The King
"Any time you want it to be." -- Frank Baxter as The Scientist
(from the Bell System film "About Time")
The 1989 update of the time zone package featured
* POSIXization (including interpretation of POSIX-style TZ environment
variables, provided by Guy Harris),
* ANSIfication (including versions of "mktime" and "difftime"),
* SVIDulation (an "altzone" variable)
* MACHination (the "gtime" function)
* corrections to some time zone data (including corrections to the rules
for Great Britain and New Zealand)
* reference data from the United States Naval Observatory for folks who
want to do additional time zones
* and the 1989 data for Saudi Arabia.
(Since this code will be treated as "part of the implementation" in some places
and as "part of the application" in others, there's no good way to name
functions, such as timegm, that are not part of the proposed ANSI C standard;
such functions have kept their old, underscore-free names in this update.)
And the "dysize" function has disappeared; it was present to allow compilation
of the "date" command on old BSD systems, and a version of "date" is now
provided in the package. The "date" command is not created when you "make all"
since it may lack options provided by the version distributed with your
operating system, or may not interact with the system in the same way the
native version does.
Since POSIX frowns on correct leap second handling, the default behavior of
the "zic" command (in the absence of a "-L" option) has been changed to omit
leap second information from its output files.
Here is a recipe for acquiring, building, installing, and testing the
tz distribution on a GNU/Linux or similar host.
mkdir tz
cd tz
wget 'ftp://elsie.nci.nih.gov/pub/tz*.tar.gz'
gzip -dc tzcode*.tar.gz | tar -xf -
gzip -dc tzdata*.tar.gz | tar -xf -
Be sure to read the comments in "Makefile" and make any changes needed
to make things right for your system, especially if you are using some
platform other than GNU/Linux. Then run the following commands,
substituting your desired installation directory for "$HOME/tzdir":
make TOPDIR=$HOME/tzdir install
$HOME/tzdir/etc/zdump -v America/Los_Angeles
To use the new functions, use a "-ltz" option when compiling or linking.
Historical local time information has been included here to:
* provide a compendium of data about the history of civil time
that is useful even if the data are not 100% accurate;
* give an idea of the variety of local time rules that have
existed in the past and thus an idea of the variety that may be
expected in the future;
* provide a test of the generality of the local time rule description
system.
The information in the time zone data files is by no means authoritative;
the files currently do not even attempt to cover all time stamps before
1970, and there are undoubtedly errors even for time stamps since 1970.
If you know that the rules are different from those in a file, by all means
feel free to change file (and please send the changed version to
tz@elsie.nci.nih.gov for use in the future). Europeans take note!
Thanks to these Timezone Caballeros who've made major contributions to the
time conversion package: Keith Bostic; Bob Devine; Paul Eggert; Robert Elz;
Guy Harris; Mark Horton; John Mackin; and Bradley White. Thanks also to
Michael Bloom, Art Neilson, Stephen Prince, John Sovereign, and Frank Wales
for testing work, and to Gwillim Law for checking local mean time data.
None of them are responsible for remaining errors.
Look in the ~ftp/pub directory of elsie.nci.nih.gov
for updated versions of these files.
Please send comments or information to tz@elsie.nci.nih.gov.

View File

@ -1,15 +0,0 @@
# $FreeBSD$
.PATH: ${SRCTOP}/contrib/tzcode/zic
PROG= zdump
MAN= zdump.8
SRCS= zdump.c ialloc.c scheck.c
CFLAGS+= -DTM_GMTOFF=tm_gmtoff -DTM_ZONE=tm_zone -DSTD_INSPIRED -DPCTS
CFLAGS+= -DHAVE_LONG_DOUBLE -DTZDIR=\"${SHAREDIR}/zoneinfo\" -Demkdir=mkdir
CFLAGS+= -I${.CURDIR:H} -I${SRCTOP}/contrib/tzcode/stdtime
WARNS?= 2
.include <bsd.prog.mk>

View File

@ -1,22 +0,0 @@
# $FreeBSD$
.include <src.opts.mk>
.PATH: ${SRCTOP}/contrib/tzcode/zic
PROG= zic
MAN= zic.8
SRCS= zic.c ialloc.c scheck.c
CFLAGS+= -DTM_GMTOFF=tm_gmtoff -DTM_ZONE=tm_zone -DSTD_INSPIRED -DPCTS
CFLAGS+= -DHAVE_LONG_DOUBLE -DTZDIR=\"${SHAREDIR}/zoneinfo\" -Demkdir=mkdir
CFLAGS+= -DHAVE_STRERROR -DHAVE_UNISTD_H
CFLAGS+= -I${.CURDIR:H} -I${SRCTOP}/contrib/tzcode/stdtime
WARNS?= 2
.if ${COMPILER_TYPE} == "gcc"
CWARNFLAGS+= -Wno-error=strict-overflow
.endif
.include <bsd.prog.mk>