Added TZ_LINK_INTL option

This commit is contained in:
spectranator
2025-06-15 03:54:09 +02:00
parent dee5dca459
commit 25c6aaec18
70 changed files with 48094 additions and 4 deletions

3
.gitmodules vendored
View File

@@ -31,9 +31,6 @@
[submodule "libadrenotools"]
path = externals/libadrenotools
url = https://github.com/bylaws/libadrenotools.git
[submodule "tzdb_to_nx"]
path = externals/nx_tzdb/tzdb_to_nx
url = https://github.com/lat9nq/tzdb_to_nx.git
[submodule "simpleini"]
path = externals/simpleini
url = https://github.com/brofield/simpleini.git

View File

@@ -0,0 +1,52 @@
name: CMake
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: Release
jobs:
build:
# The CMake configure and build commands are platform agnostic and should work equally well on Windows or Mac.
# You can convert this to a matrix build if you need cross-platform coverage.
# See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
strategy:
matrix:
platform: [ubuntu-latest,macos-latest]
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v3
with:
submodules: 'true'
- name: Configure CMake
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
run: |
cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
echo "nx_tzdb_dir=$(grep NX_TZDB_DIR ${{github.workspace}}/build/CMakeCache.txt | sed 's/.*=//g')" > "$GITHUB_ENV"
- name: Build
# Build your program with the given configuration
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --target x80e
- name: Package
run: |
mkdir -p ${{github.workspace}}/artifacts
cp -Rv ${{ env.nx_tzdb_dir }} ${{github.workspace}}/artifacts/
- name: Version
run: |
echo "nx_version=$(cat ${{ env.nx_tzdb_dir }}/version.txt)" > "$GITHUB_ENV"
- name: Upload
uses: actions/upload-artifact@v3
with:
name: ${{ env.nx_version }}_${{ matrix.platform }}
path: artifacts/nx

View File

@@ -0,0 +1,2 @@
.cache
build

View File

@@ -0,0 +1,3 @@
[submodule "externals/tz/tz"]
path = externals/tz/tz
url = https://github.com/eggert/tz.git

View File

@@ -0,0 +1,21 @@
cmake_minimum_required(VERSION 3.10)
project(tzdb2nx VERSION 1.0)
option(TZDB2NX_ZONEINFO_DIR "Specify a custom zoneinfo directory containing time zone data you wish to use" "")
option(TZDB2NX_VERSION "Specify a custom zoneinfo version with the directory" "")
if (TZDB2NX_ZONEINFO_DIR AND NOT TZDB2NX_VERSION)
message(FATAL_ERROR "TZDB2NX_ZONEINFO_DIR was specified but TZDB2NX_VERSION was left undefined.")
endif()
set(CMAKE_CXX_STANDARD 20)
option(TZ_LINK_INTL "Enable if gettext needs to link with libintl" ${APPLE})
if (TZ_LINK_INTL)
find_package(Intl REQUIRED)
endif()
add_subdirectory(externals)
add_subdirectory(src)

View File

@@ -0,0 +1,10 @@
set(WITH_DIRECTORIES ${CMAKE_ARGV3})
set(RECURSE ${CMAKE_ARGV4})
set(HOW_TO_GLOB "GLOB")
if (RECURSE)
set(HOW_TO_GLOB "GLOB_RECURSE")
endif()
file(${HOW_TO_GLOB} FILE_LIST LIST_DIRECTORIES ${WITH_DIRECTORIES} RELATIVE ${CMAKE_SOURCE_DIR} "*")
execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${FILE_LIST};")

21
externals/nx_tzdb/tzdb_to_nx/LICENSE vendored Normal file
View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright © 2023 lat9nq
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the “Software”), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

22
externals/nx_tzdb/tzdb_to_nx/README.md vendored Normal file
View File

