summaryrefslogtreecommitdiffstats
path: root/vendor/chrono
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:57:31 +0000
commitdc0db358abe19481e475e10c32149b53370f1a1c (patch)
treeab8ce99c4b255ce46f99ef402c27916055b899ee /vendor/chrono
parentReleasing progress-linux version 1.71.1+dfsg1-2~progress7.99u1. (diff)
downloadrustc-dc0db358abe19481e475e10c32149b53370f1a1c.tar.xz
rustc-dc0db358abe19481e475e10c32149b53370f1a1c.zip
Merging upstream version 1.72.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/chrono')
-rw-r--r--vendor/chrono/.cargo-checksum.json2
-rw-r--r--vendor/chrono/AUTHORS.txt43
-rw-r--r--vendor/chrono/Cargo.toml17
-rw-r--r--vendor/chrono/README.md85
-rw-r--r--vendor/chrono/benches/chrono.rs2
-rw-r--r--vendor/chrono/clippy.toml1
-rw-r--r--vendor/chrono/src/date.rs27
-rw-r--r--vendor/chrono/src/datetime/mod.rs168
-rw-r--r--vendor/chrono/src/datetime/serde.rs77
-rw-r--r--vendor/chrono/src/datetime/tests.rs71
-rw-r--r--vendor/chrono/src/format/locales.rs16
-rw-r--r--vendor/chrono/src/format/mod.rs25
-rw-r--r--vendor/chrono/src/format/parse.rs71
-rw-r--r--vendor/chrono/src/format/parsed.rs69
-rw-r--r--vendor/chrono/src/format/scan.rs36
-rw-r--r--vendor/chrono/src/format/strftime.rs10
-rw-r--r--vendor/chrono/src/lib.rs105
-rw-r--r--vendor/chrono/src/month.rs67
-rw-r--r--vendor/chrono/src/naive/date.rs281
-rw-r--r--vendor/chrono/src/naive/datetime/mod.rs220
-rw-r--r--vendor/chrono/src/naive/datetime/serde.rs52
-rw-r--r--vendor/chrono/src/naive/datetime/tests.rs10
-rw-r--r--vendor/chrono/src/naive/internals.rs287
-rw-r--r--vendor/chrono/src/naive/isoweek.rs45
-rw-r--r--vendor/chrono/src/naive/time/mod.rs108
-rw-r--r--vendor/chrono/src/offset/fixed.rs33
-rw-r--r--vendor/chrono/src/offset/local/mod.rs177
-rw-r--r--vendor/chrono/src/offset/local/stub.rs236
-rw-r--r--vendor/chrono/src/offset/local/tz_info/mod.rs15
-rw-r--r--vendor/chrono/src/offset/local/tz_info/parser.rs7
-rw-r--r--vendor/chrono/src/offset/local/tz_info/rule.rs15
-rw-r--r--vendor/chrono/src/offset/local/tz_info/timezone.rs19
-rw-r--r--vendor/chrono/src/offset/local/unix.rs52
-rw-r--r--vendor/chrono/src/offset/local/windows.rs346
-rw-r--r--vendor/chrono/src/offset/mod.rs11
-rw-r--r--vendor/chrono/src/offset/utc.rs7
-rw-r--r--vendor/chrono/src/oldtime.rs31
-rw-r--r--vendor/chrono/src/round.rs41
-rw-r--r--vendor/chrono/src/traits.rs4
-rw-r--r--vendor/chrono/src/weekday.rs53
-rw-r--r--vendor/chrono/tests/dateutils.rs68
41 files changed, 1665 insertions, 1345 deletions
diff --git a/vendor/chrono/.cargo-checksum.json b/vendor/chrono/.cargo-checksum.json
index 5d66a6fc4..259fad17d 100644
--- a/vendor/chrono/.cargo-checksum.json
+++ b/vendor/chrono/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"AUTHORS.txt":"8bfaf8f8599111cd6eef4408a55b98ba188611d1bcab0295e5b6a35def1343df","CHANGELOG.md":"1cc518c80946bc676a8c691428abe1cdf5a2e4e210b3cacc264b2efc5489d566","Cargo.toml":"d43fb7f28cbbd4c4e5410fdca9b5d22f8fb6ff8ae880f09038a0fb20c7916a13","LICENSE.txt":"46610329ff0b38effb9cb05979ff1ef761e465fed96b2eaca39e439d00129fd7","Makefile":"1a85008275ee7bf7cc0f0c054b1b393f34a4e614a28ebf3418c9d6b6e53b1b2c","README.md":"9260b662c38f931780e5bf89c837e351dada72affc29cacc9cfea6c558003845","appveyor.yml":"bcfcff73097a37be373e91934294cfea31fbdfe7a4b01a83bcbc64a8a56c3971","benches/chrono.rs":"a18e8f87e80d7e32cc4a1103d7c075b868ff3018eec2a09cc3b4c80e773fa987","benches/serde.rs":"0cebd95c96f0ddf0f7b6ca2d4a4fa307c7ccc691ee5eb090556f89807120eb9f","clippy.toml":"0ee2428866ddc7519d178a46d9073399e28b3c879a9d14658a1e7c5c023c3a7c","deny.toml":"4189fcb1125499ac851c0bd29f3f27a614b28573fa3299f712ee4bdace897dd3","rustfmt.toml":"f74204a6f92aa7422a16ecb2ffe2d5bae0f123b778d08b5db1a398a3c9ca4306","src/date.rs":"4929ac7b68a3d26ae7f94e1b375017a08a3f80581432f69c6e068832377a0ff6","src/datetime/mod.rs":"8eee73e7fe6e903e05b8d39acdb1e835d9163f6e1638d8f0ba74de7ea8ec1fd1","src/datetime/rustc_serialize.rs":"8cef7bba6aec9e75679c78b5544f22be41989c15e253fb739b76fcc4c9ee9fbe","src/datetime/serde.rs":"85d8bd79ded20fe68d7b8b68889c19a9f9dad5af6620885554190365d58967f2","src/datetime/tests.rs":"80c6e770c8dabebfee45ee67ede5a7418bdae24b5de9957bb15ecaca630e7c33","src/format/locales.rs":"8c14cb93c68b747947b74ab2933aae53c8a0edd009ff16815e756015fbea6e9f","src/format/mod.rs":"abf92d8f13683d13167a094add4a2908cb1a2cba0ec6867018e93ce4dbc5df8d","src/format/parse.rs":"74aeac3d34385497901a889f0ed55faea9a489391e9db1055e6bd1af1819d6e8","src/format/parsed.rs":"999fadd3e787b4c69b2f2471247fbfce32951156705bac20170da5aed76c2b98","src/format/scan.rs":"392c12418cd0cc3b570ea68542db9281d01f1ec595e95005d743d9287752e0ff","src/format/strftime.rs":"a10f904e4a86748657f2a8f4fe5fc0f44bf99275311ac8ac50b821208e41e891","src/lib.rs":"935de4f470a6189b92ca4a78ea14b149d3d418fbd4abdfb1b90f84c4bfcfe480","src/month.rs":"198802cc8a6dfd6614842e81729eef2fa9e6f5b2d418bad64e4bb1a49fcd3c21","src/naive/date.rs":"803664c44eef75e2f0bbc8a8174679208146d01fc3da18b1036d6fabd7ca0f46","src/naive/datetime/mod.rs":"ab619388eaa0659934c71fdc06b51fbd0f0250fe0ad6bfd88d6e76b090ab4d1e","src/naive/datetime/rustc_serialize.rs":"50491c855583694f01aed7d577c43dee9adf9bd548377b6707b4d596d887e0b2","src/naive/datetime/serde.rs":"8f677be5ece94f799219b66d018bd9dc82471c2192e2374c9d904ceabf982686","src/naive/datetime/tests.rs":"9bfbe494525fa1c8943c22c985bb9ce358459a97b8939fbdb8540b45fc6c2c8a","src/naive/internals.rs":"c73325b4f63ed221436643ebd58935004f8f76b4aa25a20a0703a2ebfc2a6c12","src/naive/isoweek.rs":"6c34cda15d21bdc095393c1de5bfaefa9611e6c35417aa21af82c4b44b4d6765","src/naive/mod.rs":"743e0ba276a235baa536005108e11597c1ca4ee100ed86e09cbad2216a91939d","src/naive/time/mod.rs":"c8cff488deb75943f02fe73e905fe16cc63cea52c84a6d8a1c5f2c7592338a51","src/naive/time/rustc_serialize.rs":"ce93c81341f35e29ec32a43644fd892a27823643b8ac2f010194824f434180ca","src/naive/time/serde.rs":"a89c1f0d127e89793d8bc1b786996babf02d5aa0a2d859d53a6d3ad02399d9a1","src/naive/time/tests.rs":"b8586903b65c1b050253c04bc9770f7889bfd4db87d02143a2b7fddbecf56dea","src/offset/fixed.rs":"9ac52822a66eac1f7eab92c8c77235573a40a5ca0b58c17e7894df51ae8edaa4","src/offset/local/mod.rs":"7160b6db6efcf06b6604cba363323f741c9dd8b235b2bd062b70eeb19f5d07b6","src/offset/local/stub.rs":"c753e9f45b85834e834191a38802c1105098ae17c56c31c2d99be42c50e6247c","src/offset/local/tz_info/mod.rs":"3488ac6811ea2a39418ff22f0de282ebddba4620dc916595d8b250d50d0bfb20","src/offset/local/tz_info/parser.rs":"47a569bf39eec6121ab9cd69d8fafb679be463d1e919e9d81a7d523667868136","src/offset/local/tz_info/rule.rs":"a88ad07f638ead425ae2dcc1aa76842b44a9f939c9f736cfa6fe2189e2b9f2a5","src/offset/local/tz_info/timezone.rs":"7dee5dd24c5bec63b2e94e3355d3f7e1ed5055771ffb6b70a449bd8f6b22fba8","src/offset/local/unix.rs":"e854d1cb52e9d18c4161ed660b03c62bc8d05418f85c746e2799dd1bdf7ed105","src/offset/local/windows.rs":"edda38f1f78f2392e0e89d01f6f06454ed8f1f269df0505d533107eeed9e713f","src/offset/mod.rs":"f0d486ab04c803a887b6b775e7f50a0b341b050497d3b4df67abc211daaa41f7","src/offset/utc.rs":"e15afd6a7aba6d2706d262f75b6e6b38e4536af0611b077446da04b06f40be6e","src/oldtime.rs":"8a4a0e1c932a04a30aa306bafdaf2457ffdbcd7f735c9b5cc365e56fdcba2ddc","src/round.rs":"3b70e5a88ea00ab2b70307b4b19c9cd1b42a8bf3356f0f63e4bd4696f46f3a84","src/traits.rs":"48d78381164232c13449dbd229b653ad05215ab44c7901fb026da94938d2ec9d","src/weekday.rs":"61891524fb27ad43d751b47dd4c0115b7f6d4ce509801953d03b8e44afd3e31a","tests/dateutils.rs":"eeff9ce9bf705818690af811f8611990eb8c580756b10f4d8c1691517a8ff969","tests/wasm.rs":"026c36013894a2a55794b4510f893eabeae89c2600b578ea428473ad339db333"},"package":"4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b"} \ No newline at end of file
+{"files":{"CHANGELOG.md":"1cc518c80946bc676a8c691428abe1cdf5a2e4e210b3cacc264b2efc5489d566","Cargo.toml":"2fd03d64b57769ecc8cd9d6ae29681eec3ef1b2a52478c0f2c4c3c020240bb3f","LICENSE.txt":"46610329ff0b38effb9cb05979ff1ef761e465fed96b2eaca39e439d00129fd7","Makefile":"1a85008275ee7bf7cc0f0c054b1b393f34a4e614a28ebf3418c9d6b6e53b1b2c","README.md":"25308c06a4e16008c9b1fafd31fea67ba8e61ff6f7b5ec5b919a127d40c4f530","appveyor.yml":"bcfcff73097a37be373e91934294cfea31fbdfe7a4b01a83bcbc64a8a56c3971","benches/chrono.rs":"878752a20e1ef655e45697540bcc610ab08e9a99651fef84cb7154e39a10db9d","benches/serde.rs":"0cebd95c96f0ddf0f7b6ca2d4a4fa307c7ccc691ee5eb090556f89807120eb9f","deny.toml":"4189fcb1125499ac851c0bd29f3f27a614b28573fa3299f712ee4bdace897dd3","rustfmt.toml":"f74204a6f92aa7422a16ecb2ffe2d5bae0f123b778d08b5db1a398a3c9ca4306","src/date.rs":"62bd777c64a6108f8362990dd17219a5721c1044170397214234d2d72145cea2","src/datetime/mod.rs":"0cb9d965e3b7014dbd415f5c1574372e7d71355bdf2daca332b7ae95bdf73bda","src/datetime/rustc_serialize.rs":"8cef7bba6aec9e75679c78b5544f22be41989c15e253fb739b76fcc4c9ee9fbe","src/datetime/serde.rs":"11bc2a04d74566d9bbbd893faa2e27fddc81994e5d5cf8760235e1c32ee50ea3","src/datetime/tests.rs":"b5b75a8738bb5074866fad2372cead4a1e935ff68a7210b9c15b3a806a39a815","src/format/locales.rs":"d24c08f87b98f1f88ea86020f1f55c8c2cefc74a0eb9b3513d820f6e200192d3","src/format/mod.rs":"b93b41021e994a7444382a23749093a535ef1126a88023c021e2fbcfa37a91c8","src/format/parse.rs":"3e8daa91c4bff4f00b52e91ab9166b816b4780c18e6811aec45c19fd6f309bc6","src/format/parsed.rs":"e55129bf34d3f2974c843868b435b87d0b4a418cbb803a6f0bb74844a6a71328","src/format/scan.rs":"057e182001d66d2f0c84dbd41898561b3289bdbc9b39068d4f86fc6ec5a43bdd","src/format/strftime.rs":"3ee6f4d8d9f66b971f111f36e3ecd22e001996e43a63363590d761333dd66998","src/lib.rs":"33a434b25adb6a8bb96db57976dab8cb5a41f4b528a8e283c55013d7efb6cc7d","src/month.rs":"7e7639941aca103bc3b086e2e1d4ba4e1cc9337fac2e6031007a38ecb39faf6d","src/naive/date.rs":"8b9299609b0b3e80b44362f92fe643096859251c265f2b53ae566973e0cbb53a","src/naive/datetime/mod.rs":"3744899f3aba44b2a687ceecd3a59abda7fa5772bf1a86fad7a44bdb476ba1db","src/naive/datetime/rustc_serialize.rs":"50491c855583694f01aed7d577c43dee9adf9bd548377b6707b4d596d887e0b2","src/naive/datetime/serde.rs":"0d0a71231f519fe0e07e4b0ff745e63b6eb3a706e143f143ca3d879353c6645d","src/naive/datetime/tests.rs":"047a67038ab4d9e06d35a9832206460bc8c7fb396ffe3485b74e5884bf62a587","src/naive/internals.rs":"ce83d5847a845eb9e6e6b02c0b92218b76fec71fa40f9865ce906864cced18d1","src/naive/isoweek.rs":"6f18d4b3d1120b8a426a9f82d855e2a4021fac80a6ebcce106f6af1ad12b9fd9","src/naive/mod.rs":"743e0ba276a235baa536005108e11597c1ca4ee100ed86e09cbad2216a91939d","src/naive/time/mod.rs":"3555f9ab4c924c2b88536560d32a4b28b58fdd4d91af1a853497f9f8ba8cd26c","src/naive/time/rustc_serialize.rs":"ce93c81341f35e29ec32a43644fd892a27823643b8ac2f010194824f434180ca","src/naive/time/serde.rs":"a89c1f0d127e89793d8bc1b786996babf02d5aa0a2d859d53a6d3ad02399d9a1","src/naive/time/tests.rs":"b8586903b65c1b050253c04bc9770f7889bfd4db87d02143a2b7fddbecf56dea","src/offset/fixed.rs":"a59c40d7dc741715f4628863a5830efa983d6c7ad49eebcf10f50d5a32b7de22","src/offset/local/mod.rs":"0944133a2e277bdf3e6ca729064a48109f7ba37f0d720c0d12343d6393ca8800","src/offset/local/tz_info/mod.rs":"c8096637c04687ea396e444c25fdf0008e2b9975ab3c173a41dd63ac213c7877","src/offset/local/tz_info/parser.rs":"4e2f34a6e760833392bc7da038721fb5e266eebb8e4b327a8140e2d8504de4ec","src/offset/local/tz_info/rule.rs":"54df6b45c4517e5442c04654a87c3082dc789b48761237449389802b829acab9","src/offset/local/tz_info/timezone.rs":"64a0dda51a2dc2c76ca6944ae69d67c3ab75fa891e53d8a79c54539b0ddb3f10","src/offset/local/unix.rs":"5a03f58cf5e8efb8046308a88f2fcf36dbd295077071398300e7d7c5da1bfdbf","src/offset/local/windows.rs":"9f7f9e6abd2b1efe4c5e9c8c962dccf160fdeea0f7b223efa7d466d4f3630964","src/offset/mod.rs":"9082d9544516ff671d11515f82a7c2e53acae46642ecc36298afe011e70c3906","src/offset/utc.rs":"3855758f6d931bef03afc06fb7f47879601225984a43950ea7a541f34ae9708b","src/oldtime.rs":"b64a301069cf6cc94ef65f5d35aee7e7a785b052fd6a9b22cfd991d88893f8d8","src/round.rs":"ac1ffe7c9ebd06fd9ee2c71815336270dd82f84c74e5d3be3be1fa19e4e2b026","src/traits.rs":"6e9a33e7af1c2f2a098101818f21dd39f61e04b4a6d2f77c7de2a74010f509a5","src/weekday.rs":"1c2c11af3cfa8938b5416dbd004646ac0f16f60247f7a40da02c8845b1828521","tests/dateutils.rs":"d27af7c3b98fda2fbd1cd90dc421c38d19a2241e3fda76c1dbe2130ceee6ed34","tests/wasm.rs":"026c36013894a2a55794b4510f893eabeae89c2600b578ea428473ad339db333"},"package":"ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5"} \ No newline at end of file
diff --git a/vendor/chrono/AUTHORS.txt b/vendor/chrono/AUTHORS.txt
deleted file mode 100644
index caff57915..000000000
--- a/vendor/chrono/AUTHORS.txt
+++ /dev/null
@@ -1,43 +0,0 @@
-Chrono is mainly written by Kang Seonghoon <public+rust@mearie.org>,
-and also the following people (in ascending order):
-
-Alex Mikhalev <alexmikhalevalex@gmail.com>
-Alexander Bulaev <alexbool@yandex-team.ru>
-Ashley Mannix <ashleymannix@live.com.au>
-Ben Boeckel <mathstuf@gmail.com>
-Ben Eills <ben@beneills.com>
-Brandon W Maister <bwm@knewton.com>
-Brandon W Maister <quodlibetor@gmail.com>
-Cecile Tonglet <cecile.tonglet@cecton.com>
-Colin Ray <r.colinray@gmail.com>
-Corey Farwell <coreyf@rwell.org>
-Dan <dan@ebip.co.uk>
-Danilo Bargen <mail@dbrgn.ch>
-David Hewson <dev@daveid.co.uk>
-David Ross <daboross@daboross.net>
-David Tolnay <dtolnay@gmail.com>
-David Willie <david.willie.1@gmail.com>
-Eric Findlay <e.findlay@protonmail.ch>
-Eunchong Yu <kroisse@gmail.com>
-Frans Skarman <frans.skarman@gmail.com>
-Huon Wilson <dbau.pp+github@gmail.com>
-Igor Gnatenko <ignatenko@redhat.com>
-Jake Vossen <jake@vossen.dev>
-Jim Turner <jturner314@gmail.com>
-Jisoo Park <xxxyel@gmail.com>
-Joe Wilm <joe@jwilm.com>
-John Heitmann <jheitmann@gmail.com>
-John Nagle <nagle@sitetruth.com>
-Jonas mg <jonasmg@yepmail.net>
-János Illés <ijanos@gmail.com>
-Ken Tossell <ken@tossell.net>
-Martin Risell Lilja <martin.risell.lilja@gmail.com>
-Richard Petrie <rap1011@ksu.edu>
-Ryan Lewis <ryansname@gmail.com>
-Sergey V. Shadoy <shadoysv@yandex.ru>
-Sergey V. Galtsev <sergey.v.galtsev@github.com>
-Steve Klabnik <steve@steveklabnik.com>
-Tom Gallacher <tomgallacher23@gmail.com>
-klutzy <klutzytheklutzy@gmail.com>
-kud1ing <github@kudling.de>
-Yohan Boogaert <yozhgoor@outlook.com>
diff --git a/vendor/chrono/Cargo.toml b/vendor/chrono/Cargo.toml
index eaf0e6945..7f49bad0b 100644
--- a/vendor/chrono/Cargo.toml
+++ b/vendor/chrono/Cargo.toml
@@ -10,9 +10,10 @@
# See Cargo.toml.orig for the original contents.
[package]
-edition = "2018"
+edition = "2021"
+rust-version = "1.56.0"
name = "chrono"
-version = "0.4.24"
+version = "0.4.26"
exclude = ["/ci/*"]
description = "Date and time library for Rust"
homepage = "https://github.com/chronotope/chrono"
@@ -62,10 +63,6 @@ optional = true
version = "0.4.0"
optional = true
-[dependencies.num-integer]
-version = "0.1.36"
-default-features = false
-
[dependencies.num-traits]
version = "0.2"
default-features = false
@@ -97,10 +94,6 @@ version = "1.3.0"
[dev-dependencies.doc-comment]
version = "0.3"
-[dev-dependencies.num-iter]
-version = "0.1.35"
-default-features = false
-
[dev-dependencies.serde_derive]
version = "1"
default-features = false
@@ -146,6 +139,9 @@ optional = true
[target."cfg(all(target_arch = \"wasm32\", not(any(target_os = \"emscripten\", target_os = \"wasi\"))))".dev-dependencies.wasm-bindgen-test]
version = "0.3"
+[target."cfg(target_os = \"android\")".dependencies.android-tzdata]
+version = "0.1.1"
+
[target."cfg(unix)".dependencies.iana-time-zone]
version = "0.1.45"
features = ["fallback"]
@@ -158,5 +154,6 @@ features = [
"minwinbase",
"minwindef",
"timezoneapi",
+ "sysinfoapi",
]
optional = true
diff --git a/vendor/chrono/README.md b/vendor/chrono/README.md
index ad9591889..639a09144 100644
--- a/vendor/chrono/README.md
+++ b/vendor/chrono/README.md
@@ -1,4 +1,4 @@
-[Chrono][docsrs]: Date and Time for Rust
+[Chrono][docsrs]: Timezone-aware date and time handling
========================================
[![Chrono GitHub Actions][gh-image]][gh-checks]
@@ -15,45 +15,66 @@
[gitter-image]: https://badges.gitter.im/chrono-rs/chrono.svg
[gitter]: https://gitter.im/chrono-rs/chrono
-It aims to be a feature-complete superset of
-the [time](https://github.com/rust-lang-deprecated/time) library.
-In particular,
+Chrono aims to provide all functionality needed to do correct operations on dates and times in the
+[proleptic Gregorian calendar](https://en.wikipedia.org/wiki/Proleptic_Gregorian_calendar):
-* Chrono strictly adheres to ISO 8601.
-* Chrono is timezone-aware by default, with separate timezone-naive types.
-* Chrono is space-optimal and (while not being the primary goal) reasonably efficient.
+* The [`DateTime`](https://docs.rs/chrono/latest/chrono/struct.DateTime.html) type is timezone-aware
+ by default, with separate timezone-naive types.
+* Operations that may produce an invalid or ambiguous date and time return `Option` or
+ [`LocalResult`](https://docs.rs/chrono/latest/chrono/offset/enum.LocalResult.html).
+* Configurable parsing and formatting with an `strftime` inspired date and time formatting syntax.
+* The [`Local`](https://docs.rs/chrono/latest/chrono/offset/struct.Local.html) timezone works with
+ the current timezone of the OS.
+* Types and operations are implemented to be reasonably efficient.
-There were several previous attempts to bring a good date and time library to Rust,
-which Chrono builds upon and should acknowledge:
+Timezone data is not shipped with chrono by default to limit binary sizes. Use the companion crate
+[Chrono-TZ](https://crates.io/crates/chrono-tz) or [`tzfile`](https://crates.io/crates/tzfile) for
+full timezone support.
-* [Initial research on
- the wiki](https://github.com/rust-lang/rust-wiki-backup/blob/master/Lib-datetime.md)
-* Dietrich Epp's [datetime-rs](https://github.com/depp/datetime-rs)
-* Luis de Bethencourt's [rust-datetime](https://github.com/luisbg/rust-datetime)
+## Documentation
+
+See [docs.rs](https://docs.rs/chrono/latest/chrono/) for the API reference.
## Limitations
-Only proleptic Gregorian calendar (i.e. extended to support older dates) is supported.
-Be very careful if you really have to deal with pre-20C dates, they can be in Julian or others.
+* Only the proleptic Gregorian calendar (i.e. extended to support older dates) is supported.
+* Date types are limited to about +/- 262,000 years from the common epoch.
+* Time types are limited to nanosecond accuracy.
+* Leap seconds can be represented, but Chrono does not fully support them.
+ See [Leap Second Handling](https://docs.rs/chrono/latest/chrono/naive/struct.NaiveTime.html#leap-second-handling).
+
+## Crate features
+
+Default features:
+
+* `alloc`: Enable features that depend on allocation (primarily string formatting)
+* `std`: Enables functionality that depends on the standard library. This is a superset of `alloc`
+ and adds interoperation with standard library types and traits.
+* `clock`: Enables reading the system time (`now`) and local timezone (`Local`).
+* `wasmbind`: Interface with the JS Date API for the `wasm32` target.
+
+Optional features:
+
+* `serde`: Enable serialization/deserialization via serde.
+* `rkyv`: Enable serialization/deserialization via rkyv.
+* `rustc-serialize`: Enable serialization/deserialization via rustc-serialize (deprecated).
+* `old_time`: compatability with the `Duration` type of the `time` 0.1 crate (deprecated).
+* `arbitrary`: construct arbitrary instances of a type with the Arbitrary crate.
+* `unstable-locales`: Enable localization. This adds various methods with a `_localized` suffix.
+ The implementation and API may change or even be removed in a patch release. Feedback welcome.
+
+## Rust version requirements
+
+The Minimum Supported Rust Version (MSRV) is currently **Rust 1.56.0**.
-Date types are limited in about +/- 262,000 years from the common epoch.
-Time types are limited in the nanosecond accuracy.
+The MSRV is explicitly tested in CI. It may be bumped in minor releases, but this is not done
+lightly.
-[Leap seconds are supported in the representation but
-Chrono doesn't try to make use of them](https://docs.rs/chrono/0.4/chrono/naive/struct.NaiveTime.html#leap-second-handling).
-(The main reason is that leap seconds are not really predictable.)
-Almost *every* operation over the possible leap seconds will ignore them.
-Consider using `NaiveDateTime` with the implicit TAI (International Atomic Time) scale
-if you want.
+## License
-Chrono inherently does not support an inaccurate or partial date and time representation.
-Any operation that can be ambiguous will return `None` in such cases.
-For example, "a month later" of 2014-01-30 is not well-defined
-and consequently `Utc.ymd_opt(2014, 1, 30).unwrap().with_month(2)` returns `None`.
+This project is licensed under either of
-Non ISO week handling is not yet supported.
-For now you can use the [chrono_ext](https://crates.io/crates/chrono_ext)
-crate ([sources](https://github.com/bcourtine/chrono-ext/)).
+* [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0)
+* [MIT License](https://opensource.org/licenses/MIT)
-Advanced time zone handling is not yet supported.
-For now you can try the [Chrono-tz](https://github.com/chronotope/chrono-tz/) crate instead.
+at your option.
diff --git a/vendor/chrono/benches/chrono.rs b/vendor/chrono/benches/chrono.rs
index 246271b81..216616b82 100644
--- a/vendor/chrono/benches/chrono.rs
+++ b/vendor/chrono/benches/chrono.rs
@@ -64,7 +64,7 @@ fn bench_year_flags_from_year(c: &mut Criterion) {
c.bench_function("bench_year_flags_from_year", |b| {
b.iter(|| {
for year in -999i32..1000 {
- __BenchYearFlags::from_year(year);
+ let _ = __BenchYearFlags::from_year(black_box(year));
}
})
});
diff --git a/vendor/chrono/clippy.toml b/vendor/chrono/clippy.toml
deleted file mode 100644
index 749c3b58a..000000000
--- a/vendor/chrono/clippy.toml
+++ /dev/null
@@ -1 +0,0 @@
-msrv = "1.38"
diff --git a/vendor/chrono/src/date.rs b/vendor/chrono/src/date.rs
index bad4bfbb8..962555651 100644
--- a/vendor/chrono/src/date.rs
+++ b/vendor/chrono/src/date.rs
@@ -77,6 +77,7 @@ impl<Tz: TimeZone> Date<Tz> {
//
// note: this constructor is purposely not named to `new` to discourage the direct usage.
#[inline]
+ #[must_use]
pub fn from_utc(date: NaiveDate, offset: Tz::Offset) -> Date<Tz> {
Date { date, offset }
}
@@ -86,6 +87,7 @@ impl<Tz: TimeZone> Date<Tz> {
///
/// Panics on invalid datetime.
#[inline]
+ #[must_use]
pub fn and_time(&self, time: NaiveTime) -> Option<DateTime<Tz>> {
let localdt = self.naive_local().and_time(time);
self.timezone().from_local_datetime(&localdt).single()
@@ -97,6 +99,7 @@ impl<Tz: TimeZone> Date<Tz> {
/// Panics on invalid hour, minute and/or second.
#[deprecated(since = "0.4.23", note = "Use and_hms_opt() instead")]
#[inline]
+ #[must_use]
pub fn and_hms(&self, hour: u32, min: u32, sec: u32) -> DateTime<Tz> {
self.and_hms_opt(hour, min, sec).expect("invalid time")
}
@@ -106,6 +109,7 @@ impl<Tz: TimeZone> Date<Tz> {
///
/// Returns `None` on invalid hour, minute and/or second.
#[inline]
+ #[must_use]
pub fn and_hms_opt(&self, hour: u32, min: u32, sec: u32) -> Option<DateTime<Tz>> {
NaiveTime::from_hms_opt(hour, min, sec).and_then(|time| self.and_time(time))
}
@@ -117,6 +121,7 @@ impl<Tz: TimeZone> Date<Tz> {
/// Panics on invalid hour, minute, second and/or millisecond.
#[deprecated(since = "0.4.23", note = "Use and_hms_milli_opt() instead")]
#[inline]
+ #[must_use]
pub fn and_hms_milli(&self, hour: u32, min: u32, sec: u32, milli: u32) -> DateTime<Tz> {
self.and_hms_milli_opt(hour, min, sec, milli).expect("invalid time")
}
@@ -127,6 +132,7 @@ impl<Tz: TimeZone> Date<Tz> {
///
/// Returns `None` on invalid hour, minute, second and/or millisecond.
#[inline]
+ #[must_use]
pub fn and_hms_milli_opt(
&self,
hour: u32,
@@ -144,6 +150,7 @@ impl<Tz: TimeZone> Date<Tz> {
/// Panics on invalid hour, minute, second and/or microsecond.
#[deprecated(since = "0.4.23", note = "Use and_hms_micro_opt() instead")]
#[inline]
+ #[must_use]
pub fn and_hms_micro(&self, hour: u32, min: u32, sec: u32, micro: u32) -> DateTime<Tz> {
self.and_hms_micro_opt(hour, min, sec, micro).expect("invalid time")
}
@@ -154,6 +161,7 @@ impl<Tz: TimeZone> Date<Tz> {
///
/// Returns `None` on invalid hour, minute, second and/or microsecond.
#[inline]
+ #[must_use]
pub fn and_hms_micro_opt(
&self,
hour: u32,
@@ -171,6 +179,7 @@ impl<Tz: TimeZone> Date<Tz> {
/// Panics on invalid hour, minute, second and/or nanosecond.
#[deprecated(since = "0.4.23", note = "Use and_hms_nano_opt() instead")]
#[inline]
+ #[must_use]
pub fn and_hms_nano(&self, hour: u32, min: u32, sec: u32, nano: u32) -> DateTime<Tz> {
self.and_hms_nano_opt(hour, min, sec, nano).expect("invalid time")
}
@@ -181,6 +190,7 @@ impl<Tz: TimeZone> Date<Tz> {
///
/// Returns `None` on invalid hour, minute, second and/or nanosecond.
#[inline]
+ #[must_use]
pub fn and_hms_nano_opt(
&self,
hour: u32,
@@ -196,6 +206,7 @@ impl<Tz: TimeZone> Date<Tz> {
/// Panics when `self` is the last representable date.
#[deprecated(since = "0.4.23", note = "Use succ_opt() instead")]
#[inline]
+ #[must_use]
pub fn succ(&self) -> Date<Tz> {
self.succ_opt().expect("out of bound")
}
@@ -204,6 +215,7 @@ impl<Tz: TimeZone> Date<Tz> {
///
/// Returns `None` when `self` is the last representable date.
#[inline]
+ #[must_use]
pub fn succ_opt(&self) -> Option<Date<Tz>> {
self.date.succ_opt().map(|date| Date::from_utc(date, self.offset.clone()))
}
@@ -213,6 +225,7 @@ impl<Tz: TimeZone> Date<Tz> {
/// Panics when `self` is the first representable date.
#[deprecated(since = "0.4.23", note = "Use pred_opt() instead")]
#[inline]
+ #[must_use]
pub fn pred(&self) -> Date<Tz> {
self.pred_opt().expect("out of bound")
}
@@ -221,18 +234,21 @@ impl<Tz: TimeZone> Date<Tz> {
///
/// Returns `None` when `self` is the first representable date.
#[inline]
+ #[must_use]
pub fn pred_opt(&self) -> Option<Date<Tz>> {
self.date.pred_opt().map(|date| Date::from_utc(date, self.offset.clone()))
}
/// Retrieves an associated offset from UTC.
#[inline]
+ #[must_use]
pub fn offset(&self) -> &Tz::Offset {
&self.offset
}
/// Retrieves an associated time zone.
#[inline]
+ #[must_use]
pub fn timezone(&self) -> Tz {
TimeZone::from_offset(&self.offset)
}
@@ -240,6 +256,7 @@ impl<Tz: TimeZone> Date<Tz> {
/// Changes the associated time zone.
/// This does not change the actual `Date` (but will change the string representation).
#[inline]
+ #[must_use]
pub fn with_timezone<Tz2: TimeZone>(&self, tz: &Tz2) -> Date<Tz2> {
tz.from_utc_date(&self.date)
}
@@ -248,6 +265,7 @@ impl<Tz: TimeZone> Date<Tz> {
///
/// Returns `None` when it will result in overflow.
#[inline]
+ #[must_use]
pub fn checked_add_signed(self, rhs: OldDuration) -> Option<Date<Tz>> {
let date = self.date.checked_add_signed(rhs)?;
Some(Date { date, offset: self.offset })
@@ -257,6 +275,7 @@ impl<Tz: TimeZone> Date<Tz> {
///
/// Returns `None` when it will result in overflow.
#[inline]
+ #[must_use]
pub fn checked_sub_signed(self, rhs: OldDuration) -> Option<Date<Tz>> {
let date = self.date.checked_sub_signed(rhs)?;
Some(Date { date, offset: self.offset })
@@ -268,12 +287,14 @@ impl<Tz: TimeZone> Date<Tz> {
/// This does not overflow or underflow at all,
/// as all possible output fits in the range of `Duration`.
#[inline]
+ #[must_use]
pub fn signed_duration_since<Tz2: TimeZone>(self, rhs: Date<Tz2>) -> OldDuration {
self.date.signed_duration_since(rhs.date)
}
/// Returns a view to the naive UTC date.
#[inline]
+ #[must_use]
pub fn naive_utc(&self) -> NaiveDate {
self.date
}
@@ -284,11 +305,13 @@ impl<Tz: TimeZone> Date<Tz> {
/// because the offset is restricted to never exceed one day,
/// but provided for the consistency.
#[inline]
+ #[must_use]
pub fn naive_local(&self) -> NaiveDate {
self.date
}
/// Returns the number of whole years from the given `base` until `self`.
+ #[must_use]
pub fn years_since(&self, base: Self) -> Option<u32> {
self.date.years_since(base.date)
}
@@ -315,6 +338,7 @@ where
#[cfg(any(feature = "alloc", feature = "std", test))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "alloc", feature = "std"))))]
#[inline]
+ #[must_use]
pub fn format_with_items<'a, I, B>(&self, items: I) -> DelayedFormat<I>
where
I: Iterator<Item = B> + Clone,
@@ -329,6 +353,7 @@ where
#[cfg(any(feature = "alloc", feature = "std", test))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "alloc", feature = "std"))))]
#[inline]
+ #[must_use]
pub fn format<'a>(&self, fmt: &'a str) -> DelayedFormat<StrftimeItems<'a>> {
self.format_with_items(StrftimeItems::new(fmt))
}
@@ -337,6 +362,7 @@ where
#[cfg(feature = "unstable-locales")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable-locales")))]
#[inline]
+ #[must_use]
pub fn format_localized_with_items<'a, I, B>(
&self,
items: I,
@@ -361,6 +387,7 @@ where
#[cfg(feature = "unstable-locales")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable-locales")))]
#[inline]
+ #[must_use]
pub fn format_localized<'a>(
&self,
fmt: &'a str,
diff --git a/vendor/chrono/src/datetime/mod.rs b/vendor/chrono/src/datetime/mod.rs
index 38416cb6f..65a39aa8d 100644
--- a/vendor/chrono/src/datetime/mod.rs
+++ b/vendor/chrono/src/datetime/mod.rs
@@ -23,7 +23,7 @@ use std::time::{SystemTime, UNIX_EPOCH};
use crate::format::DelayedFormat;
#[cfg(feature = "unstable-locales")]
use crate::format::Locale;
-use crate::format::{parse, ParseError, ParseResult, Parsed, StrftimeItems};
+use crate::format::{parse, parse_and_remainder, ParseError, ParseResult, Parsed, StrftimeItems};
use crate::format::{Fixed, Item};
use crate::naive::{Days, IsoWeek, NaiveDate, NaiveDateTime, NaiveTime};
#[cfg(feature = "clock")]
@@ -113,6 +113,7 @@ impl<Tz: TimeZone> DateTime<Tz> {
//
// note: this constructor is purposely not named to `new` to discourage the direct usage.
#[inline]
+ #[must_use]
pub fn from_utc(datetime: NaiveDateTime, offset: Tz::Offset) -> DateTime<Tz> {
DateTime { datetime, offset }
}
@@ -142,6 +143,7 @@ impl<Tz: TimeZone> DateTime<Tz> {
/// assert_eq!(datetime_west, datetime_utc.with_timezone(&timezone_west));
/// ```
#[inline]
+ #[must_use]
pub fn from_local(datetime: NaiveDateTime, offset: Tz::Offset) -> DateTime<Tz> {
let datetime_utc = datetime - offset.fix();
@@ -156,6 +158,7 @@ impl<Tz: TimeZone> DateTime<Tz> {
#[inline]
#[deprecated(since = "0.4.23", note = "Use `date_naive()` instead")]
#[allow(deprecated)]
+ #[must_use]
pub fn date(&self) -> Date<Tz> {
Date::from_utc(self.naive_local().date(), self.offset.clone())
}
@@ -173,6 +176,7 @@ impl<Tz: TimeZone> DateTime<Tz> {
/// assert_eq!(date.date_naive(), other.date_naive());
/// ```
#[inline]
+ #[must_use]
pub fn date_naive(&self) -> NaiveDate {
let local = self.naive_local();
NaiveDate::from_ymd_opt(local.year(), local.month(), local.day()).unwrap()
@@ -181,6 +185,7 @@ impl<Tz: TimeZone> DateTime<Tz> {
/// Retrieves a time component.
/// Unlike `date`, this is not associated to the time zone.
#[inline]
+ #[must_use]
pub fn time(&self) -> NaiveTime {
self.datetime.time() + self.offset.fix()
}
@@ -188,6 +193,7 @@ impl<Tz: TimeZone> DateTime<Tz> {
/// Returns the number of non-leap seconds since January 1, 1970 0:00:00 UTC
/// (aka "UNIX timestamp").
#[inline]
+ #[must_use]
pub fn timestamp(&self) -> i64 {
self.datetime.timestamp()
}
@@ -202,7 +208,7 @@ impl<Tz: TimeZone> DateTime<Tz> {
/// # Example
///
/// ```
- /// use chrono::{Utc, TimeZone, NaiveDate};
+ /// use chrono::{Utc, NaiveDate};
///
/// let dt = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap().and_hms_milli_opt(0, 0, 1, 444).unwrap().and_local_timezone(Utc).unwrap();
/// assert_eq!(dt.timestamp_millis(), 1_444);
@@ -211,6 +217,7 @@ impl<Tz: TimeZone> DateTime<Tz> {
/// assert_eq!(dt.timestamp_millis(), 1_000_000_000_555);
/// ```
#[inline]
+ #[must_use]
pub fn timestamp_millis(&self) -> i64 {
self.datetime.timestamp_millis()
}
@@ -225,7 +232,7 @@ impl<Tz: TimeZone> DateTime<Tz> {
/// # Example
///
/// ```
- /// use chrono::{Utc, TimeZone, NaiveDate};
+ /// use chrono::{Utc, NaiveDate};
///
/// let dt = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap().and_hms_micro_opt(0, 0, 1, 444).unwrap().and_local_timezone(Utc).unwrap();
/// assert_eq!(dt.timestamp_micros(), 1_000_444);
@@ -234,6 +241,7 @@ impl<Tz: TimeZone> DateTime<Tz> {
/// assert_eq!(dt.timestamp_micros(), 1_000_000_000_000_555);
/// ```
#[inline]
+ #[must_use]
pub fn timestamp_micros(&self) -> i64 {
self.datetime.timestamp_micros()
}
@@ -248,7 +256,7 @@ impl<Tz: TimeZone> DateTime<Tz> {
/// # Example
///
/// ```
- /// use chrono::{Utc, TimeZone, NaiveDate};
+ /// use chrono::{Utc, NaiveDate};
///
/// let dt = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap().and_hms_nano_opt(0, 0, 1, 444).unwrap().and_local_timezone(Utc).unwrap();
/// assert_eq!(dt.timestamp_nanos(), 1_000_000_444);
@@ -257,6 +265,7 @@ impl<Tz: TimeZone> DateTime<Tz> {
/// assert_eq!(dt.timestamp_nanos(), 1_000_000_000_000_000_555);
/// ```
#[inline]
+ #[must_use]
pub fn timestamp_nanos(&self) -> i64 {
self.datetime.timestamp_nanos()
}
@@ -267,6 +276,7 @@ impl<Tz: TimeZone> DateTime<Tz> {
///
/// note: this is not the number of milliseconds since January 1, 1970 0:00:00 UTC
#[inline]
+ #[must_use]
pub fn timestamp_subsec_millis(&self) -> u32 {
self.datetime.timestamp_subsec_millis()
}
@@ -277,6 +287,7 @@ impl<Tz: TimeZone> DateTime<Tz> {
///
/// note: this is not the number of microseconds since January 1, 1970 0:00:00 UTC
#[inline]
+ #[must_use]
pub fn timestamp_subsec_micros(&self) -> u32 {
self.datetime.timestamp_subsec_micros()
}
@@ -287,18 +298,21 @@ impl<Tz: TimeZone> DateTime<Tz> {
///
/// note: this is not the number of nanoseconds since January 1, 1970 0:00:00 UTC
#[inline]
+ #[must_use]
pub fn timestamp_subsec_nanos(&self) -> u32 {
self.datetime.timestamp_subsec_nanos()
}
/// Retrieves an associated offset from UTC.
#[inline]
+ #[must_use]
pub fn offset(&self) -> &Tz::Offset {
&self.offset
}
/// Retrieves an associated time zone.
#[inline]
+ #[must_use]
pub fn timezone(&self) -> Tz {
TimeZone::from_offset(&self.offset)
}
@@ -306,14 +320,24 @@ impl<Tz: TimeZone> DateTime<Tz> {
/// Changes the associated time zone.
/// The returned `DateTime` references the same instant of time from the perspective of the provided time zone.
#[inline]
+ #[must_use]
pub fn with_timezone<Tz2: TimeZone>(&self, tz: &Tz2) -> DateTime<Tz2> {
tz.from_utc_datetime(&self.datetime)
}
+ /// Fix the offset from UTC to its current value, dropping the associated timezone information.
+ /// This it useful for converting a generic `DateTime<Tz: Timezone>` to `DateTime<FixedOffset>`.
+ #[inline]
+ #[must_use]
+ pub fn fixed_offset(&self) -> DateTime<FixedOffset> {
+ self.with_timezone(&self.offset().fix())
+ }
+
/// Adds given `Duration` to the current date and time.
///
/// Returns `None` when it will result in overflow.
#[inline]
+ #[must_use]
pub fn checked_add_signed(self, rhs: OldDuration) -> Option<DateTime<Tz>> {
let datetime = self.datetime.checked_add_signed(rhs)?;
let tz = self.timezone();
@@ -326,6 +350,7 @@ impl<Tz: TimeZone> DateTime<Tz> {
/// local time is not valid on the newly calculated date.
///
/// See [`NaiveDate::checked_add_months`] for more details on behavior
+ #[must_use]
pub fn checked_add_months(self, rhs: Months) -> Option<DateTime<Tz>> {
self.naive_local()
.checked_add_months(rhs)?
@@ -337,6 +362,7 @@ impl<Tz: TimeZone> DateTime<Tz> {
///
/// Returns `None` when it will result in overflow.
#[inline]
+ #[must_use]
pub fn checked_sub_signed(self, rhs: OldDuration) -> Option<DateTime<Tz>> {
let datetime = self.datetime.checked_sub_signed(rhs)?;
let tz = self.timezone();
@@ -349,6 +375,7 @@ impl<Tz: TimeZone> DateTime<Tz> {
/// local time is not valid on the newly calculated date.
///
/// See [`NaiveDate::checked_sub_months`] for more details on behavior
+ #[must_use]
pub fn checked_sub_months(self, rhs: Months) -> Option<DateTime<Tz>> {
self.naive_local()
.checked_sub_months(rhs)?
@@ -359,6 +386,7 @@ impl<Tz: TimeZone> DateTime<Tz> {
/// Add a duration in [`Days`] to the date part of the `DateTime`
///
/// Returns `None` if the resulting date would be out of range.
+ #[must_use]
pub fn checked_add_days(self, days: Days) -> Option<Self> {
self.naive_local()
.checked_add_days(days)?
@@ -369,6 +397,7 @@ impl<Tz: TimeZone> DateTime<Tz> {
/// Subtract a duration in [`Days`] from the date part of the `DateTime`
///
/// Returns `None` if the resulting date would be out of range.
+ #[must_use]
pub fn checked_sub_days(self, days: Days) -> Option<Self> {
self.naive_local()
.checked_sub_days(days)?
@@ -379,23 +408,27 @@ impl<Tz: TimeZone> DateTime<Tz> {
/// Subtracts another `DateTime` from the current date and time.
/// This does not overflow or underflow at all.
#[inline]
+ #[must_use]
pub fn signed_duration_since<Tz2: TimeZone>(self, rhs: DateTime<Tz2>) -> OldDuration {
self.datetime.signed_duration_since(rhs.datetime)
}
/// Returns a view to the naive UTC datetime.
#[inline]
+ #[must_use]
pub fn naive_utc(&self) -> NaiveDateTime {
self.datetime
}
/// Returns a view to the naive local datetime.
#[inline]
+ #[must_use]
pub fn naive_local(&self) -> NaiveDateTime {
self.datetime + self.offset.fix()
}
/// Retrieve the elapsed years from now to the given [`DateTime`].
+ #[must_use]
pub fn years_since(&self, base: Self) -> Option<u32> {
let mut years = self.year() - base.year();
let earlier_time =
@@ -504,10 +537,9 @@ impl From<DateTime<Local>> for DateTime<Utc> {
impl From<DateTime<Local>> for DateTime<FixedOffset> {
/// Convert this `DateTime<Local>` instance into a `DateTime<FixedOffset>` instance.
///
- /// Conversion is performed via [`DateTime::with_timezone`]. Note that the converted value returned
- /// by this will be created with a fixed timezone offset of 0.
+ /// Conversion is performed via [`DateTime::with_timezone`].
fn from(src: DateTime<Local>) -> Self {
- src.with_timezone(&FixedOffset::east_opt(0).unwrap())
+ src.with_timezone(&src.offset().fix())
}
}
@@ -520,14 +552,16 @@ where
}
impl DateTime<FixedOffset> {
- /// Parses an RFC 2822 date and time string such as `Tue, 1 Jul 2003 10:52:37 +0200`,
- /// then returns a new [`DateTime`] with a parsed [`FixedOffset`].
+ /// Parses an RFC 2822 date-and-time string into a `DateTime<FixedOffset>` value.
///
- /// RFC 2822 is the internet message standard that specifies the
- /// representation of times in HTTP and email headers.
+ /// This parses valid RFC 2822 datetime strings (such as `Tue, 1 Jul 2003 10:52:37 +0200`)
+ /// and returns a new [`DateTime`] instance with the parsed timezone as the [`FixedOffset`].
+ ///
+ /// RFC 2822 is the internet message standard that specifies the representation of times in HTTP
+ /// and email headers.
///
/// ```
- /// # use chrono::{DateTime, FixedOffset, TimeZone, NaiveDate};
+ /// # use chrono::{DateTime, FixedOffset, TimeZone};
/// assert_eq!(
/// DateTime::parse_from_rfc2822("Wed, 18 Feb 2015 23:16:09 GMT").unwrap(),
/// FixedOffset::east_opt(0).unwrap().with_ymd_and_hms(2015, 2, 18, 23, 16, 9).unwrap()
@@ -540,11 +574,19 @@ impl DateTime<FixedOffset> {
parsed.to_datetime()
}
- /// Parses an RFC 3339 and ISO 8601 date and time string such as `1996-12-19T16:39:57-08:00`,
- /// then returns a new [`DateTime`] with a parsed [`FixedOffset`].
+ /// Parses an RFC 3339 date-and-time string into a `DateTime<FixedOffset>` value.
+ ///
+ /// Parses all valid RFC 3339 values (as well as the subset of valid ISO 8601 values that are
+ /// also valid RFC 3339 date-and-time values) and returns a new [`DateTime`] with a
+ /// [`FixedOffset`] corresponding to the parsed timezone. While RFC 3339 values come in a wide
+ /// variety of shapes and sizes, `1996-12-19T16:39:57-08:00` is an example of the most commonly
+ /// encountered variety of RFC 3339 formats.
///
- /// Why isn't this named `parse_from_iso8601`? That's because ISO 8601 allows some freedom
- /// over the syntax and RFC 3339 exercises that freedom to rigidly define a fixed format.
+ /// Why isn't this named `parse_from_iso8601`? That's because ISO 8601 allows representing
+ /// values in a wide range of formats, only some of which represent actual date-and-time
+ /// instances (rather than periods, ranges, dates, or times). Some valid ISO 8601 values are
+ /// also simultaneously valid RFC 3339 values, but not all RFC 3339 values are valid ISO 8601
+ /// values (or the other way around).
pub fn parse_from_rfc3339(s: &str) -> ParseResult<DateTime<FixedOffset>> {
const ITEMS: &[Item<'static>] = &[Item::Fixed(Fixed::RFC3339)];
let mut parsed = Parsed::new();
@@ -552,18 +594,15 @@ impl DateTime<FixedOffset> {
parsed.to_datetime()
}
- /// Parses a string with the specified format string and returns a new
- /// [`DateTime`] with a parsed [`FixedOffset`].
+ /// Parses a string from a user-specified format into a `DateTime<FixedOffset>` value.
///
- /// See the [`crate::format::strftime`] module on the supported escape
- /// sequences.
- ///
- /// See also [`TimeZone::datetime_from_str`] which gives a local
- /// [`DateTime`] on specific time zone.
+ /// Note that this method *requires a timezone* in the input string. See
+ /// [`NaiveDateTime::parse_from_str`](./naive/struct.NaiveDateTime.html#method.parse_from_str)
+ /// for a version that does not require a timezone in the to-be-parsed str. The returned
+ /// [`DateTime`] value will have a [`FixedOffset`] reflecting the parsed timezone.
///
- /// Note that this method *requires a timezone* in the string. See
- /// [`NaiveDateTime::parse_from_str`]
- /// for a version that does not require a timezone in the to-be-parsed str.
+ /// See the [`format::strftime` module](./format/strftime/index.html) for supported format
+ /// sequences.
///
/// # Example
///
@@ -579,6 +618,40 @@ impl DateTime<FixedOffset> {
parse(&mut parsed, s, StrftimeItems::new(fmt))?;
parsed.to_datetime()
}
+
+ /// Parses a string from a user-specified format into a `DateTime<FixedOffset>` value, and a
+ /// slice with the remaining portion of the string.
+ ///
+ /// Note that this method *requires a timezone* in the input string. See
+ /// [`NaiveDateTime::parse_and_remainder`] for a version that does not
+ /// require a timezone in `s`. The returned [`DateTime`] value will have a [`FixedOffset`]
+ /// reflecting the parsed timezone.
+ ///
+ /// See the [`format::strftime` module](./format/strftime/index.html) for supported format
+ /// sequences.
+ ///
+ /// Similar to [`parse_from_str`](#method.parse_from_str).
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// # use chrono::{DateTime, FixedOffset, TimeZone};
+ /// let (datetime, remainder) = DateTime::parse_and_remainder(
+ /// "2015-02-18 23:16:09 +0200 trailing text", "%Y-%m-%d %H:%M:%S %z").unwrap();
+ /// assert_eq!(
+ /// datetime,
+ /// FixedOffset::east_opt(2*3600).unwrap().with_ymd_and_hms(2015, 2, 18, 23, 16, 9).unwrap()
+ /// );
+ /// assert_eq!(remainder, " trailing text");
+ /// ```
+ pub fn parse_and_remainder<'a>(
+ s: &'a str,
+ fmt: &str,
+ ) -> ParseResult<(DateTime<FixedOffset>, &'a str)> {
+ let mut parsed = Parsed::new();
+ let remainder = parse_and_remainder(&mut parsed, s, StrftimeItems::new(fmt))?;
+ parsed.to_datetime().map(|d| (d, remainder))
+ }
}
impl<Tz: TimeZone> DateTime<Tz>
@@ -588,6 +661,7 @@ where
/// Returns an RFC 2822 date and time string such as `Tue, 1 Jul 2003 10:52:37 +0200`.
#[cfg(any(feature = "alloc", feature = "std", test))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "alloc", feature = "std"))))]
+ #[must_use]
pub fn to_rfc2822(&self) -> String {
let mut result = String::with_capacity(32);
crate::format::write_rfc2822(&mut result, self.naive_local(), self.offset.fix())
@@ -598,6 +672,7 @@ where
/// Returns an RFC 3339 and ISO 8601 date and time string such as `1996-12-19T16:39:57-08:00`.
#[cfg(any(feature = "alloc", feature = "std", test))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "alloc", feature = "std"))))]
+ #[must_use]
pub fn to_rfc3339(&self) -> String {
let mut result = String::with_capacity(32);
crate::format::write_rfc3339(&mut result, self.naive_local(), self.offset.fix())
@@ -606,16 +681,16 @@ where
}
/// Return an RFC 3339 and ISO 8601 date and time string with subseconds
- /// formatted as per a `SecondsFormat`.
+ /// formatted as per `SecondsFormat`.
///
- /// If passed `use_z` true and the timezone is UTC (offset 0), use 'Z', as
- /// per [`Fixed::TimezoneOffsetColonZ`] If passed `use_z` false, use
+ /// If `use_z` is true and the timezone is UTC (offset 0), uses `Z` as
+ /// per [`Fixed::TimezoneOffsetColonZ`]. If `use_z` is false, uses
/// [`Fixed::TimezoneOffsetColon`]
///
/// # Examples
///
/// ```rust
- /// # use chrono::{DateTime, FixedOffset, SecondsFormat, TimeZone, Utc, NaiveDate};
+ /// # use chrono::{FixedOffset, SecondsFormat, TimeZone, Utc, NaiveDate};
/// let dt = NaiveDate::from_ymd_opt(2018, 1, 26).unwrap().and_hms_micro_opt(18, 30, 9, 453_829).unwrap().and_local_timezone(Utc).unwrap();
/// assert_eq!(dt.to_rfc3339_opts(SecondsFormat::Millis, false),
/// "2018-01-26T18:30:09.453+00:00");
@@ -631,6 +706,7 @@ where
/// ```
#[cfg(any(feature = "alloc", feature = "std", test))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "alloc", feature = "std"))))]
+ #[must_use]
pub fn to_rfc3339_opts(&self, secform: SecondsFormat, use_z: bool) -> String {
use crate::format::Numeric::*;
use crate::format::Pad::Zero;
@@ -677,6 +753,7 @@ where
#[cfg(any(feature = "alloc", feature = "std", test))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "alloc", feature = "std"))))]
#[inline]
+ #[must_use]
pub fn format_with_items<'a, I, B>(&self, items: I) -> DelayedFormat<I>
where
I: Iterator<Item = B> + Clone,
@@ -686,9 +763,9 @@ where
DelayedFormat::new_with_offset(Some(local.date()), Some(local.time()), &self.offset, items)
}
- /// Formats the combined date and time with the specified format string.
- /// See the [`crate::format::strftime`] module
- /// on the supported escape sequences.
+ /// Formats the combined date and time per the specified format string.
+ ///
+ /// See the [`crate::format::strftime`] module for the supported escape sequences.
///
/// # Example
/// ```rust
@@ -701,6 +778,7 @@ where
#[cfg(any(feature = "alloc", feature = "std", test))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "alloc", feature = "std"))))]
#[inline]
+ #[must_use]
pub fn format<'a>(&self, fmt: &'a str) -> DelayedFormat<StrftimeItems<'a>> {
self.format_with_items(StrftimeItems::new(fmt))
}
@@ -709,6 +787,7 @@ where
#[cfg(feature = "unstable-locales")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable-locales")))]
#[inline]
+ #[must_use]
pub fn format_localized_with_items<'a, I, B>(
&self,
items: I,
@@ -728,7 +807,7 @@ where
)
}
- /// Formats the combined date and time with the specified format string and
+ /// Formats the combined date and time per the specified format string and
/// locale.
///
/// See the [`crate::format::strftime`] module on the supported escape
@@ -736,6 +815,7 @@ where
#[cfg(feature = "unstable-locales")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable-locales")))]
#[inline]
+ #[must_use]
pub fn format_localized<'a>(
&self,
fmt: &'a str,
@@ -1002,14 +1082,16 @@ where
/// Accepts a relaxed form of RFC3339.
/// A space or a 'T' are acepted as the separator between the date and time
-/// parts. Additional spaces are allowed between each component.
+/// parts.
///
/// All of these examples are equivalent:
/// ```
/// # use chrono::{DateTime, Utc};
-/// "2012-12-12T12:12:12Z".parse::<DateTime<Utc>>();
-/// "2012-12-12 12:12:12Z".parse::<DateTime<Utc>>();
-/// "2012- 12-12T12: 12:12Z".parse::<DateTime<Utc>>();
+/// "2012-12-12T12:12:12Z".parse::<DateTime<Utc>>()?;
+/// "2012-12-12 12:12:12Z".parse::<DateTime<Utc>>()?;
+/// "2012-12-12 12:12:12+0000".parse::<DateTime<Utc>>()?;
+/// "2012-12-12 12:12:12+00:00".parse::<DateTime<Utc>>()?;
+/// # Ok::<(), chrono::ParseError>(())
/// ```
impl str::FromStr for DateTime<Utc> {
type Err = ParseError;
@@ -1021,14 +1103,16 @@ impl str::FromStr for DateTime<Utc> {
/// Accepts a relaxed form of RFC3339.
/// A space or a 'T' are acepted as the separator between the date and time
-/// parts. Additional spaces are allowed between each component.
+/// parts.
///
/// All of these examples are equivalent:
/// ```
/// # use chrono::{DateTime, Local};
-/// "2012-12-12T12:12:12Z".parse::<DateTime<Local>>();
-/// "2012-12-12 12:12:12Z".parse::<DateTime<Local>>();
-/// "2012- 12-12T12: 12:12Z".parse::<DateTime<Local>>();
+/// "2012-12-12T12:12:12Z".parse::<DateTime<Local>>()?;
+/// "2012-12-12 12:12:12Z".parse::<DateTime<Local>>()?;
+/// "2012-12-12 12:12:12+0000".parse::<DateTime<Local>>()?;
+/// "2012-12-12 12:12:12+00:00".parse::<DateTime<Local>>()?;
+/// # Ok::<(), chrono::ParseError>(())
/// ```
#[cfg(feature = "clock")]
#[cfg_attr(docsrs, doc(cfg(feature = "clock")))]
diff --git a/vendor/chrono/src/datetime/serde.rs b/vendor/chrono/src/datetime/serde.rs
index ab0126e2b..72ada0cca 100644
--- a/vendor/chrono/src/datetime/serde.rs
+++ b/vendor/chrono/src/datetime/serde.rs
@@ -122,7 +122,7 @@ impl<'de> de::Deserialize<'de> for DateTime<Local> {
/// # Example:
///
/// ```rust
-/// # use chrono::{TimeZone, DateTime, Utc, NaiveDate};
+/// # use chrono::{DateTime, Utc, NaiveDate};
/// # use serde_derive::{Deserialize, Serialize};
/// use chrono::serde::ts_nanoseconds;
/// #[derive(Deserialize, Serialize)]
@@ -158,7 +158,7 @@ pub mod ts_nanoseconds {
/// # Example:
///
/// ```rust
- /// # use chrono::{TimeZone, DateTime, Utc, NaiveDate};
+ /// # use chrono::{DateTime, Utc, NaiveDate};
/// # use serde_derive::Serialize;
/// use chrono::serde::ts_nanoseconds::serialize as to_nano_ts;
/// #[derive(Serialize)]
@@ -174,6 +174,7 @@ pub mod ts_nanoseconds {
/// assert_eq!(as_string, r#"{"time":1526522699918355733}"#);
/// # Ok::<(), serde_json::Error>(())
/// ```
+ #[must_use]
pub fn serialize<S>(dt: &DateTime<Utc>, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
@@ -188,18 +189,20 @@ pub mod ts_nanoseconds {
/// # Example:
///
/// ```rust
- /// # use chrono::{DateTime, Utc};
+ /// # use chrono::{DateTime, TimeZone, Utc};
/// # use serde_derive::Deserialize;
/// use chrono::serde::ts_nanoseconds::deserialize as from_nano_ts;
- /// #[derive(Deserialize)]
+ /// #[derive(Debug, PartialEq, Deserialize)]
/// struct S {
/// #[serde(deserialize_with = "from_nano_ts")]
/// time: DateTime<Utc>
/// }
///
/// let my_s: S = serde_json::from_str(r#"{ "time": 1526522699918355733 }"#)?;
+ /// assert_eq!(my_s, S { time: Utc.timestamp_opt(1526522699, 918355733).unwrap() });
/// # Ok::<(), serde_json::Error>(())
/// ```
+ #[must_use]
pub fn deserialize<'de, D>(d: D) -> Result<DateTime<Utc>, D::Error>
where
D: de::Deserializer<'de>,
@@ -245,7 +248,7 @@ pub mod ts_nanoseconds {
/// # Example:
///
/// ```rust
-/// # use chrono::{TimeZone, DateTime, Utc, NaiveDate};
+/// # use chrono::{DateTime, Utc, NaiveDate};
/// # use serde_derive::{Deserialize, Serialize};
/// use chrono::serde::ts_nanoseconds_option;
/// #[derive(Deserialize, Serialize)]
@@ -280,7 +283,7 @@ pub mod ts_nanoseconds_option {
/// # Example:
///
/// ```rust
- /// # use chrono::{TimeZone, DateTime, Utc, NaiveDate};
+ /// # use chrono::{DateTime, Utc, NaiveDate};
/// # use serde_derive::Serialize;
/// use chrono::serde::ts_nanoseconds_option::serialize as to_nano_tsopt;
/// #[derive(Serialize)]
@@ -296,6 +299,7 @@ pub mod ts_nanoseconds_option {
/// assert_eq!(as_string, r#"{"time":1526522699918355733}"#);
/// # Ok::<(), serde_json::Error>(())
/// ```
+ #[must_use]
pub fn serialize<S>(opt: &Option<DateTime<Utc>>, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
@@ -313,18 +317,20 @@ pub mod ts_nanoseconds_option {
/// # Example:
///
/// ```rust
- /// # use chrono::{DateTime, Utc};
+ /// # use chrono::{DateTime, TimeZone, Utc};
/// # use serde_derive::Deserialize;
/// use chrono::serde::ts_nanoseconds_option::deserialize as from_nano_tsopt;
- /// #[derive(Deserialize)]
+ /// #[derive(Debug, PartialEq, Deserialize)]
/// struct S {
/// #[serde(deserialize_with = "from_nano_tsopt")]
/// time: Option<DateTime<Utc>>
/// }
///
/// let my_s: S = serde_json::from_str(r#"{ "time": 1526522699918355733 }"#)?;
+ /// assert_eq!(my_s, S { time: Utc.timestamp_opt(1526522699, 918355733).single() });
/// # Ok::<(), serde_json::Error>(())
/// ```
+ #[must_use]
pub fn deserialize<'de, D>(d: D) -> Result<Option<DateTime<Utc>>, D::Error>
where
D: de::Deserializer<'de>,
@@ -374,7 +380,7 @@ pub mod ts_nanoseconds_option {
/// # Example:
///
/// ```rust
-/// # use chrono::{TimeZone, DateTime, Utc, NaiveDate};
+/// # use chrono::{DateTime, Utc, NaiveDate};
/// # use serde_derive::{Deserialize, Serialize};
/// use chrono::serde::ts_microseconds;
/// #[derive(Deserialize, Serialize)]
@@ -409,7 +415,7 @@ pub mod ts_microseconds {
/// # Example:
///
/// ```rust
- /// # use chrono::{TimeZone, DateTime, Utc, NaiveDate};
+ /// # use chrono::{DateTime, Utc, NaiveDate};
/// # use serde_derive::Serialize;
/// use chrono::serde::ts_microseconds::serialize as to_micro_ts;
/// #[derive(Serialize)]
@@ -425,6 +431,7 @@ pub mod ts_microseconds {
/// assert_eq!(as_string, r#"{"time":1526522699918355}"#);
/// # Ok::<(), serde_json::Error>(())
/// ```
+ #[must_use]
pub fn serialize<S>(dt: &DateTime<Utc>, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
@@ -439,18 +446,20 @@ pub mod ts_microseconds {
/// # Example:
///
/// ```rust
- /// # use chrono::{DateTime, Utc};
+ /// # use chrono::{DateTime, TimeZone, Utc};
/// # use serde_derive::Deserialize;
/// use chrono::serde::ts_microseconds::deserialize as from_micro_ts;
- /// #[derive(Deserialize)]
+ /// #[derive(Debug, PartialEq, Deserialize)]
/// struct S {
/// #[serde(deserialize_with = "from_micro_ts")]
/// time: DateTime<Utc>
/// }
///
/// let my_s: S = serde_json::from_str(r#"{ "time": 1526522699918355 }"#)?;
+ /// assert_eq!(my_s, S { time: Utc.timestamp_opt(1526522699, 918355000).unwrap() });
/// # Ok::<(), serde_json::Error>(())
/// ```
+ #[must_use]
pub fn deserialize<'de, D>(d: D) -> Result<DateTime<Utc>, D::Error>
where
D: de::Deserializer<'de>,
@@ -496,7 +505,7 @@ pub mod ts_microseconds {
/// # Example:
///
/// ```rust
-/// # use chrono::{TimeZone, DateTime, Utc, NaiveDate};
+/// # use chrono::{DateTime, Utc, NaiveDate};
/// # use serde_derive::{Deserialize, Serialize};
/// use chrono::serde::ts_microseconds_option;
/// #[derive(Deserialize, Serialize)]
@@ -530,7 +539,7 @@ pub mod ts_microseconds_option {
/// # Example:
///
/// ```rust
- /// # use chrono::{TimeZone, DateTime, Utc, NaiveDate};
+ /// # use chrono::{DateTime, Utc, NaiveDate};
/// # use serde_derive::Serialize;
/// use chrono::serde::ts_microseconds_option::serialize as to_micro_tsopt;
/// #[derive(Serialize)]
@@ -546,6 +555,7 @@ pub mod ts_microseconds_option {
/// assert_eq!(as_string, r#"{"time":1526522699918355}"#);
/// # Ok::<(), serde_json::Error>(())
/// ```
+ #[must_use]
pub fn serialize<S>(opt: &Option<DateTime<Utc>>, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
@@ -563,18 +573,20 @@ pub mod ts_microseconds_option {
/// # Example:
///
/// ```rust
- /// # use chrono::{DateTime, Utc};
+ /// # use chrono::{DateTime, TimeZone, Utc};
/// # use serde_derive::Deserialize;
/// use chrono::serde::ts_microseconds_option::deserialize as from_micro_tsopt;
- /// #[derive(Deserialize)]
+ /// #[derive(Debug, PartialEq, Deserialize)]
/// struct S {
/// #[serde(deserialize_with = "from_micro_tsopt")]
/// time: Option<DateTime<Utc>>
/// }
///
/// let my_s: S = serde_json::from_str(r#"{ "time": 1526522699918355 }"#)?;
+ /// assert_eq!(my_s, S { time: Utc.timestamp_opt(1526522699, 918355000).single() });
/// # Ok::<(), serde_json::Error>(())
/// ```
+ #[must_use]
pub fn deserialize<'de, D>(d: D) -> Result<Option<DateTime<Utc>>, D::Error>
where
D: de::Deserializer<'de>,
@@ -624,7 +636,7 @@ pub mod ts_microseconds_option {
/// # Example
///
/// ```rust
-/// # use chrono::{TimeZone, DateTime, Utc, NaiveDate};
+/// # use chrono::{DateTime, Utc, NaiveDate};
/// # use serde_derive::{Deserialize, Serialize};
/// use chrono::serde::ts_milliseconds;
/// #[derive(Deserialize, Serialize)]
@@ -659,7 +671,7 @@ pub mod ts_milliseconds {
/// # Example:
///
/// ```rust
- /// # use chrono::{TimeZone, DateTime, Utc, NaiveDate};
+ /// # use chrono::{DateTime, Utc, NaiveDate};
/// # use serde_derive::Serialize;
/// use chrono::serde::ts_milliseconds::serialize as to_milli_ts;
/// #[derive(Serialize)]
@@ -675,6 +687,7 @@ pub mod ts_milliseconds {
/// assert_eq!(as_string, r#"{"time":1526522699918}"#);
/// # Ok::<(), serde_json::Error>(())
/// ```
+ #[must_use]
pub fn serialize<S>(dt: &DateTime<Utc>, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
@@ -689,18 +702,20 @@ pub mod ts_milliseconds {
/// # Example:
///
/// ```rust
- /// # use chrono::{DateTime, Utc};
+ /// # use chrono::{DateTime, TimeZone, Utc};
/// # use serde_derive::Deserialize;
/// use chrono::serde::ts_milliseconds::deserialize as from_milli_ts;
- /// #[derive(Deserialize)]
+ /// #[derive(Debug, PartialEq, Deserialize)]
/// struct S {
/// #[serde(deserialize_with = "from_milli_ts")]
/// time: DateTime<Utc>
/// }
///
/// let my_s: S = serde_json::from_str(r#"{ "time": 1526522699918 }"#)?;
+ /// assert_eq!(my_s, S { time: Utc.timestamp_opt(1526522699, 918000000).unwrap() });
/// # Ok::<(), serde_json::Error>(())
/// ```
+ #[must_use]
pub fn deserialize<'de, D>(d: D) -> Result<DateTime<Utc>, D::Error>
where
D: de::Deserializer<'de>,
@@ -743,7 +758,7 @@ pub mod ts_milliseconds {
/// # Example
///
/// ```rust
-/// # use chrono::{TimeZone, DateTime, Utc, NaiveDate};
+/// # use chrono::{DateTime, Utc, NaiveDate};
/// # use serde_derive::{Deserialize, Serialize};
/// use chrono::serde::ts_milliseconds_option;
/// #[derive(Deserialize, Serialize)]
@@ -777,7 +792,7 @@ pub mod ts_milliseconds_option {
/// # Example:
///
/// ```rust
- /// # use chrono::{TimeZone, DateTime, Utc, NaiveDate};
+ /// # use chrono::{DateTime, Utc, NaiveDate};
/// # use serde_derive::Serialize;
/// use chrono::serde::ts_milliseconds_option::serialize as to_milli_tsopt;
/// #[derive(Serialize)]
@@ -793,6 +808,7 @@ pub mod ts_milliseconds_option {
/// assert_eq!(as_string, r#"{"time":1526522699918}"#);
/// # Ok::<(), serde_json::Error>(())
/// ```
+ #[must_use]
pub fn serialize<S>(opt: &Option<DateTime<Utc>>, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
@@ -827,13 +843,14 @@ pub mod ts_milliseconds_option {
/// }
///
/// let my_s: E<S> = serde_json::from_str(r#"{ "time": 1526522699918 }"#)?;
- /// assert_eq!(my_s, E::V(S { time: Some(Utc.timestamp(1526522699, 918000000)) }));
+ /// assert_eq!(my_s, E::V(S { time: Some(Utc.timestamp_opt(1526522699, 918000000).unwrap()) }));
/// let s: E<S> = serde_json::from_str(r#"{ "time": null }"#)?;
/// assert_eq!(s, E::V(S { time: None }));
/// let t: E<S> = serde_json::from_str(r#"{}"#)?;
/// assert_eq!(t, E::V(S { time: None }));
/// # Ok::<(), serde_json::Error>(())
/// ```
+ #[must_use]
pub fn deserialize<'de, D>(d: D) -> Result<Option<DateTime<Utc>>, D::Error>
where
D: de::Deserializer<'de>,
@@ -935,6 +952,7 @@ pub mod ts_seconds {
/// assert_eq!(as_string, r#"{"time":1431684000}"#);
/// # Ok::<(), serde_json::Error>(())
/// ```
+ #[must_use]
pub fn serialize<S>(dt: &DateTime<Utc>, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
@@ -949,18 +967,20 @@ pub mod ts_seconds {
/// # Example:
///
/// ```rust
- /// # use chrono::{DateTime, Utc};
+ /// # use chrono::{DateTime, TimeZone, Utc};
/// # use serde_derive::Deserialize;
/// use chrono::serde::ts_seconds::deserialize as from_ts;
- /// #[derive(Deserialize)]
+ /// #[derive(Debug, PartialEq, Deserialize)]
/// struct S {
/// #[serde(deserialize_with = "from_ts")]
/// time: DateTime<Utc>
/// }
///
/// let my_s: S = serde_json::from_str(r#"{ "time": 1431684000 }"#)?;
+ /// assert_eq!(my_s, S { time: Utc.timestamp_opt(1431684000, 0).unwrap() });
/// # Ok::<(), serde_json::Error>(())
/// ```
+ #[must_use]
pub fn deserialize<'de, D>(d: D) -> Result<DateTime<Utc>, D::Error>
where
D: de::Deserializer<'de>,
@@ -1050,6 +1070,7 @@ pub mod ts_seconds_option {
/// assert_eq!(as_string, r#"{"time":1431684000}"#);
/// # Ok::<(), serde_json::Error>(())
/// ```
+ #[must_use]
pub fn serialize<S>(opt: &Option<DateTime<Utc>>, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
@@ -1067,18 +1088,20 @@ pub mod ts_seconds_option {
/// # Example:
///
/// ```rust
- /// # use chrono::{DateTime, Utc};
+ /// # use chrono::{DateTime, TimeZone, Utc};
/// # use serde_derive::Deserialize;
/// use chrono::serde::ts_seconds_option::deserialize as from_tsopt;
- /// #[derive(Deserialize)]
+ /// #[derive(Debug, PartialEq, Deserialize)]
/// struct S {
/// #[serde(deserialize_with = "from_tsopt")]
/// time: Option<DateTime<Utc>>
/// }
///
/// let my_s: S = serde_json::from_str(r#"{ "time": 1431684000 }"#)?;
+ /// assert_eq!(my_s, S { time: Utc.timestamp_opt(1431684000, 0).single() });
/// # Ok::<(), serde_json::Error>(())
/// ```
+ #[must_use]
pub fn deserialize<'de, D>(d: D) -> Result<Option<DateTime<Utc>>, D::Error>
where
D: de::Deserializer<'de>,
diff --git a/vendor/chrono/src/datetime/tests.rs b/vendor/chrono/src/datetime/tests.rs
index ebd32cae9..c6be142d0 100644
--- a/vendor/chrono/src/datetime/tests.rs
+++ b/vendor/chrono/src/datetime/tests.rs
@@ -2,13 +2,11 @@ use std::time::{SystemTime, UNIX_EPOCH};
use super::DateTime;
use crate::naive::{NaiveDate, NaiveTime};
-#[cfg(feature = "clock")]
-use crate::offset::Local;
use crate::offset::{FixedOffset, TimeZone, Utc};
-use crate::oldtime::Duration;
#[cfg(feature = "clock")]
-use crate::Datelike;
-use crate::{Days, LocalResult, Months, NaiveDateTime};
+use crate::offset::{Local, Offset};
+use crate::oldtime::Duration;
+use crate::{Datelike, Days, LocalResult, Months, NaiveDateTime};
#[derive(Clone)]
struct DstTester;
@@ -472,7 +470,7 @@ fn test_rfc3339_opts() {
fn test_rfc3339_opts_nonexhaustive() {
use crate::SecondsFormat;
let dt = Utc.with_ymd_and_hms(1999, 10, 9, 1, 2, 3).unwrap();
- dt.to_rfc3339_opts(SecondsFormat::__NonExhaustive, true);
+ let _ = dt.to_rfc3339_opts(SecondsFormat::__NonExhaustive, true);
}
#[test]
@@ -950,3 +948,64 @@ fn test_datetime_sub_assign_local() {
assert_eq!(datetime_sub, datetime - Duration::days(i))
}
}
+
+#[test]
+#[cfg(all(target_os = "windows", feature = "clock"))]
+fn test_from_naive_date_time_windows() {
+ let min_year = NaiveDate::from_ymd_opt(1601, 1, 3).unwrap().and_hms_opt(0, 0, 0).unwrap();
+
+ let max_year = NaiveDate::from_ymd_opt(30827, 12, 29).unwrap().and_hms_opt(23, 59, 59).unwrap();
+
+ let too_low_year =
+ NaiveDate::from_ymd_opt(1600, 12, 29).unwrap().and_hms_opt(23, 59, 59).unwrap();
+
+ let too_high_year = NaiveDate::from_ymd_opt(30829, 1, 3).unwrap().and_hms_opt(0, 0, 0).unwrap();
+
+ let _ = Local.from_utc_datetime(&min_year);
+ let _ = Local.from_utc_datetime(&max_year);
+
+ let _ = Local.from_local_datetime(&min_year);
+ let _ = Local.from_local_datetime(&max_year);
+
+ let local_too_low = Local.from_local_datetime(&too_low_year);
+ let local_too_high = Local.from_local_datetime(&too_high_year);
+
+ assert_eq!(local_too_low, LocalResult::None);
+ assert_eq!(local_too_high, LocalResult::None);
+
+ let err = std::panic::catch_unwind(|| {
+ Local.from_utc_datetime(&too_low_year);
+ });
+ assert!(err.is_err());
+
+ let err = std::panic::catch_unwind(|| {
+ Local.from_utc_datetime(&too_high_year);
+ });
+ assert!(err.is_err());
+}
+
+#[test]
+#[cfg(feature = "clock")]
+fn test_datetime_local_from_preserves_offset() {
+ let naivedatetime = NaiveDate::from_ymd_opt(2023, 1, 1).unwrap().and_hms_opt(0, 0, 0).unwrap();
+
+ let datetime = Local.from_utc_datetime(&naivedatetime);
+ let offset = datetime.offset().fix();
+
+ let datetime_fixed: DateTime<FixedOffset> = datetime.into();
+ assert_eq!(&offset, datetime_fixed.offset());
+ assert_eq!(datetime.fixed_offset(), datetime_fixed);
+}
+
+#[test]
+fn test_datetime_fixed_offset() {
+ let naivedatetime = NaiveDate::from_ymd_opt(2023, 1, 1).unwrap().and_hms_opt(0, 0, 0).unwrap();
+
+ let datetime = Utc.from_utc_datetime(&naivedatetime);
+ let fixed_utc = FixedOffset::east_opt(0).unwrap();
+ assert_eq!(datetime.fixed_offset(), fixed_utc.from_local_datetime(&naivedatetime).unwrap());
+
+ let fixed_offset = FixedOffset::east_opt(3600).unwrap();
+ let datetime_fixed = fixed_offset.from_local_datetime(&naivedatetime).unwrap();
+ assert_eq!(datetime_fixed.fixed_offset(), datetime_fixed);
+}
diff --git a/vendor/chrono/src/format/locales.rs b/vendor/chrono/src/format/locales.rs
index f7b4bbde5..d6fecc978 100644
--- a/vendor/chrono/src/format/locales.rs
+++ b/vendor/chrono/src/format/locales.rs
@@ -1,33 +1,33 @@
use pure_rust_locales::{locale_match, Locale};
-pub(crate) fn short_months(locale: Locale) -> &'static [&'static str] {
+pub(crate) const fn short_months(locale: Locale) -> &'static [&'static str] {
locale_match!(locale => LC_TIME::ABMON)
}
-pub(crate) fn long_months(locale: Locale) -> &'static [&'static str] {
+pub(crate) const fn long_months(locale: Locale) -> &'static [&'static str] {
locale_match!(locale => LC_TIME::MON)
}
-pub(crate) fn short_weekdays(locale: Locale) -> &'static [&'static str] {
+pub(crate) const fn short_weekdays(locale: Locale) -> &'static [&'static str] {
locale_match!(locale => LC_TIME::ABDAY)
}
-pub(crate) fn long_weekdays(locale: Locale) -> &'static [&'static str] {
+pub(crate) const fn long_weekdays(locale: Locale) -> &'static [&'static str] {
locale_match!(locale => LC_TIME::DAY)
}
-pub(crate) fn am_pm(locale: Locale) -> &'static [&'static str] {
+pub(crate) const fn am_pm(locale: Locale) -> &'static [&'static str] {
locale_match!(locale => LC_TIME::AM_PM)
}
-pub(crate) fn d_fmt(locale: Locale) -> &'static str {
+pub(crate) const fn d_fmt(locale: Locale) -> &'static str {
locale_match!(locale => LC_TIME::D_FMT)
}
-pub(crate) fn d_t_fmt(locale: Locale) -> &'static str {
+pub(crate) const fn d_t_fmt(locale: Locale) -> &'static str {
locale_match!(locale => LC_TIME::D_T_FMT)
}
-pub(crate) fn t_fmt(locale: Locale) -> &'static str {
+pub(crate) const fn t_fmt(locale: Locale) -> &'static str {
locale_match!(locale => LC_TIME::T_FMT)
}
diff --git a/vendor/chrono/src/format/mod.rs b/vendor/chrono/src/format/mod.rs
index c05ba4d04..93c9f86d0 100644
--- a/vendor/chrono/src/format/mod.rs
+++ b/vendor/chrono/src/format/mod.rs
@@ -16,9 +16,9 @@
//! C's `strftime` format. The available options can be found [here](./strftime/index.html).
//!
//! # Example
-//! ```rust
-//! # use std::error::Error;
-//! use chrono::prelude::*;
+#![cfg_attr(not(feature = "std"), doc = "```ignore")]
+#![cfg_attr(feature = "std", doc = "```rust")]
+//! use chrono::{TimeZone, Utc};
//!
//! let date_time = Utc.with_ymd_and_hms(2020, 11, 10, 0, 1, 32).unwrap();
//!
@@ -56,7 +56,7 @@ use crate::{Month, ParseMonthError, ParseWeekdayError, Weekday};
#[cfg(feature = "unstable-locales")]
pub(crate) mod locales;
-pub use parse::parse;
+pub use parse::{parse, parse_and_remainder};
pub use parsed::Parsed;
/// L10n locales.
#[cfg(feature = "unstable-locales")]
@@ -356,6 +356,7 @@ impl ParseError {
}
/// The category of parse error
+#[allow(clippy::manual_non_exhaustive)]
#[derive(Debug, Clone, PartialEq, Eq, Copy, Hash)]
pub enum ParseErrorKind {
/// Given field is out of permitted range.
@@ -386,7 +387,7 @@ pub enum ParseErrorKind {
/// There was an error on the formatting string, or there were non-supported formating items.
BadFormat,
- // TODO: Change this to `#[non_exhaustive]` (on the enum) when MSRV is increased
+ // TODO: Change this to `#[non_exhaustive]` (on the enum) with the next breaking release.
#[doc(hidden)]
__Nonexhaustive,
}
@@ -510,8 +511,6 @@ fn format_inner(
) -> fmt::Result {
let locale = Locales::new(locale);
- use num_integer::{div_floor, mod_floor};
-
match *item {
Item::Literal(s) | Item::Space(s) => result.push_str(s),
#[cfg(any(feature = "alloc", feature = "std", test))]
@@ -525,11 +524,11 @@ fn format_inner(
let (width, v) = match *spec {
Year => (4, date.map(|d| i64::from(d.year()))),
- YearDiv100 => (2, date.map(|d| div_floor(i64::from(d.year()), 100))),
- YearMod100 => (2, date.map(|d| mod_floor(i64::from(d.year()), 100))),
+ YearDiv100 => (2, date.map(|d| i64::from(d.year()).div_euclid(100))),
+ YearMod100 => (2, date.map(|d| i64::from(d.year()).rem_euclid(100))),
IsoYear => (4, date.map(|d| i64::from(d.iso_week().year()))),
- IsoYearDiv100 => (2, date.map(|d| div_floor(i64::from(d.iso_week().year()), 100))),
- IsoYearMod100 => (2, date.map(|d| mod_floor(i64::from(d.iso_week().year()), 100))),
+ IsoYearDiv100 => (2, date.map(|d| i64::from(d.iso_week().year()).div_euclid(100))),
+ IsoYearMod100 => (2, date.map(|d| i64::from(d.iso_week().year()).rem_euclid(100))),
Month => (2, date.map(|d| i64::from(d.month()))),
Day => (2, date.map(|d| i64::from(d.day()))),
WeekFromSun => (2, date.map(|d| i64::from(week_from_sun(d)))),
@@ -867,6 +866,7 @@ pub struct DelayedFormat<I> {
#[cfg(any(feature = "alloc", feature = "std", test))]
impl<'a, I: Iterator<Item = B> + Clone, B: Borrow<Item<'a>>> DelayedFormat<I> {
/// Makes a new `DelayedFormat` value out of local date and time.
+ #[must_use]
pub fn new(date: Option<NaiveDate>, time: Option<NaiveTime>, items: I) -> DelayedFormat<I> {
DelayedFormat {
date,
@@ -879,6 +879,7 @@ impl<'a, I: Iterator<Item = B> + Clone, B: Borrow<Item<'a>>> DelayedFormat<I> {
}
/// Makes a new `DelayedFormat` value out of local date and time and UTC offset.
+ #[must_use]
pub fn new_with_offset<Off>(
date: Option<NaiveDate>,
time: Option<NaiveTime>,
@@ -902,6 +903,7 @@ impl<'a, I: Iterator<Item = B> + Clone, B: Borrow<Item<'a>>> DelayedFormat<I> {
/// Makes a new `DelayedFormat` value out of local date and time and locale.
#[cfg(feature = "unstable-locales")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable-locales")))]
+ #[must_use]
pub fn new_with_locale(
date: Option<NaiveDate>,
time: Option<NaiveTime>,
@@ -914,6 +916,7 @@ impl<'a, I: Iterator<Item = B> + Clone, B: Borrow<Item<'a>>> DelayedFormat<I> {
/// Makes a new `DelayedFormat` value out of local date and time, UTC offset and locale.
#[cfg(feature = "unstable-locales")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable-locales")))]
+ #[must_use]
pub fn new_with_offset_and_locale<Off>(
date: Option<NaiveDate>,
time: Option<NaiveTime>,
diff --git a/vendor/chrono/src/format/parse.rs b/vendor/chrono/src/format/parse.rs
index 69204d2e9..ed3f91f6d 100644
--- a/vendor/chrono/src/format/parse.rs
+++ b/vendor/chrono/src/format/parse.rs
@@ -248,6 +248,36 @@ where
parse_internal(parsed, s, items).map(|_| ()).map_err(|(_s, e)| e)
}
+/// Tries to parse given string into `parsed` with given formatting items.
+/// Returns `Ok` with a slice of the unparsed remainder.
+///
+/// This particular date and time parser is:
+///
+/// - Greedy. It will consume the longest possible prefix.
+/// For example, `April` is always consumed entirely when the long month name is requested;
+/// it equally accepts `Apr`, but prefers the longer prefix in this case.
+///
+/// - Padding-agnostic (for numeric items).
+/// The [`Pad`](./enum.Pad.html) field is completely ignored,
+/// so one can prepend any number of zeroes before numbers.
+///
+/// - (Still) obeying the intrinsic parsing width. This allows, for example, parsing `HHMMSS`.
+pub fn parse_and_remainder<'a, 'b, I, B>(
+ parsed: &mut Parsed,
+ s: &'b str,
+ items: I,
+) -> ParseResult<&'b str>
+where
+ I: Iterator<Item = B>,
+ B: Borrow<Item<'a>>,
+{
+ match parse_internal(parsed, s, items) {
+ Ok(s) => Ok(s),
+ Err((s, ParseError(ParseErrorKind::TooLong))) => Ok(s),
+ Err((_s, e)) => Err(e),
+ }
+}
+
fn parse_internal<'a, 'b, I, B>(
parsed: &mut Parsed,
mut s: &'b str,
@@ -474,9 +504,10 @@ where
/// All of these examples are equivalent:
/// ```
/// # use chrono::{DateTime, offset::FixedOffset};
-/// "2012-12-12T12:12:12Z".parse::<DateTime<FixedOffset>>();
-/// "2012-12-12 12:12:12Z".parse::<DateTime<FixedOffset>>();
-/// "2012- 12-12T12: 12:12Z".parse::<DateTime<FixedOffset>>();
+/// "2012-12-12T12:12:12Z".parse::<DateTime<FixedOffset>>()?;
+/// "2012-12-12 12:12:12Z".parse::<DateTime<FixedOffset>>()?;
+/// "2012- 12-12T12: 12:12Z".parse::<DateTime<FixedOffset>>()?;
+/// # Ok::<(), chrono::ParseError>(())
/// ```
impl str::FromStr for DateTime<FixedOffset> {
type Err = ParseError;
@@ -686,6 +717,7 @@ fn test_parse() {
// fixed: dot plus nanoseconds
check!("", [fix!(Nanosecond)]; ); // no field set, but not an error
+ check!(".", [fix!(Nanosecond)]; TOO_SHORT);
check!("4", [fix!(Nanosecond)]; TOO_LONG); // never consumes `4`
check!("4", [fix!(Nanosecond), num!(Second)]; second: 4);
check!(".0", [fix!(Nanosecond)]; nanosecond: 0);
@@ -704,6 +736,7 @@ fn test_parse() {
// fixed: nanoseconds without the dot
check!("", [internal_fix!(Nanosecond3NoDot)]; TOO_SHORT);
+ check!(".", [internal_fix!(Nanosecond3NoDot)]; TOO_SHORT);
check!("0", [internal_fix!(Nanosecond3NoDot)]; TOO_SHORT);
check!("4", [internal_fix!(Nanosecond3NoDot)]; TOO_SHORT);
check!("42", [internal_fix!(Nanosecond3NoDot)]; TOO_SHORT);
@@ -715,6 +748,7 @@ fn test_parse() {
check!(".421", [internal_fix!(Nanosecond3NoDot)]; INVALID);
check!("", [internal_fix!(Nanosecond6NoDot)]; TOO_SHORT);
+ check!(".", [internal_fix!(Nanosecond6NoDot)]; TOO_SHORT);
check!("0", [internal_fix!(Nanosecond6NoDot)]; TOO_SHORT);
check!("42195", [internal_fix!(Nanosecond6NoDot)]; TOO_SHORT);
check!("421950", [internal_fix!(Nanosecond6NoDot)]; nanosecond: 421_950_000);
@@ -725,6 +759,7 @@ fn test_parse() {
check!(".42100", [internal_fix!(Nanosecond6NoDot)]; INVALID);
check!("", [internal_fix!(Nanosecond9NoDot)]; TOO_SHORT);
+ check!(".", [internal_fix!(Nanosecond9NoDot)]; TOO_SHORT);
check!("42195", [internal_fix!(Nanosecond9NoDot)]; TOO_SHORT);
check!("421950803", [internal_fix!(Nanosecond9NoDot)]; nanosecond: 421_950_803);
check!("000000003", [internal_fix!(Nanosecond9NoDot)]; nanosecond: 3);
@@ -854,6 +889,28 @@ fn test_rfc2822() {
("Tue, 20 Jan 2015 17:35:20 -0890", Err(OUT_OF_RANGE)), // bad offset
("6 Jun 1944 04:00:00Z", Err(INVALID)), // bad offset (zulu not allowed)
("Tue, 20 Jan 2015 17:35:20 HAS", Err(NOT_ENOUGH)), // bad named time zone
+ // named timezones that have specific timezone offsets
+ // see https://www.rfc-editor.org/rfc/rfc2822#section-4.3
+ ("Tue, 20 Jan 2015 17:35:20 GMT", Ok("Tue, 20 Jan 2015 17:35:20 +0000")),
+ ("Tue, 20 Jan 2015 17:35:20 UT", Ok("Tue, 20 Jan 2015 17:35:20 +0000")),
+ ("Tue, 20 Jan 2015 17:35:20 ut", Ok("Tue, 20 Jan 2015 17:35:20 +0000")),
+ ("Tue, 20 Jan 2015 17:35:20 EDT", Ok("Tue, 20 Jan 2015 17:35:20 -0400")),
+ ("Tue, 20 Jan 2015 17:35:20 EST", Ok("Tue, 20 Jan 2015 17:35:20 -0500")),
+ ("Tue, 20 Jan 2015 17:35:20 CDT", Ok("Tue, 20 Jan 2015 17:35:20 -0500")),
+ ("Tue, 20 Jan 2015 17:35:20 CST", Ok("Tue, 20 Jan 2015 17:35:20 -0600")),
+ ("Tue, 20 Jan 2015 17:35:20 MDT", Ok("Tue, 20 Jan 2015 17:35:20 -0600")),
+ ("Tue, 20 Jan 2015 17:35:20 MST", Ok("Tue, 20 Jan 2015 17:35:20 -0700")),
+ ("Tue, 20 Jan 2015 17:35:20 PDT", Ok("Tue, 20 Jan 2015 17:35:20 -0700")),
+ ("Tue, 20 Jan 2015 17:35:20 PST", Ok("Tue, 20 Jan 2015 17:35:20 -0800")),
+ ("Tue, 20 Jan 2015 17:35:20 pst", Ok("Tue, 20 Jan 2015 17:35:20 -0800")),
+ // named single-letter military timezones must fallback to +0000
+ ("Tue, 20 Jan 2015 17:35:20 Z", Ok("Tue, 20 Jan 2015 17:35:20 +0000")),
+ ("Tue, 20 Jan 2015 17:35:20 A", Ok("Tue, 20 Jan 2015 17:35:20 +0000")),
+ ("Tue, 20 Jan 2015 17:35:20 a", Ok("Tue, 20 Jan 2015 17:35:20 +0000")),
+ ("Tue, 20 Jan 2015 17:35:20 K", Ok("Tue, 20 Jan 2015 17:35:20 +0000")),
+ ("Tue, 20 Jan 2015 17:35:20 k", Ok("Tue, 20 Jan 2015 17:35:20 +0000")),
+ // named single-letter timezone "J" is specifically not valid
+ ("Tue, 20 Jan 2015 17:35:20 J", Err(NOT_ENOUGH)),
];
fn rfc2822_to_datetime(date: &str) -> ParseResult<DateTime<FixedOffset>> {
@@ -975,3 +1032,11 @@ fn test_rfc3339() {
}
}
}
+
+#[cfg(test)]
+#[test]
+fn test_issue_1010() {
+ let dt = crate::NaiveDateTime::parse_from_str("\u{c}SUN\u{e}\u{3000}\0m@J\u{3000}\0\u{3000}\0m\u{c}!\u{c}\u{b}\u{c}\u{c}\u{c}\u{c}%A\u{c}\u{b}\0SU\u{c}\u{c}",
+ "\u{c}\u{c}%A\u{c}\u{b}\0SUN\u{c}\u{c}\u{c}SUNN\u{c}\u{c}\u{c}SUN\u{c}\u{c}!\u{c}\u{b}\u{c}\u{c}\u{c}\u{c}%A\u{c}\u{b}%a");
+ assert_eq!(dt, Err(ParseError(ParseErrorKind::Invalid)));
+}
diff --git a/vendor/chrono/src/format/parsed.rs b/vendor/chrono/src/format/parsed.rs
index 6cc29e9d4..9526785ee 100644
--- a/vendor/chrono/src/format/parsed.rs
+++ b/vendor/chrono/src/format/parsed.rs
@@ -4,9 +4,6 @@
//! A collection of parsed date and time items.
//! They can be constructed incrementally while being checked for consistency.
-use num_integer::div_rem;
-use num_traits::ToPrimitive;
-
use super::{ParseResult, IMPOSSIBLE, NOT_ENOUGH, OUT_OF_RANGE};
use crate::naive::{NaiveDate, NaiveDateTime, NaiveTime};
use crate::offset::{FixedOffset, LocalResult, Offset, TimeZone};
@@ -22,6 +19,7 @@ use crate::{Datelike, Timelike};
///
/// - `to_*` methods try to make a concrete date and time value out of set fields.
/// It fully checks any remaining out-of-range conditions and inconsistent/impossible fields.
+#[allow(clippy::manual_non_exhaustive)]
#[derive(Clone, PartialEq, Eq, Debug, Default, Hash)]
pub struct Parsed {
/// Year.
@@ -106,6 +104,7 @@ pub struct Parsed {
pub offset: Option<i32>,
/// A dummy field to make this type not fully destructible (required for API stability).
+ // TODO: Change this to `#[non_exhaustive]` (on the enum) with the next breaking release.
_dummy: (),
}
@@ -127,6 +126,7 @@ fn set_if_consistent<T: PartialEq>(old: &mut Option<T>, new: T) -> ParseResult<(
impl Parsed {
/// Returns the initial value of parsed parts.
+ #[must_use]
pub fn new() -> Parsed {
Parsed::default()
}
@@ -134,7 +134,7 @@ impl Parsed {
/// Tries to set the [`year`](#structfield.year) field from given value.
#[inline]
pub fn set_year(&mut self, value: i64) -> ParseResult<()> {
- set_if_consistent(&mut self.year, value.to_i32().ok_or(OUT_OF_RANGE)?)
+ set_if_consistent(&mut self.year, i32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
}
/// Tries to set the [`year_div_100`](#structfield.year_div_100) field from given value.
@@ -143,7 +143,7 @@ impl Parsed {
if value < 0 {
return Err(OUT_OF_RANGE);
}
- set_if_consistent(&mut self.year_div_100, value.to_i32().ok_or(OUT_OF_RANGE)?)
+ set_if_consistent(&mut self.year_div_100, i32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
}
/// Tries to set the [`year_mod_100`](#structfield.year_mod_100) field from given value.
@@ -152,13 +152,13 @@ impl Parsed {
if value < 0 {
return Err(OUT_OF_RANGE);
}
- set_if_consistent(&mut self.year_mod_100, value.to_i32().ok_or(OUT_OF_RANGE)?)
+ set_if_consistent(&mut self.year_mod_100, i32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
}
/// Tries to set the [`isoyear`](#structfield.isoyear) field from given value.
#[inline]
pub fn set_isoyear(&mut self, value: i64) -> ParseResult<()> {
- set_if_consistent(&mut self.isoyear, value.to_i32().ok_or(OUT_OF_RANGE)?)
+ set_if_consistent(&mut self.isoyear, i32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
}
/// Tries to set the [`isoyear_div_100`](#structfield.isoyear_div_100) field from given value.
@@ -167,7 +167,10 @@ impl Parsed {
if value < 0 {
return Err(OUT_OF_RANGE);
}
- set_if_consistent(&mut self.isoyear_div_100, value.to_i32().ok_or(OUT_OF_RANGE)?)
+ set_if_consistent(
+ &mut self.isoyear_div_100,
+ i32::try_from(value).map_err(|_| OUT_OF_RANGE)?,
+ )
}
/// Tries to set the [`isoyear_mod_100`](#structfield.isoyear_mod_100) field from given value.
@@ -176,31 +179,34 @@ impl Parsed {
if value < 0 {
return Err(OUT_OF_RANGE);
}
- set_if_consistent(&mut self.isoyear_mod_100, value.to_i32().ok_or(OUT_OF_RANGE)?)
+ set_if_consistent(
+ &mut self.isoyear_mod_100,
+ i32::try_from(value).map_err(|_| OUT_OF_RANGE)?,
+ )
}
/// Tries to set the [`month`](#structfield.month) field from given value.
#[inline]
pub fn set_month(&mut self, value: i64) -> ParseResult<()> {
- set_if_consistent(&mut self.month, value.to_u32().ok_or(OUT_OF_RANGE)?)
+ set_if_consistent(&mut self.month, u32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
}
/// Tries to set the [`week_from_sun`](#structfield.week_from_sun) field from given value.
#[inline]
pub fn set_week_from_sun(&mut self, value: i64) -> ParseResult<()> {
- set_if_consistent(&mut self.week_from_sun, value.to_u32().ok_or(OUT_OF_RANGE)?)
+ set_if_consistent(&mut self.week_from_sun, u32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
}
/// Tries to set the [`week_from_mon`](#structfield.week_from_mon) field from given value.
#[inline]
pub fn set_week_from_mon(&mut self, value: i64) -> ParseResult<()> {
- set_if_consistent(&mut self.week_from_mon, value.to_u32().ok_or(OUT_OF_RANGE)?)
+ set_if_consistent(&mut self.week_from_mon, u32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
}
/// Tries to set the [`isoweek`](#structfield.isoweek) field from given value.
#[inline]
pub fn set_isoweek(&mut self, value: i64) -> ParseResult<()> {
- set_if_consistent(&mut self.isoweek, value.to_u32().ok_or(OUT_OF_RANGE)?)
+ set_if_consistent(&mut self.isoweek, u32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
}
/// Tries to set the [`weekday`](#structfield.weekday) field from given value.
@@ -212,13 +218,13 @@ impl Parsed {
/// Tries to set the [`ordinal`](#structfield.ordinal) field from given value.
#[inline]
pub fn set_ordinal(&mut self, value: i64) -> ParseResult<()> {
- set_if_consistent(&mut self.ordinal, value.to_u32().ok_or(OUT_OF_RANGE)?)
+ set_if_consistent(&mut self.ordinal, u32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
}
/// Tries to set the [`day`](#structfield.day) field from given value.
#[inline]
pub fn set_day(&mut self, value: i64) -> ParseResult<()> {
- set_if_consistent(&mut self.day, value.to_u32().ok_or(OUT_OF_RANGE)?)
+ set_if_consistent(&mut self.day, u32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
}
/// Tries to set the [`hour_div_12`](#structfield.hour_div_12) field from given value.
@@ -242,7 +248,7 @@ impl Parsed {
/// [`hour_mod_12`](#structfield.hour_mod_12) fields from given value.
#[inline]
pub fn set_hour(&mut self, value: i64) -> ParseResult<()> {
- let v = value.to_u32().ok_or(OUT_OF_RANGE)?;
+ let v = u32::try_from(value).map_err(|_| OUT_OF_RANGE)?;
set_if_consistent(&mut self.hour_div_12, v / 12)?;
set_if_consistent(&mut self.hour_mod_12, v % 12)?;
Ok(())
@@ -251,19 +257,19 @@ impl Parsed {
/// Tries to set the [`minute`](#structfield.minute) field from given value.
#[inline]
pub fn set_minute(&mut self, value: i64) -> ParseResult<()> {
- set_if_consistent(&mut self.minute, value.to_u32().ok_or(OUT_OF_RANGE)?)
+ set_if_consistent(&mut self.minute, u32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
}
/// Tries to set the [`second`](#structfield.second) field from given value.
#[inline]
pub fn set_second(&mut self, value: i64) -> ParseResult<()> {
- set_if_consistent(&mut self.second, value.to_u32().ok_or(OUT_OF_RANGE)?)
+ set_if_consistent(&mut self.second, u32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
}
/// Tries to set the [`nanosecond`](#structfield.nanosecond) field from given value.
#[inline]
pub fn set_nanosecond(&mut self, value: i64) -> ParseResult<()> {
- set_if_consistent(&mut self.nanosecond, value.to_u32().ok_or(OUT_OF_RANGE)?)
+ set_if_consistent(&mut self.nanosecond, u32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
}
/// Tries to set the [`timestamp`](#structfield.timestamp) field from given value.
@@ -275,7 +281,7 @@ impl Parsed {
/// Tries to set the [`offset`](#structfield.offset) field from given value.
#[inline]
pub fn set_offset(&mut self, value: i64) -> ParseResult<()> {
- set_if_consistent(&mut self.offset, value.to_i32().ok_or(OUT_OF_RANGE)?)
+ set_if_consistent(&mut self.offset, i32::try_from(value).map_err(|_| OUT_OF_RANGE)?)
}
/// Returns a parsed naive date out of given fields.
@@ -308,7 +314,8 @@ impl Parsed {
if y < 0 {
return Err(OUT_OF_RANGE);
}
- let (q_, r_) = div_rem(y, 100);
+ let q_ = y / 100;
+ let r_ = y % 100;
if q.unwrap_or(q_) == q_ && r.unwrap_or(r_) == r_ {
Ok(Some(y))
} else {
@@ -343,8 +350,7 @@ impl Parsed {
let verify_ymd = |date: NaiveDate| {
let year = date.year();
let (year_div_100, year_mod_100) = if year >= 0 {
- let (q, r) = div_rem(year, 100);
- (Some(q), Some(r))
+ (Some(year / 100), Some(year % 100))
} else {
(None, None) // they should be empty to be consistent
};
@@ -364,8 +370,7 @@ impl Parsed {
let isoweek = week.week();
let weekday = date.weekday();
let (isoyear_div_100, isoyear_mod_100) = if isoyear >= 0 {
- let (q, r) = div_rem(isoyear, 100);
- (Some(q), Some(r))
+ (Some(isoyear / 100), Some(isoyear % 100))
} else {
(None, None) // they should be empty to be consistent
};
@@ -1286,4 +1291,18 @@ mod tests {
// TODO test with a variable time zone (for None and Ambiguous cases)
}
+
+ #[test]
+ fn issue_551() {
+ use crate::Weekday;
+ let mut parsed = Parsed::new();
+
+ parsed.year = Some(2002);
+ parsed.week_from_mon = Some(22);
+ parsed.weekday = Some(Weekday::Mon);
+ assert_eq!(NaiveDate::from_ymd_opt(2002, 6, 3).unwrap(), parsed.to_naive_date().unwrap());
+
+ parsed.year = Some(2001);
+ assert_eq!(NaiveDate::from_ymd_opt(2001, 5, 28).unwrap(), parsed.to_naive_date().unwrap());
+ }
}
diff --git a/vendor/chrono/src/format/scan.rs b/vendor/chrono/src/format/scan.rs
index 263fec556..2962ef162 100644
--- a/vendor/chrono/src/format/scan.rs
+++ b/vendor/chrono/src/format/scan.rs
@@ -12,8 +12,8 @@ use crate::Weekday;
/// Returns true when two slices are equal case-insensitively (in ASCII).
/// Assumes that the `pattern` is already converted to lower case.
-fn equals(s: &str, pattern: &str) -> bool {
- let mut xs = s.as_bytes().iter().map(|&c| match c {
+fn equals(s: &[u8], pattern: &str) -> bool {
+ let mut xs = s.iter().map(|&c| match c {
b'A'..=b'Z' => c + 32,
_ => c,
});
@@ -48,7 +48,7 @@ pub(super) fn number(s: &str, min: usize, max: usize) -> ParseResult<(&str, i64)
let mut n = 0i64;
for (i, c) in bytes.iter().take(max).cloned().enumerate() {
// cloned() = copied()
- if !(b'0'..=b'9').contains(&c) {
+ if !c.is_ascii_digit() {
if i < min {
return Err(INVALID);
} else {
@@ -79,7 +79,7 @@ pub(super) fn nanosecond(s: &str) -> ParseResult<(&str, i64)> {
let v = v.checked_mul(SCALE[consumed]).ok_or(OUT_OF_RANGE)?;
// if there are more than 9 digits, skip next digits.
- let s = s.trim_left_matches(|c: char| ('0'..='9').contains(&c));
+ let s = s.trim_left_matches(|c: char| c.is_ascii_digit());
Ok((s, v))
}
@@ -152,7 +152,7 @@ pub(super) fn short_or_long_month0(s: &str) -> ParseResult<(&str, u8)> {
// tries to consume the suffix if possible
let suffix = LONG_MONTH_SUFFIXES[month0 as usize];
- if s.len() >= suffix.len() && equals(&s[..suffix.len()], suffix) {
+ if s.len() >= suffix.len() && equals(&s.as_bytes()[..suffix.len()], suffix) {
s = &s[suffix.len()..];
}
@@ -170,7 +170,7 @@ pub(super) fn short_or_long_weekday(s: &str) -> ParseResult<(&str, Weekday)> {
// tries to consume the suffix if possible
let suffix = LONG_WEEKDAY_SUFFIXES[weekday.num_days_from_monday() as usize];
- if s.len() >= suffix.len() && equals(&s[..suffix.len()], suffix) {
+ if s.len() >= suffix.len() && equals(&s.as_bytes()[..suffix.len()], suffix) {
s = &s[suffix.len()..];
}
@@ -222,7 +222,7 @@ fn timezone_offset_internal<F>(
where
F: FnMut(&str) -> ParseResult<&str>,
{
- fn digits(s: &str) -> ParseResult<(u8, u8)> {
+ const fn digits(s: &str) -> ParseResult<(u8, u8)> {
let b = s.as_bytes();
if b.len() < 2 {
Err(TOO_SHORT)
@@ -308,18 +308,14 @@ where
/// Same as `timezone_offset` but also allows for RFC 2822 legacy timezones.
/// May return `None` which indicates an insufficient offset data (i.e. `-0000`).
+/// See [RFC 2822 Section 4.3].
+///
+/// [RFC 2822 Section 4.3]: https://tools.ietf.org/html/rfc2822#section-4.3
pub(super) fn timezone_offset_2822(s: &str) -> ParseResult<(&str, Option<i32>)> {
// tries to parse legacy time zone names
- let upto = s
- .as_bytes()
- .iter()
- .position(|&c| match c {
- b'a'..=b'z' | b'A'..=b'Z' => false,
- _ => true,
- })
- .unwrap_or(s.len());
+ let upto = s.as_bytes().iter().position(|&c| !c.is_ascii_alphabetic()).unwrap_or(s.len());
if upto > 0 {
- let name = &s[..upto];
+ let name = &s.as_bytes()[..upto];
let s = &s[upto..];
let offset_hours = |o| Ok((s, Some(o * 3600)));
if equals(name, "gmt") || equals(name, "ut") {
@@ -334,8 +330,14 @@ pub(super) fn timezone_offset_2822(s: &str) -> ParseResult<(&str, Option<i32>)>
offset_hours(-7)
} else if equals(name, "pst") {
offset_hours(-8)
+ } else if name.len() == 1 {
+ match name[0] {
+ // recommended by RFC 2822: consume but treat it as -0000
+ b'a'..=b'i' | b'k'..=b'z' | b'A'..=b'I' | b'K'..=b'Z' => offset_hours(0),
+ _ => Ok((s, None)),
+ }
} else {
- Ok((s, None)) // recommended by RFC 2822: consume but treat it as -0000
+ Ok((s, None))
}
} else {
let (s_, offset) = timezone_offset(s, |s| Ok(s))?;
diff --git a/vendor/chrono/src/format/strftime.rs b/vendor/chrono/src/format/strftime.rs
index dcaabe49f..24bae20c0 100644
--- a/vendor/chrono/src/format/strftime.rs
+++ b/vendor/chrono/src/format/strftime.rs
@@ -68,7 +68,7 @@ The following specifiers are available both to formatting and parsing.
| `%r` | `12:34:60 AM` | Hour-minute-second format in 12-hour clocks. Same as `%I:%M:%S %p`. |
| | | |
| | | **TIME ZONE SPECIFIERS:** |
-| `%Z` | `ACST` | Local time zone name. Skips all non-whitespace characters during parsing. [^8] |
+| `%Z` | `ACST` | Local time zone name. Skips all non-whitespace characters during parsing. Identical to `%:z` when formatting. [^8] |
| `%z` | `+0930` | Offset from the local time to UTC (with UTC being `+0000`). |
| `%:z` | `+09:30` | Same as `%z` but with a colon. |
|`%::z`|`+09:30:00`| Offset from the local time to UTC with seconds. |
@@ -164,6 +164,12 @@ Notes:
Note that they can read nothing if the fractional part is zero.
[^8]: `%Z`:
+ Since `chrono` is not aware of timezones beyond their offsets, this specifier
+ **only prints the offset** when used for formatting. The timezone abbreviation
+ will NOT be printed. See [this issue](https://github.com/chronotope/chrono/issues/960)
+ for more information.
+ <br>
+ <br>
Offset will not be populated from the parsed data, nor will it be validated.
Timezone is completely ignored. Similar to the glibc `strptime` treatment of
this format code.
@@ -227,6 +233,7 @@ pub struct StrftimeItems<'a> {
impl<'a> StrftimeItems<'a> {
/// Creates a new parsing iterator from the `strftime`-like format string.
+ #[must_use]
pub fn new(s: &'a str) -> StrftimeItems<'a> {
Self::with_remainer(s)
}
@@ -234,6 +241,7 @@ impl<'a> StrftimeItems<'a> {
/// Creates a new parsing iterator from the `strftime`-like format string.
#[cfg(feature = "unstable-locales")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable-locales")))]
+ #[must_use]
pub fn new_with_locale(s: &'a str, locale: Locale) -> StrftimeItems<'a> {
let d_fmt = StrftimeItems::new(locales::d_fmt(locale)).collect();
let d_t_fmt = StrftimeItems::new(locales::d_t_fmt(locale)).collect();
diff --git a/vendor/chrono/src/lib.rs b/vendor/chrono/src/lib.rs
index 861ee1059..3737d1a9b 100644
--- a/vendor/chrono/src/lib.rs
+++ b/vendor/chrono/src/lib.rs
@@ -110,7 +110,8 @@
//! or in the local time zone
//! ([`Local::now()`](./offset/struct.Local.html#method.now)).
//!
-//! ```rust
+#![cfg_attr(not(feature = "clock"), doc = "```ignore")]
+#![cfg_attr(feature = "clock", doc = "```rust")]
//! use chrono::prelude::*;
//!
//! let utc: DateTime<Utc> = Utc::now(); // e.g. `2014-11-28T12:45:59.324310806Z`
@@ -122,25 +123,30 @@
//! This is a bit verbose due to Rust's lack of function and method overloading,
//! but in turn we get a rich combination of initialization methods.
//!
-//! ```rust
+#![cfg_attr(not(feature = "std"), doc = "```ignore")]
+#![cfg_attr(feature = "std", doc = "```rust")]
//! use chrono::prelude::*;
//! use chrono::offset::LocalResult;
//!
+//! # fn doctest() -> Option<()> {
+//!
//! let dt = Utc.with_ymd_and_hms(2014, 7, 8, 9, 10, 11).unwrap(); // `2014-07-08T09:10:11Z`
+//! assert_eq!(dt, NaiveDate::from_ymd_opt(2014, 7, 8)?.and_hms_opt(9, 10, 11)?.and_local_timezone(Utc).unwrap());
+//!
//! // July 8 is 188th day of the year 2014 (`o` for "ordinal")
-//! assert_eq!(dt, Utc.yo(2014, 189).and_hms_opt(9, 10, 11).unwrap());
+//! assert_eq!(dt, NaiveDate::from_yo_opt(2014, 189)?.and_hms_opt(9, 10, 11)?.and_utc());
//! // July 8 is Tuesday in ISO week 28 of the year 2014.
-//! assert_eq!(dt, Utc.isoywd(2014, 28, Weekday::Tue).and_hms_opt(9, 10, 11).unwrap());
+//! assert_eq!(dt, NaiveDate::from_isoywd_opt(2014, 28, Weekday::Tue)?.and_hms_opt(9, 10, 11)?.and_utc());
//!
-//! let dt = NaiveDate::from_ymd_opt(2014, 7, 8).unwrap().and_hms_milli_opt(9, 10, 11, 12).unwrap().and_local_timezone(Utc).unwrap(); // `2014-07-08T09:10:11.012Z`
-//! assert_eq!(dt, NaiveDate::from_ymd_opt(2014, 7, 8).unwrap().and_hms_micro_opt(9, 10, 11, 12_000).unwrap().and_local_timezone(Utc).unwrap());
-//! assert_eq!(dt, NaiveDate::from_ymd_opt(2014, 7, 8).unwrap().and_hms_nano_opt(9, 10, 11, 12_000_000).unwrap().and_local_timezone(Utc).unwrap());
+//! let dt = NaiveDate::from_ymd_opt(2014, 7, 8)?.and_hms_milli_opt(9, 10, 11, 12)?.and_local_timezone(Utc).unwrap(); // `2014-07-08T09:10:11.012Z`
+//! assert_eq!(dt, NaiveDate::from_ymd_opt(2014, 7, 8)?.and_hms_micro_opt(9, 10, 11, 12_000)?.and_local_timezone(Utc).unwrap());
+//! assert_eq!(dt, NaiveDate::from_ymd_opt(2014, 7, 8)?.and_hms_nano_opt(9, 10, 11, 12_000_000)?.and_local_timezone(Utc).unwrap());
//!
//! // dynamic verification
-//! assert_eq!(Utc.ymd_opt(2014, 7, 8).and_hms_opt(21, 15, 33),
-//! LocalResult::Single(Utc.with_ymd_and_hms(2014, 7, 8, 21, 15, 33).unwrap()));
-//! assert_eq!(Utc.ymd_opt(2014, 7, 8).and_hms_opt(80, 15, 33), LocalResult::None);
-//! assert_eq!(Utc.ymd_opt(2014, 7, 38).and_hms_opt(21, 15, 33), LocalResult::None);
+//! assert_eq!(Utc.with_ymd_and_hms(2014, 7, 8, 21, 15, 33),
+//! LocalResult::Single(NaiveDate::from_ymd_opt(2014, 7, 8)?.and_hms_opt(21, 15, 33)?.and_utc()));
+//! assert_eq!(Utc.with_ymd_and_hms(2014, 7, 8, 80, 15, 33), LocalResult::None);
+//! assert_eq!(Utc.with_ymd_and_hms(2014, 7, 38, 21, 15, 33), LocalResult::None);
//!
//! // other time zone objects can be used to construct a local datetime.
//! // obviously, `local_dt` is normally different from `dt`, but `fixed_dt` should be identical.
@@ -148,6 +154,9 @@
//! let fixed_dt = FixedOffset::east_opt(9 * 3600).unwrap().from_local_datetime(&NaiveDate::from_ymd_opt(2014, 7, 8).unwrap().and_hms_milli_opt(18, 10, 11, 12).unwrap()).unwrap();
//! assert_eq!(dt, fixed_dt);
//! # let _ = local_dt;
+//! # Some(())
+//! # }
+//! # doctest().unwrap();
//! ```
//!
//! Various properties are available to the date and time, and can be altered individually.
@@ -217,6 +226,7 @@
//! The `unstable-locales` feature requires and implies at least the `alloc` feature.
//!
//! ```rust
+//! # #[allow(unused_imports)]
//! use chrono::prelude::*;
//!
//! # #[cfg(feature = "unstable-locales")]
@@ -314,12 +324,13 @@
//! [`DateTime.timestamp_subsec_nanos`](./struct.DateTime.html#method.timestamp_subsec_nanos)
//! to get the number of additional number of nanoseconds.
//!
-//! ```rust
+#![cfg_attr(not(feature = "std"), doc = "```ignore")]
+#![cfg_attr(feature = "std", doc = "```rust")]
//! // We need the trait in scope to use Utc::timestamp().
//! use chrono::{DateTime, TimeZone, Utc};
//!
//! // Construct a datetime from epoch:
-//! let dt = Utc.timestamp(1_500_000_000, 0);
+//! let dt = Utc.timestamp_opt(1_500_000_000, 0).unwrap();
//! assert_eq!(dt.to_rfc2822(), "Fri, 14 Jul 2017 02:40:00 +0000");
//!
//! // Get epoch value from a datetime:
@@ -327,33 +338,6 @@
//! assert_eq!(dt.timestamp(), 1_500_000_000);
//! ```
//!
-//! ### Individual date
-//!
-//! Chrono also provides an individual date type ([**`Date`**](./struct.Date.html)).
-//! It also has time zones attached, and have to be constructed via time zones.
-//! Most operations available to `DateTime` are also available to `Date` whenever appropriate.
-//!
-//! ```rust
-//! use chrono::prelude::*;
-//! use chrono::offset::LocalResult;
-//!
-//! # // these *may* fail, but only very rarely. just rerun the test if you were that unfortunate ;)
-//! assert_eq!(Utc::today(), Utc::now().date());
-//! assert_eq!(Local::today(), Local::now().date());
-//!
-//! assert_eq!(Utc.ymd_opt(2014, 11, 28).unwrap().weekday(), Weekday::Fri);
-//! assert_eq!(Utc.ymd_opt(2014, 11, 31), LocalResult::None);
-//! assert_eq!(NaiveDate::from_ymd_opt(2014, 11, 28).unwrap().and_hms_milli_opt(7, 8, 9, 10).unwrap().and_local_timezone(Utc).unwrap().format("%H%M%S").to_string(),
-//! "070809");
-//! ```
-//!
-//! There is no timezone-aware `Time` due to the lack of usefulness and also the complexity.
-//!
-//! `DateTime` has [`date`](./struct.DateTime.html#method.date) method
-//! which returns a `Date` which represents its date component.
-//! There is also a [`time`](./struct.DateTime.html#method.time) method,
-//! which simply returns a naive local time described below.
-//!
//! ### Naive date and time
//!
//! Chrono provides naive counterparts to `Date`, (non-existent) `Time` and `DateTime`
@@ -398,7 +382,7 @@
//! Advanced time zone handling is not yet supported.
//! For now you can try the [Chrono-tz](https://github.com/chronotope/chrono-tz/) crate instead.
-#![doc(html_root_url = "https://docs.rs/chrono/latest/")]
+#![doc(html_root_url = "https://docs.rs/chrono/latest/", test(attr(deny(warnings))))]
#![cfg_attr(feature = "bench", feature(test))] // lib stability features as per RFC #507
#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
@@ -418,6 +402,8 @@ mod oldtime;
// this reexport is to aid the transition and should not be in the prelude!
pub use oldtime::{Duration, OutOfRangeError};
+use core::fmt;
+
#[cfg(feature = "__doctest")]
#[cfg_attr(feature = "__doctest", cfg(doctest))]
use doc_comment::doctest;
@@ -502,26 +488,41 @@ pub use naive::__BenchYearFlags;
/// Serialization/Deserialization with serde.
///
/// This module provides default implementations for `DateTime` using the [RFC 3339][1] format and various
-/// alternatives for use with serde's [`with` annotation][1].
+/// alternatives for use with serde's [`with` annotation][2].
///
/// *Available on crate feature 'serde' only.*
///
/// [1]: https://tools.ietf.org/html/rfc3339
-/// [2]: https://serde.rs/attributes.html#field-attributes
+/// [2]: https://serde.rs/field-attrs.html#with
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
pub mod serde {
pub use super::datetime::serde::*;
}
-/// MSRV 1.42
-#[cfg(test)]
-#[macro_export]
-macro_rules! matches {
- ($expression:expr, $(|)? $( $pattern:pat )|+ $( if $guard: expr )? $(,)?) => {
- match $expression {
- $( $pattern )|+ $( if $guard )? => true,
- _ => false
- }
+/// Out of range error type used in various converting APIs
+#[derive(Clone, Copy, Hash, PartialEq, Eq)]
+pub struct OutOfRange {
+ _private: (),
+}
+
+impl OutOfRange {
+ const fn new() -> OutOfRange {
+ OutOfRange { _private: () }
}
}
+
+impl fmt::Display for OutOfRange {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "out of range")
+ }
+}
+
+impl fmt::Debug for OutOfRange {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "out of range")
+ }
+}
+
+#[cfg(feature = "std")]
+impl std::error::Error for OutOfRange {}
diff --git a/vendor/chrono/src/month.rs b/vendor/chrono/src/month.rs
index 46f09d0fb..11df7613d 100644
--- a/vendor/chrono/src/month.rs
+++ b/vendor/chrono/src/month.rs
@@ -3,6 +3,8 @@ use core::fmt;
#[cfg(feature = "rkyv")]
use rkyv::{Archive, Deserialize, Serialize};
+use crate::OutOfRange;
+
/// The month of the year.
///
/// This enum is just a convenience implementation.
@@ -10,11 +12,10 @@ use rkyv::{Archive, Deserialize, Serialize};
///
/// It is possible to convert from a date to a month independently
/// ```
-/// use num_traits::FromPrimitive;
/// use chrono::prelude::*;
/// let date = Utc.with_ymd_and_hms(2019, 10, 28, 9, 10, 11).unwrap();
/// // `2019-10-28T09:10:11Z`
-/// let month = Month::from_u32(date.month());
+/// let month = Month::try_from(u8::try_from(date.month()).unwrap()).ok();
/// assert_eq!(month, Some(Month::October))
/// ```
/// Or from a Month to an integer usable by dates
@@ -27,7 +28,7 @@ use rkyv::{Archive, Deserialize, Serialize};
/// Allows mapping from and to month, from 1-January to 12-December.
/// Can be Serialized/Deserialized with serde
// Actual implementation is zero-indexed, API intended as 1-indexed for more intuitive behavior.
-#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash)]
+#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash, PartialOrd)]
#[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))]
#[cfg_attr(feature = "rkyv", derive(Archive, Deserialize, Serialize))]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
@@ -65,7 +66,8 @@ impl Month {
/// ----------- | --------- | ---------- | --- | ---------
/// `m.succ()`: | `February` | `March` | `...` | `January`
#[inline]
- pub fn succ(&self) -> Month {
+ #[must_use]
+ pub const fn succ(&self) -> Month {
match *self {
Month::January => Month::February,
Month::February => Month::March,
@@ -88,7 +90,8 @@ impl Month {
/// ----------- | --------- | ---------- | --- | ---------
/// `m.pred()`: | `December` | `January` | `...` | `November`
#[inline]
- pub fn pred(&self) -> Month {
+ #[must_use]
+ pub const fn pred(&self) -> Month {
match *self {
Month::January => Month::December,
Month::February => Month::January,
@@ -111,7 +114,8 @@ impl Month {
/// -------------------------| --------- | ---------- | --- | -----
/// `m.number_from_month()`: | 1 | 2 | `...` | 12
#[inline]
- pub fn number_from_month(&self) -> u32 {
+ #[must_use]
+ pub const fn number_from_month(&self) -> u32 {
match *self {
Month::January => 1,
Month::February => 2,
@@ -135,7 +139,8 @@ impl Month {
///
/// assert_eq!(Month::January.name(), "January")
/// ```
- pub fn name(&self) -> &'static str {
+ #[must_use]
+ pub const fn name(&self) -> &'static str {
match *self {
Month::January => "January",
Month::February => "February",
@@ -153,6 +158,28 @@ impl Month {
}
}
+impl TryFrom<u8> for Month {
+ type Error = OutOfRange;
+
+ fn try_from(value: u8) -> Result<Self, Self::Error> {
+ match value {
+ 1 => Ok(Month::January),
+ 2 => Ok(Month::February),
+ 3 => Ok(Month::March),
+ 4 => Ok(Month::April),
+ 5 => Ok(Month::May),
+ 6 => Ok(Month::June),
+ 7 => Ok(Month::July),
+ 8 => Ok(Month::August),
+ 9 => Ok(Month::September),
+ 10 => Ok(Month::October),
+ 11 => Ok(Month::November),
+ 12 => Ok(Month::December),
+ _ => Err(OutOfRange::new()),
+ }
+ }
+}
+
impl num_traits::FromPrimitive for Month {
/// Returns an `Option<Month>` from a i64, assuming a 1-index, January = 1.
///
@@ -322,7 +349,22 @@ mod month_serde {
#[cfg(test)]
mod tests {
use super::Month;
- use crate::{Datelike, TimeZone, Utc};
+ use crate::{Datelike, OutOfRange, TimeZone, Utc};
+
+ #[test]
+ fn test_month_enum_try_from() {
+ assert_eq!(Month::try_from(1), Ok(Month::January));
+ assert_eq!(Month::try_from(2), Ok(Month::February));
+ assert_eq!(Month::try_from(12), Ok(Month::December));
+ assert_eq!(Month::try_from(13), Err(OutOfRange::new()));
+
+ let date = Utc.with_ymd_and_hms(2019, 10, 28, 9, 10, 11).unwrap();
+ assert_eq!(Month::try_from(date.month() as u8), Ok(Month::October));
+
+ let month = Month::January;
+ let dt = Utc.with_ymd_and_hms(2019, month.number_from_month(), 28, 9, 10, 11).unwrap();
+ assert_eq!((dt.year(), dt.month(), dt.day()), (2019, 1, 28));
+ }
#[test]
fn test_month_enum_primitive_parse() {
@@ -352,4 +394,13 @@ mod tests {
assert_eq!(Month::January.pred(), Month::December);
assert_eq!(Month::February.pred(), Month::January);
}
+
+ #[test]
+ fn test_month_partial_ord() {
+ assert!(Month::January <= Month::January);
+ assert!(Month::January < Month::February);
+ assert!(Month::January < Month::December);
+ assert!(Month::July >= Month::May);
+ assert!(Month::September > Month::March);
+ }
}
diff --git a/vendor/chrono/src/naive/date.rs b/vendor/chrono/src/naive/date.rs
index 64af978f3..b9404a15f 100644
--- a/vendor/chrono/src/naive/date.rs
+++ b/vendor/chrono/src/naive/date.rs
@@ -5,12 +5,9 @@
#[cfg(any(feature = "alloc", feature = "std", test))]
use core::borrow::Borrow;
-use core::convert::TryFrom;
use core::ops::{Add, AddAssign, RangeInclusive, Sub, SubAssign};
use core::{fmt, str};
-use num_integer::div_mod_floor;
-use num_traits::ToPrimitive;
#[cfg(feature = "rkyv")]
use rkyv::{Archive, Deserialize, Serialize};
@@ -20,8 +17,10 @@ use pure_rust_locales::Locale;
#[cfg(any(feature = "alloc", feature = "std", test))]
use crate::format::DelayedFormat;
-use crate::format::{parse, write_hundreds, ParseError, ParseResult, Parsed, StrftimeItems};
-use crate::format::{Item, Numeric, Pad};
+use crate::format::{
+ parse, parse_and_remainder, write_hundreds, Item, Numeric, Pad, ParseError, ParseResult,
+ Parsed, StrftimeItems,
+};
use crate::month::Months;
use crate::naive::{IsoWeek, NaiveDateTime, NaiveTime};
use crate::oldtime::Duration as OldDuration;
@@ -77,11 +76,15 @@ impl NaiveWeek {
/// assert!(week.first_day() <= date);
/// ```
#[inline]
+ #[must_use]
pub fn first_day(&self) -> NaiveDate {
- let start = self.start.num_days_from_monday();
- let end = self.date.weekday().num_days_from_monday();
- let days = if start > end { 7 - start + end } else { end - start };
- self.date - Duration::days(days.into())
+ let start = self.start.num_days_from_monday() as i32;
+ let ref_day = self.date.weekday().num_days_from_monday() as i32;
+ // Calculate the number of days to subtract from `self.date`.
+ // Do not construct an intermediate date beyond `self.date`, because that may be out of
+ // range if `date` is close to `NaiveDate::MAX`.
+ let days = start - ref_day - if start > ref_day { 7 } else { 0 };
+ self.date.diff_days(days as i64).unwrap()
}
/// Returns a date representing the last day of the week.
@@ -96,8 +99,15 @@ impl NaiveWeek {
/// assert!(week.last_day() >= date);
/// ```
#[inline]
+ #[must_use]
pub fn last_day(&self) -> NaiveDate {
- self.first_day() + Duration::days(6)
+ let end = self.start.pred().num_days_from_monday() as i32;
+ let ref_day = self.date.weekday().num_days_from_monday() as i32;
+ // Calculate the number of days to add to `self.date`.
+ // Do not construct an intermediate date before `self.date` (like with `first_day()`),
+ // because that may be out of range if `date` is close to `NaiveDate::MIN`.
+ let days = end - ref_day + if end < ref_day { 7 } else { 0 };
+ self.date.diff_days(days as i64).unwrap()
}
/// Returns a [`RangeInclusive<T>`] representing the whole week bounded by
@@ -115,6 +125,7 @@ impl NaiveWeek {
/// assert!(days.contains(&date));
/// ```
#[inline]
+ #[must_use]
pub fn days(&self) -> RangeInclusive<NaiveDate> {
self.first_day()..=self.last_day()
}
@@ -137,8 +148,7 @@ impl Days {
}
/// ISO 8601 calendar date without timezone.
-/// Allows for every [proleptic Gregorian date](#calendar-date)
-/// from Jan 1, 262145 BCE to Dec 31, 262143 CE.
+/// Allows for every [proleptic Gregorian date] from Jan 1, 262145 BCE to Dec 31, 262143 CE.
/// Also supports the conversion from ISO 8601 ordinal and week date.
///
/// # Calendar Date
@@ -184,6 +194,8 @@ impl Days {
/// The year number is the same as that of the [calendar date](#calendar-date).
///
/// This is currently the internal format of Chrono's date types.
+///
+/// [proleptic Gregorian date]: crate::NaiveDate#calendar-date
#[derive(PartialEq, Eq, Hash, PartialOrd, Ord, Copy, Clone)]
#[cfg_attr(feature = "rkyv", derive(Archive, Deserialize, Serialize))]
pub struct NaiveDate {
@@ -239,19 +251,35 @@ impl NaiveDate {
pub(crate) fn weeks_from(&self, day: Weekday) -> i32 {
(self.ordinal() as i32 - self.weekday().num_days_from(day) as i32 + 6) / 7
}
- /// Makes a new `NaiveDate` from year and packed ordinal-flags, with a verification.
- fn from_of(year: i32, of: Of) -> Option<NaiveDate> {
- if (MIN_YEAR..=MAX_YEAR).contains(&year) && of.valid() {
- let Of(of) = of;
- Some(NaiveDate { ymdf: (year << 13) | (of as DateImpl) })
- } else {
- None
+
+ /// Makes a new `NaiveDate` from year, ordinal and flags.
+ /// Does not check whether the flags are correct for the provided year.
+ const fn from_ordinal_and_flags(
+ year: i32,
+ ordinal: u32,
+ flags: YearFlags,
+ ) -> Option<NaiveDate> {
+ if year < MIN_YEAR || year > MAX_YEAR {
+ return None; // Out-of-range
+ }
+ // Enable debug check once the MSRV >= 1.57 (panicking in const feature)
+ // debug_assert!(YearFlags::from_year(year).0 == flags.0);
+ match Of::new(ordinal, flags) {
+ Some(of) => Some(NaiveDate { ymdf: (year << 13) | (of.inner() as DateImpl) }),
+ None => None, // Invalid: Ordinal outside of the nr of days in a year with those flags.
}
}
- /// Makes a new `NaiveDate` from year and packed month-day-flags, with a verification.
- fn from_mdf(year: i32, mdf: Mdf) -> Option<NaiveDate> {
- NaiveDate::from_of(year, mdf.to_of())
+ /// Makes a new `NaiveDate` from year and packed month-day-flags.
+ /// Does not check whether the flags are correct for the provided year.
+ const fn from_mdf(year: i32, mdf: Mdf) -> Option<NaiveDate> {
+ if year < MIN_YEAR || year > MAX_YEAR {
+ return None; // Out-of-range
+ }
+ match mdf.to_of() {
+ Some(of) => Some(NaiveDate { ymdf: (year << 13) | (of.inner() as DateImpl) }),
+ None => None, // Non-existing date
+ }
}
/// Makes a new `NaiveDate` from the [calendar date](#calendar-date)
@@ -259,6 +287,7 @@ impl NaiveDate {
///
/// Panics on the out-of-range date, invalid month and/or day.
#[deprecated(since = "0.4.23", note = "use `from_ymd_opt()` instead")]
+ #[must_use]
pub fn from_ymd(year: i32, month: u32, day: u32) -> NaiveDate {
NaiveDate::from_ymd_opt(year, month, day).expect("invalid or out-of-range date")
}
@@ -282,6 +311,7 @@ impl NaiveDate {
/// assert!(from_ymd_opt(400000, 1, 1).is_none());
/// assert!(from_ymd_opt(-400000, 1, 1).is_none());
/// ```
+ #[must_use]
pub fn from_ymd_opt(year: i32, month: u32, day: u32) -> Option<NaiveDate> {
let flags = YearFlags::from_year(year);
NaiveDate::from_mdf(year, Mdf::new(month, day, flags)?)
@@ -292,6 +322,7 @@ impl NaiveDate {
///
/// Panics on the out-of-range date and/or invalid day of year.
#[deprecated(since = "0.4.23", note = "use `from_yo_opt()` instead")]
+ #[must_use]
pub fn from_yo(year: i32, ordinal: u32) -> NaiveDate {
NaiveDate::from_yo_opt(year, ordinal).expect("invalid or out-of-range date")
}
@@ -316,9 +347,10 @@ impl NaiveDate {
/// assert!(from_yo_opt(400000, 1).is_none());
/// assert!(from_yo_opt(-400000, 1).is_none());
/// ```
+ #[must_use]
pub fn from_yo_opt(year: i32, ordinal: u32) -> Option<NaiveDate> {
let flags = YearFlags::from_year(year);
- NaiveDate::from_of(year, Of::new(ordinal, flags)?)
+ NaiveDate::from_ordinal_and_flags(year, ordinal, flags)
}
/// Makes a new `NaiveDate` from the [ISO week date](#week-date)
@@ -327,6 +359,7 @@ impl NaiveDate {
///
/// Panics on the out-of-range date and/or invalid week number.
#[deprecated(since = "0.4.23", note = "use `from_isoywd_opt()` instead")]
+ #[must_use]
pub fn from_isoywd(year: i32, week: u32, weekday: Weekday) -> NaiveDate {
NaiveDate::from_isoywd_opt(year, week, weekday).expect("invalid or out-of-range date")
}
@@ -342,7 +375,7 @@ impl NaiveDate {
/// ```
/// use chrono::{NaiveDate, Weekday};
///
- /// let from_ymd = NaiveDate::from_ymd;
+ /// let from_ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap();
/// let from_isoywd_opt = NaiveDate::from_isoywd_opt;
///
/// assert_eq!(from_isoywd_opt(2015, 0, Weekday::Sun), None);
@@ -358,7 +391,7 @@ impl NaiveDate {
///
/// ```
/// # use chrono::{NaiveDate, Weekday};
- /// # let from_ymd = NaiveDate::from_ymd;
+ /// # let from_ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap();
/// # let from_isoywd_opt = NaiveDate::from_isoywd_opt;
/// // Mo Tu We Th Fr Sa Su
/// // 2014-W52 22 23 24 25 26 27 28 has 4+ days of new year,
@@ -375,6 +408,7 @@ impl NaiveDate {
/// assert_eq!(from_isoywd_opt(2015, 54, Weekday::Mon), None);
/// assert_eq!(from_isoywd_opt(2016, 1, Weekday::Mon), Some(from_ymd(2016, 1, 4)));
/// ```
+ #[must_use]
pub fn from_isoywd_opt(year: i32, week: u32, weekday: Weekday) -> Option<NaiveDate> {
let flags = YearFlags::from_year(year);
let nweeks = flags.nisoweeks();
@@ -385,20 +419,21 @@ impl NaiveDate {
if weekord <= delta {
// ordinal < 1, previous year
let prevflags = YearFlags::from_year(year - 1);
- NaiveDate::from_of(
+ NaiveDate::from_ordinal_and_flags(
year - 1,
- Of::new(weekord + prevflags.ndays() - delta, prevflags)?,
+ weekord + prevflags.ndays() - delta,
+ prevflags,
)
} else {
let ordinal = weekord - delta;
let ndays = flags.ndays();
if ordinal <= ndays {
// this year
- NaiveDate::from_of(year, Of::new(ordinal, flags)?)
+ NaiveDate::from_ordinal_and_flags(year, ordinal, flags)
} else {
// ordinal > ndays, next year
let nextflags = YearFlags::from_year(year + 1);
- NaiveDate::from_of(year + 1, Of::new(ordinal - ndays, nextflags)?)
+ NaiveDate::from_ordinal_and_flags(year + 1, ordinal - ndays, nextflags)
}
}
} else {
@@ -412,6 +447,7 @@ impl NaiveDate {
/// Panics if the date is out of range.
#[deprecated(since = "0.4.23", note = "use `from_num_days_from_ce_opt()` instead")]
#[inline]
+ #[must_use]
pub fn from_num_days_from_ce(days: i32) -> NaiveDate {
NaiveDate::from_num_days_from_ce_opt(days).expect("out-of-range date")
}
@@ -436,12 +472,13 @@ impl NaiveDate {
/// assert_eq!(from_ndays_opt(100_000_000), None);
/// assert_eq!(from_ndays_opt(-100_000_000), None);
/// ```
+ #[must_use]
pub fn from_num_days_from_ce_opt(days: i32) -> Option<NaiveDate> {
- let days = days + 365; // make December 31, 1 BCE equal to day 0
+ let days = days.checked_add(365)?; // make December 31, 1 BCE equal to day 0
let (year_div_400, cycle) = div_mod_floor(days, 146_097);
let (year_mod_400, ordinal) = internals::cycle_to_yo(cycle as u32);
let flags = YearFlags::from_year_mod_400(year_mod_400 as i32);
- NaiveDate::from_of(year_div_400 * 400 + year_mod_400 as i32, Of::new(ordinal, flags)?)
+ NaiveDate::from_ordinal_and_flags(year_div_400 * 400 + year_mod_400 as i32, ordinal, flags)
}
/// Makes a new `NaiveDate` by counting the number of occurrences of a particular day-of-week
@@ -455,6 +492,7 @@ impl NaiveDate {
///
/// `n` is 1-indexed. Passing `n=0` will cause a panic.
#[deprecated(since = "0.4.23", note = "use `from_weekday_of_month_opt()` instead")]
+ #[must_use]
pub fn from_weekday_of_month(year: i32, month: u32, weekday: Weekday, n: u8) -> NaiveDate {
NaiveDate::from_weekday_of_month_opt(year, month, weekday, n).expect("out-of-range date")
}
@@ -471,6 +509,7 @@ impl NaiveDate {
///
/// Returns `None` if `n` out-of-range; ie. if `n` is larger than the number of `weekday` in
/// `month` (eg. the 6th Friday of March 2017), or if `n == 0`.
+ #[must_use]
pub fn from_weekday_of_month_opt(
year: i32,
month: u32,
@@ -534,6 +573,28 @@ impl NaiveDate {
parsed.to_naive_date()
}
+ /// Parses a string from a user-specified format into a new `NaiveDate` value, and a slice with
+ /// the remaining portion of the string.
+ /// See the [`format::strftime` module](../format/strftime/index.html)
+ /// on the supported escape sequences.
+ ///
+ /// Similar to [`parse_from_str`](#method.parse_from_str).
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// # use chrono::{NaiveDate};
+ /// let (date, remainder) = NaiveDate::parse_and_remainder(
+ /// "2015-02-18 trailing text", "%Y-%m-%d").unwrap();
+ /// assert_eq!(date, NaiveDate::from_ymd_opt(2015, 2, 18).unwrap());
+ /// assert_eq!(remainder, " trailing text");
+ /// ```
+ pub fn parse_and_remainder<'a>(s: &'a str, fmt: &str) -> ParseResult<(NaiveDate, &'a str)> {
+ let mut parsed = Parsed::new();
+ let remainder = parse_and_remainder(&mut parsed, s, StrftimeItems::new(fmt))?;
+ parsed.to_naive_date().map(|d| (d, remainder))
+ }
+
/// Add a duration in [`Months`] to the date
///
/// If the day would be out of range for the resulting month, use the last day for that month.
@@ -551,6 +612,7 @@ impl NaiveDate {
/// Some(NaiveDate::from_ymd_opt(2022, 9, 30).unwrap())
/// );
/// ```
+ #[must_use]
pub fn checked_add_months(self, months: Months) -> Option<Self> {
if months.0 == 0 {
return Some(self);
@@ -581,6 +643,7 @@ impl NaiveDate {
/// None
/// );
/// ```
+ #[must_use]
pub fn checked_sub_months(self, months: Months) -> Option<Self> {
if months.0 == 0 {
return Some(self);
@@ -654,6 +717,7 @@ impl NaiveDate {
/// None
/// );
/// ```
+ #[must_use]
pub fn checked_add_days(self, days: Days) -> Option<Self> {
if days.0 == 0 {
return Some(self);
@@ -677,6 +741,7 @@ impl NaiveDate {
/// None
/// );
/// ```
+ #[must_use]
pub fn checked_sub_days(self, days: Days) -> Option<Self> {
if days.0 == 0 {
return Some(self);
@@ -708,6 +773,7 @@ impl NaiveDate {
/// assert_eq!(dt.time(), t);
/// ```
#[inline]
+ #[must_use]
pub const fn and_time(&self, time: NaiveTime) -> NaiveDateTime {
NaiveDateTime::new(*self, time)
}
@@ -720,6 +786,7 @@ impl NaiveDate {
/// Panics on invalid hour, minute and/or second.
#[deprecated(since = "0.4.23", note = "use `and_hms_opt()` instead")]
#[inline]
+ #[must_use]
pub fn and_hms(&self, hour: u32, min: u32, sec: u32) -> NaiveDateTime {
self.and_hms_opt(hour, min, sec).expect("invalid time")
}
@@ -743,6 +810,7 @@ impl NaiveDate {
/// assert!(d.and_hms_opt(24, 34, 56).is_none());
/// ```
#[inline]
+ #[must_use]
pub fn and_hms_opt(&self, hour: u32, min: u32, sec: u32) -> Option<NaiveDateTime> {
NaiveTime::from_hms_opt(hour, min, sec).map(|time| self.and_time(time))
}
@@ -755,6 +823,7 @@ impl NaiveDate {
/// Panics on invalid hour, minute, second and/or millisecond.
#[deprecated(since = "0.4.23", note = "use `and_hms_milli_opt()` instead")]
#[inline]
+ #[must_use]
pub fn and_hms_milli(&self, hour: u32, min: u32, sec: u32, milli: u32) -> NaiveDateTime {
self.and_hms_milli_opt(hour, min, sec, milli).expect("invalid time")
}
@@ -780,6 +849,7 @@ impl NaiveDate {
/// assert!(d.and_hms_milli_opt(24, 34, 56, 789).is_none());
/// ```
#[inline]
+ #[must_use]
pub fn and_hms_milli_opt(
&self,
hour: u32,
@@ -804,7 +874,7 @@ impl NaiveDate {
///
/// let d = NaiveDate::from_ymd_opt(2015, 6, 3).unwrap();
///
- /// let dt: NaiveDateTime = d.and_hms_micro(12, 34, 56, 789_012);
+ /// let dt: NaiveDateTime = d.and_hms_micro_opt(12, 34, 56, 789_012).unwrap();
/// assert_eq!(dt.year(), 2015);
/// assert_eq!(dt.weekday(), Weekday::Wed);
/// assert_eq!(dt.second(), 56);
@@ -812,6 +882,7 @@ impl NaiveDate {
/// ```
#[deprecated(since = "0.4.23", note = "use `and_hms_micro_opt()` instead")]
#[inline]
+ #[must_use]
pub fn and_hms_micro(&self, hour: u32, min: u32, sec: u32, micro: u32) -> NaiveDateTime {
self.and_hms_micro_opt(hour, min, sec, micro).expect("invalid time")
}
@@ -837,6 +908,7 @@ impl NaiveDate {
/// assert!(d.and_hms_micro_opt(24, 34, 56, 789_012).is_none());
/// ```
#[inline]
+ #[must_use]
pub fn and_hms_micro_opt(
&self,
hour: u32,
@@ -855,6 +927,7 @@ impl NaiveDate {
/// Panics on invalid hour, minute, second and/or nanosecond.
#[deprecated(since = "0.4.23", note = "use `and_hms_nano_opt()` instead")]
#[inline]
+ #[must_use]
pub fn and_hms_nano(&self, hour: u32, min: u32, sec: u32, nano: u32) -> NaiveDateTime {
self.and_hms_nano_opt(hour, min, sec, nano).expect("invalid time")
}
@@ -880,6 +953,7 @@ impl NaiveDate {
/// assert!(d.and_hms_nano_opt(24, 34, 56, 789_012_345).is_none());
/// ```
#[inline]
+ #[must_use]
pub fn and_hms_nano_opt(
&self,
hour: u32,
@@ -899,7 +973,7 @@ impl NaiveDate {
/// Returns the packed ordinal-flags.
#[inline]
const fn of(&self) -> Of {
- Of((self.ymdf & 0b1_1111_1111_1111) as u32)
+ Of::from_date_impl(self.ymdf)
}
/// Makes a new `NaiveDate` with the packed month-day-flags changed.
@@ -907,20 +981,16 @@ impl NaiveDate {
/// Returns `None` when the resulting `NaiveDate` would be invalid.
#[inline]
fn with_mdf(&self, mdf: Mdf) -> Option<NaiveDate> {
- self.with_of(mdf.to_of())
+ Some(self.with_of(mdf.to_of()?))
}
/// Makes a new `NaiveDate` with the packed ordinal-flags changed.
///
/// Returns `None` when the resulting `NaiveDate` would be invalid.
+ /// Does not check if the year flags match the year.
#[inline]
- fn with_of(&self, of: Of) -> Option<NaiveDate> {
- if of.valid() {
- let Of(of) = of;
- Some(NaiveDate { ymdf: (self.ymdf & !0b1_1111_1111_1111) | of as DateImpl })
- } else {
- None
- }
+ const fn with_of(&self, of: Of) -> NaiveDate {
+ NaiveDate { ymdf: (self.ymdf & !0b1_1111_1111_1111) | of.inner() as DateImpl }
}
/// Makes a new `NaiveDate` for the next calendar date.
@@ -928,6 +998,7 @@ impl NaiveDate {
/// Panics when `self` is the last representable date.
#[deprecated(since = "0.4.23", note = "use `succ_opt()` instead")]
#[inline]
+ #[must_use]
pub fn succ(&self) -> NaiveDate {
self.succ_opt().expect("out of bound")
}
@@ -946,8 +1017,12 @@ impl NaiveDate {
/// assert_eq!(NaiveDate::MAX.succ_opt(), None);
/// ```
#[inline]
+ #[must_use]
pub fn succ_opt(&self) -> Option<NaiveDate> {
- self.with_of(self.of().succ()).or_else(|| NaiveDate::from_ymd_opt(self.year() + 1, 1, 1))
+ match self.of().succ() {
+ Some(of) => Some(self.with_of(of)),
+ None => NaiveDate::from_ymd_opt(self.year() + 1, 1, 1),
+ }
}
/// Makes a new `NaiveDate` for the previous calendar date.
@@ -955,6 +1030,7 @@ impl NaiveDate {
/// Panics when `self` is the first representable date.
#[deprecated(since = "0.4.23", note = "use `pred_opt()` instead")]
#[inline]
+ #[must_use]
pub fn pred(&self) -> NaiveDate {
self.pred_opt().expect("out of bound")
}
@@ -973,8 +1049,12 @@ impl NaiveDate {
/// assert_eq!(NaiveDate::MIN.pred_opt(), None);
/// ```
#[inline]
+ #[must_use]
pub fn pred_opt(&self) -> Option<NaiveDate> {
- self.with_of(self.of().pred()).or_else(|| NaiveDate::from_ymd_opt(self.year() - 1, 12, 31))
+ match self.of().pred() {
+ Some(of) => Some(self.with_of(of)),
+ None => NaiveDate::from_ymd_opt(self.year() - 1, 12, 31),
+ }
}
/// Adds the `days` part of given `Duration` to the current date.
@@ -995,17 +1075,18 @@ impl NaiveDate {
/// assert_eq!(d.checked_add_signed(Duration::days(-1_000_000_000)), None);
/// assert_eq!(NaiveDate::MAX.checked_add_signed(Duration::days(1)), None);
/// ```
+ #[must_use]
pub fn checked_add_signed(self, rhs: OldDuration) -> Option<NaiveDate> {
let year = self.year();
let (mut year_div_400, year_mod_400) = div_mod_floor(year, 400);
let cycle = internals::yo_to_cycle(year_mod_400 as u32, self.of().ordinal());
- let cycle = (cycle as i32).checked_add(rhs.num_days().to_i32()?)?;
+ let cycle = (cycle as i32).checked_add(i32::try_from(rhs.num_days()).ok()?)?;
let (cycle_div_400y, cycle) = div_mod_floor(cycle, 146_097);
year_div_400 += cycle_div_400y;
let (year_mod_400, ordinal) = internals::cycle_to_yo(cycle as u32);
let flags = YearFlags::from_year_mod_400(year_mod_400 as i32);
- NaiveDate::from_of(year_div_400 * 400 + year_mod_400 as i32, Of::new(ordinal, flags)?)
+ NaiveDate::from_ordinal_and_flags(year_div_400 * 400 + year_mod_400 as i32, ordinal, flags)
}
/// Subtracts the `days` part of given `Duration` from the current date.
@@ -1026,17 +1107,18 @@ impl NaiveDate {
/// assert_eq!(d.checked_sub_signed(Duration::days(-1_000_000_000)), None);
/// assert_eq!(NaiveDate::MIN.checked_sub_signed(Duration::days(1)), None);
/// ```
+ #[must_use]
pub fn checked_sub_signed(self, rhs: OldDuration) -> Option<NaiveDate> {
let year = self.year();
let (mut year_div_400, year_mod_400) = div_mod_floor(year, 400);
let cycle = internals::yo_to_cycle(year_mod_400 as u32, self.of().ordinal());
- let cycle = (cycle as i32).checked_sub(rhs.num_days().to_i32()?)?;
+ let cycle = (cycle as i32).checked_sub(i32::try_from(rhs.num_days()).ok()?)?;
let (cycle_div_400y, cycle) = div_mod_floor(cycle, 146_097);
year_div_400 += cycle_div_400y;
let (year_mod_400, ordinal) = internals::cycle_to_yo(cycle as u32);
let flags = YearFlags::from_year_mod_400(year_mod_400 as i32);
- NaiveDate::from_of(year_div_400 * 400 + year_mod_400 as i32, Of::new(ordinal, flags)?)
+ NaiveDate::from_ordinal_and_flags(year_div_400 * 400 + year_mod_400 as i32, ordinal, flags)
}
/// Subtracts another `NaiveDate` from the current date.
@@ -1050,7 +1132,7 @@ impl NaiveDate {
/// ```
/// use chrono::{Duration, NaiveDate};
///
- /// let from_ymd = NaiveDate::from_ymd;
+ /// let from_ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap();
/// let since = NaiveDate::signed_duration_since;
///
/// assert_eq!(since(from_ymd(2014, 1, 1), from_ymd(2014, 1, 1)), Duration::zero());
@@ -1061,6 +1143,7 @@ impl NaiveDate {
/// assert_eq!(since(from_ymd(2014, 1, 1), from_ymd(2010, 1, 1)), Duration::days(365*4 + 1));
/// assert_eq!(since(from_ymd(2014, 1, 1), from_ymd(1614, 1, 1)), Duration::days(365*400 + 97));
/// ```
+ #[must_use]
pub fn signed_duration_since(self, rhs: NaiveDate) -> OldDuration {
let year1 = self.year();
let year2 = rhs.year();
@@ -1074,6 +1157,7 @@ impl NaiveDate {
}
/// Returns the number of whole years from the given `base` until `self`.
+ #[must_use]
pub fn years_since(&self, base: Self) -> Option<u32> {
let mut years = self.year() - base.year();
if (self.month(), self.day()) < (base.month(), base.day()) {
@@ -1116,6 +1200,7 @@ impl NaiveDate {
#[cfg(any(feature = "alloc", feature = "std", test))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "alloc", feature = "std"))))]
#[inline]
+ #[must_use]
pub fn format_with_items<'a, I, B>(&self, items: I) -> DelayedFormat<I>
where
I: Iterator<Item = B> + Clone,
@@ -1159,6 +1244,7 @@ impl NaiveDate {
#[cfg(any(feature = "alloc", feature = "std", test))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "alloc", feature = "std"))))]
#[inline]
+ #[must_use]
pub fn format<'a>(&self, fmt: &'a str) -> DelayedFormat<StrftimeItems<'a>> {
self.format_with_items(StrftimeItems::new(fmt))
}
@@ -1167,6 +1253,7 @@ impl NaiveDate {
#[cfg(feature = "unstable-locales")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable-locales")))]
#[inline]
+ #[must_use]
pub fn format_localized_with_items<'a, I, B>(
&self,
items: I,
@@ -1186,6 +1273,7 @@ impl NaiveDate {
#[cfg(feature = "unstable-locales")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable-locales")))]
#[inline]
+ #[must_use]
pub fn format_localized<'a>(
&self,
fmt: &'a str,
@@ -1345,7 +1433,7 @@ impl Datelike for NaiveDate {
/// let d = NaiveDate::from_ymd_opt(y, m, 1).unwrap();
///
/// // ...is preceded by the last day of the original month
- /// d.pred().day()
+ /// d.pred_opt().unwrap().day()
/// }
///
/// assert_eq!(ndays_in_month(2015, 8), 31);
@@ -1401,7 +1489,7 @@ impl Datelike for NaiveDate {
/// let d = NaiveDate::from_ymd_opt(year + 1, 1, 1).unwrap();
///
/// // ...is preceded by the last day of the original year
- /// d.pred().ordinal()
+ /// d.pred_opt().unwrap().ordinal()
/// }
///
/// assert_eq!(ndays_in_year(2015), 365);
@@ -1521,7 +1609,8 @@ impl Datelike for NaiveDate {
/// ```
#[inline]
fn with_month0(&self, month0: u32) -> Option<NaiveDate> {
- self.with_mdf(self.mdf().with_month(month0 + 1)?)
+ let month = month0.checked_add(1)?;
+ self.with_mdf(self.mdf().with_month(month)?)
}
/// Makes a new `NaiveDate` with the day of month (starting from 1) changed.
@@ -1559,7 +1648,8 @@ impl Datelike for NaiveDate {
/// ```
#[inline]
fn with_day0(&self, day0: u32) -> Option<NaiveDate> {
- self.with_mdf(self.mdf().with_day(day0 + 1)?)
+ let day = day0.checked_add(1)?;
+ self.with_mdf(self.mdf().with_day(day)?)
}
/// Makes a new `NaiveDate` with the day of year (starting from 1) changed.
@@ -1583,7 +1673,7 @@ impl Datelike for NaiveDate {
/// ```
#[inline]
fn with_ordinal(&self, ordinal: u32) -> Option<NaiveDate> {
- self.with_of(self.of().with_ordinal(ordinal)?)
+ self.of().with_ordinal(ordinal).map(|of| self.with_of(of))
}
/// Makes a new `NaiveDate` with the day of year (starting from 0) changed.
@@ -1607,22 +1697,22 @@ impl Datelike for NaiveDate {
/// ```
#[inline]
fn with_ordinal0(&self, ordinal0: u32) -> Option<NaiveDate> {
- self.with_of(self.of().with_ordinal(ordinal0 + 1)?)
+ let ordinal = ordinal0.checked_add(1)?;
+ self.with_ordinal(ordinal)
}
}
/// An addition of `Duration` to `NaiveDate` discards the fractional days,
/// rounding to the closest integral number of days towards `Duration::zero()`.
///
-/// Panics on underflow or overflow.
-/// Use [`NaiveDate::checked_add_signed`](#method.checked_add_signed) to detect that.
+/// Panics on underflow or overflow. Use [`NaiveDate::checked_add_signed`] to detect that.
///
/// # Example
///
/// ```
/// use chrono::{Duration, NaiveDate};
///
-/// let from_ymd = NaiveDate::from_ymd;
+/// let from_ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap();
///
/// assert_eq!(from_ymd(2014, 1, 1) + Duration::zero(), from_ymd(2014, 1, 1));
/// assert_eq!(from_ymd(2014, 1, 1) + Duration::seconds(86399), from_ymd(2014, 1, 1));
@@ -1633,6 +1723,8 @@ impl Datelike for NaiveDate {
/// assert_eq!(from_ymd(2014, 1, 1) + Duration::days(365*4 + 1), from_ymd(2018, 1, 1));
/// assert_eq!(from_ymd(2014, 1, 1) + Duration::days(365*400 + 97), from_ymd(2414, 1, 1));
/// ```
+///
+/// [`NaiveDate::checked_add_signed`]: crate::NaiveDate::checked_add_signed
impl Add<OldDuration> for NaiveDate {
type Output = NaiveDate;
@@ -1661,9 +1753,9 @@ impl Add<Months> for NaiveDate {
/// # Example
///
/// ```
- /// use chrono::{Duration, NaiveDate, Months};
+ /// use chrono::{NaiveDate, Months};
///
- /// let from_ymd = NaiveDate::from_ymd;
+ /// let from_ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap();
///
/// assert_eq!(from_ymd(2014, 1, 1) + Months::new(1), from_ymd(2014, 2, 1));
/// assert_eq!(from_ymd(2014, 1, 1) + Months::new(11), from_ymd(2014, 12, 1));
@@ -1689,9 +1781,9 @@ impl Sub<Months> for NaiveDate {
/// # Example
///
/// ```
- /// use chrono::{Duration, NaiveDate, Months};
+ /// use chrono::{NaiveDate, Months};
///
- /// let from_ymd = NaiveDate::from_ymd;
+ /// let from_ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap();
///
/// assert_eq!(from_ymd(2014, 1, 1) - Months::new(11), from_ymd(2013, 2, 1));
/// assert_eq!(from_ymd(2014, 1, 1) - Months::new(12), from_ymd(2013, 1, 1));
@@ -1722,15 +1814,14 @@ impl Sub<Days> for NaiveDate {
/// rounding to the closest integral number of days towards `Duration::zero()`.
/// It is the same as the addition with a negated `Duration`.
///
-/// Panics on underflow or overflow.
-/// Use [`NaiveDate::checked_sub_signed`](#method.checked_sub_signed) to detect that.
+/// Panics on underflow or overflow. Use [`NaiveDate::checked_sub_signed`] to detect that.
///
/// # Example
///
/// ```
/// use chrono::{Duration, NaiveDate};
///
-/// let from_ymd = NaiveDate::from_ymd;
+/// let from_ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap();
///
/// assert_eq!(from_ymd(2014, 1, 1) - Duration::zero(), from_ymd(2014, 1, 1));
/// assert_eq!(from_ymd(2014, 1, 1) - Duration::seconds(86399), from_ymd(2014, 1, 1));
@@ -1741,6 +1832,8 @@ impl Sub<Days> for NaiveDate {
/// assert_eq!(from_ymd(2014, 1, 1) - Duration::days(365*4 + 1), from_ymd(2010, 1, 1));
/// assert_eq!(from_ymd(2014, 1, 1) - Duration::days(365*400 + 97), from_ymd(1614, 1, 1));
/// ```
+///
+/// [`NaiveDate::checked_sub_signed`]: crate::NaiveDate::checked_sub_signed
impl Sub<OldDuration> for NaiveDate {
type Output = NaiveDate;
@@ -1771,7 +1864,7 @@ impl SubAssign<OldDuration> for NaiveDate {
/// ```
/// use chrono::{Duration, NaiveDate};
///
-/// let from_ymd = NaiveDate::from_ymd;
+/// let from_ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap();
///
/// assert_eq!(from_ymd(2014, 1, 1) - from_ymd(2014, 1, 1), Duration::zero());
/// assert_eq!(from_ymd(2014, 1, 1) - from_ymd(2013, 12, 31), Duration::days(1));
@@ -1790,6 +1883,12 @@ impl Sub<NaiveDate> for NaiveDate {
}
}
+impl From<NaiveDateTime> for NaiveDate {
+ fn from(naive_datetime: NaiveDateTime) -> Self {
+ naive_datetime.date()
+ }
+}
+
/// Iterator over `NaiveDate` with a step size of one day.
#[derive(Debug, Copy, Clone, Hash, PartialEq, PartialOrd, Eq, Ord)]
pub struct NaiveDateDaysIterator {
@@ -1993,6 +2092,10 @@ impl Default for NaiveDate {
}
}
+fn div_mod_floor(val: i32, div: i32) -> (i32, i32) {
+ (val.div_euclid(div), val.rem_euclid(div))
+}
+
#[cfg(all(test, any(feature = "rustc-serialize", feature = "serde")))]
fn test_encodable_json<F, E>(to_string: F)
where
@@ -2183,10 +2286,7 @@ mod tests {
};
use crate::oldtime::Duration;
use crate::{Datelike, Weekday};
- use std::{
- convert::{TryFrom, TryInto},
- i32, u32,
- };
+ use std::{i32, u32};
#[test]
fn diff_months() {
@@ -2208,7 +2308,7 @@ mod tests {
assert_eq!(
NaiveDate::from_ymd_opt(2022, 8, 3)
.unwrap()
- .checked_sub_months(Months::new((i32::MIN as i64).abs() as u32 + 1)),
+ .checked_sub_months(Months::new(i32::MIN.unsigned_abs() + 1)),
None
);
@@ -2275,9 +2375,7 @@ mod tests {
#[test]
fn test_readme_doomsday() {
- use num_iter::range_inclusive;
-
- for y in range_inclusive(NaiveDate::MIN.year(), NaiveDate::MAX.year()) {
+ for y in NaiveDate::MIN.year()..=NaiveDate::MAX.year() {
// even months
let d4 = NaiveDate::from_ymd_opt(y, 4, 4).unwrap();
let d6 = NaiveDate::from_ymd_opt(y, 6, 6).unwrap();
@@ -2459,6 +2557,9 @@ mod tests {
assert_eq!(from_ndays_from_ce(NaiveDate::MIN.num_days_from_ce() - 1), None);
assert_eq!(from_ndays_from_ce(NaiveDate::MAX.num_days_from_ce()), Some(NaiveDate::MAX));
assert_eq!(from_ndays_from_ce(NaiveDate::MAX.num_days_from_ce() + 1), None);
+
+ assert_eq!(from_ndays_from_ce(i32::MIN), None);
+ assert_eq!(from_ndays_from_ce(i32::MAX), None);
}
#[test]
@@ -2915,24 +3016,32 @@ mod tests {
fn test_naiveweek() {
let date = NaiveDate::from_ymd_opt(2022, 5, 18).unwrap();
let asserts = vec![
- (Weekday::Mon, "2022-05-16", "2022-05-22"),
- (Weekday::Tue, "2022-05-17", "2022-05-23"),
- (Weekday::Wed, "2022-05-18", "2022-05-24"),
- (Weekday::Thu, "2022-05-12", "2022-05-18"),
- (Weekday::Fri, "2022-05-13", "2022-05-19"),
- (Weekday::Sat, "2022-05-14", "2022-05-20"),
- (Weekday::Sun, "2022-05-15", "2022-05-21"),
+ (Weekday::Mon, "Mon 2022-05-16", "Sun 2022-05-22"),
+ (Weekday::Tue, "Tue 2022-05-17", "Mon 2022-05-23"),
+ (Weekday::Wed, "Wed 2022-05-18", "Tue 2022-05-24"),
+ (Weekday::Thu, "Thu 2022-05-12", "Wed 2022-05-18"),
+ (Weekday::Fri, "Fri 2022-05-13", "Thu 2022-05-19"),
+ (Weekday::Sat, "Sat 2022-05-14", "Fri 2022-05-20"),
+ (Weekday::Sun, "Sun 2022-05-15", "Sat 2022-05-21"),
];
for (start, first_day, last_day) in asserts {
let week = date.week(start);
let days = week.days();
- assert_eq!(Ok(week.first_day()), NaiveDate::parse_from_str(first_day, "%Y-%m-%d"));
- assert_eq!(Ok(week.last_day()), NaiveDate::parse_from_str(last_day, "%Y-%m-%d"));
+ assert_eq!(Ok(week.first_day()), NaiveDate::parse_from_str(first_day, "%a %Y-%m-%d"));
+ assert_eq!(Ok(week.last_day()), NaiveDate::parse_from_str(last_day, "%a %Y-%m-%d"));
assert!(days.contains(&date));
}
}
#[test]
+ fn test_naiveweek_min_max() {
+ let date_max = NaiveDate::MAX;
+ assert!(date_max.week(Weekday::Mon).first_day() <= date_max);
+ let date_min = NaiveDate::MIN;
+ assert!(date_min.week(Weekday::Mon).last_day() >= date_min);
+ }
+
+ #[test]
fn test_weeks_from() {
// tests per: https://github.com/chronotope/chrono/issues/961
// these internally use `weeks_from` via the parsing infrastructure
@@ -2994,4 +3103,12 @@ mod tests {
}
}
}
+
+ #[test]
+ fn test_with_0_overflow() {
+ let dt = NaiveDate::from_ymd_opt(2023, 4, 18).unwrap();
+ assert!(dt.with_month0(4294967295).is_none());
+ assert!(dt.with_day0(4294967295).is_none());
+ assert!(dt.with_ordinal0(4294967295).is_none());
+ }
}
diff --git a/vendor/chrono/src/naive/datetime/mod.rs b/vendor/chrono/src/naive/datetime/mod.rs
index ec0d842c0..0a3f70380 100644
--- a/vendor/chrono/src/naive/datetime/mod.rs
+++ b/vendor/chrono/src/naive/datetime/mod.rs
@@ -5,24 +5,21 @@
#[cfg(any(feature = "alloc", feature = "std", test))]
use core::borrow::Borrow;
-use core::convert::TryFrom;
use core::fmt::Write;
use core::ops::{Add, AddAssign, Sub, SubAssign};
use core::{fmt, str};
-use num_integer::div_mod_floor;
-use num_traits::ToPrimitive;
#[cfg(feature = "rkyv")]
use rkyv::{Archive, Deserialize, Serialize};
#[cfg(any(feature = "alloc", feature = "std", test))]
use crate::format::DelayedFormat;
-use crate::format::{parse, ParseError, ParseResult, Parsed, StrftimeItems};
+use crate::format::{parse, parse_and_remainder, ParseError, ParseResult, Parsed, StrftimeItems};
use crate::format::{Fixed, Item, Numeric, Pad};
use crate::naive::{Days, IsoWeek, NaiveDate, NaiveTime};
+use crate::offset::Utc;
use crate::oldtime::Duration as OldDuration;
use crate::{DateTime, Datelike, LocalResult, Months, TimeZone, Timelike, Weekday};
-use core::cmp::Ordering;
#[cfg(feature = "rustc-serialize")]
pub(super) mod rustc_serialize;
@@ -42,11 +39,6 @@ mod tests;
/// touching that call when we are already sure that it WILL overflow...
const MAX_SECS_BITS: usize = 44;
-/// Number of nanoseconds in a millisecond
-const NANOS_IN_MILLISECOND: u32 = 1_000_000;
-/// Number of nanoseconds in a second
-const NANOS_IN_SECOND: u32 = 1000 * NANOS_IN_MILLISECOND;
-
/// The minimum possible `NaiveDateTime`.
#[deprecated(since = "0.4.20", note = "Use NaiveDateTime::MIN instead")]
pub const MIN_DATETIME: NaiveDateTime = NaiveDateTime::MIN;
@@ -87,32 +79,6 @@ pub struct NaiveDateTime {
time: NaiveTime,
}
-/// The unit of a timestamp expressed in fractions of a second.
-/// Currently either milliseconds or microseconds.
-///
-/// This is a private type, used in the implementation of
-/// [NaiveDateTime::from_timestamp_millis] and [NaiveDateTime::from_timestamp_micros].
-#[derive(Clone, Copy, Debug)]
-enum TimestampUnit {
- Millis,
- Micros,
-}
-
-impl TimestampUnit {
- fn per_second(self) -> u32 {
- match self {
- TimestampUnit::Millis => 1_000,
- TimestampUnit::Micros => 1_000_000,
- }
- }
- fn nanos_per(self) -> u32 {
- match self {
- TimestampUnit::Millis => 1_000_000,
- TimestampUnit::Micros => 1_000,
- }
- }
-}
-
impl NaiveDateTime {
/// Makes a new `NaiveDateTime` from date and time components.
/// Equivalent to [`date.and_time(time)`](./struct.NaiveDate.html#method.and_time)
@@ -150,6 +116,7 @@ impl NaiveDateTime {
/// Panics on the out-of-range number of seconds and/or invalid nanosecond.
#[deprecated(since = "0.4.23", note = "use `from_timestamp_opt()` instead")]
#[inline]
+ #[must_use]
pub fn from_timestamp(secs: i64, nsecs: u32) -> NaiveDateTime {
let datetime = NaiveDateTime::from_timestamp_opt(secs, nsecs);
datetime.expect("invalid or out-of-range datetime")
@@ -177,8 +144,11 @@ impl NaiveDateTime {
/// assert_eq!(timestamp_millis, naive_datetime.unwrap().timestamp_millis());
/// ```
#[inline]
+ #[must_use]
pub fn from_timestamp_millis(millis: i64) -> Option<NaiveDateTime> {
- Self::from_timestamp_unit(millis, TimestampUnit::Millis)
+ let secs = millis.div_euclid(1000);
+ let nsecs = millis.rem_euclid(1000) as u32 * 1_000_000;
+ NaiveDateTime::from_timestamp_opt(secs, nsecs)
}
/// Creates a new [NaiveDateTime] from microseconds since the UNIX epoch.
@@ -203,8 +173,11 @@ impl NaiveDateTime {
/// assert_eq!(timestamp_micros, naive_datetime.unwrap().timestamp_micros());
/// ```
#[inline]
+ #[must_use]
pub fn from_timestamp_micros(micros: i64) -> Option<NaiveDateTime> {
- Self::from_timestamp_unit(micros, TimestampUnit::Micros)
+ let secs = micros.div_euclid(1_000_000);
+ let nsecs = micros.rem_euclid(1_000_000) as u32 * 1000;
+ NaiveDateTime::from_timestamp_opt(secs, nsecs)
}
/// Makes a new `NaiveDateTime` corresponding to a UTC date and time,
@@ -222,7 +195,7 @@ impl NaiveDateTime {
/// # Example
///
/// ```
- /// use chrono::{NaiveDateTime, NaiveDate};
+ /// use chrono::NaiveDateTime;
/// use std::i64;
///
/// let from_timestamp_opt = NaiveDateTime::from_timestamp_opt;
@@ -234,10 +207,12 @@ impl NaiveDateTime {
/// assert!(from_timestamp_opt(i64::MAX, 0).is_none());
/// ```
#[inline]
+ #[must_use]
pub fn from_timestamp_opt(secs: i64, nsecs: u32) -> Option<NaiveDateTime> {
- let (days, secs) = div_mod_floor(secs, 86_400);
- let date = days
- .to_i32()
+ let days = secs.div_euclid(86_400);
+ let secs = secs.rem_euclid(86_400);
+ let date = i32::try_from(days)
+ .ok()
.and_then(|days| days.checked_add(719_163))
.and_then(NaiveDate::from_num_days_from_ce_opt);
let time = NaiveTime::from_num_seconds_from_midnight_opt(secs as u32, nsecs);
@@ -312,18 +287,43 @@ impl NaiveDateTime {
/// Years before 1 BCE or after 9999 CE, require an initial sign
///
///```
- /// # use chrono::{NaiveDate, NaiveDateTime};
+ /// # use chrono::NaiveDateTime;
/// # let parse_from_str = NaiveDateTime::parse_from_str;
/// let fmt = "%Y-%m-%d %H:%M:%S";
/// assert!(parse_from_str("10000-09-09 01:46:39", fmt).is_err());
/// assert!(parse_from_str("+10000-09-09 01:46:39", fmt).is_ok());
- ///```
+ ///```
pub fn parse_from_str(s: &str, fmt: &str) -> ParseResult<NaiveDateTime> {
let mut parsed = Parsed::new();
parse(&mut parsed, s, StrftimeItems::new(fmt))?;
parsed.to_naive_datetime_with_offset(0) // no offset adjustment
}
+ /// Parses a string with the specified format string and returns a new `NaiveDateTime`, and a
+ /// slice with the remaining portion of the string.
+ /// See the [`format::strftime` module](../format/strftime/index.html)
+ /// on the supported escape sequences.
+ ///
+ /// Similar to [`parse_from_str`](#method.parse_from_str).
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// # use chrono::{NaiveDate, NaiveDateTime};
+ /// let (datetime, remainder) = NaiveDateTime::parse_and_remainder(
+ /// "2015-02-18 23:16:09 trailing text", "%Y-%m-%d %H:%M:%S").unwrap();
+ /// assert_eq!(
+ /// datetime,
+ /// NaiveDate::from_ymd_opt(2015, 2, 18).unwrap().and_hms_opt(23, 16, 9).unwrap()
+ /// );
+ /// assert_eq!(remainder, " trailing text");
+ /// ```
+ pub fn parse_and_remainder<'a>(s: &'a str, fmt: &str) -> ParseResult<(NaiveDateTime, &'a str)> {
+ let mut parsed = Parsed::new();
+ let remainder = parse_and_remainder(&mut parsed, s, StrftimeItems::new(fmt))?;
+ parsed.to_naive_datetime_with_offset(0).map(|d| (d, remainder)) // no offset adjustment
+ }
+
/// Retrieves a date component.
///
/// # Example
@@ -377,6 +377,7 @@ impl NaiveDateTime {
/// assert_eq!(dt.timestamp(), -62198755200);
/// ```
#[inline]
+ #[must_use]
pub fn timestamp(&self) -> i64 {
const UNIX_EPOCH_DAY: i64 = 719_163;
let gregorian_day = i64::from(self.date.num_days_from_ce());
@@ -409,6 +410,7 @@ impl NaiveDateTime {
/// assert_eq!(dt.timestamp_millis(), -900);
/// ```
#[inline]
+ #[must_use]
pub fn timestamp_millis(&self) -> i64 {
let as_ms = self.timestamp() * 1000;
as_ms + i64::from(self.timestamp_subsec_millis())
@@ -436,6 +438,7 @@ impl NaiveDateTime {
/// assert_eq!(dt.timestamp_micros(), 1_000_000_000_000_555);
/// ```
#[inline]
+ #[must_use]
pub fn timestamp_micros(&self) -> i64 {
let as_us = self.timestamp() * 1_000_000;
as_us + i64::from(self.timestamp_subsec_micros())
@@ -470,11 +473,12 @@ impl NaiveDateTime {
/// let nanos = dt.timestamp_nanos();
/// assert_eq!(nanos, 1_000_000_000_000_000_555);
/// assert_eq!(
- /// dt,
- /// NaiveDateTime::from_timestamp(nanos / A_BILLION, (nanos % A_BILLION) as u32)
+ /// Some(dt),
+ /// NaiveDateTime::from_timestamp_opt(nanos / A_BILLION, (nanos % A_BILLION) as u32)
/// );
/// ```
#[inline]
+ #[must_use]
pub fn timestamp_nanos(&self) -> i64 {
let as_ns = self.timestamp() * 1_000_000_000;
as_ns + i64::from(self.timestamp_subsec_nanos())
@@ -497,6 +501,7 @@ impl NaiveDateTime {
/// assert_eq!(dt.timestamp_subsec_millis(), 1_234);
/// ```
#[inline]
+ #[must_use]
pub fn timestamp_subsec_millis(&self) -> u32 {
self.timestamp_subsec_nanos() / 1_000_000
}
@@ -518,6 +523,7 @@ impl NaiveDateTime {
/// assert_eq!(dt.timestamp_subsec_micros(), 1_234_567);
/// ```
#[inline]
+ #[must_use]
pub fn timestamp_subsec_micros(&self) -> u32 {
self.timestamp_subsec_nanos() / 1_000
}
@@ -539,6 +545,7 @@ impl NaiveDateTime {
/// assert_eq!(dt.timestamp_subsec_nanos(), 1_234_567_890);
/// ```
#[inline]
+ #[must_use]
pub fn timestamp_subsec_nanos(&self) -> u32 {
self.time.nanosecond()
}
@@ -557,7 +564,7 @@ impl NaiveDateTime {
/// ```
/// use chrono::{Duration, NaiveDate};
///
- /// let from_ymd = NaiveDate::from_ymd;
+ /// let from_ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap();
///
/// let d = from_ymd(2016, 7, 8);
/// let hms = |h, m, s| d.and_hms_opt(h, m, s).unwrap();
@@ -590,7 +597,7 @@ impl NaiveDateTime {
///
/// ```
/// # use chrono::{Duration, NaiveDate};
- /// # let from_ymd = NaiveDate::from_ymd;
+ /// # let from_ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap();
/// # let hmsm = |h, m, s, milli| from_ymd(2016, 7, 8).and_hms_milli_opt(h, m, s, milli).unwrap();
/// let leap = hmsm(3, 5, 59, 1_300);
/// assert_eq!(leap.checked_add_signed(Duration::zero()),
@@ -608,6 +615,7 @@ impl NaiveDateTime {
/// assert_eq!(leap.checked_add_signed(Duration::days(1)),
/// Some(from_ymd(2016, 7, 9).and_hms_milli_opt(3, 5, 59, 300).unwrap()));
/// ```
+ #[must_use]
pub fn checked_add_signed(self, rhs: OldDuration) -> Option<NaiveDateTime> {
let (time, rhs) = self.time.overflowing_add_signed(rhs);
@@ -629,8 +637,7 @@ impl NaiveDateTime {
/// # Example
///
/// ```
- /// use std::str::FromStr;
- /// use chrono::{Months, NaiveDate, NaiveDateTime};
+ /// use chrono::{Months, NaiveDate};
///
/// assert_eq!(
/// NaiveDate::from_ymd_opt(2014, 1, 1).unwrap().and_hms_opt(1, 0, 0).unwrap()
@@ -644,6 +651,7 @@ impl NaiveDateTime {
/// None
/// );
/// ```
+ #[must_use]
pub fn checked_add_months(self, rhs: Months) -> Option<NaiveDateTime> {
Some(Self { date: self.date.checked_add_months(rhs)?, time: self.time })
}
@@ -662,7 +670,7 @@ impl NaiveDateTime {
/// ```
/// use chrono::{Duration, NaiveDate};
///
- /// let from_ymd = NaiveDate::from_ymd;
+ /// let from_ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap();
///
/// let d = from_ymd(2016, 7, 8);
/// let hms = |h, m, s| d.and_hms_opt(h, m, s).unwrap();
@@ -695,7 +703,7 @@ impl NaiveDateTime {
///
/// ```
/// # use chrono::{Duration, NaiveDate};
- /// # let from_ymd = NaiveDate::from_ymd;
+ /// # let from_ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap();
/// # let hmsm = |h, m, s, milli| from_ymd(2016, 7, 8).and_hms_milli_opt(h, m, s, milli).unwrap();
/// let leap = hmsm(3, 5, 59, 1_300);
/// assert_eq!(leap.checked_sub_signed(Duration::zero()),
@@ -709,6 +717,7 @@ impl NaiveDateTime {
/// assert_eq!(leap.checked_sub_signed(Duration::days(1)),
/// Some(from_ymd(2016, 7, 7).and_hms_milli_opt(3, 6, 0, 300).unwrap()));
/// ```
+ #[must_use]
pub fn checked_sub_signed(self, rhs: OldDuration) -> Option<NaiveDateTime> {
let (time, rhs) = self.time.overflowing_sub_signed(rhs);
@@ -730,8 +739,7 @@ impl NaiveDateTime {
/// # Example
///
/// ```
- /// use std::str::FromStr;
- /// use chrono::{Months, NaiveDate, NaiveDateTime};
+ /// use chrono::{Months, NaiveDate};
///
/// assert_eq!(
/// NaiveDate::from_ymd_opt(2014, 1, 1).unwrap().and_hms_opt(1, 0, 0).unwrap()
@@ -745,6 +753,7 @@ impl NaiveDateTime {
/// None
/// );
/// ```
+ #[must_use]
pub fn checked_sub_months(self, rhs: Months) -> Option<NaiveDateTime> {
Some(Self { date: self.date.checked_sub_months(rhs)?, time: self.time })
}
@@ -752,6 +761,7 @@ impl NaiveDateTime {
/// Add a duration in [`Days`] to the date part of the `NaiveDateTime`
///
/// Returns `None` if the resulting date would be out of range.
+ #[must_use]
pub fn checked_add_days(self, days: Days) -> Option<Self> {
Some(Self { date: self.date.checked_add_days(days)?, ..self })
}
@@ -759,6 +769,7 @@ impl NaiveDateTime {
/// Subtract a duration in [`Days`] from the date part of the `NaiveDateTime`
///
/// Returns `None` if the resulting date would be out of range.
+ #[must_use]
pub fn checked_sub_days(self, days: Days) -> Option<Self> {
Some(Self { date: self.date.checked_sub_days(days)?, ..self })
}
@@ -777,7 +788,7 @@ impl NaiveDateTime {
/// ```
/// use chrono::{Duration, NaiveDate};
///
- /// let from_ymd = NaiveDate::from_ymd;
+ /// let from_ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap();
///
/// let d = from_ymd(2016, 7, 8);
/// assert_eq!(d.and_hms_opt(3, 5, 7).unwrap().signed_duration_since(d.and_hms_opt(2, 4, 6).unwrap()),
@@ -794,13 +805,14 @@ impl NaiveDateTime {
///
/// ```
/// # use chrono::{Duration, NaiveDate};
- /// # let from_ymd = NaiveDate::from_ymd;
+ /// # let from_ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap();
/// let leap = from_ymd(2015, 6, 30).and_hms_milli_opt(23, 59, 59, 1_500).unwrap();
/// assert_eq!(leap.signed_duration_since(from_ymd(2015, 6, 30).and_hms_opt(23, 0, 0).unwrap()),
/// Duration::seconds(3600) + Duration::milliseconds(500));
/// assert_eq!(from_ymd(2015, 7, 1).and_hms_opt(1, 0, 0).unwrap().signed_duration_since(leap),
/// Duration::seconds(3600) - Duration::milliseconds(500));
/// ```
+ #[must_use]
pub fn signed_duration_since(self, rhs: NaiveDateTime) -> OldDuration {
self.date.signed_duration_since(rhs.date) + self.time.signed_duration_since(rhs.time)
}
@@ -835,6 +847,7 @@ impl NaiveDateTime {
#[cfg(any(feature = "alloc", feature = "std", test))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "alloc", feature = "std"))))]
#[inline]
+ #[must_use]
pub fn format_with_items<'a, I, B>(&self, items: I) -> DelayedFormat<I>
where
I: Iterator<Item = B> + Clone,
@@ -878,6 +891,7 @@ impl NaiveDateTime {
#[cfg(any(feature = "alloc", feature = "std", test))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "alloc", feature = "std"))))]
#[inline]
+ #[must_use]
pub fn format<'a>(&self, fmt: &'a str) -> DelayedFormat<StrftimeItems<'a>> {
self.format_with_items(StrftimeItems::new(fmt))
}
@@ -896,51 +910,39 @@ impl NaiveDateTime {
/// # Example
///
/// ```
- /// use chrono::{NaiveDate, Utc};
- /// let dt = NaiveDate::from_ymd_opt(2015, 9, 5).unwrap().and_hms_opt(23, 56, 4).unwrap().and_local_timezone(Utc).unwrap();
- /// assert_eq!(dt.timezone(), Utc);
+ /// use chrono::{NaiveDate, FixedOffset};
+ /// let hour = 3600;
+ /// let tz = FixedOffset::east_opt(5 * hour).unwrap();
+ /// let dt = NaiveDate::from_ymd_opt(2015, 9, 5).unwrap().and_hms_opt(23, 56, 4).unwrap().and_local_timezone(tz).unwrap();
+ /// assert_eq!(dt.timezone(), tz);
+ /// ```
+ #[must_use]
pub fn and_local_timezone<Tz: TimeZone>(&self, tz: Tz) -> LocalResult<DateTime<Tz>> {
tz.from_local_datetime(self)
}
+ /// Converts the `NaiveDateTime` into the timezone-aware `DateTime<Utc>`.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use chrono::{NaiveDate, Utc};
+ /// let dt = NaiveDate::from_ymd_opt(2023, 1, 30).unwrap().and_hms_opt(19, 32, 33).unwrap().and_utc();
+ /// assert_eq!(dt.timezone(), Utc);
+ /// ```
+ #[must_use]
+ pub fn and_utc(&self) -> DateTime<Utc> {
+ Utc.from_utc_datetime(self)
+ }
+
/// The minimum possible `NaiveDateTime`.
pub const MIN: Self = Self { date: NaiveDate::MIN, time: NaiveTime::MIN };
/// The maximum possible `NaiveDateTime`.
pub const MAX: Self = Self { date: NaiveDate::MAX, time: NaiveTime::MAX };
-
- /// Creates a new [NaiveDateTime] from milliseconds or microseconds since the UNIX epoch.
- ///
- /// This is a private function used by [from_timestamp_millis] and [from_timestamp_micros].
- #[inline]
- fn from_timestamp_unit(value: i64, unit: TimestampUnit) -> Option<NaiveDateTime> {
- let (secs, subsecs) =
- (value / i64::from(unit.per_second()), value % i64::from(unit.per_second()));
-
- match subsecs.cmp(&0) {
- Ordering::Less => {
- // in the case where our subsec part is negative, then we are actually in the earlier second
- // hence we subtract one from the seconds part, and we then add a whole second worth of nanos
- // to our nanos part. Due to the use of u32 datatype, it is more convenient to subtract
- // the absolute value of the subsec nanos from a whole second worth of nanos
- let nsecs = u32::try_from(subsecs.abs()).ok()? * unit.nanos_per();
- NaiveDateTime::from_timestamp_opt(
- secs.checked_sub(1)?,
- NANOS_IN_SECOND.checked_sub(nsecs)?,
- )
- }
- Ordering::Equal => NaiveDateTime::from_timestamp_opt(secs, 0),
- Ordering::Greater => {
- // convert the subsec millis into nanosecond scale so they can be supplied
- // as the nanoseconds parameter
- let nsecs = u32::try_from(subsecs).ok()? * unit.nanos_per();
- NaiveDateTime::from_timestamp_opt(secs, nsecs)
- }
- }
- }
}
impl Datelike for NaiveDateTime {
- /// Returns the year number in the [calendar date](./index.html#calendar-date).
+ /// Returns the year number in the [calendar date](./struct.NaiveDate.html#calendar-date).
///
/// See also the [`NaiveDate::year`] method.
///
@@ -1415,10 +1417,9 @@ impl Timelike for NaiveDateTime {
/// An addition of `Duration` to `NaiveDateTime` yields another `NaiveDateTime`.
///
-/// As a part of Chrono's [leap second handling](./struct.NaiveTime.html#leap-second-handling),
-/// the addition assumes that **there is no leap second ever**,
-/// except when the `NaiveDateTime` itself represents a leap second
-/// in which case the assumption becomes that **there is exactly a single leap second ever**.
+/// As a part of Chrono's [leap second handling], the addition assumes that **there is no leap
+/// second ever**, except when the `NaiveDateTime` itself represents a leap second in which case
+/// the assumption becomes that **there is exactly a single leap second ever**.
///
/// Panics on underflow or overflow. Use [`NaiveDateTime::checked_add_signed`]
/// to detect that.
@@ -1428,7 +1429,7 @@ impl Timelike for NaiveDateTime {
/// ```
/// use chrono::{Duration, NaiveDate};
///
-/// let from_ymd = NaiveDate::from_ymd;
+/// let from_ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap();
///
/// let d = from_ymd(2016, 7, 8);
/// let hms = |h, m, s| d.and_hms_opt(h, m, s).unwrap();
@@ -1450,7 +1451,7 @@ impl Timelike for NaiveDateTime {
///
/// ```
/// # use chrono::{Duration, NaiveDate};
-/// # let from_ymd = NaiveDate::from_ymd;
+/// # let from_ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap();
/// # let hmsm = |h, m, s, milli| from_ymd(2016, 7, 8).and_hms_milli_opt(h, m, s, milli).unwrap();
/// let leap = hmsm(3, 5, 59, 1_300);
/// assert_eq!(leap + Duration::zero(), hmsm(3, 5, 59, 1_300));
@@ -1462,6 +1463,8 @@ impl Timelike for NaiveDateTime {
/// assert_eq!(leap + Duration::days(1),
/// from_ymd(2016, 7, 9).and_hms_milli_opt(3, 5, 59, 300).unwrap());
/// ```
+///
+/// [leap second handling]: crate::NaiveTime#leap-second-handling
impl Add<OldDuration> for NaiveDateTime {
type Output = NaiveDateTime;
@@ -1490,8 +1493,7 @@ impl Add<Months> for NaiveDateTime {
/// # Example
///
/// ```
- /// use chrono::{Duration, NaiveDateTime, Months, NaiveDate};
- /// use std::str::FromStr;
+ /// use chrono::{Months, NaiveDate};
///
/// assert_eq!(
/// NaiveDate::from_ymd_opt(2014, 1, 1).unwrap().and_hms_opt(1, 0, 0).unwrap() + Months::new(1),
@@ -1526,10 +1528,9 @@ impl Add<Months> for NaiveDateTime {
/// A subtraction of `Duration` from `NaiveDateTime` yields another `NaiveDateTime`.
/// It is the same as the addition with a negated `Duration`.
///
-/// As a part of Chrono's [leap second handling](./struct.NaiveTime.html#leap-second-handling),
-/// the addition assumes that **there is no leap second ever**,
-/// except when the `NaiveDateTime` itself represents a leap second
-/// in which case the assumption becomes that **there is exactly a single leap second ever**.
+/// As a part of Chrono's [leap second handling] the subtraction assumes that **there is no leap
+/// second ever**, except when the `NaiveDateTime` itself represents a leap second in which case
+/// the assumption becomes that **there is exactly a single leap second ever**.
///
/// Panics on underflow or overflow. Use [`NaiveDateTime::checked_sub_signed`]
/// to detect that.
@@ -1539,7 +1540,7 @@ impl Add<Months> for NaiveDateTime {
/// ```
/// use chrono::{Duration, NaiveDate};
///
-/// let from_ymd = NaiveDate::from_ymd;
+/// let from_ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap();
///
/// let d = from_ymd(2016, 7, 8);
/// let hms = |h, m, s| d.and_hms_opt(h, m, s).unwrap();
@@ -1561,7 +1562,7 @@ impl Add<Months> for NaiveDateTime {
///
/// ```
/// # use chrono::{Duration, NaiveDate};
-/// # let from_ymd = NaiveDate::from_ymd;
+/// # let from_ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap();
/// # let hmsm = |h, m, s, milli| from_ymd(2016, 7, 8).and_hms_milli_opt(h, m, s, milli).unwrap();
/// let leap = hmsm(3, 5, 59, 1_300);
/// assert_eq!(leap - Duration::zero(), hmsm(3, 5, 59, 1_300));
@@ -1571,6 +1572,8 @@ impl Add<Months> for NaiveDateTime {
/// assert_eq!(leap - Duration::days(1),
/// from_ymd(2016, 7, 7).and_hms_milli_opt(3, 6, 0, 300).unwrap());
/// ```
+///
+/// [leap second handling]: crate::NaiveTime#leap-second-handling
impl Sub<OldDuration> for NaiveDateTime {
type Output = NaiveDateTime;
@@ -1596,8 +1599,7 @@ impl SubAssign<OldDuration> for NaiveDateTime {
/// # Example
///
/// ```
-/// use chrono::{Duration, NaiveDateTime, Months, NaiveDate};
-/// use std::str::FromStr;
+/// use chrono::{Months, NaiveDate};
///
/// assert_eq!(
/// NaiveDate::from_ymd_opt(2014, 01, 01).unwrap().and_hms_opt(01, 00, 00).unwrap() - Months::new(11),
@@ -1636,7 +1638,7 @@ impl Sub<Months> for NaiveDateTime {
/// ```
/// use chrono::{Duration, NaiveDate};
///
-/// let from_ymd = NaiveDate::from_ymd;
+/// let from_ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap();
///
/// let d = from_ymd(2016, 7, 8);
/// assert_eq!(d.and_hms_opt(3, 5, 7).unwrap() - d.and_hms_opt(2, 4, 6).unwrap(), Duration::seconds(3600 + 60 + 1));
@@ -1652,7 +1654,7 @@ impl Sub<Months> for NaiveDateTime {
///
/// ```
/// # use chrono::{Duration, NaiveDate};
-/// # let from_ymd = NaiveDate::from_ymd;
+/// # let from_ymd = |y, m, d| NaiveDate::from_ymd_opt(y, m, d).unwrap();
/// let leap = from_ymd(2015, 6, 30).and_hms_milli_opt(23, 59, 59, 1_500).unwrap();
/// assert_eq!(leap - from_ymd(2015, 6, 30).and_hms_opt(23, 0, 0).unwrap(),
/// Duration::seconds(3600) + Duration::milliseconds(500));
@@ -1808,7 +1810,7 @@ impl str::FromStr for NaiveDateTime {
/// use chrono::NaiveDateTime;
///
/// let default_date = NaiveDateTime::default();
-/// assert_eq!(default_date, NaiveDateTime::from_timestamp(0, 0));
+/// assert_eq!(Some(default_date), NaiveDateTime::from_timestamp_opt(0, 0));
/// ```
impl Default for NaiveDateTime {
fn default() -> Self {
diff --git a/vendor/chrono/src/naive/datetime/serde.rs b/vendor/chrono/src/naive/datetime/serde.rs
index 40695fa74..8107f384d 100644
--- a/vendor/chrono/src/naive/datetime/serde.rs
+++ b/vendor/chrono/src/naive/datetime/serde.rs
@@ -110,6 +110,7 @@ pub mod ts_nanoseconds {
/// assert_eq!(as_string, r#"{"time":1526522699918355733}"#);
/// # Ok::<(), serde_json::Error>(())
/// ```
+ #[must_use]
pub fn serialize<S>(dt: &NaiveDateTime, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
@@ -127,15 +128,17 @@ pub mod ts_nanoseconds {
/// # use chrono::NaiveDateTime;
/// # use serde_derive::Deserialize;
/// use chrono::naive::serde::ts_nanoseconds::deserialize as from_nano_ts;
- /// #[derive(Deserialize)]
+ /// #[derive(Debug, PartialEq, Deserialize)]
/// struct S {
/// #[serde(deserialize_with = "from_nano_ts")]
/// time: NaiveDateTime
/// }
///
/// let my_s: S = serde_json::from_str(r#"{ "time": 1526522699918355733 }"#)?;
+ /// assert_eq!(my_s, S { time: NaiveDateTime::from_timestamp_opt(1526522699, 918355733).unwrap() });
/// # Ok::<(), serde_json::Error>(())
/// ```
+ #[must_use]
pub fn deserialize<'de, D>(d: D) -> Result<NaiveDateTime, D::Error>
where
D: de::Deserializer<'de>,
@@ -230,6 +233,7 @@ pub mod ts_nanoseconds_option {
/// assert_eq!(as_string, r#"{"time":1526522699918355733}"#);
/// # Ok::<(), serde_json::Error>(())
/// ```
+ #[must_use]
pub fn serialize<S>(opt: &Option<NaiveDateTime>, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
@@ -247,18 +251,20 @@ pub mod ts_nanoseconds_option {
/// # Example:
///
/// ```rust
- /// # use chrono::naive::{NaiveDate, NaiveDateTime};
+ /// # use chrono::naive::NaiveDateTime;
/// # use serde_derive::Deserialize;
/// use chrono::naive::serde::ts_nanoseconds_option::deserialize as from_nano_tsopt;
- /// #[derive(Deserialize)]
+ /// #[derive(Debug, PartialEq, Deserialize)]
/// struct S {
/// #[serde(deserialize_with = "from_nano_tsopt")]
/// time: Option<NaiveDateTime>
/// }
///
/// let my_s: S = serde_json::from_str(r#"{ "time": 1526522699918355733 }"#)?;
+ /// assert_eq!(my_s, S { time: NaiveDateTime::from_timestamp_opt(1526522699, 918355733) });
/// # Ok::<(), serde_json::Error>(())
/// ```
+ #[must_use]
pub fn deserialize<'de, D>(d: D) -> Result<Option<NaiveDateTime>, D::Error>
where
D: de::Deserializer<'de>,
@@ -356,6 +362,7 @@ pub mod ts_microseconds {
/// assert_eq!(as_string, r#"{"time":1526522699918355}"#);
/// # Ok::<(), serde_json::Error>(())
/// ```
+ #[must_use]
pub fn serialize<S>(dt: &NaiveDateTime, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
@@ -373,15 +380,17 @@ pub mod ts_microseconds {
/// # use chrono::NaiveDateTime;
/// # use serde_derive::Deserialize;
/// use chrono::naive::serde::ts_microseconds::deserialize as from_micro_ts;
- /// #[derive(Deserialize)]
+ /// #[derive(Debug, PartialEq, Deserialize)]
/// struct S {
/// #[serde(deserialize_with = "from_micro_ts")]
/// time: NaiveDateTime
/// }
///
/// let my_s: S = serde_json::from_str(r#"{ "time": 1526522699918355 }"#)?;
+ /// assert_eq!(my_s, S { time: NaiveDateTime::from_timestamp_opt(1526522699, 918355000).unwrap() });
/// # Ok::<(), serde_json::Error>(())
/// ```
+ #[must_use]
pub fn deserialize<'de, D>(d: D) -> Result<NaiveDateTime, D::Error>
where
D: de::Deserializer<'de>,
@@ -479,6 +488,7 @@ pub mod ts_microseconds_option {
/// assert_eq!(as_string, r#"{"time":1526522699918355}"#);
/// # Ok::<(), serde_json::Error>(())
/// ```
+ #[must_use]
pub fn serialize<S>(opt: &Option<NaiveDateTime>, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
@@ -496,18 +506,20 @@ pub mod ts_microseconds_option {
/// # Example:
///
/// ```rust
- /// # use chrono::naive::{NaiveDate, NaiveDateTime};
+ /// # use chrono::naive::NaiveDateTime;
/// # use serde_derive::Deserialize;
/// use chrono::naive::serde::ts_microseconds_option::deserialize as from_micro_tsopt;
- /// #[derive(Deserialize)]
+ /// #[derive(Debug, PartialEq, Deserialize)]
/// struct S {
/// #[serde(deserialize_with = "from_micro_tsopt")]
/// time: Option<NaiveDateTime>
/// }
///
/// let my_s: S = serde_json::from_str(r#"{ "time": 1526522699918355 }"#)?;
+ /// assert_eq!(my_s, S { time: NaiveDateTime::from_timestamp_opt(1526522699, 918355000) });
/// # Ok::<(), serde_json::Error>(())
/// ```
+ #[must_use]
pub fn deserialize<'de, D>(d: D) -> Result<Option<NaiveDateTime>, D::Error>
where
D: de::Deserializer<'de>,
@@ -605,6 +617,7 @@ pub mod ts_milliseconds {
/// assert_eq!(as_string, r#"{"time":1526522699918}"#);
/// # Ok::<(), serde_json::Error>(())
/// ```
+ #[must_use]
pub fn serialize<S>(dt: &NaiveDateTime, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
@@ -622,15 +635,17 @@ pub mod ts_milliseconds {
/// # use chrono::NaiveDateTime;
/// # use serde_derive::Deserialize;
/// use chrono::naive::serde::ts_milliseconds::deserialize as from_milli_ts;
- /// #[derive(Deserialize)]
+ /// #[derive(Debug, PartialEq, Deserialize)]
/// struct S {
/// #[serde(deserialize_with = "from_milli_ts")]
/// time: NaiveDateTime
/// }
///
/// let my_s: S = serde_json::from_str(r#"{ "time": 1526522699918 }"#)?;
+ /// assert_eq!(my_s, S { time: NaiveDateTime::from_timestamp_opt(1526522699, 918000000).unwrap() });
/// # Ok::<(), serde_json::Error>(())
/// ```
+ #[must_use]
pub fn deserialize<'de, D>(d: D) -> Result<NaiveDateTime, D::Error>
where
D: de::Deserializer<'de>,
@@ -725,6 +740,7 @@ pub mod ts_milliseconds_option {
/// assert_eq!(as_string, r#"{"time":1526522699918}"#);
/// # Ok::<(), serde_json::Error>(())
/// ```
+ #[must_use]
pub fn serialize<S>(opt: &Option<NaiveDateTime>, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
@@ -735,25 +751,27 @@ pub mod ts_milliseconds_option {
}
}
- /// Deserialize a `NaiveDateTime` from a nanosecond timestamp or none
+ /// Deserialize a `NaiveDateTime` from a millisecond timestamp or none
///
/// Intended for use with `serde`s `deserialize_with` attribute.
///
/// # Example:
///
/// ```rust
- /// # use chrono::naive::{NaiveDate, NaiveDateTime};
+ /// # use chrono::naive::NaiveDateTime;
/// # use serde_derive::Deserialize;
/// use chrono::naive::serde::ts_milliseconds_option::deserialize as from_milli_tsopt;
- /// #[derive(Deserialize)]
+ /// #[derive(Debug, PartialEq, Deserialize)]
/// struct S {
/// #[serde(deserialize_with = "from_milli_tsopt")]
/// time: Option<NaiveDateTime>
/// }
///
- /// let my_s: S = serde_json::from_str(r#"{ "time": 1526522699918355 }"#)?;
+ /// let my_s: S = serde_json::from_str(r#"{ "time": 1526522699918 }"#)?;
+ /// assert_eq!(my_s, S { time: NaiveDateTime::from_timestamp_opt(1526522699, 918000000) });
/// # Ok::<(), serde_json::Error>(())
/// ```
+ #[must_use]
pub fn deserialize<'de, D>(d: D) -> Result<Option<NaiveDateTime>, D::Error>
where
D: de::Deserializer<'de>,
@@ -851,6 +869,7 @@ pub mod ts_seconds {
/// assert_eq!(as_string, r#"{"time":1431684000}"#);
/// # Ok::<(), serde_json::Error>(())
/// ```
+ #[must_use]
pub fn serialize<S>(dt: &NaiveDateTime, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
@@ -868,15 +887,17 @@ pub mod ts_seconds {
/// # use chrono::NaiveDateTime;
/// # use serde_derive::Deserialize;
/// use chrono::naive::serde::ts_seconds::deserialize as from_ts;
- /// #[derive(Deserialize)]
+ /// #[derive(Debug, PartialEq, Deserialize)]
/// struct S {
/// #[serde(deserialize_with = "from_ts")]
/// time: NaiveDateTime
/// }
///
/// let my_s: S = serde_json::from_str(r#"{ "time": 1431684000 }"#)?;
+ /// assert_eq!(my_s, S { time: NaiveDateTime::from_timestamp_opt(1431684000, 0).unwrap() });
/// # Ok::<(), serde_json::Error>(())
/// ```
+ #[must_use]
pub fn deserialize<'de, D>(d: D) -> Result<NaiveDateTime, D::Error>
where
D: de::Deserializer<'de>,
@@ -968,6 +989,7 @@ pub mod ts_seconds_option {
/// assert_eq!(as_string, r#"{"time":1526522699}"#);
/// # Ok::<(), serde_json::Error>(())
/// ```
+ #[must_use]
pub fn serialize<S>(opt: &Option<NaiveDateTime>, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
@@ -985,18 +1007,20 @@ pub mod ts_seconds_option {
/// # Example:
///
/// ```rust
- /// # use chrono::naive::{NaiveDate, NaiveDateTime};
+ /// # use chrono::naive::NaiveDateTime;
/// # use serde_derive::Deserialize;
/// use chrono::naive::serde::ts_seconds_option::deserialize as from_tsopt;
- /// #[derive(Deserialize)]
+ /// #[derive(Debug, PartialEq, Deserialize)]
/// struct S {
/// #[serde(deserialize_with = "from_tsopt")]
/// time: Option<NaiveDateTime>
/// }
///
/// let my_s: S = serde_json::from_str(r#"{ "time": 1431684000 }"#)?;
+ /// assert_eq!(my_s, S { time: NaiveDateTime::from_timestamp_opt(1431684000, 0) });
/// # Ok::<(), serde_json::Error>(())
/// ```
+ #[must_use]
pub fn deserialize<'de, D>(d: D) -> Result<Option<NaiveDateTime>, D::Error>
where
D: de::Deserializer<'de>,
diff --git a/vendor/chrono/src/naive/datetime/tests.rs b/vendor/chrono/src/naive/datetime/tests.rs
index 202bdb34d..07309a48a 100644
--- a/vendor/chrono/src/naive/datetime/tests.rs
+++ b/vendor/chrono/src/naive/datetime/tests.rs
@@ -330,7 +330,7 @@ fn test_nanosecond_range() {
}
#[test]
-fn test_and_timezone() {
+fn test_and_local_timezone() {
let ndt = NaiveDate::from_ymd_opt(2022, 6, 15).unwrap().and_hms_opt(18, 59, 36).unwrap();
let dt_utc = ndt.and_local_timezone(Utc).unwrap();
assert_eq!(dt_utc.naive_local(), ndt);
@@ -341,3 +341,11 @@ fn test_and_timezone() {
assert_eq!(dt_offset.naive_local(), ndt);
assert_eq!(dt_offset.timezone(), offset_tz);
}
+
+#[test]
+fn test_and_utc() {
+ let ndt = NaiveDate::from_ymd_opt(2023, 1, 30).unwrap().and_hms_opt(19, 32, 33).unwrap();
+ let dt_utc = ndt.and_utc();
+ assert_eq!(dt_utc.naive_local(), ndt);
+ assert_eq!(dt_utc.timezone(), Utc);
+}
diff --git a/vendor/chrono/src/naive/internals.rs b/vendor/chrono/src/naive/internals.rs
index 05305b506..65b47ae73 100644
--- a/vendor/chrono/src/naive/internals.rs
+++ b/vendor/chrono/src/naive/internals.rs
@@ -17,10 +17,8 @@
use crate::Weekday;
use core::{fmt, i32};
-use num_integer::{div_rem, mod_floor};
-use num_traits::FromPrimitive;
-/// The internal date representation. This also includes the packed `Mdf` value.
+/// The internal date representation: `year << 13 | Of`
pub(super) type DateImpl = i32;
pub(super) const MAX_YEAR: DateImpl = i32::MAX >> 13;
@@ -53,7 +51,7 @@ pub(super) const FE: YearFlags = YearFlags(0o07);
pub(super) const G: YearFlags = YearFlags(0o16);
pub(super) const GF: YearFlags = YearFlags(0o06);
-static YEAR_TO_FLAGS: [YearFlags; 400] = [
+const YEAR_TO_FLAGS: &[YearFlags; 400] = &[
BA, G, F, E, DC, B, A, G, FE, D, C, B, AG, F, E, D, CB, A, G, F, ED, C, B, A, GF, E, D, C, BA,
G, F, E, DC, B, A, G, FE, D, C, B, AG, F, E, D, CB, A, G, F, ED, C, B, A, GF, E, D, C, BA, G,
F, E, DC, B, A, G, FE, D, C, B, AG, F, E, D, CB, A, G, F, ED, C, B, A, GF, E, D, C, BA, G, F,
@@ -72,7 +70,7 @@ static YEAR_TO_FLAGS: [YearFlags; 400] = [
D, CB, A, G, F, ED, C, B, A, GF, E, D, C, // 400
];
-static YEAR_DELTAS: [u8; 401] = [
+const YEAR_DELTAS: &[u8; 401] = &[
0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8,
8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14,
15, 15, 15, 15, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, 20, 20, 20, 20,
@@ -94,46 +92,48 @@ static YEAR_DELTAS: [u8; 401] = [
96, 97, 97, 97, 97, // 400+1
];
-pub(super) fn cycle_to_yo(cycle: u32) -> (u32, u32) {
- let (mut year_mod_400, mut ordinal0) = div_rem(cycle, 365);
- let delta = u32::from(YEAR_DELTAS[year_mod_400 as usize]);
+pub(super) const fn cycle_to_yo(cycle: u32) -> (u32, u32) {
+ let mut year_mod_400 = cycle / 365;
+ let mut ordinal0 = cycle % 365;
+ let delta = YEAR_DELTAS[year_mod_400 as usize] as u32;
if ordinal0 < delta {
year_mod_400 -= 1;
- ordinal0 += 365 - u32::from(YEAR_DELTAS[year_mod_400 as usize]);
+ ordinal0 += 365 - YEAR_DELTAS[year_mod_400 as usize] as u32;
} else {
ordinal0 -= delta;
}
(year_mod_400, ordinal0 + 1)
}
-pub(super) fn yo_to_cycle(year_mod_400: u32, ordinal: u32) -> u32 {
- year_mod_400 * 365 + u32::from(YEAR_DELTAS[year_mod_400 as usize]) + ordinal - 1
+pub(super) const fn yo_to_cycle(year_mod_400: u32, ordinal: u32) -> u32 {
+ year_mod_400 * 365 + YEAR_DELTAS[year_mod_400 as usize] as u32 + ordinal - 1
}
impl YearFlags {
#[allow(unreachable_pub)] // public as an alias for benchmarks only
#[doc(hidden)] // for benchmarks only
#[inline]
- pub fn from_year(year: i32) -> YearFlags {
- let year = mod_floor(year, 400);
+ #[must_use]
+ pub const fn from_year(year: i32) -> YearFlags {
+ let year = year.rem_euclid(400);
YearFlags::from_year_mod_400(year)
}
#[inline]
- pub(super) fn from_year_mod_400(year: i32) -> YearFlags {
+ pub(super) const fn from_year_mod_400(year: i32) -> YearFlags {
YEAR_TO_FLAGS[year as usize]
}
#[inline]
- pub(super) fn ndays(&self) -> u32 {
+ pub(super) const fn ndays(&self) -> u32 {
let YearFlags(flags) = *self;
- 366 - u32::from(flags >> 3)
+ 366 - (flags >> 3) as u32
}
#[inline]
- pub(super) fn isoweek_delta(&self) -> u32 {
+ pub(super) const fn isoweek_delta(&self) -> u32 {
let YearFlags(flags) = *self;
- let mut delta = u32::from(flags) & 0b0111;
+ let mut delta = (flags & 0b0111) as u32;
if delta < 3 {
delta += 7;
}
@@ -172,12 +172,13 @@ impl fmt::Debug for YearFlags {
}
}
+// OL: (ordinal << 1) | leap year flag
pub(super) const MIN_OL: u32 = 1 << 1;
-pub(super) const MAX_OL: u32 = 366 << 1; // larger than the non-leap last day `(365 << 1) | 1`
+pub(super) const MAX_OL: u32 = 366 << 1; // `(366 << 1) | 1` would be day 366 in a non-leap year
pub(super) const MAX_MDL: u32 = (12 << 6) | (31 << 1) | 1;
const XX: i8 = -128;
-static MDL_TO_OL: [i8; MAX_MDL as usize + 1] = [
+const MDL_TO_OL: &[i8; MAX_MDL as usize + 1] = &[
XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX,
XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX,
XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, XX, // 0
@@ -220,7 +221,7 @@ static MDL_TO_OL: [i8; MAX_MDL as usize + 1] = [
100, // 12
];
-static OL_TO_MDL: [u8; MAX_OL as usize + 1] = [
+const OL_TO_MDL: &[u8; MAX_OL as usize + 1] = &[
0, 0, // 0
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
@@ -265,60 +266,76 @@ static OL_TO_MDL: [u8; MAX_OL as usize + 1] = [
///
/// The whole bits except for the least 3 bits are referred as `Ol` (ordinal and leap flag),
/// which is an index to the `OL_TO_MDL` lookup table.
+///
+/// The methods implemented on `Of` always return a valid value.
#[derive(PartialEq, PartialOrd, Copy, Clone)]
-pub(super) struct Of(pub(crate) u32);
+pub(super) struct Of(u32);
impl Of {
#[inline]
- pub(super) fn new(ordinal: u32, YearFlags(flags): YearFlags) -> Option<Of> {
- match ordinal <= 366 {
- true => Some(Of((ordinal << 4) | u32::from(flags))),
- false => None,
- }
+ pub(super) const fn new(ordinal: u32, YearFlags(flags): YearFlags) -> Option<Of> {
+ let of = Of((ordinal << 4) | flags as u32);
+ of.validate()
+ }
+
+ pub(super) const fn from_date_impl(date_impl: DateImpl) -> Of {
+ // We assume the value in the `DateImpl` is valid.
+ Of((date_impl & 0b1_1111_1111_1111) as u32)
}
#[inline]
- pub(super) fn from_mdf(Mdf(mdf): Mdf) -> Of {
+ pub(super) const fn from_mdf(Mdf(mdf): Mdf) -> Option<Of> {
let mdl = mdf >> 3;
- match MDL_TO_OL.get(mdl as usize) {
- Some(&v) => Of(mdf.wrapping_sub((i32::from(v) as u32 & 0x3ff) << 3)),
- None => Of(0),
+ if mdl > MAX_MDL {
+ // Panicking on out-of-bounds indexing would be reasonable, but just return `None`.
+ return None;
}
+ // Array is indexed from `[1..=MAX_MDL]`, with a `0` index having a meaningless value.
+ let v = MDL_TO_OL[mdl as usize];
+ let of = Of(mdf.wrapping_sub((v as i32 as u32 & 0x3ff) << 3));
+ of.validate()
}
#[inline]
- pub(super) fn valid(&self) -> bool {
- let Of(of) = *self;
- let ol = of >> 3;
- (MIN_OL..=MAX_OL).contains(&ol)
+ pub(super) const fn inner(&self) -> u32 {
+ self.0
}
+ /// Returns `(ordinal << 1) | leap-year-flag`.
#[inline]
- pub(super) const fn ordinal(&self) -> u32 {
- let Of(of) = *self;
- of >> 4
+ const fn ol(&self) -> u32 {
+ self.0 >> 3
}
#[inline]
- pub(super) fn with_ordinal(&self, ordinal: u32) -> Option<Of> {
- if ordinal > 366 {
- return None;
+ const fn validate(self) -> Option<Of> {
+ let ol = self.ol();
+ match ol >= MIN_OL && ol <= MAX_OL {
+ true => Some(self),
+ false => None,
}
+ }
- let Of(of) = *self;
- Some(Of((of & 0b1111) | (ordinal << 4)))
+ #[inline]
+ pub(super) const fn ordinal(&self) -> u32 {
+ self.0 >> 4
+ }
+
+ #[inline]
+ pub(super) const fn with_ordinal(&self, ordinal: u32) -> Option<Of> {
+ let of = Of((ordinal << 4) | (self.0 & 0b1111));
+ of.validate()
}
#[inline]
pub(super) const fn flags(&self) -> YearFlags {
- let Of(of) = *self;
- YearFlags((of & 0b1111) as u8)
+ YearFlags((self.0 & 0b1111) as u8)
}
#[inline]
- pub(super) fn weekday(&self) -> Weekday {
+ pub(super) const fn weekday(&self) -> Weekday {
let Of(of) = *self;
- Weekday::from_u32(((of >> 4) + (of & 0b111)) % 7).unwrap()
+ weekday_from_u32_mod7((of >> 4) + (of & 0b111))
}
#[inline]
@@ -326,25 +343,29 @@ impl Of {
// week ordinal = ordinal + delta
let Of(of) = *self;
let weekord = (of >> 4).wrapping_add(self.flags().isoweek_delta());
- (weekord / 7, Weekday::from_u32(weekord % 7).unwrap())
+ (weekord / 7, weekday_from_u32_mod7(weekord))
}
#[cfg_attr(feature = "cargo-clippy", allow(clippy::wrong_self_convention))]
#[inline]
- pub(super) fn to_mdf(&self) -> Mdf {
+ pub(super) const fn to_mdf(&self) -> Mdf {
Mdf::from_of(*self)
}
+ /// Returns an `Of` with the next day, or `None` if this is the last day of the year.
#[inline]
- pub(super) const fn succ(&self) -> Of {
- let Of(of) = *self;
- Of(of + (1 << 4))
+ pub(super) const fn succ(&self) -> Option<Of> {
+ let of = Of(self.0 + (1 << 4));
+ of.validate()
}
+ /// Returns an `Of` with the previous day, or `None` if this is the first day of the year.
#[inline]
- pub(super) const fn pred(&self) -> Of {
- let Of(of) = *self;
- Of(of - (1 << 4))
+ pub(super) const fn pred(&self) -> Option<Of> {
+ match self.ordinal() {
+ 1 => None,
+ _ => Some(Of(self.0 - (1 << 4))),
+ }
}
}
@@ -366,34 +387,44 @@ impl fmt::Debug for Of {
/// The whole bits except for the least 3 bits are referred as `Mdl`
/// (month, day of month and leap flag),
/// which is an index to the `MDL_TO_OL` lookup table.
+///
+/// The methods implemented on `Mdf` do not always return a valid value.
+/// Dates that can't exist, like February 30, can still be represented.
+/// Use `Mdl::valid` to check whether the date is valid.
#[derive(PartialEq, PartialOrd, Copy, Clone)]
-pub(super) struct Mdf(pub(super) u32);
+pub(super) struct Mdf(u32);
impl Mdf {
#[inline]
- pub(super) fn new(month: u32, day: u32, YearFlags(flags): YearFlags) -> Option<Mdf> {
- match month <= 12 && day <= 31 {
- true => Some(Mdf((month << 9) | (day << 4) | u32::from(flags))),
+ pub(super) const fn new(month: u32, day: u32, YearFlags(flags): YearFlags) -> Option<Mdf> {
+ match month >= 1 && month <= 12 && day >= 1 && day <= 31 {
+ true => Some(Mdf((month << 9) | (day << 4) | flags as u32)),
false => None,
}
}
#[inline]
- pub(super) fn from_of(Of(of): Of) -> Mdf {
+ pub(super) const fn from_of(Of(of): Of) -> Mdf {
let ol = of >> 3;
- match OL_TO_MDL.get(ol as usize) {
- Some(&v) => Mdf(of + (u32::from(v) << 3)),
- None => Mdf(0),
+ if ol <= MAX_OL {
+ // Array is indexed from `[1..=MAX_OL]`, with a `0` index having a meaningless value.
+ Mdf(of + ((OL_TO_MDL[ol as usize] as u32) << 3))
+ } else {
+ // Panicking here would be reasonable, but we are just going on with a safe value.
+ Mdf(0)
}
}
#[cfg(test)]
- pub(super) fn valid(&self) -> bool {
+ pub(super) const fn valid(&self) -> bool {
let Mdf(mdf) = *self;
let mdl = mdf >> 3;
- match MDL_TO_OL.get(mdl as usize) {
- Some(&v) => v >= 0,
- None => false,
+ if mdl <= MAX_MDL {
+ // Array is indexed from `[1..=MAX_MDL]`, with a `0` index having a meaningless value.
+ MDL_TO_OL[mdl as usize] >= 0
+ } else {
+ // Panicking here would be reasonable, but we are just going on with a safe value.
+ false
}
}
@@ -404,7 +435,7 @@ impl Mdf {
}
#[inline]
- pub(super) fn with_month(&self, month: u32) -> Option<Mdf> {
+ pub(super) const fn with_month(&self, month: u32) -> Option<Mdf> {
if month > 12 {
return None;
}
@@ -420,7 +451,7 @@ impl Mdf {
}
#[inline]
- pub(super) fn with_day(&self, day: u32) -> Option<Mdf> {
+ pub(super) const fn with_day(&self, day: u32) -> Option<Mdf> {
if day > 31 {
return None;
}
@@ -430,14 +461,14 @@ impl Mdf {
}
#[inline]
- pub(super) fn with_flags(&self, YearFlags(flags): YearFlags) -> Mdf {
+ pub(super) const fn with_flags(&self, YearFlags(flags): YearFlags) -> Mdf {
let Mdf(mdf) = *self;
- Mdf((mdf & !0b1111) | u32::from(flags))
+ Mdf((mdf & !0b1111) | flags as u32)
}
#[cfg_attr(feature = "cargo-clippy", allow(clippy::wrong_self_convention))]
#[inline]
- pub(super) fn to_of(&self) -> Of {
+ pub(super) const fn to_of(&self) -> Option<Of> {
Of::from_mdf(*self)
}
}
@@ -456,11 +487,26 @@ impl fmt::Debug for Mdf {
}
}
+/// Create a `Weekday` from an `u32`, with Monday = 0.
+/// Infallible, takes any `n` and applies `% 7`.
+#[inline]
+const fn weekday_from_u32_mod7(n: u32) -> Weekday {
+ match n % 7 {
+ 0 => Weekday::Mon,
+ 1 => Weekday::Tue,
+ 2 => Weekday::Wed,
+ 3 => Weekday::Thu,
+ 4 => Weekday::Fri,
+ 5 => Weekday::Sat,
+ _ => Weekday::Sun,
+ }
+}
+
#[cfg(test)]
mod tests {
- use num_iter::range_inclusive;
use std::u32;
+ use super::weekday_from_u32_mod7;
use super::{Mdf, Of};
use super::{YearFlags, A, AG, B, BA, C, CB, D, DC, E, ED, F, FE, G, GF};
use crate::Weekday;
@@ -507,7 +553,7 @@ mod tests {
#[test]
fn test_of() {
fn check(expected: bool, flags: YearFlags, ordinal1: u32, ordinal2: u32) {
- for ordinal in range_inclusive(ordinal1, ordinal2) {
+ for ordinal in ordinal1..=ordinal2 {
let of = match Of::new(ordinal, flags) {
Some(of) => of,
None if !expected => continue,
@@ -515,7 +561,7 @@ mod tests {
};
assert!(
- of.valid() == expected,
+ of.validate().is_some() == expected,
"ordinal {} = {:?} should be {} for dominical year {:?}",
ordinal,
of,
@@ -543,8 +589,8 @@ mod tests {
#[test]
fn test_mdf_valid() {
fn check(expected: bool, flags: YearFlags, month1: u32, day1: u32, month2: u32, day2: u32) {
- for month in range_inclusive(month1, month2) {
- for day in range_inclusive(day1, day2) {
+ for month in month1..=month2 {
+ for day in day1..=day2 {
let mdf = match Mdf::new(month, day, flags) {
Some(mdf) => mdf,
None if !expected => continue,
@@ -634,9 +680,8 @@ mod tests {
#[test]
fn test_of_fields() {
for &flags in FLAGS.iter() {
- for ordinal in range_inclusive(1u32, 366) {
- let of = Of::new(ordinal, flags).unwrap();
- if of.valid() {
+ for ordinal in 1u32..=366 {
+ if let Some(of) = Of::new(ordinal, flags) {
assert_eq!(of.ordinal(), ordinal);
}
}
@@ -648,15 +693,10 @@ mod tests {
fn check(flags: YearFlags, ordinal: u32) {
let of = Of::new(ordinal, flags).unwrap();
- for ordinal in range_inclusive(0u32, 1024) {
- let of = match of.with_ordinal(ordinal) {
- Some(of) => of,
- None if ordinal > 366 => continue,
- None => panic!("failed to create Of with ordinal {}", ordinal),
- };
-
- assert_eq!(of.valid(), Of::new(ordinal, flags).unwrap().valid());
- if of.valid() {
+ for ordinal in 0u32..=1024 {
+ let of = of.with_ordinal(ordinal);
+ assert_eq!(of, Of::new(ordinal, flags));
+ if let Some(of) = of {
assert_eq!(of.ordinal(), ordinal);
}
}
@@ -691,7 +731,7 @@ mod tests {
for &flags in FLAGS.iter() {
let mut prev = Of::new(1, flags).unwrap().weekday();
- for ordinal in range_inclusive(2u32, flags.ndays()) {
+ for ordinal in 2u32..=flags.ndays() {
let of = Of::new(ordinal, flags).unwrap();
let expected = prev.succ();
assert_eq!(of.weekday(), expected);
@@ -703,8 +743,8 @@ mod tests {
#[test]
fn test_mdf_fields() {
for &flags in FLAGS.iter() {
- for month in range_inclusive(1u32, 12) {
- for day in range_inclusive(1u32, 31) {
+ for month in 1u32..=12 {
+ for day in 1u32..31 {
let mdf = match Mdf::new(month, day, flags) {
Some(mdf) => mdf,
None => continue,
@@ -724,7 +764,7 @@ mod tests {
fn check(flags: YearFlags, month: u32, day: u32) {
let mdf = Mdf::new(month, day, flags).unwrap();
- for month in range_inclusive(0u32, 16) {
+ for month in 0u32..=16 {
let mdf = match mdf.with_month(month) {
Some(mdf) => mdf,
None if month > 12 => continue,
@@ -737,7 +777,7 @@ mod tests {
}
}
- for day in range_inclusive(0u32, 1024) {
+ for day in 0u32..=1024 {
let mdf = match mdf.with_day(day) {
Some(mdf) => mdf,
None if day > 31 => continue,
@@ -780,37 +820,74 @@ mod tests {
#[test]
fn test_of_to_mdf() {
- for i in range_inclusive(0u32, 8192) {
- let of = Of(i);
- assert_eq!(of.valid(), of.to_mdf().valid());
+ for i in 0u32..=8192 {
+ if let Some(of) = Of(i).validate() {
+ assert!(of.to_mdf().valid());
+ }
}
}
#[test]
fn test_mdf_to_of() {
- for i in range_inclusive(0u32, 8192) {
+ for i in 0u32..=8192 {
let mdf = Mdf(i);
- assert_eq!(mdf.valid(), mdf.to_of().valid());
+ assert_eq!(mdf.valid(), mdf.to_of().is_some());
}
}
#[test]
fn test_of_to_mdf_to_of() {
- for i in range_inclusive(0u32, 8192) {
- let of = Of(i);
- if of.valid() {
- assert_eq!(of, of.to_mdf().to_of());
+ for i in 0u32..=8192 {
+ if let Some(of) = Of(i).validate() {
+ assert_eq!(of, of.to_mdf().to_of().unwrap());
}
}
}
#[test]
fn test_mdf_to_of_to_mdf() {
- for i in range_inclusive(0u32, 8192) {
+ for i in 0u32..=8192 {
let mdf = Mdf(i);
if mdf.valid() {
- assert_eq!(mdf, mdf.to_of().to_mdf());
+ assert_eq!(mdf, mdf.to_of().unwrap().to_mdf());
}
}
}
+
+ #[test]
+ fn test_invalid_returns_none() {
+ let regular_year = YearFlags::from_year(2023);
+ let leap_year = YearFlags::from_year(2024);
+ assert!(Of::new(0, regular_year).is_none());
+ assert!(Of::new(366, regular_year).is_none());
+ assert!(Of::new(366, leap_year).is_some());
+ assert!(Of::new(367, regular_year).is_none());
+
+ assert!(Mdf::new(0, 1, regular_year).is_none());
+ assert!(Mdf::new(13, 1, regular_year).is_none());
+ assert!(Mdf::new(1, 0, regular_year).is_none());
+ assert!(Mdf::new(1, 32, regular_year).is_none());
+ assert!(Mdf::new(2, 31, regular_year).is_some());
+
+ assert!(Of::from_mdf(Mdf::new(2, 30, regular_year).unwrap()).is_none());
+ assert!(Of::from_mdf(Mdf::new(2, 30, leap_year).unwrap()).is_none());
+ assert!(Of::from_mdf(Mdf::new(2, 29, regular_year).unwrap()).is_none());
+ assert!(Of::from_mdf(Mdf::new(2, 29, leap_year).unwrap()).is_some());
+ assert!(Of::from_mdf(Mdf::new(2, 28, regular_year).unwrap()).is_some());
+
+ assert!(Of::new(365, regular_year).unwrap().succ().is_none());
+ assert!(Of::new(365, leap_year).unwrap().succ().is_some());
+ assert!(Of::new(366, leap_year).unwrap().succ().is_none());
+
+ assert!(Of::new(1, regular_year).unwrap().pred().is_none());
+ assert!(Of::new(1, leap_year).unwrap().pred().is_none());
+ }
+
+ #[test]
+ fn test_weekday_from_u32_mod7() {
+ for i in 0..=1000 {
+ assert_eq!(weekday_from_u32_mod7(i), Weekday::try_from((i % 7) as u8).unwrap());
+ }
+ assert_eq!(weekday_from_u32_mod7(u32::MAX), Weekday::Thu);
+ }
}
diff --git a/vendor/chrono/src/naive/isoweek.rs b/vendor/chrono/src/naive/isoweek.rs
index 6a4fcfd11..df5556a12 100644
--- a/vendor/chrono/src/naive/isoweek.rs
+++ b/vendor/chrono/src/naive/isoweek.rs
@@ -46,7 +46,8 @@ pub(super) fn iso_week_from_yof(year: i32, of: Of) -> IsoWeek {
(year, rawweek)
}
};
- IsoWeek { ywf: (year << 10) | (week << 4) as DateImpl | DateImpl::from(of.flags().0) }
+ let flags = YearFlags::from_year(year);
+ IsoWeek { ywf: (year << 10) | (week << 4) as DateImpl | DateImpl::from(flags.0) }
}
impl IsoWeek {
@@ -57,7 +58,7 @@ impl IsoWeek {
/// ```
/// use chrono::{NaiveDate, Datelike, Weekday};
///
- /// let d = NaiveDate::from_isoywd(2015, 1, Weekday::Mon);
+ /// let d = NaiveDate::from_isoywd_opt(2015, 1, Weekday::Mon).unwrap();
/// assert_eq!(d.iso_week().year(), 2015);
/// ```
///
@@ -66,7 +67,7 @@ impl IsoWeek {
///
/// ```
/// # use chrono::{NaiveDate, Datelike, Weekday};
- /// # let d = NaiveDate::from_isoywd(2015, 1, Weekday::Mon);
+ /// # let d = NaiveDate::from_isoywd_opt(2015, 1, Weekday::Mon).unwrap();
/// assert_eq!(d.year(), 2014);
/// assert_eq!(d, NaiveDate::from_ymd_opt(2014, 12, 29).unwrap());
/// ```
@@ -84,7 +85,7 @@ impl IsoWeek {
/// ```
/// use chrono::{NaiveDate, Datelike, Weekday};
///
- /// let d = NaiveDate::from_isoywd(2015, 15, Weekday::Mon);
+ /// let d = NaiveDate::from_isoywd_opt(2015, 15, Weekday::Mon).unwrap();
/// assert_eq!(d.iso_week().week(), 15);
/// ```
#[inline]
@@ -101,7 +102,7 @@ impl IsoWeek {
/// ```
/// use chrono::{NaiveDate, Datelike, Weekday};
///
- /// let d = NaiveDate::from_isoywd(2015, 15, Weekday::Mon);
+ /// let d = NaiveDate::from_isoywd_opt(2015, 15, Weekday::Mon).unwrap();
/// assert_eq!(d.iso_week().week0(), 14);
/// ```
#[inline]
@@ -164,4 +165,38 @@ mod tests {
assert_eq!(maxweek.week0(), 0);
assert_eq!(format!("{:?}", maxweek), NaiveDate::MAX.format("%G-W%V").to_string());
}
+
+ #[test]
+ fn test_iso_week_equivalence_for_first_week() {
+ let monday = NaiveDate::from_ymd_opt(2024, 12, 30).unwrap();
+ let friday = NaiveDate::from_ymd_opt(2025, 1, 3).unwrap();
+
+ assert_eq!(monday.iso_week(), friday.iso_week());
+ }
+
+ #[test]
+ fn test_iso_week_equivalence_for_last_week() {
+ let monday = NaiveDate::from_ymd_opt(2026, 12, 28).unwrap();
+ let friday = NaiveDate::from_ymd_opt(2027, 1, 1).unwrap();
+
+ assert_eq!(monday.iso_week(), friday.iso_week());
+ }
+
+ #[test]
+ fn test_iso_week_ordering_for_first_week() {
+ let monday = NaiveDate::from_ymd_opt(2024, 12, 30).unwrap();
+ let friday = NaiveDate::from_ymd_opt(2025, 1, 3).unwrap();
+
+ assert!(monday.iso_week() >= friday.iso_week());
+ assert!(monday.iso_week() <= friday.iso_week());
+ }
+
+ #[test]
+ fn test_iso_week_ordering_for_last_week() {
+ let monday = NaiveDate::from_ymd_opt(2026, 12, 28).unwrap();
+ let friday = NaiveDate::from_ymd_opt(2027, 1, 1).unwrap();
+
+ assert!(monday.iso_week() >= friday.iso_week());
+ assert!(monday.iso_week() <= friday.iso_week());
+ }
}
diff --git a/vendor/chrono/src/naive/time/mod.rs b/vendor/chrono/src/naive/time/mod.rs
index 1d36583aa..3700c5cba 100644
--- a/vendor/chrono/src/naive/time/mod.rs
+++ b/vendor/chrono/src/naive/time/mod.rs
@@ -8,14 +8,15 @@ use core::borrow::Borrow;
use core::ops::{Add, AddAssign, Sub, SubAssign};
use core::{fmt, str};
-use num_integer::div_mod_floor;
#[cfg(feature = "rkyv")]
use rkyv::{Archive, Deserialize, Serialize};
#[cfg(any(feature = "alloc", feature = "std", test))]
use crate::format::DelayedFormat;
-use crate::format::{parse, write_hundreds, ParseError, ParseResult, Parsed, StrftimeItems};
-use crate::format::{Fixed, Item, Numeric, Pad};
+use crate::format::{
+ parse, parse_and_remainder, write_hundreds, Fixed, Item, Numeric, Pad, ParseError, ParseResult,
+ Parsed, StrftimeItems,
+};
use crate::oldtime::Duration as OldDuration;
use crate::Timelike;
@@ -74,7 +75,7 @@ mod tests;
/// All methods accepting fractional seconds will accept such values.
///
/// ```
-/// use chrono::{NaiveDate, NaiveTime, Utc, TimeZone};
+/// use chrono::{NaiveDate, NaiveTime, Utc};
///
/// let t = NaiveTime::from_hms_milli_opt(8, 59, 59, 1_000).unwrap();
///
@@ -161,7 +162,7 @@ mod tests;
/// will be represented as the second part being 60, as required by ISO 8601.
///
/// ```
-/// use chrono::{Utc, TimeZone, NaiveDate};
+/// use chrono::{Utc, NaiveDate};
///
/// let dt = NaiveDate::from_ymd_opt(2015, 6, 30).unwrap().and_hms_milli_opt(23, 59, 59, 1_000).unwrap().and_local_timezone(Utc).unwrap();
/// assert_eq!(format!("{:?}", dt), "2015-06-30T23:59:60Z");
@@ -214,6 +215,7 @@ impl NaiveTime {
/// Panics on invalid hour, minute and/or second.
#[deprecated(since = "0.4.23", note = "use `from_hms_opt()` instead")]
#[inline]
+ #[must_use]
pub fn from_hms(hour: u32, min: u32, sec: u32) -> NaiveTime {
NaiveTime::from_hms_opt(hour, min, sec).expect("invalid time")
}
@@ -239,7 +241,8 @@ impl NaiveTime {
/// assert!(from_hms_opt(23, 59, 60).is_none());
/// ```
#[inline]
- pub fn from_hms_opt(hour: u32, min: u32, sec: u32) -> Option<NaiveTime> {
+ #[must_use]
+ pub const fn from_hms_opt(hour: u32, min: u32, sec: u32) -> Option<NaiveTime> {
NaiveTime::from_hms_nano_opt(hour, min, sec, 0)
}
@@ -251,6 +254,7 @@ impl NaiveTime {
/// Panics on invalid hour, minute, second and/or millisecond.
#[deprecated(since = "0.4.23", note = "use `from_hms_milli_opt()` instead")]
#[inline]
+ #[must_use]
pub fn from_hms_milli(hour: u32, min: u32, sec: u32, milli: u32) -> NaiveTime {
NaiveTime::from_hms_milli_opt(hour, min, sec, milli).expect("invalid time")
}
@@ -278,6 +282,7 @@ impl NaiveTime {
/// assert!(from_hmsm_opt(23, 59, 59, 2_000).is_none());
/// ```
#[inline]
+ #[must_use]
pub fn from_hms_milli_opt(hour: u32, min: u32, sec: u32, milli: u32) -> Option<NaiveTime> {
milli
.checked_mul(1_000_000)
@@ -292,6 +297,7 @@ impl NaiveTime {
/// Panics on invalid hour, minute, second and/or microsecond.
#[deprecated(since = "0.4.23", note = "use `from_hms_micro_opt()` instead")]
#[inline]
+ #[must_use]
pub fn from_hms_micro(hour: u32, min: u32, sec: u32, micro: u32) -> NaiveTime {
NaiveTime::from_hms_micro_opt(hour, min, sec, micro).expect("invalid time")
}
@@ -319,6 +325,7 @@ impl NaiveTime {
/// assert!(from_hmsu_opt(23, 59, 59, 2_000_000).is_none());
/// ```
#[inline]
+ #[must_use]
pub fn from_hms_micro_opt(hour: u32, min: u32, sec: u32, micro: u32) -> Option<NaiveTime> {
micro.checked_mul(1_000).and_then(|nano| NaiveTime::from_hms_nano_opt(hour, min, sec, nano))
}
@@ -331,6 +338,7 @@ impl NaiveTime {
/// Panics on invalid hour, minute, second and/or nanosecond.
#[deprecated(since = "0.4.23", note = "use `from_hms_nano_opt()` instead")]
#[inline]
+ #[must_use]
pub fn from_hms_nano(hour: u32, min: u32, sec: u32, nano: u32) -> NaiveTime {
NaiveTime::from_hms_nano_opt(hour, min, sec, nano).expect("invalid time")
}
@@ -358,7 +366,8 @@ impl NaiveTime {
/// assert!(from_hmsn_opt(23, 59, 59, 2_000_000_000).is_none());
/// ```
#[inline]
- pub fn from_hms_nano_opt(hour: u32, min: u32, sec: u32, nano: u32) -> Option<NaiveTime> {
+ #[must_use]
+ pub const fn from_hms_nano_opt(hour: u32, min: u32, sec: u32, nano: u32) -> Option<NaiveTime> {
if hour >= 24 || min >= 60 || sec >= 60 || nano >= 2_000_000_000 {
return None;
}
@@ -374,6 +383,7 @@ impl NaiveTime {
/// Panics on invalid number of seconds and/or nanosecond.
#[deprecated(since = "0.4.23", note = "use `from_num_seconds_from_midnight_opt()` instead")]
#[inline]
+ #[must_use]
pub fn from_num_seconds_from_midnight(secs: u32, nano: u32) -> NaiveTime {
NaiveTime::from_num_seconds_from_midnight_opt(secs, nano).expect("invalid time")
}
@@ -399,7 +409,8 @@ impl NaiveTime {
/// assert!(from_nsecs_opt(86399, 2_000_000_000).is_none());
/// ```
#[inline]
- pub fn from_num_seconds_from_midnight_opt(secs: u32, nano: u32) -> Option<NaiveTime> {
+ #[must_use]
+ pub const fn from_num_seconds_from_midnight_opt(secs: u32, nano: u32) -> Option<NaiveTime> {
if secs >= 86_400 || nano >= 2_000_000_000 {
return None;
}
@@ -473,6 +484,28 @@ impl NaiveTime {
parsed.to_naive_time()
}
+ /// Parses a string from a user-specified format into a new `NaiveTime` value, and a slice with
+ /// the remaining portion of the string.
+ /// See the [`format::strftime` module](../format/strftime/index.html)
+ /// on the supported escape sequences.
+ ///
+ /// Similar to [`parse_from_str`](#method.parse_from_str).
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// # use chrono::{NaiveTime};
+ /// let (time, remainder) = NaiveTime::parse_and_remainder(
+ /// "3h4m33s trailing text", "%-Hh%-Mm%-Ss").unwrap();
+ /// assert_eq!(time, NaiveTime::from_hms_opt(3, 4, 33).unwrap());
+ /// assert_eq!(remainder, " trailing text");
+ /// ```
+ pub fn parse_and_remainder<'a>(s: &'a str, fmt: &str) -> ParseResult<(NaiveTime, &'a str)> {
+ let mut parsed = Parsed::new();
+ let remainder = parse_and_remainder(&mut parsed, s, StrftimeItems::new(fmt))?;
+ parsed.to_naive_time().map(|t| (t, remainder))
+ }
+
/// Adds given `Duration` to the current time,
/// and also returns the number of *seconds*
/// in the integral number of days ignored from the addition.
@@ -483,7 +516,7 @@ impl NaiveTime {
/// ```
/// use chrono::{Duration, NaiveTime};
///
- /// let from_hms = NaiveTime::from_hms;
+ /// let from_hms = |h, m, s| { NaiveTime::from_hms_opt(h, m, s).unwrap() };
///
/// assert_eq!(from_hms(3, 4, 5).overflowing_add_signed(Duration::hours(11)),
/// (from_hms(14, 4, 5), 0));
@@ -492,6 +525,7 @@ impl NaiveTime {
/// assert_eq!(from_hms(3, 4, 5).overflowing_add_signed(Duration::hours(-7)),
/// (from_hms(20, 4, 5), -86_400));
/// ```
+ #[must_use]
pub fn overflowing_add_signed(&self, mut rhs: OldDuration) -> (NaiveTime, i64) {
let mut secs = self.secs;
let mut frac = self.frac;
@@ -565,7 +599,7 @@ impl NaiveTime {
/// ```
/// use chrono::{Duration, NaiveTime};
///
- /// let from_hms = NaiveTime::from_hms;
+ /// let from_hms = |h, m, s| { NaiveTime::from_hms_opt(h, m, s).unwrap() };
///
/// assert_eq!(from_hms(3, 4, 5).overflowing_sub_signed(Duration::hours(2)),
/// (from_hms(1, 4, 5), 0));
@@ -575,6 +609,7 @@ impl NaiveTime {
/// (from_hms(1, 4, 5), -86_400));
/// ```
#[inline]
+ #[must_use]
pub fn overflowing_sub_signed(&self, rhs: OldDuration) -> (NaiveTime, i64) {
let (time, rhs) = self.overflowing_add_signed(-rhs);
(time, -rhs) // safe to negate, rhs is within +/- (2^63 / 1000)
@@ -595,7 +630,7 @@ impl NaiveTime {
/// ```
/// use chrono::{Duration, NaiveTime};
///
- /// let from_hmsm = NaiveTime::from_hms_milli;
+ /// let from_hmsm = |h, m, s, milli| { NaiveTime::from_hms_milli_opt(h, m, s, milli).unwrap() };
/// let since = NaiveTime::signed_duration_since;
///
/// assert_eq!(since(from_hmsm(3, 5, 7, 900), from_hmsm(3, 5, 7, 900)),
@@ -621,7 +656,7 @@ impl NaiveTime {
///
/// ```
/// # use chrono::{Duration, NaiveTime};
- /// # let from_hmsm = NaiveTime::from_hms_milli;
+ /// # let from_hmsm = |h, m, s, milli| { NaiveTime::from_hms_milli_opt(h, m, s, milli).unwrap() };
/// # let since = NaiveTime::signed_duration_since;
/// assert_eq!(since(from_hmsm(3, 0, 59, 1_000), from_hmsm(3, 0, 59, 0)),
/// Duration::seconds(1));
@@ -634,6 +669,7 @@ impl NaiveTime {
/// assert_eq!(since(from_hmsm(3, 0, 59, 1_000), from_hmsm(2, 59, 59, 1_000)),
/// Duration::seconds(61));
/// ```
+ #[must_use]
pub fn signed_duration_since(self, rhs: NaiveTime) -> OldDuration {
// | | :leap| | | | | | | :leap| |
// | | : | | | | | | | : | |
@@ -696,6 +732,7 @@ impl NaiveTime {
#[cfg(any(feature = "alloc", feature = "std", test))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "alloc", feature = "std"))))]
#[inline]
+ #[must_use]
pub fn format_with_items<'a, I, B>(&self, items: I) -> DelayedFormat<I>
where
I: Iterator<Item = B> + Clone,
@@ -741,14 +778,17 @@ impl NaiveTime {
#[cfg(any(feature = "alloc", feature = "std", test))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "alloc", feature = "std"))))]
#[inline]
+ #[must_use]
pub fn format<'a>(&self, fmt: &'a str) -> DelayedFormat<StrftimeItems<'a>> {
self.format_with_items(StrftimeItems::new(fmt))
}
/// Returns a triple of the hour, minute and second numbers.
fn hms(&self) -> (u32, u32, u32) {
- let (mins, sec) = div_mod_floor(self.secs, 60);
- let (hour, min) = div_mod_floor(mins, 60);
+ let sec = self.secs % 60;
+ let mins = self.secs / 60;
+ let min = mins % 60;
+ let hour = mins / 60;
(hour, min, sec)
}
@@ -803,7 +843,8 @@ impl Timelike for NaiveTime {
/// ([Why?](#leap-second-handling))
/// Use the proper [formatting method](#method.format) to get a human-readable representation.
///
- /// ```
+ #[cfg_attr(not(feature = "std"), doc = "```ignore")]
+ #[cfg_attr(feature = "std", doc = "```")]
/// # use chrono::{NaiveTime, Timelike};
/// let leap = NaiveTime::from_hms_milli_opt(23, 59, 59, 1_000).unwrap();
/// assert_eq!(leap.second(), 59);
@@ -831,7 +872,8 @@ impl Timelike for NaiveTime {
/// You can reduce the range with `time.nanosecond() % 1_000_000_000`, or
/// use the proper [formatting method](#method.format) to get a human-readable representation.
///
- /// ```
+ #[cfg_attr(not(feature = "std"), doc = "```ignore")]
+ #[cfg_attr(feature = "std", doc = "```")]
/// # use chrono::{NaiveTime, Timelike};
/// let leap = NaiveTime::from_hms_milli_opt(23, 59, 59, 1_000).unwrap();
/// assert_eq!(leap.nanosecond(), 1_000_000_000);
@@ -969,17 +1011,16 @@ impl Timelike for NaiveTime {
/// An addition of `Duration` to `NaiveTime` wraps around and never overflows or underflows.
/// In particular the addition ignores integral number of days.
///
-/// As a part of Chrono's [leap second handling](#leap-second-handling),
-/// the addition assumes that **there is no leap second ever**,
-/// except when the `NaiveTime` itself represents a leap second
-/// in which case the assumption becomes that **there is exactly a single leap second ever**.
+/// As a part of Chrono's [leap second handling], the addition assumes that **there is no leap
+/// second ever**, except when the `NaiveTime` itself represents a leap second in which case the
+/// assumption becomes that **there is exactly a single leap second ever**.
///
/// # Example
///
/// ```
/// use chrono::{Duration, NaiveTime};
///
-/// let from_hmsm = NaiveTime::from_hms_milli;
+/// let from_hmsm = |h, m, s, milli| { NaiveTime::from_hms_milli_opt(h, m, s, milli).unwrap() };
///
/// assert_eq!(from_hmsm(3, 5, 7, 0) + Duration::zero(), from_hmsm(3, 5, 7, 0));
/// assert_eq!(from_hmsm(3, 5, 7, 0) + Duration::seconds(1), from_hmsm(3, 5, 8, 0));
@@ -995,7 +1036,7 @@ impl Timelike for NaiveTime {
///
/// ```
/// # use chrono::{Duration, NaiveTime};
-/// # let from_hmsm = NaiveTime::from_hms_milli;
+/// # let from_hmsm = |h, m, s, milli| { NaiveTime::from_hms_milli_opt(h, m, s, milli).unwrap() };
/// assert_eq!(from_hmsm(3, 5, 7, 0) + Duration::seconds(22*60*60), from_hmsm(1, 5, 7, 0));
/// assert_eq!(from_hmsm(3, 5, 7, 0) + Duration::seconds(-8*60*60), from_hmsm(19, 5, 7, 0));
/// assert_eq!(from_hmsm(3, 5, 7, 0) + Duration::days(800), from_hmsm(3, 5, 7, 0));
@@ -1005,7 +1046,7 @@ impl Timelike for NaiveTime {
///
/// ```
/// # use chrono::{Duration, NaiveTime};
-/// # let from_hmsm = NaiveTime::from_hms_milli;
+/// # let from_hmsm = |h, m, s, milli| { NaiveTime::from_hms_milli_opt(h, m, s, milli).unwrap() };
/// let leap = from_hmsm(3, 5, 59, 1_300);
/// assert_eq!(leap + Duration::zero(), from_hmsm(3, 5, 59, 1_300));
/// assert_eq!(leap + Duration::milliseconds(-500), from_hmsm(3, 5, 59, 800));
@@ -1015,6 +1056,8 @@ impl Timelike for NaiveTime {
/// assert_eq!(leap + Duration::seconds(-10), from_hmsm(3, 5, 50, 300));
/// assert_eq!(leap + Duration::days(1), from_hmsm(3, 5, 59, 300));
/// ```
+///
+/// [leap second handling]: crate::NaiveTime#leap-second-handling
impl Add<OldDuration> for NaiveTime {
type Output = NaiveTime;
@@ -1035,17 +1078,16 @@ impl AddAssign<OldDuration> for NaiveTime {
/// In particular the addition ignores integral number of days.
/// It is the same as the addition with a negated `Duration`.
///
-/// As a part of Chrono's [leap second handling](#leap-second-handling),
-/// the addition assumes that **there is no leap second ever**,
-/// except when the `NaiveTime` itself represents a leap second
-/// in which case the assumption becomes that **there is exactly a single leap second ever**.
+/// As a part of Chrono's [leap second handling], the subtraction assumes that **there is no leap
+/// second ever**, except when the `NaiveTime` itself represents a leap second in which case the
+/// assumption becomes that **there is exactly a single leap second ever**.
///
/// # Example
///
/// ```
/// use chrono::{Duration, NaiveTime};
///
-/// let from_hmsm = NaiveTime::from_hms_milli;
+/// let from_hmsm = |h, m, s, milli| { NaiveTime::from_hms_milli_opt(h, m, s, milli).unwrap() };
///
/// assert_eq!(from_hmsm(3, 5, 7, 0) - Duration::zero(), from_hmsm(3, 5, 7, 0));
/// assert_eq!(from_hmsm(3, 5, 7, 0) - Duration::seconds(1), from_hmsm(3, 5, 6, 0));
@@ -1059,7 +1101,7 @@ impl AddAssign<OldDuration> for NaiveTime {
///
/// ```
/// # use chrono::{Duration, NaiveTime};
-/// # let from_hmsm = NaiveTime::from_hms_milli;
+/// # let from_hmsm = |h, m, s, milli| { NaiveTime::from_hms_milli_opt(h, m, s, milli).unwrap() };
/// assert_eq!(from_hmsm(3, 5, 7, 0) - Duration::seconds(8*60*60), from_hmsm(19, 5, 7, 0));
/// assert_eq!(from_hmsm(3, 5, 7, 0) - Duration::days(800), from_hmsm(3, 5, 7, 0));
/// ```
@@ -1068,7 +1110,7 @@ impl AddAssign<OldDuration> for NaiveTime {
///
/// ```
/// # use chrono::{Duration, NaiveTime};
-/// # let from_hmsm = NaiveTime::from_hms_milli;
+/// # let from_hmsm = |h, m, s, milli| { NaiveTime::from_hms_milli_opt(h, m, s, milli).unwrap() };
/// let leap = from_hmsm(3, 5, 59, 1_300);
/// assert_eq!(leap - Duration::zero(), from_hmsm(3, 5, 59, 1_300));
/// assert_eq!(leap - Duration::milliseconds(200), from_hmsm(3, 5, 59, 1_100));
@@ -1076,6 +1118,8 @@ impl AddAssign<OldDuration> for NaiveTime {
/// assert_eq!(leap - Duration::seconds(60), from_hmsm(3, 5, 0, 300));
/// assert_eq!(leap - Duration::days(1), from_hmsm(3, 6, 0, 300));
/// ```
+///
+/// [leap second handling]: crate::NaiveTime#leap-second-handling
impl Sub<OldDuration> for NaiveTime {
type Output = NaiveTime;
@@ -1110,7 +1154,7 @@ impl SubAssign<OldDuration> for NaiveTime {
/// ```
/// use chrono::{Duration, NaiveTime};
///
-/// let from_hmsm = NaiveTime::from_hms_milli;
+/// let from_hmsm = |h, m, s, milli| { NaiveTime::from_hms_milli_opt(h, m, s, milli).unwrap() };
///
/// assert_eq!(from_hmsm(3, 5, 7, 900) - from_hmsm(3, 5, 7, 900), Duration::zero());
/// assert_eq!(from_hmsm(3, 5, 7, 900) - from_hmsm(3, 5, 7, 875), Duration::milliseconds(25));
@@ -1128,7 +1172,7 @@ impl SubAssign<OldDuration> for NaiveTime {
///
/// ```
/// # use chrono::{Duration, NaiveTime};
-/// # let from_hmsm = NaiveTime::from_hms_milli;
+/// # let from_hmsm = |h, m, s, milli| { NaiveTime::from_hms_milli_opt(h, m, s, milli).unwrap() };
/// assert_eq!(from_hmsm(3, 0, 59, 1_000) - from_hmsm(3, 0, 59, 0), Duration::seconds(1));
/// assert_eq!(from_hmsm(3, 0, 59, 1_500) - from_hmsm(3, 0, 59, 0),
/// Duration::milliseconds(1500));
diff --git a/vendor/chrono/src/offset/fixed.rs b/vendor/chrono/src/offset/fixed.rs
index 0989dfa5b..246d6666e 100644
--- a/vendor/chrono/src/offset/fixed.rs
+++ b/vendor/chrono/src/offset/fixed.rs
@@ -6,7 +6,6 @@
use core::fmt;
use core::ops::{Add, Sub};
-use num_integer::div_mod_floor;
#[cfg(feature = "rkyv")]
use rkyv::{Archive, Deserialize, Serialize};
@@ -34,6 +33,7 @@ impl FixedOffset {
///
/// Panics on the out-of-bound `secs`.
#[deprecated(since = "0.4.23", note = "use `east_opt()` instead")]
+ #[must_use]
pub fn east(secs: i32) -> FixedOffset {
FixedOffset::east_opt(secs).expect("FixedOffset::east out of bounds")
}
@@ -45,14 +45,18 @@ impl FixedOffset {
///
/// # Example
///
- /// ```
+ #[cfg_attr(not(feature = "std"), doc = "```ignore")]
+ #[cfg_attr(feature = "std", doc = "```")]
/// use chrono::{FixedOffset, TimeZone};
/// let hour = 3600;
- /// let datetime = FixedOffset::east_opt(5 * hour).unwrap().ymd_opt(2016, 11, 08).unwrap()
- /// .and_hms_opt(0, 0, 0).unwrap();
+ /// let datetime = FixedOffset::east_opt(5 * hour)
+ /// .unwrap()
+ /// .with_ymd_and_hms(2016, 11, 08, 0, 0, 0)
+ /// .unwrap();
/// assert_eq!(&datetime.to_rfc3339(), "2016-11-08T00:00:00+05:00")
/// ```
- pub fn east_opt(secs: i32) -> Option<FixedOffset> {
+ #[must_use]
+ pub const fn east_opt(secs: i32) -> Option<FixedOffset> {
if -86_400 < secs && secs < 86_400 {
Some(FixedOffset { local_minus_utc: secs })
} else {
@@ -65,6 +69,7 @@ impl FixedOffset {
///
/// Panics on the out-of-bound `secs`.
#[deprecated(since = "0.4.23", note = "use `west_opt()` instead")]
+ #[must_use]
pub fn west(secs: i32) -> FixedOffset {
FixedOffset::west_opt(secs).expect("FixedOffset::west out of bounds")
}
@@ -76,14 +81,18 @@ impl FixedOffset {
///
/// # Example
///
- /// ```
+ #[cfg_attr(not(feature = "std"), doc = "```ignore")]
+ #[cfg_attr(feature = "std", doc = "```")]
/// use chrono::{FixedOffset, TimeZone};
/// let hour = 3600;
- /// let datetime = FixedOffset::west_opt(5 * hour).unwrap().ymd_opt(2016, 11, 08).unwrap()
- /// .and_hms_opt(0, 0, 0).unwrap();
+ /// let datetime = FixedOffset::west_opt(5 * hour)
+ /// .unwrap()
+ /// .with_ymd_and_hms(2016, 11, 08, 0, 0, 0)
+ /// .unwrap();
/// assert_eq!(&datetime.to_rfc3339(), "2016-11-08T00:00:00-05:00")
/// ```
- pub fn west_opt(secs: i32) -> Option<FixedOffset> {
+ #[must_use]
+ pub const fn west_opt(secs: i32) -> Option<FixedOffset> {
if -86_400 < secs && secs < 86_400 {
Some(FixedOffset { local_minus_utc: -secs })
} else {
@@ -136,8 +145,10 @@ impl fmt::Debug for FixedOffset {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let offset = self.local_minus_utc;
let (sign, offset) = if offset < 0 { ('-', -offset) } else { ('+', offset) };
- let (mins, sec) = div_mod_floor(offset, 60);
- let (hour, min) = div_mod_floor(mins, 60);
+ let sec = offset.rem_euclid(60);
+ let mins = offset.div_euclid(60);
+ let min = mins.rem_euclid(60);
+ let hour = mins.div_euclid(60);
if sec == 0 {
write!(f, "{}{:02}:{:02}", sign, hour, min)
} else {
diff --git a/vendor/chrono/src/offset/local/mod.rs b/vendor/chrono/src/offset/local/mod.rs
index e280c7800..372fd4976 100644
--- a/vendor/chrono/src/offset/local/mod.rs
+++ b/vendor/chrono/src/offset/local/mod.rs
@@ -8,12 +8,19 @@ use rkyv::{Archive, Deserialize, Serialize};
use super::fixed::FixedOffset;
use super::{LocalResult, TimeZone};
-use crate::naive::{NaiveDate, NaiveDateTime};
+use crate::naive::{NaiveDate, NaiveDateTime, NaiveTime};
#[allow(deprecated)]
-use crate::{Date, DateTime};
+use crate::Date;
+use crate::{DateTime, Utc};
+
+#[cfg(unix)]
+#[path = "unix.rs"]
+mod inner;
+
+#[cfg(windows)]
+#[path = "windows.rs"]
+mod inner;
-// we don't want `stub.rs` when the target_os is not wasi or emscripten
-// as we use js-sys to get the date instead
#[cfg(all(
not(unix),
not(windows),
@@ -23,16 +30,37 @@ use crate::{Date, DateTime};
not(any(target_os = "emscripten", target_os = "wasi"))
))
))]
-#[path = "stub.rs"]
-mod inner;
+mod inner {
+ use crate::{FixedOffset, LocalResult, NaiveDateTime};
-#[cfg(unix)]
-#[path = "unix.rs"]
-mod inner;
+ pub(super) fn offset_from_utc_datetime(_utc_time: &NaiveDateTime) -> LocalResult<FixedOffset> {
+ LocalResult::Single(FixedOffset::east_opt(0).unwrap())
+ }
-#[cfg(windows)]
-#[path = "windows.rs"]
-mod inner;
+ pub(super) fn offset_from_local_datetime(
+ _local_time: &NaiveDateTime,
+ ) -> LocalResult<FixedOffset> {
+ LocalResult::Single(FixedOffset::east_opt(0).unwrap())
+ }
+}
+
+#[cfg(all(
+ target_arch = "wasm32",
+ feature = "wasmbind",
+ not(any(target_os = "emscripten", target_os = "wasi"))
+))]
+mod inner {
+ use crate::{FixedOffset, LocalResult, NaiveDateTime};
+
+ pub(super) fn offset_from_utc_datetime(_utc: &NaiveDateTime) -> LocalResult<FixedOffset> {
+ let offset = js_sys::Date::new_0().get_timezone_offset();
+ LocalResult::Single(FixedOffset::west_opt((offset as i32) * 60).unwrap())
+ }
+
+ pub(super) fn offset_from_local_datetime(local: &NaiveDateTime) -> LocalResult<FixedOffset> {
+ offset_from_utc_datetime(local)
+ }
+}
#[cfg(unix)]
mod tz_info;
@@ -48,8 +76,9 @@ mod tz_info;
/// ```
/// use chrono::{Local, DateTime, TimeZone};
///
-/// let dt: DateTime<Local> = Local::now();
-/// let dt: DateTime<Local> = Local.timestamp(0, 0);
+/// let dt1: DateTime<Local> = Local::now();
+/// let dt2: DateTime<Local> = Local.timestamp_opt(0, 0).unwrap();
+/// assert!(dt1 >= dt2);
/// ```
#[derive(Copy, Clone, Debug)]
#[cfg_attr(feature = "rkyv", derive(Archive, Deserialize, Serialize))]
@@ -60,6 +89,7 @@ impl Local {
/// Returns a `Date` which corresponds to the current date.
#[deprecated(since = "0.4.23", note = "use `Local::now()` instead")]
#[allow(deprecated)]
+ #[must_use]
pub fn today() -> Date<Local> {
Local::now().date()
}
@@ -70,8 +100,9 @@ impl Local {
feature = "wasmbind",
not(any(target_os = "emscripten", target_os = "wasi"))
)))]
+ #[must_use]
pub fn now() -> DateTime<Local> {
- inner::now()
+ Utc::now().with_timezone(&Local)
}
/// Returns a `DateTime` which corresponds to the current date and time.
@@ -80,6 +111,7 @@ impl Local {
feature = "wasmbind",
not(any(target_os = "emscripten", target_os = "wasi"))
))]
+ #[must_use]
pub fn now() -> DateTime<Local> {
use super::Utc;
let now: DateTime<Utc> = super::Utc::now();
@@ -99,87 +131,24 @@ impl TimeZone for Local {
Local
}
- // they are easier to define in terms of the finished date and time unlike other offsets
#[allow(deprecated)]
fn offset_from_local_date(&self, local: &NaiveDate) -> LocalResult<FixedOffset> {
- self.from_local_date(local).map(|date| *date.offset())
+ // Get the offset at local midnight.
+ self.offset_from_local_datetime(&local.and_time(NaiveTime::MIN))
}
fn offset_from_local_datetime(&self, local: &NaiveDateTime) -> LocalResult<FixedOffset> {
- self.from_local_datetime(local).map(|datetime| *datetime.offset())
+ inner::offset_from_local_datetime(local)
}
#[allow(deprecated)]
fn offset_from_utc_date(&self, utc: &NaiveDate) -> FixedOffset {
- *self.from_utc_date(utc).offset()
+ // Get the offset at midnight.
+ self.offset_from_utc_datetime(&utc.and_time(NaiveTime::MIN))
}
fn offset_from_utc_datetime(&self, utc: &NaiveDateTime) -> FixedOffset {
- *self.from_utc_datetime(utc).offset()
- }
-
- // override them for avoiding redundant works
- #[allow(deprecated)]
- fn from_local_date(&self, local: &NaiveDate) -> LocalResult<Date<Local>> {
- // this sounds very strange, but required for keeping `TimeZone::ymd` sane.
- // in the other words, we use the offset at the local midnight
- // but keep the actual date unaltered (much like `FixedOffset`).
- let midnight = self.from_local_datetime(&local.and_hms_opt(0, 0, 0).unwrap());
- midnight.map(|datetime| Date::from_utc(*local, *datetime.offset()))
- }
-
- #[cfg(all(
- target_arch = "wasm32",
- feature = "wasmbind",
- not(any(target_os = "emscripten", target_os = "wasi"))
- ))]
- fn from_local_datetime(&self, local: &NaiveDateTime) -> LocalResult<DateTime<Local>> {
- let mut local = local.clone();
- // Get the offset from the js runtime
- let offset =
- FixedOffset::west_opt((js_sys::Date::new_0().get_timezone_offset() as i32) * 60)
- .unwrap();
- local -= crate::Duration::seconds(offset.local_minus_utc() as i64);
- LocalResult::Single(DateTime::from_utc(local, offset))
- }
-
- #[cfg(not(all(
- target_arch = "wasm32",
- feature = "wasmbind",
- not(any(target_os = "emscripten", target_os = "wasi"))
- )))]
- fn from_local_datetime(&self, local: &NaiveDateTime) -> LocalResult<DateTime<Local>> {
- inner::naive_to_local(local, true)
- }
-
- #[allow(deprecated)]
- fn from_utc_date(&self, utc: &NaiveDate) -> Date<Local> {
- let midnight = self.from_utc_datetime(&utc.and_hms_opt(0, 0, 0).unwrap());
- Date::from_utc(*utc, *midnight.offset())
- }
-
- #[cfg(all(
- target_arch = "wasm32",
- feature = "wasmbind",
- not(any(target_os = "emscripten", target_os = "wasi"))
- ))]
- fn from_utc_datetime(&self, utc: &NaiveDateTime) -> DateTime<Local> {
- // Get the offset from the js runtime
- let offset =
- FixedOffset::west_opt((js_sys::Date::new_0().get_timezone_offset() as i32) * 60)
- .unwrap();
- DateTime::from_utc(*utc, offset)
- }
-
- #[cfg(not(all(
- target_arch = "wasm32",
- feature = "wasmbind",
- not(any(target_os = "emscripten", target_os = "wasi"))
- )))]
- fn from_utc_datetime(&self, utc: &NaiveDateTime) -> DateTime<Local> {
- // this is OK to unwrap as getting local time from a UTC
- // timestamp is never ambiguous
- inner::naive_to_local(utc, false).unwrap()
+ inner::offset_from_utc_datetime(utc).unwrap()
}
}
@@ -243,18 +212,32 @@ mod tests {
// issue #123
let today = Utc::now().date_naive();
- let dt = today.and_hms_milli_opt(1, 2, 59, 1000).unwrap();
- let timestr = dt.time().to_string();
- // the OS API may or may not support the leap second,
- // but there are only two sensible options.
- assert!(timestr == "01:02:60" || timestr == "01:03:00", "unexpected timestr {:?}", timestr);
-
- let dt = today.and_hms_milli_opt(1, 2, 3, 1234).unwrap();
- let timestr = dt.time().to_string();
- assert!(
- timestr == "01:02:03.234" || timestr == "01:02:04.234",
- "unexpected timestr {:?}",
- timestr
- );
+ if let Some(dt) = today.and_hms_milli_opt(15, 2, 59, 1000) {
+ let timestr = dt.time().to_string();
+ // the OS API may or may not support the leap second,
+ // but there are only two sensible options.
+ assert!(
+ timestr == "15:02:60" || timestr == "15:03:00",
+ "unexpected timestr {:?}",
+ timestr
+ );
+ }
+
+ if let Some(dt) = today.and_hms_milli_opt(15, 2, 3, 1234) {
+ let timestr = dt.time().to_string();
+ assert!(
+ timestr == "15:02:03.234" || timestr == "15:02:04.234",
+ "unexpected timestr {:?}",
+ timestr
+ );
+ }
+ }
+
+ /// Test Issue #866
+ #[test]
+ fn test_issue_866() {
+ #[allow(deprecated)]
+ let local_20221106 = Local.ymd(2022, 11, 6);
+ let _dt_20221106 = local_20221106.and_hms_milli_opt(1, 2, 59, 1000).unwrap();
}
}
diff --git a/vendor/chrono/src/offset/local/stub.rs b/vendor/chrono/src/offset/local/stub.rs
deleted file mode 100644
index 9ececd3c2..000000000
--- a/vendor/chrono/src/offset/local/stub.rs
+++ /dev/null
@@ -1,236 +0,0 @@
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use std::time::{SystemTime, UNIX_EPOCH};
-
-use super::{FixedOffset, Local};
-use crate::{DateTime, Datelike, LocalResult, NaiveDate, NaiveDateTime, NaiveTime, Timelike};
-
-pub(super) fn now() -> DateTime<Local> {
- tm_to_datetime(Timespec::now().local())
-}
-
-/// Converts a local `NaiveDateTime` to the `time::Timespec`.
-#[cfg(not(all(
- target_arch = "wasm32",
- feature = "wasmbind",
- not(any(target_os = "emscripten", target_os = "wasi"))
-)))]
-pub(super) fn naive_to_local(d: &NaiveDateTime, local: bool) -> LocalResult<DateTime<Local>> {
- let tm = Tm {
- tm_sec: d.second() as i32,
- tm_min: d.minute() as i32,
- tm_hour: d.hour() as i32,
- tm_mday: d.day() as i32,
- tm_mon: d.month0() as i32, // yes, C is that strange...
- tm_year: d.year() - 1900, // this doesn't underflow, we know that d is `NaiveDateTime`.
- tm_wday: 0, // to_local ignores this
- tm_yday: 0, // and this
- tm_isdst: -1,
- // This seems pretty fake?
- tm_utcoff: if local { 1 } else { 0 },
- // do not set this, OS APIs are heavily inconsistent in terms of leap second handling
- tm_nsec: 0,
- };
-
- let spec = Timespec {
- sec: match local {
- false => utc_tm_to_time(&tm),
- true => local_tm_to_time(&tm),
- },
- nsec: tm.tm_nsec,
- };
-
- // Adjust for leap seconds
- let mut tm = spec.local();
- assert_eq!(tm.tm_nsec, 0);
- tm.tm_nsec = d.nanosecond() as i32;
-
- LocalResult::Single(tm_to_datetime(tm))
-}
-
-/// Converts a `time::Tm` struct into the timezone-aware `DateTime`.
-/// This assumes that `time` is working correctly, i.e. any error is fatal.
-#[cfg(not(all(
- target_arch = "wasm32",
- feature = "wasmbind",
- not(any(target_os = "emscripten", target_os = "wasi"))
-)))]
-fn tm_to_datetime(mut tm: Tm) -> DateTime<Local> {
- if tm.tm_sec >= 60 {
- tm.tm_nsec += (tm.tm_sec - 59) * 1_000_000_000;
- tm.tm_sec = 59;
- }
-
- let date = NaiveDate::from_yo(tm.tm_year + 1900, tm.tm_yday as u32 + 1);
- let time = NaiveTime::from_hms_nano(
- tm.tm_hour as u32,
- tm.tm_min as u32,
- tm.tm_sec as u32,
- tm.tm_nsec as u32,
- );
-
- let offset = FixedOffset::east_opt(tm.tm_utcoff).unwrap();
- DateTime::from_utc(date.and_time(time) - offset, offset)
-}
-
-/// A record specifying a time value in seconds and nanoseconds, where
-/// nanoseconds represent the offset from the given second.
-///
-/// For example a timespec of 1.2 seconds after the beginning of the epoch would
-/// be represented as {sec: 1, nsec: 200000000}.
-struct Timespec {
- sec: i64,
- nsec: i32,
-}
-
-impl Timespec {
- /// Constructs a timespec representing the current time in UTC.
- fn now() -> Timespec {
- let st =
- SystemTime::now().duration_since(UNIX_EPOCH).expect("system time before Unix epoch");
- Timespec { sec: st.as_secs() as i64, nsec: st.subsec_nanos() as i32 }
- }
-
- /// Converts this timespec into the system's local time.
- fn local(self) -> Tm {
- let mut tm = Tm {
- tm_sec: 0,
- tm_min: 0,
- tm_hour: 0,
- tm_mday: 0,
- tm_mon: 0,
- tm_year: 0,
- tm_wday: 0,
- tm_yday: 0,
- tm_isdst: 0,
- tm_utcoff: 0,
- tm_nsec: 0,
- };
- time_to_local_tm(self.sec, &mut tm);
- tm.tm_nsec = self.nsec;
- tm
- }
-}
-
-/// Holds a calendar date and time broken down into its components (year, month,
-/// day, and so on), also called a broken-down time value.
-// FIXME: use c_int instead of i32?
-#[repr(C)]
-pub(super) struct Tm {
- /// Seconds after the minute - [0, 60]
- tm_sec: i32,
-
- /// Minutes after the hour - [0, 59]
- tm_min: i32,
-
- /// Hours after midnight - [0, 23]
- tm_hour: i32,
-
- /// Day of the month - [1, 31]
- tm_mday: i32,
-
- /// Months since January - [0, 11]
- tm_mon: i32,
-
- /// Years since 1900
- tm_year: i32,
-
- /// Days since Sunday - [0, 6]. 0 = Sunday, 1 = Monday, ..., 6 = Saturday.
- tm_wday: i32,
-
- /// Days since January 1 - [0, 365]
- tm_yday: i32,
-
- /// Daylight Saving Time flag.
- ///
- /// This value is positive if Daylight Saving Time is in effect, zero if
- /// Daylight Saving Time is not in effect, and negative if this information
- /// is not available.
- tm_isdst: i32,
-
- /// Identifies the time zone that was used to compute this broken-down time
- /// value, including any adjustment for Daylight Saving Time. This is the
- /// number of seconds east of UTC. For example, for U.S. Pacific Daylight
- /// Time, the value is `-7*60*60 = -25200`.
- tm_utcoff: i32,
-
- /// Nanoseconds after the second - [0, 10<sup>9</sup> - 1]
- tm_nsec: i32,
-}
-
-fn time_to_tm(ts: i64, tm: &mut Tm) {
- let leapyear = |year| -> bool { year % 4 == 0 && (year % 100 != 0 || year % 400 == 0) };
-
- static YTAB: [[i64; 12]; 2] = [
- [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
- [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
- ];
-
- let mut year = 1970;
-
- let dayclock = ts % 86400;
- let mut dayno = ts / 86400;
-
- tm.tm_sec = (dayclock % 60) as i32;
- tm.tm_min = ((dayclock % 3600) / 60) as i32;
- tm.tm_hour = (dayclock / 3600) as i32;
- tm.tm_wday = ((dayno + 4) % 7) as i32;
- loop {
- let yearsize = if leapyear(year) { 366 } else { 365 };
- if dayno >= yearsize {
- dayno -= yearsize;
- year += 1;
- } else {
- break;
- }
- }
- tm.tm_year = (year - 1900) as i32;
- tm.tm_yday = dayno as i32;
- let mut mon = 0;
- while dayno >= YTAB[if leapyear(year) { 1 } else { 0 }][mon] {
- dayno -= YTAB[if leapyear(year) { 1 } else { 0 }][mon];
- mon += 1;
- }
- tm.tm_mon = mon as i32;
- tm.tm_mday = dayno as i32 + 1;
- tm.tm_isdst = 0;
-}
-
-fn tm_to_time(tm: &Tm) -> i64 {
- let mut y = tm.tm_year as i64 + 1900;
- let mut m = tm.tm_mon as i64 + 1;
- if m <= 2 {
- y -= 1;
- m += 12;
- }
- let d = tm.tm_mday as i64;
- let h = tm.tm_hour as i64;
- let mi = tm.tm_min as i64;
- let s = tm.tm_sec as i64;
- (365 * y + y / 4 - y / 100 + y / 400 + 3 * (m + 1) / 5 + 30 * m + d - 719561) * 86400
- + 3600 * h
- + 60 * mi
- + s
-}
-
-pub(super) fn time_to_local_tm(sec: i64, tm: &mut Tm) {
- // FIXME: Add timezone logic
- time_to_tm(sec, tm);
-}
-
-pub(super) fn utc_tm_to_time(tm: &Tm) -> i64 {
- tm_to_time(tm)
-}
-
-pub(super) fn local_tm_to_time(tm: &Tm) -> i64 {
- // FIXME: Add timezone logic
- tm_to_time(tm)
-}
diff --git a/vendor/chrono/src/offset/local/tz_info/mod.rs b/vendor/chrono/src/offset/local/tz_info/mod.rs
index bd2693b6b..780e15ace 100644
--- a/vendor/chrono/src/offset/local/tz_info/mod.rs
+++ b/vendor/chrono/src/offset/local/tz_info/mod.rs
@@ -100,21 +100,6 @@ impl From<Utf8Error> for Error {
}
}
-// MSRV: 1.38
-#[inline]
-fn rem_euclid(v: i64, rhs: i64) -> i64 {
- let r = v % rhs;
- if r < 0 {
- if rhs < 0 {
- r - rhs
- } else {
- r + rhs
- }
- } else {
- r
- }
-}
-
/// Number of hours in one day
const HOURS_PER_DAY: i64 = 24;
/// Number of seconds in one hour
diff --git a/vendor/chrono/src/offset/local/tz_info/parser.rs b/vendor/chrono/src/offset/local/tz_info/parser.rs
index 5652a0ea9..47cc0377e 100644
--- a/vendor/chrono/src/offset/local/tz_info/parser.rs
+++ b/vendor/chrono/src/offset/local/tz_info/parser.rs
@@ -7,7 +7,6 @@ use super::rule::TransitionRule;
use super::timezone::{LeapSecond, LocalTimeType, TimeZone, Transition};
use super::Error;
-#[allow(clippy::map_clone)] // MSRV: 1.36
pub(super) fn parse(bytes: &[u8]) -> Result<TimeZone, Error> {
let mut cursor = Cursor::new(bytes);
let state = State::new(&mut cursor, true)?;
@@ -66,8 +65,8 @@ pub(super) fn parse(bytes: &[u8]) -> Result<TimeZone, Error> {
leap_seconds.push(LeapSecond::new(unix_leap_time, correction));
}
- let std_walls_iter = state.std_walls.iter().map(|&i| i).chain(iter::repeat(0));
- let ut_locals_iter = state.ut_locals.iter().map(|&i| i).chain(iter::repeat(0));
+ let std_walls_iter = state.std_walls.iter().copied().chain(iter::repeat(0));
+ let ut_locals_iter = state.ut_locals.iter().copied().chain(iter::repeat(0));
if std_walls_iter.zip(ut_locals_iter).take(state.header.type_count).any(|pair| pair == (0, 1)) {
return Err(Error::InvalidTzFile(
"invalid couple of standard/wall and UT/local indicators",
@@ -238,7 +237,7 @@ impl<'a> Cursor<'a> {
}
/// Returns `true` if data is remaining
- pub(crate) fn is_empty(&self) -> bool {
+ pub(crate) const fn is_empty(&self) -> bool {
self.remaining.is_empty()
}
diff --git a/vendor/chrono/src/offset/local/tz_info/rule.rs b/vendor/chrono/src/offset/local/tz_info/rule.rs
index 7befddb5c..369e317a4 100644
--- a/vendor/chrono/src/offset/local/tz_info/rule.rs
+++ b/vendor/chrono/src/offset/local/tz_info/rule.rs
@@ -3,7 +3,7 @@ use std::cmp::Ordering;
use super::parser::Cursor;
use super::timezone::{LocalTimeType, SECONDS_PER_WEEK};
use super::{
- rem_euclid, Error, CUMUL_DAY_IN_MONTHS_NORMAL_YEAR, DAYS_PER_WEEK, DAY_IN_MONTHS_NORMAL_YEAR,
+ Error, CUMUL_DAY_IN_MONTHS_NORMAL_YEAR, DAYS_PER_WEEK, DAY_IN_MONTHS_NORMAL_YEAR,
SECONDS_PER_DAY,
};
@@ -127,7 +127,7 @@ pub(super) struct AlternateTime {
impl AlternateTime {
/// Construct a transition rule representing alternate local time types
- fn new(
+ const fn new(
std: LocalTimeType,
dst: LocalTimeType,
dst_start: RuleDay,
@@ -504,7 +504,7 @@ impl RuleDay {
}
/// Construct a transition rule day represented by a zero-based Julian day in `[0, 365]`, taking occasional Feb 29 into account
- fn julian_0(julian_day_0: u16) -> Result<Self, Error> {
+ const fn julian_0(julian_day_0: u16) -> Result<Self, Error> {
if julian_day_0 > 365 {
return Err(Error::TransitionRule("invalid rule day julian day"));
}
@@ -589,9 +589,9 @@ impl RuleDay {
}
let week_day_of_first_month_day =
- rem_euclid(4 + days_since_unix_epoch(year, month, 1), DAYS_PER_WEEK);
+ (4 + days_since_unix_epoch(year, month, 1)).rem_euclid(DAYS_PER_WEEK);
let first_week_day_occurence_in_month =
- 1 + rem_euclid(week_day as i64 - week_day_of_first_month_day, DAYS_PER_WEEK);
+ 1 + (week_day as i64 - week_day_of_first_month_day).rem_euclid(DAYS_PER_WEEK);
let mut month_day =
first_week_day_occurence_in_month + (week as i64 - 1) * DAYS_PER_WEEK;
@@ -737,7 +737,7 @@ const DAY_IN_MONTHS_LEAP_YEAR_FROM_MARCH: [i64; 12] =
/// * `year`: Year
/// * `month`: Month in `[1, 12]`
/// * `month_day`: Day of the month in `[1, 31]`
-pub(crate) fn days_since_unix_epoch(year: i32, month: usize, month_day: i64) -> i64 {
+pub(crate) const fn days_since_unix_epoch(year: i32, month: usize, month_day: i64) -> i64 {
let is_leap_year = is_leap_year(year);
let year = year as i64;
@@ -768,7 +768,7 @@ pub(crate) fn days_since_unix_epoch(year: i32, month: usize, month_day: i64) ->
}
/// Check if a year is a leap year
-pub(crate) fn is_leap_year(year: i32) -> bool {
+pub(crate) const fn is_leap_year(year: i32) -> bool {
year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)
}
@@ -777,7 +777,6 @@ mod tests {
use super::super::timezone::Transition;
use super::super::{Error, TimeZone};
use super::{AlternateTime, LocalTimeType, RuleDay, TransitionRule};
- use crate::matches;
#[test]
fn test_quoted() -> Result<(), Error> {
diff --git a/vendor/chrono/src/offset/local/tz_info/timezone.rs b/vendor/chrono/src/offset/local/tz_info/timezone.rs
index 8572825a8..33c89060c 100644
--- a/vendor/chrono/src/offset/local/tz_info/timezone.rs
+++ b/vendor/chrono/src/offset/local/tz_info/timezone.rs
@@ -43,6 +43,14 @@ impl TimeZone {
return Self::from_tz_data(&fs::read("/etc/localtime")?);
}
+ // attributes are not allowed on if blocks in Rust 1.38
+ #[cfg(target_os = "android")]
+ {
+ if let Ok(bytes) = android_tzdata::find_tz_data(tz_string) {
+ return Self::from_tz_data(&bytes);
+ }
+ }
+
let mut chars = tz_string.chars();
if chars.next() == Some(':') {
return Self::from_file(&mut find_tz_file(chars.as_str())?);
@@ -374,7 +382,7 @@ impl<'a> TimeZoneRef<'a> {
}
/// Convert Unix time to Unix leap time, from the list of leap seconds in a time zone
- fn unix_time_to_unix_leap_time(&self, unix_time: i64) -> Result<i64, Error> {
+ const fn unix_time_to_unix_leap_time(&self, unix_time: i64) -> Result<i64, Error> {
let mut unix_leap_time = unix_time;
let mut i = 0;
@@ -563,7 +571,7 @@ impl LocalTimeType {
}
/// Construct a local time type with the specified UTC offset in seconds
- pub(super) fn with_offset(ut_offset: i32) -> Result<Self, Error> {
+ pub(super) const fn with_offset(ut_offset: i32) -> Result<Self, Error> {
if ut_offset == i32::min_value() {
return Err(Error::LocalTimeType("invalid UTC offset"));
}
@@ -608,7 +616,7 @@ fn find_tz_file(path: impl AsRef<Path>) -> Result<File, Error> {
}
#[inline]
-fn saturating_abs(v: i32) -> i32 {
+const fn saturating_abs(v: i32) -> i32 {
if v.is_positive() {
v
} else if v == i32::min_value() {
@@ -620,8 +628,8 @@ fn saturating_abs(v: i32) -> i32 {
// Possible system timezone directories
#[cfg(unix)]
-const ZONE_INFO_DIRECTORIES: [&str; 3] =
- ["/usr/share/zoneinfo", "/share/zoneinfo", "/etc/zoneinfo"];
+const ZONE_INFO_DIRECTORIES: [&str; 4] =
+ ["/usr/share/zoneinfo", "/share/zoneinfo", "/etc/zoneinfo", "/usr/share/lib/zoneinfo"];
/// Number of seconds in one week
pub(crate) const SECONDS_PER_WEEK: i64 = SECONDS_PER_DAY * DAYS_PER_WEEK;
@@ -632,7 +640,6 @@ const SECONDS_PER_28_DAYS: i64 = SECONDS_PER_DAY * 28;
mod tests {
use super::super::Error;
use super::{LeapSecond, LocalTimeType, TimeZone, TimeZoneName, Transition, TransitionRule};
- use crate::matches;
#[test]
fn test_no_dst() -> Result<(), Error> {
diff --git a/vendor/chrono/src/offset/local/unix.rs b/vendor/chrono/src/offset/local/unix.rs
index 32aa31618..ce96a6e3b 100644
--- a/vendor/chrono/src/offset/local/unix.rs
+++ b/vendor/chrono/src/offset/local/unix.rs
@@ -11,15 +11,18 @@
use std::{cell::RefCell, collections::hash_map, env, fs, hash::Hasher, time::SystemTime};
use super::tz_info::TimeZone;
-use super::{DateTime, FixedOffset, Local, NaiveDateTime};
-use crate::{Datelike, LocalResult, Utc};
+use super::{FixedOffset, NaiveDateTime};
+use crate::{Datelike, LocalResult};
-pub(super) fn now() -> DateTime<Local> {
- let now = Utc::now().naive_utc();
- naive_to_local(&now, false).unwrap()
+pub(super) fn offset_from_utc_datetime(utc: &NaiveDateTime) -> LocalResult<FixedOffset> {
+ offset(utc, false)
}
-pub(super) fn naive_to_local(d: &NaiveDateTime, local: bool) -> LocalResult<DateTime<Local>> {
+pub(super) fn offset_from_local_datetime(local: &NaiveDateTime) -> LocalResult<FixedOffset> {
+ offset(local, true)
+}
+
+fn offset(d: &NaiveDateTime, local: bool) -> LocalResult<FixedOffset> {
TZ_INFO.with(|maybe_cache| {
maybe_cache.borrow_mut().get_or_insert_with(Cache::default).offset(*d, local)
})
@@ -68,19 +71,18 @@ struct Cache {
last_checked: SystemTime,
}
-#[cfg(target_os = "android")]
-const TZDB_LOCATION: &str = " /system/usr/share/zoneinfo";
-
#[cfg(target_os = "aix")]
const TZDB_LOCATION: &str = "/usr/share/lib/zoneinfo";
-#[allow(dead_code)] // keeps the cfg simpler
#[cfg(not(any(target_os = "android", target_os = "aix")))]
const TZDB_LOCATION: &str = "/usr/share/zoneinfo";
fn fallback_timezone() -> Option<TimeZone> {
let tz_name = iana_time_zone::get_timezone().ok()?;
+ #[cfg(not(target_os = "android"))]
let bytes = fs::read(format!("{}/{}", TZDB_LOCATION, tz_name)).ok()?;
+ #[cfg(target_os = "android")]
+ let bytes = android_tzdata::find_tz_data(&tz_name).ok()?;
TimeZone::from_tz_data(&bytes).ok()
}
@@ -88,7 +90,7 @@ impl Default for Cache {
fn default() -> Cache {
// default to UTC if no local timezone can be found
let env_tz = env::var("TZ").ok();
- let env_ref = env_tz.as_ref().map(|s| s.as_str());
+ let env_ref = env_tz.as_deref();
Cache {
last_checked: SystemTime::now(),
source: Source::new(env_ref),
@@ -102,7 +104,7 @@ fn current_zone(var: Option<&str>) -> TimeZone {
}
impl Cache {
- fn offset(&mut self, d: NaiveDateTime, local: bool) -> LocalResult<DateTime<Local>> {
+ fn offset(&mut self, d: NaiveDateTime, local: bool) -> LocalResult<FixedOffset> {
let now = SystemTime::now();
match now.duration_since(self.last_checked) {
@@ -114,7 +116,7 @@ impl Cache {
Ok(d) if d.as_secs() < 1 => (),
Ok(_) | Err(_) => {
let env_tz = env::var("TZ").ok();
- let env_ref = env_tz.as_ref().map(|s| s.as_str());
+ let env_ref = env_tz.as_deref();
let new_source = Source::new(env_ref);
let out_of_date = match (&self.source, &new_source) {
@@ -154,32 +156,16 @@ impl Cache {
.offset();
return match FixedOffset::east_opt(offset) {
- Some(offset) => LocalResult::Single(DateTime::from_utc(d, offset)),
+ Some(offset) => LocalResult::Single(offset),
None => LocalResult::None,
};
}
// we pass through the year as the year of a local point in time must either be valid in that locale, or
- // the entire time was skipped in which case we will return LocalResult::None anywa.
- match self
- .zone
+ // the entire time was skipped in which case we will return LocalResult::None anyway.
+ self.zone
.find_local_time_type_from_local(d.timestamp(), d.year())
.expect("unable to select local time type")
- {
- LocalResult::None => LocalResult::None,
- LocalResult::Ambiguous(early, late) => {
- let early_offset = FixedOffset::east_opt(early.offset()).unwrap();
- let late_offset = FixedOffset::east_opt(late.offset()).unwrap();
-
- LocalResult::Ambiguous(
- DateTime::from_utc(d - early_offset, early_offset),
- DateTime::from_utc(d - late_offset, late_offset),
- )
- }
- LocalResult::Single(tt) => {
- let offset = FixedOffset::east_opt(tt.offset()).unwrap();
- LocalResult::Single(DateTime::from_utc(d - offset, offset))
- }
- }
+ .map(|o| FixedOffset::east_opt(o.offset()).unwrap())
}
}
diff --git a/vendor/chrono/src/offset/local/windows.rs b/vendor/chrono/src/offset/local/windows.rs
index e6415015c..84585170c 100644
--- a/vendor/chrono/src/offset/local/windows.rs
+++ b/vendor/chrono/src/offset/local/windows.rs
@@ -8,271 +8,133 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::io;
-use std::mem;
-use std::time::{SystemTime, UNIX_EPOCH};
+use core::mem::MaybeUninit;
+use std::io::Error;
+use std::ptr;
+use std::result::Result;
-use winapi::shared::minwindef::*;
+use winapi::shared::minwindef::FILETIME;
use winapi::um::minwinbase::SYSTEMTIME;
-use winapi::um::timezoneapi::*;
+use winapi::um::timezoneapi::{
+ SystemTimeToFileTime, SystemTimeToTzSpecificLocalTime, TzSpecificLocalTimeToSystemTime,
+};
-use super::{FixedOffset, Local};
-use crate::{DateTime, Datelike, LocalResult, NaiveDate, NaiveDateTime, NaiveTime, Timelike};
+use super::FixedOffset;
+use crate::{Datelike, LocalResult, NaiveDateTime, Timelike};
-pub(super) fn now() -> DateTime<Local> {
- tm_to_datetime(Timespec::now().local())
-}
-
-/// Converts a local `NaiveDateTime` to the `time::Timespec`.
-pub(super) fn naive_to_local(d: &NaiveDateTime, local: bool) -> LocalResult<DateTime<Local>> {
- let tm = Tm {
- tm_sec: d.second() as i32,
- tm_min: d.minute() as i32,
- tm_hour: d.hour() as i32,
- tm_mday: d.day() as i32,
- tm_mon: d.month0() as i32, // yes, C is that strange...
- tm_year: d.year() - 1900, // this doesn't underflow, we know that d is `NaiveDateTime`.
- tm_wday: 0, // to_local ignores this
- tm_yday: 0, // and this
- tm_isdst: -1,
- // This seems pretty fake?
- tm_utcoff: if local { 1 } else { 0 },
- // do not set this, OS APIs are heavily inconsistent in terms of leap second handling
- tm_nsec: 0,
- };
-
- let spec = Timespec {
- sec: match local {
- false => utc_tm_to_time(&tm),
- true => local_tm_to_time(&tm),
- },
- nsec: tm.tm_nsec,
- };
-
- // Adjust for leap seconds
- let mut tm = spec.local();
- assert_eq!(tm.tm_nsec, 0);
- tm.tm_nsec = d.nanosecond() as i32;
-
- // #TODO - there should be ambiguous cases, investigate?
- LocalResult::Single(tm_to_datetime(tm))
-}
-
-/// Converts a `time::Tm` struct into the timezone-aware `DateTime`.
-fn tm_to_datetime(mut tm: Tm) -> DateTime<Local> {
- if tm.tm_sec >= 60 {
- tm.tm_nsec += (tm.tm_sec - 59) * 1_000_000_000;
- tm.tm_sec = 59;
- }
-
- let date = NaiveDate::from_ymd_opt(tm.tm_year + 1900, tm.tm_mon as u32 + 1, tm.tm_mday as u32)
- .unwrap();
- let time = NaiveTime::from_hms_nano(
- tm.tm_hour as u32,
- tm.tm_min as u32,
- tm.tm_sec as u32,
- tm.tm_nsec as u32,
- );
-
- let offset = FixedOffset::east_opt(tm.tm_utcoff).unwrap();
- DateTime::from_utc(date.and_time(time) - offset, offset)
-}
-
-/// A record specifying a time value in seconds and nanoseconds, where
-/// nanoseconds represent the offset from the given second.
+/// This macro calls a Windows API FFI and checks whether the function errored with the provided error_id. If an error returns,
+/// the macro will return an `Error::last_os_error()`.
///
-/// For example a timespec of 1.2 seconds after the beginning of the epoch would
-/// be represented as {sec: 1, nsec: 200000000}.
-struct Timespec {
- sec: i64,
- nsec: i32,
-}
-
-impl Timespec {
- /// Constructs a timespec representing the current time in UTC.
- fn now() -> Timespec {
- let st =
- SystemTime::now().duration_since(UNIX_EPOCH).expect("system time before Unix epoch");
- Timespec { sec: st.as_secs() as i64, nsec: st.subsec_nanos() as i32 }
- }
-
- /// Converts this timespec into the system's local time.
- fn local(self) -> Tm {
- let mut tm = Tm {
- tm_sec: 0,
- tm_min: 0,
- tm_hour: 0,
- tm_mday: 0,
- tm_mon: 0,
- tm_year: 0,
- tm_wday: 0,
- tm_yday: 0,
- tm_isdst: 0,
- tm_utcoff: 0,
- tm_nsec: 0,
- };
- time_to_local_tm(self.sec, &mut tm);
- tm.tm_nsec = self.nsec;
- tm
+/// # Safety
+///
+/// The provided error ID must align with the provided Windows API, providing the wrong ID could lead to UB.
+macro_rules! windows_sys_call {
+ ($name:ident($($arg:expr),*), $error_id:expr) => {
+ if $name($($arg),*) == $error_id {
+ return Err(Error::last_os_error());
+ }
}
}
-/// Holds a calendar date and time broken down into its components (year, month,
-/// day, and so on), also called a broken-down time value.
-// FIXME: use c_int instead of i32?
-#[repr(C)]
-struct Tm {
- /// Seconds after the minute - [0, 60]
- tm_sec: i32,
-
- /// Minutes after the hour - [0, 59]
- tm_min: i32,
-
- /// Hours after midnight - [0, 23]
- tm_hour: i32,
-
- /// Day of the month - [1, 31]
- tm_mday: i32,
-
- /// Months since January - [0, 11]
- tm_mon: i32,
-
- /// Years since 1900
- tm_year: i32,
-
- /// Days since Sunday - [0, 6]. 0 = Sunday, 1 = Monday, ..., 6 = Saturday.
- tm_wday: i32,
-
- /// Days since January 1 - [0, 365]
- tm_yday: i32,
-
- /// Daylight Saving Time flag.
- ///
- /// This value is positive if Daylight Saving Time is in effect, zero if
- /// Daylight Saving Time is not in effect, and negative if this information
- /// is not available.
- tm_isdst: i32,
-
- /// Identifies the time zone that was used to compute this broken-down time
- /// value, including any adjustment for Daylight Saving Time. This is the
- /// number of seconds east of UTC. For example, for U.S. Pacific Daylight
- /// Time, the value is `-7*60*60 = -25200`.
- tm_utcoff: i32,
-
- /// Nanoseconds after the second - [0, 10<sup>9</sup> - 1]
- tm_nsec: i32,
-}
-
const HECTONANOSECS_IN_SEC: i64 = 10_000_000;
const HECTONANOSEC_TO_UNIX_EPOCH: i64 = 11_644_473_600 * HECTONANOSECS_IN_SEC;
-fn time_to_file_time(sec: i64) -> FILETIME {
- let t = ((sec * HECTONANOSECS_IN_SEC) + HECTONANOSEC_TO_UNIX_EPOCH) as u64;
- FILETIME { dwLowDateTime: t as DWORD, dwHighDateTime: (t >> 32) as DWORD }
-}
-
-fn file_time_as_u64(ft: &FILETIME) -> u64 {
- ((ft.dwHighDateTime as u64) << 32) | (ft.dwLowDateTime as u64)
+pub(super) fn offset_from_utc_datetime(utc: &NaiveDateTime) -> LocalResult<FixedOffset> {
+ offset(utc, false)
}
-fn file_time_to_unix_seconds(ft: &FILETIME) -> i64 {
- let t = file_time_as_u64(ft) as i64;
- ((t - HECTONANOSEC_TO_UNIX_EPOCH) / HECTONANOSECS_IN_SEC) as i64
+pub(super) fn offset_from_local_datetime(local: &NaiveDateTime) -> LocalResult<FixedOffset> {
+ offset(local, true)
}
-fn system_time_to_file_time(sys: &SYSTEMTIME) -> FILETIME {
- unsafe {
- let mut ft = mem::zeroed();
- SystemTimeToFileTime(sys, &mut ft);
- ft
- }
-}
-
-fn tm_to_system_time(tm: &Tm) -> SYSTEMTIME {
- let mut sys: SYSTEMTIME = unsafe { mem::zeroed() };
- sys.wSecond = tm.tm_sec as WORD;
- sys.wMinute = tm.tm_min as WORD;
- sys.wHour = tm.tm_hour as WORD;
- sys.wDay = tm.tm_mday as WORD;
- sys.wDayOfWeek = tm.tm_wday as WORD;
- sys.wMonth = (tm.tm_mon + 1) as WORD;
- sys.wYear = (tm.tm_year + 1900) as WORD;
- sys
-}
-
-fn system_time_to_tm(sys: &SYSTEMTIME, tm: &mut Tm) {
- tm.tm_sec = sys.wSecond as i32;
- tm.tm_min = sys.wMinute as i32;
- tm.tm_hour = sys.wHour as i32;
- tm.tm_mday = sys.wDay as i32;
- tm.tm_wday = sys.wDayOfWeek as i32;
- tm.tm_mon = (sys.wMonth - 1) as i32;
- tm.tm_year = (sys.wYear - 1900) as i32;
- tm.tm_yday = yday(tm.tm_year, tm.tm_mon + 1, tm.tm_mday);
-
- fn yday(year: i32, month: i32, day: i32) -> i32 {
- let leap = if month > 2 {
- if year % 4 == 0 {
- 1
- } else {
- 2
- }
- } else {
- 0
- };
- let july = if month > 7 { 1 } else { 0 };
+/// Converts a local `NaiveDateTime` to the `time::Timespec`.
+pub(super) fn offset(d: &NaiveDateTime, local: bool) -> LocalResult<FixedOffset> {
+ let naive_sys_time = system_time_from_naive_date_time(d);
- (month - 1) * 30 + month / 2 + (day - 1) - leap + july
- }
-}
+ let local_sys_time = match local {
+ false => from_utc_time(naive_sys_time),
+ true => from_local_time(naive_sys_time),
+ };
-macro_rules! call {
- ($name:ident($($arg:expr),*)) => {
- if $name($($arg),*) == 0 {
- panic!(concat!(stringify!($name), " failed with: {}"),
- io::Error::last_os_error());
- }
+ if let Ok(offset) = local_sys_time {
+ return LocalResult::Single(offset);
}
-}
-
-fn time_to_local_tm(sec: i64, tm: &mut Tm) {
- let ft = time_to_file_time(sec);
- unsafe {
- let mut utc = mem::zeroed();
- let mut local = mem::zeroed();
- call!(FileTimeToSystemTime(&ft, &mut utc));
- call!(SystemTimeToTzSpecificLocalTime(0 as *const _, &mut utc, &mut local));
- system_time_to_tm(&local, tm);
-
- let local = system_time_to_file_time(&local);
- let local_sec = file_time_to_unix_seconds(&local);
-
- let mut tz = mem::zeroed();
- GetTimeZoneInformation(&mut tz);
-
- // SystemTimeToTzSpecificLocalTime already applied the biases so
- // check if it non standard
- tm.tm_utcoff = (local_sec - sec) as i32;
- tm.tm_isdst = if tm.tm_utcoff == -60 * (tz.Bias + tz.StandardBias) { 0 } else { 1 };
+ LocalResult::None
+}
+
+fn from_utc_time(utc_time: SYSTEMTIME) -> Result<FixedOffset, Error> {
+ let local_time = utc_to_local_time(&utc_time)?;
+ let utc_secs = system_time_as_unix_seconds(&utc_time)?;
+ let local_secs = system_time_as_unix_seconds(&local_time)?;
+ let offset = (local_secs - utc_secs) as i32;
+ Ok(FixedOffset::east_opt(offset).unwrap())
+}
+
+fn from_local_time(local_time: SYSTEMTIME) -> Result<FixedOffset, Error> {
+ let utc_time = local_to_utc_time(&local_time)?;
+ let utc_secs = system_time_as_unix_seconds(&utc_time)?;
+ let local_secs = system_time_as_unix_seconds(&local_time)?;
+ let offset = (local_secs - utc_secs) as i32;
+ Ok(FixedOffset::east_opt(offset).unwrap())
+}
+
+fn system_time_from_naive_date_time(dt: &NaiveDateTime) -> SYSTEMTIME {
+ SYSTEMTIME {
+ // Valid values: 1601-30827
+ wYear: dt.year() as u16,
+ // Valid values:1-12
+ wMonth: dt.month() as u16,
+ // Valid values: 0-6, starting Sunday.
+ // NOTE: enum returns 1-7, starting Monday, so we are
+ // off here, but this is not currently used in local.
+ wDayOfWeek: dt.weekday() as u16,
+ // Valid values: 1-31
+ wDay: dt.day() as u16,
+ // Valid values: 0-23
+ wHour: dt.hour() as u16,
+ // Valid values: 0-59
+ wMinute: dt.minute() as u16,
+ // Valid values: 0-59
+ wSecond: dt.second() as u16,
+ // Valid values: 0-999
+ wMilliseconds: 0,
}
}
-fn utc_tm_to_time(tm: &Tm) -> i64 {
+pub(crate) fn local_to_utc_time(local: &SYSTEMTIME) -> Result<SYSTEMTIME, Error> {
+ let mut sys_time = MaybeUninit::<SYSTEMTIME>::uninit();
unsafe {
- let mut ft = mem::zeroed();
- let sys_time = tm_to_system_time(tm);
- call!(SystemTimeToFileTime(&sys_time, &mut ft));
- file_time_to_unix_seconds(&ft)
- }
+ windows_sys_call!(
+ TzSpecificLocalTimeToSystemTime(ptr::null(), local, sys_time.as_mut_ptr()),
+ 0
+ )
+ };
+ // SAFETY: TzSpecificLocalTimeToSystemTime must have succeeded at this point, so we can
+ // assume the value is initialized.
+ Ok(unsafe { sys_time.assume_init() })
}
-fn local_tm_to_time(tm: &Tm) -> i64 {
+pub(crate) fn utc_to_local_time(utc_time: &SYSTEMTIME) -> Result<SYSTEMTIME, Error> {
+ let mut local = MaybeUninit::<SYSTEMTIME>::uninit();
unsafe {
- let mut ft = mem::zeroed();
- let mut utc = mem::zeroed();
- let mut sys_time = tm_to_system_time(tm);
- call!(TzSpecificLocalTimeToSystemTime(0 as *mut _, &mut sys_time, &mut utc));
- call!(SystemTimeToFileTime(&utc, &mut ft));
- file_time_to_unix_seconds(&ft)
- }
+ windows_sys_call!(
+ SystemTimeToTzSpecificLocalTime(ptr::null(), utc_time, local.as_mut_ptr()),
+ 0
+ )
+ };
+ // SAFETY: SystemTimeToTzSpecificLocalTime must have succeeded at this point, so we can
+ // assume the value is initialized.
+ Ok(unsafe { local.assume_init() })
+}
+
+/// Returns a i64 value representing the unix seconds conversion of the current `WinSystemTime`.
+pub(crate) fn system_time_as_unix_seconds(st: &SYSTEMTIME) -> Result<i64, Error> {
+ let mut init = MaybeUninit::<FILETIME>::uninit();
+ unsafe { windows_sys_call!(SystemTimeToFileTime(st, init.as_mut_ptr()), 0) }
+ // SystemTimeToFileTime must have succeeded at this point, so we can assum the value is
+ // initalized.
+ let filetime = unsafe { init.assume_init() };
+ let bit_shift = ((filetime.dwHighDateTime as u64) << 32) | (filetime.dwLowDateTime as u64);
+ let unix_secs = (bit_shift as i64 - HECTONANOSEC_TO_UNIX_EPOCH) / HECTONANOSECS_IN_SEC;
+ Ok(unix_secs)
}
diff --git a/vendor/chrono/src/offset/mod.rs b/vendor/chrono/src/offset/mod.rs
index 09d0714e9..ee1fe7e23 100644
--- a/vendor/chrono/src/offset/mod.rs
+++ b/vendor/chrono/src/offset/mod.rs
@@ -52,6 +52,7 @@ pub enum LocalResult<T> {
impl<T> LocalResult<T> {
/// Returns `Some` only when the conversion result is unique, or `None` otherwise.
+ #[must_use]
pub fn single(self) -> Option<T> {
match self {
LocalResult::Single(t) => Some(t),
@@ -60,6 +61,7 @@ impl<T> LocalResult<T> {
}
/// Returns `Some` for the earliest possible conversion result, or `None` if none.
+ #[must_use]
pub fn earliest(self) -> Option<T> {
match self {
LocalResult::Single(t) | LocalResult::Ambiguous(t, _) => Some(t),
@@ -68,6 +70,7 @@ impl<T> LocalResult<T> {
}
/// Returns `Some` for the latest possible conversion result, or `None` if none.
+ #[must_use]
pub fn latest(self) -> Option<T> {
match self {
LocalResult::Single(t) | LocalResult::Ambiguous(_, t) => Some(t),
@@ -76,6 +79,7 @@ impl<T> LocalResult<T> {
}
/// Maps a `LocalResult<T>` into `LocalResult<U>` with given function.
+ #[must_use]
pub fn map<U, F: FnMut(T) -> U>(self, mut f: F) -> LocalResult<U> {
match self {
LocalResult::None => LocalResult::None,
@@ -92,6 +96,7 @@ impl<Tz: TimeZone> LocalResult<Date<Tz>> {
///
/// Propagates any error. Ambiguous result would be discarded.
#[inline]
+ #[must_use]
pub fn and_time(self, time: NaiveTime) -> LocalResult<DateTime<Tz>> {
match self {
LocalResult::Single(d) => {
@@ -106,6 +111,7 @@ impl<Tz: TimeZone> LocalResult<Date<Tz>> {
///
/// Propagates any error. Ambiguous result would be discarded.
#[inline]
+ #[must_use]
pub fn and_hms_opt(self, hour: u32, min: u32, sec: u32) -> LocalResult<DateTime<Tz>> {
match self {
LocalResult::Single(d) => {
@@ -121,6 +127,7 @@ impl<Tz: TimeZone> LocalResult<Date<Tz>> {
///
/// Propagates any error. Ambiguous result would be discarded.
#[inline]
+ #[must_use]
pub fn and_hms_milli_opt(
self,
hour: u32,
@@ -142,6 +149,7 @@ impl<Tz: TimeZone> LocalResult<Date<Tz>> {
///
/// Propagates any error. Ambiguous result would be discarded.
#[inline]
+ #[must_use]
pub fn and_hms_micro_opt(
self,
hour: u32,
@@ -163,6 +171,7 @@ impl<Tz: TimeZone> LocalResult<Date<Tz>> {
///
/// Propagates any error. Ambiguous result would be discarded.
#[inline]
+ #[must_use]
pub fn and_hms_nano_opt(
self,
hour: u32,
@@ -181,6 +190,8 @@ impl<Tz: TimeZone> LocalResult<Date<Tz>> {
impl<T: fmt::Debug> LocalResult<T> {
/// Returns the single unique conversion result, or panics accordingly.
+ #[must_use]
+ #[track_caller]
pub fn unwrap(self) -> T {
match self {
LocalResult::None => panic!("No such local time"),
diff --git a/vendor/chrono/src/offset/utc.rs b/vendor/chrono/src/offset/utc.rs
index cfed754b2..dbcb8eecb 100644
--- a/vendor/chrono/src/offset/utc.rs
+++ b/vendor/chrono/src/offset/utc.rs
@@ -35,9 +35,9 @@ use crate::{Date, DateTime};
/// ```
/// use chrono::{DateTime, TimeZone, NaiveDateTime, Utc};
///
-/// let dt = DateTime::<Utc>::from_utc(NaiveDateTime::from_timestamp(61, 0), Utc);
+/// let dt = DateTime::<Utc>::from_utc(NaiveDateTime::from_timestamp_opt(61, 0).unwrap(), Utc);
///
-/// assert_eq!(Utc.timestamp(61, 0), dt);
+/// assert_eq!(Utc.timestamp_opt(61, 0).unwrap(), dt);
/// assert_eq!(Utc.with_ymd_and_hms(1970, 1, 1, 0, 1, 1).unwrap(), dt);
/// ```
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
@@ -54,6 +54,7 @@ impl Utc {
note = "use `Utc::now()` instead, potentially with `.date_naive()`"
)]
#[allow(deprecated)]
+ #[must_use]
pub fn today() -> Date<Utc> {
Utc::now().date()
}
@@ -64,6 +65,7 @@ impl Utc {
feature = "wasmbind",
not(any(target_os = "emscripten", target_os = "wasi"))
)))]
+ #[must_use]
pub fn now() -> DateTime<Utc> {
let now =
SystemTime::now().duration_since(UNIX_EPOCH).expect("system time before Unix epoch");
@@ -78,6 +80,7 @@ impl Utc {
feature = "wasmbind",
not(any(target_os = "emscripten", target_os = "wasi"))
))]
+ #[must_use]
pub fn now() -> DateTime<Utc> {
let now = js_sys::Date::new_0();
DateTime::<Utc>::from(now)
diff --git a/vendor/chrono/src/oldtime.rs b/vendor/chrono/src/oldtime.rs
index 8e2b3d2c0..e27be7db6 100644
--- a/vendor/chrono/src/oldtime.rs
+++ b/vendor/chrono/src/oldtime.rs
@@ -74,6 +74,7 @@ impl Duration {
/// Equivalent to `Duration::seconds(weeks * 7 * 24 * 60 * 60)` with overflow checks.
/// Panics when the duration is out of bounds.
#[inline]
+ #[must_use]
pub fn weeks(weeks: i64) -> Duration {
let secs = weeks.checked_mul(SECS_PER_WEEK).expect("Duration::weeks out of bounds");
Duration::seconds(secs)
@@ -83,6 +84,7 @@ impl Duration {
/// Equivalent to `Duration::seconds(days * 24 * 60 * 60)` with overflow checks.
/// Panics when the duration is out of bounds.
#[inline]
+ #[must_use]
pub fn days(days: i64) -> Duration {
let secs = days.checked_mul(SECS_PER_DAY).expect("Duration::days out of bounds");
Duration::seconds(secs)
@@ -92,6 +94,7 @@ impl Duration {
/// Equivalent to `Duration::seconds(hours * 60 * 60)` with overflow checks.
/// Panics when the duration is out of bounds.
#[inline]
+ #[must_use]
pub fn hours(hours: i64) -> Duration {
let secs = hours.checked_mul(SECS_PER_HOUR).expect("Duration::hours ouf of bounds");
Duration::seconds(secs)
@@ -101,6 +104,7 @@ impl Duration {
/// Equivalent to `Duration::seconds(minutes * 60)` with overflow checks.
/// Panics when the duration is out of bounds.
#[inline]
+ #[must_use]
pub fn minutes(minutes: i64) -> Duration {
let secs = minutes.checked_mul(SECS_PER_MINUTE).expect("Duration::minutes out of bounds");
Duration::seconds(secs)
@@ -110,6 +114,7 @@ impl Duration {
/// Panics when the duration is more than `i64::MAX` seconds
/// or less than `i64::MIN` seconds.
#[inline]
+ #[must_use]
pub fn seconds(seconds: i64) -> Duration {
let d = Duration { secs: seconds, nanos: 0 };
if d < MIN || d > MAX {
@@ -211,6 +216,7 @@ impl Duration {
}
/// Add two durations, returning `None` if overflow occurred.
+ #[must_use]
pub fn checked_add(&self, rhs: &Duration) -> Option<Duration> {
let mut secs = try_opt!(self.secs.checked_add(rhs.secs));
let mut nanos = self.nanos + rhs.nanos;
@@ -229,6 +235,7 @@ impl Duration {
}
/// Subtract two durations, returning `None` if overflow occurred.
+ #[must_use]
pub fn checked_sub(&self, rhs: &Duration) -> Option<Duration> {
let mut secs = try_opt!(self.secs.checked_sub(rhs.secs));
let mut nanos = self.nanos - rhs.nanos;
@@ -455,31 +462,9 @@ impl Error for OutOfRangeError {
}
}
-// Copied from libnum
#[inline]
const fn div_mod_floor_64(this: i64, other: i64) -> (i64, i64) {
- (div_floor_64(this, other), mod_floor_64(this, other))
-}
-
-#[inline]
-const fn div_floor_64(this: i64, other: i64) -> i64 {
- match div_rem_64(this, other) {
- (d, r) if (r > 0 && other < 0) || (r < 0 && other > 0) => d - 1,
- (d, _) => d,
- }
-}
-
-#[inline]
-const fn mod_floor_64(this: i64, other: i64) -> i64 {
- match this % other {
- r if (r > 0 && other < 0) || (r < 0 && other > 0) => r + other,
- r => r,
- }
-}
-
-#[inline]
-const fn div_rem_64(this: i64, other: i64) -> (i64, i64) {
- (this / other, this % other)
+ (this.div_euclid(other), this.rem_euclid(other))
}
#[cfg(feature = "arbitrary")]
diff --git a/vendor/chrono/src/round.rs b/vendor/chrono/src/round.rs
index b95f24570..f43ab595c 100644
--- a/vendor/chrono/src/round.rs
+++ b/vendor/chrono/src/round.rs
@@ -24,7 +24,7 @@ pub trait SubsecRound {
///
/// # Example
/// ``` rust
- /// # use chrono::{DateTime, SubsecRound, Timelike, TimeZone, Utc, NaiveDate};
+ /// # use chrono::{SubsecRound, Timelike, Utc, NaiveDate};
/// let dt = NaiveDate::from_ymd_opt(2018, 1, 11).unwrap().and_hms_milli_opt(12, 0, 0, 154).unwrap().and_local_timezone(Utc).unwrap();
/// assert_eq!(dt.round_subsecs(2).nanosecond(), 150_000_000);
/// assert_eq!(dt.round_subsecs(1).nanosecond(), 200_000_000);
@@ -36,7 +36,7 @@ pub trait SubsecRound {
///
/// # Example
/// ``` rust
- /// # use chrono::{DateTime, SubsecRound, Timelike, TimeZone, Utc, NaiveDate};
+ /// # use chrono::{SubsecRound, Timelike, Utc, NaiveDate};
/// let dt = NaiveDate::from_ymd_opt(2018, 1, 11).unwrap().and_hms_milli_opt(12, 0, 0, 154).unwrap().and_local_timezone(Utc).unwrap();
/// assert_eq!(dt.trunc_subsecs(2).nanosecond(), 150_000_000);
/// assert_eq!(dt.trunc_subsecs(1).nanosecond(), 100_000_000);
@@ -75,7 +75,7 @@ where
}
// Return the maximum span in nanoseconds for the target number of digits.
-fn span_for_digits(digits: u16) -> u32 {
+const fn span_for_digits(digits: u16) -> u32 {
// fast lookup form of: 10^(9-min(9,digits))
match digits {
0 => 1_000_000_000,
@@ -111,7 +111,7 @@ pub trait DurationRound: Sized {
///
/// # Example
/// ``` rust
- /// # use chrono::{DateTime, DurationRound, Duration, TimeZone, Utc, NaiveDate};
+ /// # use chrono::{DurationRound, Duration, Utc, NaiveDate};
/// let dt = NaiveDate::from_ymd_opt(2018, 1, 11).unwrap().and_hms_milli_opt(12, 0, 0, 154).unwrap().and_local_timezone(Utc).unwrap();
/// assert_eq!(
/// dt.duration_round(Duration::milliseconds(10)).unwrap().to_string(),
@@ -128,7 +128,7 @@ pub trait DurationRound: Sized {
///
/// # Example
/// ``` rust
- /// # use chrono::{DateTime, DurationRound, Duration, TimeZone, Utc, NaiveDate};
+ /// # use chrono::{DurationRound, Duration, Utc, NaiveDate};
/// let dt = NaiveDate::from_ymd_opt(2018, 1, 11).unwrap().and_hms_milli_opt(12, 0, 0, 154).unwrap().and_local_timezone(Utc).unwrap();
/// assert_eq!(
/// dt.duration_trunc(Duration::milliseconds(10)).unwrap().to_string(),
@@ -178,6 +178,9 @@ where
T: Timelike + Add<Duration, Output = T> + Sub<Duration, Output = T>,
{
if let Some(span) = duration.num_nanoseconds() {
+ if span < 0 {
+ return Err(RoundingError::DurationExceedsLimit);
+ }
if naive.timestamp().abs() > MAX_SECONDS_TIMESTAMP_FOR_NANOS {
return Err(RoundingError::TimestampExceedsLimit);
}
@@ -217,6 +220,9 @@ where
T: Timelike + Add<Duration, Output = T> + Sub<Duration, Output = T>,
{
if let Some(span) = duration.num_nanoseconds() {
+ if span < 0 {
+ return Err(RoundingError::DurationExceedsLimit);
+ }
if naive.timestamp().abs() > MAX_SECONDS_TIMESTAMP_FOR_NANOS {
return Err(RoundingError::TimestampExceedsLimit);
}
@@ -243,7 +249,7 @@ pub enum RoundingError {
/// Error when the Duration exceeds the Duration from or until the Unix epoch.
///
/// ``` rust
- /// # use chrono::{DateTime, DurationRound, Duration, RoundingError, TimeZone, Utc};
+ /// # use chrono::{DurationRound, Duration, RoundingError, TimeZone, Utc};
/// let dt = Utc.with_ymd_and_hms(1970, 12, 12, 0, 0, 0).unwrap();
///
/// assert_eq!(
@@ -256,7 +262,7 @@ pub enum RoundingError {
/// Error when `Duration.num_nanoseconds` exceeds the limit.
///
/// ``` rust
- /// # use chrono::{DateTime, DurationRound, Duration, RoundingError, TimeZone, Utc, NaiveDate};
+ /// # use chrono::{DurationRound, Duration, RoundingError, Utc, NaiveDate};
/// let dt = NaiveDate::from_ymd_opt(2260, 12, 31).unwrap().and_hms_nano_opt(23, 59, 59, 1_75_500_000).unwrap().and_local_timezone(Utc).unwrap();
///
/// assert_eq!(
@@ -269,7 +275,7 @@ pub enum RoundingError {
/// Error when `DateTime.timestamp_nanos` exceeds the limit.
///
/// ``` rust
- /// # use chrono::{DateTime, DurationRound, Duration, RoundingError, TimeZone, Utc};
+ /// # use chrono::{DurationRound, Duration, RoundingError, TimeZone, Utc};
/// let dt = Utc.with_ymd_and_hms(2300, 12, 12, 0, 0, 0).unwrap();
///
/// assert_eq!(dt.duration_round(Duration::days(1)), Err(RoundingError::TimestampExceedsLimit),);
@@ -304,10 +310,10 @@ impl std::error::Error for RoundingError {
#[cfg(test)]
mod tests {
- use super::{Duration, DurationRound, SubsecRound};
+ use super::{Duration, DurationRound, RoundingError, SubsecRound};
use crate::offset::{FixedOffset, TimeZone, Utc};
- use crate::NaiveDate;
use crate::Timelike;
+ use crate::{NaiveDate, NaiveDateTime};
#[test]
fn test_round_subsecs() {
@@ -760,4 +766,19 @@ mod tests {
"1969-12-12 12:10:00 UTC"
);
}
+
+ #[test]
+ fn issue1010() {
+ let dt = NaiveDateTime::from_timestamp_opt(-4227854320, 1678774288).unwrap();
+ let span = Duration::microseconds(-7019067213869040);
+ assert_eq!(dt.duration_trunc(span), Err(RoundingError::DurationExceedsLimit));
+
+ let dt = NaiveDateTime::from_timestamp_opt(320041586, 1920103021).unwrap();
+ let span = Duration::nanoseconds(-8923838508697114584);
+ assert_eq!(dt.duration_round(span), Err(RoundingError::DurationExceedsLimit));
+
+ let dt = NaiveDateTime::from_timestamp_opt(-2621440, 0).unwrap();
+ let span = Duration::nanoseconds(-9223372036854771421);
+ assert_eq!(dt.duration_round(span), Err(RoundingError::DurationExceedsLimit));
+ }
}
diff --git a/vendor/chrono/src/traits.rs b/vendor/chrono/src/traits.rs
index 1b6af6926..a6199dc6d 100644
--- a/vendor/chrono/src/traits.rs
+++ b/vendor/chrono/src/traits.rs
@@ -219,9 +219,7 @@ mod tests {
date.ordinal() as i32 + 365 * diff(1) + diff(4) - diff(100) + diff(400)
}
- use num_iter::range_inclusive;
-
- for year in range_inclusive(NaiveDate::MIN.year(), NaiveDate::MAX.year()) {
+ for year in NaiveDate::MIN.year()..=NaiveDate::MAX.year() {
let jan1_year = NaiveDate::from_ymd_opt(year, 1, 1).unwrap();
assert_eq!(
jan1_year.num_days_from_ce(),
diff --git a/vendor/chrono/src/weekday.rs b/vendor/chrono/src/weekday.rs
index 72e384673..e2973cf79 100644
--- a/vendor/chrono/src/weekday.rs
+++ b/vendor/chrono/src/weekday.rs
@@ -3,11 +3,32 @@ use core::fmt;
#[cfg(feature = "rkyv")]
use rkyv::{Archive, Deserialize, Serialize};
+use crate::OutOfRange;
+
/// The day of week.
///
/// The order of the days of week depends on the context.
/// (This is why this type does *not* implement `PartialOrd` or `Ord` traits.)
/// One should prefer `*_from_monday` or `*_from_sunday` methods to get the correct result.
+///
+/// # Example
+/// ```
+/// use chrono::Weekday;
+///
+/// let monday = "Monday".parse::<Weekday>().unwrap();
+/// assert_eq!(monday, Weekday::Mon);
+///
+/// let sunday = Weekday::try_from(6).unwrap();
+/// assert_eq!(sunday, Weekday::Sun);
+///
+/// assert_eq!(sunday.num_days_from_monday(), 6); // starts counting with Monday = 0
+/// assert_eq!(sunday.number_from_monday(), 7); // starts counting with Monday = 1
+/// assert_eq!(sunday.num_days_from_sunday(), 0); // starts counting with Sunday = 0
+/// assert_eq!(sunday.number_from_sunday(), 1); // starts counting with Sunday = 1
+///
+/// assert_eq!(sunday.succ(), monday);
+/// assert_eq!(sunday.pred(), Weekday::Sat);
+/// ```
#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash)]
#[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))]
#[cfg_attr(feature = "rkyv", derive(Archive, Deserialize, Serialize))]
@@ -36,7 +57,8 @@ impl Weekday {
/// ----------- | ----- | ----- | ----- | ----- | ----- | ----- | -----
/// `w.succ()`: | `Tue` | `Wed` | `Thu` | `Fri` | `Sat` | `Sun` | `Mon`
#[inline]
- pub fn succ(&self) -> Weekday {
+ #[must_use]
+ pub const fn succ(&self) -> Weekday {
match *self {
Weekday::Mon => Weekday::Tue,
Weekday::Tue => Weekday::Wed,
@@ -54,7 +76,8 @@ impl Weekday {
/// ----------- | ----- | ----- | ----- | ----- | ----- | ----- | -----
/// `w.pred()`: | `Sun` | `Mon` | `Tue` | `Wed` | `Thu` | `Fri` | `Sat`
#[inline]
- pub fn pred(&self) -> Weekday {
+ #[must_use]
+ pub const fn pred(&self) -> Weekday {
match *self {
Weekday::Mon => Weekday::Sun,
Weekday::Tue => Weekday::Mon,
@@ -108,7 +131,7 @@ impl Weekday {
/// Returns a day-of-week number starting from the parameter `day` (D) = 0.
///
- /// `w`: | `D` | `D+1` | `D+2` | `D+3` | `D+4` | `D+5` | `D+6`
+ /// `w`: | `D` | `D+1` | `D+2` | `D+3` | `D+4` | `D+5` | `D+6`
/// --------------------------- | ----- | ----- | ----- | ----- | ----- | ----- | -----
/// `w.num_days_from(wd)`: | 0 | 1 | 2 | 3 | 4 | 5 | 6
#[inline]
@@ -134,6 +157,26 @@ impl fmt::Display for Weekday {
/// Any weekday can be represented as an integer from 0 to 6, which equals to
/// [`Weekday::num_days_from_monday`](#method.num_days_from_monday) in this implementation.
/// Do not heavily depend on this though; use explicit methods whenever possible.
+impl TryFrom<u8> for Weekday {
+ type Error = OutOfRange;
+
+ fn try_from(value: u8) -> Result<Self, Self::Error> {
+ match value {
+ 0 => Ok(Weekday::Mon),
+ 1 => Ok(Weekday::Tue),
+ 2 => Ok(Weekday::Wed),
+ 3 => Ok(Weekday::Thu),
+ 4 => Ok(Weekday::Fri),
+ 5 => Ok(Weekday::Sat),
+ 6 => Ok(Weekday::Sun),
+ _ => Err(OutOfRange::new()),
+ }
+ }
+}
+
+/// Any weekday can be represented as an integer from 0 to 6, which equals to
+/// [`Weekday::num_days_from_monday`](#method.num_days_from_monday) in this implementation.
+/// Do not heavily depend on this though; use explicit methods whenever possible.
impl num_traits::FromPrimitive for Weekday {
#[inline]
fn from_i64(n: i64) -> Option<Weekday> {
@@ -188,14 +231,12 @@ impl fmt::Debug for ParseWeekdayError {
#[cfg(test)]
mod tests {
- use num_traits::FromPrimitive;
-
use super::Weekday;
#[test]
fn test_num_days_from() {
for i in 0..7 {
- let base_day = Weekday::from_u64(i).unwrap();
+ let base_day = Weekday::try_from(i).unwrap();
assert_eq!(base_day.num_days_from_monday(), base_day.num_days_from(Weekday::Mon));
assert_eq!(base_day.num_days_from_sunday(), base_day.num_days_from(Weekday::Sun));
diff --git a/vendor/chrono/tests/dateutils.rs b/vendor/chrono/tests/dateutils.rs
index dec6bfe11..d671ecca8 100644
--- a/vendor/chrono/tests/dateutils.rs
+++ b/vendor/chrono/tests/dateutils.rs
@@ -1,7 +1,11 @@
+#[cfg(unix)]
use chrono::offset::TimeZone;
+#[cfg(unix)]
use chrono::Local;
+#[cfg(unix)]
use chrono::{Datelike, NaiveDate, NaiveDateTime, Timelike};
+#[cfg(unix)]
use std::{path, process};
#[cfg(unix)]
@@ -48,31 +52,68 @@ fn verify_against_date_command_local(path: &'static str, dt: NaiveDateTime) {
}
}
+/// path to Unix `date` command. Should work on most Linux and Unixes. Not the
+/// path for MacOS (/bin/date) which uses a different version of `date` with
+/// different arguments (so it won't run which is okay).
+/// for testing only
+#[allow(dead_code)]
+#[cfg(not(target_os = "aix"))]
+const DATE_PATH: &'static str = "/usr/bin/date";
+#[allow(dead_code)]
+#[cfg(target_os = "aix")]
+const DATE_PATH: &'static str = "/opt/freeware/bin/date";
+
+#[cfg(test)]
+/// test helper to sanity check the date command behaves as expected
+/// asserts the command succeeded
+fn assert_run_date_version() {
+ // note environment variable `LANG`
+ match std::env::var_os("LANG") {
+ Some(lang) => eprintln!("LANG: {:?}", lang),
+ None => eprintln!("LANG not set"),
+ }
+ let out = process::Command::new(DATE_PATH).arg("--version").output().unwrap();
+ let stdout = String::from_utf8(out.stdout).unwrap();
+ let stderr = String::from_utf8(out.stderr).unwrap();
+ // note the `date` binary version
+ eprintln!("command: {:?} --version\nstdout: {:?}\nstderr: {:?}", DATE_PATH, stdout, stderr);
+ assert!(out.status.success(), "command failed: {:?} --version", DATE_PATH);
+}
+
#[test]
#[cfg(unix)]
fn try_verify_against_date_command() {
- let date_path = "/usr/bin/date";
-
- if !path::Path::new(date_path).exists() {
- // date command not found, skipping
- // avoid running this on macOS, which has path /bin/date
- // as the required CLI arguments are not present in the
- // macOS build.
+ if !path::Path::new(DATE_PATH).exists() {
+ eprintln!("date command {:?} not found, skipping", DATE_PATH);
return;
}
+ assert_run_date_version();
let mut date = NaiveDate::from_ymd_opt(1975, 1, 1).unwrap().and_hms_opt(0, 0, 0).unwrap();
+ eprintln!(
+ "Run command {:?} for every hour from {} to 2077, skipping some years...",
+ DATE_PATH,
+ date.year()
+ );
+ let mut count: u64 = 0;
+ let mut year_at = date.year();
while date.year() < 2078 {
if (1975..=1977).contains(&date.year())
|| (2020..=2022).contains(&date.year())
|| (2073..=2077).contains(&date.year())
{
- verify_against_date_command_local(date_path, date);
+ if date.year() != year_at {
+ eprintln!("at year {}...", date.year());
+ year_at = date.year();
+ }
+ verify_against_date_command_local(DATE_PATH, date);
+ count += 1;
}
date += chrono::Duration::hours(1);
}
+ eprintln!("Command {:?} was run {} times", DATE_PATH, count);
}
#[cfg(target_os = "linux")]
@@ -91,6 +132,7 @@ fn verify_against_date_command_format_local(path: &'static str, dt: NaiveDateTim
// Z%Z - too many ways to represent it, will most likely fail
let output = process::Command::new(path)
+ .env("LANG", "c")
.arg("-d")
.arg(format!(
"{}-{:02}-{:02} {:02}:{:02}:{:02}",
@@ -117,15 +159,15 @@ fn verify_against_date_command_format_local(path: &'static str, dt: NaiveDateTim
#[test]
#[cfg(target_os = "linux")]
fn try_verify_against_date_command_format() {
- let date_path = "/usr/bin/date";
-
- if !path::Path::new(date_path).exists() {
- // date command not found, skipping
+ if !path::Path::new(DATE_PATH).exists() {
+ eprintln!("date command {:?} not found, skipping", DATE_PATH);
return;
}
+ assert_run_date_version();
+
let mut date = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap().and_hms_opt(12, 11, 13).unwrap();
while date.year() < 2008 {
- verify_against_date_command_format_local(date_path, date);
+ verify_against_date_command_format_local(DATE_PATH, date);
date += chrono::Duration::days(55);
}
}