The latest and greatest timezone code from Arthur David Olson, part 1.
This import comprises the `zic' and `zdump' programs. Obtained from: Arthur David Olson, ftp://elsie.nci.nih.gov/pub/tzcode94g
This commit is contained in:
commit
4872ce1251
72
usr.sbin/zic/README
Normal file
72
usr.sbin/zic/README
Normal file
@ -0,0 +1,72 @@
|
||||
@(#)README 7.5
|
||||
|
||||
"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 on 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.)
|
||||
|
||||
Support for the tz_abbr variable has been eliminated from this version
|
||||
(to forestall "kitchen sink" complaints from certain quarters :-).
|
||||
|
||||
Support for Turbo C compilation has also been eliminated; it was present to
|
||||
allow checking in an ANSI-style environment, and such checking is now done with
|
||||
gcc.
|
||||
|
||||
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.
|
||||
|
||||
Be sure to read the comments in "Makefile" and make any changes
|
||||
needed to make things right for your system.
|
||||
|
||||
To use the new functions, use a "-lz" option when compiling or linking.
|
||||
|
||||
Historical local time information has been included here not because it
|
||||
is particularly useful, but rather to:
|
||||
|
||||
* 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;
|
||||
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. None of them are responsible for remaining errors.
|
||||
|
||||
Look in the ~ftp/pub directory of elsie.nci.nih.gov (128.231.16.1)
|
||||
for updated versions of these files.
|
||||
|
||||
Please send comments or information to ado@elsie.nci.nih.gov.
|
120
usr.sbin/zic/Theory
Normal file
120
usr.sbin/zic/Theory
Normal file
@ -0,0 +1,120 @@
|
||||
@(#)Theory 7.2
|
||||
|
||||
These time and date functions are much like the System V Release 2.0 (SVR2)
|
||||
time and date functions; there are a few additions and changes to extend
|
||||
the usefulness of the SVR2 functions:
|
||||
|
||||
* In SVR2, time display in a process is controlled by the environment
|
||||
variable TZ, which "must be a three-letter time zone name, followed
|
||||
by a number representing the difference between local time and
|
||||
Greenwich Mean Time in hours, followed by an optional three-letter
|
||||
name for a daylight time zone;" when the optional daylight time zone is
|
||||
present, "standard U.S.A. Daylight Savings Time conversion is applied."
|
||||
This means that SVR2 can't deal with other (for example, Australian)
|
||||
daylight savings time rules, or situations where more than two
|
||||
time zone abbreviations are used in an area.
|
||||
|
||||
* In SVR2, time conversion information is compiled into each program
|
||||
that does time conversion. This means that when 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 SVR2, time conversion fails for near-minimum or near-maximum
|
||||
time_t values when doing conversions for places that don't use GMT.
|
||||
|
||||
* In SVR2, 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 GMT" to get
|
||||
around the problem, doing so is inconvenient and precludes handling
|
||||
daylight savings time shifts--as might be required to limit phone
|
||||
calls to off-peak hours.)
|
||||
|
||||
* These functions can account for leap seconds, thanks to Bradley White
|
||||
(bww@k.cs.cmu.edu).
|
||||
|
||||
These are the changes that have been made to the SVR2 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 "US/Eastern" 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 SVR2, 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 or supported. (You can use a compile-time option to cause
|
||||
these variables to be defined and to be 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.)
|
||||
|
||||
Points of interest to folks with Version 7 or BSD systems:
|
||||
|
||||
* The BSD "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 BSD gettimeofday function is not used in this package;
|
||||
this lets users control the time zone used in doing time conversions.
|
||||
Users who don't try to control things (that is, users who do not set
|
||||
the environment variable TZ) get the time conversion specified in the
|
||||
file "/etc/zoneinfo/localtime"; see the time zone compiler writeup for
|
||||
information on how to initialize this file.
|
||||
|
||||
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
|
||||
close to SVR2 (with the exceptions outlined above) to ensure its broad
|
||||
acceptability. If more powerful time conversion functions can be standardized,
|
||||
so much the better.
|
103
usr.sbin/zic/ialloc.c
Normal file
103
usr.sbin/zic/ialloc.c
Normal file
@ -0,0 +1,103 @@
|
||||
#ifndef lint
|
||||
#ifndef NOID
|
||||
static char elsieid[] = "@(#)ialloc.c 8.21";
|
||||
#endif /* !defined NOID */
|
||||
#endif /* !defined lint */
|
||||
|
||||
/*LINTLIBRARY*/
|
||||
|
||||
#include "private.h"
|
||||
|
||||
#ifdef MAL
|
||||
#define NULLMAL(x) ((x) == NULL || (x) == MAL)
|
||||
#endif /* defined MAL */
|
||||
#ifndef MAL
|
||||
#define NULLMAL(x) ((x) == NULL)
|
||||
#endif /* !defined MAL */
|
||||
|
||||
#define nonzero(n) (((n) == 0) ? 1 : (n))
|
||||
|
||||
char * icalloc P((int nelem, int elsize));
|
||||
char * icatalloc P((char * old, const char * new));
|
||||
char * icpyalloc P((const char * string));
|
||||
char * imalloc P((int n));
|
||||
char * irealloc P((char * pointer, int size));
|
||||
void ifree P((char * pointer));
|
||||
|
||||
char *
|
||||
imalloc(n)
|
||||
const int n;
|
||||
{
|
||||
#ifdef MAL
|
||||
register char * result;
|
||||
|
||||
result = malloc((alloc_size_t) nonzero(n));
|
||||
return NULLMAL(result) ? NULL : result;
|
||||
#endif /* defined MAL */
|
||||
#ifndef MAL
|
||||
return malloc((alloc_size_t) nonzero(n));
|
||||
#endif /* !defined MAL */
|
||||
}
|
||||
|
||||
char *
|
||||
icalloc(nelem, elsize)
|
||||
int nelem;
|
||||
int elsize;
|
||||
{
|
||||
if (nelem == 0 || elsize == 0)
|
||||
nelem = elsize = 1;
|
||||
return calloc((alloc_size_t) nelem, (alloc_size_t) elsize);
|
||||
}
|
||||
|
||||
char *
|
||||
irealloc(pointer, size)
|
||||
char * const pointer;
|
||||
const int size;
|
||||
{
|
||||
if (NULLMAL(pointer))
|
||||
return imalloc(size);
|
||||
return realloc((genericptr_t) pointer, (alloc_size_t) nonzero(size));
|
||||
}
|
||||
|
||||
char *
|
||||
icatalloc(old, new)
|
||||
char * const old;
|
||||
const char * const new;
|
||||
{
|
||||
register char * result;
|
||||
register int oldsize, newsize;
|
||||
|
||||
newsize = NULLMAL(new) ? 0 : strlen(new);
|
||||
if (NULLMAL(old))
|
||||
oldsize = 0;
|
||||
else if (newsize == 0)
|
||||
return old;
|
||||
else oldsize = strlen(old);
|
||||
if ((result = irealloc(old, oldsize + newsize + 1)) != NULL)
|
||||
if (!NULLMAL(new))
|
||||
(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 (!NULLMAL(p))
|
||||
(void) free(p);
|
||||
}
|
||||
|
||||
void
|
||||
icfree(p)
|
||||
char * const p;
|
||||
{
|
||||
if (!NULLMAL(p))
|
||||
(void) free(p);
|
||||
}
|
62
usr.sbin/zic/scheck.c
Normal file
62
usr.sbin/zic/scheck.c
Normal file
@ -0,0 +1,62 @@
|
||||
#ifndef lint
|
||||
#ifndef NOID
|
||||
static char elsieid[] = "@(#)scheck.c 8.11";
|
||||
#endif /* !defined lint */
|
||||
#endif /* !defined NOID */
|
||||
|
||||
/*LINTLIBRARY*/
|
||||
|
||||
#include "private.h"
|
||||
|
||||
extern char * imalloc P((int n));
|
||||
extern void ifree P((char * p));
|
||||
|
||||
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 char * result;
|
||||
char dummy;
|
||||
static char nada[1];
|
||||
|
||||
result = nada;
|
||||
if (string == NULL || format == NULL)
|
||||
return result;
|
||||
fbuf = imalloc(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 (isascii(*fp) && isdigit(*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;
|
||||
}
|
40
usr.sbin/zic/zdump.8
Normal file
40
usr.sbin/zic/zdump.8
Normal file
@ -0,0 +1,40 @@
|
||||
.TH ZDUMP 8
|
||||
.SH NAME
|
||||
zdump \- time zone dumper
|
||||
.SH SYNOPSIS
|
||||
.B zdump
|
||||
[
|
||||
.B \-v
|
||||
] [
|
||||
.B \-c
|
||||
cutoffyear ] [ zonename ... ]
|
||||
.SH DESCRIPTION
|
||||
.I Zdump
|
||||
prints the current time in each
|
||||
.I zonename
|
||||
named on the command line.
|
||||
.PP
|
||||
These options are available:
|
||||
.TP
|
||||
.B \-v
|
||||
For each
|
||||
.I zonename
|
||||
on the command line,
|
||||
print the current time,
|
||||
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
|
||||
.B isdst=1
|
||||
if the given time is Daylight Saving Time or
|
||||
.B isdst=0
|
||||
otherwise.
|
||||
.TP
|
||||
.BI "\-c " cutoffyear
|
||||
Cut off the verbose output near the start of the given year.
|
||||
.SH "SEE ALSO"
|
||||
newctime(3), tzfile(5), zic(8)
|
||||
.\" @(#)zdump.8 7.2
|
307
usr.sbin/zic/zdump.c
Normal file
307
usr.sbin/zic/zdump.c
Normal file
@ -0,0 +1,307 @@
|
||||
#ifndef lint
|
||||
#ifndef NOID
|
||||
static char elsieid[] = "@(#)zdump.c 7.10";
|
||||
#endif /* !defined NOID */
|
||||
#endif /* !defined 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 "stdio.h" /* for stdout, stderr */
|
||||
#include "string.h" /* for strcpy */
|
||||
#include "sys/types.h" /* for time_t */
|
||||
#include "time.h" /* for struct tm */
|
||||
|
||||
#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 */
|
||||
|
||||
extern char ** environ;
|
||||
extern int getopt();
|
||||
extern char * optarg;
|
||||
extern int optind;
|
||||
extern time_t time();
|
||||
extern char * tzname[2];
|
||||
extern void tzset();
|
||||
|
||||
#ifdef USG
|
||||
extern void exit();
|
||||
extern void perror();
|
||||
#endif /* defined USG */
|
||||
|
||||
static char * abbr();
|
||||
static long delta();
|
||||
static time_t hunt();
|
||||
static int longest;
|
||||
static char * progname;
|
||||
static void show();
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char * argv[];
|
||||
{
|
||||
register int i, c;
|
||||
register int vflag;
|
||||
register char * cutoff;
|
||||
register int cutyear;
|
||||
register long cuttime;
|
||||
time_t now;
|
||||
time_t t, newt;
|
||||
time_t hibit;
|
||||
struct tm tm, newtm;
|
||||
|
||||
progname = argv[0];
|
||||
vflag = 0;
|
||||
cutoff = NULL;
|
||||
while ((c = getopt(argc, argv, "c:v")) == 'c' || c == 'v')
|
||||
if (c == 'v')
|
||||
vflag = 1;
|
||||
else cutoff = optarg;
|
||||
if (c != EOF ||
|
||||
(optind == argc - 1 && strcmp(argv[optind], "=") == 0)) {
|
||||
(void) fprintf(stderr,
|
||||
"%s: usage is %s [ -v ] [ -c cutoff ] zonename ...\n",
|
||||
argv[0], argv[0]);
|
||||
(void) exit(EXIT_FAILURE);
|
||||
}
|
||||
if (cutoff != NULL) {
|
||||
int y;
|
||||
|
||||
cutyear = atoi(cutoff);
|
||||
cuttime = 0;
|
||||
for (y = EPOCH_YEAR; y < cutyear; ++y)
|
||||
cuttime += DAYSPERNYEAR + isleap(y);
|
||||
cuttime *= SECSPERHOUR * HOURSPERDAY;
|
||||
}
|
||||
(void) time(&now);
|
||||
longest = 0;
|
||||
for (i = optind; i < argc; ++i)
|
||||
if (strlen(argv[i]) > longest)
|
||||
longest = strlen(argv[i]);
|
||||
for (hibit = 1; (hibit << 1) != 0; hibit <<= 1)
|
||||
continue;
|
||||
for (i = optind; i < argc; ++i) {
|
||||
register char ** saveenv;
|
||||
static char buf[MAX_STRING_LENGTH];
|
||||
char * fakeenv[2];
|
||||
|
||||
if (strlen(argv[i]) + 4 > sizeof buf) {
|
||||
(void) fflush(stdout);
|
||||
(void) fprintf(stderr, "%s: argument too long -- %s\n",
|
||||
progname, argv[i]);
|
||||
(void) exit(EXIT_FAILURE);
|
||||
}
|
||||
(void) strcpy(buf, "TZ=");
|
||||
(void) strcat(buf, argv[i]);
|
||||
fakeenv[0] = buf;
|
||||
fakeenv[1] = NULL;
|
||||
saveenv = environ;
|
||||
environ = fakeenv;
|
||||
(void) tzset();
|
||||
environ = saveenv;
|
||||
show(argv[i], now, FALSE);
|
||||
if (!vflag)
|
||||
continue;
|
||||
/*
|
||||
** Get lowest value of t.
|
||||
*/
|
||||
t = hibit;
|
||||
if (t > 0) /* time_t is unsigned */
|
||||
t = 0;
|
||||
show(argv[i], t, TRUE);
|
||||
t += SECSPERHOUR * HOURSPERDAY;
|
||||
show(argv[i], t, TRUE);
|
||||
tm = *localtime(&t);
|
||||
(void) strncpy(buf, abbr(&tm), (sizeof buf) - 1);
|
||||
for ( ; ; ) {
|
||||
if (cutoff != NULL && t >= cuttime)
|
||||
break;
|
||||
newt = t + SECSPERHOUR * 12;
|
||||
if (cutoff != NULL && newt >= cuttime)
|
||||
break;
|
||||
if (newt <= t)
|
||||
break;
|
||||
newtm = *localtime(&newt);
|
||||
if (delta(&newtm, &tm) != (newt - t) ||
|
||||
newtm.tm_isdst != tm.tm_isdst ||
|
||||
strcmp(abbr(&newtm), buf) != 0) {
|
||||
newt = hunt(argv[i], t, newt);
|
||||
newtm = *localtime(&newt);
|
||||
(void) strncpy(buf, abbr(&newtm),
|
||||
(sizeof buf) - 1);
|
||||
}
|
||||
t = newt;
|
||||
tm = newtm;
|
||||
}
|
||||
/*
|
||||
** Get highest value of t.
|
||||
*/
|
||||
t = ~((time_t) 0);
|
||||
if (t < 0) /* time_t is signed */
|
||||
t &= ~hibit;
|
||||
t -= SECSPERHOUR * HOURSPERDAY;
|
||||
show(argv[i], t, TRUE);
|
||||
t += SECSPERHOUR * HOURSPERDAY;
|
||||
show(argv[i], t, TRUE);
|
||||
}
|
||||
if (fflush(stdout) || ferror(stdout)) {
|
||||
(void) fprintf(stderr, "%s: Error writing standard output ",
|
||||
argv[0]);
|
||||
(void) perror("standard output");
|
||||
(void) exit(EXIT_FAILURE);
|
||||
}
|
||||
exit(EXIT_SUCCESS);
|
||||
|
||||
/* gcc -Wall pacifier */
|
||||
for ( ; ; )
|
||||
continue;
|
||||
}
|
||||
|
||||
static time_t
|
||||
hunt(name, lot, hit)
|
||||
char * name;
|
||||
time_t lot;
|
||||
time_t hit;
|
||||
{
|
||||
time_t t;
|
||||
struct tm lotm;
|
||||
struct tm tm;
|
||||
static char loab[MAX_STRING_LENGTH];
|
||||
|
||||
lotm = *localtime(&lot);
|
||||
(void) strncpy(loab, abbr(&lotm), (sizeof loab) - 1);
|
||||
while ((hit - lot) >= 2) {
|
||||
t = lot / 2 + hit / 2;
|
||||
if (t <= lot)
|
||||
++t;
|
||||
else if (t >= hit)
|
||||
--t;
|
||||
tm = *localtime(&t);
|
||||
if (delta(&tm, &lotm) == (t - lot) &&
|
||||
tm.tm_isdst == lotm.tm_isdst &&
|
||||
strcmp(abbr(&tm), loab) == 0) {
|
||||
lot = t;
|
||||
lotm = tm;
|
||||
} else hit = t;
|
||||
}
|
||||
show(name, lot, TRUE);
|
||||
show(name, hit, TRUE);
|
||||
return hit;
|
||||
}
|
||||
|
||||
/*
|
||||
** Thanks to Paul Eggert (eggert@twinsun.com) for logic used in delta.
|
||||
*/
|
||||
|
||||
static long
|
||||
delta(newp, oldp)
|
||||
struct tm * newp;
|
||||
struct tm * oldp;
|
||||
{
|
||||
long result;
|
||||
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(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(zone, t, v)
|
||||
char * zone;
|
||||
time_t t;
|
||||
int v;
|
||||
{
|
||||
struct tm * tmp;
|
||||
extern struct tm * localtime();
|
||||
|
||||
(void) printf("%-*s ", longest, zone);
|
||||
if (v)
|
||||
(void) printf("%.24s GMT = ", asctime(gmtime(&t)));
|
||||
tmp = localtime(&t);
|
||||
(void) printf("%.24s", asctime(tmp));
|
||||
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");
|
||||
}
|
||||
|
||||
static char *
|
||||
abbr(tmp)
|
||||
struct tm * tmp;
|
||||
{
|
||||
register char * result;
|
||||
static char nada[1];
|
||||
|
||||
if (tmp->tm_isdst != 0 && tmp->tm_isdst != 1)
|
||||
return nada;
|
||||
result = tzname[tmp->tm_isdst];
|
||||
return (result == NULL) ? nada : result;
|
||||
}
|
412
usr.sbin/zic/zic.8
Normal file
412
usr.sbin/zic/zic.8
Normal file
@ -0,0 +1,412 @@
|
||||
.TH ZIC 8
|
||||
.SH NAME
|
||||
zic \- time zone compiler
|
||||
.SH SYNOPSIS
|
||||
.B zic
|
||||
[
|
||||
.B \-v
|
||||
] [
|
||||
.B \-d
|
||||
.I directory
|
||||
] [
|
||||
.B \-l
|
||||
.I localtime
|
||||
] [
|
||||
.B \-p
|
||||
.I posixrules
|
||||
] [
|
||||
.B \-L
|
||||
.I leapsecondfilename
|
||||
] [
|
||||
.B \-s
|
||||
] [
|
||||
.B \-y
|
||||
.I command
|
||||
] [
|
||||
.I filename
|
||||
\&... ]
|
||||
.SH DESCRIPTION
|
||||
.if t .ds lq ``
|
||||
.if t .ds rq ''
|
||||
.if n .ds lq \&"\"
|
||||
.if n .ds rq \&"\"
|
||||
.de q
|
||||
\\$3\*(lq\\$1\*(rq\\$2
|
||||
..
|
||||
.I Zic
|
||||
reads text from the file(s) named on the command line
|
||||
and creates the time conversion information files specified in this input.
|
||||
If a
|
||||
.I filename
|
||||
is
|
||||
.BR \- ,
|
||||
the standard input is read.
|
||||
.PP
|
||||
These options are available:
|
||||
.TP
|
||||
.BI "\-d " directory
|
||||
Create time conversion information files in the named directory rather than
|
||||
in the standard directory named below.
|
||||
.TP
|
||||
.BI "\-l " timezone
|
||||
Use the given time zone as local time.
|
||||
.I Zic
|
||||
will act as if the input contained a link line of the form
|
||||
.sp
|
||||
.ti +.5i
|
||||
Link \fItimezone\fP localtime
|
||||
.TP
|
||||
.BI "\-p " timezone
|
||||
Use the given time zone's rules when handling POSIX-format
|
||||
time zone environment variables.
|
||||
.I Zic
|
||||
will act as if the input contained a link line of the form
|
||||
.sp
|
||||
.ti +.5i
|
||||
Link \fItimezone\fP posixrules
|
||||
.TP
|
||||
.BI "\-L " 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.
|
||||
.TP
|
||||
.B \-v
|
||||
Complain if a year that appears in a data file is outside the range
|
||||
of years representable by
|
||||
.IR time (2)
|
||||
values.
|
||||
.TP
|
||||
.B \-s
|
||||
Limit time values stored in output files to values that are the same
|
||||
whether they're taken to be signed or unsigned.
|
||||
You can use this option to generate SVVS-compatible files.
|
||||
.TP
|
||||
.BI "\-y " command
|
||||
Use the given
|
||||
.I command
|
||||
rather than
|
||||
.B yearistype
|
||||
when checking year types (see below).
|
||||
.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're 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
|
||||
A rule line has the form
|
||||
.nf
|
||||
.ti +.5i
|
||||
.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
|
||||
.sp
|
||||
For example:
|
||||
.ti +.5i
|
||||
.sp
|
||||
Rule US 1967 1973 \- Apr lastSun 2:00 1:00 D
|
||||
.sp
|
||||
.fi
|
||||
The fields that make up a rule line are:
|
||||
.TP "\w'LETTER/S'u"
|
||||
.B NAME
|
||||
Gives the (arbitrary) name of the set of rules this rule is part of.
|
||||
.TP
|
||||
.B FROM
|
||||
Gives the first year in which the rule applies.
|
||||
Any integer year can be supplied; the Gregorian calendar is assumed.
|
||||
The word
|
||||
.B minimum
|
||||
(or an abbreviation) means the minimum year representable as an integer.
|
||||
The word
|
||||
.B 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.
|
||||
.TP
|
||||
.B TO
|
||||
Gives the final year in which the rule applies.
|
||||
In addition to
|
||||
.B minimum
|
||||
and
|
||||
.B maximum
|
||||
(as above),
|
||||
the word
|
||||
.B only
|
||||
(or an abbreviation)
|
||||
may be used to repeat the value of the
|
||||
.B FROM
|
||||
field.
|
||||
.TP
|
||||
.B TYPE
|
||||
Gives the type of year in which the rule applies.
|
||||
If
|
||||
.B TYPE
|
||||
is
|
||||
.B \-
|
||||
then the rule applies in all years between
|
||||
.B FROM
|
||||
and
|
||||
.B TO
|
||||
inclusive;
|
||||
if
|
||||
.B TYPE
|
||||
is
|
||||
.BR uspres ,
|
||||
the rule applies in U.S. Presidential election years;
|
||||
if
|
||||
.B TYPE
|
||||
is
|
||||
.BR nonpres ,
|
||||
the rule applies in years other than U.S. Presidential election years.
|
||||
If
|
||||
.B TYPE
|
||||
is something else, then
|
||||
.I zic
|
||||
executes the command
|
||||
.ti +.5i
|
||||
\fByearistype\fP \fIyear\fP \fItype\fP
|
||||
.br
|
||||
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.
|
||||
.TP
|
||||
.B IN
|
||||
Names the month in which the rule takes effect.
|
||||
Month names may be abbreviated.
|
||||
.TP
|
||||
.B ON
|
||||
Gives the day on which the rule takes effect.
|
||||
Recognized forms include:
|
||||
.nf
|
||||
.in +.5i
|
||||
.sp
|
||||
.ta \w'Sun<=25\0\0'u
|
||||
5 the fifth of the month
|
||||
lastSun the last Sunday in the month
|
||||
lastMon the last Monday in the month
|
||||
Sun>=8 first Sunday on or after the eighth
|
||||
Sun<=25 last Sunday on or before the 25th
|
||||
.fi
|
||||
.in -.5i
|
||||
.sp
|
||||
Names of days of the week may be abbreviated or spelled out in full.
|
||||
Note that there must be no spaces within the
|
||||
.B ON
|
||||
field.
|
||||
.TP
|
||||
.B AT
|
||||
Gives the time of day at which the rule takes effect.
|
||||
Recognized forms include:
|
||||
.nf
|
||||
.in +.5i
|
||||
.sp
|
||||
.ta \w'1:28:13\0\0'u
|
||||
2 time in hours
|
||||
2:00 time in hours and minutes
|
||||
15:00 24-hour format time (for times after noon)
|
||||
1:28:14 time in hours, minutes, and seconds
|
||||
.fi
|
||||
.in -.5i
|
||||
.sp
|
||||
Any of these forms may be followed by the letter
|
||||
.B w
|
||||
if the given time is local
|
||||
.q "wall clock"
|
||||
time or
|
||||
.B s
|
||||
if the given time is local
|
||||
.q standard
|
||||
time; in the absence of
|
||||
.B w
|
||||
or
|
||||
.BR s ,
|
||||
wall clock time is assumed.
|
||||
.TP
|
||||
.B SAVE
|
||||
Gives 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
|
||||
.B AT
|
||||
field
|
||||
(although, of course, the
|
||||
.B w
|
||||
and
|
||||
.B s
|
||||
suffixes are not used).
|
||||
.TP
|
||||
.B LETTER/S
|
||||
Gives the
|
||||
.q "variable part"
|
||||
(for example, the
|
||||
.q S
|
||||
or
|
||||
.q D
|
||||
in
|
||||
.q EST
|
||||
or
|
||||
.q EDT )
|
||||
of time zone abbreviations to be used when this rule is in effect.
|
||||
If this field is
|
||||
.BR \- ,
|
||||
the variable part is null.
|
||||
.PP
|
||||
A zone line has the form
|
||||
.sp
|
||||
.nf
|
||||
.ti +.5i
|
||||
.ta \w'Zone\0\0'u +\w'Australia/Adelaide\0\0'u +\w'GMTOFF\0\0'u +\w'RULES/SAVE\0\0'u +\w'FORMAT\0\0'u
|
||||
Zone NAME GMTOFF RULES/SAVE FORMAT [UNTIL]
|
||||
.sp
|
||||
For example:
|
||||
.sp
|
||||
.ti +.5i
|
||||
Zone Australia/Adelaide 9:30 Aus CST 1971 Oct 31 2:00
|
||||
.sp
|
||||
.fi
|
||||
The fields that make up a zone line are:
|
||||
.TP "\w'GMTOFF'u"
|
||||
.B NAME
|
||||
The name of the time zone.
|
||||
This is the name used in creating the time conversion information file for the
|
||||
zone.
|
||||
.TP
|
||||
.B GMTOFF
|
||||
The amount of time to add to GMT to get standard time in this zone.
|
||||
This field has the same format as the
|
||||
.B AT
|
||||
and
|
||||
.B SAVE
|
||||
fields of rule lines;
|
||||
begin the field with a minus sign if time must be subtracted from GMT.
|
||||
.TP
|
||||
.B 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
|
||||
.B \-
|
||||
then standard time always applies in the time zone.
|
||||
.TP
|
||||
.B FORMAT
|
||||
The format for time zone abbreviations in this time zone.
|
||||
The pair of characters
|
||||
.B %s
|
||||
is used to show where the
|
||||
.q "variable part"
|
||||
of the time zone abbreviation goes.
|
||||
.TP
|
||||
.B UNTIL
|
||||
The time at which the GMT 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 GMT offset
|
||||
and rule change until the time specified.
|
||||
.IP
|
||||
The next line must be a
|
||||
.q continuation
|
||||
line; this has the same form as a zone line except that the
|
||||
string
|
||||
.q Zone
|
||||
and the name are omitted, as the continuation line will
|
||||
place information starting at the time specified as the
|
||||
.B UNTIL
|
||||
field in the previous line in the file used by the previous line.
|
||||
Continuation lines may contain an
|
||||
.B UNTIL
|
||||
field, just as zone lines do, indicating that the next line is a further
|
||||
continuation.
|
||||
.PP
|
||||
A link line has the form
|
||||
.sp
|
||||
.nf
|
||||
.ti +.5i
|
||||
.if t .ta \w'Link\0\0'u +\w'LINK-FROM\0\0'u
|
||||
.if n .ta \w'Link\0\0'u +\w'US/Eastern\0\0'u
|
||||
Link LINK-FROM LINK-TO
|
||||
.sp
|
||||
For example:
|
||||
.sp
|
||||
.ti +.5i
|
||||
Link US/Eastern EST5EDT
|
||||
.sp
|
||||
.fi
|
||||
The
|
||||
.B LINK-FROM
|
||||
field should appear as the
|
||||
.B NAME
|
||||
field in some zone line;
|
||||
the
|
||||
.B 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:
|
||||
.nf
|
||||
.ti +.5i
|
||||
.ta \w'Leap\0\0'u +\w'YEAR\0\0'u +\w'MONTH\0\0'u +\w'DAY\0\0'u +\w'HH:MM:SS\0\0'u +\w'CORR\0\0'u
|
||||
.sp
|
||||
Leap YEAR MONTH DAY HH:MM:SS CORR R/S
|
||||
.sp
|
||||
For example:
|
||||
.ti +.5i
|
||||
.sp
|
||||
Leap 1974 Dec 31 23:59:60 + S
|
||||
.sp
|
||||
.fi
|
||||
The
|
||||
.BR YEAR ,
|
||||
.BR MONTH ,
|
||||
.BR DAY ,
|
||||
and
|
||||
.B HH:MM:SS
|
||||
fields tell when the leap second happened.
|
||||
The
|
||||
.B CORR
|
||||
field
|
||||
should be
|
||||
.q +
|
||||
if a second was added
|
||||
or
|
||||
.q -
|
||||
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
|
||||
.B R/S
|
||||
field
|
||||
should be (an abbreviation of)
|
||||
.q Stationary
|
||||
if the leap second time given by the other fields should be interpreted as GMT
|
||||
or
|
||||
(an abbreviation of)
|
||||
.q Rolling
|
||||
if the leap second time given by the other fields should be interpreted as
|
||||
local wall clock time.
|
||||
.SH NOTE
|
||||
For areas with more than two types of local time,
|
||||
you may need to use local standard time in the
|
||||
.B AT
|
||||
field of the earliest transition time's rule to ensure that
|
||||
the earliest transition time recorded in the compiled file is correct.
|
||||
.SH FILE
|
||||
/usr/local/etc/zoneinfo standard directory used for created files
|
||||
.SH "SEE ALSO"
|
||||
newctime(3), tzfile(5), zdump(8)
|
||||
.\" @(#)zic.8 7.7
|
1939
usr.sbin/zic/zic.c
Normal file
1939
usr.sbin/zic/zic.c
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user