@@ -0,0 +1,22 @@
# tzdb_to_nx
This is a CMake/C++ project to convert RFC 8536 time zone data to the Nintendo Switch's format.
This makes use a lot of Unix system calls as well as a bash script to convert the data, so it likely requires a bit of work to port to a non-POSIX platform, such as Windows.
Intended for use with the [yuzu Emulator](https://yuzu-emu.org/) project, but the project in the future likely won't ship synthesized Switch archives.
That leaves this project in a place where it is not likely to be used, but will remain here as a reference.
- tzdb: CMake and bash script to build and convert time zone data from https://www.iana.org/time-zones into the Nintendo Switch's format.
- tzdb2nx: C++ program that converts a single tzif file to the Nintendo's format.
The fine folks over at [SwitchBrew](https://switchbrew.org/wiki/PSC_services#ITimeZoneService) have left very helpful information on reading the data.
Nintendo's file is simply the TZif version 2 data, with standard_indicators and ut_indicators data stripped out (and the necessary modifications needed in the header to make the data valid).
This means the TZif 1 data is not present, so essentially we are left with the second half of each file.
Nintendo also does not seem to run the `zic` program on their output when they build the time zone data.
I have left the relevant build command for that in src/tzdb/CMakeLists.txt commented out, but it isn't used here.
This lets the project produce data identical to Nintendo's firmware for time zones, however this code does not produce the time zone data on US/Pacific-New or America/East-Saskatchewan (I may have bunged up the actual paths for these as this is 3 day old memory).
The CMake and C++ code in this repository is licensed under the MIT License.
The source files date.c, newstrftime.3 and strftime.c from submodule eggert/tz use the BSD-3 clause license [[source]](https://github.com/eggert/tz/blob/main/LICENSE).
The time zone data output from this repository, like those found in archives in the Release setcion, is in the public domain [[source]](https://github.com/eggert/tz/blob/main/LICENSE).

View File

@@ -0,0 +1 @@
add_subdirectory(tz)

View File

@@ -0,0 +1,73 @@
set(TZ_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/tz" CACHE PATH "Time zone source directory")
set(TZ_DIR "${CMAKE_CURRENT_BINARY_DIR}/tz")
set(TZ_TMP_SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/tmpsrc")
set(TZIF_LIST_FILE "${CMAKE_CURRENT_BINARY_DIR}/tzif_list.txt" CACHE PATH "List of zone info files")
if (TZDB2NX_ZONEINFO_DIR)
set(TZ_ZONEINFO_DIR "${TZDB2NX_ZONEINFO_DIR}" CACHE PATH "Time zone info data directory")
else()
set(TZ_ZONEINFO_DIR "${TZ_DIR}/usr/share/zoneinfo" CACHE PATH "Time zone info data directory")
endif()
find_program(GNU_MAKE make)
if (NOT GNU_MAKE)
message(FATAL_ERROR "GNU make not found")
endif()
if (NOT EXISTS "${TZ_DIR}" OR NOT EXISTS "${TZIF_LIST_FILE}")
if (NOT TZDB2NX_ZONEINFO_DIR) # If a custom zoneinfo directory was specified
# tz's makefile can only build in-tree, so copy the whole source tree to a
# separate directory before building.
execute_process(
COMMAND
${CMAKE_COMMAND} -E copy_directory "${TZ_SOURCE_DIR}" "${TZ_TMP_SOURCE_DIR}"
COMMAND_ERROR_IS_FATAL ANY
)
if (TZ_LINK_INTL)
set(TZ_MAKEFLAGS "LDLIBS=${Intl_LIBRARY}")
else()
set(TZ_MAKEFLAGS)
endif()
execute_process(
COMMAND
${GNU_MAKE} DESTDIR=${TZ_DIR} ${TZ_MAKEFLAGS} install
WORKING_DIRECTORY
${TZ_TMP_SOURCE_DIR}
COMMAND_ERROR_IS_FATAL ANY
)
unset(TZ_MAKEFLAGS)
# Step taken by Arch Linux packaging, but Nintendo apparently skips it
# execute_process(
# COMMAND
# "${TZDB_LOCATION}/zic" -b fat -d ${TZDB_ZONEINFO} africa antarctica asia australasia europe northamerica southamerica etcetera backward factory
# WORKING_DIRECTORY
# "${TZDB_LOCATION}"
# COMMAND_ERROR_IS_FATAL ANY
# )
endif()
execute_process(
COMMAND
${CMAKE_COMMAND} -P ${PROJECT_SOURCE_DIR}/CMakeModules/list_directory.cmake false ON
WORKING_DIRECTORY
"${TZ_ZONEINFO_DIR}"
OUTPUT_VARIABLE
TZIF_SCAN
)
set(TZIF_LIST "")
foreach(CANDIDATE ${TZIF_SCAN})
if (CANDIDATE STREQUAL "\n")
continue()
endif()
set(TZIF_FILE "${TZ_ZONEINFO_DIR}/${CANDIDATE}")
file(READ "${TZIF_FILE}" HEADER LIMIT 4)
string(SUBSTRING "${HEADER}" 0 4 HEADER) # Remove trailing newline
if (HEADER STREQUAL "TZif")
file(APPEND "${TZIF_LIST_FILE}" "${TZIF_FILE}\n")
endif()
endforeach()
endif()

View File

@@ -0,0 +1,26 @@
# Files intentionally not tracked by Git.
# This file is in the public domain.
*.a
*.asc
*.diff
*.i
*.o
*.orig
*.patch
*.rej
*.tar
*.tar.*
*.txt
*.tzs
*.zi
*~
ChangeLog
check_*
date
leapseconds
tzselect
version
version.h
yearistype
zdump
zic

View File

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

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,309 @@
# tzdb data for Antarctica and environs
# This file is in the public domain, so clarified as of
# 2009-05-17 by Arthur David Olson.
# From Paul Eggert (1999-11-15):
# To keep things manageable, we list only locations occupied year-round; see
# COMNAP - Stations and Bases
# http://www.comnap.aq/comnap/comnap.nsf/P/Stations/
# and
# Summary of the Peri-Antarctic Islands (1998-07-23)
# http://www.spri.cam.ac.uk/bob/periant.htm
# for information.
# Unless otherwise specified, we have no time zone information.
# FORMAT is '-00' and STDOFF is 0 for locations while uninhabited.
# Argentina - year-round bases
# Belgrano II, Confin Coast, -770227-0343737, since 1972-02-05
# Carlini, Potter Cove, King George Island, -6414-0602320, since 1982-01
# Esperanza, Hope Bay, -6323-05659, since 1952-12-17
# Marambio, -6414-05637, since 1969-10-29
# Orcadas, Laurie I, -6016-04444, since 1904-02-22
# San Martín, Barry I, -6808-06706, since 1951-03-21
# (except 1960-03 / 1976-03-21)
# Australia - territories
# Heard Island, McDonald Islands (uninhabited)
# previously sealers and scientific personnel wintered
# Margaret Turner reports
# https://web.archive.org/web/20021204222245/http://www.dstc.qut.edu.au/DST/marg/daylight.html
# (1999-09-30) that they're UT +05, with no DST;
# presumably this is when they have visitors.
#
# year-round bases
# Casey, Bailey Peninsula, -6617+11032, since 1969
# Davis, Vestfold Hills, -6835+07759, since 1957-01-13
# (except 1964-11 - 1969-02)
# Mawson, Holme Bay, -6736+06253, since 1954-02-13
# From Steffen Thorsen (2009-03-11):
# Three Australian stations in Antarctica have changed their time zone:
# Casey moved from UTC+8 to UTC+11
# Davis moved from UTC+7 to UTC+5
# Mawson moved from UTC+6 to UTC+5
# The changes occurred on 2009-10-18 at 02:00 (local times).
#
# Government source: (Australian Antarctic Division)
# http://www.aad.gov.au/default.asp?casid=37079
#
# We have more background information here:
# https://www.timeanddate.com/news/time/antarctica-new-times.html
# From Steffen Thorsen (2010-03-10):
# We got these changes from the Australian Antarctic Division: ...
#
# - Casey station reverted to its normal time of UTC+8 on 5 March 2010.
# The change to UTC+11 is being considered as a regular summer thing but
# has not been decided yet.
#
# - Davis station will revert to its normal time of UTC+7 at 10 March 2010
# 20:00 UTC.
#
# - Mawson station stays on UTC+5.
#
# Background:
# https://www.timeanddate.com/news/time/antartica-time-changes-2010.html
# From Steffen Thorsen (2016-10-28):
# Australian Antarctica Division informed us that Casey changed time
# zone to UTC+11 in "the morning of 22nd October 2016".
# From Steffen Thorsen (2020-10-02, as corrected):
# Based on information we have received from the Australian Antarctic
# Division, Casey station and Macquarie Island station will move to Tasmanian
# daylight savings time on Sunday 4 October. This will take effect from 0001
# hrs on Sunday 4 October 2020 and will mean Casey and Macquarie Island will
# be on the same time zone as Hobart. Some past dates too for this 3 hour
# time change back and forth between UTC+8 and UTC+11 for Casey:
# - 2018 Oct 7 4:00 - 2019 Mar 17 3:00 - 2019 Oct 4 3:00 - 2020 Mar 8 3:00
# and now - 2020 Oct 4 0:01
# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Antarctica/Casey 0 - -00 1969
8:00 - +08 2009 Oct 18 2:00
11:00 - +11 2010 Mar 5 2:00
8:00 - +08 2011 Oct 28 2:00
11:00 - +11 2012 Feb 21 17:00u
8:00 - +08 2016 Oct 22
11:00 - +11 2018 Mar 11 4:00
8:00 - +08 2018 Oct 7 4:00
11:00 - +11 2019 Mar 17 3:00
8:00 - +08 2019 Oct 4 3:00
11:00 - +11 2020 Mar 8 3:00
8:00 - +08 2020 Oct 4 0:01
11:00 - +11
Zone Antarctica/Davis 0 - -00 1957 Jan 13
7:00 - +07 1964 Nov
0 - -00 1969 Feb
7:00 - +07 2009 Oct 18 2:00
5:00 - +05 2010 Mar 10 20:00u
7:00 - +07 2011 Oct 28 2:00
5:00 - +05 2012 Feb 21 20:00u
7:00 - +07
Zone Antarctica/Mawson 0 - -00 1954 Feb 13
6:00 - +06 2009 Oct 18 2:00
5:00 - +05
# References:
# Casey Weather (1998-02-26)
# http://www.antdiv.gov.au/aad/exop/sfo/casey/casey_aws.html
# Davis Station, Antarctica (1998-02-26)
# http://www.antdiv.gov.au/aad/exop/sfo/davis/video.html
# Mawson Station, Antarctica (1998-02-25)
# http://www.antdiv.gov.au/aad/exop/sfo/mawson/video.html
# Belgium - year-round base
# Princess Elisabeth, Queen Maud Land, -713412+0231200, since 2007
# Brazil - year-round base
# Ferraz, King George Island, -6205+05824, since 1983/4
# Bulgaria - year-round base
# St. Kliment Ohridski, Livingston Island, -623829-0602153, since 1988
# Chile - year-round bases and towns
# Escudero, South Shetland Is, -621157-0585735, since 1994
# Frei Montalva, King George Island, -6214-05848, since 1969-03-07
# O'Higgins, Antarctic Peninsula, -6319-05704, since 1948-02
# Prat, -6230-05941
# Villa Las Estrellas (a town), around the Frei base, since 1984-04-09
# These locations employ Region of Magallanes time; use
# TZ='America/Punta_Arenas'.
# China - year-round bases
# Great Wall, King George Island, -6213-05858, since 1985-02-20
# Zhongshan, Larsemann Hills, Prydz Bay, -6922+07623, since 1989-02-26
# France - year-round bases (also see "France & Italy")
#
# From Antoine Leca (1997-01-20):
# Time data entries are from Nicole Pailleau at the IFRTP
# (French Institute for Polar Research and Technology).
# She confirms that French Southern Territories and Terre Adélie bases
# don't observe daylight saving time, even if Terre Adélie supplies came
# from Tasmania.
#
# French Southern Territories with year-round inhabitants
#
# Alfred Faure, Possession Island, Crozet Islands, -462551+0515152, since 1964;
# sealing & whaling stations operated variously 1802/1911+;
# see Asia/Dubai.
#
# Martin-de-Viviès, Amsterdam Island, -374105+0773155, since 1950
# Port-aux-Français, Kerguelen Islands, -492110+0701303, since 1951;
# whaling & sealing station operated 1908/1914, 1920/1929, and 1951/1956
#
# St Paul Island - near Amsterdam, uninhabited
# fishing stations operated variously 1819/1931
#
# Kerguelen - see Indian/Maldives.
#
# year-round base in the main continent
# Dumont d'Urville - see Pacific/Port_Moresby.
# France & Italy - year-round base
# Concordia, -750600+1232000, since 2005
# Germany - year-round base
# Neumayer III, -704080-0081602, since 2009
# India - year-round bases
# Bharati, -692428+0761114, since 2012
# Maitri, -704558+0114356, since 1989
# Italy - year-round base (also see "France & Italy")
# Zuchelli, Terra Nova Bay, -744140+1640647, since 1986
# Japan - year-round bases
# See Asia/Riyadh.
# S Korea - year-round base
# Jang Bogo, Terra Nova Bay, -743700+1641205 since 2014
# King Sejong, King George Island, -6213-05847, since 1988
# New Zealand - claims
# Balleny Islands (never inhabited)
# Scott Island (never inhabited)
#
# year-round base
# Scott Base, Ross Island, since 1957-01.
# See Pacific/Auckland.
# Norway - territories
# Bouvet (never inhabited)
#
# claims
# Peter I Island (never inhabited)
#
# year-round base
# Troll, Queen Maud Land, -720041+0023206, since 2005-02-12
#
# From Paul-Inge Flakstad (2014-03-10):
# I recently had a long dialog about this with the developer of timegenie.com.
# In the absence of specific dates, he decided to choose some likely ones:
# GMT +1 - From March 1 to the last Sunday in March
# GMT +2 - From the last Sunday in March until the last Sunday in October
# GMT +1 - From the last Sunday in October until November 7
# GMT +0 - From November 7 until March 1
# The dates for switching to and from UTC+0 will probably not be absolutely
# correct, but they should be quite close to the actual dates.
#
# From Paul Eggert (2014-03-21):
# The CET-switching Troll rules require zic from tz 2014b or later, so as
# suggested by Bengt-Inge Larsson comment them out for now, and approximate
# with only UTC and CEST. Uncomment them when 2014b is more prevalent.
#
# Rule NAME FROM TO - IN ON AT SAVE LETTER/S
#Rule Troll 2005 max - Mar 1 1:00u 1:00 +01
Rule Troll 2005 max - Mar lastSun 1:00u 2:00 +02
#Rule Troll 2005 max - Oct lastSun 1:00u 1:00 +01
#Rule Troll 2004 max - Nov 7 1:00u 0:00 +00
# Remove the following line when uncommenting the above '#Rule' lines.
Rule Troll 2004 max - Oct lastSun 1:00u 0:00 +00
# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Antarctica/Troll 0 - -00 2005 Feb 12
0:00 Troll %s
# Poland - year-round base
# Arctowski, King George Island, -620945-0582745, since 1977
# Romania - year-bound base
# Law-Racoviță, Larsemann Hills, -692319+0762251, since 1986
# Russia - year-round bases
# Bellingshausen, King George Island, -621159-0585337, since 1968-02-22
# Mirny, Davis coast, -6633+09301, since 1956-02
# Molodezhnaya, Alasheyev Bay, -6740+04551,
# year-round from 1962-02 to 1999-07-01
# Novolazarevskaya, Queen Maud Land, -7046+01150,
# year-round from 1960/61 to 1992
# Vostok, since 1957-12-16, temporarily closed 1994-02/1994-11
# See Asia/Urumqi.
# S Africa - year-round bases
# Marion Island, -4653+03752
# SANAE IV, Vesleskarvet, Queen Maud Land, -714022-0025026, since 1997
# Ukraine - year-round base
# Vernadsky (formerly Faraday), Galindez Island, -651445-0641526, since 1954
# United Kingdom
#
# British Antarctic Territories (BAT) claims
# South Orkney Islands
# scientific station from 1903
# whaling station at Signy I 1920/1926
# South Shetland Islands
#
# year-round bases
# Bird Island, South Georgia, -5400-03803, since 1983
# Deception Island, -6259-06034, whaling station 1912/1931,
# scientific station 1943/1967,
# previously sealers and a scientific expedition wintered by accident,
# and a garrison was deployed briefly
# Halley, Coates Land, -7535-02604, since 1956-01-06
# Halley is on a moving ice shelf and is periodically relocated
# so that it is never more than 10km from its nominal location.
# Rothera, Adelaide Island, -6734-6808, since 1976-12-01
#
# From Paul Eggert (2002-10-22)
# <http://webexhibits.org/daylightsaving/g.html> says Rothera is -03 all year.
#
# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Antarctica/Rothera 0 - -00 1976 Dec 1
-3:00 - -03
# Uruguay - year round base
# Artigas, King George Island, -621104-0585107
# USA - year-round bases
#
# Palmer, Anvers Island, since 1965 (moved 2 miles in 1968)
# See 'southamerica' for Antarctica/Palmer, since it uses South American DST.
#
# McMurdo Station, Ross Island, since 1955-12
# Amundsen-Scott South Pole Station, continuously occupied since 1956-11-20
#
# From Chris Carrier (1996-06-27):
# Siple, the first commander of the South Pole station,
# stated that he would have liked to have kept GMT at the station,
# but that he found it more convenient to keep GMT+12
# as supplies for the station were coming from McMurdo Sound,
# which was on GMT+12 because New Zealand was on GMT+12 all year
# at that time (1957). (Source: Siple's book 90 Degrees South.)
#
# From Susan Smith
# http://www.cybertours.com/whs/pole10.html
# (1995-11-13 16:24:56 +1300, no longer available):
# We use the same time as McMurdo does.
# And they use the same time as Christchurch, NZ does....
# One last quirk about South Pole time.
# All the electric clocks are usually wrong.
# Something about the generators running at 60.1hertz or something
# makes all of the clocks run fast. So every couple of days,
# we have to go around and set them back 5 minutes or so.
# Maybe if we let them run fast all of the time, we'd get to leave here sooner!!
#
# See Pacific/Auckland.

View File

@@ -0,0 +1,131 @@
/* asctime and asctime_r a la POSIX and ISO C, except pad years before 1000. */
/*
** This file is in the public domain, so clarified as of
** 1996-06-05 by Arthur David Olson.
*/
/*
** Avoid the temptation to punt entirely to strftime;
** the output of strftime is supposed to be locale specific
** whereas the output of asctime is supposed to be constant.
*/
/*LINTLIBRARY*/
#include "private.h"
#include <stdio.h>
/*
** All years associated with 32-bit time_t values are exactly four digits long;
** some years associated with 64-bit time_t values are not.
** Vintage programs are coded for years that are always four digits long
** and may assume that the newline always lands in the same place.
** For years that are less than four digits, we pad the output with
** leading zeroes to get the newline in the traditional place.
** The -4 ensures that we get four characters of output even if
** we call a strftime variant that produces fewer characters for some years.
** The ISO C and POSIX standards prohibit padding the year,
** but many implementations pad anyway; most likely the standards are buggy.
*/
static char const ASCTIME_FMT[] = "%s %s%3d %.2d:%.2d:%.2d %-4s\n";
/*
** For years that are more than four digits we put extra spaces before the year
** so that code trying to overwrite the newline won't end up overwriting
** a digit within a year and truncating the year (operating on the assumption
** that no output is better than wrong output).
*/
static char const ASCTIME_FMT_B[] = "%s %s%3d %.2d:%.2d:%.2d %s\n";
enum { STD_ASCTIME_BUF_SIZE = 26 };
/*
** Big enough for something such as
** ??? ???-2147483648 -2147483648:-2147483648:-2147483648 -2147483648\n
** (two three-character abbreviations, five strings denoting integers,
** seven explicit spaces, two explicit colons, a newline,
** and a trailing NUL byte).
** The values above are for systems where an int is 32 bits and are provided
** as an example; the size expression below is a bound for the system at
** hand.
*/
static char buf_asctime[2*3 + 5*INT_STRLEN_MAXIMUM(int) + 7 + 2 + 1 + 1];
/* A similar buffer for ctime.
C89 requires that they be the same buffer.
This requirement was removed in C99, so support it only if requested,
as support is more likely to lead to bugs in badly-written programs. */
#if SUPPORT_C89
# define buf_ctime buf_asctime
#else
static char buf_ctime[sizeof buf_asctime];
#endif
char *
asctime_r(register const struct tm *timeptr, char *buf)
{
static const char wday_name[][4] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
static const char mon_name[][4] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
register const char * wn;
register const char * mn;
char year[INT_STRLEN_MAXIMUM(int) + 2];
char result[sizeof buf_asctime];
if (timeptr == NULL) {
errno = EINVAL;
return strcpy(buf, "??? ??? ?? ??:??:?? ????\n");
}
if (timeptr->tm_wday < 0 || timeptr->tm_wday >= DAYSPERWEEK)
wn = "???";
else wn = wday_name[timeptr->tm_wday];
if (timeptr->tm_mon < 0 || timeptr->tm_mon >= MONSPERYEAR)
mn = "???";
else mn = mon_name[timeptr->tm_mon];
/*
** Use strftime's %Y to generate the year, to avoid overflow problems
** when computing timeptr->tm_year + TM_YEAR_BASE.
** Assume that strftime is unaffected by other out-of-range members
** (e.g., timeptr->tm_mday) when processing "%Y".
*/
strftime(year, sizeof year, "%Y", timeptr);
/*
** We avoid using snprintf since it's not available on all systems.
*/
sprintf(result,
((strlen(year) <= 4) ? ASCTIME_FMT : ASCTIME_FMT_B),
wn, mn,
timeptr->tm_mday, timeptr->tm_hour,
timeptr->tm_min, timeptr->tm_sec,
year);
if (strlen(result) < STD_ASCTIME_BUF_SIZE
|| buf == buf_ctime || buf == buf_asctime)
return strcpy(buf, result);
else {
errno = EOVERFLOW;
return NULL;
}
}
char *
asctime(register const struct tm *timeptr)
{
return asctime_r(timeptr, buf_asctime);
}
char *
ctime_r(const time_t *timep, char *buf)
{
struct tm mytm;
struct tm *tmp = localtime_r(timep, &mytm);
return tmp ? asctime_r(tmp, buf) : NULL;
}
char *
ctime(const time_t *timep)
{
return ctime_r(timep, buf_ctime);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,318 @@
# tzdb links for backward compatibility
# This file is in the public domain, so clarified as of
# 2009-05-17 by Arthur David Olson.
# This file provides links from old or merged timezone names to current ones.
# Many names changed in 1993 and in 1995, and many merged names moved here
# in the period from 2013 through 2022. Several of these names are
# also present in the file 'backzone', which has data important only
# for pre-1970 timestamps and so is out of scope for tzdb proper.
# Although this file is optional and tzdb will work if you omit it by
# building with 'make BACKWARD=', in practice downstream users
# typically use this file for backward compatibility.
# This file is divided into sections, one for each major reason for a
# backward compatibility link. Each section is sorted by link name.
# A "#= TARGET1" comment labels each link inserted only because some
# .zi parsers (including tzcode through 2022e) mishandle links to links.
# The comment says what the target would be if these parsers were fixed
# so that data could contain links to links. For example, the line
# "Link Australia/Sydney Australia/ACT #= Australia/Canberra" would be
# "Link Australia/Canberra Australia/ACT" were it not that data lines
# refrain from linking to links like Australia/Canberra, which means
# the Australia/ACT line links instead to Australia/Sydney,
# Australia/Canberra's target.
# Pre-1993 naming conventions
# Link TARGET LINK-NAME #= TARGET1
Link Australia/Sydney Australia/ACT #= Australia/Canberra
Link Australia/Lord_Howe Australia/LHI
Link Australia/Sydney Australia/NSW
Link Australia/Darwin Australia/North
Link Australia/Brisbane Australia/Queensland
Link Australia/Adelaide Australia/South
Link Australia/Hobart Australia/Tasmania
Link Australia/Melbourne Australia/Victoria
Link Australia/Perth Australia/West
Link Australia/Broken_Hill Australia/Yancowinna
Link America/Rio_Branco Brazil/Acre #= America/Porto_Acre
Link America/Noronha Brazil/DeNoronha
Link America/Sao_Paulo Brazil/East
Link America/Manaus Brazil/West
Link America/Halifax Canada/Atlantic
Link America/Winnipeg Canada/Central
# This line is commented out, as the name exceeded the 14-character limit
# and was an unused misnomer.
#Link America/Regina Canada/East-Saskatchewan
Link America/Toronto Canada/Eastern
Link America/Edmonton Canada/Mountain
Link America/St_Johns Canada/Newfoundland
Link America/Vancouver Canada/Pacific
Link America/Regina Canada/Saskatchewan
Link America/Whitehorse Canada/Yukon
Link America/Santiago Chile/Continental
Link Pacific/Easter Chile/EasterIsland
Link America/Havana Cuba
Link Africa/Cairo Egypt
Link Europe/Dublin Eire
# Vanguard section, for most .zi parsers.
#Link GMT Etc/GMT
#Link GMT Etc/GMT+0
#Link GMT Etc/GMT-0
#Link GMT Etc/GMT0
#Link GMT Etc/Greenwich
# Rearguard section, for TZUpdater 2.3.2 and earlier.
Link Etc/GMT Etc/GMT+0
Link Etc/GMT Etc/GMT-0
Link Etc/GMT Etc/GMT0
Link Etc/GMT Etc/Greenwich
# End of rearguard section.
Link Etc/UTC Etc/UCT
Link Etc/UTC Etc/Universal
Link Etc/UTC Etc/Zulu
Link Europe/London GB
Link Europe/London GB-Eire
# Vanguard section, for most .zi parsers.
#Link GMT GMT+0
#Link GMT GMT-0
#Link GMT GMT0
#Link GMT Greenwich
# Rearguard section, for TZUpdater 2.3.2 and earlier.
Link Etc/GMT GMT+0
Link Etc/GMT GMT-0
Link Etc/GMT GMT0
Link Etc/GMT Greenwich
# End of rearguard section.
Link Asia/Hong_Kong Hongkong
Link Africa/Abidjan Iceland #= Atlantic/Reykjavik
Link Asia/Tehran Iran
Link Asia/Jerusalem Israel
Link America/Jamaica Jamaica
Link Asia/Tokyo Japan
Link Pacific/Kwajalein Kwajalein
Link Africa/Tripoli Libya
Link America/Tijuana Mexico/BajaNorte
Link America/Mazatlan Mexico/BajaSur
Link America/Mexico_City Mexico/General
Link Pacific/Auckland NZ
Link Pacific/Chatham NZ-CHAT
Link America/Denver Navajo #= America/Shiprock
Link Asia/Shanghai PRC
Link Europe/Warsaw Poland
Link Europe/Lisbon Portugal
Link Asia/Taipei ROC
Link Asia/Seoul ROK
Link Asia/Singapore Singapore
Link Europe/Istanbul Turkey
Link Etc/UTC UCT
Link America/Anchorage US/Alaska
Link America/Adak US/Aleutian
Link America/Phoenix US/Arizona
Link America/Chicago US/Central
Link America/Indiana/Indianapolis US/East-Indiana
Link America/New_York US/Eastern
Link Pacific/Honolulu US/Hawaii
Link America/Indiana/Knox US/Indiana-Starke
Link America/Detroit US/Michigan
Link America/Denver US/Mountain
Link America/Los_Angeles US/Pacific
Link Pacific/Pago_Pago US/Samoa
Link Etc/UTC UTC
Link Etc/UTC Universal
Link Europe/Moscow W-SU
Link Etc/UTC Zulu
# Two-part names that were renamed mostly to three-part names in 1995
# Link TARGET LINK-NAME #= TARGET1
Link America/Argentina/Buenos_Aires America/Buenos_Aires
Link America/Argentina/Catamarca America/Catamarca
Link America/Argentina/Cordoba America/Cordoba
Link America/Indiana/Indianapolis America/Indianapolis
Link America/Argentina/Jujuy America/Jujuy
Link America/Indiana/Knox America/Knox_IN
Link America/Kentucky/Louisville America/Louisville
Link America/Argentina/Mendoza America/Mendoza
Link America/Puerto_Rico America/Virgin #= America/St_Thomas
Link Pacific/Pago_Pago Pacific/Samoa
# Pre-2013 practice, which typically had a Zone per zone.tab line
# Link TARGET LINK-NAME
Link Africa/Abidjan Africa/Accra
Link Africa/Nairobi Africa/Addis_Ababa
Link Africa/Nairobi Africa/Asmara
Link Africa/Abidjan Africa/Bamako
Link Africa/Lagos Africa/Bangui
Link Africa/Abidjan Africa/Banjul
Link Africa/Maputo Africa/Blantyre
Link Africa/Lagos Africa/Brazzaville
Link Africa/Maputo Africa/Bujumbura
Link Africa/Abidjan Africa/Conakry
Link Africa/Abidjan Africa/Dakar
Link Africa/Nairobi Africa/Dar_es_Salaam
Link Africa/Nairobi Africa/Djibouti
Link Africa/Lagos Africa/Douala
Link Africa/Abidjan Africa/Freetown
Link Africa/Maputo Africa/Gaborone
Link Africa/Maputo Africa/Harare
Link Africa/Nairobi Africa/Kampala
Link Africa/Maputo Africa/Kigali
Link Africa/Lagos Africa/Kinshasa
Link Africa/Lagos Africa/Libreville
Link Africa/Abidjan Africa/Lome
Link Africa/Lagos Africa/Luanda
Link Africa/Maputo Africa/Lubumbashi
Link Africa/Maputo Africa/Lusaka
Link Africa/Lagos Africa/Malabo
Link Africa/Johannesburg Africa/Maseru
Link Africa/Johannesburg Africa/Mbabane
Link Africa/Nairobi Africa/Mogadishu
Link Africa/Lagos Africa/Niamey
Link Africa/Abidjan Africa/Nouakchott
Link Africa/Abidjan Africa/Ouagadougou
Link Africa/Lagos Africa/Porto-Novo
Link America/Puerto_Rico America/Anguilla
Link America/Puerto_Rico America/Antigua
Link America/Puerto_Rico America/Aruba
Link America/Panama America/Atikokan
Link America/Puerto_Rico America/Blanc-Sablon
Link America/Panama America/Cayman
Link America/Phoenix America/Creston
Link America/Puerto_Rico America/Curacao
Link America/Puerto_Rico America/Dominica
Link America/Puerto_Rico America/Grenada
Link America/Puerto_Rico America/Guadeloupe
Link America/Puerto_Rico America/Kralendijk
Link America/Puerto_Rico America/Lower_Princes
Link America/Puerto_Rico America/Marigot
Link America/Puerto_Rico America/Montserrat
Link America/Toronto America/Nassau
Link America/Puerto_Rico America/Port_of_Spain
Link America/Puerto_Rico America/St_Barthelemy
Link America/Puerto_Rico America/St_Kitts
Link America/Puerto_Rico America/St_Lucia
Link America/Puerto_Rico America/St_Thomas
Link America/Puerto_Rico America/St_Vincent
Link America/Puerto_Rico America/Tortola
Link Pacific/Port_Moresby Antarctica/DumontDUrville
Link Pacific/Auckland Antarctica/McMurdo
Link Asia/Riyadh Antarctica/Syowa
Link Asia/Urumqi Antarctica/Vostok
Link Europe/Berlin Arctic/Longyearbyen
Link Asia/Riyadh Asia/Aden
Link Asia/Qatar Asia/Bahrain
Link Asia/Kuching Asia/Brunei
Link Asia/Singapore Asia/Kuala_Lumpur
Link Asia/Riyadh Asia/Kuwait
Link Asia/Dubai Asia/Muscat
Link Asia/Bangkok Asia/Phnom_Penh
Link Asia/Bangkok Asia/Vientiane
Link Africa/Abidjan Atlantic/Reykjavik
Link Africa/Abidjan Atlantic/St_Helena
Link Europe/Brussels Europe/Amsterdam
Link Europe/Prague Europe/Bratislava
Link Europe/Zurich Europe/Busingen
Link Europe/Berlin Europe/Copenhagen
Link Europe/London Europe/Guernsey
Link Europe/London Europe/Isle_of_Man
Link Europe/London Europe/Jersey
Link Europe/Belgrade Europe/Ljubljana
Link Europe/Brussels Europe/Luxembourg
Link Europe/Helsinki Europe/Mariehamn
Link Europe/Paris Europe/Monaco
Link Europe/Berlin Europe/Oslo
Link Europe/Belgrade Europe/Podgorica
Link Europe/Rome Europe/San_Marino
Link Europe/Belgrade Europe/Sarajevo
Link Europe/Belgrade Europe/Skopje
Link Europe/Berlin Europe/Stockholm
Link Europe/Zurich Europe/Vaduz
Link Europe/Rome Europe/Vatican
Link Europe/Belgrade Europe/Zagreb
Link Africa/Nairobi Indian/Antananarivo
Link Asia/Bangkok Indian/Christmas
Link Asia/Yangon Indian/Cocos
Link Africa/Nairobi Indian/Comoro
Link Indian/Maldives Indian/Kerguelen
Link Asia/Dubai Indian/Mahe
Link Africa/Nairobi Indian/Mayotte
Link Asia/Dubai Indian/Reunion
Link Pacific/Port_Moresby Pacific/Chuuk
Link Pacific/Tarawa Pacific/Funafuti
Link Pacific/Tarawa Pacific/Majuro
Link Pacific/Pago_Pago Pacific/Midway
Link Pacific/Guadalcanal Pacific/Pohnpei
Link Pacific/Guam Pacific/Saipan
Link Pacific/Tarawa Pacific/Wake
Link Pacific/Tarawa Pacific/Wallis
# Non-zone.tab locations with timestamps since 1970 that duplicate
# those of an existing location
# Link TARGET LINK-NAME
Link Africa/Abidjan Africa/Timbuktu
Link America/Argentina/Catamarca America/Argentina/ComodRivadavia
Link America/Adak America/Atka
Link America/Panama America/Coral_Harbour
Link America/Tijuana America/Ensenada
Link America/Indiana/Indianapolis America/Fort_Wayne
Link America/Toronto America/Montreal
Link America/Toronto America/Nipigon
Link America/Iqaluit America/Pangnirtung
Link America/Rio_Branco America/Porto_Acre
Link America/Winnipeg America/Rainy_River
Link America/Argentina/Cordoba America/Rosario
Link America/Tijuana America/Santa_Isabel
Link America/Denver America/Shiprock
Link America/Toronto America/Thunder_Bay
Link Pacific/Auckland Antarctica/South_Pole
Link Asia/Shanghai Asia/Chongqing
Link Asia/Shanghai Asia/Harbin
Link Asia/Urumqi Asia/Kashgar
Link Asia/Jerusalem Asia/Tel_Aviv
Link Europe/Berlin Atlantic/Jan_Mayen
Link Australia/Sydney Australia/Canberra
Link Australia/Hobart Australia/Currie
Link Europe/London Europe/Belfast
Link Europe/Chisinau Europe/Tiraspol
Link Europe/Kyiv Europe/Uzhgorod
Link Europe/Kyiv Europe/Zaporozhye
Link Pacific/Kanton Pacific/Enderbury
Link Pacific/Honolulu Pacific/Johnston
Link Pacific/Port_Moresby Pacific/Yap
# Alternate names for the same location
# Link TARGET LINK-NAME #= TARGET1
Link Africa/Nairobi Africa/Asmera #= Africa/Asmara
Link America/Nuuk America/Godthab
Link Asia/Ashgabat Asia/Ashkhabad
Link Asia/Kolkata Asia/Calcutta
Link Asia/Shanghai Asia/Chungking #= Asia/Chongqing
Link Asia/Dhaka Asia/Dacca
# Istanbul is in both continents.
Link Europe/Istanbul Asia/Istanbul
Link Asia/Kathmandu Asia/Katmandu
Link Asia/Macau Asia/Macao
Link Asia/Yangon Asia/Rangoon
Link Asia/Ho_Chi_Minh Asia/Saigon
Link Asia/Thimphu Asia/Thimbu
Link Asia/Makassar Asia/Ujung_Pandang
Link Asia/Ulaanbaatar Asia/Ulan_Bator
Link Atlantic/Faroe Atlantic/Faeroe
Link Europe/Kyiv Europe/Kiev
# Classically, Cyprus is in Asia; e.g. see Herodotus, Histories, I.72.
# However, for various reasons many users expect to find it under Europe.
Link Asia/Nicosia Europe/Nicosia
Link Pacific/Guadalcanal Pacific/Ponape #= Pacific/Pohnpei
Link Pacific/Port_Moresby Pacific/Truk #= Pacific/Chuuk

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -0,0 +1,70 @@
# Check links in tz tables.
# Contributed by Paul Eggert. This file is in the public domain.
BEGIN {
# Special marker indicating that the name is defined as a Zone.
# It is a newline so that it cannot match a valid name.
# It is not null so that its slot does not appear unset.
Zone = "\n"
}
/^Z/ {
if (defined[$2]) {
if (defined[$2] == Zone) {
printf "%s: Zone has duplicate definition\n", $2
} else {
printf "%s: Link with same name as Zone\n", $2
}
status = 1
}
defined[$2] = Zone
}
/^L/ {
if (defined[$3]) {
if (defined[$3] == Zone) {
printf "%s: Link with same name as Zone\n", $3
} else if (defined[$3] == $2) {
printf "%s: Link has duplicate definition\n", $3
} else {
printf "%s: Link to both %s and %s\n", $3, defined[$3], $2
}
status = 1
}
if (backcheck && FILENAME != backcheck && $3 != "GMT") {
printf "%s: Link should be in '%s'\n", $3, backcheck
status = 1
}
if ($4 == "#=") {
shortcut[$5] = $3
}
used[$2] = 1
defined[$3] = $2
}
END {
for (tz in used) {
if (defined[tz] != Zone) {
if (!defined[tz]) {
printf "%s: Link to nowhere\n", tz
status = 1
} else if (DATAFORM != "vanguard") {
printf "%s: Link to link\n", tz
status = 1
}
}
}
for (tz in shortcut) {
if (defined[shortcut[tz]] != defined[tz]) {
target = (!defined[tz] ? "absence" \
: defined[tz] == "\n" ? "zone" \
: defined[tz])
printf "%s: target %s disagrees with %s's target %s\n", \
tz, target, shortcut[tz], defined[shortcut[tz]]
status = 1
}
}
exit status
}

View File

@@ -0,0 +1,191 @@
# Check tz tables for consistency.
# Contributed by Paul Eggert. This file is in the public domain.
BEGIN {
FS = "\t"
if (!iso_table) iso_table = "iso3166.tab"
if (!zone_table) zone_table = "zone1970.tab"
if (!want_warnings) want_warnings = -1
while (getline <iso_table) {
iso_NR++
if ($0 ~ /^#/) continue
if (NF != 2) {
printf "%s:%d: wrong number of columns\n", \
iso_table, iso_NR >>"/dev/stderr"
status = 1
}
cc = $1
name = $2
if (cc !~ /^[A-Z][A-Z]$/) {
printf "%s:%d: invalid country code '%s'\n", \
iso_table, iso_NR, cc >>"/dev/stderr"
status = 1
}
if (cc <= cc0) {
if (cc == cc0) {
s = "duplicate";
} else {
s = "out of order";
}
printf "%s:%d: country code '%s' is %s\n", \
iso_table, iso_NR, cc, s \
>>"/dev/stderr"
status = 1
}
cc0 = cc
if (name2cc[name]) {
printf "%s:%d: '%s' and '%s' have the same name\n", \
iso_table, iso_NR, name2cc[name], cc \
>>"/dev/stderr"
status = 1
}
name2cc[name] = cc
cc2name[cc] = name
cc2NR[cc] = iso_NR
}
cc0 = ""
while (getline <zone_table) {
zone_NR++
if ($0 ~ /^#/) continue
if (NF != 3 && NF != 4) {
printf "%s:%d: wrong number of columns\n", \
zone_table, zone_NR >>"/dev/stderr"
status = 1
}
ccs = input_ccs[zone_NR] = $1
coordinates = $2
tz = $3
comments = input_comments[zone_NR] = $4
split(ccs, cca, /,/)
cc = cca[1]
# Don't complain about a special case for Crimea in zone.tab.
# FIXME: zone.tab should be removed, since it is obsolete.
# Or at least put just "XX" in its country-code column.
if (cc < cc0 \
&& !(zone_table == "zone.tab" \
&& tz0 == "Europe/Simferopol")) {
printf "%s:%d: country code '%s' is out of order\n", \
zone_table, zone_NR, cc >>"/dev/stderr"
status = 1
}
cc0 = cc
tz0 = tz
tztab[tz] = 1
tz2NR[tz] = zone_NR
for (i in cca) {
cc = cca[i]
if (cc2name[cc]) {
cc_used[cc]++
} else {
printf "%s:%d: %s: unknown country code\n", \
zone_table, zone_NR, cc >>"/dev/stderr"
status = 1
}
}
if (coordinates !~ /^[-+][0-9][0-9][0-5][0-9][-+][01][0-9][0-9][0-5][0-9]$/ \
&& coordinates !~ /^[-+][0-9][0-9][0-5][0-9][0-5][0-9][-+][01][0-9][0-9][0-5][0-9][0-5][0-9]$/) {
printf "%s:%d: %s: invalid coordinates\n", \
zone_table, zone_NR, coordinates >>"/dev/stderr"
status = 1
}
}
for (i = 1; i <= zone_NR; i++) {
ccs = input_ccs[i]
if (!ccs) continue
comments = input_comments[i]
split(ccs, cca, /,/)
used_max = 0
for (j in cca) {
cc = cca[j]
if (used_max < cc_used[cc]) {
used_max = cc_used[cc]
}
}
if (used_max <= 1 && comments) {
printf "%s:%d: unnecessary comment '%s'\n", \
zone_table, i, comments \
>>"/dev/stderr"
status = 1
} else if (1 < cc_used[cc] && !comments) {
printf "%s:%d: missing comment for %s\n", \
zone_table, i, cc \
>>"/dev/stderr"
status = 1
}
}
FS = " "
}
$1 ~ /^#/ { next }
{
tz = rules = ""
if ($1 == "Zone") {
tz = $2
ruleUsed[$4] = 1
if ($5 ~ /%/) rulePercentUsed[$4] = 1
} else if ($1 == "Link" && zone_table == "zone.tab") {
# Ignore Link commands if source and destination basenames
# are identical, e.g. Europe/Istanbul versus Asia/Istanbul.
src = $2
dst = $3
while ((i = index(src, "/"))) src = substr(src, i+1)
while ((i = index(dst, "/"))) dst = substr(dst, i+1)
if (src != dst) tz = $3
} else if ($1 == "Rule") {
ruleDefined[$2] = 1
if ($10 != "-") ruleLetters[$2] = 1
} else {
ruleUsed[$2] = 1
if ($3 ~ /%/) rulePercentUsed[$2] = 1
}
if (tz && tz ~ /\// && tz !~ /^Etc\//) {
if (!tztab[tz] && FILENAME != "backward") {
printf "%s: no data for '%s'\n", zone_table, tz \
>>"/dev/stderr"
status = 1
}
zoneSeen[tz] = 1
}
}
END {
for (tz in ruleDefined) {
if (!ruleUsed[tz]) {
printf "%s: Rule never used\n", tz
status = 1
}
}
for (tz in ruleLetters) {
if (!rulePercentUsed[tz]) {
printf "%s: Rule contains letters never used\n", tz
status = 1
}
}
for (tz in tztab) {
if (!zoneSeen[tz] && tz !~ /^Etc\//) {
printf "%s:%d: no Zone table for '%s'\n", \
zone_table, tz2NR[tz], tz >>"/dev/stderr"
status = 1
}
}
if (0 < want_warnings) {
for (cc in cc2name) {
if (!cc_used[cc]) {
printf "%s:%d: warning: " \
"no Zone entries for %s (%s)\n", \
iso_table, cc2NR[cc], cc, cc2name[cc]
}
}
}
exit status
}

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,79 @@
# tzdb data for ships at sea and other miscellany
# This file is in the public domain, so clarified as of
# 2009-05-17 by Arthur David Olson.
# These entries are for uses not otherwise covered by the tz database.
# Their main practical use is for platforms like Android that lack
# support for POSIX-style TZ strings. On such platforms these entries
# can be useful if the timezone database is wrong or if a ship or
# aircraft at sea is not in a timezone.
# Starting with POSIX 1003.1-2001, the entries below are all
# unnecessary as settings for the TZ environment variable. E.g.,
# instead of TZ='Etc/GMT+4' one can use the POSIX setting TZ='<-04>+4'.
#
# Do not use a POSIX TZ setting like TZ='GMT+4', which is four hours
# behind GMT but uses the completely misleading abbreviation "GMT".
# The following zone is used by tzcode functions like gmtime,
# which load the "UTC" file to handle seconds properly.
Zone Etc/UTC 0 - UTC
# Functions like gmtime load the "GMT" file to handle leap seconds properly.
# Vanguard section, which works with most .zi parsers.
#Zone GMT 0 - GMT
# Rearguard section, for TZUpdater 2.3.2 and earlier.
Zone Etc/GMT 0 - GMT
# The following link uses older naming conventions,
# but it belongs here, not in the file 'backward',
# as it is needed for tzcode releases through 2022a,
# where functions like gmtime load "GMT" instead of the "Etc/UTC".
# We want this to work even on installations that omit 'backward'.
Link Etc/GMT GMT
# End of rearguard section.
# Be consistent with POSIX TZ settings in the Zone names,
# even though this is the opposite of what many people expect.
# POSIX has positive signs west of Greenwich, but many people expect
# positive signs east of Greenwich. For example, TZ='Etc/GMT+4' uses
# the abbreviation "-04" and corresponds to 4 hours behind UT
# (i.e. west of Greenwich) even though many people would expect it to
# mean 4 hours ahead of UT (i.e. east of Greenwich).
# Earlier incarnations of this package were not POSIX-compliant,
# and had lines such as
# Zone GMT-12 -12 - GMT-1200
# We did not want things to change quietly if someone accustomed to the old
# way does a
# zic -l GMT-12
# so we moved the names into the Etc subdirectory.
# Also, the time zone abbreviations are now compatible with %z.
Zone Etc/GMT-14 14 - +14
Zone Etc/GMT-13 13 - +13
Zone Etc/GMT-12 12 - +12
Zone Etc/GMT-11 11 - +11
Zone Etc/GMT-10 10 - +10
Zone Etc/GMT-9 9 - +09
Zone Etc/GMT-8 8 - +08
Zone Etc/GMT-7 7 - +07
Zone Etc/GMT-6 6 - +06
Zone Etc/GMT-5 5 - +05
Zone Etc/GMT-4 4 - +04
Zone Etc/GMT-3 3 - +03
Zone Etc/GMT-2 2 - +02
Zone Etc/GMT-1 1 - +01
Zone Etc/GMT+1 -1 - -01
Zone Etc/GMT+2 -2 - -02
Zone Etc/GMT+3 -3 - -03
Zone Etc/GMT+4 -4 - -04
Zone Etc/GMT+5 -5 - -05
Zone Etc/GMT+6 -6 - -06
Zone Etc/GMT+7 -7 - -07
Zone Etc/GMT+8 -8 - -08
Zone Etc/GMT+9 -9 - -09
Zone Etc/GMT+10 -10 - -10
Zone Etc/GMT+11 -11 - -11
Zone Etc/GMT+12 -12 - -12

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,12 @@
# tzdb data for noncommittal factory settings
# This file is in the public domain, so clarified as of
# 2009-05-17 by Arthur David Olson.
# For distributors who don't want to specify a timezone in their
# installation procedures. Users who run 'date' will get the
# time zone abbreviation "-00", indicating that the actual time zone
# is unknown.
# Zone NAME STDOFF RULES FORMAT
Zone Factory 0 - -00

View File

@@ -0,0 +1,274 @@
# ISO 3166 alpha-2 country codes
#
# This file is in the public domain, so clarified as of
# 2009-05-17 by Arthur David Olson.
#
# From Paul Eggert (2022-11-18):
# This file contains a table of two-letter country codes. Columns are
# separated by a single tab. Lines beginning with '#' are comments.
# All text uses UTF-8 encoding. The columns of the table are as follows:
#
# 1. ISO 3166-1 alpha-2 country code, current as of
# ISO 3166-1 N1087 (2022-09-02). See: Updates on ISO 3166-1
# https://isotc.iso.org/livelink/livelink/Open/16944257
# 2. The usual English name for the coded region,
# chosen so that alphabetic sorting of subsets produces helpful lists.
# This is not the same as the English name in the ISO 3166 tables.
#
# The table is sorted by country code.
#
# This table is intended as an aid for users, to help them select time
# zone data appropriate for their practical needs. It is not intended
# to take or endorse any position on legal or territorial claims.
#
#country-
#code name of country, territory, area, or subdivision
AD Andorra
AE United Arab Emirates
AF Afghanistan
AG Antigua & Barbuda
AI Anguilla
AL Albania
AM Armenia
AO Angola
AQ Antarctica
AR Argentina
AS Samoa (American)
AT Austria
AU Australia
AW Aruba
AX Åland Islands
AZ Azerbaijan
BA Bosnia & Herzegovina
BB Barbados
BD Bangladesh
BE Belgium
BF Burkina Faso
BG Bulgaria
BH Bahrain
BI Burundi
BJ Benin
BL St Barthelemy
BM Bermuda
BN Brunei
BO Bolivia
BQ Caribbean NL
BR Brazil
BS Bahamas
BT Bhutan
BV Bouvet Island
BW Botswana
BY Belarus
BZ Belize
CA Canada
CC Cocos (Keeling) Islands
CD Congo (Dem. Rep.)
CF Central African Rep.
CG Congo (Rep.)
CH Switzerland
CI Côte d'Ivoire
CK Cook Islands
CL Chile
CM Cameroon
CN China
CO Colombia
CR Costa Rica
CU Cuba
CV Cape Verde
CW Curaçao
CX Christmas Island
CY Cyprus
CZ Czech Republic
DE Germany
DJ Djibouti
DK Denmark
DM Dominica
DO Dominican Republic
DZ Algeria
EC Ecuador
EE Estonia
EG Egypt
EH Western Sahara
ER Eritrea
ES Spain
ET Ethiopia
FI Finland
FJ Fiji
FK Falkland Islands
FM Micronesia
FO Faroe Islands
FR France
GA Gabon
GB Britain (UK)
GD Grenada
GE Georgia
GF French Guiana
GG Guernsey
GH Ghana
GI Gibraltar
GL Greenland
GM Gambia
GN Guinea
GP Guadeloupe
GQ Equatorial Guinea
GR Greece
GS South Georgia & the South Sandwich Islands
GT Guatemala
GU Guam
GW Guinea-Bissau
GY Guyana
HK Hong Kong
HM Heard Island & McDonald Islands
HN Honduras
HR Croatia
HT Haiti
HU Hungary
ID Indonesia
IE Ireland
IL Israel
IM Isle of Man
IN India
IO British Indian Ocean Territory
IQ Iraq
IR Iran
IS Iceland
IT Italy
JE Jersey
JM Jamaica
JO Jordan
JP Japan
KE Kenya
KG Kyrgyzstan
KH Cambodia
KI Kiribati
KM Comoros
KN St Kitts & Nevis
KP Korea (North)
KR Korea (South)
KW Kuwait
KY Cayman Islands
KZ Kazakhstan
LA Laos
LB Lebanon
LC St Lucia
LI Liechtenstein
LK Sri Lanka
LR Liberia
LS Lesotho
LT Lithuania
LU Luxembourg
LV Latvia
LY Libya
MA Morocco
MC Monaco
MD Moldova
ME Montenegro
MF St Martin (French)
MG Madagascar
MH Marshall Islands
MK North Macedonia
ML Mali
MM Myanmar (Burma)
MN Mongolia
MO Macau
MP Northern Mariana Islands
MQ Martinique
MR Mauritania
MS Montserrat
MT Malta
MU Mauritius
MV Maldives
MW Malawi
MX Mexico
MY Malaysia
MZ Mozambique
NA Namibia
NC New Caledonia
NE Niger
NF Norfolk Island
NG Nigeria
NI Nicaragua
NL Netherlands
NO Norway
NP Nepal
NR Nauru
NU Niue
NZ New Zealand
OM Oman
PA Panama
PE Peru
PF French Polynesia
PG Papua New Guinea
PH Philippines
PK Pakistan
PL Poland
PM St Pierre & Miquelon
PN Pitcairn
PR Puerto Rico
PS Palestine
PT Portugal
PW Palau
PY Paraguay
QA Qatar
RE Réunion
RO Romania
RS Serbia
RU Russia
RW Rwanda
SA Saudi Arabia
SB Solomon Islands
SC Seychelles
SD Sudan
SE Sweden
SG Singapore
SH St Helena
SI Slovenia
SJ Svalbard & Jan Mayen
SK Slovakia
SL Sierra Leone
SM San Marino
SN Senegal
SO Somalia
SR Suriname
SS South Sudan
ST Sao Tome & Principe
SV El Salvador
SX St Maarten (Dutch)
SY Syria
SZ Eswatini (Swaziland)
TC Turks & Caicos Is
TD Chad
TF French Southern Territories
TG Togo
TH Thailand
TJ Tajikistan
TK Tokelau
TL East Timor
TM Turkmenistan
TN Tunisia
TO Tonga
TR Turkey
TT Trinidad & Tobago
TV Tuvalu
TW Taiwan
TZ Tanzania
UA Ukraine
UG Uganda
UM US minor outlying islands
US United States
UY Uruguay
UZ Uzbekistan
VA Vatican City
VC St Vincent
VE Venezuela
VG Virgin Islands (UK)
VI Virgin Islands (US)
VN Vietnam
VU Vanuatu
WF Wallis & Futuna
WS Samoa (western)
YE Yemen
YT Mayotte
ZA South Africa
ZM Zambia
ZW Zimbabwe

View File

@@ -0,0 +1,255 @@
#
# In the following text, the symbol '#' introduces
# a comment, which continues from that symbol until
# the end of the line. A plain comment line has a
# whitespace character following the comment indicator.
# There are also special comment lines defined below.
# A special comment will always have a non-whitespace
# character in column 2.
#
# A blank line should be ignored.
#
# The following table shows the corrections that must
# be applied to compute International Atomic Time (TAI)
# from the Coordinated Universal Time (UTC) values that
# are transmitted by almost all time services.
#
# The first column shows an epoch as a number of seconds
# since 1 January 1900, 00:00:00 (1900.0 is also used to
# indicate the same epoch.) Both of these time stamp formats
# ignore the complexities of the time scales that were
# used before the current definition of UTC at the start
# of 1972. (See note 3 below.)
# The second column shows the number of seconds that
# must be added to UTC to compute TAI for any timestamp
# at or after that epoch. The value on each line is
# valid from the indicated initial instant until the
# epoch given on the next one or indefinitely into the
# future if there is no next line.
# (The comment on each line shows the representation of
# the corresponding initial epoch in the usual
# day-month-year format. The epoch always begins at
# 00:00:00 UTC on the indicated day. See Note 5 below.)
#
# Important notes:
#
# 1. Coordinated Universal Time (UTC) is often referred to
# as Greenwich Mean Time (GMT). The GMT time scale is no
# longer used, and the use of GMT to designate UTC is
# discouraged.
#
# 2. The UTC time scale is realized by many national
# laboratories and timing centers. Each laboratory
# identifies its realization with its name: Thus
# UTC(NIST), UTC(USNO), etc. The differences among
# these different realizations are typically on the
# order of a few nanoseconds (i.e., 0.000 000 00x s)
# and can be ignored for many purposes. These differences
# are tabulated in Circular T, which is published monthly
# by the International Bureau of Weights and Measures
# (BIPM). See www.bipm.org for more information.
#
# 3. The current definition of the relationship between UTC
# and TAI dates from 1 January 1972. A number of different
# time scales were in use before that epoch, and it can be
# quite difficult to compute precise timestamps and time
# intervals in those "prehistoric" days. For more information,
# consult:
#
# The Explanatory Supplement to the Astronomical
# Ephemeris.
# or
# Terry Quinn, "The BIPM and the Accurate Measurement
# of Time," Proc. of the IEEE, Vol. 79, pp. 894-905,
# July, 1991. <http://dx.doi.org/10.1109/5.84965>
# reprinted in:
# Christine Hackman and Donald B Sullivan (eds.)
# Time and Frequency Measurement
# American Association of Physics Teachers (1996)
# <http://tf.nist.gov/general/pdf/1168.pdf>, pp. 75-86
#
# 4. The decision to insert a leap second into UTC is currently
# the responsibility of the International Earth Rotation and
# Reference Systems Service. (The name was changed from the
# International Earth Rotation Service, but the acronym IERS
# is still used.)
#
# Leap seconds are announced by the IERS in its Bulletin C.
#
# See www.iers.org for more details.
#
# Every national laboratory and timing center uses the
# data from the BIPM and the IERS to construct UTC(lab),
# their local realization of UTC.
#
# Although the definition also includes the possibility
# of dropping seconds ("negative" leap seconds), this has
# never been done and is unlikely to be necessary in the
# foreseeable future.
#
# 5. If your system keeps time as the number of seconds since
# some epoch (e.g., NTP timestamps), then the algorithm for
# assigning a UTC time stamp to an event that happens during a positive
# leap second is not well defined. The official name of that leap
# second is 23:59:60, but there is no way of representing that time
# in these systems.
# Many systems of this type effectively stop the system clock for
# one second during the leap second and use a time that is equivalent
# to 23:59:59 UTC twice. For these systems, the corresponding TAI
# timestamp would be obtained by advancing to the next entry in the
# following table when the time equivalent to 23:59:59 UTC
# is used for the second time. Thus the leap second which
# occurred on 30 June 1972 at 23:59:59 UTC would have TAI
# timestamps computed as follows:
#
# ...
# 30 June 1972 23:59:59 (2287785599, first time): TAI= UTC + 10 seconds
# 30 June 1972 23:59:60 (2287785599,second time): TAI= UTC + 11 seconds
# 1 July 1972 00:00:00 (2287785600) TAI= UTC + 11 seconds
# ...
#
# If your system realizes the leap second by repeating 00:00:00 UTC twice
# (this is possible but not usual), then the advance to the next entry
# in the table must occur the second time that a time equivalent to
# 00:00:00 UTC is used. Thus, using the same example as above:
#
# ...
# 30 June 1972 23:59:59 (2287785599): TAI= UTC + 10 seconds
# 30 June 1972 23:59:60 (2287785600, first time): TAI= UTC + 10 seconds
# 1 July 1972 00:00:00 (2287785600,second time): TAI= UTC + 11 seconds
# ...
#
# in both cases the use of timestamps based on TAI produces a smooth
# time scale with no discontinuity in the time interval. However,
# although the long-term behavior of the time scale is correct in both
# methods, the second method is technically not correct because it adds
# the extra second to the wrong day.
#
# This complexity would not be needed for negative leap seconds (if they
# are ever used). The UTC time would skip 23:59:59 and advance from
# 23:59:58 to 00:00:00 in that case. The TAI offset would decrease by
# 1 second at the same instant. This is a much easier situation to deal
# with, since the difficulty of unambiguously representing the epoch
# during the leap second does not arise.
#
# Some systems implement leap seconds by amortizing the leap second
# over the last few minutes of the day. The frequency of the local
# clock is decreased (or increased) to realize the positive (or
# negative) leap second. This method removes the time step described
# above. Although the long-term behavior of the time scale is correct
# in this case, this method introduces an error during the adjustment
# period both in time and in frequency with respect to the official
# definition of UTC.
#
# Questions or comments to:
# Judah Levine
# Time and Frequency Division
# NIST
# Boulder, Colorado
# Judah.Levine@nist.gov
#
# Last Update of leap second values: 8 July 2016
#
# The following line shows this last update date in NTP timestamp
# format. This is the date on which the most recent change to
# the leap second data was added to the file. This line can
# be identified by the unique pair of characters in the first two
# columns as shown below.
#
#$ 3676924800
#
# The NTP timestamps are in units of seconds since the NTP epoch,
# which is 1 January 1900, 00:00:00. The Modified Julian Day number
# corresponding to the NTP time stamp, X, can be computed as
#
# X/86400 + 15020
#
# where the first term converts seconds to days and the second
# term adds the MJD corresponding to the time origin defined above.
# The integer portion of the result is the integer MJD for that
# day, and any remainder is the time of day, expressed as the
# fraction of the day since 0 hours UTC. The conversion from day
# fraction to seconds or to hours, minutes, and seconds may involve
# rounding or truncation, depending on the method used in the
# computation.
#
# The data in this file will be updated periodically as new leap
# seconds are announced. In addition to being entered on the line
# above, the update time (in NTP format) will be added to the basic
# file name leap-seconds to form the name leap-seconds.<NTP TIME>.
# In addition, the generic name leap-seconds.list will always point to
# the most recent version of the file.
#
# This update procedure will be performed only when a new leap second
# is announced.
#
# The following entry specifies the expiration date of the data
# in this file in units of seconds since the origin at the instant
# 1 January 1900, 00:00:00. This expiration date will be changed
# at least twice per year whether or not a new leap second is
# announced. These semi-annual changes will be made no later
# than 1 June and 1 December of each year to indicate what
# action (if any) is to be taken on 30 June and 31 December,
# respectively. (These are the customary effective dates for new
# leap seconds.) This expiration date will be identified by a
# unique pair of characters in columns 1 and 2 as shown below.
# In the unlikely event that a leap second is announced with an
# effective date other than 30 June or 31 December, then this
# file will be edited to include that leap second as soon as it is
# announced or at least one month before the effective date
# (whichever is later).
# If an announcement by the IERS specifies that no leap second is
# scheduled, then only the expiration date of the file will
# be advanced to show that the information in the file is still
# current -- the update time stamp, the data and the name of the file
# will not change.
#
# Updated through IERS Bulletin C64
# File expires on: 28 June 2023
#
#@ 3896899200
#
2272060800 10 # 1 Jan 1972
2287785600 11 # 1 Jul 1972
2303683200 12 # 1 Jan 1973
2335219200 13 # 1 Jan 1974
2366755200 14 # 1 Jan 1975
2398291200 15 # 1 Jan 1976
2429913600 16 # 1 Jan 1977
2461449600 17 # 1 Jan 1978
2492985600 18 # 1 Jan 1979
2524521600 19 # 1 Jan 1980
2571782400 20 # 1 Jul 1981
2603318400 21 # 1 Jul 1982
2634854400 22 # 1 Jul 1983
2698012800 23 # 1 Jul 1985
2776982400 24 # 1 Jan 1988
2840140800 25 # 1 Jan 1990
2871676800 26 # 1 Jan 1991
2918937600 27 # 1 Jul 1992
2950473600 28 # 1 Jul 1993
2982009600 29 # 1 Jul 1994
3029443200 30 # 1 Jan 1996
3076704000 31 # 1 Jul 1997
3124137600 32 # 1 Jan 1999
3345062400 33 # 1 Jan 2006
3439756800 34 # 1 Jan 2009
3550089600 35 # 1 Jul 2012
3644697600 36 # 1 Jul 2015
3692217600 37 # 1 Jan 2017
#
# the following special comment contains the
# hash value of the data in this file computed
# use the secure hash algorithm as specified
# by FIPS 180-1. See the files in ~/pub/sha for
# the details of how this hash value is
# computed. Note that the hash computation
# ignores comments and whitespace characters
# in data lines. It includes the NTP values
# of both the last modification time and the
# expiration time of the file, but not the
# white space on those lines.
# the hash line is also ignored in the
# computation.
#
#h 2c413af9 124e1031 f165174 ff527c6b 756ae00b

View File

@@ -0,0 +1,240 @@
# Generate zic format 'leapseconds' from NIST format 'leap-seconds.list'.
# This file is in the public domain.
# This program uses awk arithmetic. POSIX requires awk to support
# exact integer arithmetic only through 10**10, which means for NTP
# timestamps this program works only to the year 2216, which is the
# year 1900 plus 10**10 seconds. However, in practice
# POSIX-conforming awk implementations invariably use IEEE-754 double
# and so support exact integers through 2**53. By the year 2216,
# POSIX will almost surely require at least 2**53 for awk, so for NTP
# timestamps this program should be good until the year 285,428,681
# (the year 1900 plus 2**53 seconds). By then leap seconds will be
# long obsolete, as the Earth will likely slow down so much that
# there will be more than 25 hours per day and so some other scheme
# will be needed.
BEGIN {
print "# Allowance for leap seconds added to each time zone file."
print ""
print "# This file is in the public domain."
print ""
print "# This file is generated automatically from the data in the public-domain"
print "# NIST format leap-seconds.list file, which can be copied from"
print "# <ftp://ftp.nist.gov/pub/time/leap-seconds.list>"
print "# or <ftp://ftp.boulder.nist.gov/pub/time/leap-seconds.list>."
print "# The NIST file is used instead of its IERS upstream counterpart"
print "# <https://hpiers.obspm.fr/iers/bul/bulc/ntp/leap-seconds.list>"
print "# because under US law the NIST file is public domain"
print "# whereas the IERS file's copyright and license status is unclear."
print "# For more about leap-seconds.list, please see"
print "# The NTP Timescale and Leap Seconds"
print "# <https://www.eecis.udel.edu/~mills/leap.html>."
print ""
print "# The rules for leap seconds are specified in Annex 1 (Time scales) of:"
print "# Standard-frequency and time-signal emissions."
print "# International Telecommunication Union - Radiocommunication Sector"
print "# (ITU-R) Recommendation TF.460-6 (02/2002)"
print "# <https://www.itu.int/rec/R-REC-TF.460-6-200202-I/>."
print "# The International Earth Rotation and Reference Systems Service (IERS)"
print "# periodically uses leap seconds to keep UTC to within 0.9 s of UT1"
print "# (a proxy for Earth's angle in space as measured by astronomers)"
print "# and publishes leap second data in a copyrighted file"
print "# <https://hpiers.obspm.fr/iers/bul/bulc/Leap_Second.dat>."
print "# See: Levine J. Coordinated Universal Time and the leap second."
print "# URSI Radio Sci Bull. 2016;89(4):30-6. doi:10.23919/URSIRSB.2016.7909995"
print "# <https://ieeexplore.ieee.org/document/7909995>."
print ""
print "# There were no leap seconds before 1972, as no official mechanism"
print "# accounted for the discrepancy between atomic time (TAI) and the earth's"
print "# rotation. The first (\"1 Jan 1972\") data line in leap-seconds.list"
print "# does not denote a leap second; it denotes the start of the current definition"
print "# of UTC."
print ""
print "# All leap-seconds are Stationary (S) at the given UTC time."
print "# The correction (+ or -) is made at the given time, so in the unlikely"
print "# event of a negative leap second, a line would look like this:"
print "# Leap YEAR MON DAY 23:59:59 - S"
print "# Typical lines look like this:"
print "# Leap YEAR MON DAY 23:59:60 + S"
monthabbr[ 1] = "Jan"
monthabbr[ 2] = "Feb"
monthabbr[ 3] = "Mar"
monthabbr[ 4] = "Apr"
monthabbr[ 5] = "May"
monthabbr[ 6] = "Jun"
monthabbr[ 7] = "Jul"
monthabbr[ 8] = "Aug"
monthabbr[ 9] = "Sep"
monthabbr[10] = "Oct"
monthabbr[11] = "Nov"
monthabbr[12] = "Dec"
sstamp_init()
}
# In case the input has CRLF form a la NIST.
{ sub(/\r$/, "") }
/^#[ \t]*[Uu]pdated through/ || /^#[ \t]*[Ff]ile expires on/ {
last_lines = last_lines $0 "\n"
}
/^#[$][ \t]/ { updated = $2 }
/^#[@][ \t]/ { expires = $2 }
/^[ \t]*#/ { next }
{
NTP_timestamp = $1
TAI_minus_UTC = $2
if (old_TAI_minus_UTC) {
if (old_TAI_minus_UTC < TAI_minus_UTC) {
sign = "23:59:60\t+"
} else {
sign = "23:59:59\t-"
}
sstamp_to_ymdhMs(NTP_timestamp - 1, ss_NTP)
printf "Leap\t%d\t%s\t%d\t%s\tS\n", \
ss_year, monthabbr[ss_month], ss_mday, sign
}
old_TAI_minus_UTC = TAI_minus_UTC
}
END {
sstamp_to_ymdhMs(expires, ss_NTP)
print ""
print "# UTC timestamp when this leap second list expires."
print "# Any additional leap seconds will come after this."
if (! EXPIRES_LINE) {
print "# This Expires line is commented out for now,"
print "# so that pre-2020a zic implementations do not reject this file."
}
printf "%sExpires %.4d\t%s\t%.2d\t%.2d:%.2d:%.2d\n", \
EXPIRES_LINE ? "" : "#", \
ss_year, monthabbr[ss_month], ss_mday, ss_hour, ss_min, ss_sec
# The difference between the NTP and POSIX epochs is 70 years
# (including 17 leap days), each 24 hours of 60 minutes of 60
# seconds each.
epoch_minus_NTP = ((1970 - 1900) * 365 + 17) * 24 * 60 * 60
print ""
print "# POSIX timestamps for the data in this file:"
sstamp_to_ymdhMs(updated, ss_NTP)
printf "#updated %d (%.4d-%.2d-%.2d %.2d:%.2d:%.2d UTC)\n", \
updated - epoch_minus_NTP, \
ss_year, ss_month, ss_mday, ss_hour, ss_min, ss_sec
sstamp_to_ymdhMs(expires, ss_NTP)
printf "#expires %d (%.4d-%.2d-%.2d %.2d:%.2d:%.2d UTC)\n", \
expires - epoch_minus_NTP, \
ss_year, ss_month, ss_mday, ss_hour, ss_min, ss_sec
printf "\n%s", last_lines
}
# sstamp_to_ymdhMs - convert seconds timestamp to date and time
#
# Call as:
#
# sstamp_to_ymdhMs(sstamp, epoch_days)
#
# where:
#
# sstamp - is the seconds timestamp.
# epoch_days - is the timestamp epoch in Gregorian days since 1600-03-01.
# ss_NTP is appropriate for an NTP sstamp.
#
# Both arguments should be nonnegative integers.
# On return, the following variables are set based on sstamp:
#
# ss_year - Gregorian calendar year
# ss_month - month of the year (1-January to 12-December)
# ss_mday - day of the month (1-31)
# ss_hour - hour (0-23)
# ss_min - minute (0-59)
# ss_sec - second (0-59)
# ss_wday - day of week (0-Sunday to 6-Saturday)
#
# The function sstamp_init should be called prior to using sstamp_to_ymdhMs.
function sstamp_init()
{
# Days in month N, where March is month 0 and January month 10.
ss_mon_days[ 0] = 31
ss_mon_days[ 1] = 30
ss_mon_days[ 2] = 31
ss_mon_days[ 3] = 30
ss_mon_days[ 4] = 31
ss_mon_days[ 5] = 31
ss_mon_days[ 6] = 30
ss_mon_days[ 7] = 31
ss_mon_days[ 8] = 30
ss_mon_days[ 9] = 31
ss_mon_days[10] = 31
# Counts of days in a Gregorian year, quad-year, century, and quad-century.
ss_year_days = 365
ss_quadyear_days = ss_year_days * 4 + 1
ss_century_days = ss_quadyear_days * 25 - 1
ss_quadcentury_days = ss_century_days * 4 + 1
# Standard day epochs, suitable for epoch_days.
# ss_MJD = 94493
# ss_POSIX = 135080
ss_NTP = 109513
}
function sstamp_to_ymdhMs(sstamp, epoch_days, \
quadcentury, century, quadyear, year, month, day)
{
ss_hour = int(sstamp / 3600) % 24
ss_min = int(sstamp / 60) % 60
ss_sec = sstamp % 60
# Start with a count of days since 1600-03-01 Gregorian.
day = epoch_days + int(sstamp / (24 * 60 * 60))
# Compute a year-month-day date with days of the month numbered
# 0-30, months (March-February) numbered 0-11, and years that start
# start March 1 and end after the last day of February. A quad-year
# starts on March 1 of a year evenly divisible by 4 and ends after
# the last day of February 4 years later. A century starts on and
# ends before March 1 in years evenly divisible by 100.
# A quad-century starts on and ends before March 1 in years divisible
# by 400. While the number of days in a quad-century is a constant,
# the number of days in each other time period can vary by 1.
# Any variation is in the last day of the time period (there might
# or might not be a February 29) where it is easy to deal with.
quadcentury = int(day / ss_quadcentury_days)
day -= quadcentury * ss_quadcentury_days
ss_wday = (day + 3) % 7
century = int(day / ss_century_days)
century -= century == 4
day -= century * ss_century_days
quadyear = int(day / ss_quadyear_days)
day -= quadyear * ss_quadyear_days
year = int(day / ss_year_days)
year -= year == 4
day -= year * ss_year_days
for (month = 0; month < 11; month++) {
if (day < ss_mon_days[month])
break
day -= ss_mon_days[month]
}
# Convert the date to a conventional day of month (1-31),
# month (1-12, January-December) and Gregorian year.
ss_mday = day + 1
if (month <= 9) {
ss_month = month + 3
} else {
ss_month = month - 9
year++
}
ss_year = 1600 + quadcentury * 400 + century * 100 + quadyear * 4 + year
}

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

File diff suppressed because it is too large Load Diff

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,133 @@
.\" This file is in the public domain, so clarified as of
.\" 1996-06-05 by Arthur David Olson.
.TH time2posix 3
.SH NAME
time2posix, posix2time \- convert seconds since the Epoch
.SH SYNOPSIS
.nf
.ie \n(.g .ds - \f(CR-\fP
.el .ds - \-
.B #include <time.h>
.PP
.B time_t time2posix(time_t t);
.PP
.B time_t posix2time(time_t t);
.PP
.B cc ... \*-ltz
.fi
.SH DESCRIPTION
.ie '\(en'' .ds en \-
.el .ds en \(en
.ie '\(lq'' .ds lq \&"\"
.el .ds lq \(lq\"
.ie '\(rq'' .ds rq \&"\"
.el .ds rq \(rq\"
.de q
\\$3\*(lq\\$1\*(rq\\$2
..
IEEE Standard 1003.1
(POSIX)
requires the time_t value 536457599 to stand for 1986-12-31 23:59:59 UTC.
This effectively implies that POSIX time_t values cannot include leap
seconds and,
therefore,
that the system time must be adjusted as each leap occurs.
.PP
If the time package is configured with leap-second support
enabled,
however,
no such adjustment is needed and
time_t values continue to increase over leap events
(as a true
.q "seconds since...\&"
value).
This means that these values will differ from those required by POSIX
by the net number of leap seconds inserted since the Epoch.
.PP
Typically this is not a problem as the type time_t is intended
to be
(mostly)
opaque \*(en time_t values should only be obtained-from and
passed-to functions such as
.BR time(2) ,
.BR localtime(3) ,
.BR mktime(3) ,
and
.BR difftime(3) .
However,
POSIX gives an arithmetic
expression for directly computing a time_t value from a given date/time,
and the same relationship is assumed by some
(usually older)
applications.
Any programs creating/dissecting time_t values
using such a relationship will typically not handle intervals
over leap seconds correctly.
.PP
The
.B time2posix
and
.B posix2time
functions are provided to address this time_t mismatch by converting
between local time_t values and their POSIX equivalents.
This is done by accounting for the number of time-base changes that
would have taken place on a POSIX system as leap seconds were inserted
or deleted.
These converted values can then be used in lieu of correcting the older
applications,
or when communicating with POSIX-compliant systems.
.PP
The
.B time2posix
function
is single-valued.
That is,
every local time_t
corresponds to a single POSIX time_t.
The
.B posix2time
function
is less well-behaved:
for a positive leap second hit the result is not unique,
and for a negative leap second hit the corresponding
POSIX time_t doesn't exist so an adjacent value is returned.
Both of these are good indicators of the inferiority of the
POSIX representation.
.PP
The following table summarizes the relationship between a time
T and its conversion to,
and back from,
the POSIX representation over the leap second inserted at the end of June,
1993.
.nf
.ta \w'93/06/30 'u +\w'23:59:59 'u +\w'A+0 'u +\w'X=time2posix(T) 'u
DATE TIME T X=time2posix(T) posix2time(X)
93/06/30 23:59:59 A+0 B+0 A+0
93/06/30 23:59:60 A+1 B+1 A+1 or A+2
93/07/01 00:00:00 A+2 B+1 A+1 or A+2
93/07/01 00:00:01 A+3 B+2 A+3
A leap second deletion would look like...
DATE TIME T X=time2posix(T) posix2time(X)
??/06/30 23:59:58 A+0 B+0 A+0
??/07/01 00:00:00 A+1 B+2 A+1
??/07/01 00:00:01 A+2 B+3 A+2
.sp
.ce
[Note: posix2time(B+1) => A+0 or A+1]
.fi
.PP
If leap-second support is not enabled,
local time_t and
POSIX time_t values are equivalent,
and both
.B time2posix
and
.B posix2time
degenerate to the identity function.
.SH SEE ALSO
difftime(3),
localtime(3),
mktime(3),
time(2)

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,386 @@
# Convert tzdata source into vanguard or rearguard form.
# Contributed by Paul Eggert. This file is in the public domain.
# This is not a general-purpose converter; it is designed for current tzdata.
# It just converts from current source to main, vanguard, and rearguard forms.
# Although it might be nice for it to be idempotent, or to be useful
# for converting back and forth between vanguard and rearguard formats,
# it does not do these nonessential tasks now.
#
# Although main and vanguard forms are currently equivalent,
# this need not always be the case. When the two forms differ,
# this script can convert either from main to vanguard form (needed then),
# or from vanguard to main form (this conversion would be needed later,
# after main became rearguard and vanguard became main).
# There is no need to convert rearguard to other forms.
#
# When converting to vanguard form, the output can use the line
# "Zone GMT 0 - GMT" which TZUpdater 2.3.2 mistakenly rejects.
#
# When converting to vanguard form, the output can use negative SAVE
# values.
#
# When converting to rearguard form, the output uses only nonnegative
# SAVE values. The idea is for the output data to simulate the behavior
# of the input data as best it can within the constraints of the
# rearguard format.
# Given a FIELD like "-0:30", return a minute count like -30.
function get_minutes(field, \
sign, hours, minutes)
{
sign = field ~ /^-/ ? -1 : 1
hours = +field
if (field ~ /:/) {
minutes = field
sub(/[^:]*:/, "", minutes)
}
return 60 * hours + sign * minutes
}
# Given an OFFSET, which is a minute count like 300 or 330,
# return a %z-style abbreviation like "+05" or "+0530".
function offset_abbr(offset, \
hours, minutes, sign)
{
hours = int(offset / 60)
minutes = offset % 60
if (minutes) {
return sprintf("%+.4d", hours * 100 + minutes);
} else {
return sprintf("%+.2d", hours)
}
}
# Round TIMESTAMP (a +-hh:mm:ss.dddd string) to the nearest second.
function round_to_second(timestamp, \
hh, mm, ss, seconds, dot_dddd, subseconds)
{
dot_dddd = timestamp
if (!sub(/^[+-]?[0-9]+:[0-9]+:[0-9]+\./, ".", dot_dddd))
return timestamp
hh = mm = ss = timestamp
sub(/^[-+]?[0-9]+:[0-9]+:/, "", ss)
sub(/^[-+]?[0-9]+:/, "", mm)
sub(/^[-+]?/, "", hh)
seconds = 3600 * hh + 60 * mm + ss
subseconds = +dot_dddd
seconds += 0.5 < subseconds || ((subseconds == 0.5) && (seconds % 2));
return sprintf("%s%d:%.2d:%.2d", timestamp ~ /^-/ ? "-" : "", \
seconds / 3600, seconds / 60 % 60, seconds % 60)
}
BEGIN {
dataform_type["vanguard"] = 1
dataform_type["main"] = 1
dataform_type["rearguard"] = 1
if (PACKRATLIST) {
while (getline <PACKRATLIST) {
if ($0 ~ /^#/) continue
packratlist[$3] = 1
}
}
# The command line should set DATAFORM.
if (!dataform_type[DATAFORM]) exit 1
}
$1 == "#PACKRATLIST" && $2 == PACKRATLIST {
sub(/^#PACKRATLIST[\t ]+[^\t ]+[\t ]+/, "")
}
/^Zone/ { zone = $2 }
DATAFORM != "main" {
in_comment = $0 ~ /^#/
uncomment = comment_out = 0
# If this line should differ due to Czechoslovakia using negative SAVE values,
# uncomment the desired version and comment out the undesired one.
if (zone == "Europe/Prague" && $0 ~ /^#?[\t ]+[01]:00[\t ]/ \
&& $0 ~ /1947 Feb 23/) {
if (($(in_comment + 2) != "-") == (DATAFORM != "rearguard")) {
uncomment = in_comment
} else {
comment_out = !in_comment
}
}
# If this line should differ due to Ireland using negative SAVE values,
# uncomment the desired version and comment out the undesired one.
Rule_Eire = $0 ~ /^#?Rule[\t ]+Eire[\t ]/
Zone_Dublin_post_1968 \
= (zone == "Europe/Dublin" && $0 ~ /^#?[\t ]+[01]:00[\t ]/ \
&& (!$(in_comment + 4) || 1968 < $(in_comment + 4)))
if (Rule_Eire || Zone_Dublin_post_1968) {
if ((Rule_Eire \
|| (Zone_Dublin_post_1968 && $(in_comment + 3) == "IST/GMT")) \
== (DATAFORM != "rearguard")) {
uncomment = in_comment
} else {
comment_out = !in_comment
}
}
# If this line should differ due to Namibia using negative SAVE values,
# uncomment the desired version and comment out the undesired one.
Rule_Namibia = $0 ~ /^#?Rule[\t ]+Namibia[\t ]/
Zone_using_Namibia_rule \
= (zone == "Africa/Windhoek" && $0 ~ /^#?[\t ]+[12]:00[\t ]/ \
&& ($(in_comment + 2) == "Namibia" \
|| ($(in_comment + 2) == "-" && $(in_comment + 3) == "CAT" \
&& ((1994 <= $(in_comment + 4) && $(in_comment + 4) <= 2017) \
|| in_comment + 3 == NF))))
if (Rule_Namibia || Zone_using_Namibia_rule) {
if ((Rule_Namibia \
? ($9 ~ /^-/ || ($9 == 0 && $10 == "CAT")) \
: $(in_comment + 1) == "2:00" && $(in_comment + 2) == "Namibia") \
== (DATAFORM != "rearguard")) {
uncomment = in_comment
} else {
comment_out = !in_comment
}
}
# If this line should differ due to Portugal benefiting from %z if supported,
# uncomment the desired version and comment out the undesired one.
if ($0 ~ /^#?[\t ]+-[12]:00[\t ]+Port[\t ]+[%+-]/) {
if (($0 ~ /%z/) == (DATAFORM == "vanguard")) {
uncomment = in_comment
} else {
comment_out = !in_comment
}
}
# In vanguard form, use the line "Zone GMT 0 - GMT" instead of
# "Zone Etc/GMT 0 - GMT" and adjust Link lines accordingly.
# This works around a bug in TZUpdater 2.3.2.
if (/^#?(Zone|Link)[\t ]+(Etc\/)?GMT[\t ]/) {
if (($2 == "GMT") == (DATAFORM == "vanguard")) {
uncomment = in_comment
} else {
comment_out = !in_comment
}
}
if (uncomment) {
sub(/^#/, "")
}
if (comment_out) {
sub(/^/, "#")
}
# Prefer %z in vanguard form, explicit abbreviations otherwise.
if (DATAFORM == "vanguard") {
sub(/^(Zone[\t ]+[^\t ]+)?[\t ]+[^\t ]+[\t ]+[^\t ]+[\t ]+[-+][^\t ]+/, \
"&CHANGE-TO-%z")
sub(/-00CHANGE-TO-%z/, "-00")
sub(/[-+][^\t ]+CHANGE-TO-/, "")
} else {
if ($0 ~ /^[^#]*%z/) {
stdoff_column = 2 * ($0 ~ /^Zone/) + 1
rules_column = stdoff_column + 1
stdoff = get_minutes($stdoff_column)
rules = $rules_column
stdabbr = offset_abbr(stdoff)
if (rules == "-") {
abbr = stdabbr
} else {
dstabbr_only = rules ~ /^[+0-9-]/
if (dstabbr_only) {
dstoff = get_minutes(rules)
} else {
# The DST offset is normally an hour, but there are special cases.
if (rules == "Morocco" && NF == 3) {
dstoff = -60
} else if (rules == "NBorneo") {
dstoff = 20
} else if (((rules == "Cook" || rules == "LH") && NF == 3) \
|| (rules == "Uruguay" \
&& $0 ~ /[\t ](1942 Dec 14|1960|1970|1974 Dec 22)$/)) {
dstoff = 30
} else if (rules == "Uruguay" && $0 ~ /[\t ]1974 Mar 10$/) {
dstoff = 90
} else {
dstoff = 60
}
}
dstabbr = offset_abbr(stdoff + dstoff)
if (dstabbr_only) {
abbr = dstabbr
} else {
abbr = stdabbr "/" dstabbr
}
}
sub(/%z/, abbr)
}
}
# Normally, prefer whole seconds. However, prefer subseconds
# if generating vanguard form and the otherwise-undocumented
# VANGUARD_SUBSECONDS environment variable is set.
# This relies on #STDOFF comment lines in the data.
# It is for hypothetical clients that support UT offsets that are
# not integer multiples of one second (e.g., Europe/Lisbon, 1884 to 1912).
# No known clients need this currently, and this experimental
# feature may be changed or withdrawn in future releases.
if ($1 == "#STDOFF") {
stdoff = $2
rounded_stdoff = round_to_second(stdoff)
if (DATAFORM == "vanguard" && ENVIRON["VANGUARD_SUBSECONDS"]) {
stdoff_subst[0] = rounded_stdoff
stdoff_subst[1] = stdoff
} else {
stdoff_subst[0] = stdoff
stdoff_subst[1] = rounded_stdoff
}
} else if (stdoff_subst[0]) {
stdoff_column = 2 * ($0 ~ /^Zone/) + 1
stdoff_column_val = $stdoff_column
if (stdoff_column_val == stdoff_subst[0]) {
sub(stdoff_subst[0], stdoff_subst[1])
} else if (stdoff_column_val != stdoff_subst[1]) {
stdoff_subst[0] = 0
}
}
# In rearguard form, change the Japan rule line with "Sat>=8 25:00"
# to "Sun>=9 1:00", to cater to zic before 2007 and to older Java.
if ($0 ~ /^Rule/ && $2 == "Japan") {
if (DATAFORM == "rearguard") {
if ($7 == "Sat>=8" && $8 == "25:00") {
sub(/Sat>=8/, "Sun>=9")
sub(/25:00/, " 1:00")
}
} else {
if ($7 == "Sun>=9" && $8 == "1:00") {
sub(/Sun>=9/, "Sat>=8")
sub(/ 1:00/, "25:00")
}
}
}
# In rearguard form, change the Morocco lines with negative SAVE values
# to use positive SAVE values.
if ($2 == "Morocco") {
if ($0 ~ /^Rule/) {
if ($4 ~ /^201[78]$/ && $6 == "Oct") {
if (DATAFORM == "rearguard") {
sub(/\t2018\t/, "\t2017\t")
} else {
sub(/\t2017\t/, "\t2018\t")
}
}
if (2019 <= $3) {
if ($8 == "2:00") {
if (DATAFORM == "rearguard") {
sub(/\t0\t/, "\t1:00\t")
} else {
sub(/\t1:00\t/, "\t0\t")
}
} else {
if (DATAFORM == "rearguard") {
sub(/\t-1:00\t/, "\t0\t")
} else {
sub(/\t0\t/, "\t-1:00\t")
}
}
}
}
if ($1 ~ /^[+0-9-]/ && NF == 3) {
if (DATAFORM == "rearguard") {
sub(/1:00\tMorocco/, "0:00\tMorocco")
sub(/\t\+01\/\+00$/, "\t+00/+01")
} else {
sub(/0:00\tMorocco/, "1:00\tMorocco")
sub(/\t\+00\/+01$/, "\t+01/+00")
}
}
}
}
/^Zone/ {
packrat_ignored = FILENAME == PACKRATDATA && PACKRATLIST && !packratlist[$2];
}
{
if (packrat_ignored && $0 !~ /^Rule/) {
sub(/^/, "#")
}
}
# Return a link line resulting by changing OLDLINE to link to TARGET
# from LINKNAME, instead of linking to OLDTARGET from LINKNAME.
# Align data columns the same as they were in OLDLINE.
# Also, replace any existing white space followed by comment with COMMENT.
function make_linkline(oldline, target, linkname, oldtarget, comment, \
oldprefix, oldprefixlen, oldtargettabs, \
replsuffix, targettabs)
{
oldprefix = "Link\t" oldtarget "\t"
oldprefixlen = length(oldprefix)
if (substr(oldline, 1, oldprefixlen) == oldprefix) {
# Use tab stops to preserve LINKNAME's column.
replsuffix = substr(oldline, oldprefixlen + 1)
sub(/[\t ]*#.*/, "", replsuffix)
oldtargettabs = int(length(oldtarget) / 8) + 1
targettabs = int(length(target) / 8) + 1
for (; targettabs < oldtargettabs; targettabs++) {
replsuffix = "\t" replsuffix
}
for (; oldtargettabs < targettabs && replsuffix ~ /^\t/; targettabs--) {
replsuffix = substr(replsuffix, 2)
}
} else {
# Odd format line; don't bother lining up its replacement nicely.
replsuffix = linkname
}
return "Link\t" target "\t" replsuffix comment
}
/^Link/ && $4 == "#=" && DATAFORM == "vanguard" {
$0 = make_linkline($0, $5, $3, $2)
}
# If a Link line is followed by a Link or Zone line for the same data, comment
# out the Link line. This can happen if backzone overrides a Link
# with a Zone or a different Link.
/^Zone/ {
sub(/^Link/, "#Link", line[linkline[$2]])
}
/^Link/ {
sub(/^Link/, "#Link", line[linkline[$3]])
linkline[$3] = NR
linktarget[$3] = $2
}
{ line[NR] = $0 }
function cut_link_chains_short( \
l, linkname, t, target)
{
for (linkname in linktarget) {
target = linktarget[linkname]
t = linktarget[target]
if (t) {
# TARGET is itself a link name. Replace the line "Link TARGET LINKNAME"
# with "Link T LINKNAME #= TARGET", where T is at the end of the chain
# of links that LINKNAME points to.
while ((u = linktarget[t])) {
t = u
}
l = linkline[linkname]
line[l] = make_linkline(line[l], t, linkname, target, "\t#= " target)
}
}
}
END {
if (DATAFORM != "vanguard") {
cut_link_chains_short()
}
for (i = 1; i <= NR; i++)
print line[i]
}

View File

@@ -0,0 +1,356 @@
# Convert tzdata source into a smaller version of itself.
# Contributed by Paul Eggert. This file is in the public domain.
# This is not a general-purpose converter; it is designed for current tzdata.
# 'zic' should treat this script's output as if it were identical to
# this script's input.
# Record a hash N for the new name NAME, checking for collisions.
function record_hash(n, name)
{
if (used_hashes[n]) {
printf "# ! collision: %s %s\n", used_hashes[n], name
exit 1
}
used_hashes[n] = name
}
# Return a shortened rule name representing NAME,
# and record this relationship to the hash table.
function gen_rule_name(name, \
n)
{
# Use a simple mnemonic: the first two letters.
n = substr(name, 1, 2)
record_hash(n, name)
# printf "# %s = %s\n", n, name
return n
}
function prehash_rule_names( \
name)
{
# Rule names are not part of the tzdb API, so substitute shorter
# ones. Shortening them consistently from one release to the next
# simplifies comparison of the output. That being said, the
# 1-letter names below are not standardized in any way, and can
# change arbitrarily from one release to the next, as the main goal
# here is compression not comparison.
# Abbreviating these rules names to one letter saved the most space
# circa 2018e.
rule["Arg"] = "A"
rule["Brazil"] = "B"
rule["Canada"] = "C"
rule["Denmark"] = "D"
rule["EU"] = "E"
rule["France"] = "F"
rule["GB-Eire"] = "G"
rule["Halifax"] = "H"
rule["Italy"] = "I"
rule["Jordan"] = "J"
rule["Egypt"] = "K" # "Kemet" in ancient Egyptian
rule["Libya"] = "L"
rule["Morocco"] = "M"
rule["Neth"] = "N"
rule["Poland"] = "O" # arbitrary
rule["Palestine"] = "P"
rule["Cuba"] = "Q" # Its start sounds like "Q".
rule["Russia"] = "R"
rule["Syria"] = "S"
rule["Turkey"] = "T"
rule["Uruguay"] = "U"
rule["Vincennes"] = "V"
rule["Winn"] = "W"
rule["Mongol"] = "X" # arbitrary
rule["NT_YK"] = "Y"
rule["Zion"] = "Z"
rule["Austria"] = "a"
rule["Belgium"] = "b"
rule["C-Eur"] = "c"
rule["Algeria"] = "d" # country code DZ
rule["E-Eur"] = "e"
rule["Taiwan"] = "f" # Formosa
rule["Greece"] = "g"
rule["Hungary"] = "h"
rule["Iran"] = "i"
rule["StJohns"] = "j"
rule["Chatham"] = "k" # arbitrary
rule["Lebanon"] = "l"
rule["Mexico"] = "m"
rule["Tunisia"] = "n" # country code TN
rule["Moncton"] = "o" # arbitrary
rule["Port"] = "p"
rule["Albania"] = "q" # arbitrary
rule["Regina"] = "r"
rule["Spain"] = "s"
rule["Toronto"] = "t"
rule["US"] = "u"
rule["Louisville"] = "v" # ville
rule["Iceland"] = "w" # arbitrary
rule["Chile"] = "x" # arbitrary
rule["Para"] = "y" # country code PY
rule["Romania"] = "z" # arbitrary
rule["Macau"] = "_" # arbitrary
# Use ISO 3166 alpha-2 country codes for remaining names that are countries.
# This is more systematic, and avoids collisions (e.g., Malta and Moldova).
rule["Armenia"] = "AM"
rule["Aus"] = "AU"
rule["Azer"] = "AZ"
rule["Barb"] = "BB"
rule["Dhaka"] = "BD"
rule["Bulg"] = "BG"
rule["Bahamas"] = "BS"
rule["Belize"] = "BZ"
rule["Swiss"] = "CH"
rule["Cook"] = "CK"
rule["PRC"] = "CN"
rule["Cyprus"] = "CY"
rule["Czech"] = "CZ"
rule["Germany"] = "DE"
rule["DR"] = "DO"
rule["Ecuador"] = "EC"
rule["Finland"] = "FI"
rule["Fiji"] = "FJ"
rule["Falk"] = "FK"
rule["Ghana"] = "GH"
rule["Guat"] = "GT"
rule["Hond"] = "HN"
rule["Haiti"] = "HT"
rule["Eire"] = "IE"
rule["Iraq"] = "IQ"
rule["Japan"] = "JP"
rule["Kyrgyz"] = "KG"
rule["ROK"] = "KR"
rule["Latvia"] = "LV"
rule["Lux"] = "LX"
rule["Moldova"] = "MD"
rule["Malta"] = "MT"
rule["Mauritius"] = "MU"
rule["Namibia"] = "NA"
rule["Nic"] = "NI"
rule["Norway"] = "NO"
rule["Peru"] = "PE"
rule["Phil"] = "PH"
rule["Pakistan"] = "PK"
rule["Sudan"] = "SD"
rule["Salv"] = "SV"
rule["Tonga"] = "TO"
rule["Vanuatu"] = "VU"
# Avoid collisions.
rule["Detroit"] = "Dt" # De = Denver
for (name in rule) {
record_hash(rule[name], name)
}
}
function make_line(n, field, \
f, r)
{
r = field[1]
for (f = 2; f <= n; f++)
r = r " " field[f]
return r
}
# Process the input line LINE and save it for later output.
function process_input_line(line, \
f, field, end, i, n, r, startdef, \
linkline, ruleline, zoneline)
{
# Remove comments, normalize spaces, and append a space to each line.
sub(/#.*/, "", line)
line = line " "
gsub(/[\t ]+/, " ", line)
# Abbreviate keywords and determine line type.
linkline = sub(/^Link /, "L ", line)
ruleline = sub(/^Rule /, "R ", line)
zoneline = sub(/^Zone /, "Z ", line)
# Replace FooAsia rules with the same rules without "Asia", as they
# are duplicates.
if (match(line, /[^ ]Asia /)) {
if (ruleline) return
line = substr(line, 1, RSTART) substr(line, RSTART + 5)
}
# Abbreviate times.
while (match(line, /[: ]0+[0-9]/))
line = substr(line, 1, RSTART) substr(line, RSTART + RLENGTH - 1)
while (match(line, /:0[^:]/))
line = substr(line, 1, RSTART - 1) substr(line, RSTART + 2)
# Abbreviate weekday names.
while (match(line, / (last)?(Mon|Wed|Fri)[ <>]/)) {
end = RSTART + RLENGTH
line = substr(line, 1, end - 4) substr(line, end - 1)
}
while (match(line, / (last)?(Sun|Tue|Thu|Sat)[ <>]/)) {
end = RSTART + RLENGTH
line = substr(line, 1, end - 3) substr(line, end - 1)
}
# Abbreviate "max", "min", "only" and month names.
gsub(/ max /, " ma ", line)
gsub(/ min /, " mi ", line)
gsub(/ only /, " o ", line)
gsub(/ Jan /, " Ja ", line)
gsub(/ Feb /, " F ", line)
gsub(/ Apr /, " Ap ", line)
gsub(/ Aug /, " Au ", line)
gsub(/ Sep /, " S ", line)
gsub(/ Oct /, " O ", line)
gsub(/ Nov /, " N ", line)
gsub(/ Dec /, " D ", line)
# Strip leading and trailing space.
sub(/^ /, "", line)
sub(/ $/, "", line)
# Remove unnecessary trailing zero fields.
sub(/ 0+$/, "", line)
# Remove unnecessary trailing days-of-month "1".
if (match(line, /[A-Za-z] 1$/))
line = substr(line, 1, RSTART)
# Remove unnecessary trailing " Ja" (for January).
sub(/ Ja$/, "", line)
n = split(line, field)
# Record which rule names are used, and generate their abbreviations.
f = zoneline ? 4 : linkline || ruleline ? 0 : 2
r = field[f]
if (r ~ /^[^-+0-9]/) {
rule_used[r] = 1
}
# If this zone supersedes an earlier one, delete the earlier one
# from the saved output lines.
startdef = ""
if (zoneline)
zonename = startdef = field[2]
else if (linkline)
zonename = startdef = field[3]
else if (ruleline)
zonename = ""
if (startdef) {
i = zonedef[startdef]
if (i) {
do
output_line[i - 1] = ""
while (output_line[i++] ~ /^[-+0-9]/);
}
}
zonedef[zonename] = nout + 1
# Save the line for later output.
output_line[nout++] = make_line(n, field)
}
function omit_unused_rules( \
i, field)
{
for (i = 0; i < nout; i++) {
split(output_line[i], field)
if (field[1] == "R" && !rule_used[field[2]]) {
output_line[i] = ""
}
}
}
function abbreviate_rule_names( \
abbr, f, field, i, n, r)
{
for (i = 0; i < nout; i++) {
n = split(output_line[i], field)
if (n) {
f = field[1] == "Z" ? 4 : field[1] == "L" ? 0 : 2
r = field[f]
if (r ~ /^[^-+0-9]/) {
abbr = rule[r]
if (!abbr) {
rule[r] = abbr = gen_rule_name(r)
}
field[f] = abbr
output_line[i] = make_line(n, field)
}
}
}
}
function output_saved_lines( \
i)
{
for (i = 0; i < nout; i++)
if (output_line[i])
print output_line[i]
}
BEGIN {
# Files that the output normally depends on.
default_dep["africa"] = 1
default_dep["antarctica"] = 1
default_dep["asia"] = 1
default_dep["australasia"] = 1
default_dep["backward"] = 1
default_dep["etcetera"] = 1
default_dep["europe"] = 1
default_dep["factory"] = 1
default_dep["northamerica"] = 1
default_dep["southamerica"] = 1
default_dep["ziguard.awk"] = 1
default_dep["zishrink.awk"] = 1
# Output a version string from 'version' and related configuration variables
# supported by tzdb's Makefile. If you change the makefile or any other files
# that affect the output of this script, you should append '-SOMETHING'
# to the contents of 'version', where SOMETHING identifies what was changed.
ndeps = split(deps, dep)
ddeps = ""
for (i = 1; i <= ndeps; i++) {
if (default_dep[dep[i]]) {
default_dep[dep[i]]++
} else {
ddeps = ddeps " " dep[i]
}
}
for (d in default_dep) {
if (default_dep[d] == 1) {
ddeps = ddeps " !" d
}
}
print "# version", version
if (dataform != "main") {
print "# dataform", dataform
}
if (redo != "posix_right") {
print "# redo " redo
}
if (ddeps) {
print "# ddeps" ddeps
}
print "# This zic input file is in the public domain."
prehash_rule_names()
}
/^[\t ]*[^#\t ]/ {
process_input_line($0)
}
END {
omit_unused_rules()
abbreviate_rule_names()
output_saved_lines()
}

View File

@@ -0,0 +1,449 @@
# tzdb timezone descriptions (deprecated version)
#
# This file is in the public domain, so clarified as of
# 2009-05-17 by Arthur David Olson.
#
# From Paul Eggert (2021-09-20):
# This file is intended as a backward-compatibility aid for older programs.
# New programs should use zone1970.tab. This file is like zone1970.tab (see
# zone1970.tab's comments), but with the following additional restrictions:
#
# 1. This file contains only ASCII characters.
# 2. The first data column contains exactly one country code.
#
# Because of (2), each row stands for an area that is the intersection
# of a region identified by a country code and of a timezone where civil
# clocks have agreed since 1970; this is a narrower definition than
# that of zone1970.tab.
#
# Unlike zone1970.tab, a row's third column can be a Link from
# 'backward' instead of a Zone.
#
# This table is intended as an aid for users, to help them select timezones
# appropriate for their practical needs. It is not intended to take or
# endorse any position on legal or territorial claims.
#
#country-
#code coordinates TZ comments
AD +4230+00131 Europe/Andorra
AE +2518+05518 Asia/Dubai
AF +3431+06912 Asia/Kabul
AG +1703-06148 America/Antigua
AI +1812-06304 America/Anguilla
AL +4120+01950 Europe/Tirane
AM +4011+04430 Asia/Yerevan
AO -0848+01314 Africa/Luanda
AQ -7750+16636 Antarctica/McMurdo New Zealand time - McMurdo, South Pole
AQ -6617+11031 Antarctica/Casey Casey
AQ -6835+07758 Antarctica/Davis Davis
AQ -6640+14001 Antarctica/DumontDUrville Dumont-d'Urville
AQ -6736+06253 Antarctica/Mawson Mawson
AQ -6448-06406 Antarctica/Palmer Palmer
AQ -6734-06808 Antarctica/Rothera Rothera
AQ -690022+0393524 Antarctica/Syowa Syowa
AQ -720041+0023206 Antarctica/Troll Troll
AQ -7824+10654 Antarctica/Vostok Vostok
AR -3436-05827 America/Argentina/Buenos_Aires Buenos Aires (BA, CF)
AR -3124-06411 America/Argentina/Cordoba Argentina (most areas: CB, CC, CN, ER, FM, MN, SE, SF)
AR -2447-06525 America/Argentina/Salta Salta (SA, LP, NQ, RN)
AR -2411-06518 America/Argentina/Jujuy Jujuy (JY)
AR -2649-06513 America/Argentina/Tucuman Tucuman (TM)
AR -2828-06547 America/Argentina/Catamarca Catamarca (CT); Chubut (CH)
AR -2926-06651 America/Argentina/La_Rioja La Rioja (LR)
AR -3132-06831 America/Argentina/San_Juan San Juan (SJ)
AR -3253-06849 America/Argentina/Mendoza Mendoza (MZ)
AR -3319-06621 America/Argentina/San_Luis San Luis (SL)
AR -5138-06913 America/Argentina/Rio_Gallegos Santa Cruz (SC)
AR -5448-06818 America/Argentina/Ushuaia Tierra del Fuego (TF)
AS -1416-17042 Pacific/Pago_Pago
AT +4813+01620 Europe/Vienna
AU -3133+15905 Australia/Lord_Howe Lord Howe Island
AU -5430+15857 Antarctica/Macquarie Macquarie Island
AU -4253+14719 Australia/Hobart Tasmania
AU -3749+14458 Australia/Melbourne Victoria
AU -3352+15113 Australia/Sydney New South Wales (most areas)
AU -3157+14127 Australia/Broken_Hill New South Wales (Yancowinna)
AU -2728+15302 Australia/Brisbane Queensland (most areas)
AU -2016+14900 Australia/Lindeman Queensland (Whitsunday Islands)
AU -3455+13835 Australia/Adelaide South Australia
AU -1228+13050 Australia/Darwin Northern Territory
AU -3157+11551 Australia/Perth Western Australia (most areas)
AU -3143+12852 Australia/Eucla Western Australia (Eucla)
AW +1230-06958 America/Aruba
AX +6006+01957 Europe/Mariehamn
AZ +4023+04951 Asia/Baku
BA +4352+01825 Europe/Sarajevo
BB +1306-05937 America/Barbados
BD +2343+09025 Asia/Dhaka
BE +5050+00420 Europe/Brussels
BF +1222-00131 Africa/Ouagadougou
BG +4241+02319 Europe/Sofia
BH +2623+05035 Asia/Bahrain
BI -0323+02922 Africa/Bujumbura
BJ +0629+00237 Africa/Porto-Novo
BL +1753-06251 America/St_Barthelemy
BM +3217-06446 Atlantic/Bermuda
BN +0456+11455 Asia/Brunei
BO -1630-06809 America/La_Paz
BQ +120903-0681636 America/Kralendijk
BR -0351-03225 America/Noronha Atlantic islands
BR -0127-04829 America/Belem Para (east); Amapa
BR -0343-03830 America/Fortaleza Brazil (northeast: MA, PI, CE, RN, PB)
BR -0803-03454 America/Recife Pernambuco
BR -0712-04812 America/Araguaina Tocantins
BR -0940-03543 America/Maceio Alagoas, Sergipe
BR -1259-03831 America/Bahia Bahia
BR -2332-04637 America/Sao_Paulo Brazil (southeast: GO, DF, MG, ES, RJ, SP, PR, SC, RS)
BR -2027-05437 America/Campo_Grande Mato Grosso do Sul
BR -1535-05605 America/Cuiaba Mato Grosso
BR -0226-05452 America/Santarem Para (west)
BR -0846-06354 America/Porto_Velho Rondonia
BR +0249-06040 America/Boa_Vista Roraima
BR -0308-06001 America/Manaus Amazonas (east)
BR -0640-06952 America/Eirunepe Amazonas (west)
BR -0958-06748 America/Rio_Branco Acre
BS +2505-07721 America/Nassau
BT +2728+08939 Asia/Thimphu
BW -2439+02555 Africa/Gaborone
BY +5354+02734 Europe/Minsk
BZ +1730-08812 America/Belize
CA +4734-05243 America/St_Johns Newfoundland; Labrador (southeast)
CA +4439-06336 America/Halifax Atlantic - NS (most areas); PE
CA +4612-05957 America/Glace_Bay Atlantic - NS (Cape Breton)
CA +4606-06447 America/Moncton Atlantic - New Brunswick
CA +5320-06025 America/Goose_Bay Atlantic - Labrador (most areas)
CA +5125-05707 America/Blanc-Sablon AST - QC (Lower North Shore)
CA +4339-07923 America/Toronto Eastern - ON, QC (most areas)
CA +6344-06828 America/Iqaluit Eastern - NU (most areas)
CA +484531-0913718 America/Atikokan EST - ON (Atikokan); NU (Coral H)
CA +4953-09709 America/Winnipeg Central - ON (west); Manitoba
CA +744144-0944945 America/Resolute Central - NU (Resolute)
CA +624900-0920459 America/Rankin_Inlet Central - NU (central)
CA +5024-10439 America/Regina CST - SK (most areas)
CA +5017-10750 America/Swift_Current CST - SK (midwest)
CA +5333-11328 America/Edmonton Mountain - AB; BC (E); SK (W)
CA +690650-1050310 America/Cambridge_Bay Mountain - NU (west)
CA +6227-11421 America/Yellowknife Mountain - NT (central)
CA +682059-1334300 America/Inuvik Mountain - NT (west)
CA +4906-11631 America/Creston MST - BC (Creston)
CA +5546-12014 America/Dawson_Creek MST - BC (Dawson Cr, Ft St John)
CA +5848-12242 America/Fort_Nelson MST - BC (Ft Nelson)
CA +6043-13503 America/Whitehorse MST - Yukon (east)
CA +6404-13925 America/Dawson MST - Yukon (west)
CA +4916-12307 America/Vancouver Pacific - BC (most areas)
CC -1210+09655 Indian/Cocos
CD -0418+01518 Africa/Kinshasa Dem. Rep. of Congo (west)
CD -1140+02728 Africa/Lubumbashi Dem. Rep. of Congo (east)
CF +0422+01835 Africa/Bangui
CG -0416+01517 Africa/Brazzaville
CH +4723+00832 Europe/Zurich
CI +0519-00402 Africa/Abidjan
CK -2114-15946 Pacific/Rarotonga
CL -3327-07040 America/Santiago Chile (most areas)
CL -5309-07055 America/Punta_Arenas Region of Magallanes
CL -2709-10926 Pacific/Easter Easter Island
CM +0403+00942 Africa/Douala
CN +3114+12128 Asia/Shanghai Beijing Time
CN +4348+08735 Asia/Urumqi Xinjiang Time
CO +0436-07405 America/Bogota
CR +0956-08405 America/Costa_Rica
CU +2308-08222 America/Havana
CV +1455-02331 Atlantic/Cape_Verde
CW +1211-06900 America/Curacao
CX -1025+10543 Indian/Christmas
CY +3510+03322 Asia/Nicosia Cyprus (most areas)
CY +3507+03357 Asia/Famagusta Northern Cyprus
CZ +5005+01426 Europe/Prague
DE +5230+01322 Europe/Berlin Germany (most areas)
DE +4742+00841 Europe/Busingen Busingen
DJ +1136+04309 Africa/Djibouti
DK +5540+01235 Europe/Copenhagen
DM +1518-06124 America/Dominica
DO +1828-06954 America/Santo_Domingo
DZ +3647+00303 Africa/Algiers
EC -0210-07950 America/Guayaquil Ecuador (mainland)
EC -0054-08936 Pacific/Galapagos Galapagos Islands
EE +5925+02445 Europe/Tallinn
EG +3003+03115 Africa/Cairo
EH +2709-01312 Africa/El_Aaiun
ER +1520+03853 Africa/Asmara
ES +4024-00341 Europe/Madrid Spain (mainland)
ES +3553-00519 Africa/Ceuta Ceuta, Melilla
ES +2806-01524 Atlantic/Canary Canary Islands
ET +0902+03842 Africa/Addis_Ababa
FI +6010+02458 Europe/Helsinki
FJ -1808+17825 Pacific/Fiji
FK -5142-05751 Atlantic/Stanley
FM +0725+15147 Pacific/Chuuk Chuuk/Truk, Yap
FM +0658+15813 Pacific/Pohnpei Pohnpei/Ponape
FM +0519+16259 Pacific/Kosrae Kosrae
FO +6201-00646 Atlantic/Faroe
FR +4852+00220 Europe/Paris
GA +0023+00927 Africa/Libreville
GB +513030-0000731 Europe/London
GD +1203-06145 America/Grenada
GE +4143+04449 Asia/Tbilisi
GF +0456-05220 America/Cayenne
GG +492717-0023210 Europe/Guernsey
GH +0533-00013 Africa/Accra
GI +3608-00521 Europe/Gibraltar
GL +6411-05144 America/Nuuk Greenland (most areas)
GL +7646-01840 America/Danmarkshavn National Park (east coast)
GL +7029-02158 America/Scoresbysund Scoresbysund/Ittoqqortoormiit
GL +7634-06847 America/Thule Thule/Pituffik
GM +1328-01639 Africa/Banjul
GN +0931-01343 Africa/Conakry
GP +1614-06132 America/Guadeloupe
GQ +0345+00847 Africa/Malabo
GR +3758+02343 Europe/Athens
GS -5416-03632 Atlantic/South_Georgia
GT +1438-09031 America/Guatemala
GU +1328+14445 Pacific/Guam
GW +1151-01535 Africa/Bissau
GY +0648-05810 America/Guyana
HK +2217+11409 Asia/Hong_Kong
HN +1406-08713 America/Tegucigalpa
HR +4548+01558 Europe/Zagreb
HT +1832-07220 America/Port-au-Prince
HU +4730+01905 Europe/Budapest
ID -0610+10648 Asia/Jakarta Java, Sumatra
ID -0002+10920 Asia/Pontianak Borneo (west, central)
ID -0507+11924 Asia/Makassar Borneo (east, south); Sulawesi/Celebes, Bali, Nusa Tengarra; Timor (west)
ID -0232+14042 Asia/Jayapura New Guinea (West Papua / Irian Jaya); Malukus/Moluccas
IE +5320-00615 Europe/Dublin
IL +314650+0351326 Asia/Jerusalem
IM +5409-00428 Europe/Isle_of_Man
IN +2232+08822 Asia/Kolkata
IO -0720+07225 Indian/Chagos
IQ +3321+04425 Asia/Baghdad
IR +3540+05126 Asia/Tehran
IS +6409-02151 Atlantic/Reykjavik
IT +4154+01229 Europe/Rome
JE +491101-0020624 Europe/Jersey
JM +175805-0764736 America/Jamaica
JO +3157+03556 Asia/Amman
JP +353916+1394441 Asia/Tokyo
KE -0117+03649 Africa/Nairobi
KG +4254+07436 Asia/Bishkek
KH +1133+10455 Asia/Phnom_Penh
KI +0125+17300 Pacific/Tarawa Gilbert Islands
KI -0247-17143 Pacific/Kanton Phoenix Islands
KI +0152-15720 Pacific/Kiritimati Line Islands
KM -1141+04316 Indian/Comoro
KN +1718-06243 America/St_Kitts
KP +3901+12545 Asia/Pyongyang
KR +3733+12658 Asia/Seoul
KW +2920+04759 Asia/Kuwait
KY +1918-08123 America/Cayman
KZ +4315+07657 Asia/Almaty Kazakhstan (most areas)
KZ +4448+06528 Asia/Qyzylorda Qyzylorda/Kyzylorda/Kzyl-Orda
KZ +5312+06337 Asia/Qostanay Qostanay/Kostanay/Kustanay
KZ +5017+05710 Asia/Aqtobe Aqtobe/Aktobe
KZ +4431+05016 Asia/Aqtau Mangghystau/Mankistau
KZ +4707+05156 Asia/Atyrau Atyrau/Atirau/Gur'yev
KZ +5113+05121 Asia/Oral West Kazakhstan
LA +1758+10236 Asia/Vientiane
LB +3353+03530 Asia/Beirut
LC +1401-06100 America/St_Lucia
LI +4709+00931 Europe/Vaduz
LK +0656+07951 Asia/Colombo
LR +0618-01047 Africa/Monrovia
LS -2928+02730 Africa/Maseru
LT +5441+02519 Europe/Vilnius
LU +4936+00609 Europe/Luxembourg
LV +5657+02406 Europe/Riga
LY +3254+01311 Africa/Tripoli
MA +3339-00735 Africa/Casablanca
MC +4342+00723 Europe/Monaco
MD +4700+02850 Europe/Chisinau
ME +4226+01916 Europe/Podgorica
MF +1804-06305 America/Marigot
MG -1855+04731 Indian/Antananarivo
MH +0709+17112 Pacific/Majuro Marshall Islands (most areas)
MH +0905+16720 Pacific/Kwajalein Kwajalein
MK +4159+02126 Europe/Skopje
ML +1239-00800 Africa/Bamako
MM +1647+09610 Asia/Yangon
MN +4755+10653 Asia/Ulaanbaatar Mongolia (most areas)
MN +4801+09139 Asia/Hovd Bayan-Olgiy, Govi-Altai, Hovd, Uvs, Zavkhan
MN +4804+11430 Asia/Choibalsan Dornod, Sukhbaatar
MO +221150+1133230 Asia/Macau
MP +1512+14545 Pacific/Saipan
MQ +1436-06105 America/Martinique
MR +1806-01557 Africa/Nouakchott
MS +1643-06213 America/Montserrat
MT +3554+01431 Europe/Malta
MU -2010+05730 Indian/Mauritius
MV +0410+07330 Indian/Maldives
MW -1547+03500 Africa/Blantyre
MX +1924-09909 America/Mexico_City Central Mexico
MX +2105-08646 America/Cancun Quintana Roo
MX +2058-08937 America/Merida Campeche, Yucatan
MX +2540-10019 America/Monterrey Durango; Coahuila, Nuevo Leon, Tamaulipas (most areas)
MX +2550-09730 America/Matamoros Coahuila, Nuevo Leon, Tamaulipas (US border)
MX +2838-10605 America/Chihuahua Chihuahua (most areas)
MX +3144-10629 America/Ciudad_Juarez Chihuahua (US border - west)
MX +2934-10425 America/Ojinaga Chihuahua (US border - east)
MX +2313-10625 America/Mazatlan Baja California Sur, Nayarit (most areas), Sinaloa
MX +2048-10515 America/Bahia_Banderas Bahia de Banderas
MX +2904-11058 America/Hermosillo Sonora
MX +3232-11701 America/Tijuana Baja California
MY +0310+10142 Asia/Kuala_Lumpur Malaysia (peninsula)
MY +0133+11020 Asia/Kuching Sabah, Sarawak
MZ -2558+03235 Africa/Maputo
NA -2234+01706 Africa/Windhoek
NC -2216+16627 Pacific/Noumea
NE +1331+00207 Africa/Niamey
NF -2903+16758 Pacific/Norfolk
NG +0627+00324 Africa/Lagos
NI +1209-08617 America/Managua
NL +5222+00454 Europe/Amsterdam
NO +5955+01045 Europe/Oslo
NP +2743+08519 Asia/Kathmandu
NR -0031+16655 Pacific/Nauru
NU -1901-16955 Pacific/Niue
NZ -3652+17446 Pacific/Auckland New Zealand (most areas)
NZ -4357-17633 Pacific/Chatham Chatham Islands
OM +2336+05835 Asia/Muscat
PA +0858-07932 America/Panama
PE -1203-07703 America/Lima
PF -1732-14934 Pacific/Tahiti Society Islands
PF -0900-13930 Pacific/Marquesas Marquesas Islands
PF -2308-13457 Pacific/Gambier Gambier Islands
PG -0930+14710 Pacific/Port_Moresby Papua New Guinea (most areas)
PG -0613+15534 Pacific/Bougainville Bougainville
PH +1435+12100 Asia/Manila
PK +2452+06703 Asia/Karachi
PL +5215+02100 Europe/Warsaw
PM +4703-05620 America/Miquelon
PN -2504-13005 Pacific/Pitcairn
PR +182806-0660622 America/Puerto_Rico
PS +3130+03428 Asia/Gaza Gaza Strip
PS +313200+0350542 Asia/Hebron West Bank
PT +3843-00908 Europe/Lisbon Portugal (mainland)
PT +3238-01654 Atlantic/Madeira Madeira Islands
PT +3744-02540 Atlantic/Azores Azores
PW +0720+13429 Pacific/Palau
PY -2516-05740 America/Asuncion
QA +2517+05132 Asia/Qatar
RE -2052+05528 Indian/Reunion
RO +4426+02606 Europe/Bucharest
RS +4450+02030 Europe/Belgrade
RU +5443+02030 Europe/Kaliningrad MSK-01 - Kaliningrad
RU +554521+0373704 Europe/Moscow MSK+00 - Moscow area
# The obsolescent zone.tab format cannot represent Europe/Simferopol well.
# Put it in RU section and list as UA. See "territorial claims" above.
# Programs should use zone1970.tab instead; see above.
UA +4457+03406 Europe/Simferopol Crimea
RU +5836+04939 Europe/Kirov MSK+00 - Kirov
RU +4844+04425 Europe/Volgograd MSK+00 - Volgograd
RU +4621+04803 Europe/Astrakhan MSK+01 - Astrakhan
RU +5134+04602 Europe/Saratov MSK+01 - Saratov
RU +5420+04824 Europe/Ulyanovsk MSK+01 - Ulyanovsk
RU +5312+05009 Europe/Samara MSK+01 - Samara, Udmurtia
RU +5651+06036 Asia/Yekaterinburg MSK+02 - Urals
RU +5500+07324 Asia/Omsk MSK+03 - Omsk
RU +5502+08255 Asia/Novosibirsk MSK+04 - Novosibirsk
RU +5322+08345 Asia/Barnaul MSK+04 - Altai
RU +5630+08458 Asia/Tomsk MSK+04 - Tomsk
RU +5345+08707 Asia/Novokuznetsk MSK+04 - Kemerovo
RU +5601+09250 Asia/Krasnoyarsk MSK+04 - Krasnoyarsk area
RU +5216+10420 Asia/Irkutsk MSK+05 - Irkutsk, Buryatia
RU +5203+11328 Asia/Chita MSK+06 - Zabaykalsky
RU +6200+12940 Asia/Yakutsk MSK+06 - Lena River
RU +623923+1353314 Asia/Khandyga MSK+06 - Tomponsky, Ust-Maysky
RU +4310+13156 Asia/Vladivostok MSK+07 - Amur River
RU +643337+1431336 Asia/Ust-Nera MSK+07 - Oymyakonsky
RU +5934+15048 Asia/Magadan MSK+08 - Magadan
RU +4658+14242 Asia/Sakhalin MSK+08 - Sakhalin Island
RU +6728+15343 Asia/Srednekolymsk MSK+08 - Sakha (E); North Kuril Is
RU +5301+15839 Asia/Kamchatka MSK+09 - Kamchatka
RU +6445+17729 Asia/Anadyr MSK+09 - Bering Sea
RW -0157+03004 Africa/Kigali
SA +2438+04643 Asia/Riyadh
SB -0932+16012 Pacific/Guadalcanal
SC -0440+05528 Indian/Mahe
SD +1536+03232 Africa/Khartoum
SE +5920+01803 Europe/Stockholm
SG +0117+10351 Asia/Singapore
SH -1555-00542 Atlantic/St_Helena
SI +4603+01431 Europe/Ljubljana
SJ +7800+01600 Arctic/Longyearbyen
SK +4809+01707 Europe/Bratislava
SL +0830-01315 Africa/Freetown
SM +4355+01228 Europe/San_Marino
SN +1440-01726 Africa/Dakar
SO +0204+04522 Africa/Mogadishu
SR +0550-05510 America/Paramaribo
SS +0451+03137 Africa/Juba
ST +0020+00644 Africa/Sao_Tome
SV +1342-08912 America/El_Salvador
SX +180305-0630250 America/Lower_Princes
SY +3330+03618 Asia/Damascus
SZ -2618+03106 Africa/Mbabane
TC +2128-07108 America/Grand_Turk
TD +1207+01503 Africa/Ndjamena
TF -492110+0701303 Indian/Kerguelen
TG +0608+00113 Africa/Lome
TH +1345+10031 Asia/Bangkok
TJ +3835+06848 Asia/Dushanbe
TK -0922-17114 Pacific/Fakaofo
TL -0833+12535 Asia/Dili
TM +3757+05823 Asia/Ashgabat
TN +3648+01011 Africa/Tunis
TO -210800-1751200 Pacific/Tongatapu
TR +4101+02858 Europe/Istanbul
TT +1039-06131 America/Port_of_Spain
TV -0831+17913 Pacific/Funafuti
TW +2503+12130 Asia/Taipei
TZ -0648+03917 Africa/Dar_es_Salaam
UA +5026+03031 Europe/Kyiv Ukraine (most areas)
UG +0019+03225 Africa/Kampala
UM +2813-17722 Pacific/Midway Midway Islands
UM +1917+16637 Pacific/Wake Wake Island
US +404251-0740023 America/New_York Eastern (most areas)
US +421953-0830245 America/Detroit Eastern - MI (most areas)
US +381515-0854534 America/Kentucky/Louisville Eastern - KY (Louisville area)
US +364947-0845057 America/Kentucky/Monticello Eastern - KY (Wayne)
US +394606-0860929 America/Indiana/Indianapolis Eastern - IN (most areas)
US +384038-0873143 America/Indiana/Vincennes Eastern - IN (Da, Du, K, Mn)
US +410305-0863611 America/Indiana/Winamac Eastern - IN (Pulaski)
US +382232-0862041 America/Indiana/Marengo Eastern - IN (Crawford)
US +382931-0871643 America/Indiana/Petersburg Eastern - IN (Pike)
US +384452-0850402 America/Indiana/Vevay Eastern - IN (Switzerland)
US +415100-0873900 America/Chicago Central (most areas)
US +375711-0864541 America/Indiana/Tell_City Central - IN (Perry)
US +411745-0863730 America/Indiana/Knox Central - IN (Starke)
US +450628-0873651 America/Menominee Central - MI (Wisconsin border)
US +470659-1011757 America/North_Dakota/Center Central - ND (Oliver)
US +465042-1012439 America/North_Dakota/New_Salem Central - ND (Morton rural)
US +471551-1014640 America/North_Dakota/Beulah Central - ND (Mercer)
US +394421-1045903 America/Denver Mountain (most areas)
US +433649-1161209 America/Boise Mountain - ID (south); OR (east)
US +332654-1120424 America/Phoenix MST - Arizona (except Navajo)
US +340308-1181434 America/Los_Angeles Pacific
US +611305-1495401 America/Anchorage Alaska (most areas)
US +581807-1342511 America/Juneau Alaska - Juneau area
US +571035-1351807 America/Sitka Alaska - Sitka area
US +550737-1313435 America/Metlakatla Alaska - Annette Island
US +593249-1394338 America/Yakutat Alaska - Yakutat
US +643004-1652423 America/Nome Alaska (west)
US +515248-1763929 America/Adak Aleutian Islands
US +211825-1575130 Pacific/Honolulu Hawaii
UY -345433-0561245 America/Montevideo
UZ +3940+06648 Asia/Samarkand Uzbekistan (west)
UZ +4120+06918 Asia/Tashkent Uzbekistan (east)
VA +415408+0122711 Europe/Vatican
VC +1309-06114 America/St_Vincent
VE +1030-06656 America/Caracas
VG +1827-06437 America/Tortola
VI +1821-06456 America/St_Thomas
VN +1045+10640 Asia/Ho_Chi_Minh
VU -1740+16825 Pacific/Efate
WF -1318-17610 Pacific/Wallis
WS -1350-17144 Pacific/Apia
YE +1245+04512 Asia/Aden
YT -1247+04514 Indian/Mayotte
ZA -2615+02800 Africa/Johannesburg
ZM -1525+02817 Africa/Lusaka
ZW -1750+03103 Africa/Harare

View File

@@ -0,0 +1,372 @@
# tzdb timezone descriptions
#
# This file is in the public domain.
#
# From Paul Eggert (2018-06-27):
# This file contains a table where each row stands for a timezone where
# civil timestamps have agreed since 1970. Columns are separated by
# a single tab. Lines beginning with '#' are comments. All text uses
# UTF-8 encoding. The columns of the table are as follows:
#
# 1. The countries that overlap the timezone, as a comma-separated list
# of ISO 3166 2-character country codes. See the file 'iso3166.tab'.
# 2. Latitude and longitude of the timezone's principal location
# in ISO 6709 sign-degrees-minutes-seconds format,
# either ±DDMM±DDDMM or ±DDMMSS±DDDMMSS,
# first latitude (+ is north), then longitude (+ is east).
# 3. Timezone name used in value of TZ environment variable.
# Please see the theory.html file for how these names are chosen.
# If multiple timezones overlap a country, each has a row in the
# table, with each column 1 containing the country code.
# 4. Comments; present if and only if a country has multiple timezones.
#
# If a timezone covers multiple countries, the most-populous city is used,
# and that country is listed first in column 1; any other countries
# are listed alphabetically by country code. The table is sorted
# first by country code, then (if possible) by an order within the
# country that (1) makes some geographical sense, and (2) puts the
# most populous timezones first, where that does not contradict (1).
#
# This table is intended as an aid for users, to help them select timezones
# appropriate for their practical needs. It is not intended to take or
# endorse any position on legal or territorial claims.
#
#country-
#codes coordinates TZ comments
AD +4230+00131 Europe/Andorra
AE,OM,RE,SC,TF +2518+05518 Asia/Dubai UAE, Oman, Réunion, Seychelles, Crozet, Scattered Is
AF +3431+06912 Asia/Kabul
AL +4120+01950 Europe/Tirane
AM +4011+04430 Asia/Yerevan
AQ -6617+11031 Antarctica/Casey Casey
AQ -6835+07758 Antarctica/Davis Davis
AQ -6736+06253 Antarctica/Mawson Mawson
AQ -6448-06406 Antarctica/Palmer Palmer
AQ -6734-06808 Antarctica/Rothera Rothera
AQ -720041+0023206 Antarctica/Troll Troll
AR -3436-05827 America/Argentina/Buenos_Aires Buenos Aires (BA, CF)
AR -3124-06411 America/Argentina/Cordoba Argentina (most areas: CB, CC, CN, ER, FM, MN, SE, SF)
AR -2447-06525 America/Argentina/Salta Salta (SA, LP, NQ, RN)
AR -2411-06518 America/Argentina/Jujuy Jujuy (JY)
AR -2649-06513 America/Argentina/Tucuman Tucumán (TM)
AR -2828-06547 America/Argentina/Catamarca Catamarca (CT); Chubut (CH)
AR -2926-06651 America/Argentina/La_Rioja La Rioja (LR)
AR -3132-06831 America/Argentina/San_Juan San Juan (SJ)
AR -3253-06849 America/Argentina/Mendoza Mendoza (MZ)
AR -3319-06621 America/Argentina/San_Luis San Luis (SL)
AR -5138-06913 America/Argentina/Rio_Gallegos Santa Cruz (SC)
AR -5448-06818 America/Argentina/Ushuaia Tierra del Fuego (TF)
AS,UM -1416-17042 Pacific/Pago_Pago Samoa, Midway
AT +4813+01620 Europe/Vienna
AU -3133+15905 Australia/Lord_Howe Lord Howe Island
AU -5430+15857 Antarctica/Macquarie Macquarie Island
AU -4253+14719 Australia/Hobart Tasmania
AU -3749+14458 Australia/Melbourne Victoria
AU -3352+15113 Australia/Sydney New South Wales (most areas)
AU -3157+14127 Australia/Broken_Hill New South Wales (Yancowinna)
AU -2728+15302 Australia/Brisbane Queensland (most areas)
AU -2016+14900 Australia/Lindeman Queensland (Whitsunday Islands)
AU -3455+13835 Australia/Adelaide South Australia
AU -1228+13050 Australia/Darwin Northern Territory
AU -3157+11551 Australia/Perth Western Australia (most areas)
AU -3143+12852 Australia/Eucla Western Australia (Eucla)
AZ +4023+04951 Asia/Baku
BB +1306-05937 America/Barbados
BD +2343+09025 Asia/Dhaka
BE,LU,NL +5050+00420 Europe/Brussels
BG +4241+02319 Europe/Sofia
BM +3217-06446 Atlantic/Bermuda
BO -1630-06809 America/La_Paz
BR -0351-03225 America/Noronha Atlantic islands
BR -0127-04829 America/Belem Pará (east); Amapá
BR -0343-03830 America/Fortaleza Brazil (northeast: MA, PI, CE, RN, PB)
BR -0803-03454 America/Recife Pernambuco
BR -0712-04812 America/Araguaina Tocantins
BR -0940-03543 America/Maceio Alagoas, Sergipe
BR -1259-03831 America/Bahia Bahia
BR -2332-04637 America/Sao_Paulo Brazil (southeast: GO, DF, MG, ES, RJ, SP, PR, SC, RS)
BR -2027-05437 America/Campo_Grande Mato Grosso do Sul
BR -1535-05605 America/Cuiaba Mato Grosso
BR -0226-05452 America/Santarem Pará (west)
BR -0846-06354 America/Porto_Velho Rondônia
BR +0249-06040 America/Boa_Vista Roraima
BR -0308-06001 America/Manaus Amazonas (east)
BR -0640-06952 America/Eirunepe Amazonas (west)
BR -0958-06748 America/Rio_Branco Acre
BT +2728+08939 Asia/Thimphu
BY +5354+02734 Europe/Minsk
BZ +1730-08812 America/Belize
CA +4734-05243 America/St_Johns Newfoundland; Labrador (southeast)
CA +4439-06336 America/Halifax Atlantic - NS (most areas); PE
CA +4612-05957 America/Glace_Bay Atlantic - NS (Cape Breton)
CA +4606-06447 America/Moncton Atlantic - New Brunswick
CA +5320-06025 America/Goose_Bay Atlantic - Labrador (most areas)
CA,BS +4339-07923 America/Toronto Eastern - ON, QC (most areas), Bahamas
CA +6344-06828 America/Iqaluit Eastern - NU (most areas)
CA +4953-09709 America/Winnipeg Central - ON (west); Manitoba
CA +744144-0944945 America/Resolute Central - NU (Resolute)
CA +624900-0920459 America/Rankin_Inlet Central - NU (central)
CA +5024-10439 America/Regina CST - SK (most areas)
CA +5017-10750 America/Swift_Current CST - SK (midwest)
CA +5333-11328 America/Edmonton Mountain - AB; BC (E); SK (W)
CA +690650-1050310 America/Cambridge_Bay Mountain - NU (west)
CA +6227-11421 America/Yellowknife Mountain - NT (central)
CA +682059-1334300 America/Inuvik Mountain - NT (west)
CA +5546-12014 America/Dawson_Creek MST - BC (Dawson Cr, Ft St John)
CA +5848-12242 America/Fort_Nelson MST - BC (Ft Nelson)
CA +6043-13503 America/Whitehorse MST - Yukon (east)
CA +6404-13925 America/Dawson MST - Yukon (west)
CA +4916-12307 America/Vancouver Pacific - BC (most areas)
CH,DE,LI +4723+00832 Europe/Zurich Swiss time
CI,BF,GH,GM,GN,IS,ML,MR,SH,SL,SN,TG +0519-00402 Africa/Abidjan
CK -2114-15946 Pacific/Rarotonga
CL -3327-07040 America/Santiago Chile (most areas)
CL -5309-07055 America/Punta_Arenas Region of Magallanes
CL -2709-10926 Pacific/Easter Easter Island
CN +3114+12128 Asia/Shanghai Beijing Time
CN,AQ +4348+08735 Asia/Urumqi Xinjiang Time, Vostok
CO +0436-07405 America/Bogota
CR +0956-08405 America/Costa_Rica
CU +2308-08222 America/Havana
CV +1455-02331 Atlantic/Cape_Verde
CY +3510+03322 Asia/Nicosia Cyprus (most areas)
CY +3507+03357 Asia/Famagusta Northern Cyprus
CZ,SK +5005+01426 Europe/Prague
DE,DK,NO,SE,SJ +5230+01322 Europe/Berlin Germany (most areas), Scandinavia
DO +1828-06954 America/Santo_Domingo
DZ +3647+00303 Africa/Algiers
EC -0210-07950 America/Guayaquil Ecuador (mainland)
EC -0054-08936 Pacific/Galapagos Galápagos Islands
EE +5925+02445 Europe/Tallinn
EG +3003+03115 Africa/Cairo
EH +2709-01312 Africa/El_Aaiun
ES +4024-00341 Europe/Madrid Spain (mainland)
ES +3553-00519 Africa/Ceuta Ceuta, Melilla
ES +2806-01524 Atlantic/Canary Canary Islands
FI,AX +6010+02458 Europe/Helsinki
FJ -1808+17825 Pacific/Fiji
FK -5142-05751 Atlantic/Stanley
FM +0519+16259 Pacific/Kosrae Kosrae
FO +6201-00646 Atlantic/Faroe
FR,MC +4852+00220 Europe/Paris
GB,GG,IM,JE +513030-0000731 Europe/London
GE +4143+04449 Asia/Tbilisi
GF +0456-05220 America/Cayenne
GI +3608-00521 Europe/Gibraltar
GL +6411-05144 America/Nuuk Greenland (most areas)
GL +7646-01840 America/Danmarkshavn National Park (east coast)
GL +7029-02158 America/Scoresbysund Scoresbysund/Ittoqqortoormiit
GL +7634-06847 America/Thule Thule/Pituffik
GR +3758+02343 Europe/Athens
GS -5416-03632 Atlantic/South_Georgia
GT +1438-09031 America/Guatemala
GU,MP +1328+14445 Pacific/Guam
GW +1151-01535 Africa/Bissau
GY +0648-05810 America/Guyana
HK +2217+11409 Asia/Hong_Kong
HN +1406-08713 America/Tegucigalpa
HT +1832-07220 America/Port-au-Prince
HU +4730+01905 Europe/Budapest
ID -0610+10648 Asia/Jakarta Java, Sumatra
ID -0002+10920 Asia/Pontianak Borneo (west, central)
ID -0507+11924 Asia/Makassar Borneo (east, south); Sulawesi/Celebes, Bali, Nusa Tengarra; Timor (west)
ID -0232+14042 Asia/Jayapura New Guinea (West Papua / Irian Jaya); Malukus/Moluccas
IE +5320-00615 Europe/Dublin
IL +314650+0351326 Asia/Jerusalem
IN +2232+08822 Asia/Kolkata
IO -0720+07225 Indian/Chagos
IQ +3321+04425 Asia/Baghdad
IR +3540+05126 Asia/Tehran
IT,SM,VA +4154+01229 Europe/Rome
JM +175805-0764736 America/Jamaica
JO +3157+03556 Asia/Amman
JP +353916+1394441 Asia/Tokyo
KE,DJ,ER,ET,KM,MG,SO,TZ,UG,YT -0117+03649 Africa/Nairobi
KG +4254+07436 Asia/Bishkek
KI,MH,TV,UM,WF +0125+17300 Pacific/Tarawa Gilberts, Marshalls, Tuvalu, Wallis & Futuna, Wake
KI -0247-17143 Pacific/Kanton Phoenix Islands
KI +0152-15720 Pacific/Kiritimati Line Islands
KP +3901+12545 Asia/Pyongyang
KR +3733+12658 Asia/Seoul
KZ +4315+07657 Asia/Almaty Kazakhstan (most areas)
KZ +4448+06528 Asia/Qyzylorda Qyzylorda/Kyzylorda/Kzyl-Orda
KZ +5312+06337 Asia/Qostanay Qostanay/Kostanay/Kustanay
KZ +5017+05710 Asia/Aqtobe Aqtöbe/Aktobe
KZ +4431+05016 Asia/Aqtau Mangghystaū/Mankistau
KZ +4707+05156 Asia/Atyrau Atyraū/Atirau/Gur'yev
KZ +5113+05121 Asia/Oral West Kazakhstan
LB +3353+03530 Asia/Beirut
LK +0656+07951 Asia/Colombo
LR +0618-01047 Africa/Monrovia
LT +5441+02519 Europe/Vilnius
LV +5657+02406 Europe/Riga
LY +3254+01311 Africa/Tripoli
MA +3339-00735 Africa/Casablanca
MD +4700+02850 Europe/Chisinau
MH +0905+16720 Pacific/Kwajalein Kwajalein
MM,CC +1647+09610 Asia/Yangon
MN +4755+10653 Asia/Ulaanbaatar Mongolia (most areas)
MN +4801+09139 Asia/Hovd Bayan-Ölgii, Govi-Altai, Hovd, Uvs, Zavkhan
MN +4804+11430 Asia/Choibalsan Dornod, Sükhbaatar
MO +221150+1133230 Asia/Macau
MQ +1436-06105 America/Martinique
MT +3554+01431 Europe/Malta
MU -2010+05730 Indian/Mauritius
MV,TF +0410+07330 Indian/Maldives Maldives, Kerguelen, St Paul I, Amsterdam I
MX +1924-09909 America/Mexico_City Central Mexico
MX +2105-08646 America/Cancun Quintana Roo
MX +2058-08937 America/Merida Campeche, Yucatán
MX +2540-10019 America/Monterrey Durango; Coahuila, Nuevo León, Tamaulipas (most areas)
MX +2550-09730 America/Matamoros Coahuila, Nuevo León, Tamaulipas (US border)
MX +2838-10605 America/Chihuahua Chihuahua (most areas)
MX +3144-10629 America/Ciudad_Juarez Chihuahua (US border - west)
MX +2934-10425 America/Ojinaga Chihuahua (US border - east)
MX +2313-10625 America/Mazatlan Baja California Sur, Nayarit (most areas), Sinaloa
MX +2048-10515 America/Bahia_Banderas Bahía de Banderas
MX +2904-11058 America/Hermosillo Sonora
MX +3232-11701 America/Tijuana Baja California
MY,BN +0133+11020 Asia/Kuching Sabah, Sarawak, Brunei
MZ,BI,BW,CD,MW,RW,ZM,ZW -2558+03235 Africa/Maputo Central Africa Time
NA -2234+01706 Africa/Windhoek
NC -2216+16627 Pacific/Noumea
NF -2903+16758 Pacific/Norfolk
NG,AO,BJ,CD,CF,CG,CM,GA,GQ,NE +0627+00324 Africa/Lagos West Africa Time
NI +1209-08617 America/Managua
NP +2743+08519 Asia/Kathmandu
NR -0031+16655 Pacific/Nauru
NU -1901-16955 Pacific/Niue
NZ,AQ -3652+17446 Pacific/Auckland New Zealand time
NZ -4357-17633 Pacific/Chatham Chatham Islands
PA,CA,KY +0858-07932 America/Panama EST - Panama, Cayman, ON (Atikokan), NU (Coral H)
PE -1203-07703 America/Lima
PF -1732-14934 Pacific/Tahiti Society Islands
PF -0900-13930 Pacific/Marquesas Marquesas Islands
PF -2308-13457 Pacific/Gambier Gambier Islands
PG,AQ,FM -0930+14710 Pacific/Port_Moresby Papua New Guinea (most areas), Chuuk, Yap, Dumont d'Urville
PG -0613+15534 Pacific/Bougainville Bougainville
PH +1435+12100 Asia/Manila
PK +2452+06703 Asia/Karachi
PL +5215+02100 Europe/Warsaw
PM +4703-05620 America/Miquelon
PN -2504-13005 Pacific/Pitcairn
PR,AG,CA,AI,AW,BL,BQ,CW,DM,GD,GP,KN,LC,MF,MS,SX,TT,VC,VG,VI +182806-0660622 America/Puerto_Rico AST
PS +3130+03428 Asia/Gaza Gaza Strip
PS +313200+0350542 Asia/Hebron West Bank
PT +3843-00908 Europe/Lisbon Portugal (mainland)
PT +3238-01654 Atlantic/Madeira Madeira Islands
PT +3744-02540 Atlantic/Azores Azores
PW +0720+13429 Pacific/Palau
PY -2516-05740 America/Asuncion
QA,BH +2517+05132 Asia/Qatar
RO +4426+02606 Europe/Bucharest
RS,BA,HR,ME,MK,SI +4450+02030 Europe/Belgrade
RU +5443+02030 Europe/Kaliningrad MSK-01 - Kaliningrad
RU +554521+0373704 Europe/Moscow MSK+00 - Moscow area
# Mention RU and UA alphabetically. See "territorial claims" above.
RU,UA +4457+03406 Europe/Simferopol Crimea
RU +5836+04939 Europe/Kirov MSK+00 - Kirov
RU +4844+04425 Europe/Volgograd MSK+00 - Volgograd
RU +4621+04803 Europe/Astrakhan MSK+01 - Astrakhan
RU +5134+04602 Europe/Saratov MSK+01 - Saratov
RU +5420+04824 Europe/Ulyanovsk MSK+01 - Ulyanovsk
RU +5312+05009 Europe/Samara MSK+01 - Samara, Udmurtia
RU +5651+06036 Asia/Yekaterinburg MSK+02 - Urals
RU +5500+07324 Asia/Omsk MSK+03 - Omsk
RU +5502+08255 Asia/Novosibirsk MSK+04 - Novosibirsk
RU +5322+08345 Asia/Barnaul MSK+04 - Altai
RU +5630+08458 Asia/Tomsk MSK+04 - Tomsk
RU +5345+08707 Asia/Novokuznetsk MSK+04 - Kemerovo
RU +5601+09250 Asia/Krasnoyarsk MSK+04 - Krasnoyarsk area
RU +5216+10420 Asia/Irkutsk MSK+05 - Irkutsk, Buryatia
RU +5203+11328 Asia/Chita MSK+06 - Zabaykalsky
RU +6200+12940 Asia/Yakutsk MSK+06 - Lena River
RU +623923+1353314 Asia/Khandyga MSK+06 - Tomponsky, Ust-Maysky
RU +4310+13156 Asia/Vladivostok MSK+07 - Amur River
RU +643337+1431336 Asia/Ust-Nera MSK+07 - Oymyakonsky
RU +5934+15048 Asia/Magadan MSK+08 - Magadan
RU +4658+14242 Asia/Sakhalin MSK+08 - Sakhalin Island
RU +6728+15343 Asia/Srednekolymsk MSK+08 - Sakha (E); North Kuril Is
RU +5301+15839 Asia/Kamchatka MSK+09 - Kamchatka
RU +6445+17729 Asia/Anadyr MSK+09 - Bering Sea
SA,AQ,KW,YE +2438+04643 Asia/Riyadh Arabia, Syowa
SB,FM -0932+16012 Pacific/Guadalcanal Solomons, Pohnpei
SD +1536+03232 Africa/Khartoum
SG,MY +0117+10351 Asia/Singapore Singapore, peninsular Malaysia
SR +0550-05510 America/Paramaribo
SS +0451+03137 Africa/Juba
ST +0020+00644 Africa/Sao_Tome
SV +1342-08912 America/El_Salvador
SY +3330+03618 Asia/Damascus
TC +2128-07108 America/Grand_Turk
TD +1207+01503 Africa/Ndjamena
TH,CX,KH,LA,VN +1345+10031 Asia/Bangkok Indochina (most areas)
TJ +3835+06848 Asia/Dushanbe
TK -0922-17114 Pacific/Fakaofo
TL -0833+12535 Asia/Dili
TM +3757+05823 Asia/Ashgabat
TN +3648+01011 Africa/Tunis
TO -210800-1751200 Pacific/Tongatapu
TR +4101+02858 Europe/Istanbul
TW +2503+12130 Asia/Taipei
UA +5026+03031 Europe/Kyiv Ukraine (most areas)
US +404251-0740023 America/New_York Eastern (most areas)
US +421953-0830245 America/Detroit Eastern - MI (most areas)
US +381515-0854534 America/Kentucky/Louisville Eastern - KY (Louisville area)
US +364947-0845057 America/Kentucky/Monticello Eastern - KY (Wayne)
US +394606-0860929 America/Indiana/Indianapolis Eastern - IN (most areas)
US +384038-0873143 America/Indiana/Vincennes Eastern - IN (Da, Du, K, Mn)
US +410305-0863611 America/Indiana/Winamac Eastern - IN (Pulaski)
US +382232-0862041 America/Indiana/Marengo Eastern - IN (Crawford)
US +382931-0871643 America/Indiana/Petersburg Eastern - IN (Pike)
US +384452-0850402 America/Indiana/Vevay Eastern - IN (Switzerland)
US +415100-0873900 America/Chicago Central (most areas)
US +375711-0864541 America/Indiana/Tell_City Central - IN (Perry)
US +411745-0863730 America/Indiana/Knox Central - IN (Starke)
US +450628-0873651 America/Menominee Central - MI (Wisconsin border)
US +470659-1011757 America/North_Dakota/Center Central - ND (Oliver)
US +465042-1012439 America/North_Dakota/New_Salem Central - ND (Morton rural)
US +471551-1014640 America/North_Dakota/Beulah Central - ND (Mercer)
US +394421-1045903 America/Denver Mountain (most areas)
US +433649-1161209 America/Boise Mountain - ID (south); OR (east)
US,CA +332654-1120424 America/Phoenix MST - Arizona (except Navajo), Creston BC
US +340308-1181434 America/Los_Angeles Pacific
US +611305-1495401 America/Anchorage Alaska (most areas)
US +581807-1342511 America/Juneau Alaska - Juneau area
US +571035-1351807 America/Sitka Alaska - Sitka area
US +550737-1313435 America/Metlakatla Alaska - Annette Island
US +593249-1394338 America/Yakutat Alaska - Yakutat
US +643004-1652423 America/Nome Alaska (west)
US +515248-1763929 America/Adak Aleutian Islands
US,UM +211825-1575130 Pacific/Honolulu Hawaii
UY -345433-0561245 America/Montevideo
UZ +3940+06648 Asia/Samarkand Uzbekistan (west)
UZ +4120+06918 Asia/Tashkent Uzbekistan (east)
VE +1030-06656 America/Caracas
VN +1045+10640 Asia/Ho_Chi_Minh Vietnam (south)
VU -1740+16825 Pacific/Efate
WS -1350-17144 Pacific/Apia
ZA,LS,SZ -2615+02800 Africa/Johannesburg
#
# The next section contains experimental tab-separated comments for
# use by user agents like tzselect that identify continents and oceans.
#
# For example, the comment "#@AQ<tab>Antarctica/" means the country code
# AQ is in the continent Antarctica regardless of the Zone name,
# so Pacific/Auckland should be listed under Antarctica as well as
# under the Pacific because its line's country codes include AQ.
#
# If more than one country code is affected each is listed separated
# by commas, e.g., #@IS,SH<tab>Atlantic/". If a country code is in
# more than one continent or ocean, each is listed separated by
# commas, e.g., the second column of "#@CY,TR<tab>Asia/,Europe/".
#
# These experimental comments are present only for country codes where
# the continent or ocean is not already obvious from the Zone name.
# For example, there is no such comment for RU since it already
# corresponds to Zone names starting with both "Europe/" and "Asia/".
#
#@AQ Antarctica/
#@IS,SH Atlantic/
#@CY,TR Asia/,Europe/
#@SJ Arctic/
#@CC,CX,KM,MG,YT Indian/

View File

@@ -0,0 +1,11 @@
add_compile_options(
-Werror=all
-Werror=extra
-Werror=shadow
)
include_directories(.)
add_subdirectory(tzdb2nx)
add_subdirectory(tzdb)

View File

@@ -0,0 +1,90 @@
find_program(GIT_PROGRAM git)
if (NOT GIT_PROGRAM)
message(FATAL_ERROR "git program not found")
endif()
find_program(GNU_DATE date)
if (NOT GNU_DATE)
message(FATAL_ERROR "date program not found")
endif()
set(NX_TZDB_DIR "${CMAKE_CURRENT_BINARY_DIR}/nx" CACHE PATH "Path to Switch-style time zone data")
set(NX_ZONEINFO_DIR "${NX_TZDB_DIR}/zoneinfo")
set(TZDB_VERSION_FILE ${TZ_SOURCE_DIR}/NEWS)
if (NOT "${TZDB2NX_VERSION}" STREQUAL "")
set(TZDB_VERSION "${TZDB2NX_VERSION}\n")
else()
execute_process(
COMMAND
${GIT_PROGRAM} log --pretty=%at -n1 NEWS
OUTPUT_VARIABLE
TZ_COMMIT_TIME
WORKING_DIRECTORY
${TZ_SOURCE_DIR}
COMMAND_ERROR_IS_FATAL ANY)
string(REPLACE "\n" "" TZ_COMMIT_TIME "${TZ_COMMIT_TIME}")
if (APPLE OR CMAKE_SYSTEM_NAME MATCHES "DragonFly|FreeBSD|NetBSD|OpenBSD")
set(VERSION_COMMAND ${GNU_DATE} -r ${TZ_COMMIT_TIME} +%y%m%d)
else ()
set(VERSION_COMMAND ${GNU_DATE} +%y%m%d --date=@${TZ_COMMIT_TIME})
endif ()
execute_process(
COMMAND
${VERSION_COMMAND}
OUTPUT_VARIABLE
TZDB_VERSION
COMMAND_ERROR_IS_FATAL ANY)
endif()
set(NX_VERSION_FILE ${NX_TZDB_DIR}/version.txt)
file(WRITE ${NX_VERSION_FILE} "${TZDB_VERSION}")
add_custom_target(x80e
DEPENDS
tzdb2nx
${NX_VERSION_FILE})
set(BINARY_LIST_TXT ${NX_TZDB_DIR}/binaryList.txt)
add_custom_command(
OUTPUT
${BINARY_LIST_TXT}
COMMAND
${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/generate_binary_list_txt.cmake ${BINARY_LIST_TXT} ${PROJECT_SOURCE_DIR}/CMakeModules/list_directory.cmake
WORKING_DIRECTORY
${NX_ZONEINFO_DIR})
add_custom_target(time_zone_binary_list
DEPENDS ${BINARY_LIST_TXT})
add_dependencies(x80e time_zone_binary_list)
set(TZ_DATA_LIST "")
file(STRINGS "${TZIF_LIST_FILE}" TZ_FILES)
foreach(FILE ${TZ_FILES})
file(RELATIVE_PATH TARG "${TZ_ZONEINFO_DIR}" "${FILE}")
get_filename_component(TARG_PATH "${NX_ZONEINFO_DIR}/${TARG}" DIRECTORY)
string(REGEX REPLACE "\/" "_" TARG_SANITIZED "${TARG}")
set(NX_TZ_TARGET ${NX_ZONEINFO_DIR}/${TARG})
add_custom_command(
OUTPUT
${NX_TZ_TARGET}
COMMAND
mkdir -p ${TARG_PATH}
COMMAND
${TZDB2NX_PATH} ${FILE} ${NX_ZONEINFO_DIR}/${TARG}
DEPENDS
tzdb2nx)
list(APPEND TZ_DATA_LIST ${NX_TZ_TARGET})
endforeach()
add_custom_target(time_zone_data
DEPENDS ${TZ_DATA_LIST})
add_dependencies(x80e time_zone_data)
add_dependencies(time_zone_binary_list time_zone_data)

View File

@@ -0,0 +1,52 @@
set(BINARY_LIST_TXT ${CMAKE_ARGV3})
set(LIST_DIR_CMAKE ${CMAKE_ARGV4})
# Fill text file with zone names
# Issue: Hyphens/underscores are not handled the same way Nintendo handles them
function(get_files_nx TARG SUB_DIR)
execute_process(
COMMAND
${CMAKE_COMMAND} -P ${LIST_DIR_CMAKE} false OFF
WORKING_DIRECTORY
${TARG}
OUTPUT_VARIABLE
FILE_LIST
)
list(SORT FILE_LIST)
execute_process(
COMMAND
${CMAKE_COMMAND} -P ${LIST_DIR_CMAKE} true OFF
WORKING_DIRECTORY
${TARG}
OUTPUT_VARIABLE
DIR_LIST
)
foreach(FILE ${FILE_LIST})
if(FILE STREQUAL "\n")
continue()
endif()
list(REMOVE_ITEM DIR_LIST FILE)
if (SUB_DIR)
file(APPEND ${BINARY_LIST_TXT} "${SUB_DIR}/${FILE}\r\n")
else()
file(APPEND ${BINARY_LIST_TXT} "${FILE}\r\n")
endif()
endforeach()
list(SORT DIR_LIST)
foreach(DIR ${DIR_LIST})
if (NOT DIR OR DIR STREQUAL "\n")
continue()
endif()
if (SUB_DIR)
get_files_nx(${TARG}/${DIR} ${SUB_DIR}/${DIR})
else()
get_files_nx(${TARG}/${DIR} ${DIR})
endif()
endforeach()
endfunction()
get_files_nx(${CMAKE_SOURCE_DIR} "")

View File

@@ -0,0 +1,6 @@
add_executable(tzdb2nx
main.cpp
tzif.cpp
tzif.h)
set(TZDB2NX_PATH "$<TARGET_FILE:tzdb2nx>" CACHE PATH "Path to tzdb2nx path")

View File

@@ -0,0 +1,158 @@
#include "tzif.h"
#include <array>
#include <cerrno>
#include <cstdio>
#include <cstring>
#include <fcntl.h>
#include <getopt.h>
#include <poll.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
constexpr std::size_t ten_megabytes{(1 << 20) * 10};
static void ShortHelp(const char *argv0) {
std::fprintf(stderr, "Usage: %s [INFILE] [OUTFILE]\n", argv0);
}
static void PrintArg(const char *short_arg, const char *long_arg,
const char *text) {
std::fprintf(stderr, "%5s, %-20s %s\n", short_arg, long_arg, text);
}
static void PrintHelp(const char *argv0) {
ShortHelp(argv0);
std::fprintf(stderr,
"Converts a TZif file INFILE from the RFC8536 format to a "
"Nintendo Switch compatible file OUTFILE.\nWith no arguments, "
"tzdb2nx can read and write from stdin/stdout, "
"respectively.\nGiving no arguments without input will print "
"usage information and exit the program.\n\nArguments:\n");
PrintArg("-h", "--help", "Print this help text and exit");
}
int main(int argc, char *argv[]) {
int f{STDIN_FILENO};
const char *filename{"(stdin)"};
std::size_t filesize{ten_megabytes};
const char *optstring = "h";
int c;
const struct option longopts[] = {
{
"help",
no_argument,
nullptr,
'h',
},
{
nullptr,
0,
nullptr,
0,
},
};
while ((c = getopt_long(argc, argv, optstring, longopts, nullptr)) != -1) {
switch (c) {
case 'h':
PrintHelp(argv[0]);
return -1;
case '?':
ShortHelp(argv[0]);
return -1;
}
}
if (argc > 1) {
filename = argv[1];
f = open(filename, O_RDONLY);
if (f == -1) {
const int err = errno;
std::fprintf(stderr, "%s: %s\n", filename, std::strerror(err));
return err;
}
struct stat statbuf;
fstat(f, &statbuf);
filesize = statbuf.st_size;
} else {
struct pollfd fds {
f, POLLIN, 0,
};
const int result = poll(&fds, 1, 0);
if (result == 0) {
std::fprintf(stderr, "%s: No input\n", filename);
ShortHelp(argv[0]);
return -1;
}
}
u_int8_t *buf = new u_int8_t[filesize];
filesize = read(f, buf, filesize);
if (filesize == static_cast<std::size_t>(-1)) {
const int err = errno;
std::fprintf(stderr, "%s: %s\n", filename, std::strerror(err));
return err;
}
int result = close(f);
if (result == -1) {
const int err = errno;
std::fprintf(stderr, "%s: %s\n", filename, std::strerror(err));
return err;
}
if (filesize < 4) {
std::fprintf(stderr, "%s: Too small\n", filename);
return -1;
}
if (std::strncmp(reinterpret_cast<const char *>(buf), "TZif", 4) != 0) {
std::fprintf(stderr, "%s: Bad magic number\n", filename);
return -1;
}
const std::unique_ptr<Tzif::Data> tzif_data = Tzif::ReadData(buf, filesize);
if (tzif_data == nullptr) {
std::fprintf(stderr, "%s: Error occured while reading data\n", filename);
return -1;
}
delete[] buf;
std::vector<u_int8_t> output_buffer;
tzif_data->ReformatNintendo(output_buffer);
filename = "(stdout)";
f = STDOUT_FILENO;
if (argc > 2) {
filename = argv[2];
f = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0664);
if (f == -1) {
const int err = errno;
std::fprintf(stderr, "%s: %s\n", filename, std::strerror(err));
return err;
}
}
result = write(f, output_buffer.data(), output_buffer.size());
if (result == -1) {
const int err = errno;
std::fprintf(stderr, "%s: %s\n", filename, std::strerror(err));
return err;
}
result = close(f);
if (result == -1) {
const int err = errno;
std::fprintf(stderr, "%s: %s\n", filename, std::strerror(err));
return err;
}
return 0;
}

View File

@@ -0,0 +1,146 @@
#include "tzif.h"
#include <cstdint>
#include <cstring>
#include <memory>
#include <sys/types.h>
namespace Tzif {
static std::size_t SkipToVersion2(const u_int8_t *data, std::size_t size) {
char magic[5];
const u_int8_t *p{data};
std::memcpy(magic, data, 4);
magic[4] = '\0';
if (std::strcmp(magic, "TZif") != 0) {
return -1;
}
do {
p++;
if (p >= data + size) {
return -1;
}
} while (std::strncmp(reinterpret_cast<const char *>(p), "TZif", 4) != 0);
return p - data;
}
template <typename Type> constexpr static void SwapEndianess(Type *value) {
u_int8_t *data = reinterpret_cast<u_int8_t *>(value);
union {
u_int8_t data[sizeof(Type)];
Type value;
} temp;
for (u_int32_t i = 0; i < sizeof(Type); i++) {
u_int32_t alt_index = sizeof(Type) - i - 1;
temp.data[alt_index] = data[i];
}
*value = temp.value;
}
static void FlipHeader(Header &header) {
SwapEndianess(&header.isutcnt);
SwapEndianess(&header.isstdcnt);
SwapEndianess(&header.leapcnt);
SwapEndianess(&header.timecnt);
SwapEndianess(&header.typecnt);
SwapEndianess(&header.charcnt);
}
std::unique_ptr<DataImpl> ReadData(const u_int8_t *data, std::size_t size) {
const std::size_t v2_offset = SkipToVersion2(data, size);
if (v2_offset == static_cast<std::size_t>(-1)) {
return nullptr;
}
const u_int8_t *p = data + v2_offset;
Header header;
std::memcpy(&header, p, sizeof(header));
p += sizeof(header);
FlipHeader(header);
const std::size_t data_block_length =
header.timecnt * sizeof(int64_t) + header.timecnt * sizeof(u_int8_t) +
header.typecnt * sizeof(TimeTypeRecord) +
header.charcnt * sizeof(int8_t) + header.isstdcnt * sizeof(u_int8_t) +
header.isutcnt * sizeof(u_int8_t);
if (v2_offset + data_block_length + sizeof(Header) > size) {
return nullptr;
}
std::unique_ptr<DataImpl> impl = std::make_unique<DataImpl>();
impl->header = header;
const auto copy =
[]<typename Type>(std::unique_ptr<Type[]> &array, int length,
const u_int8_t *const &ptr) -> const u_int8_t * {
const std::size_t region_length = length * sizeof(Type);
array = std::make_unique<Type[]>(length);
std::memcpy(array.get(), ptr, region_length);
return ptr + region_length;
};
p = copy(impl->transition_times, header.timecnt, p);
p = copy(impl->transition_types, header.timecnt, p);
p = copy(impl->local_time_type_records, header.typecnt, p);
p = copy(impl->time_zone_designations, header.charcnt, p);
p = copy(impl->standard_indicators, header.isstdcnt, p);
p = copy(impl->ut_indicators, header.isutcnt, p);
const std::size_t footer_string_length = data + size - p - 2;
p++;
if (p + footer_string_length > data + size ||
p + footer_string_length < data) {
return nullptr;
}
impl->footer.tz_string = std::make_unique<char[]>(footer_string_length);
std::memcpy(impl->footer.tz_string.get(), p, footer_string_length);
impl->footer.footer_string_length = footer_string_length;
return impl;
}
static void PushToBuffer(std::vector<u_int8_t> &buffer, const void *data,
std::size_t size) {
const u_int8_t *p{reinterpret_cast<const u_int8_t *>(data)};
for (std::size_t i = 0; i < size; i++) {
buffer.push_back(*p);
p++;
}
}
void DataImpl::ReformatNintendo(std::vector<u_int8_t> &buffer) const {
buffer.clear();
Header header_copy{header};
header_copy.isstdcnt = 0;
header_copy.isutcnt = 0;
FlipHeader(header_copy);
PushToBuffer(buffer, &header_copy, sizeof(Header));
PushToBuffer(buffer, transition_times.get(),
header.timecnt * sizeof(int64_t));
PushToBuffer(buffer, transition_types.get(),
header.timecnt * sizeof(u_int8_t));
PushToBuffer(buffer, local_time_type_records.get(),
header.typecnt * sizeof(TimeTypeRecord));
PushToBuffer(buffer, time_zone_designations.get(),
header.charcnt * sizeof(int8_t));
// omit standard_indicators
// omit ut_indicators
PushToBuffer(buffer, &footer.nl_a, 1);
PushToBuffer(buffer, footer.tz_string.get(), footer.footer_string_length);
PushToBuffer(buffer, &footer.nl_b, 1);
}
} // namespace Tzif

View File

@@ -0,0 +1,72 @@
#pragma once
#include <array>
#include <memory>
#include <sys/types.h>
#include <vector>
namespace Tzif {
typedef struct {
char magic[4];
u_int8_t version;
u_int8_t reserved[15];
u_int32_t isutcnt;
u_int32_t isstdcnt;
u_int32_t leapcnt;
u_int32_t timecnt;
u_int32_t typecnt;
u_int32_t charcnt;
} Header;
static_assert(sizeof(Header) == 0x2c);
class Footer {
public:
explicit Footer() = default;
~Footer() = default;
const char nl_a{'\n'};
std::unique_ptr<char[]> tz_string;
const char nl_b{'\n'};
std::size_t footer_string_length;
};
#pragma pack(push, 1)
typedef struct {
u_int32_t utoff;
u_int8_t dst;
u_int8_t idx;
} TimeTypeRecord;
#pragma pack(pop)
static_assert(sizeof(TimeTypeRecord) == 0x6);
class Data {
public:
explicit Data() = default;
virtual ~Data() = default;
virtual void ReformatNintendo(std::vector<u_int8_t> &buffer) const = 0;
};
class DataImpl : public Data {
public:
explicit DataImpl() = default;
~DataImpl() override = default;
void ReformatNintendo(std::vector<u_int8_t> &buffer) const override;
Header header;
Footer footer;
std::unique_ptr<int64_t[]> transition_times;
std::unique_ptr<u_int8_t[]> transition_types;
std::unique_ptr<TimeTypeRecord[]> local_time_type_records;
std::unique_ptr<int8_t[]> time_zone_designations;
std::unique_ptr<u_int8_t[]> standard_indicators;
std::unique_ptr<u_int8_t[]> ut_indicators;
};
std::unique_ptr<DataImpl> ReadData(const u_int8_t *data, std::size_t size);
} // namespace Tzif