Vendor dependencies

This commit is contained in:
2026-08-01 16:11:49 +03:00
parent 7f139a0241
commit 6b5e7f0f8b
29706 changed files with 9575646 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
{"$comment":"This file only protects against accidental modifications. It is not a security mechanism and does not protect against malicious changes.","files":{".cargo_vcs_info.json":"3f19b373a18619ac0965a65a7733a8740d576b3c0d3ec0f8bc3d2bebc0c61b2f","Cargo.lock":"5cc5cfd04853a719a8ca8a683da283f850a2479da2e900b9d5e91f736d447422","Cargo.toml":"27fea19d54e96f666a78cb5630a28bc3f9d716b544ea37c6a102d5c17cdcfe3b","Cargo.toml.orig":"7eeed1bc1f6bd33e281be640d91b915eb0c049ac40cc72fe2b5c3bda37f90b8b","LICENSE":"4789210f4df8abc03fce1cddd9c2ba517f184840687f2815d741de282c1aa93a","README.md":"d415695659bf264b6bb798dba9a812710c03310568ad163a6c84d65c73fc4a0c","build.rs":"a95f00ef475e4250661ae26ea1bc1a2562695c44aee8b9bd4a7e175df27c21e7","src/binary_search.rs":"438395fca5de4761060e35e77eb5646da0ddb7aa33180f0fb34a1085cc1a2358","src/lib.rs":"2e5545cdb37495538a2b45ce92719b1048787a2b917e25e431c386ad9c0bb75c","src/prebuilt/directory.rs":"bec2cf63fc0c40e9b11bc80fc8a56a1f69849b28e6196c1003c203cf2509673a","src/prebuilt/mod.rs":"0cb2d0e1b169b1290e91343d91e7aa8443146a65134f0118675e98740c4398aa","src/prebuilt/timezones.rs":"7d91787728ab990bf57334e3f9502d3ba0f744bd431608732f3fa48176b4ca72","src/serde.rs":"85258bdcd70dc662229925342189bf4a135c1daa29dec2b1b023ca446fdb4a13","src/timezone_impl.rs":"b92a42e46744c72388e67315ddca0098ee48673b74363fe45edd29554bb76183","tests/codegen.rs":"578989c82b9a05d6115580e3e6a4e4d9c26a0ff9559c45a93fe2536b946c9971","tests/numberphile.rs":"507494e403fe1356960eb174f1fedb8cff787db2b6b33b794022c3cce580fe16","tests/tzfile.rs":"63b81eee62ab0bf31a50558c4b248e364cde0aed40ea8f66535efa52d029c5e2","tz/LICENSE":"0613408568889f5739e5ae252b722a2659c02002839ad970a63dc5e9174b27cf","tz/NEWS":"800d5b6bddf7fff2b15b6165c9a3b863902f83ad6c294fa4f9b28a5d6a180951","tz/africa":"40e411950ede9d132c53377d1255d55eae78ddc1184f04f790ead09278b69d32","tz/antarctica":"c9b24697993845edccfadf806fe883c2a04c7c5189e597b2b50d01af8e8cba71","tz/asia":"9a8b7e640cb0692b9e50b9126f599bf89360a2f9ed9e54b722f3e5b6f631b419","tz/australasia":"d5cac9647eda54e639524689fdf8459a7da67e3d9a9acaecefd0c3507dd256fd","tz/backward":"d2f4c8953f204982ddf4dc0c2debf41b2464de376dad7d546d0fc70f889fa706","tz/etcetera":"e158fbdb05e3a0f2b5b6b6bce0cffd480305ec10d8b0769c959c30af6726d2b6","tz/europe":"a33695f21dff308ba3e900244a083450331d8aa215a641f612eb218e49b272d9","tz/northamerica":"382bc1672c47ca0c8e2cf303a34cb9da689c9bca0e0c3d7f5cde884c05cb49f4","tz/southamerica":"57cc4ee3dc4bd575f126ba76f284a9ee67330c6fbb7576792eda27f41451ff22"},"package":"a6139a8597ed92cf816dfb33f5dd6cf0bb93a6adc938f11039f371bc5bcd26c3"}
+6
View File
@@ -0,0 +1,6 @@
{
"git": {
"sha1": "e15d1f308a1ac2fdf3f1bf19c325dc202d418081"
},
"path_in_vcs": "chrono-tz"
}
+266
View File
@@ -0,0 +1,266 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "arbitrary"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110"
dependencies = [
"derive_arbitrary",
]
[[package]]
name = "autocfg"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "chrono"
version = "0.4.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
dependencies = [
"num-traits",
]
[[package]]
name = "chrono-tz"
version = "0.10.4"
dependencies = [
"arbitrary",
"chrono",
"chrono-tz-build",
"phf",
"serde",
"serde_test",
"tzfile",
"uncased",
]
[[package]]
name = "chrono-tz-build"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7d8d1efd5109b9c1cd3b7966bd071cdfb53bb6eb0b22a473a68c2f70a11a1eb"
dependencies = [
"parse-zoneinfo",
"phf_codegen",
"phf_shared",
"regex",
"uncased",
]
[[package]]
name = "derive_arbitrary"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "fastrand"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
[[package]]
name = "num-traits"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
dependencies = [
"autocfg",
]
[[package]]
name = "parse-zoneinfo"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3c406c9e2aa74554e662d2c2ee11cd3e73756988800be7e6f5eddb16fed4699"
[[package]]
name = "phf"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "913273894cec178f401a31ec4b656318d95473527be05c0752cc41cdc32be8b7"
dependencies = [
"phf_macros",
"phf_shared",
]
[[package]]
name = "phf_codegen"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efbdcb6f01d193b17f0b9c3360fa7e0e620991b193ff08702f78b3ce365d7e61"
dependencies = [
"phf_generator",
"phf_shared",
]
[[package]]
name = "phf_generator"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2cbb1126afed61dd6368748dae63b1ee7dc480191c6262a3b4ff1e29d86a6c5b"
dependencies = [
"fastrand",
"phf_shared",
]
[[package]]
name = "phf_macros"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d713258393a82f091ead52047ca779d37e5766226d009de21696c4e667044368"
dependencies = [
"phf_generator",
"phf_shared",
"proc-macro2",
"quote",
"syn",
"uncased",
]
[[package]]
name = "phf_shared"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06005508882fb681fd97892ecff4b7fd0fee13ef1aa569f8695dae7ab9099981"
dependencies = [
"siphasher",
"uncased",
]
[[package]]
name = "proc-macro2"
version = "1.0.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a56dea16b0a29e94408b9aa5e2940a4eedbd128a1ba20e8f7ae60fd3d465af0e"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
dependencies = [
"proc-macro2",
]
[[package]]
name = "regex"
version = "1.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c"
dependencies = [
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
dependencies = [
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
[[package]]
name = "serde"
version = "1.0.197"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.197"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_test"
version = "1.0.176"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a2f49ace1498612d14f7e0b8245519584db8299541dfe31a06374a828d620ab"
dependencies = [
"serde",
]
[[package]]
name = "siphasher"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
[[package]]
name = "syn"
version = "2.0.59"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a6531ffc7b071655e4ce2e04bd464c4830bb585a61cabb96cf808f05172615a"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "tzfile"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f59c22c42a2537e4c7ad21a4007273bbc5bebed7f36bc93730a5780e22a4592e"
dependencies = [
"byteorder",
"chrono",
]
[[package]]
name = "uncased"
version = "0.9.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1b88fcfe09e89d3866a5c11019378088af2d24c3fbd4f0543f96b479ec90697"
dependencies = [
"version_check",
]
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
+131
View File
@@ -0,0 +1,131 @@
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.
[package]
edition = "2021"
rust-version = "1.65"
name = "chrono-tz"
version = "0.10.4"
build = "build.rs"
include = [
"src/*.rs",
"src/prebuilt/*.rs",
"tests/*.rs",
"build.rs",
"LICENSE",
"tz/africa",
"tz/antarctica",
"tz/asia",
"tz/australasia",
"tz/backward",
"tz/etcetera",
"tz/europe",
"tz/northamerica",
"tz/southamerica",
"tz/NEWS",
]
autolib = false
autobins = false
autoexamples = false
autotests = false
autobenches = false
description = "TimeZone implementations for chrono from the IANA database"
documentation = "https://docs.rs/chrono-tz"
readme = "README.md"
keywords = [
"date",
"time",
"timezone",
"zone",
"iana",
]
categories = ["date-and-time"]
license = "MIT OR Apache-2.0"
repository = "https://github.com/chronotope/chrono-tz"
[package.metadata.docs.rs]
all-features = true
rustdoc-args = [
"--cfg",
"docsrs",
]
[features]
case-insensitive = [
"dep:uncased",
"chrono-tz-build",
"chrono-tz-build/case-insensitive",
"phf/uncased",
]
default = ["std"]
filter-by-regex = [
"chrono-tz-build",
"chrono-tz-build/filter-by-regex",
]
serde = ["dep:serde"]
std = []
[lib]
name = "chrono_tz"
path = "src/lib.rs"
[[test]]
name = "codegen"
path = "tests/codegen.rs"
[[test]]
name = "numberphile"
path = "tests/numberphile.rs"
[[test]]
name = "tzfile"
path = "tests/tzfile.rs"
[dependencies.arbitrary]
version = "1.2"
features = ["derive"]
optional = true
[dependencies.chrono]
version = "0.4.25"
default-features = false
[dependencies.phf]
version = "0.12"
default-features = false
[dependencies.serde]
version = "1.0.99"
optional = true
default-features = false
[dependencies.uncased]
version = "0.9"
optional = true
default-features = false
[dev-dependencies.chrono]
version = "0.4"
features = ["alloc"]
default-features = false
[dev-dependencies.chrono-tz-build]
version = "0.5"
[dev-dependencies.serde_test]
version = "1"
[dev-dependencies.tzfile]
version = "0.1"
[build-dependencies.chrono-tz-build]
version = "0.5"
optional = true
+57
View File
@@ -0,0 +1,57 @@
[package]
name = "chrono-tz"
version = "0.10.4"
edition = "2021"
rust-version = "1.65"
build = "build.rs"
description = "TimeZone implementations for chrono from the IANA database"
keywords = ["date", "time", "timezone", "zone", "iana"]
categories = ["date-and-time"]
repository = "https://github.com/chronotope/chrono-tz"
documentation = "https://docs.rs/chrono-tz"
readme = "../README.md"
license = "MIT OR Apache-2.0"
include = [
"src/*.rs",
"src/prebuilt/*.rs",
"tests/*.rs",
"build.rs",
"LICENSE",
"tz/africa",
"tz/antarctica",
"tz/asia",
"tz/australasia",
"tz/backward",
"tz/etcetera",
"tz/europe",
"tz/northamerica",
"tz/southamerica",
"tz/NEWS",
]
[dependencies]
arbitrary = { version = "1.2", optional = true, features = ["derive"] }
chrono = { version = "0.4.25", default-features = false }
serde = { version = "1.0.99", optional = true, default-features = false }
phf = { version = "0.12", default-features = false }
uncased = { version = "0.9", optional = true, default-features = false }
[features]
default = ["std"]
std = []
serde = ["dep:serde"]
filter-by-regex = ["chrono-tz-build", "chrono-tz-build/filter-by-regex"]
case-insensitive = ["dep:uncased", "chrono-tz-build", "chrono-tz-build/case-insensitive", "phf/uncased"]
[build-dependencies]
chrono-tz-build = { path = "../chrono-tz-build", version = "0.5", optional = true }
[dev-dependencies]
serde_test = "1"
chrono = { version = "0.4", default-features = false, features = ["alloc"] }
chrono-tz-build = { path = "../chrono-tz-build", version = "0.5" }
tzfile = "0.1"
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
+228
View File
@@ -0,0 +1,228 @@
Chrono-TZ is dual-licensed under the MIT License and Apache 2.0 Licence.
The licenses do not apply to files in the tzdb folder which are in the
public domain. parse-zoneinfo was forked from zoneinfo-parse, which
was originally created by Benjamin Sago under the MIT license.
Copyright (c) 2016-2024 Benjamin Sago & the chronotope maintainers
The MIT License
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.
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2016 Djzin
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
+190
View File
@@ -0,0 +1,190 @@
# Chrono-TZ
[![Chrono-TZ GitHub Actions][gh-image]][gh-checks]
[![Chrono-TZ on crates.io][cratesio-image]][cratesio]
[![Chrono-TZ on docs.rs][docsrs-image]][docsrs]
[![Chat][discord-image]][discord]
[gh-image]: https://github.com/chronotope/chrono-tz/actions/workflows/rust.yml/badge.svg
[gh-checks]: https://github.com/chronotope/chrono-tz/actions/workflows/rust.yml
[cratesio-image]: https://img.shields.io/crates/v/chrono-tz.svg
[cratesio]: https://crates.io/crates/chrono-tz
[docsrs-image]: https://docs.rs/chrono-tz/badge.svg
[docsrs]: https://docs.rs/chrono-tz
[discord-image]: https://img.shields.io/discord/976380008299917365?logo=discord
[discord]: https://discord.gg/sXpav4PS7M
`Chrono-TZ` is a library that provides implementors of the [`TimeZone`] trait for [chrono]. The
impls are generated by a build script using the [`IANA database`][iana] and [`parse-zoneinfo`].
[chrono]: https://crates.io/crates/chrono
[`TimeZone`]: https://docs.rs/chrono/latest/chrono/trait.TimeZone.html
[iana]: http://www.iana.org/time-zones
[`parse-zoneinfo`]: https://crates.io/crates/parse-zoneinfo
## Documentation
Documentation is hosted on [docs.rs][docsrs]
[docsrs]: https://docs.rs/chrono-tz
## Examples
Create a time in one timezone and convert it to UTC
```rust
use chrono::{TimeZone, Utc};
use chrono_tz::US::Pacific;
let pacific_time = Pacific.ymd(1990, 5, 6).and_hms(12, 30, 45);
let utc_time = pacific_time.with_timezone(&Utc);
assert_eq!(utc_time, Utc.ymd(1990, 5, 6).and_hms(19, 30, 45));
```
Create a naive datetime and convert it to a timezone-aware datetime
```rust
use chrono::{TimeZone, NaiveDate};
use chrono_tz::Africa::Johannesburg;
let naive_dt = NaiveDate::from_ymd(2038, 1, 19).and_hms(3, 14, 08);
let tz_aware = Johannesburg.from_local_datetime(&naive_dt).unwrap();
assert_eq!(tz_aware.to_string(), "2038-01-19 03:14:08 SAST");
```
London and New York change their clocks on different days in March
so only have a 4-hour difference on certain days.
```rust
use chrono::TimeZone;
use chrono_tz::Europe::London;
use chrono_tz::America::New_York;
let london_time = London.ymd(2016, 3, 18).and_hms(3, 0, 0);
let ny_time = london_time.with_timezone(&New_York);
assert_eq!(ny_time, New_York.ymd(2016, 3, 17).and_hms(23, 0, 0));
```
You can get the raw offsets as well if you want to see the standard
UTC offset as well as any special offsets in effect (such as DST)
at a given time. Note that you need to import the `OffsetComponents`
trait.
```rust
use chrono::{Duration, TimeZone};
use chrono_tz::Europe::London;
use chrono_tz::OffsetComponents;
let london_time = London.ymd(2016, 5, 10).and_hms(12, 0, 0);
// London typically has zero offset from UTC, but has a 1h adjustment forward
// when summer time is in effect.
assert_eq!(london_time.offset().base_utc_offset(), Duration::hours(0));
assert_eq!(london_time.offset().dst_offset(), Duration::hours(1));
```
Adding 24 hours across a daylight savings change causes a change
in local time
```rust
use chrono::{TimeZone, Duration};
use chrono_tz::Europe::London;
let dt = London.ymd(2016, 10, 29).and_hms(12, 0, 0);
let later = dt + Duration::hours(24);
assert_eq!(later, London.ymd(2016, 10, 30).and_hms(11, 0, 0));
```
And of course you can always convert a local time to a unix timestamp
```rust
use chrono::TimeZone;
use chrono_tz::Asia::Kolkata;
let dt = Kolkata.ymd(2000, 1, 1).and_hms(0, 0, 0);
let timestamp = dt.timestamp();
assert_eq!(timestamp, 946665000);
```
Pretty-printing a string will use the correct abbreviation for the timezone
```rust
use chrono::TimeZone;
use chrono_tz::Europe::London;
let dt = London.ymd(2016, 5, 10).and_hms(12, 0, 0);
assert_eq!(dt.to_string(), "2016-05-10 12:00:00 BST");
assert_eq!(dt.to_rfc3339(), "2016-05-10T12:00:00+01:00");
```
You can convert a timezone string to a timezone using the FromStr trait
```rust
use chrono::TimeZone;
use chrono_tz::Tz;
use chrono_tz::UTC;
let tz: Tz = "Antarctica/South_Pole".parse().unwrap();
let dt = tz.ymd(2016, 10, 22).and_hms(12, 0, 0);
let utc = dt.with_timezone(&UTC);
assert_eq!(utc.to_string(), "2016-10-21 23:00:00 UTC");
```
## `no_std` Support
To use this library without depending on the Rust standard library, put this
in your `Cargo.toml`:
```toml
[dependencies]
chrono = { version = "0.4", default-features = false }
chrono-tz = { version = "0.5", default-features = false }
```
If you are using this library in an environment with limited program
space, such as a microcontroller, take note that you will also likely
need to enable optimizations and Link Time Optimization:
```toml
[profile.dev]
opt-level = 2
lto = true
[profile.release]
lto = true
```
Otherwise, the additional binary size added by this library may overflow
available program space and trigger a linker error.
## Limiting the Timezone Table to Zones of Interest
`Chrono-tz` by default generates timezones for all entries in the [IANA database][]. If you are
interested in only a few timezones you can use enable the `filter-by-regex` feature and set an
environment variable to select them. The environment variable is called
`CHRONO_TZ_TIMEZONE_FILTER` and is a regular expression. It should be specified in your top-level
build:
```sh
CHRONO_TZ_TIMEZONE_FILTER="(Europe/London|US/.*)" cargo build
```
This can significantly reduce the size of the generated database, depending on how many timezones
you are interested in. Wikipedia has an [article listing the timezone names][wiki-list].
The filtering applied is liberal; if you use a pattern such as "US/.*" then `chrono-tz` will
include all the zones that are linked, such as "America/Denver", not just "US/Mountain".
[IANA database]: http://www.iana.org/time-zones
[wiki-list]: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
## Developing
`chrono-tz` uses git submodules, so in order to build locally you will need to
run `git submodule init` and `git submodule update`.
## Future Improvements
- Handle leap seconds
- Handle Julian to Gregorian calendar transitions
- Load tzdata always from latest version
- Dynamic tzdata loading
+16
View File
@@ -0,0 +1,16 @@
#[cfg(any(feature = "filter-by-regex", feature = "case-insensitive"))]
use std::{env, path::Path};
#[cfg(feature = "filter-by-regex")]
use chrono_tz_build::FILTER_ENV_VAR_NAME;
fn main() {
#[cfg(feature = "filter-by-regex")]
println!("cargo:rerun-if-env-changed={FILTER_ENV_VAR_NAME}");
#[cfg(any(feature = "filter-by-regex", feature = "case-insensitive"))]
chrono_tz_build::main(
Path::new(&env::var("OUT_DIR").unwrap()),
cfg!(feature = "filter-by-regex"),
cfg!(feature = "case-insensitive"),
);
}
+37
View File
@@ -0,0 +1,37 @@
use core::cmp::Ordering;
/// An implementation of binary search on indices only
/// that does not require slices to be constructed. Mirrors
/// the semantics of binary_search_by in the standard library.
pub fn binary_search<F>(mut start: usize, mut end: usize, mut f: F) -> Result<usize, usize>
where
F: FnMut(usize) -> Ordering,
{
loop {
let mid = start + (end - start) / 2;
if mid == end {
return Err(start);
}
match f(mid) {
Ordering::Less => start = mid + 1,
Ordering::Greater => end = mid,
Ordering::Equal => return Ok(mid),
}
}
}
#[test]
fn test_binary_search() {
assert_eq!(binary_search(0, 5000, |x| x.cmp(&1337)), Ok(1337));
assert_eq!(binary_search(0, 5000, |x| x.cmp(&9000)), Err(5000));
assert_eq!(binary_search(30, 50, |x| x.cmp(&42)), Ok(42));
assert_eq!(binary_search(300, 500, |x| x.cmp(&42)), Err(300));
assert_eq!(
binary_search(0, 500, |x| if x < 42 {
Ordering::Less
} else {
Ordering::Greater
}),
Err(42)
);
}
+653
View File
@@ -0,0 +1,653 @@
//! # Chrono-TZ
//!
//! `Chrono-TZ` is a library that provides implementors of the
//! [`TimeZone`][timezone] trait for [`chrono`][chrono]. The
//! impls are generated by a build script using the [`IANA database`][iana]
//! and [`zoneinfo_parse`][zoneinfo_parse].
//!
//! [chrono]: https://github.com/lifthrasiir/rust-chrono
//! [timezone]: https://lifthrasiir.github.io/rust-chrono/chrono/offset/trait.TimeZone.html
//! [iana]: http://www.iana.org/time-zones
//! [zoneinfo_parse]: https://github.com/rust-datetime/zoneinfo-parse
//!
//! ## Examples
//!
//! Create a time in one timezone and convert it to UTC
//!
//! ```
//! # extern crate chrono;
//! # extern crate chrono_tz;
//! use chrono::{TimeZone, Utc};
//! use chrono_tz::US::Pacific;
//!
//! # fn main() {
//! let pacific_time = Pacific.ymd(1990, 5, 6).and_hms(12, 30, 45);
//! let utc_time = pacific_time.with_timezone(&Utc);
//! assert_eq!(utc_time, Utc.ymd(1990, 5, 6).and_hms(19, 30, 45));
//! # }
//! ```
//!
//! Create a naive datetime and convert it to a timezone-aware datetime
//!
//! ```
//! # extern crate chrono;
//! # extern crate chrono_tz;
//! use chrono::{TimeZone, NaiveDate};
//! use chrono_tz::Africa::Johannesburg;
//!
//! # fn main() {
//! let naive_dt = NaiveDate::from_ymd(2038, 1, 19).and_hms(3, 14, 08);
//! let tz_aware = Johannesburg.from_local_datetime(&naive_dt).unwrap();
//! assert_eq!(tz_aware.to_string(), "2038-01-19 03:14:08 SAST");
//! # }
//! ```
//!
//! London and New York change their clocks on different days in March
//! so only have a 4-hour difference on certain days.
//!
//! ```
//! # extern crate chrono;
//! # extern crate chrono_tz;
//! use chrono::TimeZone;
//! use chrono_tz::Europe::London;
//! use chrono_tz::America::New_York;
//!
//! # fn main() {
//! let london_time = London.ymd(2016, 3, 18).and_hms(3, 0, 0);
//! let ny_time = london_time.with_timezone(&New_York);
//! assert_eq!(ny_time, New_York.ymd(2016, 3, 17).and_hms(23, 0, 0));
//! # }
//! ```
//!
//! Adding 24 hours across a daylight savings change causes a change
//! in local time
//!
//! ```
//! # extern crate chrono;
//! # extern crate chrono_tz;
//! use chrono::{TimeZone, Duration};
//! use chrono_tz::Europe::London;
//!
//! # fn main() {
//! let dt = London.ymd(2016, 10, 29).and_hms(12, 0, 0);
//! let later = dt + Duration::hours(24);
//! assert_eq!(later, London.ymd(2016, 10, 30).and_hms(11, 0, 0));
//! # }
//! ```
//!
//! And of course you can always convert a local time to a unix timestamp
//!
//! ```
//! # extern crate chrono;
//! # extern crate chrono_tz;
//! use chrono::TimeZone;
//! use chrono_tz::Asia::Kolkata;
//!
//! # fn main() {
//! let dt = Kolkata.ymd(2000, 1, 1).and_hms(0, 0, 0);
//! let timestamp = dt.timestamp();
//! assert_eq!(timestamp, 946665000);
//! # }
//! ```
//!
//! Pretty-printing a string will use the correct abbreviation for the timezone
//!
//! ```
//! # extern crate chrono;
//! # extern crate chrono_tz;
//! use chrono::TimeZone;
//! use chrono_tz::Europe::London;
//!
//! # fn main() {
//! let dt = London.ymd(2016, 5, 10).and_hms(12, 0, 0);
//! assert_eq!(dt.to_string(), "2016-05-10 12:00:00 BST");
//! assert_eq!(dt.to_rfc3339(), "2016-05-10T12:00:00+01:00");
//! # }
//! ```
//!
//! You can convert a timezone string to a timezone using the `FromStr` trait
//!
//! ```
//! # extern crate chrono;
//! # extern crate chrono_tz;
//! use chrono::TimeZone;
//! use chrono_tz::Tz;
//! use chrono_tz::UTC;
//!
//! # fn main() {
//! let tz: Tz = "Antarctica/South_Pole".parse().unwrap();
//! let dt = tz.ymd(2016, 10, 22).and_hms(12, 0, 0);
//! let utc = dt.with_timezone(&UTC);
//! assert_eq!(utc.to_string(), "2016-10-21 23:00:00 UTC");
//! # }
//! ```
//!
//! If you need to iterate over all variants you can use the `TZ_VARIANTS` array
//! ```
//! use chrono_tz::{TZ_VARIANTS, Tz};
//! assert!(TZ_VARIANTS.iter().any(|v| *v == Tz::UTC));
//! ```
#![cfg_attr(not(any(feature = "std", test)), no_std)]
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
#[cfg(feature = "serde")]
mod serde;
mod binary_search;
#[cfg(not(any(feature = "case-insensitive", feature = "filter-by-regex")))]
use prebuilt::directory;
mod prebuilt;
#[cfg(any(feature = "case-insensitive", feature = "filter-by-regex"))]
mod directory {
#![allow(
dead_code,
non_camel_case_types,
non_snake_case,
non_upper_case_globals
)]
include!(concat!(env!("OUT_DIR"), "/directory.rs"));
}
mod timezone_impl;
#[cfg(not(any(feature = "case-insensitive", feature = "filter-by-regex")))]
use prebuilt::timezones;
#[cfg(any(feature = "case-insensitive", feature = "filter-by-regex"))]
mod timezones {
#![allow(non_camel_case_types, clippy::unreadable_literal)]
include!(concat!(env!("OUT_DIR"), "/timezones.rs"));
}
pub use crate::timezone_impl::{GapInfo, OffsetComponents, OffsetName, TzOffset};
pub use directory::*;
pub use timezones::ParseError;
pub use timezones::Tz;
pub use timezones::TZ_VARIANTS;
pub use IANA_TZDB_VERSION;
#[cfg(test)]
mod tests {
use super::Africa::Addis_Ababa;
use super::America::Danmarkshavn;
use super::America::Scoresbysund;
use super::Antarctica::Casey;
use super::Asia::Dhaka;
use super::Australia::Adelaide;
use super::Europe::Berlin;
use super::Europe::London;
use super::Europe::Moscow;
use super::Europe::Vilnius;
use super::Europe::Warsaw;
use super::GapInfo;
use super::Pacific::Apia;
use super::Pacific::Noumea;
use super::Pacific::Tahiti;
use super::Tz;
use super::IANA_TZDB_VERSION;
use super::US::Eastern;
use super::UTC;
use chrono::NaiveDateTime;
use chrono::{Duration, NaiveDate, TimeZone};
#[test]
fn london_to_berlin() {
let dt = London.with_ymd_and_hms(2016, 10, 8, 17, 0, 0).unwrap();
let converted = dt.with_timezone(&Berlin);
let expected = Berlin.with_ymd_and_hms(2016, 10, 8, 18, 0, 0).unwrap();
assert_eq!(converted, expected);
}
#[test]
fn us_eastern_dst_commutativity() {
let dt = UTC.with_ymd_and_hms(2002, 4, 7, 7, 0, 0).unwrap();
for days in -420..720 {
let dt1 = (dt + Duration::days(days)).with_timezone(&Eastern);
let dt2 = dt.with_timezone(&Eastern) + Duration::days(days);
assert_eq!(dt1, dt2);
}
}
#[test]
fn test_addition_across_dst_boundary() {
use chrono::TimeZone;
let two_hours = Duration::hours(2);
let edt = Eastern.with_ymd_and_hms(2019, 11, 3, 0, 0, 0).unwrap();
let est = edt + two_hours;
assert_eq!(edt.to_string(), "2019-11-03 00:00:00 EDT".to_string());
assert_eq!(est.to_string(), "2019-11-03 01:00:00 EST".to_string());
assert_eq!(est.timestamp(), edt.timestamp() + two_hours.num_seconds());
}
#[test]
fn warsaw_tz_name() {
let dt = UTC.with_ymd_and_hms(1915, 8, 4, 22, 35, 59).unwrap();
assert_eq!(dt.with_timezone(&Warsaw).format("%Z").to_string(), "WMT");
let dt = dt + Duration::seconds(1);
assert_eq!(dt.with_timezone(&Warsaw).format("%Z").to_string(), "CET");
}
#[test]
fn vilnius_utc_offset() {
let dt = UTC
.with_ymd_and_hms(1916, 12, 31, 22, 35, 59)
.unwrap()
.with_timezone(&Vilnius);
assert_eq!(
dt,
Vilnius.with_ymd_and_hms(1916, 12, 31, 23, 59, 59).unwrap()
);
let dt = dt + Duration::seconds(1);
assert_eq!(dt, Vilnius.with_ymd_and_hms(1917, 1, 1, 0, 11, 36).unwrap());
}
#[test]
fn victorian_times() {
let dt = UTC
.with_ymd_and_hms(1847, 12, 1, 0, 1, 14)
.unwrap()
.with_timezone(&London);
assert_eq!(
dt,
London.with_ymd_and_hms(1847, 11, 30, 23, 59, 59).unwrap()
);
let dt = dt + Duration::seconds(1);
assert_eq!(dt, London.with_ymd_and_hms(1847, 12, 1, 0, 1, 15).unwrap());
}
#[test]
fn london_dst() {
let dt = London.with_ymd_and_hms(2016, 3, 10, 5, 0, 0).unwrap();
let later = dt + Duration::days(180);
let expected = London.with_ymd_and_hms(2016, 9, 6, 6, 0, 0).unwrap();
assert_eq!(later, expected);
}
#[test]
fn international_date_line_change() {
let dt = UTC
.with_ymd_and_hms(2011, 12, 30, 9, 59, 59)
.unwrap()
.with_timezone(&Apia);
assert_eq!(dt, Apia.with_ymd_and_hms(2011, 12, 29, 23, 59, 59).unwrap());
let dt = dt + Duration::seconds(1);
assert_eq!(dt, Apia.with_ymd_and_hms(2011, 12, 31, 0, 0, 0).unwrap());
}
#[test]
fn negative_offset_with_minutes_and_seconds() {
let dt = UTC
.with_ymd_and_hms(1900, 1, 1, 12, 0, 0)
.unwrap()
.with_timezone(&Danmarkshavn);
assert_eq!(
dt,
Danmarkshavn
.with_ymd_and_hms(1900, 1, 1, 10, 45, 20)
.unwrap()
);
}
#[test]
fn monotonicity() {
let mut dt = Noumea.with_ymd_and_hms(1800, 1, 1, 12, 0, 0).unwrap();
for _ in 0..24 * 356 * 400 {
let new = dt + Duration::hours(1);
assert!(new > dt);
assert!(new.with_timezone(&UTC) > dt.with_timezone(&UTC));
dt = new;
}
}
fn test_inverse<T: TimeZone>(tz: T, begin: i32, end: i32) {
for y in begin..end {
for d in 1..366 {
let date = NaiveDate::from_yo_opt(y, d).unwrap();
for h in 0..24 {
for m in 0..60 {
let dt = date.and_hms_opt(h, m, 0).unwrap().and_utc();
let with_tz = dt.with_timezone(&tz);
let utc = with_tz.with_timezone(&UTC);
assert_eq!(dt, utc);
}
}
}
}
}
#[test]
fn inverse_london() {
test_inverse(London, 1989, 1994);
}
#[test]
fn inverse_dhaka() {
test_inverse(Dhaka, 1995, 2000);
}
#[test]
fn inverse_apia() {
test_inverse(Apia, 2011, 2012);
}
#[test]
fn inverse_tahiti() {
test_inverse(Tahiti, 1911, 1914);
}
#[test]
fn string_representation() {
let dt = UTC
.with_ymd_and_hms(2000, 9, 1, 12, 30, 15)
.unwrap()
.with_timezone(&Adelaide);
assert_eq!(dt.to_string(), "2000-09-01 22:00:15 ACST");
assert_eq!(format!("{dt:?}"), "2000-09-01T22:00:15ACST");
assert_eq!(dt.to_rfc3339(), "2000-09-01T22:00:15+09:30");
assert_eq!(format!("{dt}"), "2000-09-01 22:00:15 ACST");
}
#[test]
fn tahiti() {
let dt = UTC
.with_ymd_and_hms(1912, 10, 1, 9, 58, 16)
.unwrap()
.with_timezone(&Tahiti);
let before = dt - Duration::hours(1);
assert_eq!(
before,
Tahiti.with_ymd_and_hms(1912, 9, 30, 23, 0, 0).unwrap()
);
let after = dt + Duration::hours(1);
assert_eq!(
after,
Tahiti.with_ymd_and_hms(1912, 10, 1, 0, 58, 16).unwrap()
);
}
#[test]
fn nonexistent_time() {
assert!(London
.with_ymd_and_hms(2016, 3, 27, 1, 30, 0)
.single()
.is_none());
}
#[test]
fn nonexistent_time_2() {
assert!(London
.with_ymd_and_hms(2016, 3, 27, 1, 0, 0)
.single()
.is_none());
}
#[test]
fn time_exists() {
assert!(London
.with_ymd_and_hms(2016, 3, 27, 2, 0, 0)
.single()
.is_some());
}
#[test]
fn ambiguous_time() {
let ambiguous = London.with_ymd_and_hms(2016, 10, 30, 1, 0, 0);
let earliest_utc = NaiveDate::from_ymd_opt(2016, 10, 30)
.unwrap()
.and_hms_opt(0, 0, 0)
.unwrap();
assert_eq!(
ambiguous.earliest().unwrap(),
London.from_utc_datetime(&earliest_utc)
);
let latest_utc = NaiveDate::from_ymd_opt(2016, 10, 30)
.unwrap()
.and_hms_opt(1, 0, 0)
.unwrap();
assert_eq!(
ambiguous.latest().unwrap(),
London.from_utc_datetime(&latest_utc)
);
}
#[test]
fn ambiguous_time_2() {
let ambiguous = London.with_ymd_and_hms(2016, 10, 30, 1, 30, 0);
let earliest_utc = NaiveDate::from_ymd_opt(2016, 10, 30)
.unwrap()
.and_hms_opt(0, 30, 0)
.unwrap();
assert_eq!(
ambiguous.earliest().unwrap(),
London.from_utc_datetime(&earliest_utc)
);
let latest_utc = NaiveDate::from_ymd_opt(2016, 10, 30)
.unwrap()
.and_hms_opt(1, 30, 0)
.unwrap();
assert_eq!(
ambiguous.latest().unwrap(),
London.from_utc_datetime(&latest_utc)
);
}
#[test]
fn ambiguous_time_3() {
let ambiguous = Moscow.with_ymd_and_hms(2014, 10, 26, 1, 30, 0);
let earliest_utc = NaiveDate::from_ymd_opt(2014, 10, 25)
.unwrap()
.and_hms_opt(21, 30, 0)
.unwrap();
assert_eq!(
ambiguous.earliest().unwrap().fixed_offset(),
Moscow.from_utc_datetime(&earliest_utc).fixed_offset()
);
let latest_utc = NaiveDate::from_ymd_opt(2014, 10, 25)
.unwrap()
.and_hms_opt(22, 30, 0)
.unwrap();
assert_eq!(
ambiguous.latest().unwrap(),
Moscow.from_utc_datetime(&latest_utc)
);
}
#[test]
fn ambiguous_time_4() {
let ambiguous = Moscow.with_ymd_and_hms(2014, 10, 26, 1, 0, 0);
let earliest_utc = NaiveDate::from_ymd_opt(2014, 10, 25)
.unwrap()
.and_hms_opt(21, 0, 0)
.unwrap();
assert_eq!(
ambiguous.earliest().unwrap().fixed_offset(),
Moscow.from_utc_datetime(&earliest_utc).fixed_offset()
);
let latest_utc = NaiveDate::from_ymd_opt(2014, 10, 25)
.unwrap()
.and_hms_opt(22, 0, 0)
.unwrap();
assert_eq!(
ambiguous.latest().unwrap(),
Moscow.from_utc_datetime(&latest_utc)
);
}
#[test]
fn unambiguous_time() {
assert!(London
.with_ymd_and_hms(2016, 10, 30, 2, 0, 0)
.single()
.is_some());
}
#[test]
fn unambiguous_time_2() {
assert!(Moscow
.with_ymd_and_hms(2014, 10, 26, 2, 0, 0)
.single()
.is_some());
}
#[test]
fn test_get_name() {
assert_eq!(London.name(), "Europe/London");
assert_eq!(Tz::Africa__Abidjan.name(), "Africa/Abidjan");
assert_eq!(Tz::UTC.name(), "UTC");
assert_eq!(Tz::Zulu.name(), "Zulu");
}
#[test]
fn test_display() {
assert_eq!(format!("{London}"), "Europe/London");
assert_eq!(format!("{}", Tz::Africa__Abidjan), "Africa/Abidjan");
assert_eq!(format!("{}", Tz::UTC), "UTC");
assert_eq!(format!("{}", Tz::Zulu), "Zulu");
}
#[test]
fn test_impl_hash() {
#[allow(dead_code)]
#[derive(Hash)]
struct Foo(Tz);
}
#[test]
fn test_iana_tzdb_version() {
// Format should be something like 2023c.
assert_eq!(5, IANA_TZDB_VERSION.len());
let numbers: Vec<&str> = IANA_TZDB_VERSION.matches(char::is_numeric).collect();
assert_eq!(4, numbers.len());
assert!(IANA_TZDB_VERSION.ends_with(|c: char| c.is_ascii_lowercase()));
}
#[test]
fn test_numeric_names() {
let dt = Scoresbysund.with_ymd_and_hms(2024, 5, 1, 0, 0, 0).unwrap();
assert_eq!(format!("{}", dt.offset()), "-01");
assert_eq!(format!("{:?}", dt.offset()), "-01");
let dt = Casey.with_ymd_and_hms(2022, 11, 1, 0, 0, 0).unwrap();
assert_eq!(format!("{}", dt.offset()), "+11");
assert_eq!(format!("{:?}", dt.offset()), "+11");
let dt = Addis_Ababa.with_ymd_and_hms(1937, 2, 1, 0, 0, 0).unwrap();
assert_eq!(format!("{}", dt.offset()), "+0245");
assert_eq!(format!("{:?}", dt.offset()), "+0245");
}
fn gap_info_test(tz: Tz, gap_begin: NaiveDateTime, gap_end: NaiveDateTime) {
let before = gap_begin - Duration::seconds(1);
let before_offset = tz.offset_from_local_datetime(&before).single().unwrap();
let gap_end = tz.from_local_datetime(&gap_end).single().unwrap();
let in_gap = gap_begin + Duration::seconds(1);
let GapInfo { begin, end } = GapInfo::new(&in_gap, &tz).unwrap();
let (begin_time, begin_offset) = begin.unwrap();
let end = end.unwrap();
assert_eq!(gap_begin, begin_time);
assert_eq!(before_offset, begin_offset);
assert_eq!(gap_end, end);
}
#[test]
fn gap_info_europe_london() {
gap_info_test(
Tz::Europe__London,
NaiveDate::from_ymd_opt(2024, 3, 31)
.unwrap()
.and_hms_opt(1, 0, 0)
.unwrap(),
NaiveDate::from_ymd_opt(2024, 3, 31)
.unwrap()
.and_hms_opt(2, 0, 0)
.unwrap(),
);
}
#[test]
fn gap_info_europe_dublin() {
gap_info_test(
Tz::Europe__Dublin,
NaiveDate::from_ymd_opt(2024, 3, 31)
.unwrap()
.and_hms_opt(1, 0, 0)
.unwrap(),
NaiveDate::from_ymd_opt(2024, 3, 31)
.unwrap()
.and_hms_opt(2, 0, 0)
.unwrap(),
);
}
#[test]
fn gap_info_australia_adelaide() {
gap_info_test(
Tz::Australia__Adelaide,
NaiveDate::from_ymd_opt(2024, 10, 6)
.unwrap()
.and_hms_opt(2, 0, 0)
.unwrap(),
NaiveDate::from_ymd_opt(2024, 10, 6)
.unwrap()
.and_hms_opt(3, 0, 0)
.unwrap(),
);
}
#[test]
fn gap_info_samoa_skips_a_day() {
gap_info_test(
Tz::Pacific__Apia,
NaiveDate::from_ymd_opt(2011, 12, 30)
.unwrap()
.and_hms_opt(0, 0, 0)
.unwrap(),
NaiveDate::from_ymd_opt(2011, 12, 31)
.unwrap()
.and_hms_opt(0, 0, 0)
.unwrap(),
);
}
#[test]
fn gap_info_libya_2013() {
gap_info_test(
Tz::Libya,
NaiveDate::from_ymd_opt(2013, 3, 29)
.unwrap()
.and_hms_opt(1, 0, 0)
.unwrap(),
NaiveDate::from_ymd_opt(2013, 3, 29)
.unwrap()
.and_hms_opt(2, 0, 0)
.unwrap(),
);
}
#[test]
fn casey_utc_change_time() {
assert_eq!(
NaiveDate::from_ymd_opt(2012, 2, 21)
.unwrap()
.and_hms_opt(16, 59, 59)
.unwrap()
.and_utc()
.with_timezone(&Casey)
.offset()
.to_string(),
"+11"
);
assert_eq!(
NaiveDate::from_ymd_opt(2012, 2, 21)
.unwrap()
.and_hms_opt(17, 00, 00)
.unwrap()
.and_utc()
.with_timezone(&Casey)
.offset()
.to_string(),
"+08"
);
}
}
+701
View File
@@ -0,0 +1,701 @@
pub const IANA_TZDB_VERSION: &str = "2025b";
use crate::timezones::Tz;
pub const CET: Tz = Tz::CET;
pub const CST6CDT: Tz = Tz::CST6CDT;
pub const Cuba: Tz = Tz::Cuba;
pub const EET: Tz = Tz::EET;
pub const EST: Tz = Tz::EST;
pub const EST5EDT: Tz = Tz::EST5EDT;
pub const Egypt: Tz = Tz::Egypt;
pub const Eire: Tz = Tz::Eire;
pub const GB: Tz = Tz::GB;
pub const GBEire: Tz = Tz::GBEire;
pub const GMT: Tz = Tz::GMT;
pub const GMTPlus0: Tz = Tz::GMTPlus0;
pub const GMTMinus0: Tz = Tz::GMTMinus0;
pub const GMT0: Tz = Tz::GMT0;
pub const Greenwich: Tz = Tz::Greenwich;
pub const HST: Tz = Tz::HST;
pub const Hongkong: Tz = Tz::Hongkong;
pub const Iceland: Tz = Tz::Iceland;
pub const Iran: Tz = Tz::Iran;
pub const Israel: Tz = Tz::Israel;
pub const Jamaica: Tz = Tz::Jamaica;
pub const Japan: Tz = Tz::Japan;
pub const Kwajalein: Tz = Tz::Kwajalein;
pub const Libya: Tz = Tz::Libya;
pub const MET: Tz = Tz::MET;
pub const MST: Tz = Tz::MST;
pub const MST7MDT: Tz = Tz::MST7MDT;
pub const NZ: Tz = Tz::NZ;
pub const NZCHAT: Tz = Tz::NZCHAT;
pub const Navajo: Tz = Tz::Navajo;
pub const PRC: Tz = Tz::PRC;
pub const PST8PDT: Tz = Tz::PST8PDT;
pub const Poland: Tz = Tz::Poland;
pub const Portugal: Tz = Tz::Portugal;
pub const ROC: Tz = Tz::ROC;
pub const ROK: Tz = Tz::ROK;
pub const Singapore: Tz = Tz::Singapore;
pub const Turkey: Tz = Tz::Turkey;
pub const UCT: Tz = Tz::UCT;
pub const UTC: Tz = Tz::UTC;
pub const Universal: Tz = Tz::Universal;
pub const WSU: Tz = Tz::WSU;
pub const WET: Tz = Tz::WET;
pub const Zulu: Tz = Tz::Zulu;
pub mod Africa {
use crate::timezones::Tz;
pub const Abidjan: Tz = Tz::Africa__Abidjan;
pub const Accra: Tz = Tz::Africa__Accra;
pub const Addis_Ababa: Tz = Tz::Africa__Addis_Ababa;
pub const Algiers: Tz = Tz::Africa__Algiers;
pub const Asmara: Tz = Tz::Africa__Asmara;
pub const Asmera: Tz = Tz::Africa__Asmera;
pub const Bamako: Tz = Tz::Africa__Bamako;
pub const Bangui: Tz = Tz::Africa__Bangui;
pub const Banjul: Tz = Tz::Africa__Banjul;
pub const Bissau: Tz = Tz::Africa__Bissau;
pub const Blantyre: Tz = Tz::Africa__Blantyre;
pub const Brazzaville: Tz = Tz::Africa__Brazzaville;
pub const Bujumbura: Tz = Tz::Africa__Bujumbura;
pub const Cairo: Tz = Tz::Africa__Cairo;
pub const Casablanca: Tz = Tz::Africa__Casablanca;
pub const Ceuta: Tz = Tz::Africa__Ceuta;
pub const Conakry: Tz = Tz::Africa__Conakry;
pub const Dakar: Tz = Tz::Africa__Dakar;
pub const Dar_es_Salaam: Tz = Tz::Africa__Dar_es_Salaam;
pub const Djibouti: Tz = Tz::Africa__Djibouti;
pub const Douala: Tz = Tz::Africa__Douala;
pub const El_Aaiun: Tz = Tz::Africa__El_Aaiun;
pub const Freetown: Tz = Tz::Africa__Freetown;
pub const Gaborone: Tz = Tz::Africa__Gaborone;
pub const Harare: Tz = Tz::Africa__Harare;
pub const Johannesburg: Tz = Tz::Africa__Johannesburg;
pub const Juba: Tz = Tz::Africa__Juba;
pub const Kampala: Tz = Tz::Africa__Kampala;
pub const Khartoum: Tz = Tz::Africa__Khartoum;
pub const Kigali: Tz = Tz::Africa__Kigali;
pub const Kinshasa: Tz = Tz::Africa__Kinshasa;
pub const Lagos: Tz = Tz::Africa__Lagos;
pub const Libreville: Tz = Tz::Africa__Libreville;
pub const Lome: Tz = Tz::Africa__Lome;
pub const Luanda: Tz = Tz::Africa__Luanda;
pub const Lubumbashi: Tz = Tz::Africa__Lubumbashi;
pub const Lusaka: Tz = Tz::Africa__Lusaka;
pub const Malabo: Tz = Tz::Africa__Malabo;
pub const Maputo: Tz = Tz::Africa__Maputo;
pub const Maseru: Tz = Tz::Africa__Maseru;
pub const Mbabane: Tz = Tz::Africa__Mbabane;
pub const Mogadishu: Tz = Tz::Africa__Mogadishu;
pub const Monrovia: Tz = Tz::Africa__Monrovia;
pub const Nairobi: Tz = Tz::Africa__Nairobi;
pub const Ndjamena: Tz = Tz::Africa__Ndjamena;
pub const Niamey: Tz = Tz::Africa__Niamey;
pub const Nouakchott: Tz = Tz::Africa__Nouakchott;
pub const Ouagadougou: Tz = Tz::Africa__Ouagadougou;
pub const PortoNovo: Tz = Tz::Africa__PortoNovo;
pub const Sao_Tome: Tz = Tz::Africa__Sao_Tome;
pub const Timbuktu: Tz = Tz::Africa__Timbuktu;
pub const Tripoli: Tz = Tz::Africa__Tripoli;
pub const Tunis: Tz = Tz::Africa__Tunis;
pub const Windhoek: Tz = Tz::Africa__Windhoek;
}
pub mod America {
use crate::timezones::Tz;
pub mod Argentina {
use crate::timezones::Tz;
pub const Buenos_Aires: Tz = Tz::America__Argentina__Buenos_Aires;
pub const Catamarca: Tz = Tz::America__Argentina__Catamarca;
pub const ComodRivadavia: Tz = Tz::America__Argentina__ComodRivadavia;
pub const Cordoba: Tz = Tz::America__Argentina__Cordoba;
pub const Jujuy: Tz = Tz::America__Argentina__Jujuy;
pub const La_Rioja: Tz = Tz::America__Argentina__La_Rioja;
pub const Mendoza: Tz = Tz::America__Argentina__Mendoza;
pub const Rio_Gallegos: Tz = Tz::America__Argentina__Rio_Gallegos;
pub const Salta: Tz = Tz::America__Argentina__Salta;
pub const San_Juan: Tz = Tz::America__Argentina__San_Juan;
pub const San_Luis: Tz = Tz::America__Argentina__San_Luis;
pub const Tucuman: Tz = Tz::America__Argentina__Tucuman;
pub const Ushuaia: Tz = Tz::America__Argentina__Ushuaia;
}
pub mod Indiana {
use crate::timezones::Tz;
pub const Indianapolis: Tz = Tz::America__Indiana__Indianapolis;
pub const Knox: Tz = Tz::America__Indiana__Knox;
pub const Marengo: Tz = Tz::America__Indiana__Marengo;
pub const Petersburg: Tz = Tz::America__Indiana__Petersburg;
pub const Tell_City: Tz = Tz::America__Indiana__Tell_City;
pub const Vevay: Tz = Tz::America__Indiana__Vevay;
pub const Vincennes: Tz = Tz::America__Indiana__Vincennes;
pub const Winamac: Tz = Tz::America__Indiana__Winamac;
}
pub mod Kentucky {
use crate::timezones::Tz;
pub const Louisville: Tz = Tz::America__Kentucky__Louisville;
pub const Monticello: Tz = Tz::America__Kentucky__Monticello;
}
pub mod North_Dakota {
use crate::timezones::Tz;
pub const Beulah: Tz = Tz::America__North_Dakota__Beulah;
pub const Center: Tz = Tz::America__North_Dakota__Center;
pub const New_Salem: Tz = Tz::America__North_Dakota__New_Salem;
}
pub const Adak: Tz = Tz::America__Adak;
pub const Anchorage: Tz = Tz::America__Anchorage;
pub const Anguilla: Tz = Tz::America__Anguilla;
pub const Antigua: Tz = Tz::America__Antigua;
pub const Araguaina: Tz = Tz::America__Araguaina;
pub const Aruba: Tz = Tz::America__Aruba;
pub const Asuncion: Tz = Tz::America__Asuncion;
pub const Atikokan: Tz = Tz::America__Atikokan;
pub const Atka: Tz = Tz::America__Atka;
pub const Bahia: Tz = Tz::America__Bahia;
pub const Bahia_Banderas: Tz = Tz::America__Bahia_Banderas;
pub const Barbados: Tz = Tz::America__Barbados;
pub const Belem: Tz = Tz::America__Belem;
pub const Belize: Tz = Tz::America__Belize;
pub const BlancSablon: Tz = Tz::America__BlancSablon;
pub const Boa_Vista: Tz = Tz::America__Boa_Vista;
pub const Bogota: Tz = Tz::America__Bogota;
pub const Boise: Tz = Tz::America__Boise;
pub const Buenos_Aires: Tz = Tz::America__Buenos_Aires;
pub const Cambridge_Bay: Tz = Tz::America__Cambridge_Bay;
pub const Campo_Grande: Tz = Tz::America__Campo_Grande;
pub const Cancun: Tz = Tz::America__Cancun;
pub const Caracas: Tz = Tz::America__Caracas;
pub const Catamarca: Tz = Tz::America__Catamarca;
pub const Cayenne: Tz = Tz::America__Cayenne;
pub const Cayman: Tz = Tz::America__Cayman;
pub const Chicago: Tz = Tz::America__Chicago;
pub const Chihuahua: Tz = Tz::America__Chihuahua;
pub const Ciudad_Juarez: Tz = Tz::America__Ciudad_Juarez;
pub const Coral_Harbour: Tz = Tz::America__Coral_Harbour;
pub const Cordoba: Tz = Tz::America__Cordoba;
pub const Costa_Rica: Tz = Tz::America__Costa_Rica;
pub const Coyhaique: Tz = Tz::America__Coyhaique;
pub const Creston: Tz = Tz::America__Creston;
pub const Cuiaba: Tz = Tz::America__Cuiaba;
pub const Curacao: Tz = Tz::America__Curacao;
pub const Danmarkshavn: Tz = Tz::America__Danmarkshavn;
pub const Dawson: Tz = Tz::America__Dawson;
pub const Dawson_Creek: Tz = Tz::America__Dawson_Creek;
pub const Denver: Tz = Tz::America__Denver;
pub const Detroit: Tz = Tz::America__Detroit;
pub const Dominica: Tz = Tz::America__Dominica;
pub const Edmonton: Tz = Tz::America__Edmonton;
pub const Eirunepe: Tz = Tz::America__Eirunepe;
pub const El_Salvador: Tz = Tz::America__El_Salvador;
pub const Ensenada: Tz = Tz::America__Ensenada;
pub const Fort_Nelson: Tz = Tz::America__Fort_Nelson;
pub const Fort_Wayne: Tz = Tz::America__Fort_Wayne;
pub const Fortaleza: Tz = Tz::America__Fortaleza;
pub const Glace_Bay: Tz = Tz::America__Glace_Bay;
pub const Godthab: Tz = Tz::America__Godthab;
pub const Goose_Bay: Tz = Tz::America__Goose_Bay;
pub const Grand_Turk: Tz = Tz::America__Grand_Turk;
pub const Grenada: Tz = Tz::America__Grenada;
pub const Guadeloupe: Tz = Tz::America__Guadeloupe;
pub const Guatemala: Tz = Tz::America__Guatemala;
pub const Guayaquil: Tz = Tz::America__Guayaquil;
pub const Guyana: Tz = Tz::America__Guyana;
pub const Halifax: Tz = Tz::America__Halifax;
pub const Havana: Tz = Tz::America__Havana;
pub const Hermosillo: Tz = Tz::America__Hermosillo;
pub const Indianapolis: Tz = Tz::America__Indianapolis;
pub const Inuvik: Tz = Tz::America__Inuvik;
pub const Iqaluit: Tz = Tz::America__Iqaluit;
pub const Jamaica: Tz = Tz::America__Jamaica;
pub const Jujuy: Tz = Tz::America__Jujuy;
pub const Juneau: Tz = Tz::America__Juneau;
pub const Knox_IN: Tz = Tz::America__Knox_IN;
pub const Kralendijk: Tz = Tz::America__Kralendijk;
pub const La_Paz: Tz = Tz::America__La_Paz;
pub const Lima: Tz = Tz::America__Lima;
pub const Los_Angeles: Tz = Tz::America__Los_Angeles;
pub const Louisville: Tz = Tz::America__Louisville;
pub const Lower_Princes: Tz = Tz::America__Lower_Princes;
pub const Maceio: Tz = Tz::America__Maceio;
pub const Managua: Tz = Tz::America__Managua;
pub const Manaus: Tz = Tz::America__Manaus;
pub const Marigot: Tz = Tz::America__Marigot;
pub const Martinique: Tz = Tz::America__Martinique;
pub const Matamoros: Tz = Tz::America__Matamoros;
pub const Mazatlan: Tz = Tz::America__Mazatlan;
pub const Mendoza: Tz = Tz::America__Mendoza;
pub const Menominee: Tz = Tz::America__Menominee;
pub const Merida: Tz = Tz::America__Merida;
pub const Metlakatla: Tz = Tz::America__Metlakatla;
pub const Mexico_City: Tz = Tz::America__Mexico_City;
pub const Miquelon: Tz = Tz::America__Miquelon;
pub const Moncton: Tz = Tz::America__Moncton;
pub const Monterrey: Tz = Tz::America__Monterrey;
pub const Montevideo: Tz = Tz::America__Montevideo;
pub const Montreal: Tz = Tz::America__Montreal;
pub const Montserrat: Tz = Tz::America__Montserrat;
pub const Nassau: Tz = Tz::America__Nassau;
pub const New_York: Tz = Tz::America__New_York;
pub const Nipigon: Tz = Tz::America__Nipigon;
pub const Nome: Tz = Tz::America__Nome;
pub const Noronha: Tz = Tz::America__Noronha;
pub const Nuuk: Tz = Tz::America__Nuuk;
pub const Ojinaga: Tz = Tz::America__Ojinaga;
pub const Panama: Tz = Tz::America__Panama;
pub const Pangnirtung: Tz = Tz::America__Pangnirtung;
pub const Paramaribo: Tz = Tz::America__Paramaribo;
pub const Phoenix: Tz = Tz::America__Phoenix;
pub const PortauPrince: Tz = Tz::America__PortauPrince;
pub const Port_of_Spain: Tz = Tz::America__Port_of_Spain;
pub const Porto_Acre: Tz = Tz::America__Porto_Acre;
pub const Porto_Velho: Tz = Tz::America__Porto_Velho;
pub const Puerto_Rico: Tz = Tz::America__Puerto_Rico;
pub const Punta_Arenas: Tz = Tz::America__Punta_Arenas;
pub const Rainy_River: Tz = Tz::America__Rainy_River;
pub const Rankin_Inlet: Tz = Tz::America__Rankin_Inlet;
pub const Recife: Tz = Tz::America__Recife;
pub const Regina: Tz = Tz::America__Regina;
pub const Resolute: Tz = Tz::America__Resolute;
pub const Rio_Branco: Tz = Tz::America__Rio_Branco;
pub const Rosario: Tz = Tz::America__Rosario;
pub const Santa_Isabel: Tz = Tz::America__Santa_Isabel;
pub const Santarem: Tz = Tz::America__Santarem;
pub const Santiago: Tz = Tz::America__Santiago;
pub const Santo_Domingo: Tz = Tz::America__Santo_Domingo;
pub const Sao_Paulo: Tz = Tz::America__Sao_Paulo;
pub const Scoresbysund: Tz = Tz::America__Scoresbysund;
pub const Shiprock: Tz = Tz::America__Shiprock;
pub const Sitka: Tz = Tz::America__Sitka;
pub const St_Barthelemy: Tz = Tz::America__St_Barthelemy;
pub const St_Johns: Tz = Tz::America__St_Johns;
pub const St_Kitts: Tz = Tz::America__St_Kitts;
pub const St_Lucia: Tz = Tz::America__St_Lucia;
pub const St_Thomas: Tz = Tz::America__St_Thomas;
pub const St_Vincent: Tz = Tz::America__St_Vincent;
pub const Swift_Current: Tz = Tz::America__Swift_Current;
pub const Tegucigalpa: Tz = Tz::America__Tegucigalpa;
pub const Thule: Tz = Tz::America__Thule;
pub const Thunder_Bay: Tz = Tz::America__Thunder_Bay;
pub const Tijuana: Tz = Tz::America__Tijuana;
pub const Toronto: Tz = Tz::America__Toronto;
pub const Tortola: Tz = Tz::America__Tortola;
pub const Vancouver: Tz = Tz::America__Vancouver;
pub const Virgin: Tz = Tz::America__Virgin;
pub const Whitehorse: Tz = Tz::America__Whitehorse;
pub const Winnipeg: Tz = Tz::America__Winnipeg;
pub const Yakutat: Tz = Tz::America__Yakutat;
pub const Yellowknife: Tz = Tz::America__Yellowknife;
}
pub mod Antarctica {
use crate::timezones::Tz;
pub const Casey: Tz = Tz::Antarctica__Casey;
pub const Davis: Tz = Tz::Antarctica__Davis;
pub const DumontDUrville: Tz = Tz::Antarctica__DumontDUrville;
pub const Macquarie: Tz = Tz::Antarctica__Macquarie;
pub const Mawson: Tz = Tz::Antarctica__Mawson;
pub const McMurdo: Tz = Tz::Antarctica__McMurdo;
pub const Palmer: Tz = Tz::Antarctica__Palmer;
pub const Rothera: Tz = Tz::Antarctica__Rothera;
pub const South_Pole: Tz = Tz::Antarctica__South_Pole;
pub const Syowa: Tz = Tz::Antarctica__Syowa;
pub const Troll: Tz = Tz::Antarctica__Troll;
pub const Vostok: Tz = Tz::Antarctica__Vostok;
}
pub mod Arctic {
use crate::timezones::Tz;
pub const Longyearbyen: Tz = Tz::Arctic__Longyearbyen;
}
pub mod Asia {
use crate::timezones::Tz;
pub const Aden: Tz = Tz::Asia__Aden;
pub const Almaty: Tz = Tz::Asia__Almaty;
pub const Amman: Tz = Tz::Asia__Amman;
pub const Anadyr: Tz = Tz::Asia__Anadyr;
pub const Aqtau: Tz = Tz::Asia__Aqtau;
pub const Aqtobe: Tz = Tz::Asia__Aqtobe;
pub const Ashgabat: Tz = Tz::Asia__Ashgabat;
pub const Ashkhabad: Tz = Tz::Asia__Ashkhabad;
pub const Atyrau: Tz = Tz::Asia__Atyrau;
pub const Baghdad: Tz = Tz::Asia__Baghdad;
pub const Bahrain: Tz = Tz::Asia__Bahrain;
pub const Baku: Tz = Tz::Asia__Baku;
pub const Bangkok: Tz = Tz::Asia__Bangkok;
pub const Barnaul: Tz = Tz::Asia__Barnaul;
pub const Beirut: Tz = Tz::Asia__Beirut;
pub const Bishkek: Tz = Tz::Asia__Bishkek;
pub const Brunei: Tz = Tz::Asia__Brunei;
pub const Calcutta: Tz = Tz::Asia__Calcutta;
pub const Chita: Tz = Tz::Asia__Chita;
pub const Choibalsan: Tz = Tz::Asia__Choibalsan;
pub const Chongqing: Tz = Tz::Asia__Chongqing;
pub const Chungking: Tz = Tz::Asia__Chungking;
pub const Colombo: Tz = Tz::Asia__Colombo;
pub const Dacca: Tz = Tz::Asia__Dacca;
pub const Damascus: Tz = Tz::Asia__Damascus;
pub const Dhaka: Tz = Tz::Asia__Dhaka;
pub const Dili: Tz = Tz::Asia__Dili;
pub const Dubai: Tz = Tz::Asia__Dubai;
pub const Dushanbe: Tz = Tz::Asia__Dushanbe;
pub const Famagusta: Tz = Tz::Asia__Famagusta;
pub const Gaza: Tz = Tz::Asia__Gaza;
pub const Harbin: Tz = Tz::Asia__Harbin;
pub const Hebron: Tz = Tz::Asia__Hebron;
pub const Ho_Chi_Minh: Tz = Tz::Asia__Ho_Chi_Minh;
pub const Hong_Kong: Tz = Tz::Asia__Hong_Kong;
pub const Hovd: Tz = Tz::Asia__Hovd;
pub const Irkutsk: Tz = Tz::Asia__Irkutsk;
pub const Istanbul: Tz = Tz::Asia__Istanbul;
pub const Jakarta: Tz = Tz::Asia__Jakarta;
pub const Jayapura: Tz = Tz::Asia__Jayapura;
pub const Jerusalem: Tz = Tz::Asia__Jerusalem;
pub const Kabul: Tz = Tz::Asia__Kabul;
pub const Kamchatka: Tz = Tz::Asia__Kamchatka;
pub const Karachi: Tz = Tz::Asia__Karachi;
pub const Kashgar: Tz = Tz::Asia__Kashgar;
pub const Kathmandu: Tz = Tz::Asia__Kathmandu;
pub const Katmandu: Tz = Tz::Asia__Katmandu;
pub const Khandyga: Tz = Tz::Asia__Khandyga;
pub const Kolkata: Tz = Tz::Asia__Kolkata;
pub const Krasnoyarsk: Tz = Tz::Asia__Krasnoyarsk;
pub const Kuala_Lumpur: Tz = Tz::Asia__Kuala_Lumpur;
pub const Kuching: Tz = Tz::Asia__Kuching;
pub const Kuwait: Tz = Tz::Asia__Kuwait;
pub const Macao: Tz = Tz::Asia__Macao;
pub const Macau: Tz = Tz::Asia__Macau;
pub const Magadan: Tz = Tz::Asia__Magadan;
pub const Makassar: Tz = Tz::Asia__Makassar;
pub const Manila: Tz = Tz::Asia__Manila;
pub const Muscat: Tz = Tz::Asia__Muscat;
pub const Nicosia: Tz = Tz::Asia__Nicosia;
pub const Novokuznetsk: Tz = Tz::Asia__Novokuznetsk;
pub const Novosibirsk: Tz = Tz::Asia__Novosibirsk;
pub const Omsk: Tz = Tz::Asia__Omsk;
pub const Oral: Tz = Tz::Asia__Oral;
pub const Phnom_Penh: Tz = Tz::Asia__Phnom_Penh;
pub const Pontianak: Tz = Tz::Asia__Pontianak;
pub const Pyongyang: Tz = Tz::Asia__Pyongyang;
pub const Qatar: Tz = Tz::Asia__Qatar;
pub const Qostanay: Tz = Tz::Asia__Qostanay;
pub const Qyzylorda: Tz = Tz::Asia__Qyzylorda;
pub const Rangoon: Tz = Tz::Asia__Rangoon;
pub const Riyadh: Tz = Tz::Asia__Riyadh;
pub const Saigon: Tz = Tz::Asia__Saigon;
pub const Sakhalin: Tz = Tz::Asia__Sakhalin;
pub const Samarkand: Tz = Tz::Asia__Samarkand;
pub const Seoul: Tz = Tz::Asia__Seoul;
pub const Shanghai: Tz = Tz::Asia__Shanghai;
pub const Singapore: Tz = Tz::Asia__Singapore;
pub const Srednekolymsk: Tz = Tz::Asia__Srednekolymsk;
pub const Taipei: Tz = Tz::Asia__Taipei;
pub const Tashkent: Tz = Tz::Asia__Tashkent;
pub const Tbilisi: Tz = Tz::Asia__Tbilisi;
pub const Tehran: Tz = Tz::Asia__Tehran;
pub const Tel_Aviv: Tz = Tz::Asia__Tel_Aviv;
pub const Thimbu: Tz = Tz::Asia__Thimbu;
pub const Thimphu: Tz = Tz::Asia__Thimphu;
pub const Tokyo: Tz = Tz::Asia__Tokyo;
pub const Tomsk: Tz = Tz::Asia__Tomsk;
pub const Ujung_Pandang: Tz = Tz::Asia__Ujung_Pandang;
pub const Ulaanbaatar: Tz = Tz::Asia__Ulaanbaatar;
pub const Ulan_Bator: Tz = Tz::Asia__Ulan_Bator;
pub const Urumqi: Tz = Tz::Asia__Urumqi;
pub const UstNera: Tz = Tz::Asia__UstNera;
pub const Vientiane: Tz = Tz::Asia__Vientiane;
pub const Vladivostok: Tz = Tz::Asia__Vladivostok;
pub const Yakutsk: Tz = Tz::Asia__Yakutsk;
pub const Yangon: Tz = Tz::Asia__Yangon;
pub const Yekaterinburg: Tz = Tz::Asia__Yekaterinburg;
pub const Yerevan: Tz = Tz::Asia__Yerevan;
}
pub mod Atlantic {
use crate::timezones::Tz;
pub const Azores: Tz = Tz::Atlantic__Azores;
pub const Bermuda: Tz = Tz::Atlantic__Bermuda;
pub const Canary: Tz = Tz::Atlantic__Canary;
pub const Cape_Verde: Tz = Tz::Atlantic__Cape_Verde;
pub const Faeroe: Tz = Tz::Atlantic__Faeroe;
pub const Faroe: Tz = Tz::Atlantic__Faroe;
pub const Jan_Mayen: Tz = Tz::Atlantic__Jan_Mayen;
pub const Madeira: Tz = Tz::Atlantic__Madeira;
pub const Reykjavik: Tz = Tz::Atlantic__Reykjavik;
pub const South_Georgia: Tz = Tz::Atlantic__South_Georgia;
pub const St_Helena: Tz = Tz::Atlantic__St_Helena;
pub const Stanley: Tz = Tz::Atlantic__Stanley;
}
pub mod Australia {
use crate::timezones::Tz;
pub const ACT: Tz = Tz::Australia__ACT;
pub const Adelaide: Tz = Tz::Australia__Adelaide;
pub const Brisbane: Tz = Tz::Australia__Brisbane;
pub const Broken_Hill: Tz = Tz::Australia__Broken_Hill;
pub const Canberra: Tz = Tz::Australia__Canberra;
pub const Currie: Tz = Tz::Australia__Currie;
pub const Darwin: Tz = Tz::Australia__Darwin;
pub const Eucla: Tz = Tz::Australia__Eucla;
pub const Hobart: Tz = Tz::Australia__Hobart;
pub const LHI: Tz = Tz::Australia__LHI;
pub const Lindeman: Tz = Tz::Australia__Lindeman;
pub const Lord_Howe: Tz = Tz::Australia__Lord_Howe;
pub const Melbourne: Tz = Tz::Australia__Melbourne;
pub const NSW: Tz = Tz::Australia__NSW;
pub const North: Tz = Tz::Australia__North;
pub const Perth: Tz = Tz::Australia__Perth;
pub const Queensland: Tz = Tz::Australia__Queensland;
pub const South: Tz = Tz::Australia__South;
pub const Sydney: Tz = Tz::Australia__Sydney;
pub const Tasmania: Tz = Tz::Australia__Tasmania;
pub const Victoria: Tz = Tz::Australia__Victoria;
pub const West: Tz = Tz::Australia__West;
pub const Yancowinna: Tz = Tz::Australia__Yancowinna;
}
pub mod Brazil {
use crate::timezones::Tz;
pub const Acre: Tz = Tz::Brazil__Acre;
pub const DeNoronha: Tz = Tz::Brazil__DeNoronha;
pub const East: Tz = Tz::Brazil__East;
pub const West: Tz = Tz::Brazil__West;
}
pub mod Canada {
use crate::timezones::Tz;
pub const Atlantic: Tz = Tz::Canada__Atlantic;
pub const Central: Tz = Tz::Canada__Central;
pub const Eastern: Tz = Tz::Canada__Eastern;
pub const Mountain: Tz = Tz::Canada__Mountain;
pub const Newfoundland: Tz = Tz::Canada__Newfoundland;
pub const Pacific: Tz = Tz::Canada__Pacific;
pub const Saskatchewan: Tz = Tz::Canada__Saskatchewan;
pub const Yukon: Tz = Tz::Canada__Yukon;
}
pub mod Chile {
use crate::timezones::Tz;
pub const Continental: Tz = Tz::Chile__Continental;
pub const EasterIsland: Tz = Tz::Chile__EasterIsland;
}
pub mod Etc {
use crate::timezones::Tz;
pub const GMT: Tz = Tz::Etc__GMT;
pub const GMTPlus0: Tz = Tz::Etc__GMTPlus0;
pub const GMTPlus1: Tz = Tz::Etc__GMTPlus1;
pub const GMTPlus10: Tz = Tz::Etc__GMTPlus10;
pub const GMTPlus11: Tz = Tz::Etc__GMTPlus11;
pub const GMTPlus12: Tz = Tz::Etc__GMTPlus12;
pub const GMTPlus2: Tz = Tz::Etc__GMTPlus2;
pub const GMTPlus3: Tz = Tz::Etc__GMTPlus3;
pub const GMTPlus4: Tz = Tz::Etc__GMTPlus4;
pub const GMTPlus5: Tz = Tz::Etc__GMTPlus5;
pub const GMTPlus6: Tz = Tz::Etc__GMTPlus6;
pub const GMTPlus7: Tz = Tz::Etc__GMTPlus7;
pub const GMTPlus8: Tz = Tz::Etc__GMTPlus8;
pub const GMTPlus9: Tz = Tz::Etc__GMTPlus9;
pub const GMTMinus0: Tz = Tz::Etc__GMTMinus0;
pub const GMTMinus1: Tz = Tz::Etc__GMTMinus1;
pub const GMTMinus10: Tz = Tz::Etc__GMTMinus10;
pub const GMTMinus11: Tz = Tz::Etc__GMTMinus11;
pub const GMTMinus12: Tz = Tz::Etc__GMTMinus12;
pub const GMTMinus13: Tz = Tz::Etc__GMTMinus13;
pub const GMTMinus14: Tz = Tz::Etc__GMTMinus14;
pub const GMTMinus2: Tz = Tz::Etc__GMTMinus2;
pub const GMTMinus3: Tz = Tz::Etc__GMTMinus3;
pub const GMTMinus4: Tz = Tz::Etc__GMTMinus4;
pub const GMTMinus5: Tz = Tz::Etc__GMTMinus5;
pub const GMTMinus6: Tz = Tz::Etc__GMTMinus6;
pub const GMTMinus7: Tz = Tz::Etc__GMTMinus7;
pub const GMTMinus8: Tz = Tz::Etc__GMTMinus8;
pub const GMTMinus9: Tz = Tz::Etc__GMTMinus9;
pub const GMT0: Tz = Tz::Etc__GMT0;
pub const Greenwich: Tz = Tz::Etc__Greenwich;
pub const UCT: Tz = Tz::Etc__UCT;
pub const UTC: Tz = Tz::Etc__UTC;
pub const Universal: Tz = Tz::Etc__Universal;
pub const Zulu: Tz = Tz::Etc__Zulu;
}
pub mod Europe {
use crate::timezones::Tz;
pub const Amsterdam: Tz = Tz::Europe__Amsterdam;
pub const Andorra: Tz = Tz::Europe__Andorra;
pub const Astrakhan: Tz = Tz::Europe__Astrakhan;
pub const Athens: Tz = Tz::Europe__Athens;
pub const Belfast: Tz = Tz::Europe__Belfast;
pub const Belgrade: Tz = Tz::Europe__Belgrade;
pub const Berlin: Tz = Tz::Europe__Berlin;
pub const Bratislava: Tz = Tz::Europe__Bratislava;
pub const Brussels: Tz = Tz::Europe__Brussels;
pub const Bucharest: Tz = Tz::Europe__Bucharest;
pub const Budapest: Tz = Tz::Europe__Budapest;
pub const Busingen: Tz = Tz::Europe__Busingen;
pub const Chisinau: Tz = Tz::Europe__Chisinau;
pub const Copenhagen: Tz = Tz::Europe__Copenhagen;
pub const Dublin: Tz = Tz::Europe__Dublin;
pub const Gibraltar: Tz = Tz::Europe__Gibraltar;
pub const Guernsey: Tz = Tz::Europe__Guernsey;
pub const Helsinki: Tz = Tz::Europe__Helsinki;
pub const Isle_of_Man: Tz = Tz::Europe__Isle_of_Man;
pub const Istanbul: Tz = Tz::Europe__Istanbul;
pub const Jersey: Tz = Tz::Europe__Jersey;
pub const Kaliningrad: Tz = Tz::Europe__Kaliningrad;
pub const Kiev: Tz = Tz::Europe__Kiev;
pub const Kirov: Tz = Tz::Europe__Kirov;
pub const Kyiv: Tz = Tz::Europe__Kyiv;
pub const Lisbon: Tz = Tz::Europe__Lisbon;
pub const Ljubljana: Tz = Tz::Europe__Ljubljana;
pub const London: Tz = Tz::Europe__London;
pub const Luxembourg: Tz = Tz::Europe__Luxembourg;
pub const Madrid: Tz = Tz::Europe__Madrid;
pub const Malta: Tz = Tz::Europe__Malta;
pub const Mariehamn: Tz = Tz::Europe__Mariehamn;
pub const Minsk: Tz = Tz::Europe__Minsk;
pub const Monaco: Tz = Tz::Europe__Monaco;
pub const Moscow: Tz = Tz::Europe__Moscow;
pub const Nicosia: Tz = Tz::Europe__Nicosia;
pub const Oslo: Tz = Tz::Europe__Oslo;
pub const Paris: Tz = Tz::Europe__Paris;
pub const Podgorica: Tz = Tz::Europe__Podgorica;
pub const Prague: Tz = Tz::Europe__Prague;
pub const Riga: Tz = Tz::Europe__Riga;
pub const Rome: Tz = Tz::Europe__Rome;
pub const Samara: Tz = Tz::Europe__Samara;
pub const San_Marino: Tz = Tz::Europe__San_Marino;
pub const Sarajevo: Tz = Tz::Europe__Sarajevo;
pub const Saratov: Tz = Tz::Europe__Saratov;
pub const Simferopol: Tz = Tz::Europe__Simferopol;
pub const Skopje: Tz = Tz::Europe__Skopje;
pub const Sofia: Tz = Tz::Europe__Sofia;
pub const Stockholm: Tz = Tz::Europe__Stockholm;
pub const Tallinn: Tz = Tz::Europe__Tallinn;
pub const Tirane: Tz = Tz::Europe__Tirane;
pub const Tiraspol: Tz = Tz::Europe__Tiraspol;
pub const Ulyanovsk: Tz = Tz::Europe__Ulyanovsk;
pub const Uzhgorod: Tz = Tz::Europe__Uzhgorod;
pub const Vaduz: Tz = Tz::Europe__Vaduz;
pub const Vatican: Tz = Tz::Europe__Vatican;
pub const Vienna: Tz = Tz::Europe__Vienna;
pub const Vilnius: Tz = Tz::Europe__Vilnius;
pub const Volgograd: Tz = Tz::Europe__Volgograd;
pub const Warsaw: Tz = Tz::Europe__Warsaw;
pub const Zagreb: Tz = Tz::Europe__Zagreb;
pub const Zaporozhye: Tz = Tz::Europe__Zaporozhye;
pub const Zurich: Tz = Tz::Europe__Zurich;
}
pub mod Indian {
use crate::timezones::Tz;
pub const Antananarivo: Tz = Tz::Indian__Antananarivo;
pub const Chagos: Tz = Tz::Indian__Chagos;
pub const Christmas: Tz = Tz::Indian__Christmas;
pub const Cocos: Tz = Tz::Indian__Cocos;
pub const Comoro: Tz = Tz::Indian__Comoro;
pub const Kerguelen: Tz = Tz::Indian__Kerguelen;
pub const Mahe: Tz = Tz::Indian__Mahe;
pub const Maldives: Tz = Tz::Indian__Maldives;
pub const Mauritius: Tz = Tz::Indian__Mauritius;
pub const Mayotte: Tz = Tz::Indian__Mayotte;
pub const Reunion: Tz = Tz::Indian__Reunion;
}
pub mod Mexico {
use crate::timezones::Tz;
pub const BajaNorte: Tz = Tz::Mexico__BajaNorte;
pub const BajaSur: Tz = Tz::Mexico__BajaSur;
pub const General: Tz = Tz::Mexico__General;
}
pub mod Pacific {
use crate::timezones::Tz;
pub const Apia: Tz = Tz::Pacific__Apia;
pub const Auckland: Tz = Tz::Pacific__Auckland;
pub const Bougainville: Tz = Tz::Pacific__Bougainville;
pub const Chatham: Tz = Tz::Pacific__Chatham;
pub const Chuuk: Tz = Tz::Pacific__Chuuk;
pub const Easter: Tz = Tz::Pacific__Easter;
pub const Efate: Tz = Tz::Pacific__Efate;
pub const Enderbury: Tz = Tz::Pacific__Enderbury;
pub const Fakaofo: Tz = Tz::Pacific__Fakaofo;
pub const Fiji: Tz = Tz::Pacific__Fiji;
pub const Funafuti: Tz = Tz::Pacific__Funafuti;
pub const Galapagos: Tz = Tz::Pacific__Galapagos;
pub const Gambier: Tz = Tz::Pacific__Gambier;
pub const Guadalcanal: Tz = Tz::Pacific__Guadalcanal;
pub const Guam: Tz = Tz::Pacific__Guam;
pub const Honolulu: Tz = Tz::Pacific__Honolulu;
pub const Johnston: Tz = Tz::Pacific__Johnston;
pub const Kanton: Tz = Tz::Pacific__Kanton;
pub const Kiritimati: Tz = Tz::Pacific__Kiritimati;
pub const Kosrae: Tz = Tz::Pacific__Kosrae;
pub const Kwajalein: Tz = Tz::Pacific__Kwajalein;
pub const Majuro: Tz = Tz::Pacific__Majuro;
pub const Marquesas: Tz = Tz::Pacific__Marquesas;
pub const Midway: Tz = Tz::Pacific__Midway;
pub const Nauru: Tz = Tz::Pacific__Nauru;
pub const Niue: Tz = Tz::Pacific__Niue;
pub const Norfolk: Tz = Tz::Pacific__Norfolk;
pub const Noumea: Tz = Tz::Pacific__Noumea;
pub const Pago_Pago: Tz = Tz::Pacific__Pago_Pago;
pub const Palau: Tz = Tz::Pacific__Palau;
pub const Pitcairn: Tz = Tz::Pacific__Pitcairn;
pub const Pohnpei: Tz = Tz::Pacific__Pohnpei;
pub const Ponape: Tz = Tz::Pacific__Ponape;
pub const Port_Moresby: Tz = Tz::Pacific__Port_Moresby;
pub const Rarotonga: Tz = Tz::Pacific__Rarotonga;
pub const Saipan: Tz = Tz::Pacific__Saipan;
pub const Samoa: Tz = Tz::Pacific__Samoa;
pub const Tahiti: Tz = Tz::Pacific__Tahiti;
pub const Tarawa: Tz = Tz::Pacific__Tarawa;
pub const Tongatapu: Tz = Tz::Pacific__Tongatapu;
pub const Truk: Tz = Tz::Pacific__Truk;
pub const Wake: Tz = Tz::Pacific__Wake;
pub const Wallis: Tz = Tz::Pacific__Wallis;
pub const Yap: Tz = Tz::Pacific__Yap;
}
pub mod US {
use crate::timezones::Tz;
pub const Alaska: Tz = Tz::US__Alaska;
pub const Aleutian: Tz = Tz::US__Aleutian;
pub const Arizona: Tz = Tz::US__Arizona;
pub const Central: Tz = Tz::US__Central;
pub const EastIndiana: Tz = Tz::US__EastIndiana;
pub const Eastern: Tz = Tz::US__Eastern;
pub const Hawaii: Tz = Tz::US__Hawaii;
pub const IndianaStarke: Tz = Tz::US__IndianaStarke;
pub const Michigan: Tz = Tz::US__Michigan;
pub const Mountain: Tz = Tz::US__Mountain;
pub const Pacific: Tz = Tz::US__Pacific;
pub const Samoa: Tz = Tz::US__Samoa;
}
+12
View File
@@ -0,0 +1,12 @@
#![allow(
dead_code,
non_camel_case_types,
non_snake_case,
non_upper_case_globals
)]
#[cfg(not(any(feature = "case-insensitive", feature = "filter-by-regex")))]
pub(crate) mod directory;
#[cfg(not(any(feature = "case-insensitive", feature = "filter-by-regex")))]
#[rustfmt::skip]
pub(crate) mod timezones;
File diff suppressed because it is too large Load Diff
+63
View File
@@ -0,0 +1,63 @@
extern crate serde;
use self::serde::{de, Deserialize, Deserializer, Serialize, Serializer};
use core::fmt;
use crate::timezones::Tz;
impl Serialize for Tz {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_str(self.name())
}
}
impl<'de> Deserialize<'de> for Tz {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct Visitor;
impl<'de> de::Visitor<'de> for Visitor {
type Value = Tz;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "an IANA timezone string")
}
fn visit_str<E: de::Error>(self, value: &str) -> Result<Tz, E> {
value
.parse::<Tz>()
.map_err(|_| E::custom(SerdeError(value)))
}
}
deserializer.deserialize_str(Visitor)
}
}
struct SerdeError<'a>(&'a str);
impl fmt::Display for SerdeError<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "failed to parse timezone: '{}'", self.0)
}
}
#[cfg(test)]
mod tests {
use crate::timezones::Tz::{self, Etc__UTC, Europe__London, UTC};
use serde_test::{assert_de_tokens_error, assert_tokens, Token};
#[test]
fn serde_ok_both_ways() {
assert_tokens(&Europe__London, &[Token::String("Europe/London")]);
assert_tokens(&Etc__UTC, &[Token::String("Etc/UTC")]);
assert_tokens(&UTC, &[Token::String("UTC")]);
}
#[test]
fn serde_de_error() {
assert_de_tokens_error::<Tz>(
&[Token::Str("Europe/L")],
"failed to parse timezone: 'Europe/L'",
);
}
}
+478
View File
@@ -0,0 +1,478 @@
use core::cmp::Ordering;
use core::fmt::{Debug, Display, Error, Formatter, Write};
use chrono::{
DateTime, Duration, FixedOffset, LocalResult, NaiveDate, NaiveDateTime, NaiveTime, Offset,
TimeZone,
};
use crate::binary_search::binary_search;
use crate::timezones::Tz;
/// Returns [`Tz::UTC`].
impl Default for Tz {
fn default() -> Self {
Tz::UTC
}
}
/// An Offset that applies for a period of time
///
/// For example, [`::US::Eastern`] is composed of at least two
/// `FixedTimespan`s: `EST` and `EDT`, that are variously in effect.
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct FixedTimespan {
/// The base offset from UTC; this usually doesn't change unless the government changes something
pub utc_offset: i32,
/// The additional offset from UTC for this timespan; typically for daylight saving time
pub dst_offset: i32,
/// The name of this timezone, for example the difference between `EDT`/`EST`
pub name: Option<&'static str>,
}
impl Offset for FixedTimespan {
fn fix(&self) -> FixedOffset {
FixedOffset::east_opt(self.utc_offset + self.dst_offset).unwrap()
}
}
impl Display for FixedTimespan {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
if let Some(name) = self.name {
return write!(f, "{name}");
}
let offset = self.utc_offset + self.dst_offset;
let (sign, off) = if offset < 0 {
('-', -offset)
} else {
('+', offset)
};
let minutes = off / 60;
let secs = (off % 60) as u8;
let mins = (minutes % 60) as u8;
let hours = (minutes / 60) as u8;
assert!(
secs == 0,
"numeric names are not used if the offset has fractional minutes"
);
f.write_char(sign)?;
write!(f, "{hours:02}")?;
if mins != 0 {
write!(f, "{mins:02}")?;
}
Ok(())
}
}
impl Debug for FixedTimespan {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
Display::fmt(self, f)
}
}
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct TzOffset {
tz: Tz,
offset: FixedTimespan,
}
/// Detailed timezone offset components that expose any special conditions currently in effect.
///
/// This trait breaks down an offset into the standard UTC offset and any special offset
/// in effect (such as DST) at a given time.
///
/// ```
/// # extern crate chrono;
/// # extern crate chrono_tz;
/// use chrono::{Duration, Offset, TimeZone};
/// use chrono_tz::Europe::London;
/// use chrono_tz::OffsetComponents;
///
/// # fn main() {
/// let london_time = London.ymd(2016, 5, 10).and_hms(12, 0, 0);
///
/// // London typically has zero offset from UTC, but has a 1h adjustment forward
/// // when summer time is in effect.
/// let lon_utc_offset = london_time.offset().base_utc_offset();
/// let lon_dst_offset = london_time.offset().dst_offset();
/// let total_offset = lon_utc_offset + lon_dst_offset;
/// assert_eq!(lon_utc_offset, Duration::hours(0));
/// assert_eq!(lon_dst_offset, Duration::hours(1));
///
/// // As a sanity check, make sure that the total offsets added together are equivalent to the
/// // total fixed offset.
/// assert_eq!(total_offset.num_seconds(), london_time.offset().fix().local_minus_utc() as i64);
/// # }
/// ```
pub trait OffsetComponents {
/// The base offset from UTC; this usually doesn't change unless the government changes something
fn base_utc_offset(&self) -> Duration;
/// The additional offset from UTC that is currently in effect; typically for daylight saving time
fn dst_offset(&self) -> Duration;
}
/// Timezone offset name information.
///
/// This trait exposes display names that describe an offset in
/// various situations.
///
/// ```
/// # extern crate chrono;
/// # extern crate chrono_tz;
/// use chrono::{Duration, Offset, TimeZone};
/// use chrono_tz::Europe::London;
/// use chrono_tz::OffsetName;
///
/// # fn main() {
/// let london_time = London.ymd(2016, 2, 10).and_hms(12, 0, 0);
/// assert_eq!(london_time.offset().tz_id(), "Europe/London");
/// // London is normally on GMT
/// assert_eq!(london_time.offset().abbreviation(), Some("GMT"));
///
/// let london_summer_time = London.ymd(2016, 5, 10).and_hms(12, 0, 0);
/// // The TZ ID remains constant year round
/// assert_eq!(london_summer_time.offset().tz_id(), "Europe/London");
/// // During the summer, this becomes British Summer Time
/// assert_eq!(london_summer_time.offset().abbreviation(), Some("BST"));
/// # }
/// ```
pub trait OffsetName {
/// The IANA TZDB identifier (ex: America/New_York)
fn tz_id(&self) -> &str;
/// The abbreviation to use in a longer timestamp (ex: EST)
///
/// This takes into account any special offsets that may be in effect.
/// For example, at a given instant, the time zone with ID *America/New_York*
/// may be either *EST* or *EDT*.
fn abbreviation(&self) -> Option<&str>;
}
impl TzOffset {
fn new(tz: Tz, offset: FixedTimespan) -> Self {
TzOffset { tz, offset }
}
fn map_localresult(tz: Tz, result: LocalResult<FixedTimespan>) -> LocalResult<Self> {
match result {
LocalResult::None => LocalResult::None,
LocalResult::Single(s) => LocalResult::Single(TzOffset::new(tz, s)),
LocalResult::Ambiguous(a, b) => {
LocalResult::Ambiguous(TzOffset::new(tz, a), TzOffset::new(tz, b))
}
}
}
}
impl OffsetComponents for TzOffset {
fn base_utc_offset(&self) -> Duration {
Duration::seconds(self.offset.utc_offset as i64)
}
fn dst_offset(&self) -> Duration {
Duration::seconds(self.offset.dst_offset as i64)
}
}
impl OffsetName for TzOffset {
fn tz_id(&self) -> &str {
self.tz.name()
}
fn abbreviation(&self) -> Option<&str> {
self.offset.name
}
}
impl Offset for TzOffset {
fn fix(&self) -> FixedOffset {
self.offset.fix()
}
}
impl Display for TzOffset {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
Display::fmt(&self.offset, f)
}
}
impl Debug for TzOffset {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
Debug::fmt(&self.offset, f)
}
}
/// Represents the span of time that a given rule is valid for.
/// Note that I have made the assumption that all ranges are
/// left-inclusive and right-exclusive - that is to say,
/// if the clocks go forward by 1 hour at 1am, the time 1am
/// does not exist in local time (the clock goes from 00:59:59
/// to 02:00:00). Likewise, if the clocks go back by one hour
/// at 2am, the clock goes from 01:59:59 to 01:00:00. This is
/// an arbitrary choice, and I could not find a source to
/// confirm whether or not this is correct.
struct Span {
begin: Option<i64>,
end: Option<i64>,
}
impl Span {
fn contains(&self, x: i64) -> bool {
match (self.begin, self.end) {
(Some(a), Some(b)) if a <= x && x < b => true,
(Some(a), None) if a <= x => true,
(None, Some(b)) if b > x => true,
(None, None) => true,
_ => false,
}
}
fn cmp(&self, x: i64) -> Ordering {
match (self.begin, self.end) {
(Some(a), Some(b)) if a <= x && x < b => Ordering::Equal,
(Some(a), Some(b)) if a <= x && b <= x => Ordering::Less,
(Some(_), Some(_)) => Ordering::Greater,
(Some(a), None) if a <= x => Ordering::Equal,
(Some(_), None) => Ordering::Greater,
(None, Some(b)) if b <= x => Ordering::Less,
(None, Some(_)) => Ordering::Equal,
(None, None) => Ordering::Equal,
}
}
}
#[derive(Copy, Clone)]
pub struct FixedTimespanSet {
pub first: FixedTimespan,
pub rest: &'static [(i64, FixedTimespan)],
}
impl FixedTimespanSet {
fn len(&self) -> usize {
1 + self.rest.len()
}
fn utc_span(&self, index: usize) -> Span {
debug_assert!(index < self.len());
Span {
begin: if index == 0 {
None
} else {
Some(self.rest[index - 1].0)
},
end: if index == self.rest.len() {
None
} else {
Some(self.rest[index].0)
},
}
}
fn local_span(&self, index: usize) -> Span {
debug_assert!(index < self.len());
Span {
begin: if index == 0 {
None
} else {
let span = self.rest[index - 1];
Some(span.0 + span.1.utc_offset as i64 + span.1.dst_offset as i64)
},
end: if index == self.rest.len() {
None
} else if index == 0 {
Some(
self.rest[index].0
+ self.first.utc_offset as i64
+ self.first.dst_offset as i64,
)
} else {
Some(
self.rest[index].0
+ self.rest[index - 1].1.utc_offset as i64
+ self.rest[index - 1].1.dst_offset as i64,
)
},
}
}
fn get(&self, index: usize) -> FixedTimespan {
debug_assert!(index < self.len());
if index == 0 {
self.first
} else {
self.rest[index - 1].1
}
}
}
pub trait TimeSpans {
fn timespans(&self) -> FixedTimespanSet;
}
impl TimeZone for Tz {
type Offset = TzOffset;
fn from_offset(offset: &Self::Offset) -> Self {
offset.tz
}
#[allow(deprecated)]
fn offset_from_local_date(&self, local: &NaiveDate) -> LocalResult<Self::Offset> {
let earliest = self.offset_from_local_datetime(&local.and_time(NaiveTime::MIN));
let latest = self.offset_from_local_datetime(&local.and_hms_opt(23, 59, 59).unwrap());
// From the chrono docs:
//
// > This type should be considered ambiguous at best, due to the inherent lack of
// > precision required for the time zone resolution. There are some guarantees on the usage
// > of `Date<Tz>`:
// > - If properly constructed via `TimeZone::ymd` and others without an error,
// > the corresponding local date should exist for at least a moment.
// > (It may still have a gap from the offset changes.)
//
// > - The `TimeZone` is free to assign *any* `Offset` to the local date,
// > as long as that offset did occur in given day.
// > For example, if `2015-03-08T01:59-08:00` is followed by `2015-03-08T03:00-07:00`,
// > it may produce either `2015-03-08-08:00` or `2015-03-08-07:00`
// > but *not* `2015-03-08+00:00` and others.
//
// > - Once constructed as a full `DateTime`,
// > `DateTime::date` and other associated methods should return those for the original `Date`.
// > For example, if `dt = tz.ymd(y,m,d).hms(h,n,s)` were valid, `dt.date() == tz.ymd(y,m,d)`.
//
// > - The date is timezone-agnostic up to one day (i.e. practically always),
// > so the local date and UTC date should be equal for most cases
// > even though the raw calculation between `NaiveDate` and `Duration` may not.
//
// For these reasons we return always a single offset here if we can, rather than being
// technically correct and returning Ambiguous(_,_) on days when the clock changes. The
// alternative is painful errors when computing unambiguous times such as
// `TimeZone.ymd(ambiguous_date).hms(unambiguous_time)`.
use chrono::LocalResult::*;
match (earliest, latest) {
(result @ Single(_), _) => result,
(_, result @ Single(_)) => result,
(Ambiguous(offset, _), _) => Single(offset),
(_, Ambiguous(offset, _)) => Single(offset),
(None, None) => None,
}
}
// First search for a timespan that the local datetime falls into, then, if it exists,
// check the two surrounding timespans (if they exist) to see if there is any ambiguity.
fn offset_from_local_datetime(&self, local: &NaiveDateTime) -> LocalResult<Self::Offset> {
let timestamp = local.and_utc().timestamp();
let timespans = self.timespans();
let index = binary_search(0, timespans.len(), |i| {
timespans.local_span(i).cmp(timestamp)
});
TzOffset::map_localresult(
*self,
match index {
Ok(0) if timespans.len() == 1 => LocalResult::Single(timespans.get(0)),
Ok(0) if timespans.local_span(1).contains(timestamp) => {
LocalResult::Ambiguous(timespans.get(0), timespans.get(1))
}
Ok(0) => LocalResult::Single(timespans.get(0)),
Ok(i) if timespans.local_span(i - 1).contains(timestamp) => {
LocalResult::Ambiguous(timespans.get(i - 1), timespans.get(i))
}
Ok(i) if i == timespans.len() - 1 => LocalResult::Single(timespans.get(i)),
Ok(i) if timespans.local_span(i + 1).contains(timestamp) => {
LocalResult::Ambiguous(timespans.get(i), timespans.get(i + 1))
}
Ok(i) => LocalResult::Single(timespans.get(i)),
Err(_) => LocalResult::None,
},
)
}
#[allow(deprecated)]
fn offset_from_utc_date(&self, utc: &NaiveDate) -> Self::Offset {
// See comment above for why it is OK to just take any arbitrary time in the day
self.offset_from_utc_datetime(&utc.and_time(NaiveTime::MIN))
}
// Binary search for the required timespan. Any i64 is guaranteed to fall within
// exactly one timespan, no matter what (so the `unwrap` is safe).
fn offset_from_utc_datetime(&self, dt: &NaiveDateTime) -> Self::Offset {
let timestamp = dt.and_utc().timestamp();
let timespans = self.timespans();
let index =
binary_search(0, timespans.len(), |i| timespans.utc_span(i).cmp(timestamp)).unwrap();
TzOffset::new(*self, timespans.get(index))
}
}
/// Represents the information of a gap.
///
/// This returns useful information that can be used when converting a local [`NaiveDateTime`]
/// to a timezone-aware [`DateTime`] with [`TimeZone::from_local_datetime`] and a gap
/// ([`LocalResult::None`]) is found.
pub struct GapInfo {
/// When available it contains information about the beginning of the gap.
///
/// The time represents the first instant in which the gap starts.
/// This means that it is the first instant that when used with [`TimeZone::from_local_datetime`]
/// it will return [`LocalResult::None`].
///
/// The offset represents the offset of the first instant before the gap.
pub begin: Option<(NaiveDateTime, TzOffset)>,
/// When available it contains the first instant after the gap.
pub end: Option<DateTime<Tz>>,
}
impl GapInfo {
/// Return information about a gap.
///
/// It returns `None` if `local` is not in a gap for the current timezone.
///
/// If `local` is at the limits of the known timestamps the fields `begin` or `end` in
/// [`GapInfo`] will be `None`.
pub fn new(local: &NaiveDateTime, tz: &Tz) -> Option<Self> {
let timestamp = local.and_utc().timestamp();
let timespans = tz.timespans();
let index = binary_search(0, timespans.len(), |i| {
timespans.local_span(i).cmp(timestamp)
});
let Err(end_idx) = index else {
return None;
};
let begin = match end_idx {
0 => None,
_ => {
let start_idx = end_idx - 1;
timespans
.local_span(start_idx)
.end
.and_then(|start_time| DateTime::from_timestamp(start_time, 0))
.map(|start_time| {
(
start_time.naive_local(),
TzOffset::new(*tz, timespans.get(start_idx)),
)
})
}
};
let end = match end_idx {
_ if end_idx >= timespans.len() => None,
_ => {
timespans
.local_span(end_idx)
.begin
.and_then(|end_time| DateTime::from_timestamp(end_time, 0))
.and_then(|date_time| {
// we create the DateTime from a timestamp that exists in the timezone
tz.from_local_datetime(&date_time.naive_local()).single()
})
}
};
Some(Self { begin, end })
}
}
+18
View File
@@ -0,0 +1,18 @@
use std::path::PathBuf;
use std::{env, fs};
#[test]
fn codegen() {
let root = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()).join("src/prebuilt");
let old_directory = fs::read_to_string(root.join("directory.rs")).unwrap();
let old_timezones = fs::read_to_string(root.join("timezones.rs")).unwrap();
fs::create_dir_all(&root).unwrap();
chrono_tz_build::main(&root, false, false);
let new_directory = fs::read_to_string(root.join("directory.rs")).unwrap();
let new_timezones = fs::read_to_string(root.join("timezones.rs")).unwrap();
if old_directory != new_directory || old_timezones != new_timezones {
panic!("prebuilt files changed -- updated");
}
}
+166
View File
@@ -0,0 +1,166 @@
//! Unit tests derived from Tom Scott's video on Numberphile,
//! [`The Problem with Time & Timezones'][video].
//! Note that not all tests are passing; the ones towards
//! the end of the video are not handled correctly (nor are
//! currently intended to be handled correctly) by chrono.
//!
//! [video]: https://www.youtube.com/watch?v=-5wpm-gesOY
use chrono::{DateTime, NaiveDate, TimeZone};
use chrono_tz::Africa::Tripoli;
use chrono_tz::America::New_York;
use chrono_tz::Asia::Gaza;
use chrono_tz::Asia::Jerusalem;
use chrono_tz::Asia::Kathmandu;
use chrono_tz::Australia::Adelaide;
use chrono_tz::Etc::UTC;
use chrono_tz::Europe::London;
use chrono_tz::Europe::Moscow;
use chrono_tz::Pacific::Apia;
fn seconds<Tz1: TimeZone, Tz2: TimeZone>(from: DateTime<Tz1>, to: DateTime<Tz2>) -> i64 {
to.signed_duration_since(from).num_seconds()
}
#[test]
fn london_5_days_ago_to_new_york() {
let from = London.with_ymd_and_hms(2013, 12, 25, 14, 0, 0).unwrap();
let to = New_York.with_ymd_and_hms(2013, 12, 30, 14, 0, 0).unwrap();
assert_eq!(seconds(from, to), 60 * 60 * (24 * 5 + 5));
}
#[test]
fn london_to_australia() {
// at the time Tom was speaking, Adelaide was 10 1/2 hours ahead
// many other parts of Australia use different time zones
let from = London.with_ymd_and_hms(2013, 12, 25, 14, 0, 0).unwrap();
let to = Adelaide.with_ymd_and_hms(2013, 12, 30, 14, 0, 0).unwrap();
assert_eq!(seconds(from, to), 60 * 60 * (24 * 5 - 10) - 60 * 30);
}
#[test]
fn london_to_nepal() {
// note Tom gets this wrong, it's 5 3/4 hours as he is speaking
let from = London.with_ymd_and_hms(2013, 12, 25, 14, 0, 0).unwrap();
let to = Kathmandu.with_ymd_and_hms(2013, 12, 30, 14, 0, 0).unwrap();
assert_eq!(seconds(from, to), 60 * 60 * (24 * 5 - 5) - 60 * 45);
}
#[test]
fn autumn() {
let from = London.with_ymd_and_hms(2013, 10, 25, 12, 0, 0).unwrap();
let to = London.with_ymd_and_hms(2013, 11, 1, 12, 0, 0).unwrap();
assert_eq!(seconds(from, to), 60 * 60 * (24 * 7 + 1));
}
#[test]
fn earlier_daylight_savings_in_new_york() {
let from = New_York.with_ymd_and_hms(2013, 10, 25, 12, 0, 0).unwrap();
let to = New_York.with_ymd_and_hms(2013, 11, 1, 12, 0, 0).unwrap();
assert_eq!(seconds(from, to), 60 * 60 * (24 * 7));
}
#[test]
fn southern_hemisphere_clocks_forward() {
let from = Adelaide.with_ymd_and_hms(2013, 10, 1, 12, 0, 0).unwrap();
let to = Adelaide.with_ymd_and_hms(2013, 11, 1, 12, 0, 0).unwrap();
assert_eq!(seconds(from, to), 60 * 60 * (24 * 31 - 1));
}
#[test]
fn samoa_skips_a_day() {
let from = Apia.with_ymd_and_hms(2011, 12, 29, 12, 0, 0).unwrap();
let to = Apia.with_ymd_and_hms(2011, 12, 31, 12, 0, 0).unwrap();
assert_eq!(seconds(from, to), 60 * 60 * 24);
}
#[test]
fn double_bst() {
let from = London.with_ymd_and_hms(1942, 6, 1, 12, 0, 0).unwrap();
let to = UTC.with_ymd_and_hms(1942, 6, 1, 12, 0, 0).unwrap();
assert_eq!(seconds(from, to), 60 * 60 * 2);
}
#[test]
fn libya_2013() {
// Libya actually put their clocks *forward* in 2013, but not in any other year
let from = Tripoli.with_ymd_and_hms(2012, 3, 1, 12, 0, 0).unwrap();
let to = Tripoli.with_ymd_and_hms(2012, 4, 1, 12, 0, 0).unwrap();
assert_eq!(seconds(from, to), 60 * 60 * 24 * 31);
let from = Tripoli.with_ymd_and_hms(2013, 3, 1, 12, 0, 0).unwrap();
let to = Tripoli.with_ymd_and_hms(2013, 4, 1, 12, 0, 0).unwrap();
assert_eq!(seconds(from, to), 60 * 60 * (24 * 31 - 1));
let from = Tripoli.with_ymd_and_hms(2014, 3, 1, 12, 0, 0).unwrap();
let to = Tripoli.with_ymd_and_hms(2014, 4, 1, 12, 0, 0).unwrap();
assert_eq!(seconds(from, to), 60 * 60 * 24 * 31);
}
#[test]
fn israel_palestine() {
let from = Jerusalem.with_ymd_and_hms(2016, 10, 29, 12, 0, 0).unwrap();
let to = Gaza.with_ymd_and_hms(2016, 10, 29, 12, 0, 0).unwrap();
assert_eq!(seconds(from, to), 60 * 60);
}
// FIXME doesn't currently work!
#[test]
#[ignore]
fn london_julian_to_gregorian() {
let from = London.with_ymd_and_hms(1752, 9, 2, 12, 0, 0).unwrap();
let to = London.with_ymd_and_hms(1752, 9, 14, 12, 0, 0).unwrap();
assert_eq!(seconds(from, to), 60 * 60 * 24);
}
// FIXME doesn't currently work!
#[test]
#[ignore]
fn russian_julian_to_gregorian() {
let from = Moscow.with_ymd_and_hms(1918, 1, 31, 12, 0, 0).unwrap();
let to = Moscow.with_ymd_and_hms(1918, 2, 14, 12, 0, 0).unwrap();
assert_eq!(seconds(from, to), 60 * 60 * 24);
}
// FIXME doesn't currently work!
#[test]
#[ignore]
fn london_25_march() {
let from = London.with_ymd_and_hms(924, 3, 24, 12, 0, 0).unwrap();
let to = London.with_ymd_and_hms(925, 3, 25, 12, 0, 0).unwrap();
assert_eq!(seconds(from, to), 60 * 60 * 24);
}
#[test]
fn leapsecond() {
let from = UTC.with_ymd_and_hms(2016, 6, 30, 23, 59, 59).unwrap();
let leap = NaiveDate::from_ymd_opt(2016, 6, 30)
.unwrap()
.and_hms_milli_opt(23, 59, 59, 1000)
.unwrap();
let to = UTC.from_local_datetime(&leap).unwrap();
assert_eq!(seconds(from, to), 1);
}
// FIXME doesn't currently work!
#[test]
#[ignore]
fn leapsecond_2() {
let from = UTC.with_ymd_and_hms(2016, 6, 30, 23, 59, 59).unwrap();
let to = UTC.with_ymd_and_hms(2016, 7, 1, 0, 0, 0).unwrap();
assert_eq!(seconds(from, to), 2);
}
// FIXME doesn't currently work!
#[test]
#[ignore]
fn leapsecond_3() {
let leap = NaiveDate::from_ymd_opt(2016, 6, 30)
.unwrap()
.and_hms_milli_opt(23, 59, 59, 1000)
.unwrap();
let from = UTC.from_local_datetime(&leap).unwrap();
let to = UTC.with_ymd_and_hms(2016, 7, 1, 0, 0, 0).unwrap();
assert_eq!(seconds(from, to), 1);
}
+38
View File
@@ -0,0 +1,38 @@
use std::fs;
use chrono::{DateTime, Offset, TimeZone};
use chrono_tz::{IANA_TZDB_VERSION, TZ_VARIANTS};
use tzfile::Tz;
#[test]
#[ignore] // Too slow to run by default
fn tzfile() {
let Ok(system_version) = fs::read_to_string("/usr/share/zoneinfo/+VERSION") else {
return;
};
if IANA_TZDB_VERSION != system_version.trim() {
return;
}
for tz in TZ_VARIANTS {
let Ok(file) = Tz::named(tz.name()) else {
continue;
};
println!("{}", tz.name());
for seconds_since_epoch in (0..i32::MAX).step_by(60 * 60) {
let utc_datetime = DateTime::from_timestamp(seconds_since_epoch as i64, 0)
.unwrap()
.naive_utc();
assert_eq!(
(&file).offset_from_utc_datetime(&utc_datetime).fix(),
tz.offset_from_utc_datetime(&utc_datetime).fix(),
"{seconds_since_epoch} {}",
tz.name()
);
}
}
}
+5
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
+364
View File
@@ -0,0 +1,364 @@
# 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
# From Paul Eggert (2023-12-20):
# Transitions from 2021 on are taken from:
# https://www.timeanddate.com/time/zone/antarctica/casey
# retrieved at various dates.
# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Antarctica/Casey 0 - -00 1969
8:00 - %z 2009 Oct 18 2:00
11:00 - %z 2010 Mar 5 2:00
8:00 - %z 2011 Oct 28 2:00
11:00 - %z 2012 Feb 21 17:00u
8:00 - %z 2016 Oct 22
11:00 - %z 2018 Mar 11 4:00
8:00 - %z 2018 Oct 7 4:00
11:00 - %z 2019 Mar 17 3:00
8:00 - %z 2019 Oct 4 3:00
11:00 - %z 2020 Mar 8 3:00
8:00 - %z 2020 Oct 4 0:01
11:00 - %z 2021 Mar 14 0:00
8:00 - %z 2021 Oct 3 0:01
11:00 - %z 2022 Mar 13 0:00
8:00 - %z 2022 Oct 2 0:01
11:00 - %z 2023 Mar 9 3:00
8:00 - %z
Zone Antarctica/Davis 0 - -00 1957 Jan 13
7:00 - %z 1964 Nov
0 - -00 1969 Feb
7:00 - %z 2009 Oct 18 2:00
5:00 - %z 2010 Mar 10 20:00u
7:00 - %z 2011 Oct 28 2:00
5:00 - %z 2012 Feb 21 20:00u
7:00 - %z
Zone Antarctica/Mawson 0 - -00 1954 Feb 13
6:00 - %z 2009 Oct 18 2:00
5:00 - %z
# 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
# https://en.wikipedia.org/wiki/Concordia_Station
# Can use Asia/Singapore, which it has agreed with since inception.
# 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
# From Craig Mundell (1994-12-15):
# http://quest.arc.nasa.gov/antarctica/QA/computers/Directions,Time,ZIP
# Vostok, which is one of the Russian stations, is set on the same
# time as Moscow, Russia.
#
# From Lee Hotz (2001-03-08):
# I queried the folks at Columbia who spent the summer at Vostok and this is
# what they had to say about time there:
# "in the US Camp (East Camp) we have been on New Zealand (McMurdo)
# time, which is 12 hours ahead of GMT. The Russian Station Vostok was
# 6 hours behind that (although only 2 miles away, i.e. 6 hours ahead
# of GMT). This is a time zone I think two hours east of Moscow. The
# natural time zone is in between the two: 8 hours ahead of GMT."
#
# From Paul Eggert (2001-05-04):
# This seems to be hopelessly confusing, so I asked Lee Hotz about it
# in person. He said that some Antarctic locations set their local
# time so that noon is the warmest part of the day, and that this
# changes during the year and does not necessarily correspond to mean
# solar noon. So the Vostok time might have been whatever the clocks
# happened to be during their visit. So we still don't really know what time
# it is at Vostok.
#
# From Zakhary V. Akulov (2023-12-17 22:00:48 +0700):
# ... from December, 18, 2023 00:00 by my decision the local time of
# the Antarctic research base Vostok will correspond to UTC+5.
# (2023-12-19): We constantly interact with Progress base, with company who
# builds new wintering station, with sledge convoys, with aviation - they all
# use UTC+5. Besides, difference between Moscow time is just 2 hours now, not 4.
# (2023-12-19, in response to the question "Has local time at Vostok
# been UTC+6 ever since 1957, or has it changed before?"): No. At least
# since my antarctic career start, 10 years ago, Vostok base has UTC+7.
# (In response to a 2023-12-18 question "from 02:00 to 00:00 today"): This.
#
# From Paul Eggert (2023-12-18):
# For lack of better info, guess Vostok was at +07 from founding through today,
# except when closed.
# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Antarctica/Vostok 0 - -00 1957 Dec 16
7:00 - %z 1994 Feb
0 - -00 1994 Nov
7:00 - %z 2023 Dec 18 2:00
5:00 - %z
# 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 - %z
# 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° 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.
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+331
View File
@@ -0,0 +1,331 @@
# Links and zones 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.
# It also provides a few zone entries for old naming conventions.
# 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 Europe/Brussels CET
Link America/Chicago CST6CDT
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 Europe/Athens EET
Link America/Panama EST
Link America/New_York EST5EDT
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 Europe/Brussels MET
Link America/Phoenix MST
Link America/Denver MST7MDT
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 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 America/Edmonton America/Yellowknife
Link Pacific/Auckland Antarctica/South_Pole
Link Asia/Ulaanbaatar Asia/Choibalsan
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
Link Europe/Lisbon WET
# 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/Honolulu HST
Link America/Los_Angeles PST8PDT
Link Pacific/Guadalcanal Pacific/Ponape #= Pacific/Pohnpei
Link Pacific/Port_Moresby Pacific/Truk #= Pacific/Chuuk
+83
View File
@@ -0,0 +1,83 @@
# 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 proleptic 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.
# There is no "Etc/Unknown" entry, as CLDR says that "Etc/Unknown"
# corresponds to an unknown or invalid time zone, and things would get
# confusing if Etc/Unknown were made valid here.
Zone Etc/GMT-14 14 - %z
Zone Etc/GMT-13 13 - %z
Zone Etc/GMT-12 12 - %z
Zone Etc/GMT-11 11 - %z
Zone Etc/GMT-10 10 - %z
Zone Etc/GMT-9 9 - %z
Zone Etc/GMT-8 8 - %z
Zone Etc/GMT-7 7 - %z
Zone Etc/GMT-6 6 - %z
Zone Etc/GMT-5 5 - %z
Zone Etc/GMT-4 4 - %z
Zone Etc/GMT-3 3 - %z
Zone Etc/GMT-2 2 - %z
Zone Etc/GMT-1 1 - %z
Zone Etc/GMT+1 -1 - %z
Zone Etc/GMT+2 -2 - %z
Zone Etc/GMT+3 -3 - %z
Zone Etc/GMT+4 -4 - %z
Zone Etc/GMT+5 -5 - %z
Zone Etc/GMT+6 -6 - %z
Zone Etc/GMT+7 -7 - %z
Zone Etc/GMT+8 -8 - %z
Zone Etc/GMT+9 -9 - %z
Zone Etc/GMT+10 -10 - %z
Zone Etc/GMT+11 -11 - %z
Zone Etc/GMT+12 -12 - %z
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff