From contrib/tzcode:
The Makefiles are leftovers from the copies and should live in usr.sbin/zic/* From usr.sbin/zic: The sources are from a vendor contributed source, therefore should live in contrib/tzcode/zic.
This commit is contained in:
parent
bee10047c0
commit
97dcdbd450
@ -1,8 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
# Vendor contact: tz@elsie.nci.nih.gov
|
||||
MAINTAINER= wollman@FreeBSD.org
|
||||
|
||||
SUBDIR= zic zdump
|
||||
|
||||
.include <bsd.subdir.mk>
|
@ -1,3 +0,0 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.include "${.CURDIR}/../../Makefile.inc"
|
@ -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.
|
@ -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);
|
||||
}
|
@ -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--see zic manual page"
|
||||
|
||||
/*
|
||||
** 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 */
|
@ -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;
|
||||
}
|
@ -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
|
@ -1,675 +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) && isalpha((unsigned char) *cp))
|
||||
++cp;
|
||||
if (cp - abbrp == 0)
|
||||
wp = _("lacks alphabetic at start");
|
||||
else if (cp - abbrp < 3)
|
||||
wp = _("has fewer than 3 alphabetics");
|
||||
else if (cp - abbrp > 6)
|
||||
wp = _("has more than 6 alphabetics");
|
||||
if (wp == NULL && (*cp == '+' || *cp == '-')) {
|
||||
++cp;
|
||||
if (isascii((unsigned char) *cp) &&
|
||||
isdigit((unsigned char) *cp))
|
||||
if (*cp++ == '1' && *cp >= '0' && *cp <= '4')
|
||||
++cp;
|
||||
if (*cp != '\0')
|
||||
wp = _("differs from POSIX standard");
|
||||
}
|
||||
if (wp == NULL)
|
||||
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;
|
||||
|
||||
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));
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/..
|
||||
.PATH: ${.CURDIR}/../../../contrib/tzcode/zic
|
||||
|
||||
PROG= zdump
|
||||
MAN= zdump.8
|
||||
|
@ -1,465 +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
|
||||
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.5
|
||||
.\" This file is in the public domain, so clarified as of
|
||||
.\" 2009-05-17 by Arthur David Olson.
|
2723
usr.sbin/zic/zic.c
2723
usr.sbin/zic/zic.c
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/..
|
||||
.PATH: ${.CURDIR}/../../../contrib/tzcode/zic
|
||||
|
||||
PROG= zic
|
||||
MAN= zic.8
|
||||
|
Loading…
Reference in New Issue
Block a user