You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
8024 lines
306 KiB
8024 lines
306 KiB
From 7dead1c8d1b8438196d0bafbd6c4a94d9eeb911a Mon Sep 17 00:00:00 2001
|
|
From: rpm-build <rpm-build>
|
|
Date: Thu, 21 Nov 2024 16:25:00 +0100
|
|
Subject: [PATCH] Update time crate
|
|
|
|
---
|
|
Cargo.lock | 16 +-
|
|
vendor/num-conv/.cargo-checksum.json | 1 +
|
|
vendor/num-conv/Cargo.toml | 55 +
|
|
vendor/num-conv/LICENSE-Apache | 202 +++
|
|
vendor/num-conv/LICENSE-MIT | 19 +
|
|
vendor/num-conv/src/lib.rs | 329 +++++
|
|
vendor/time-macros/.cargo-checksum.json | 2 +-
|
|
vendor/time-macros/Cargo.toml | 89 +-
|
|
vendor/time-macros/LICENSE-Apache | 2 +-
|
|
vendor/time-macros/LICENSE-MIT | 2 +-
|
|
vendor/time-macros/src/date.rs | 3 +-
|
|
.../time-macros/src/format_description/ast.rs | 1 -
|
|
.../src/format_description/format_item.rs | 12 +-
|
|
.../src/format_description/lexer.rs | 2 +-
|
|
.../time-macros/src/format_description/mod.rs | 6 +-
|
|
.../src/format_description/public/mod.rs | 10 +-
|
|
vendor/time-macros/src/helpers/mod.rs | 16 +-
|
|
vendor/time-macros/src/lib.rs | 7 +-
|
|
vendor/time-macros/src/offset.rs | 7 +-
|
|
vendor/time/.cargo-checksum.json | 2 +-
|
|
vendor/time/Cargo.toml | 96 +-
|
|
vendor/time/LICENSE-Apache | 2 +-
|
|
vendor/time/LICENSE-MIT | 2 +-
|
|
vendor/time/src/date.rs | 61 +-
|
|
vendor/time/src/date_time.rs | 1248 -----------------
|
|
vendor/time/src/duration.rs | 110 +-
|
|
vendor/time/src/ext.rs | 319 -----
|
|
vendor/time/src/ext/digit_count.rs | 26 +
|
|
vendor/time/src/ext/instant.rs | 100 ++
|
|
vendor/time/src/ext/mod.rs | 13 +
|
|
vendor/time/src/ext/numerical_duration.rs | 140 ++
|
|
vendor/time/src/ext/numerical_std_duration.rs | 192 +++
|
|
.../borrowed_format_item.rs | 17 +-
|
|
vendor/time/src/format_description/mod.rs | 4 +-
|
|
.../format_description/owned_format_item.rs | 32 +-
|
|
.../format_description/parse/format_item.rs | 13 +-
|
|
.../src/format_description/parse/lexer.rs | 2 +-
|
|
.../time/src/format_description/parse/mod.rs | 19 +-
|
|
.../format_description/well_known/iso8601.rs | 2 +-
|
|
vendor/time/src/formatting/formattable.rs | 30 +-
|
|
vendor/time/src/formatting/iso8601.rs | 10 +-
|
|
vendor/time/src/formatting/mod.rs | 45 +-
|
|
vendor/time/src/instant.rs | 11 +
|
|
vendor/time/src/internal_macros.rs | 5 +-
|
|
vendor/time/src/lib.rs | 16 +-
|
|
vendor/time/src/macros.rs | 4 +-
|
|
vendor/time/src/offset_date_time.rs | 591 ++++++--
|
|
vendor/time/src/parsing/combinator/mod.rs | 4 +-
|
|
.../src/parsing/combinator/rfc/iso8601.rs | 6 +-
|
|
vendor/time/src/parsing/component.rs | 39 +-
|
|
vendor/time/src/parsing/iso8601.rs | 21 +-
|
|
vendor/time/src/parsing/mod.rs | 7 +
|
|
vendor/time/src/parsing/parsable.rs | 152 +-
|
|
vendor/time/src/parsing/parsed.rs | 118 +-
|
|
vendor/time/src/primitive_date_time.rs | 278 +++-
|
|
vendor/time/src/quickcheck.rs | 29 +-
|
|
vendor/time/src/serde/mod.rs | 76 +-
|
|
.../time/src/serde/timestamp/microseconds.rs | 63 +
|
|
.../time/src/serde/timestamp/milliseconds.rs | 63 +
|
|
.../serde/{timestamp.rs => timestamp/mod.rs} | 4 +
|
|
.../time/src/serde/timestamp/nanoseconds.rs | 61 +
|
|
.../time/src/sys/local_offset_at/wasm_js.rs | 5 +-
|
|
.../time/src/sys/local_offset_at/windows.rs | 19 +-
|
|
vendor/time/src/tests.rs | 1 +
|
|
vendor/time/src/time.rs | 33 +-
|
|
vendor/time/src/utc_offset.rs | 68 +-
|
|
vendor/time/src/util.rs | 4 +-
|
|
67 files changed, 2790 insertions(+), 2154 deletions(-)
|
|
create mode 100644 vendor/num-conv/.cargo-checksum.json
|
|
create mode 100644 vendor/num-conv/Cargo.toml
|
|
create mode 100644 vendor/num-conv/LICENSE-Apache
|
|
create mode 100644 vendor/num-conv/LICENSE-MIT
|
|
create mode 100644 vendor/num-conv/src/lib.rs
|
|
delete mode 100644 vendor/time/src/date_time.rs
|
|
delete mode 100644 vendor/time/src/ext.rs
|
|
create mode 100644 vendor/time/src/ext/digit_count.rs
|
|
create mode 100644 vendor/time/src/ext/instant.rs
|
|
create mode 100644 vendor/time/src/ext/mod.rs
|
|
create mode 100644 vendor/time/src/ext/numerical_duration.rs
|
|
create mode 100644 vendor/time/src/ext/numerical_std_duration.rs
|
|
create mode 100644 vendor/time/src/serde/timestamp/microseconds.rs
|
|
create mode 100644 vendor/time/src/serde/timestamp/milliseconds.rs
|
|
rename vendor/time/src/serde/{timestamp.rs => timestamp/mod.rs} (97%)
|
|
create mode 100644 vendor/time/src/serde/timestamp/nanoseconds.rs
|
|
|
|
diff --git a/Cargo.lock b/Cargo.lock
|
|
index be5e585..c21523e 100644
|
|
--- a/Cargo.lock
|
|
+++ b/Cargo.lock
|
|
@@ -1217,6 +1217,12 @@ dependencies = [
|
|
"num-traits",
|
|
]
|
|
|
|
+[[package]]
|
|
+name = "num-conv"
|
|
+version = "0.1.0"
|
|
+source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
+checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
|
|
+
|
|
[[package]]
|
|
name = "num-integer"
|
|
version = "0.1.45"
|
|
@@ -2109,12 +2115,13 @@ dependencies = [
|
|
|
|
[[package]]
|
|
name = "time"
|
|
-version = "0.3.30"
|
|
+version = "0.3.36"
|
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
-checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5"
|
|
+checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885"
|
|
dependencies = [
|
|
"deranged",
|
|
"itoa",
|
|
+ "num-conv",
|
|
"powerfmt",
|
|
"serde",
|
|
"time-core",
|
|
@@ -2129,10 +2136,11 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
|
|
|
|
[[package]]
|
|
name = "time-macros"
|
|
-version = "0.2.15"
|
|
+version = "0.2.18"
|
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
-checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20"
|
|
+checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf"
|
|
dependencies = [
|
|
+ "num-conv",
|
|
"time-core",
|
|
]
|
|
|
|
diff --git a/vendor/num-conv/.cargo-checksum.json b/vendor/num-conv/.cargo-checksum.json
|
|
new file mode 100644
|
|
index 0000000..3886e69
|
|
--- /dev/null
|
|
+++ b/vendor/num-conv/.cargo-checksum.json
|
|
@@ -0,0 +1 @@
|
|
+{"files":{"Cargo.toml":"c1d8999190f493d43b84b07eaffd2a9144e16be197bb3ef13eb69305e2f23047","LICENSE-Apache":"c0fd5f9df8d17e13587f8fe403d2326b835e60d532817d0b42ae4aea44209251","LICENSE-MIT":"af85fff507d80e6c7ff242acfc4b0a7f5de9a72286bb3c883c782772ca4b4402","src/lib.rs":"ab6c4b28902164204179f5c31473753fbe5220a4b23082e227478e19c2aa47ca"},"package":"51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"}
|
|
\ No newline at end of file
|
|
diff --git a/vendor/num-conv/Cargo.toml b/vendor/num-conv/Cargo.toml
|
|
new file mode 100644
|
|
index 0000000..0b8a9a6
|
|
--- /dev/null
|
|
+++ b/vendor/num-conv/Cargo.toml
|
|
@@ -0,0 +1,55 @@
|
|
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
|
+#
|
|
+# When uploading crates to the registry Cargo will automatically
|
|
+# "normalize" Cargo.toml files for maximal compatibility
|
|
+# with all versions of Cargo and also rewrite `path` dependencies
|
|
+# to registry (e.g., crates.io) dependencies.
|
|
+#
|
|
+# If you are reading this file be aware that the original Cargo.toml
|
|
+# will likely look very different (and much more reasonable).
|
|
+# See Cargo.toml.orig for the original contents.
|
|
+
|
|
+[package]
|
|
+edition = "2021"
|
|
+rust-version = "1.57.0"
|
|
+name = "num-conv"
|
|
+version = "0.1.0"
|
|
+authors = ["Jacob Pratt <jacob@jhpratt.dev>"]
|
|
+include = [
|
|
+ "src/**/*",
|
|
+ "LICENSE-*",
|
|
+]
|
|
+description = """
|
|
+`num_conv` is a crate to convert between integer types without using `as` casts. This provides
|
|
+better certainty when refactoring, makes the exact behavior of code more explicit, and allows using
|
|
+turbofish syntax.
|
|
+"""
|
|
+readme = "README.md"
|
|
+keywords = [
|
|
+ "cast",
|
|
+ "extend",
|
|
+ "truncate",
|
|
+ "convert",
|
|
+ "integer",
|
|
+]
|
|
+categories = [
|
|
+ "no-std",
|
|
+ "no-std::no-alloc",
|
|
+ "rust-patterns",
|
|
+]
|
|
+license = "MIT OR Apache-2.0"
|
|
+repository = "https://github.com/jhpratt/num-conv"
|
|
+
|
|
+[package.metadata.docs.rs]
|
|
+rustdoc-args = ["--generate-link-to-definition"]
|
|
+
|
|
+[features]
|
|
+
|
|
+[lints.clippy]
|
|
+alloc-instead-of-core = "deny"
|
|
+std-instead-of-core = "deny"
|
|
+
|
|
+[lints.rust]
|
|
+missing-docs = "warn"
|
|
+unreachable-pub = "warn"
|
|
+unused = "warn"
|
|
diff --git a/vendor/num-conv/LICENSE-Apache b/vendor/num-conv/LICENSE-Apache
|
|
new file mode 100644
|
|
index 0000000..d8bca8b
|
|
--- /dev/null
|
|
+++ b/vendor/num-conv/LICENSE-Apache
|
|
@@ -0,0 +1,202 @@
|
|
+
|
|
+ Apache License
|
|
+ Version 2.0, January 2004
|
|
+ http://www.apache.org/licenses/
|
|
+
|
|
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
+
|
|
+ 1. Definitions.
|
|
+
|
|
+ "License" shall mean the terms and conditions for use, reproduction,
|
|
+ and distribution as defined by Sections 1 through 9 of this document.
|
|
+
|
|
+ "Licensor" shall mean the copyright owner or entity authorized by
|
|
+ the copyright owner that is granting the License.
|
|
+
|
|
+ "Legal Entity" shall mean the union of the acting entity and all
|
|
+ other entities that control, are controlled by, or are under common
|
|
+ control with that entity. For the purposes of this definition,
|
|
+ "control" means (i) the power, direct or indirect, to cause the
|
|
+ direction or management of such entity, whether by contract or
|
|
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
+ outstanding shares, or (iii) beneficial ownership of such entity.
|
|
+
|
|
+ "You" (or "Your") shall mean an individual or Legal Entity
|
|
+ exercising permissions granted by this License.
|
|
+
|
|
+ "Source" form shall mean the preferred form for making modifications,
|
|
+ including but not limited to software source code, documentation
|
|
+ source, and configuration files.
|
|
+
|
|
+ "Object" form shall mean any form resulting from mechanical
|
|
+ transformation or translation of a Source form, including but
|
|
+ not limited to compiled object code, generated documentation,
|
|
+ and conversions to other media types.
|
|
+
|
|
+ "Work" shall mean the work of authorship, whether in Source or
|
|
+ Object form, made available under the License, as indicated by a
|
|
+ copyright notice that is included in or attached to the work
|
|
+ (an example is provided in the Appendix below).
|
|
+
|
|
+ "Derivative Works" shall mean any work, whether in Source or Object
|
|
+ form, that is based on (or derived from) the Work and for which the
|
|
+ editorial revisions, annotations, elaborations, or other modifications
|
|
+ represent, as a whole, an original work of authorship. For the purposes
|
|
+ of this License, Derivative Works shall not include works that remain
|
|
+ separable from, or merely link (or bind by name) to the interfaces of,
|
|
+ the Work and Derivative Works thereof.
|
|
+
|
|
+ "Contribution" shall mean any work of authorship, including
|
|
+ the original version of the Work and any modifications or additions
|
|
+ to that Work or Derivative Works thereof, that is intentionally
|
|
+ submitted to Licensor for inclusion in the Work by the copyright owner
|
|
+ or by an individual or Legal Entity authorized to submit on behalf of
|
|
+ the copyright owner. For the purposes of this definition, "submitted"
|
|
+ means any form of electronic, verbal, or written communication sent
|
|
+ to the Licensor or its representatives, including but not limited to
|
|
+ communication on electronic mailing lists, source code control systems,
|
|
+ and issue tracking systems that are managed by, or on behalf of, the
|
|
+ Licensor for the purpose of discussing and improving the Work, but
|
|
+ excluding communication that is conspicuously marked or otherwise
|
|
+ designated in writing by the copyright owner as "Not a Contribution."
|
|
+
|
|
+ "Contributor" shall mean Licensor and any individual or Legal Entity
|
|
+ on behalf of whom a Contribution has been received by Licensor and
|
|
+ subsequently incorporated within the Work.
|
|
+
|
|
+ 2. Grant of Copyright License. Subject to the terms and conditions of
|
|
+ this License, each Contributor hereby grants to You a perpetual,
|
|
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
+ copyright license to reproduce, prepare Derivative Works of,
|
|
+ publicly display, publicly perform, sublicense, and distribute the
|
|
+ Work and such Derivative Works in Source or Object form.
|
|
+
|
|
+ 3. Grant of Patent License. Subject to the terms and conditions of
|
|
+ this License, each Contributor hereby grants to You a perpetual,
|
|
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
+ (except as stated in this section) patent license to make, have made,
|
|
+ use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
+ where such license applies only to those patent claims licensable
|
|
+ by such Contributor that are necessarily infringed by their
|
|
+ Contribution(s) alone or by combination of their Contribution(s)
|
|
+ with the Work to which such Contribution(s) was submitted. If You
|
|
+ institute patent litigation against any entity (including a
|
|
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
+ or a Contribution incorporated within the Work constitutes direct
|
|
+ or contributory patent infringement, then any patent licenses
|
|
+ granted to You under this License for that Work shall terminate
|
|
+ as of the date such litigation is filed.
|
|
+
|
|
+ 4. Redistribution. You may reproduce and distribute copies of the
|
|
+ Work or Derivative Works thereof in any medium, with or without
|
|
+ modifications, and in Source or Object form, provided that You
|
|
+ meet the following conditions:
|
|
+
|
|
+ (a) You must give any other recipients of the Work or
|
|
+ Derivative Works a copy of this License; and
|
|
+
|
|
+ (b) You must cause any modified files to carry prominent notices
|
|
+ stating that You changed the files; and
|
|
+
|
|
+ (c) You must retain, in the Source form of any Derivative Works
|
|
+ that You distribute, all copyright, patent, trademark, and
|
|
+ attribution notices from the Source form of the Work,
|
|
+ excluding those notices that do not pertain to any part of
|
|
+ the Derivative Works; and
|
|
+
|
|
+ (d) If the Work includes a "NOTICE" text file as part of its
|
|
+ distribution, then any Derivative Works that You distribute must
|
|
+ include a readable copy of the attribution notices contained
|
|
+ within such NOTICE file, excluding those notices that do not
|
|
+ pertain to any part of the Derivative Works, in at least one
|
|
+ of the following places: within a NOTICE text file distributed
|
|
+ as part of the Derivative Works; within the Source form or
|
|
+ documentation, if provided along with the Derivative Works; or,
|
|
+ within a display generated by the Derivative Works, if and
|
|
+ wherever such third-party notices normally appear. The contents
|
|
+ of the NOTICE file are for informational purposes only and
|
|
+ do not modify the License. You may add Your own attribution
|
|
+ notices within Derivative Works that You distribute, alongside
|
|
+ or as an addendum to the NOTICE text from the Work, provided
|
|
+ that such additional attribution notices cannot be construed
|
|
+ as modifying the License.
|
|
+
|
|
+ You may add Your own copyright statement to Your modifications and
|
|
+ may provide additional or different license terms and conditions
|
|
+ for use, reproduction, or distribution of Your modifications, or
|
|
+ for any such Derivative Works as a whole, provided Your use,
|
|
+ reproduction, and distribution of the Work otherwise complies with
|
|
+ the conditions stated in this License.
|
|
+
|
|
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
+ any Contribution intentionally submitted for inclusion in the Work
|
|
+ by You to the Licensor shall be under the terms and conditions of
|
|
+ this License, without any additional terms or conditions.
|
|
+ Notwithstanding the above, nothing herein shall supersede or modify
|
|
+ the terms of any separate license agreement you may have executed
|
|
+ with Licensor regarding such Contributions.
|
|
+
|
|
+ 6. Trademarks. This License does not grant permission to use the trade
|
|
+ names, trademarks, service marks, or product names of the Licensor,
|
|
+ except as required for reasonable and customary use in describing the
|
|
+ origin of the Work and reproducing the content of the NOTICE file.
|
|
+
|
|
+ 7. Disclaimer of Warranty. Unless required by applicable law or
|
|
+ agreed to in writing, Licensor provides the Work (and each
|
|
+ Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
+ implied, including, without limitation, any warranties or conditions
|
|
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
+ PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
+ appropriateness of using or redistributing the Work and assume any
|
|
+ risks associated with Your exercise of permissions under this License.
|
|
+
|
|
+ 8. Limitation of Liability. In no event and under no legal theory,
|
|
+ whether in tort (including negligence), contract, or otherwise,
|
|
+ unless required by applicable law (such as deliberate and grossly
|
|
+ negligent acts) or agreed to in writing, shall any Contributor be
|
|
+ liable to You for damages, including any direct, indirect, special,
|
|
+ incidental, or consequential damages of any character arising as a
|
|
+ result of this License or out of the use or inability to use the
|
|
+ Work (including but not limited to damages for loss of goodwill,
|
|
+ work stoppage, computer failure or malfunction, or any and all
|
|
+ other commercial damages or losses), even if such Contributor
|
|
+ has been advised of the possibility of such damages.
|
|
+
|
|
+ 9. Accepting Warranty or Additional Liability. While redistributing
|
|
+ the Work or Derivative Works thereof, You may choose to offer,
|
|
+ and charge a fee for, acceptance of support, warranty, indemnity,
|
|
+ or other liability obligations and/or rights consistent with this
|
|
+ License. However, in accepting such obligations, You may act only
|
|
+ on Your own behalf and on Your sole responsibility, not on behalf
|
|
+ of any other Contributor, and only if You agree to indemnify,
|
|
+ defend, and hold each Contributor harmless for any liability
|
|
+ incurred by, or claims asserted against, such Contributor by reason
|
|
+ of your accepting any such warranty or additional liability.
|
|
+
|
|
+ END OF TERMS AND CONDITIONS
|
|
+
|
|
+ APPENDIX: How to apply the Apache License to your work.
|
|
+
|
|
+ To apply the Apache License to your work, attach the following
|
|
+ boilerplate notice, with the fields enclosed by brackets "[]"
|
|
+ replaced with your own identifying information. (Don't include
|
|
+ the brackets!) The text should be enclosed in the appropriate
|
|
+ comment syntax for the file format. We also recommend that a
|
|
+ file or class name and description of purpose be included on the
|
|
+ same "printed page" as the copyright notice for easier
|
|
+ identification within third-party archives.
|
|
+
|
|
+ Copyright 2023 Jacob Pratt
|
|
+
|
|
+ Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ you may not use this file except in compliance with the License.
|
|
+ You may obtain a copy of the License at
|
|
+
|
|
+ http://www.apache.org/licenses/LICENSE-2.0
|
|
+
|
|
+ Unless required by applicable law or agreed to in writing, software
|
|
+ distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ See the License for the specific language governing permissions and
|
|
+ limitations under the License.
|
|
diff --git a/vendor/num-conv/LICENSE-MIT b/vendor/num-conv/LICENSE-MIT
|
|
new file mode 100644
|
|
index 0000000..7c7f78a
|
|
--- /dev/null
|
|
+++ b/vendor/num-conv/LICENSE-MIT
|
|
@@ -0,0 +1,19 @@
|
|
+Copyright (c) 2023 Jacob Pratt
|
|
+
|
|
+Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
+of this software and associated documentation files (the "Software"), to deal
|
|
+in the Software without restriction, including without limitation the rights
|
|
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
+copies of the Software, and to permit persons to whom the Software is
|
|
+furnished to do so, subject to the following conditions:
|
|
+
|
|
+The above copyright notice and this permission notice shall be included in all
|
|
+copies or substantial portions of the Software.
|
|
+
|
|
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
+SOFTWARE.
|
|
diff --git a/vendor/num-conv/src/lib.rs b/vendor/num-conv/src/lib.rs
|
|
new file mode 100644
|
|
index 0000000..cbf3ff2
|
|
--- /dev/null
|
|
+++ b/vendor/num-conv/src/lib.rs
|
|
@@ -0,0 +1,329 @@
|
|
+//! `num_conv` is a crate to convert between integer types without using `as` casts. This provides
|
|
+//! better certainty when refactoring, makes the exact behavior of code more explicit, and allows
|
|
+//! using turbofish syntax.
|
|
+
|
|
+#![no_std]
|
|
+
|
|
+/// Anonymously import all extension traits.
|
|
+///
|
|
+/// This allows you to use the methods without worrying about polluting the namespace or importing
|
|
+/// them individually.
|
|
+///
|
|
+/// ```rust
|
|
+/// use num_conv::prelude::*;
|
|
+/// ```
|
|
+pub mod prelude {
|
|
+ pub use crate::{CastSigned as _, CastUnsigned as _, Extend as _, Truncate as _};
|
|
+}
|
|
+
|
|
+mod sealed {
|
|
+ pub trait Integer {}
|
|
+
|
|
+ macro_rules! impl_integer {
|
|
+ ($($t:ty)*) => {$(
|
|
+ impl Integer for $t {}
|
|
+ )*};
|
|
+ }
|
|
+
|
|
+ impl_integer! {
|
|
+ u8 u16 u32 u64 u128 usize
|
|
+ i8 i16 i32 i64 i128 isize
|
|
+ }
|
|
+
|
|
+ pub trait ExtendTargetSealed<T> {
|
|
+ fn extend(self) -> T;
|
|
+ }
|
|
+
|
|
+ pub trait TruncateTargetSealed<T> {
|
|
+ fn truncate(self) -> T;
|
|
+ }
|
|
+}
|
|
+
|
|
+/// Cast to a signed integer of the same size.
|
|
+///
|
|
+/// This trait is implemented for all integers. Unsigned to signed casts are equivalent to
|
|
+/// `0.wrapping_add_signed(value)`, while signed to signed casts are an identity conversion.
|
|
+///
|
|
+/// ```rust
|
|
+/// # use num_conv::CastSigned;
|
|
+/// assert_eq!(u8::MAX.cast_signed(), -1_i8);
|
|
+/// assert_eq!(u16::MAX.cast_signed(), -1_i16);
|
|
+/// assert_eq!(u32::MAX.cast_signed(), -1_i32);
|
|
+/// assert_eq!(u64::MAX.cast_signed(), -1_i64);
|
|
+/// assert_eq!(u128::MAX.cast_signed(), -1_i128);
|
|
+/// assert_eq!(usize::MAX.cast_signed(), -1_isize);
|
|
+/// ```
|
|
+///
|
|
+/// ```rust
|
|
+/// # use num_conv::CastSigned;
|
|
+/// assert_eq!(0_i8.cast_signed(), 0_i8);
|
|
+/// assert_eq!(0_i16.cast_signed(), 0_i16);
|
|
+/// assert_eq!(0_i32.cast_signed(), 0_i32);
|
|
+/// assert_eq!(0_i64.cast_signed(), 0_i64);
|
|
+/// assert_eq!(0_i128.cast_signed(), 0_i128);
|
|
+/// assert_eq!(0_isize.cast_signed(), 0_isize);
|
|
+/// ```
|
|
+pub trait CastSigned: sealed::Integer {
|
|
+ /// The signed integer type with the same size as `Self`.
|
|
+ type Signed;
|
|
+
|
|
+ /// Cast an integer to the signed integer of the same size.
|
|
+ fn cast_signed(self) -> Self::Signed;
|
|
+}
|
|
+
|
|
+/// Cast to an unsigned integer of the same size.
|
|
+///
|
|
+/// This trait is implemented for all integers. Signed to unsigned casts are equivalent to
|
|
+/// `0.wrapping_add_unsigned(value)`, while unsigned to unsigned casts are an identity conversion.
|
|
+///
|
|
+/// ```rust
|
|
+/// # use num_conv::CastUnsigned;
|
|
+/// assert_eq!((-1_i8).cast_unsigned(), u8::MAX);
|
|
+/// assert_eq!((-1_i16).cast_unsigned(), u16::MAX);
|
|
+/// assert_eq!((-1_i32).cast_unsigned(), u32::MAX);
|
|
+/// assert_eq!((-1_i64).cast_unsigned(), u64::MAX);
|
|
+/// assert_eq!((-1_i128).cast_unsigned(), u128::MAX);
|
|
+/// assert_eq!((-1_isize).cast_unsigned(), usize::MAX);
|
|
+/// ```
|
|
+///
|
|
+/// ```rust
|
|
+/// # use num_conv::CastUnsigned;
|
|
+/// assert_eq!(0_u8.cast_unsigned(), 0_u8);
|
|
+/// assert_eq!(0_u16.cast_unsigned(), 0_u16);
|
|
+/// assert_eq!(0_u32.cast_unsigned(), 0_u32);
|
|
+/// assert_eq!(0_u64.cast_unsigned(), 0_u64);
|
|
+/// assert_eq!(0_u128.cast_unsigned(), 0_u128);
|
|
+/// assert_eq!(0_usize.cast_unsigned(), 0_usize);
|
|
+/// ```
|
|
+pub trait CastUnsigned: sealed::Integer {
|
|
+ /// The unsigned integer type with the same size as `Self`.
|
|
+ type Unsigned;
|
|
+
|
|
+ /// Cast an integer to the unsigned integer of the same size.
|
|
+ fn cast_unsigned(self) -> Self::Unsigned;
|
|
+}
|
|
+
|
|
+/// A type that can be used with turbofish syntax in [`Extend::extend`].
|
|
+///
|
|
+/// It is unlikely that you will want to use this trait directly. You are probably looking for the
|
|
+/// [`Extend`] trait.
|
|
+pub trait ExtendTarget<T>: sealed::ExtendTargetSealed<T> {}
|
|
+
|
|
+/// A type that can be used with turbofish syntax in [`Truncate::truncate`].
|
|
+///
|
|
+/// It is unlikely that you will want to use this trait directly. You are probably looking for the
|
|
+/// [`Truncate`] trait.
|
|
+pub trait TruncateTarget<T>: sealed::TruncateTargetSealed<T> {}
|
|
+
|
|
+/// Extend to an integer of the same size or larger, preserving its value.
|
|
+///
|
|
+/// ```rust
|
|
+/// # use num_conv::Extend;
|
|
+/// assert_eq!(0_u8.extend::<u16>(), 0_u16);
|
|
+/// assert_eq!(0_u16.extend::<u32>(), 0_u32);
|
|
+/// assert_eq!(0_u32.extend::<u64>(), 0_u64);
|
|
+/// assert_eq!(0_u64.extend::<u128>(), 0_u128);
|
|
+/// ```
|
|
+///
|
|
+/// ```rust
|
|
+/// # use num_conv::Extend;
|
|
+/// assert_eq!((-1_i8).extend::<i16>(), -1_i16);
|
|
+/// assert_eq!((-1_i16).extend::<i32>(), -1_i32);
|
|
+/// assert_eq!((-1_i32).extend::<i64>(), -1_i64);
|
|
+/// assert_eq!((-1_i64).extend::<i128>(), -1_i128);
|
|
+/// ```
|
|
+pub trait Extend: sealed::Integer {
|
|
+ /// Extend an integer to an integer of the same size or larger, preserving its value.
|
|
+ fn extend<T>(self) -> T
|
|
+ where
|
|
+ Self: ExtendTarget<T>;
|
|
+}
|
|
+
|
|
+impl<T: sealed::Integer> Extend for T {
|
|
+ fn extend<U>(self) -> U
|
|
+ where
|
|
+ T: ExtendTarget<U>,
|
|
+ {
|
|
+ sealed::ExtendTargetSealed::extend(self)
|
|
+ }
|
|
+}
|
|
+
|
|
+/// Truncate to an integer of the same size or smaller, preserving the least significant bits.
|
|
+///
|
|
+/// ```rust
|
|
+/// # use num_conv::Truncate;
|
|
+/// assert_eq!(u16::MAX.truncate::<u8>(), u8::MAX);
|
|
+/// assert_eq!(u32::MAX.truncate::<u16>(), u16::MAX);
|
|
+/// assert_eq!(u64::MAX.truncate::<u32>(), u32::MAX);
|
|
+/// assert_eq!(u128::MAX.truncate::<u64>(), u64::MAX);
|
|
+/// ```
|
|
+///
|
|
+/// ```rust
|
|
+/// # use num_conv::Truncate;
|
|
+/// assert_eq!((-1_i16).truncate::<i8>(), -1_i8);
|
|
+/// assert_eq!((-1_i32).truncate::<i16>(), -1_i16);
|
|
+/// assert_eq!((-1_i64).truncate::<i32>(), -1_i32);
|
|
+/// assert_eq!((-1_i128).truncate::<i64>(), -1_i64);
|
|
+/// ```
|
|
+pub trait Truncate: sealed::Integer {
|
|
+ /// Truncate an integer to an integer of the same size or smaller, preserving the least
|
|
+ /// significant bits.
|
|
+ fn truncate<T>(self) -> T
|
|
+ where
|
|
+ Self: TruncateTarget<T>;
|
|
+}
|
|
+
|
|
+impl<T: sealed::Integer> Truncate for T {
|
|
+ fn truncate<U>(self) -> U
|
|
+ where
|
|
+ T: TruncateTarget<U>,
|
|
+ {
|
|
+ sealed::TruncateTargetSealed::truncate(self)
|
|
+ }
|
|
+}
|
|
+
|
|
+macro_rules! impl_cast_signed {
|
|
+ ($($($from:ty),+ => $to:ty;)*) => {$($(
|
|
+ const _: () = assert!(
|
|
+ core::mem::size_of::<$from>() == core::mem::size_of::<$to>(),
|
|
+ concat!(
|
|
+ "cannot cast ",
|
|
+ stringify!($from),
|
|
+ " to ",
|
|
+ stringify!($to),
|
|
+ " because they are different sizes"
|
|
+ )
|
|
+ );
|
|
+
|
|
+ impl CastSigned for $from {
|
|
+ type Signed = $to;
|
|
+ fn cast_signed(self) -> Self::Signed {
|
|
+ self as _
|
|
+ }
|
|
+ }
|
|
+ )+)*};
|
|
+}
|
|
+
|
|
+macro_rules! impl_cast_unsigned {
|
|
+ ($($($from:ty),+ => $to:ty;)*) => {$($(
|
|
+ const _: () = assert!(
|
|
+ core::mem::size_of::<$from>() == core::mem::size_of::<$to>(),
|
|
+ concat!(
|
|
+ "cannot cast ",
|
|
+ stringify!($from),
|
|
+ " to ",
|
|
+ stringify!($to),
|
|
+ " because they are different sizes"
|
|
+ )
|
|
+ );
|
|
+
|
|
+ impl CastUnsigned for $from {
|
|
+ type Unsigned = $to;
|
|
+ fn cast_unsigned(self) -> Self::Unsigned {
|
|
+ self as _
|
|
+ }
|
|
+ }
|
|
+ )+)*};
|
|
+}
|
|
+
|
|
+macro_rules! impl_extend {
|
|
+ ($($from:ty => $($to:ty),+;)*) => {$($(
|
|
+ const _: () = assert!(
|
|
+ core::mem::size_of::<$from>() <= core::mem::size_of::<$to>(),
|
|
+ concat!(
|
|
+ "cannot extend ",
|
|
+ stringify!($from),
|
|
+ " to ",
|
|
+ stringify!($to),
|
|
+ " because ",
|
|
+ stringify!($from),
|
|
+ " is larger than ",
|
|
+ stringify!($to)
|
|
+ )
|
|
+ );
|
|
+
|
|
+ impl sealed::ExtendTargetSealed<$to> for $from {
|
|
+ fn extend(self) -> $to {
|
|
+ self as _
|
|
+ }
|
|
+ }
|
|
+
|
|
+ impl ExtendTarget<$to> for $from {}
|
|
+ )+)*};
|
|
+}
|
|
+
|
|
+macro_rules! impl_truncate {
|
|
+ ($($($from:ty),+ => $to:ty;)*) => {$($(
|
|
+ const _: () = assert!(
|
|
+ core::mem::size_of::<$from>() >= core::mem::size_of::<$to>(),
|
|
+ concat!(
|
|
+ "cannot truncate ",
|
|
+ stringify!($from),
|
|
+ " to ",
|
|
+ stringify!($to),
|
|
+ " because ",
|
|
+ stringify!($from),
|
|
+ " is smaller than ",
|
|
+ stringify!($to)
|
|
+ )
|
|
+ );
|
|
+
|
|
+ impl sealed::TruncateTargetSealed<$to> for $from {
|
|
+ fn truncate(self) -> $to {
|
|
+ self as _
|
|
+ }
|
|
+ }
|
|
+
|
|
+ impl TruncateTarget<$to> for $from {}
|
|
+ )+)*};
|
|
+}
|
|
+
|
|
+impl_cast_signed! {
|
|
+ u8, i8 => i8;
|
|
+ u16, i16 => i16;
|
|
+ u32, i32 => i32;
|
|
+ u64, i64 => i64;
|
|
+ u128, i128 => i128;
|
|
+ usize, isize => isize;
|
|
+}
|
|
+
|
|
+impl_cast_unsigned! {
|
|
+ u8, i8 => u8;
|
|
+ u16, i16 => u16;
|
|
+ u32, i32 => u32;
|
|
+ u64, i64 => u64;
|
|
+ u128, i128 => u128;
|
|
+ usize, isize => usize;
|
|
+}
|
|
+
|
|
+impl_extend! {
|
|
+ u8 => u8, u16, u32, u64, u128, usize;
|
|
+ u16 => u16, u32, u64, u128, usize;
|
|
+ u32 => u32, u64, u128;
|
|
+ u64 => u64, u128;
|
|
+ u128 => u128;
|
|
+ usize => usize;
|
|
+
|
|
+ i8 => i8, i16, i32, i64, i128, isize;
|
|
+ i16 => i16, i32, i64, i128, isize;
|
|
+ i32 => i32, i64, i128;
|
|
+ i64 => i64, i128;
|
|
+ i128 => i128;
|
|
+ isize => isize;
|
|
+}
|
|
+
|
|
+impl_truncate! {
|
|
+ u8, u16, u32, u64, u128, usize => u8;
|
|
+ u16, u32, u64, u128, usize => u16;
|
|
+ u32, u64, u128 => u32;
|
|
+ u64, u128 => u64;
|
|
+ u128 => u128;
|
|
+ usize => usize;
|
|
+
|
|
+ i8, i16, i32, i64, i128, isize => i8;
|
|
+ i16, i32, i64, i128, isize => i16;
|
|
+ i32, i64, i128 => i32;
|
|
+ i64, i128 => i64;
|
|
+ i128 => i128;
|
|
+ isize => isize;
|
|
+}
|
|
diff --git a/vendor/time-macros/.cargo-checksum.json b/vendor/time-macros/.cargo-checksum.json
|
|
index 43b384c..ab81b00 100644
|
|
--- a/vendor/time-macros/.cargo-checksum.json
|
|
+++ b/vendor/time-macros/.cargo-checksum.json
|
|
@@ -1 +1 @@
|
|
-{"files":{"Cargo.toml":"cdd214eacd21423c9f1ba430604c12f7b0551843f8fd4386908cb1be7de2121f","LICENSE-Apache":"b8929fea28678da67251fb2daf9438f67503814211051861612441806d8edb05","LICENSE-MIT":"04620bf27e4a643dd47bf27652320c205acdb776c1f9f24bb8c3bfaba10804c5","src/date.rs":"680dbeb4be6b8ba7be04d492047295be62b4c23d81ae2ab9494f3918e15cd590","src/datetime.rs":"5c7f6e07dc2f0dcfcd86216664df53bc008dbc86f346df57a9ff57f52fe43bc6","src/error.rs":"b3dea92631092068dd73e57e1cbf548f7ae85762826dcdea7fd6454bf357a50a","src/format_description/ast.rs":"8ba87e3249766b89c42b040f623d3134aeec46b78208fdfee825ed0eeeb4591a","src/format_description/format_item.rs":"3b3d017166802d14cbb30d1b02619fc6cf3d0a1683ca5d3d52fc771790bed4ee","src/format_description/lexer.rs":"e7db7b6431f00c81b8d15a162088a1622ecd65bfb58d4e642c3c93a8dd5ae4ad","src/format_description/mod.rs":"f48c0ff590bc74529f06a98f60a6af5814bc30d1456bf0b81ac334c0b3f41bba","src/format_description/public/component.rs":"5d86912e247724957f7183d70745ced20a7408ed90c24bb47da73a0e26550899","src/format_description/public/mod.rs":"5260592b310ea9e30808d30c92ea94c7bf1bdb171250a1342279e927d2528d73","src/format_description/public/modifier.rs":"e1d8fdababcaee2e181a7acb3a938baf309f5a0e2d3877585cf678fcc12f212a","src/helpers/mod.rs":"a8f8ed59a72b239d7a530357d212873f2e75ea924ec19a6d5d6e24a2baa8100c","src/helpers/string.rs":"3af2d0c701ca978c705922a272e76506dbdf0f376d44ed9ae7283086c67852ba","src/lib.rs":"ae001dd70bc5a07ad62aeba90a58b3a24830667db4bc92b0fda82ccc57422d34","src/offset.rs":"dd33a76a8ca22145817dc424549f125d786de535c540cb5a93bad48bd4edcc78","src/quote.rs":"d3003dafa3073825f188851a974846099681cc81145070affb033469cbc7bb31","src/serde_format_description.rs":"db5fb2dc94e01c5114cab3484e68334516d53c4642f31dae0d66f1183253a17c","src/time.rs":"299ddb54e44fb88e514592db5335f06352ebdd0dbf064752790657db85f4c13c","src/to_tokens.rs":"afb067f4d95d19c1b7a650cbcf60ae155b5a9619c89825867997f39ce163ac94"},"package":"4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20"}
|
|
\ No newline at end of file
|
|
+{"files":{"Cargo.toml":"3330436e81a4de8b20b9a2931f9e857b7974a8423462d928b04cff55ad531cff","LICENSE-Apache":"edd65bdd88957a205c47d53fa499eed8865a70320f0f03f6391668cb304ea376","LICENSE-MIT":"231c837c45eb53f108fb48929e488965bc4fcc14e9ea21d35f50e6b99d98685b","src/date.rs":"be197c8a2ed37e8b3123a798a91697b0e61cf9b60e7b1898a0e1b458fe8e3ef1","src/datetime.rs":"5c7f6e07dc2f0dcfcd86216664df53bc008dbc86f346df57a9ff57f52fe43bc6","src/error.rs":"b3dea92631092068dd73e57e1cbf548f7ae85762826dcdea7fd6454bf357a50a","src/format_description/ast.rs":"697d5ce506b5386092d706bfe5bf4f81f50e1130796cb17c2fc61457fb165307","src/format_description/format_item.rs":"02d12976209c7af83c2aa4a3221a1a65420fae8c8ba12a28933fb738a2872ff9","src/format_description/lexer.rs":"e2c75f3dda5773a0c8301fdfc0d58a0b833923ba59ac04bcc49fd10aee20496c","src/format_description/mod.rs":"2109b77a8198769c6a6732a54233d7e0058bf4a6da724824103d107859795956","src/format_description/public/component.rs":"5d86912e247724957f7183d70745ced20a7408ed90c24bb47da73a0e26550899","src/format_description/public/mod.rs":"8030e767cb94d559dda2dddc72d42654a756362bd165e5c2cccf112f15d49610","src/format_description/public/modifier.rs":"e1d8fdababcaee2e181a7acb3a938baf309f5a0e2d3877585cf678fcc12f212a","src/helpers/mod.rs":"af47d6c053ffd1113788c5d7591d46fa7d879dc0c5cb2c6c02f9c05462499c4f","src/helpers/string.rs":"3af2d0c701ca978c705922a272e76506dbdf0f376d44ed9ae7283086c67852ba","src/lib.rs":"6ed2d4a41d15a1b5d9fef7d437a1520d967acbfbab98a88630062340f701ca54","src/offset.rs":"aed29d0da9fc65a7dc77314e0346dfdc6fdaf663f17adf9edf00933e8f8e605f","src/quote.rs":"d3003dafa3073825f188851a974846099681cc81145070affb033469cbc7bb31","src/serde_format_description.rs":"db5fb2dc94e01c5114cab3484e68334516d53c4642f31dae0d66f1183253a17c","src/time.rs":"299ddb54e44fb88e514592db5335f06352ebdd0dbf064752790657db85f4c13c","src/to_tokens.rs":"afb067f4d95d19c1b7a650cbcf60ae155b5a9619c89825867997f39ce163ac94"},"package":"3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf"}
|
|
\ No newline at end of file
|
|
diff --git a/vendor/time-macros/Cargo.toml b/vendor/time-macros/Cargo.toml
|
|
index 5369417..b817622 100644
|
|
--- a/vendor/time-macros/Cargo.toml
|
|
+++ b/vendor/time-macros/Cargo.toml
|
|
@@ -13,7 +13,7 @@
|
|
edition = "2021"
|
|
rust-version = "1.67.0"
|
|
name = "time-macros"
|
|
-version = "0.2.15"
|
|
+version = "0.2.18"
|
|
authors = [
|
|
"Jacob Pratt <open-source@jhpratt.dev>",
|
|
"Time contributors",
|
|
@@ -38,6 +38,9 @@ rustdoc-args = ["--generate-link-to-definition"]
|
|
[lib]
|
|
proc-macro = true
|
|
|
|
+[dependencies.num-conv]
|
|
+version = "0.1.0"
|
|
+
|
|
[dependencies.time-core]
|
|
version = "=0.1.2"
|
|
|
|
@@ -46,3 +49,87 @@ formatting = []
|
|
large-dates = []
|
|
parsing = []
|
|
serde = []
|
|
+
|
|
+[lints.clippy]
|
|
+all = "warn"
|
|
+alloc-instead-of-core = "deny"
|
|
+dbg-macro = "warn"
|
|
+decimal-literal-representation = "warn"
|
|
+explicit-auto-deref = "warn"
|
|
+get-unwrap = "warn"
|
|
+manual-let-else = "warn"
|
|
+missing-docs-in-private-items = "warn"
|
|
+missing-enforced-import-renames = "warn"
|
|
+nursery = "warn"
|
|
+obfuscated-if-else = "warn"
|
|
+print-stdout = "warn"
|
|
+semicolon-outside-block = "warn"
|
|
+std-instead-of-core = "deny"
|
|
+todo = "warn"
|
|
+undocumented-unsafe-blocks = "deny"
|
|
+unimplemented = "warn"
|
|
+uninlined-format-args = "warn"
|
|
+unnested-or-patterns = "warn"
|
|
+unwrap-in-result = "warn"
|
|
+unwrap-used = "warn"
|
|
+use-debug = "warn"
|
|
+
|
|
+[lints.clippy.option-if-let-else]
|
|
+level = "allow"
|
|
+priority = 1
|
|
+
|
|
+[lints.clippy.redundant-pub-crate]
|
|
+level = "allow"
|
|
+priority = 1
|
|
+
|
|
+[lints.rust]
|
|
+ambiguous-glob-reexports = "deny"
|
|
+clashing-extern-declarations = "deny"
|
|
+const-item-mutation = "deny"
|
|
+deref-nullptr = "deny"
|
|
+drop-bounds = "deny"
|
|
+future-incompatible = "deny"
|
|
+hidden-glob-reexports = "deny"
|
|
+improper-ctypes = "deny"
|
|
+improper-ctypes-definitions = "deny"
|
|
+invalid-from-utf8 = "deny"
|
|
+invalid-macro-export-arguments = "deny"
|
|
+invalid-nan-comparisons = "deny"
|
|
+invalid-reference-casting = "deny"
|
|
+invalid-value = "deny"
|
|
+keyword-idents = "warn"
|
|
+let-underscore = "warn"
|
|
+macro-use-extern-crate = "warn"
|
|
+meta-variable-misuse = "warn"
|
|
+missing-abi = "warn"
|
|
+missing-copy-implementations = "warn"
|
|
+missing-debug-implementations = "warn"
|
|
+missing-docs = "warn"
|
|
+named-arguments-used-positionally = "deny"
|
|
+non-ascii-idents = "deny"
|
|
+noop-method-call = "warn"
|
|
+opaque-hidden-inferred-bound = "deny"
|
|
+overlapping-range-endpoints = "deny"
|
|
+single-use-lifetimes = "warn"
|
|
+suspicious-double-ref-op = "deny"
|
|
+temporary-cstring-as-ptr = "deny"
|
|
+trivial-casts = "warn"
|
|
+trivial-numeric-casts = "warn"
|
|
+unconditional-recursion = "deny"
|
|
+unnameable-test-items = "deny"
|
|
+unreachable-pub = "warn"
|
|
+unsafe-op-in-unsafe-fn = "deny"
|
|
+unstable-syntax-pre-expansion = "deny"
|
|
+unused = "warn"
|
|
+unused-import-braces = "warn"
|
|
+unused-lifetimes = "warn"
|
|
+unused-qualifications = "warn"
|
|
+variant-size-differences = "warn"
|
|
+
|
|
+[lints.rust.unstable-name-collisions]
|
|
+level = "warn"
|
|
+priority = 1
|
|
+
|
|
+[lints.rustdoc]
|
|
+private-doc-tests = "warn"
|
|
+unescaped-backticks = "warn"
|
|
diff --git a/vendor/time-macros/LICENSE-Apache b/vendor/time-macros/LICENSE-Apache
|
|
index 7646f21..c763a0c 100644
|
|
--- a/vendor/time-macros/LICENSE-Apache
|
|
+++ b/vendor/time-macros/LICENSE-Apache
|
|
@@ -187,7 +187,7 @@
|
|
same "printed page" as the copyright notice for easier
|
|
identification within third-party archives.
|
|
|
|
- Copyright 2022 Jacob Pratt et al.
|
|
+ Copyright 2024 Jacob Pratt et al.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
diff --git a/vendor/time-macros/LICENSE-MIT b/vendor/time-macros/LICENSE-MIT
|
|
index a11a755..5cc097f 100644
|
|
--- a/vendor/time-macros/LICENSE-MIT
|
|
+++ b/vendor/time-macros/LICENSE-MIT
|
|
@@ -1,4 +1,4 @@
|
|
-Copyright (c) 2022 Jacob Pratt et al.
|
|
+Copyright (c) 2024 Jacob Pratt et al.
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
diff --git a/vendor/time-macros/src/date.rs b/vendor/time-macros/src/date.rs
|
|
index fa16ccb..03cbf11 100644
|
|
--- a/vendor/time-macros/src/date.rs
|
|
+++ b/vendor/time-macros/src/date.rs
|
|
@@ -1,5 +1,6 @@
|
|
use std::iter::Peekable;
|
|
|
|
+use num_conv::Truncate;
|
|
use proc_macro::{token_stream, TokenTree};
|
|
use time_core::util::{days_in_year, weeks_in_year};
|
|
|
|
@@ -93,7 +94,7 @@ pub(crate) fn parse(chars: &mut Peekable<token_stream::IntoIter>) -> Result<Date
|
|
span_end: Some(month_span),
|
|
});
|
|
}
|
|
- let month = month as _;
|
|
+ let month = month.truncate();
|
|
if day == 0 || day > days_in_year_month(year, month) {
|
|
return Err(Error::InvalidComponent {
|
|
name: "day",
|
|
diff --git a/vendor/time-macros/src/format_description/ast.rs b/vendor/time-macros/src/format_description/ast.rs
|
|
index b75056b..4c3a19e 100644
|
|
--- a/vendor/time-macros/src/format_description/ast.rs
|
|
+++ b/vendor/time-macros/src/format_description/ast.rs
|
|
@@ -1,4 +1,3 @@
|
|
-use std::boxed::Box;
|
|
use std::iter;
|
|
|
|
use super::{lexer, unused, Error, Location, Spanned, SpannedValue, Unused};
|
|
diff --git a/vendor/time-macros/src/format_description/format_item.rs b/vendor/time-macros/src/format_description/format_item.rs
|
|
index 7116866..ea36cae 100644
|
|
--- a/vendor/time-macros/src/format_description/format_item.rs
|
|
+++ b/vendor/time-macros/src/format_description/format_item.rs
|
|
@@ -1,4 +1,3 @@
|
|
-use std::boxed::Box;
|
|
use std::num::NonZeroU16;
|
|
use std::str::{self, FromStr};
|
|
|
|
@@ -103,14 +102,9 @@ impl From<Item<'_>> for crate::format_description::public::OwnedFormatItem {
|
|
impl<'a> From<Box<[Item<'a>]>> for crate::format_description::public::OwnedFormatItem {
|
|
fn from(items: Box<[Item<'a>]>) -> Self {
|
|
let items = items.into_vec();
|
|
- if items.len() == 1 {
|
|
- if let Ok([item]) = <[_; 1]>::try_from(items) {
|
|
- item.into()
|
|
- } else {
|
|
- bug!("the length was just checked to be 1")
|
|
- }
|
|
- } else {
|
|
- Self::Compound(items.into_iter().map(Self::from).collect())
|
|
+ match <[_; 1]>::try_from(items) {
|
|
+ Ok([item]) => item.into(),
|
|
+ Err(vec) => Self::Compound(vec.into_iter().map(Into::into).collect()),
|
|
}
|
|
}
|
|
}
|
|
diff --git a/vendor/time-macros/src/format_description/lexer.rs b/vendor/time-macros/src/format_description/lexer.rs
|
|
index 2c927cb..2ea53af 100644
|
|
--- a/vendor/time-macros/src/format_description/lexer.rs
|
|
+++ b/vendor/time-macros/src/format_description/lexer.rs
|
|
@@ -3,7 +3,7 @@ use core::iter;
|
|
use super::{Error, Location, Spanned, SpannedValue};
|
|
|
|
pub(super) struct Lexed<I: Iterator> {
|
|
- iter: core::iter::Peekable<I>,
|
|
+ iter: iter::Peekable<I>,
|
|
}
|
|
|
|
impl<I: Iterator> Iterator for Lexed<I> {
|
|
diff --git a/vendor/time-macros/src/format_description/mod.rs b/vendor/time-macros/src/format_description/mod.rs
|
|
index fde1272..676028d 100644
|
|
--- a/vendor/time-macros/src/format_description/mod.rs
|
|
+++ b/vendor/time-macros/src/format_description/mod.rs
|
|
@@ -1,7 +1,5 @@
|
|
//! Parser for format descriptions.
|
|
|
|
-use std::vec::Vec;
|
|
-
|
|
macro_rules! version {
|
|
($range:expr) => {
|
|
$range.contains(&VERSION)
|
|
@@ -17,7 +15,7 @@ pub(crate) fn parse_with_version(
|
|
version: Option<crate::FormatDescriptionVersion>,
|
|
s: &[u8],
|
|
proc_span: proc_macro::Span,
|
|
-) -> Result<Vec<crate::format_description::public::OwnedFormatItem>, crate::Error> {
|
|
+) -> Result<Vec<public::OwnedFormatItem>, crate::Error> {
|
|
match version {
|
|
Some(crate::FormatDescriptionVersion::V1) | None => parse::<1>(s, proc_span),
|
|
Some(crate::FormatDescriptionVersion::V2) => parse::<2>(s, proc_span),
|
|
@@ -27,7 +25,7 @@ pub(crate) fn parse_with_version(
|
|
fn parse<const VERSION: u8>(
|
|
s: &[u8],
|
|
proc_span: proc_macro::Span,
|
|
-) -> Result<Vec<crate::format_description::public::OwnedFormatItem>, crate::Error> {
|
|
+) -> Result<Vec<public::OwnedFormatItem>, crate::Error> {
|
|
let mut lexed = lexer::lex::<VERSION>(s, proc_span);
|
|
let ast = ast::parse::<_, VERSION>(&mut lexed);
|
|
let format_items = format_item::parse(ast);
|
|
diff --git a/vendor/time-macros/src/format_description/public/mod.rs b/vendor/time-macros/src/format_description/public/mod.rs
|
|
index ccb0b6e..9fd8b5e 100644
|
|
--- a/vendor/time-macros/src/format_description/public/mod.rs
|
|
+++ b/vendor/time-macros/src/format_description/public/mod.rs
|
|
@@ -19,12 +19,12 @@ impl ToTokenStream for OwnedFormatItem {
|
|
fn append_to(self, ts: &mut TokenStream) {
|
|
match self {
|
|
Self::Literal(bytes) => quote_append! { ts
|
|
- ::time::format_description::FormatItem::Literal {
|
|
+ ::time::format_description::BorrowedFormatItem::Literal {
|
|
0: #(Literal::byte_string(bytes.as_ref()))
|
|
}
|
|
},
|
|
Self::Component(component) => quote_append! { ts
|
|
- ::time::format_description::FormatItem::Component { 0: #S(component) }
|
|
+ ::time::format_description::BorrowedFormatItem::Component { 0: #S(component) }
|
|
},
|
|
Self::Compound(items) => {
|
|
let items = items
|
|
@@ -33,11 +33,11 @@ impl ToTokenStream for OwnedFormatItem {
|
|
.map(|item| quote! { #S(item), })
|
|
.collect::<TokenStream>();
|
|
quote_append! { ts
|
|
- ::time::format_description::FormatItem::Compound { 0: &[#S(items)] }
|
|
+ ::time::format_description::BorrowedFormatItem::Compound { 0: &[#S(items)] }
|
|
}
|
|
}
|
|
Self::Optional(item) => quote_append! {ts
|
|
- ::time::format_description::FormatItem::Optional { 0: &#S(*item) }
|
|
+ ::time::format_description::BorrowedFormatItem::Optional { 0: &#S(*item) }
|
|
},
|
|
Self::First(items) => {
|
|
let items = items
|
|
@@ -46,7 +46,7 @@ impl ToTokenStream for OwnedFormatItem {
|
|
.map(|item| quote! { #S(item), })
|
|
.collect::<TokenStream>();
|
|
quote_append! { ts
|
|
- ::time::format_description::FormatItem::First { 0: &[#S(items)] }
|
|
+ ::time::format_description::BorrowedFormatItem::First { 0: &[#S(items)] }
|
|
}
|
|
}
|
|
}
|
|
diff --git a/vendor/time-macros/src/helpers/mod.rs b/vendor/time-macros/src/helpers/mod.rs
|
|
index 56300b3..0cca200 100644
|
|
--- a/vendor/time-macros/src/helpers/mod.rs
|
|
+++ b/vendor/time-macros/src/helpers/mod.rs
|
|
@@ -4,6 +4,7 @@ mod string;
|
|
use std::iter::Peekable;
|
|
use std::str::FromStr;
|
|
|
|
+use num_conv::prelude::*;
|
|
use proc_macro::{token_stream, Span, TokenTree};
|
|
use time_core::util::{days_in_year, is_leap_year};
|
|
|
|
@@ -92,15 +93,17 @@ fn jan_weekday(year: i32, ordinal: i32) -> u8 {
|
|
}
|
|
|
|
let adj_year = year - 1;
|
|
- ((ordinal + adj_year + div_floor!(adj_year, 4) - div_floor!(adj_year, 100)
|
|
+ (ordinal + adj_year + div_floor!(adj_year, 4) - div_floor!(adj_year, 100)
|
|
+ div_floor!(adj_year, 400)
|
|
+ 6)
|
|
- .rem_euclid(7)) as _
|
|
+ .rem_euclid(7)
|
|
+ .cast_unsigned()
|
|
+ .truncate()
|
|
}
|
|
|
|
pub(crate) fn days_in_year_month(year: i32, month: u8) -> u8 {
|
|
- [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month as usize - 1]
|
|
- + (month == 2 && is_leap_year(year)) as u8
|
|
+ [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month.extend::<usize>() - 1]
|
|
+ + u8::from(month == 2 && is_leap_year(year))
|
|
}
|
|
|
|
pub(crate) fn ywd_to_yo(year: i32, week: u8, iso_weekday_number: u8) -> (i32, u16) {
|
|
@@ -120,8 +123,9 @@ pub(crate) fn ywd_to_yo(year: i32, week: u8, iso_weekday_number: u8) -> (i32, u1
|
|
}
|
|
|
|
pub(crate) fn ymd_to_yo(year: i32, month: u8, day: u8) -> (i32, u16) {
|
|
- let ordinal = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334][month as usize - 1]
|
|
- + (month > 2 && is_leap_year(year)) as u16;
|
|
+ let ordinal = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334]
|
|
+ [month.extend::<usize>() - 1]
|
|
+ + u16::from(month > 2 && is_leap_year(year));
|
|
|
|
(year, ordinal + u16::from(day))
|
|
}
|
|
diff --git a/vendor/time-macros/src/lib.rs b/vendor/time-macros/src/lib.rs
|
|
index d9e4693..65e24d7 100644
|
|
--- a/vendor/time-macros/src/lib.rs
|
|
+++ b/vendor/time-macros/src/lib.rs
|
|
@@ -68,7 +68,7 @@ enum FormatDescriptionVersion {
|
|
#[cfg(any(feature = "formatting", feature = "parsing"))]
|
|
enum VersionOrModuleName {
|
|
Version(FormatDescriptionVersion),
|
|
- #[cfg_attr(not(feature = "serde"), allow(unused_tuple_struct_fields))]
|
|
+ #[cfg_attr(not(feature = "serde"), allow(dead_code))]
|
|
ModuleName(Ident),
|
|
}
|
|
|
|
@@ -151,7 +151,7 @@ pub fn format_description(input: TokenStream) -> TokenStream {
|
|
let items = format_description::parse_with_version(version, &string, span)?;
|
|
|
|
Ok(quote! {{
|
|
- const DESCRIPTION: &[::time::format_description::FormatItem<'_>] = &[#S(
|
|
+ const DESCRIPTION: &[::time::format_description::BorrowedFormatItem<'_>] = &[#S(
|
|
items
|
|
.into_iter()
|
|
.map(|item| quote! { #S(item), })
|
|
@@ -212,7 +212,8 @@ pub fn serde_format_description(input: TokenStream) -> TokenStream {
|
|
let items: TokenStream =
|
|
items.into_iter().map(|item| quote! { #S(item), }).collect();
|
|
let items = quote! {
|
|
- const ITEMS: &[::time::format_description::FormatItem<'_>] = &[#S(items)];
|
|
+ const ITEMS: &[::time::format_description::BorrowedFormatItem<'_>]
|
|
+ = &[#S(items)];
|
|
ITEMS
|
|
};
|
|
|
|
diff --git a/vendor/time-macros/src/offset.rs b/vendor/time-macros/src/offset.rs
|
|
index b9a3c61..04dd37f 100644
|
|
--- a/vendor/time-macros/src/offset.rs
|
|
+++ b/vendor/time-macros/src/offset.rs
|
|
@@ -1,5 +1,6 @@
|
|
use std::iter::Peekable;
|
|
|
|
+use num_conv::prelude::*;
|
|
use proc_macro::{token_stream, Span, TokenTree};
|
|
use time_core::convert::*;
|
|
|
|
@@ -52,21 +53,21 @@ pub(crate) fn parse(chars: &mut Peekable<token_stream::IntoIter>) -> Result<Offs
|
|
}
|
|
}
|
|
|
|
- if hours >= 24 {
|
|
+ if hours > 25 {
|
|
Err(Error::InvalidComponent {
|
|
name: "hour",
|
|
value: hours.to_string(),
|
|
span_start: Some(hours_span),
|
|
span_end: Some(hours_span),
|
|
})
|
|
- } else if minutes >= Minute::per(Hour) as _ {
|
|
+ } else if minutes >= Minute::per(Hour).cast_signed() {
|
|
Err(Error::InvalidComponent {
|
|
name: "minute",
|
|
value: minutes.to_string(),
|
|
span_start: Some(minutes_span),
|
|
span_end: Some(minutes_span),
|
|
})
|
|
- } else if seconds >= Second::per(Minute) as _ {
|
|
+ } else if seconds >= Second::per(Minute).cast_signed() {
|
|
Err(Error::InvalidComponent {
|
|
name: "second",
|
|
value: seconds.to_string(),
|
|
diff --git a/vendor/time/.cargo-checksum.json b/vendor/time/.cargo-checksum.json
|
|
index 410f8fb..9997a5d 100644
|
|
--- a/vendor/time/.cargo-checksum.json
|
|
+++ b/vendor/time/.cargo-checksum.json
|
|
@@ -1 +1 @@
|
|
-{"files":{"Cargo.toml":"f05ee952cdbcdad4120053c1c990b0771102b1cf2a27cbb43af5d6384384afbc","LICENSE-Apache":"b8929fea28678da67251fb2daf9438f67503814211051861612441806d8edb05","LICENSE-MIT":"04620bf27e4a643dd47bf27652320c205acdb776c1f9f24bb8c3bfaba10804c5","README.md":"36c735ebe90cdc962dec7e240607a052088697d0cefd555f093746039b0943cd","src/date.rs":"e7416c75800456e626f9c85b51775d5101d3bc89ca095b370cd8791f41e4f240","src/date_time.rs":"fbc24c3b047ba56f7d5fc33ce8914f6f6ee70c495ce5336fa21dd20bbdecbcb6","src/duration.rs":"a191b4a0e86e83b3108a707341b7c55c6df875ab5ae2fb41a7674a98d2e19c41","src/error/component_range.rs":"26a1aa4ea2d0f9887efcbe9584d5aa14b1e5d37525a52dc9f18e1e282599625d","src/error/conversion_range.rs":"972abb765370070de01e2fc2e1bb1e80808a069e6213577d7beaca02e1d707c3","src/error/different_variant.rs":"107bef7b3addd7108b36a2da8389f611d4482f34a5b63429841141e05c8cb30c","src/error/format.rs":"d87846c2ac62dec421402ea21e5d2a8d73add6658df4ac914067a4b43cb0ef20","src/error/indeterminate_offset.rs":"1f52f9ea107847fa781399cfcc8046451d70155fb497486c80b2138f82782941","src/error/invalid_format_description.rs":"cf617348b55d9c3273060fa2d99bd4eda215452270025f2b6caef6ef9f387af5","src/error/invalid_variant.rs":"b653a3e6e902f06cb9f2e0366c4da84b92e8bdb03164c2f8cb15fe66415706e4","src/error/mod.rs":"a30edbd2cdc701d0327291ef1201aa1531ab8bb1a1318945085ab71f8918bb16","src/error/parse.rs":"a3f23c10cab2e4ce159c5b3d5774d54214bd0098b70a59c48a2407777cdee9e5","src/error/parse_from_description.rs":"2de1f5b5af3d9bb358cee1c66a2721a78ee99f0ee5e0c06f159e62de7a294a5f","src/error/try_from_parsed.rs":"8c227be52653a1d33af01a8024c0fc56f1f9803f08ef01487a7eaa5833adbb57","src/ext.rs":"3f4a1a0fc601b06c3b068c3bf4060d427131501084b3e52e092ca0de432490b7","src/format_description/borrowed_format_item.rs":"afab66e65a84895751d3557fc5b8a3a5e63f9c483a6a534aa4f86fd2a5145f0b","src/format_description/component.rs":"b65c0ca896ea6ec8dbfc7570c69849c88cbba6031a2847dcfdce06d721a59397","src/format_description/mod.rs":"955a227e9bb13e3085a43457bf8028085db92c0266b6573ddf1e12df3b937c0f","src/format_description/modifier.rs":"450e6fc64353f80304c2b616bf3e8c58f1ae02e0a2875e946cf0ea27e87a4e10","src/format_description/owned_format_item.rs":"419f5354bf504562c9225dfe90b61eee9bc959211a86a327197b4f54283da775","src/format_description/parse/ast.rs":"f96b423629e265d85f4068c7590a27405cb5b4275bf9f547e674f337b281a58e","src/format_description/parse/format_item.rs":"959e8f3112fd774fb71f541216e960ff64ceb84767700c77997d80fb9dddc6e5","src/format_description/parse/lexer.rs":"c10105640a618e1e850eb6e4fd888c47d881b3f85bde691fdf204199a693e127","src/format_description/parse/mod.rs":"210cd68a37b5cbbc6a6e3b3d5161f03ad94b2902bb01899d0c02d0278f420c8c","src/format_description/well_known/iso8601.rs":"e2ed825acffbd66d8798c899c14d32e3f73fea95e8cff324199081034a5b7a2f","src/format_description/well_known/iso8601/adt_hack.rs":"8f1d5f4a0959070ab96343868086adfa6fa3f5a5823f50a111c824b4a9bcd39b","src/format_description/well_known/rfc2822.rs":"36c23394724ae12250d4193cab26887a6ff8f82ca441ea6b0d03c4f1c928b3dd","src/format_description/well_known/rfc3339.rs":"1a6318dffd3ebb6ac7cf96eae3d9b1eb44b1089cf4284fa6a7e935c6fcf1b43c","src/formatting/formattable.rs":"81c99395d5366ab16d0251af705ce0a7a68d77119cb7d563ea2cf096a5b7da33","src/formatting/iso8601.rs":"5b17b9b39747af50e06d2c93615b293b132cd189524af42811a0ddeb18b27166","src/formatting/mod.rs":"48f2894e390432d0d99a4ba07bd9f5b409995089bd3edb14497976dddfdd4f82","src/instant.rs":"72ea1cba450d8cdc12a7600e54d51e5ad63de38039b74daaf01f1a077111eb10","src/internal_macros.rs":"b8767d91b5b1c5a8a2221eec2876b5361451dce90cea2cb842a7112b91e8e7b5","src/lib.rs":"954277e5cb6b846d2eee77ff85993aa668904382280476eb63f6d53eeb030b72","src/macros.rs":"eb9e02a1f97bb8befab7bc27c937136817e4f65e0b3e040a81394ae938980558","src/month.rs":"cee05aaad0088a38f0bec22dc913590c18d3bc74208aa72394512424677ffd25","src/offset_date_time.rs":"b29c929042a99e3d63ef112a80799c5b60e703514c0bcf215f46e309f540a2c1","src/parsing/combinator/mod.rs":"b342fbd95dd986309d81e8910363920ba6db00958b459f6d97f57da3ae3e550d","src/parsing/combinator/rfc/iso8601.rs":"13289a0d58de273327830a3001167a8964edc5045486301efdf3ddc2e4079c32","src/parsing/combinator/rfc/mod.rs":"f30b75d248f5ae92c27646d504703f5489185afb76c998cc4375437b3d15c822","src/parsing/combinator/rfc/rfc2234.rs":"08e2813c6d40c0dae881875fe0417ae06886c73679256587e33186e46b3c3bae","src/parsing/combinator/rfc/rfc2822.rs":"2aff3a6a2778bc806031cff92ad2f43f0874620b5d484b5b39ee2d2507212f06","src/parsing/component.rs":"616cd06d429ac9efa8313277ed6096347fcec07cc89e3a46f0742abdd4662674","src/parsing/iso8601.rs":"07b2aacb8d24e865d5816c329eff0f8f1b55ad2bda743d0b0f7c724b2f7ec64a","src/parsing/mod.rs":"37082ac824c6c3f4900766a0a3140dc7aa46b3f85cb6098f11da7da333e421b0","src/parsing/parsable.rs":"01b10814c1036113fb4f3da3a8568e64b2f46a68436f5245c3026255fbc49f78","src/parsing/parsed.rs":"9f3825d50a6d62d282193881b4434812dc66b3a4b654a478cd7a53c002ac1f36","src/parsing/shim.rs":"46efc374bc3129e28936a850143fff8e42aafe10c69ebbb904195aaeca26adc9","src/primitive_date_time.rs":"296c62a0e8359eb0a30b379b498e29907e9729113482146ce7ea5ed5ff23591d","src/quickcheck.rs":"56146c3de1f303e9df46ae6e929b1396618ee39f0f30da5e43a3f9ae6dfd2fd8","src/rand.rs":"dcedb2473e240c46de00aa4b156d66cb755da9d5fd04adaedb3682cb6a12218f","src/serde/iso8601.rs":"997bbf4fe4018f8fdc9335ac863b543fb24a58b2dee394615505a24311331516","src/serde/mod.rs":"3f7647ac257e87cfbc4820332be43dd575fc082c74f322343662b189fb5c7619","src/serde/rfc2822.rs":"fe97aa1311037a362eb477fe8c6729b3b85ff2d0afab7148f10f64d109081f90","src/serde/rfc3339.rs":"9835c8b8fb24b53657769b81a71188fe4261e5869917779e1702b3a0aa854654","src/serde/timestamp.rs":"30971ad5d1fef11e396eee48d476b828ed4e99f6eac587383b864dd95c120fe4","src/serde/visitor.rs":"973ba2826134d09b109ef7c09a80c48ab724bd9051706bfde85e1ba930e00134","src/sys/local_offset_at/imp.rs":"4b6e57f02566364270ac9b7e1540290a5658a296f7e911f988264d103e420326","src/sys/local_offset_at/mod.rs":"95b042824b414b3021eda2bcf0821afc529bfd8d4cfcad0b893edb197e48461b","src/sys/local_offset_at/unix.rs":"ce02c86c4b4588ef3ebfa56bc82ff09e83677fc7679e61843b0bd80c4308fcbc","src/sys/local_offset_at/wasm_js.rs":"95baec44baaa4be78925fcbab1551e45b1884e59bdb448692ccdd6b251645c2c","src/sys/local_offset_at/windows.rs":"180d88935d4621a0b3b76d6b0c4bf429f47c234a8d1cea5b58d1f1a5a8c3397d","src/sys/mod.rs":"0a43797e55e986233a71f1cc4b3a21997da42bc15db7d912373296cd535e49bc","src/tests.rs":"3e4b8f398772712ace2c6928f09582740e90df23fa01961f0af490d2f1247120","src/time.rs":"02e022b8b0137ea1cec53f8776121b7beb1030522b4a65c3ffa234807a18e797","src/utc_offset.rs":"af14cea10bc48e16d5c6f7b8208fd3a2aedb338c390e67ba0c099616524ace3a","src/util.rs":"1fff6c7d712a4d2665cca55db9c142185cc13afa20f925912cb85abbcc366938","src/weekday.rs":"76ed201232f03077474c05e53f34b0403ead637c40a5228b9b61b342048f2917"},"package":"c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5"}
|
|
\ No newline at end of file
|
|
+{"files":{"Cargo.toml":"bd60027c57b6255a65c218363b8e018ccbc7339af846b30ecc14c7781e9dc701","LICENSE-Apache":"edd65bdd88957a205c47d53fa499eed8865a70320f0f03f6391668cb304ea376","LICENSE-MIT":"231c837c45eb53f108fb48929e488965bc4fcc14e9ea21d35f50e6b99d98685b","README.md":"36c735ebe90cdc962dec7e240607a052088697d0cefd555f093746039b0943cd","src/date.rs":"a20df0cc036d1c09f5554bf2c52a7dc7ceb2d08af355a5079282b3660c1bf062","src/duration.rs":"dc394786d19a1fae779ebfbd14e1502a5701756a500224fc82f116ecfeef39b2","src/error/component_range.rs":"26a1aa4ea2d0f9887efcbe9584d5aa14b1e5d37525a52dc9f18e1e282599625d","src/error/conversion_range.rs":"972abb765370070de01e2fc2e1bb1e80808a069e6213577d7beaca02e1d707c3","src/error/different_variant.rs":"107bef7b3addd7108b36a2da8389f611d4482f34a5b63429841141e05c8cb30c","src/error/format.rs":"d87846c2ac62dec421402ea21e5d2a8d73add6658df4ac914067a4b43cb0ef20","src/error/indeterminate_offset.rs":"1f52f9ea107847fa781399cfcc8046451d70155fb497486c80b2138f82782941","src/error/invalid_format_description.rs":"cf617348b55d9c3273060fa2d99bd4eda215452270025f2b6caef6ef9f387af5","src/error/invalid_variant.rs":"b653a3e6e902f06cb9f2e0366c4da84b92e8bdb03164c2f8cb15fe66415706e4","src/error/mod.rs":"a30edbd2cdc701d0327291ef1201aa1531ab8bb1a1318945085ab71f8918bb16","src/error/parse.rs":"a3f23c10cab2e4ce159c5b3d5774d54214bd0098b70a59c48a2407777cdee9e5","src/error/parse_from_description.rs":"2de1f5b5af3d9bb358cee1c66a2721a78ee99f0ee5e0c06f159e62de7a294a5f","src/error/try_from_parsed.rs":"8c227be52653a1d33af01a8024c0fc56f1f9803f08ef01487a7eaa5833adbb57","src/ext/digit_count.rs":"d32af3cac57077870f6b31c5bd6e0da3a530a7c713aaebdcd27125d9fd8857a3","src/ext/instant.rs":"7598e0fab29b6a9c2a7d1f5fa761ed7d2d8b54deac801189fec652a358ed7e08","src/ext/mod.rs":"dc70d230a170ddd1bf7798703d9ff7cac419aaadc82b5f8dbf46d5320322e2c5","src/ext/numerical_duration.rs":"d6c74898e4f6025158ef8daf35abe53268161db2c18d12e718fec17cfe442d6d","src/ext/numerical_std_duration.rs":"0dc24fc48c3eb94c22aca75423e652e13322262c63edaf5393a28bc8470d6082","src/format_description/borrowed_format_item.rs":"529cb5c91a0ff08a6f8615ccf1289c9b5f01996f691db1bd1cb5a451c25ead4c","src/format_description/component.rs":"b65c0ca896ea6ec8dbfc7570c69849c88cbba6031a2847dcfdce06d721a59397","src/format_description/mod.rs":"640958320fcda04287a84767b6fe2f941a0e5f7498b58a531f6dffbfd0ed1757","src/format_description/modifier.rs":"450e6fc64353f80304c2b616bf3e8c58f1ae02e0a2875e946cf0ea27e87a4e10","src/format_description/owned_format_item.rs":"8834a705f3f0c61a1851ffb4b897766b4216ae2dbac6ae34ad0d4aa3fd46a064","src/format_description/parse/ast.rs":"f96b423629e265d85f4068c7590a27405cb5b4275bf9f547e674f337b281a58e","src/format_description/parse/format_item.rs":"0a5b013e5dbb226a90bcda533866d9a141d1270412f44a42ba0dc053479e782c","src/format_description/parse/lexer.rs":"fae06f81ace377f716857b60bb5c0d6591123478a99b4c9823f4b19bb3f73af1","src/format_description/parse/mod.rs":"99ac90c3cdb73ce52b3e2866c4f3f7dae0557b88bce5846161c901e11fbd80c4","src/format_description/well_known/iso8601.rs":"30b2f495044ab4e1f3ff6a317a8b4ca2ffb46b7cc23428eca8b685c0f16518cc","src/format_description/well_known/iso8601/adt_hack.rs":"8f1d5f4a0959070ab96343868086adfa6fa3f5a5823f50a111c824b4a9bcd39b","src/format_description/well_known/rfc2822.rs":"36c23394724ae12250d4193cab26887a6ff8f82ca441ea6b0d03c4f1c928b3dd","src/format_description/well_known/rfc3339.rs":"1a6318dffd3ebb6ac7cf96eae3d9b1eb44b1089cf4284fa6a7e935c6fcf1b43c","src/formatting/formattable.rs":"7cd6416af947b92316b6505c2d3c45b163c87257302ae18868b1f83fbba034a4","src/formatting/iso8601.rs":"1d265461a515406c1253350b5eb870b5416f9ce76cdf96a8fbfb7c4b57dcb623","src/formatting/mod.rs":"115af930b598ed77a9b55ba8f7d89befefb1f21cec960ebd2c315188a25ba07d","src/instant.rs":"96a5aba377443945c1a75d669347711c40b33ea842f7d609eb3a7572b6ce64bf","src/internal_macros.rs":"cf2479614cc66f3b9c533f5f5c4584fe90136c7ad4d0c2137d5aa386ffa5319f","src/lib.rs":"f2fdfeaf6f85d71cbb875d54645964997a741d9c012cecdfda9c92ee82f01d15","src/macros.rs":"bea9e61c00ac2b523357300a51830d32e46f03456fc03d18fe26928042e10a2d","src/month.rs":"cee05aaad0088a38f0bec22dc913590c18d3bc74208aa72394512424677ffd25","src/offset_date_time.rs":"7d2a476c69c7f3c16c466347a9dff2c6d9687e82044b7c39034218f14adfa404","src/parsing/combinator/mod.rs":"e49d14f7d0c38a847d9f5f2e63d466464641d365f1d39c48d1a455ebe6632ec5","src/parsing/combinator/rfc/iso8601.rs":"8b819a8e3ef4b160b1bce94cad6534e3c0acbeef98cfc494606815468781c19a","src/parsing/combinator/rfc/mod.rs":"f30b75d248f5ae92c27646d504703f5489185afb76c998cc4375437b3d15c822","src/parsing/combinator/rfc/rfc2234.rs":"08e2813c6d40c0dae881875fe0417ae06886c73679256587e33186e46b3c3bae","src/parsing/combinator/rfc/rfc2822.rs":"2aff3a6a2778bc806031cff92ad2f43f0874620b5d484b5b39ee2d2507212f06","src/parsing/component.rs":"32d69c4f86e3a2e90dffbd74af8b19ea25dbeaa6f60aa89637f3988d64fd7967","src/parsing/iso8601.rs":"6cc42738e8e8ed5b2800b0fbdd85c120705ec3452483f625c75a5a1e5bf0fcc9","src/parsing/mod.rs":"7d790f512710dc33b9f6f51e4237c04812aafd7d68710df01d02d755062568d7","src/parsing/parsable.rs":"8fa8f9b2653fa5e911a6528fd3f62cd371e3b2bb2c2727447fd2a33381ffed68","src/parsing/parsed.rs":"32289f2495ad6826eab3c745c8df1c2590510c88bb4d7c21b2dbc6bfd664ed35","src/parsing/shim.rs":"46efc374bc3129e28936a850143fff8e42aafe10c69ebbb904195aaeca26adc9","src/primitive_date_time.rs":"faca737cbe28bce420dfb4468021f46968c29abdde449479af225e597441c96e","src/quickcheck.rs":"09baaccea54f77cc60d1c43a726275d15db42e1c8b4ec157d4417d3cded36762","src/rand.rs":"dcedb2473e240c46de00aa4b156d66cb755da9d5fd04adaedb3682cb6a12218f","src/serde/iso8601.rs":"997bbf4fe4018f8fdc9335ac863b543fb24a58b2dee394615505a24311331516","src/serde/mod.rs":"99a93f87c0dd35f818af72228ca74a0952ce4db4d426ddf7c21a0220caee890e","src/serde/rfc2822.rs":"fe97aa1311037a362eb477fe8c6729b3b85ff2d0afab7148f10f64d109081f90","src/serde/rfc3339.rs":"9835c8b8fb24b53657769b81a71188fe4261e5869917779e1702b3a0aa854654","src/serde/timestamp/microseconds.rs":"7b8a0f6e455ddb6c50ed4a8473ea68cf9aacb31af36ccc058b68fa3bb5f3246d","src/serde/timestamp/milliseconds.rs":"df995f05f340f0429697269aa152a39b0beca45e1b4d8e60f4a6bb27f09a4d88","src/serde/timestamp/mod.rs":"20ddd158fe5e491f9f7e74ef074d2bb10c8b02b1fcd399c0429fd796d799aa01","src/serde/timestamp/nanoseconds.rs":"a46b1e60e8b19792a26ebdab33cba53db95cb13e3c4d9675a17b1491e9fb2940","src/serde/visitor.rs":"973ba2826134d09b109ef7c09a80c48ab724bd9051706bfde85e1ba930e00134","src/sys/local_offset_at/imp.rs":"4b6e57f02566364270ac9b7e1540290a5658a296f7e911f988264d103e420326","src/sys/local_offset_at/mod.rs":"95b042824b414b3021eda2bcf0821afc529bfd8d4cfcad0b893edb197e48461b","src/sys/local_offset_at/unix.rs":"ce02c86c4b4588ef3ebfa56bc82ff09e83677fc7679e61843b0bd80c4308fcbc","src/sys/local_offset_at/wasm_js.rs":"7cdacf5548a89a00265764ef07c1abb2ea1a3211f1ec720932b066f1d18b2f20","src/sys/local_offset_at/windows.rs":"90c16515d7ac29961bd0b8af92e38c7999f260bfd3438c9935fee65e8c0cc1e9","src/sys/mod.rs":"0a43797e55e986233a71f1cc4b3a21997da42bc15db7d912373296cd535e49bc","src/tests.rs":"c858af9559784ec4fe82ddcd0f4029b1c519ef7699288995d8fac007feada859","src/time.rs":"418ae2964af95fbbfba070598b09e36475846792c1916d990e20f5481e0ea9e7","src/utc_offset.rs":"0e51f4ebb740f95b0f2b2d956b72ff49dcc993b81e4d14d1d1809fb355be5817","src/util.rs":"34b4d98803dd99d0db813d0e3cda9dcbb235a8315b6cf1438e0048d14d76663a","src/weekday.rs":"76ed201232f03077474c05e53f34b0403ead637c40a5228b9b61b342048f2917"},"package":"5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885"}
|
|
\ No newline at end of file
|
|
diff --git a/vendor/time/Cargo.toml b/vendor/time/Cargo.toml
|
|
index 112b9d9..8f1996f 100644
|
|
--- a/vendor/time/Cargo.toml
|
|
+++ b/vendor/time/Cargo.toml
|
|
@@ -13,7 +13,7 @@
|
|
edition = "2021"
|
|
rust-version = "1.67.0"
|
|
name = "time"
|
|
-version = "0.3.30"
|
|
+version = "0.3.36"
|
|
authors = [
|
|
"Jacob Pratt <open-source@jhpratt.dev>",
|
|
"Time contributors",
|
|
@@ -71,6 +71,9 @@ default-features = false
|
|
version = "1.0.1"
|
|
optional = true
|
|
|
|
+[dependencies.num-conv]
|
|
+version = "0.1.0"
|
|
+
|
|
[dependencies.powerfmt]
|
|
version = "0.2.0"
|
|
default-features = false
|
|
@@ -94,9 +97,12 @@ default-features = false
|
|
version = "=0.1.2"
|
|
|
|
[dependencies.time-macros]
|
|
-version = "=0.2.15"
|
|
+version = "=0.2.18"
|
|
optional = true
|
|
|
|
+[dev-dependencies.num-conv]
|
|
+version = "0.1.0"
|
|
+
|
|
[dev-dependencies.quickcheck_macros]
|
|
version = "1.0.0"
|
|
|
|
@@ -123,7 +129,7 @@ version = "1.0.68"
|
|
version = "1.0.126"
|
|
|
|
[dev-dependencies.time-macros]
|
|
-version = "=0.2.15"
|
|
+version = "=0.2.18"
|
|
|
|
[features]
|
|
alloc = ["serde?/alloc"]
|
|
@@ -189,3 +195,87 @@ optional = true
|
|
[target."cfg(target_family = \"unix\")".dependencies.num_threads]
|
|
version = "0.1.2"
|
|
optional = true
|
|
+
|
|
+[lints.clippy]
|
|
+all = "warn"
|
|
+alloc-instead-of-core = "deny"
|
|
+dbg-macro = "warn"
|
|
+decimal-literal-representation = "warn"
|
|
+explicit-auto-deref = "warn"
|
|
+get-unwrap = "warn"
|
|
+manual-let-else = "warn"
|
|
+missing-docs-in-private-items = "warn"
|
|
+missing-enforced-import-renames = "warn"
|
|
+nursery = "warn"
|
|
+obfuscated-if-else = "warn"
|
|
+print-stdout = "warn"
|
|
+semicolon-outside-block = "warn"
|
|
+std-instead-of-core = "deny"
|
|
+todo = "warn"
|
|
+undocumented-unsafe-blocks = "deny"
|
|
+unimplemented = "warn"
|
|
+uninlined-format-args = "warn"
|
|
+unnested-or-patterns = "warn"
|
|
+unwrap-in-result = "warn"
|
|
+unwrap-used = "warn"
|
|
+use-debug = "warn"
|
|
+
|
|
+[lints.clippy.option-if-let-else]
|
|
+level = "allow"
|
|
+priority = 1
|
|
+
|
|
+[lints.clippy.redundant-pub-crate]
|
|
+level = "allow"
|
|
+priority = 1
|
|
+
|
|
+[lints.rust]
|
|
+ambiguous-glob-reexports = "deny"
|
|
+clashing-extern-declarations = "deny"
|
|
+const-item-mutation = "deny"
|
|
+deref-nullptr = "deny"
|
|
+drop-bounds = "deny"
|
|
+future-incompatible = "deny"
|
|
+hidden-glob-reexports = "deny"
|
|
+improper-ctypes = "deny"
|
|
+improper-ctypes-definitions = "deny"
|
|
+invalid-from-utf8 = "deny"
|
|
+invalid-macro-export-arguments = "deny"
|
|
+invalid-nan-comparisons = "deny"
|
|
+invalid-reference-casting = "deny"
|
|
+invalid-value = "deny"
|
|
+keyword-idents = "warn"
|
|
+let-underscore = "warn"
|
|
+macro-use-extern-crate = "warn"
|
|
+meta-variable-misuse = "warn"
|
|
+missing-abi = "warn"
|
|
+missing-copy-implementations = "warn"
|
|
+missing-debug-implementations = "warn"
|
|
+missing-docs = "warn"
|
|
+named-arguments-used-positionally = "deny"
|
|
+non-ascii-idents = "deny"
|
|
+noop-method-call = "warn"
|
|
+opaque-hidden-inferred-bound = "deny"
|
|
+overlapping-range-endpoints = "deny"
|
|
+single-use-lifetimes = "warn"
|
|
+suspicious-double-ref-op = "deny"
|
|
+temporary-cstring-as-ptr = "deny"
|
|
+trivial-casts = "warn"
|
|
+trivial-numeric-casts = "warn"
|
|
+unconditional-recursion = "deny"
|
|
+unnameable-test-items = "deny"
|
|
+unreachable-pub = "warn"
|
|
+unsafe-op-in-unsafe-fn = "deny"
|
|
+unstable-syntax-pre-expansion = "deny"
|
|
+unused = "warn"
|
|
+unused-import-braces = "warn"
|
|
+unused-lifetimes = "warn"
|
|
+unused-qualifications = "warn"
|
|
+variant-size-differences = "warn"
|
|
+
|
|
+[lints.rust.unstable-name-collisions]
|
|
+level = "warn"
|
|
+priority = 1
|
|
+
|
|
+[lints.rustdoc]
|
|
+private-doc-tests = "warn"
|
|
+unescaped-backticks = "warn"
|
|
diff --git a/vendor/time/LICENSE-Apache b/vendor/time/LICENSE-Apache
|
|
index 7646f21..c763a0c 100644
|
|
--- a/vendor/time/LICENSE-Apache
|
|
+++ b/vendor/time/LICENSE-Apache
|
|
@@ -187,7 +187,7 @@
|
|
same "printed page" as the copyright notice for easier
|
|
identification within third-party archives.
|
|
|
|
- Copyright 2022 Jacob Pratt et al.
|
|
+ Copyright 2024 Jacob Pratt et al.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
diff --git a/vendor/time/LICENSE-MIT b/vendor/time/LICENSE-MIT
|
|
index a11a755..5cc097f 100644
|
|
--- a/vendor/time/LICENSE-MIT
|
|
+++ b/vendor/time/LICENSE-MIT
|
|
@@ -1,4 +1,4 @@
|
|
-Copyright (c) 2022 Jacob Pratt et al.
|
|
+Copyright (c) 2024 Jacob Pratt et al.
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
diff --git a/vendor/time/src/date.rs b/vendor/time/src/date.rs
|
|
index 5e62dfa..ed443c5 100644
|
|
--- a/vendor/time/src/date.rs
|
|
+++ b/vendor/time/src/date.rs
|
|
@@ -1,5 +1,7 @@
|
|
//! The [`Date`] struct and its associated `impl`s.
|
|
|
|
+#[cfg(feature = "formatting")]
|
|
+use alloc::string::String;
|
|
use core::num::NonZeroI32;
|
|
use core::ops::{Add, Sub};
|
|
use core::time::Duration as StdDuration;
|
|
@@ -8,6 +10,7 @@ use core::{cmp, fmt};
|
|
use std::io;
|
|
|
|
use deranged::RangedI32;
|
|
+use num_conv::prelude::*;
|
|
use powerfmt::ext::FormatterExt;
|
|
use powerfmt::smart_display::{self, FormatterOptions, Metadata, SmartDisplay};
|
|
|
|
@@ -119,7 +122,7 @@ impl Date {
|
|
1..=28 => {}
|
|
29..=31 if day <= days_in_year_month(year, month) => {}
|
|
_ => {
|
|
- return Err(crate::error::ComponentRange {
|
|
+ return Err(error::ComponentRange {
|
|
name: "day",
|
|
minimum: 1,
|
|
maximum: days_in_year_month(year, month) as _,
|
|
@@ -157,7 +160,7 @@ impl Date {
|
|
1..=365 => {}
|
|
366 if is_leap_year(year) => {}
|
|
_ => {
|
|
- return Err(crate::error::ComponentRange {
|
|
+ return Err(error::ComponentRange {
|
|
name: "ordinal",
|
|
minimum: 1,
|
|
maximum: days_in_year(year) as _,
|
|
@@ -194,7 +197,7 @@ impl Date {
|
|
1..=52 => {}
|
|
53 if week <= weeks_in_year(year) => {}
|
|
_ => {
|
|
- return Err(crate::error::ComponentRange {
|
|
+ return Err(error::ComponentRange {
|
|
name: "week",
|
|
minimum: 1,
|
|
maximum: weeks_in_year(year) as _,
|
|
@@ -1131,7 +1134,7 @@ impl Date {
|
|
1..=28 => {}
|
|
29..=31 if day <= days_in_year_month(self.year(), self.month()) => {}
|
|
_ => {
|
|
- return Err(crate::error::ComponentRange {
|
|
+ return Err(error::ComponentRange {
|
|
name: "day",
|
|
minimum: 1,
|
|
maximum: days_in_year_month(self.year(), self.month()) as _,
|
|
@@ -1149,6 +1152,34 @@ impl Date {
|
|
)
|
|
})
|
|
}
|
|
+
|
|
+ /// Replace the day of the year.
|
|
+ ///
|
|
+ /// ```rust
|
|
+ /// # use time_macros::date;
|
|
+ /// assert_eq!(date!(2022 - 049).replace_ordinal(1), Ok(date!(2022 - 001)));
|
|
+ /// assert!(date!(2022 - 049).replace_ordinal(0).is_err()); // 0 isn't a valid ordinal
|
|
+ /// assert!(date!(2022 - 049).replace_ordinal(366).is_err()); // 2022 isn't a leap year
|
|
+ /// ````
|
|
+ #[must_use = "This method does not mutate the original `Date`."]
|
|
+ pub const fn replace_ordinal(self, ordinal: u16) -> Result<Self, error::ComponentRange> {
|
|
+ match ordinal {
|
|
+ 1..=365 => {}
|
|
+ 366 if is_leap_year(self.year()) => {}
|
|
+ _ => {
|
|
+ return Err(error::ComponentRange {
|
|
+ name: "ordinal",
|
|
+ minimum: 1,
|
|
+ maximum: days_in_year(self.year()) as _,
|
|
+ value: ordinal as _,
|
|
+ conditional_range: true,
|
|
+ });
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // Safety: `ordinal` is in range.
|
|
+ Ok(unsafe { Self::__from_ordinal_date_unchecked(self.year(), ordinal) })
|
|
+ }
|
|
// endregion replacement
|
|
}
|
|
|
|
@@ -1337,10 +1368,10 @@ impl SmartDisplay for Date {
|
|
false
|
|
};
|
|
|
|
- let formatted_width = year_width as usize
|
|
+ let formatted_width = year_width.extend::<usize>()
|
|
+ smart_display::padded_width_of!(
|
|
"-",
|
|
- month as u8 => width(2),
|
|
+ u8::from(month) => width(2),
|
|
"-",
|
|
day => width(2),
|
|
);
|
|
@@ -1352,7 +1383,7 @@ impl SmartDisplay for Date {
|
|
year_width,
|
|
display_sign,
|
|
year,
|
|
- month: month as u8,
|
|
+ month: u8::from(month),
|
|
day,
|
|
},
|
|
)
|
|
@@ -1370,7 +1401,7 @@ impl SmartDisplay for Date {
|
|
month,
|
|
day,
|
|
} = *metadata;
|
|
- let year_width = year_width as usize;
|
|
+ let year_width = year_width.extend();
|
|
|
|
if display_sign {
|
|
f.pad_with_width(
|
|
@@ -1403,6 +1434,9 @@ impl fmt::Debug for Date {
|
|
impl Add<Duration> for Date {
|
|
type Output = Self;
|
|
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if an overflow occurs.
|
|
fn add(self, duration: Duration) -> Self::Output {
|
|
self.checked_add(duration)
|
|
.expect("overflow adding duration to date")
|
|
@@ -1412,6 +1446,9 @@ impl Add<Duration> for Date {
|
|
impl Add<StdDuration> for Date {
|
|
type Output = Self;
|
|
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if an overflow occurs.
|
|
fn add(self, duration: StdDuration) -> Self::Output {
|
|
self.checked_add_std(duration)
|
|
.expect("overflow adding duration to date")
|
|
@@ -1423,6 +1460,9 @@ impl_add_assign!(Date: Duration, StdDuration);
|
|
impl Sub<Duration> for Date {
|
|
type Output = Self;
|
|
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if an overflow occurs.
|
|
fn sub(self, duration: Duration) -> Self::Output {
|
|
self.checked_sub(duration)
|
|
.expect("overflow subtracting duration from date")
|
|
@@ -1432,6 +1472,9 @@ impl Sub<Duration> for Date {
|
|
impl Sub<StdDuration> for Date {
|
|
type Output = Self;
|
|
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if an overflow occurs.
|
|
fn sub(self, duration: StdDuration) -> Self::Output {
|
|
self.checked_sub_std(duration)
|
|
.expect("overflow subtracting duration from date")
|
|
@@ -1444,7 +1487,7 @@ impl Sub for Date {
|
|
type Output = Duration;
|
|
|
|
fn sub(self, other: Self) -> Self::Output {
|
|
- Duration::days((self.to_julian_day() - other.to_julian_day()) as _)
|
|
+ Duration::days((self.to_julian_day() - other.to_julian_day()).extend())
|
|
}
|
|
}
|
|
// endregion trait impls
|
|
diff --git a/vendor/time/src/date_time.rs b/vendor/time/src/date_time.rs
|
|
deleted file mode 100644
|
|
index 27f07ce..0000000
|
|
--- a/vendor/time/src/date_time.rs
|
|
+++ /dev/null
|
|
@@ -1,1248 +0,0 @@
|
|
-//! The [`DateTime`] struct and its associated `impl`s.
|
|
-
|
|
-// TODO(jhpratt) Document everything before making public.
|
|
-#![allow(clippy::missing_docs_in_private_items)]
|
|
-// This is intentional, as the struct will likely be exposed at some point.
|
|
-#![allow(unreachable_pub)]
|
|
-
|
|
-use core::cmp::Ordering;
|
|
-use core::fmt;
|
|
-use core::hash::{Hash, Hasher};
|
|
-use core::mem::size_of;
|
|
-use core::ops::{Add, AddAssign, Sub, SubAssign};
|
|
-use core::time::Duration as StdDuration;
|
|
-#[cfg(feature = "formatting")]
|
|
-use std::io;
|
|
-#[cfg(feature = "std")]
|
|
-use std::time::SystemTime;
|
|
-
|
|
-use deranged::RangedI64;
|
|
-use powerfmt::ext::FormatterExt;
|
|
-use powerfmt::smart_display::{self, FormatterOptions, Metadata, SmartDisplay};
|
|
-
|
|
-use crate::convert::*;
|
|
-use crate::date::{MAX_YEAR, MIN_YEAR};
|
|
-#[cfg(feature = "formatting")]
|
|
-use crate::formatting::Formattable;
|
|
-use crate::internal_macros::{
|
|
- bug, cascade, const_try, const_try_opt, div_floor, ensure_ranged, expect_opt, impl_add_assign,
|
|
- impl_sub_assign,
|
|
-};
|
|
-#[cfg(feature = "parsing")]
|
|
-use crate::parsing::{Parsable, Parsed};
|
|
-use crate::{error, util, Date, Duration, Month, Time, UtcOffset, Weekday};
|
|
-
|
|
-#[allow(missing_debug_implementations, missing_copy_implementations)]
|
|
-pub(crate) mod offset_kind {
|
|
- pub enum None {}
|
|
- pub enum Fixed {}
|
|
-}
|
|
-
|
|
-pub(crate) use sealed::MaybeOffset;
|
|
-use sealed::*;
|
|
-mod sealed {
|
|
- use super::*;
|
|
-
|
|
- /// A type that is guaranteed to be either `()` or [`UtcOffset`].
|
|
- ///
|
|
- /// **Do not** add any additional implementations of this trait.
|
|
- #[allow(unreachable_pub)] // intentional
|
|
- pub trait MaybeOffsetType {}
|
|
- impl MaybeOffsetType for () {}
|
|
- impl MaybeOffsetType for UtcOffset {}
|
|
-
|
|
- pub trait MaybeOffset: Sized {
|
|
- /// The offset type as it is stored in memory.
|
|
- #[cfg(feature = "quickcheck")]
|
|
- type MemoryOffsetType: Copy + MaybeOffsetType + quickcheck::Arbitrary;
|
|
- #[cfg(not(feature = "quickcheck"))]
|
|
- type MemoryOffsetType: Copy + MaybeOffsetType;
|
|
-
|
|
- /// The offset type as it should be thought about.
|
|
- ///
|
|
- /// For example, a `DateTime<Utc>` has a logical offset type of [`UtcOffset`], but does not
|
|
- /// actually store an offset in memory.
|
|
- type LogicalOffsetType: Copy + MaybeOffsetType;
|
|
-
|
|
- /// Required to be `Self`. Used for bound equality.
|
|
- type Self_;
|
|
-
|
|
- /// True if and only if `Self::LogicalOffsetType` is `UtcOffset`.
|
|
- const HAS_LOGICAL_OFFSET: bool =
|
|
- size_of::<Self::LogicalOffsetType>() == size_of::<UtcOffset>();
|
|
- /// True if and only if `Self::MemoryOffsetType` is `UtcOffset`.
|
|
- const HAS_MEMORY_OFFSET: bool =
|
|
- size_of::<Self::MemoryOffsetType>() == size_of::<UtcOffset>();
|
|
-
|
|
- /// `Some` if and only if the logical UTC offset is statically known.
|
|
- // TODO(jhpratt) When const trait impls are stable, this can be removed in favor of
|
|
- // `.as_offset_opt()`.
|
|
- const STATIC_OFFSET: Option<UtcOffset>;
|
|
-
|
|
- #[cfg(feature = "parsing")]
|
|
- fn try_from_parsed(parsed: Parsed) -> Result<Self::MemoryOffsetType, error::TryFromParsed>;
|
|
- }
|
|
-
|
|
- // Traits to indicate whether a `MaybeOffset` has a logical offset type of `UtcOffset` or not.
|
|
-
|
|
- pub trait HasLogicalOffset: MaybeOffset<LogicalOffsetType = UtcOffset> {}
|
|
- impl<T: MaybeOffset<LogicalOffsetType = UtcOffset>> HasLogicalOffset for T {}
|
|
-
|
|
- pub trait NoLogicalOffset: MaybeOffset<LogicalOffsetType = ()> {}
|
|
- impl<T: MaybeOffset<LogicalOffsetType = ()>> NoLogicalOffset for T {}
|
|
-
|
|
- // Traits to indicate whether a `MaybeOffset` has a memory offset type of `UtcOffset` or not.
|
|
-
|
|
- pub trait HasMemoryOffset: MaybeOffset<MemoryOffsetType = UtcOffset> {}
|
|
- impl<T: MaybeOffset<MemoryOffsetType = UtcOffset>> HasMemoryOffset for T {}
|
|
-
|
|
- pub trait NoMemoryOffset: MaybeOffset<MemoryOffsetType = ()> {}
|
|
- impl<T: MaybeOffset<MemoryOffsetType = ()>> NoMemoryOffset for T {}
|
|
-
|
|
- // Traits to indicate backing type being implemented.
|
|
-
|
|
- pub trait IsOffsetKindNone:
|
|
- MaybeOffset<Self_ = offset_kind::None, MemoryOffsetType = (), LogicalOffsetType = ()>
|
|
- {
|
|
- }
|
|
- impl IsOffsetKindNone for offset_kind::None {}
|
|
-
|
|
- pub trait IsOffsetKindFixed:
|
|
- MaybeOffset<
|
|
- Self_ = offset_kind::Fixed,
|
|
- MemoryOffsetType = UtcOffset,
|
|
- LogicalOffsetType = UtcOffset,
|
|
- >
|
|
- {
|
|
- }
|
|
- impl IsOffsetKindFixed for offset_kind::Fixed {}
|
|
-}
|
|
-
|
|
-impl MaybeOffset for offset_kind::None {
|
|
- type MemoryOffsetType = ();
|
|
- type LogicalOffsetType = ();
|
|
-
|
|
- type Self_ = Self;
|
|
-
|
|
- const STATIC_OFFSET: Option<UtcOffset> = None;
|
|
-
|
|
- #[cfg(feature = "parsing")]
|
|
- fn try_from_parsed(_: Parsed) -> Result<(), error::TryFromParsed> {
|
|
- Ok(())
|
|
- }
|
|
-}
|
|
-
|
|
-impl MaybeOffset for offset_kind::Fixed {
|
|
- type MemoryOffsetType = UtcOffset;
|
|
- type LogicalOffsetType = UtcOffset;
|
|
-
|
|
- type Self_ = Self;
|
|
-
|
|
- const STATIC_OFFSET: Option<UtcOffset> = None;
|
|
-
|
|
- #[cfg(feature = "parsing")]
|
|
- fn try_from_parsed(parsed: Parsed) -> Result<UtcOffset, error::TryFromParsed> {
|
|
- parsed.try_into()
|
|
- }
|
|
-}
|
|
-
|
|
-// region: const trait method hacks
|
|
-// TODO(jhpratt) When const trait impls are stable, these methods can be removed in favor of methods
|
|
-// in `MaybeOffset`, which would then be made `const`.
|
|
-const fn maybe_offset_as_offset_opt<O: MaybeOffset>(
|
|
- offset: O::MemoryOffsetType,
|
|
-) -> Option<UtcOffset> {
|
|
- if O::STATIC_OFFSET.is_some() {
|
|
- O::STATIC_OFFSET
|
|
- } else if O::HAS_MEMORY_OFFSET {
|
|
- #[repr(C)] // needed to guarantee they align at the start
|
|
- union Convert<O: MaybeOffset> {
|
|
- input: O::MemoryOffsetType,
|
|
- output: UtcOffset,
|
|
- }
|
|
-
|
|
- // Safety: `O::HAS_OFFSET` indicates that `O::Offset` is `UtcOffset`. This code effectively
|
|
- // performs a transmute from `O::Offset` to `UtcOffset`, which we know is the same type.
|
|
- Some(unsafe { Convert::<O> { input: offset }.output })
|
|
- } else {
|
|
- None
|
|
- }
|
|
-}
|
|
-
|
|
-const fn maybe_offset_as_offset<O: MaybeOffset + HasLogicalOffset>(
|
|
- offset: O::MemoryOffsetType,
|
|
-) -> UtcOffset {
|
|
- match maybe_offset_as_offset_opt::<O>(offset) {
|
|
- Some(offset) => offset,
|
|
- None => bug!("`MaybeOffset::as_offset` called on a type without an offset in memory"),
|
|
- }
|
|
-}
|
|
-
|
|
-pub(crate) const fn maybe_offset_from_offset<O: MaybeOffset>(
|
|
- offset: UtcOffset,
|
|
-) -> O::MemoryOffsetType {
|
|
- #[repr(C)] // needed to guarantee the types align at the start
|
|
- union Convert<O: MaybeOffset> {
|
|
- input: UtcOffset,
|
|
- output: O::MemoryOffsetType,
|
|
- }
|
|
-
|
|
- // Safety: It is statically known that there are only two possibilities due to the trait bound
|
|
- // of `O::MemoryOffsetType`, which ultimately relies on `MaybeOffsetType`. The two possibilities
|
|
- // are:
|
|
- // 1. UtcOffset -> UtcOffset
|
|
- // 2. UtcOffset -> ()
|
|
- // (1) is valid because it is an identity conversion, which is always valid. (2) is valid
|
|
- // because `()` is a 1-ZST, so converting to it is always valid.
|
|
- unsafe { Convert::<O> { input: offset }.output }
|
|
-}
|
|
-// endregion const trait methods hacks
|
|
-
|
|
-/// The Julian day of the Unix epoch.
|
|
-// Safety: `ordinal` is not zero.
|
|
-#[allow(clippy::undocumented_unsafe_blocks)]
|
|
-const UNIX_EPOCH_JULIAN_DAY: i32 =
|
|
- unsafe { Date::__from_ordinal_date_unchecked(1970, 1) }.to_julian_day();
|
|
-
|
|
-pub struct DateTime<O: MaybeOffset> {
|
|
- pub(crate) date: Date,
|
|
- pub(crate) time: Time,
|
|
- pub(crate) offset: O::MemoryOffsetType,
|
|
-}
|
|
-
|
|
-// Manual impl to remove extraneous bounds.
|
|
-impl<O: MaybeOffset> Clone for DateTime<O> {
|
|
- fn clone(&self) -> Self {
|
|
- *self
|
|
- }
|
|
-}
|
|
-
|
|
-// Manual impl to remove extraneous bounds.
|
|
-impl<O: MaybeOffset> Copy for DateTime<O> {}
|
|
-
|
|
-// region: constructors
|
|
-impl DateTime<offset_kind::None> {
|
|
- pub const MIN: Self = Self {
|
|
- date: Date::MIN,
|
|
- time: Time::MIN,
|
|
- offset: (),
|
|
- };
|
|
-
|
|
- pub const MAX: Self = Self {
|
|
- date: Date::MAX,
|
|
- time: Time::MAX,
|
|
- offset: (),
|
|
- };
|
|
-}
|
|
-
|
|
-impl DateTime<offset_kind::Fixed> {
|
|
- pub const UNIX_EPOCH: Self = Self {
|
|
- // Safety: `ordinal` is not zero.
|
|
- date: unsafe { Date::__from_ordinal_date_unchecked(1970, 1) },
|
|
- time: Time::MIDNIGHT,
|
|
- offset: UtcOffset::UTC,
|
|
- };
|
|
-}
|
|
-
|
|
-impl<O: MaybeOffset> DateTime<O> {
|
|
- pub const fn new(date: Date, time: Time) -> Self
|
|
- where
|
|
- O: IsOffsetKindNone,
|
|
- {
|
|
- Self {
|
|
- date,
|
|
- time,
|
|
- offset: (),
|
|
- }
|
|
- }
|
|
-
|
|
- pub const fn from_unix_timestamp(timestamp: i64) -> Result<Self, error::ComponentRange>
|
|
- where
|
|
- O: HasLogicalOffset,
|
|
- {
|
|
- type Timestamp = RangedI64<
|
|
- { Date::MIN.midnight().assume_utc().unix_timestamp() },
|
|
- { Date::MAX.with_time(Time::MAX).assume_utc().unix_timestamp() },
|
|
- >;
|
|
- ensure_ranged!(Timestamp: timestamp);
|
|
-
|
|
- // Use the unchecked method here, as the input validity has already been verified.
|
|
- let date = Date::from_julian_day_unchecked(
|
|
- UNIX_EPOCH_JULIAN_DAY + div_floor!(timestamp, Second::per(Day) as i64) as i32,
|
|
- );
|
|
-
|
|
- let seconds_within_day = timestamp.rem_euclid(Second::per(Day) as _);
|
|
- // Safety: All values are in range.
|
|
- let time = unsafe {
|
|
- Time::__from_hms_nanos_unchecked(
|
|
- (seconds_within_day / Second::per(Hour) as i64) as _,
|
|
- ((seconds_within_day % Second::per(Hour) as i64) / Minute::per(Hour) as i64) as _,
|
|
- (seconds_within_day % Second::per(Minute) as i64) as _,
|
|
- 0,
|
|
- )
|
|
- };
|
|
-
|
|
- Ok(Self {
|
|
- date,
|
|
- time,
|
|
- offset: maybe_offset_from_offset::<O>(UtcOffset::UTC),
|
|
- })
|
|
- }
|
|
-
|
|
- pub const fn from_unix_timestamp_nanos(timestamp: i128) -> Result<Self, error::ComponentRange>
|
|
- where
|
|
- O: HasLogicalOffset,
|
|
- {
|
|
- let datetime = const_try!(Self::from_unix_timestamp(div_floor!(
|
|
- timestamp,
|
|
- Nanosecond::per(Second) as i128
|
|
- ) as i64));
|
|
-
|
|
- Ok(Self {
|
|
- date: datetime.date,
|
|
- // Safety: `nanosecond` is in range due to `rem_euclid`.
|
|
- time: unsafe {
|
|
- Time::__from_hms_nanos_unchecked(
|
|
- datetime.hour(),
|
|
- datetime.minute(),
|
|
- datetime.second(),
|
|
- timestamp.rem_euclid(Nanosecond::per(Second) as _) as u32,
|
|
- )
|
|
- },
|
|
- offset: maybe_offset_from_offset::<O>(UtcOffset::UTC),
|
|
- })
|
|
- }
|
|
- // endregion constructors
|
|
-
|
|
- // region: now
|
|
- // The return type will likely be loosened once `ZonedDateTime` is implemented. This is not a
|
|
- // breaking change calls are currently limited to only `OffsetDateTime`.
|
|
- #[cfg(feature = "std")]
|
|
- pub fn now_utc() -> DateTime<offset_kind::Fixed>
|
|
- where
|
|
- O: IsOffsetKindFixed,
|
|
- {
|
|
- #[cfg(all(
|
|
- target_family = "wasm",
|
|
- not(any(target_os = "emscripten", target_os = "wasi")),
|
|
- feature = "wasm-bindgen"
|
|
- ))]
|
|
- {
|
|
- js_sys::Date::new_0().into()
|
|
- }
|
|
-
|
|
- #[cfg(not(all(
|
|
- target_family = "wasm",
|
|
- not(any(target_os = "emscripten", target_os = "wasi")),
|
|
- feature = "wasm-bindgen"
|
|
- )))]
|
|
- SystemTime::now().into()
|
|
- }
|
|
-
|
|
- // The return type will likely be loosened once `ZonedDateTime` is implemented. This is not a
|
|
- // breaking change calls are currently limited to only `OffsetDateTime`.
|
|
- #[cfg(feature = "local-offset")]
|
|
- pub fn now_local() -> Result<DateTime<offset_kind::Fixed>, error::IndeterminateOffset>
|
|
- where
|
|
- O: IsOffsetKindFixed,
|
|
- {
|
|
- let t = DateTime::<offset_kind::Fixed>::now_utc();
|
|
- Ok(t.to_offset(UtcOffset::local_offset_at(crate::OffsetDateTime(t))?))
|
|
- }
|
|
- // endregion now
|
|
-
|
|
- // region: getters
|
|
- // region: component getters
|
|
- pub const fn date(self) -> Date {
|
|
- self.date
|
|
- }
|
|
-
|
|
- pub const fn time(self) -> Time {
|
|
- self.time
|
|
- }
|
|
-
|
|
- pub const fn offset(self) -> UtcOffset
|
|
- where
|
|
- O: HasLogicalOffset,
|
|
- {
|
|
- maybe_offset_as_offset::<O>(self.offset)
|
|
- }
|
|
- // endregion component getters
|
|
-
|
|
- // region: date getters
|
|
- pub const fn year(self) -> i32 {
|
|
- self.date.year()
|
|
- }
|
|
-
|
|
- pub const fn month(self) -> Month {
|
|
- self.date.month()
|
|
- }
|
|
-
|
|
- pub const fn day(self) -> u8 {
|
|
- self.date.day()
|
|
- }
|
|
-
|
|
- pub const fn ordinal(self) -> u16 {
|
|
- self.date.ordinal()
|
|
- }
|
|
-
|
|
- pub const fn iso_week(self) -> u8 {
|
|
- self.date.iso_week()
|
|
- }
|
|
-
|
|
- pub const fn sunday_based_week(self) -> u8 {
|
|
- self.date.sunday_based_week()
|
|
- }
|
|
-
|
|
- pub const fn monday_based_week(self) -> u8 {
|
|
- self.date.monday_based_week()
|
|
- }
|
|
-
|
|
- pub const fn to_calendar_date(self) -> (i32, Month, u8) {
|
|
- self.date.to_calendar_date()
|
|
- }
|
|
-
|
|
- pub const fn to_ordinal_date(self) -> (i32, u16) {
|
|
- self.date.to_ordinal_date()
|
|
- }
|
|
-
|
|
- pub const fn to_iso_week_date(self) -> (i32, u8, Weekday) {
|
|
- self.date.to_iso_week_date()
|
|
- }
|
|
-
|
|
- pub const fn weekday(self) -> Weekday {
|
|
- self.date.weekday()
|
|
- }
|
|
-
|
|
- pub const fn to_julian_day(self) -> i32 {
|
|
- self.date.to_julian_day()
|
|
- }
|
|
- // endregion date getters
|
|
-
|
|
- // region: time getters
|
|
- pub const fn as_hms(self) -> (u8, u8, u8) {
|
|
- self.time.as_hms()
|
|
- }
|
|
-
|
|
- pub const fn as_hms_milli(self) -> (u8, u8, u8, u16) {
|
|
- self.time.as_hms_milli()
|
|
- }
|
|
-
|
|
- pub const fn as_hms_micro(self) -> (u8, u8, u8, u32) {
|
|
- self.time.as_hms_micro()
|
|
- }
|
|
-
|
|
- pub const fn as_hms_nano(self) -> (u8, u8, u8, u32) {
|
|
- self.time.as_hms_nano()
|
|
- }
|
|
-
|
|
- pub const fn hour(self) -> u8 {
|
|
- self.time.hour()
|
|
- }
|
|
-
|
|
- pub const fn minute(self) -> u8 {
|
|
- self.time.minute()
|
|
- }
|
|
-
|
|
- pub const fn second(self) -> u8 {
|
|
- self.time.second()
|
|
- }
|
|
-
|
|
- pub const fn millisecond(self) -> u16 {
|
|
- self.time.millisecond()
|
|
- }
|
|
-
|
|
- pub const fn microsecond(self) -> u32 {
|
|
- self.time.microsecond()
|
|
- }
|
|
-
|
|
- pub const fn nanosecond(self) -> u32 {
|
|
- self.time.nanosecond()
|
|
- }
|
|
- // endregion time getters
|
|
-
|
|
- // region: unix timestamp getters
|
|
- pub const fn unix_timestamp(self) -> i64
|
|
- where
|
|
- O: HasLogicalOffset,
|
|
- {
|
|
- let offset = maybe_offset_as_offset::<O>(self.offset).whole_seconds() as i64;
|
|
-
|
|
- let days =
|
|
- (self.to_julian_day() as i64 - UNIX_EPOCH_JULIAN_DAY as i64) * Second::per(Day) as i64;
|
|
- let hours = self.hour() as i64 * Second::per(Hour) as i64;
|
|
- let minutes = self.minute() as i64 * Second::per(Minute) as i64;
|
|
- let seconds = self.second() as i64;
|
|
- days + hours + minutes + seconds - offset
|
|
- }
|
|
-
|
|
- pub const fn unix_timestamp_nanos(self) -> i128
|
|
- where
|
|
- O: HasLogicalOffset,
|
|
- {
|
|
- self.unix_timestamp() as i128 * Nanosecond::per(Second) as i128 + self.nanosecond() as i128
|
|
- }
|
|
- // endregion unix timestamp getters
|
|
- // endregion: getters
|
|
-
|
|
- // region: attach offset
|
|
- pub const fn assume_offset(self, offset: UtcOffset) -> DateTime<offset_kind::Fixed>
|
|
- where
|
|
- O: NoLogicalOffset,
|
|
- {
|
|
- DateTime {
|
|
- date: self.date,
|
|
- time: self.time,
|
|
- offset,
|
|
- }
|
|
- }
|
|
-
|
|
- pub const fn assume_utc(self) -> DateTime<offset_kind::Fixed>
|
|
- where
|
|
- O: NoLogicalOffset,
|
|
- {
|
|
- self.assume_offset(UtcOffset::UTC)
|
|
- }
|
|
- // endregion attach offset
|
|
-
|
|
- // region: to offset
|
|
- pub const fn to_offset(self, offset: UtcOffset) -> DateTime<offset_kind::Fixed>
|
|
- where
|
|
- O: HasLogicalOffset,
|
|
- {
|
|
- expect_opt!(
|
|
- self.checked_to_offset(offset),
|
|
- "local datetime out of valid range"
|
|
- )
|
|
- }
|
|
-
|
|
- pub const fn checked_to_offset(self, offset: UtcOffset) -> Option<DateTime<offset_kind::Fixed>>
|
|
- where
|
|
- O: HasLogicalOffset,
|
|
- {
|
|
- let self_offset = maybe_offset_as_offset::<O>(self.offset);
|
|
-
|
|
- if self_offset.whole_hours() == offset.whole_hours()
|
|
- && self_offset.minutes_past_hour() == offset.minutes_past_hour()
|
|
- && self_offset.seconds_past_minute() == offset.seconds_past_minute()
|
|
- {
|
|
- return Some(DateTime {
|
|
- date: self.date,
|
|
- time: self.time,
|
|
- offset,
|
|
- });
|
|
- }
|
|
-
|
|
- let (year, ordinal, time) = self.to_offset_raw(offset);
|
|
-
|
|
- if year > MAX_YEAR || year < MIN_YEAR {
|
|
- return None;
|
|
- }
|
|
-
|
|
- Some(DateTime {
|
|
- // Safety: `ordinal` is not zero.
|
|
- date: unsafe { Date::__from_ordinal_date_unchecked(year, ordinal) },
|
|
- time,
|
|
- offset,
|
|
- })
|
|
- }
|
|
-
|
|
- /// Equivalent to `.to_offset(UtcOffset::UTC)`, but returning the year, ordinal, and time. This
|
|
- /// avoids constructing an invalid [`Date`] if the new value is out of range.
|
|
- pub(crate) const fn to_offset_raw(self, offset: UtcOffset) -> (i32, u16, Time) {
|
|
- let Some(from) = maybe_offset_as_offset_opt::<O>(self.offset) else {
|
|
- // No adjustment is needed because there is no offset.
|
|
- return (self.year(), self.ordinal(), self.time);
|
|
- };
|
|
- let to = offset;
|
|
-
|
|
- // Fast path for when no conversion is necessary.
|
|
- if from.whole_hours() == to.whole_hours()
|
|
- && from.minutes_past_hour() == to.minutes_past_hour()
|
|
- && from.seconds_past_minute() == to.seconds_past_minute()
|
|
- {
|
|
- return (self.year(), self.ordinal(), self.time());
|
|
- }
|
|
-
|
|
- let mut second = self.second() as i16 - from.seconds_past_minute() as i16
|
|
- + to.seconds_past_minute() as i16;
|
|
- let mut minute =
|
|
- self.minute() as i16 - from.minutes_past_hour() as i16 + to.minutes_past_hour() as i16;
|
|
- let mut hour = self.hour() as i8 - from.whole_hours() + to.whole_hours();
|
|
- let (mut year, ordinal) = self.to_ordinal_date();
|
|
- let mut ordinal = ordinal as i16;
|
|
-
|
|
- // Cascade the values twice. This is needed because the values are adjusted twice above.
|
|
- cascade!(second in 0..Second::per(Minute) as i16 => minute);
|
|
- cascade!(second in 0..Second::per(Minute) as i16 => minute);
|
|
- cascade!(minute in 0..Minute::per(Hour) as i16 => hour);
|
|
- cascade!(minute in 0..Minute::per(Hour) as i16 => hour);
|
|
- cascade!(hour in 0..Hour::per(Day) as i8 => ordinal);
|
|
- cascade!(hour in 0..Hour::per(Day) as i8 => ordinal);
|
|
- cascade!(ordinal => year);
|
|
-
|
|
- debug_assert!(ordinal > 0);
|
|
- debug_assert!(ordinal <= crate::util::days_in_year(year) as i16);
|
|
-
|
|
- (
|
|
- year,
|
|
- ordinal as _,
|
|
- // Safety: The cascades above ensure the values are in range.
|
|
- unsafe {
|
|
- Time::__from_hms_nanos_unchecked(
|
|
- hour as _,
|
|
- minute as _,
|
|
- second as _,
|
|
- self.nanosecond(),
|
|
- )
|
|
- },
|
|
- )
|
|
- }
|
|
- // endregion to offset
|
|
-
|
|
- // region: checked arithmetic
|
|
- pub const fn checked_add(self, duration: Duration) -> Option<Self> {
|
|
- let (date_adjustment, time) = self.time.adjusting_add(duration);
|
|
- let date = const_try_opt!(self.date.checked_add(duration));
|
|
-
|
|
- Some(Self {
|
|
- date: match date_adjustment {
|
|
- util::DateAdjustment::Previous => const_try_opt!(date.previous_day()),
|
|
- util::DateAdjustment::Next => const_try_opt!(date.next_day()),
|
|
- util::DateAdjustment::None => date,
|
|
- },
|
|
- time,
|
|
- offset: self.offset,
|
|
- })
|
|
- }
|
|
-
|
|
- pub const fn checked_sub(self, duration: Duration) -> Option<Self> {
|
|
- let (date_adjustment, time) = self.time.adjusting_sub(duration);
|
|
- let date = const_try_opt!(self.date.checked_sub(duration));
|
|
-
|
|
- Some(Self {
|
|
- date: match date_adjustment {
|
|
- util::DateAdjustment::Previous => const_try_opt!(date.previous_day()),
|
|
- util::DateAdjustment::Next => const_try_opt!(date.next_day()),
|
|
- util::DateAdjustment::None => date,
|
|
- },
|
|
- time,
|
|
- offset: self.offset,
|
|
- })
|
|
- }
|
|
- // endregion checked arithmetic
|
|
-
|
|
- // region: saturating arithmetic
|
|
- pub const fn saturating_add(self, duration: Duration) -> Self {
|
|
- if let Some(datetime) = self.checked_add(duration) {
|
|
- datetime
|
|
- } else if duration.is_negative() {
|
|
- Self {
|
|
- date: Date::MIN,
|
|
- time: Time::MIN,
|
|
- offset: self.offset,
|
|
- }
|
|
- } else {
|
|
- Self {
|
|
- date: Date::MAX,
|
|
- time: Time::MAX,
|
|
- offset: self.offset,
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- pub const fn saturating_sub(self, duration: Duration) -> Self {
|
|
- if let Some(datetime) = self.checked_sub(duration) {
|
|
- datetime
|
|
- } else if duration.is_negative() {
|
|
- Self {
|
|
- date: Date::MAX,
|
|
- time: Time::MAX,
|
|
- offset: self.offset,
|
|
- }
|
|
- } else {
|
|
- Self {
|
|
- date: Date::MIN,
|
|
- time: Time::MIN,
|
|
- offset: self.offset,
|
|
- }
|
|
- }
|
|
- }
|
|
- // endregion saturating arithmetic
|
|
-
|
|
- // region: replacement
|
|
- #[must_use = "this does not modify the original value"]
|
|
- pub const fn replace_time(self, time: Time) -> Self {
|
|
- Self {
|
|
- date: self.date,
|
|
- time,
|
|
- offset: self.offset,
|
|
- }
|
|
- }
|
|
-
|
|
- #[must_use = "this does not modify the original value"]
|
|
- pub const fn replace_date(self, date: Date) -> Self {
|
|
- Self {
|
|
- date,
|
|
- time: self.time,
|
|
- offset: self.offset,
|
|
- }
|
|
- }
|
|
-
|
|
- #[must_use = "this does not modify the original value"]
|
|
- pub const fn replace_date_time(self, date_time: DateTime<offset_kind::None>) -> Self
|
|
- where
|
|
- O: HasLogicalOffset,
|
|
- {
|
|
- Self {
|
|
- date: date_time.date,
|
|
- time: date_time.time,
|
|
- offset: self.offset,
|
|
- }
|
|
- }
|
|
-
|
|
- #[must_use = "this does not modify the original value"]
|
|
- pub const fn replace_year(self, year: i32) -> Result<Self, error::ComponentRange> {
|
|
- Ok(Self {
|
|
- date: const_try!(self.date.replace_year(year)),
|
|
- time: self.time,
|
|
- offset: self.offset,
|
|
- })
|
|
- }
|
|
-
|
|
- #[must_use = "this does not modify the original value"]
|
|
- pub const fn replace_month(self, month: Month) -> Result<Self, error::ComponentRange> {
|
|
- Ok(Self {
|
|
- date: const_try!(self.date.replace_month(month)),
|
|
- time: self.time,
|
|
- offset: self.offset,
|
|
- })
|
|
- }
|
|
-
|
|
- #[must_use = "this does not modify the original value"]
|
|
- pub const fn replace_day(self, day: u8) -> Result<Self, error::ComponentRange> {
|
|
- Ok(Self {
|
|
- date: const_try!(self.date.replace_day(day)),
|
|
- time: self.time,
|
|
- offset: self.offset,
|
|
- })
|
|
- }
|
|
-
|
|
- #[must_use = "this does not modify the original value"]
|
|
- pub const fn replace_hour(self, hour: u8) -> Result<Self, error::ComponentRange> {
|
|
- Ok(Self {
|
|
- date: self.date,
|
|
- time: const_try!(self.time.replace_hour(hour)),
|
|
- offset: self.offset,
|
|
- })
|
|
- }
|
|
-
|
|
- #[must_use = "this does not modify the original value"]
|
|
- pub const fn replace_minute(self, minute: u8) -> Result<Self, error::ComponentRange> {
|
|
- Ok(Self {
|
|
- date: self.date,
|
|
- time: const_try!(self.time.replace_minute(minute)),
|
|
- offset: self.offset,
|
|
- })
|
|
- }
|
|
-
|
|
- #[must_use = "this does not modify the original value"]
|
|
- pub const fn replace_second(self, second: u8) -> Result<Self, error::ComponentRange> {
|
|
- Ok(Self {
|
|
- date: self.date,
|
|
- time: const_try!(self.time.replace_second(second)),
|
|
- offset: self.offset,
|
|
- })
|
|
- }
|
|
-
|
|
- #[must_use = "this does not modify the original value"]
|
|
- pub const fn replace_millisecond(
|
|
- self,
|
|
- millisecond: u16,
|
|
- ) -> Result<Self, error::ComponentRange> {
|
|
- Ok(Self {
|
|
- date: self.date,
|
|
- time: const_try!(self.time.replace_millisecond(millisecond)),
|
|
- offset: self.offset,
|
|
- })
|
|
- }
|
|
-
|
|
- #[must_use = "this does not modify the original value"]
|
|
- pub const fn replace_microsecond(
|
|
- self,
|
|
- microsecond: u32,
|
|
- ) -> Result<Self, error::ComponentRange> {
|
|
- Ok(Self {
|
|
- date: self.date,
|
|
- time: const_try!(self.time.replace_microsecond(microsecond)),
|
|
- offset: self.offset,
|
|
- })
|
|
- }
|
|
-
|
|
- #[must_use = "this does not modify the original value"]
|
|
- pub const fn replace_nanosecond(self, nanosecond: u32) -> Result<Self, error::ComponentRange> {
|
|
- Ok(Self {
|
|
- date: self.date,
|
|
- time: const_try!(self.time.replace_nanosecond(nanosecond)),
|
|
- offset: self.offset,
|
|
- })
|
|
- }
|
|
-
|
|
- // Don't gate this on just having an offset, as `ZonedDateTime` cannot be set to an arbitrary
|
|
- // offset.
|
|
- #[must_use = "this does not modify the original value"]
|
|
- pub const fn replace_offset(self, offset: UtcOffset) -> DateTime<offset_kind::Fixed>
|
|
- where
|
|
- O: IsOffsetKindFixed,
|
|
- {
|
|
- DateTime {
|
|
- date: self.date,
|
|
- time: self.time,
|
|
- offset,
|
|
- }
|
|
- }
|
|
-
|
|
- // endregion replacement
|
|
-
|
|
- // region: formatting & parsing
|
|
- #[cfg(feature = "formatting")]
|
|
- pub fn format_into(
|
|
- self,
|
|
- output: &mut impl io::Write,
|
|
- format: &(impl Formattable + ?Sized),
|
|
- ) -> Result<usize, error::Format> {
|
|
- format.format_into(
|
|
- output,
|
|
- Some(self.date),
|
|
- Some(self.time),
|
|
- maybe_offset_as_offset_opt::<O>(self.offset),
|
|
- )
|
|
- }
|
|
-
|
|
- #[cfg(feature = "formatting")]
|
|
- pub fn format(self, format: &(impl Formattable + ?Sized)) -> Result<String, error::Format> {
|
|
- format.format(
|
|
- Some(self.date),
|
|
- Some(self.time),
|
|
- maybe_offset_as_offset_opt::<O>(self.offset),
|
|
- )
|
|
- }
|
|
-
|
|
- #[cfg(feature = "parsing")]
|
|
- pub fn parse(
|
|
- input: &str,
|
|
- description: &(impl Parsable + ?Sized),
|
|
- ) -> Result<Self, error::Parse> {
|
|
- description.parse_date_time(input.as_bytes())
|
|
- }
|
|
-
|
|
- /// A helper method to check if the `OffsetDateTime` is a valid representation of a leap second.
|
|
- /// Leap seconds, when parsed, are represented as the preceding nanosecond. However, leap
|
|
- /// seconds can only occur as the last second of a month UTC.
|
|
- #[cfg(feature = "parsing")]
|
|
- pub(crate) const fn is_valid_leap_second_stand_in(self) -> bool {
|
|
- // Leap seconds aren't allowed if there is no offset.
|
|
- if !O::HAS_LOGICAL_OFFSET {
|
|
- return false;
|
|
- }
|
|
-
|
|
- // This comparison doesn't need to be adjusted for the stored offset, so check it first for
|
|
- // speed.
|
|
- if self.nanosecond() != 999_999_999 {
|
|
- return false;
|
|
- }
|
|
-
|
|
- let (year, ordinal, time) = self.to_offset_raw(UtcOffset::UTC);
|
|
- let Ok(date) = Date::from_ordinal_date(year, ordinal) else {
|
|
- return false;
|
|
- };
|
|
-
|
|
- time.hour() == 23
|
|
- && time.minute() == 59
|
|
- && time.second() == 59
|
|
- && date.day() == util::days_in_year_month(year, date.month())
|
|
- }
|
|
-
|
|
- // endregion formatting & parsing
|
|
-
|
|
- // region: deprecated time getters
|
|
-
|
|
- // All the way at the bottom as it's low priority. These methods only exist for when
|
|
- // `OffsetDateTime` is made an alias of `DateTime<Fixed>`. Consider hiding these methods from
|
|
- // documentation in the future.
|
|
-
|
|
- #[doc(hidden)]
|
|
- #[allow(dead_code)] // while functionally private
|
|
- #[deprecated(since = "0.3.18", note = "use `as_hms` instead")]
|
|
- pub const fn to_hms(self) -> (u8, u8, u8)
|
|
- where
|
|
- O: IsOffsetKindFixed,
|
|
- {
|
|
- self.time.as_hms()
|
|
- }
|
|
-
|
|
- #[doc(hidden)]
|
|
- #[allow(dead_code)] // while functionally private
|
|
- #[deprecated(since = "0.3.18", note = "use `as_hms_milli` instead")]
|
|
- pub const fn to_hms_milli(self) -> (u8, u8, u8, u16)
|
|
- where
|
|
- O: IsOffsetKindFixed,
|
|
- {
|
|
- self.time.as_hms_milli()
|
|
- }
|
|
-
|
|
- #[doc(hidden)]
|
|
- #[allow(dead_code)] // while functionally private
|
|
- #[deprecated(since = "0.3.18", note = "use `as_hms_micro` instead")]
|
|
- pub const fn to_hms_micro(self) -> (u8, u8, u8, u32)
|
|
- where
|
|
- O: IsOffsetKindFixed,
|
|
- {
|
|
- self.time.as_hms_micro()
|
|
- }
|
|
-
|
|
- #[doc(hidden)]
|
|
- #[allow(dead_code)] // while functionally private
|
|
- #[deprecated(since = "0.3.18", note = "use `as_hms_nano` instead")]
|
|
- pub const fn to_hms_nano(self) -> (u8, u8, u8, u32)
|
|
- where
|
|
- O: IsOffsetKindFixed,
|
|
- {
|
|
- self.time.as_hms_nano()
|
|
- }
|
|
- // endregion deprecated time getters
|
|
-}
|
|
-
|
|
-// region: trait impls
|
|
-mod private {
|
|
- use super::*;
|
|
-
|
|
- #[non_exhaustive]
|
|
- #[derive(Debug, Clone, Copy)]
|
|
- pub struct DateTimeMetadata {
|
|
- pub(super) maybe_offset: Option<UtcOffset>,
|
|
- }
|
|
-}
|
|
-pub(crate) use private::DateTimeMetadata;
|
|
-
|
|
-impl<O: MaybeOffset> SmartDisplay for DateTime<O> {
|
|
- type Metadata = DateTimeMetadata;
|
|
-
|
|
- fn metadata(&self, _: FormatterOptions) -> Metadata<Self> {
|
|
- let maybe_offset = maybe_offset_as_offset_opt::<O>(self.offset);
|
|
- let width = match maybe_offset {
|
|
- Some(offset) => smart_display::padded_width_of!(self.date, " ", self.time, " ", offset),
|
|
- None => smart_display::padded_width_of!(self.date, " ", self.time),
|
|
- };
|
|
- Metadata::new(width, self, DateTimeMetadata { maybe_offset })
|
|
- }
|
|
-
|
|
- fn fmt_with_metadata(
|
|
- &self,
|
|
- f: &mut fmt::Formatter<'_>,
|
|
- metadata: Metadata<Self>,
|
|
- ) -> fmt::Result {
|
|
- match metadata.maybe_offset {
|
|
- Some(offset) => f.pad_with_width(
|
|
- metadata.unpadded_width(),
|
|
- format_args!("{} {} {offset}", self.date, self.time),
|
|
- ),
|
|
- None => f.pad_with_width(
|
|
- metadata.unpadded_width(),
|
|
- format_args!("{} {}", self.date, self.time),
|
|
- ),
|
|
- }
|
|
- }
|
|
-}
|
|
-
|
|
-impl<O: MaybeOffset> fmt::Display for DateTime<O> {
|
|
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
- SmartDisplay::fmt(self, f)
|
|
- }
|
|
-}
|
|
-
|
|
-impl<O: MaybeOffset> fmt::Debug for DateTime<O> {
|
|
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
- fmt::Display::fmt(self, f)
|
|
- }
|
|
-}
|
|
-
|
|
-impl<O: MaybeOffset> PartialEq for DateTime<O> {
|
|
- fn eq(&self, rhs: &Self) -> bool {
|
|
- if O::HAS_LOGICAL_OFFSET {
|
|
- self.to_offset_raw(UtcOffset::UTC) == rhs.to_offset_raw(UtcOffset::UTC)
|
|
- } else {
|
|
- (self.date, self.time) == (rhs.date, rhs.time)
|
|
- }
|
|
- }
|
|
-}
|
|
-
|
|
-impl<O: MaybeOffset> Eq for DateTime<O> {}
|
|
-
|
|
-impl<O: MaybeOffset> PartialOrd for DateTime<O> {
|
|
- fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
|
|
- Some(self.cmp(rhs))
|
|
- }
|
|
-}
|
|
-
|
|
-impl<O: MaybeOffset> Ord for DateTime<O> {
|
|
- fn cmp(&self, rhs: &Self) -> Ordering {
|
|
- if O::HAS_LOGICAL_OFFSET {
|
|
- self.to_offset_raw(UtcOffset::UTC)
|
|
- .cmp(&rhs.to_offset_raw(UtcOffset::UTC))
|
|
- } else {
|
|
- (self.date, self.time).cmp(&(rhs.date, rhs.time))
|
|
- }
|
|
- }
|
|
-}
|
|
-
|
|
-impl<O: MaybeOffset> Hash for DateTime<O> {
|
|
- fn hash<H: Hasher>(&self, hasher: &mut H) {
|
|
- if O::HAS_LOGICAL_OFFSET {
|
|
- self.to_offset_raw(UtcOffset::UTC).hash(hasher);
|
|
- } else {
|
|
- (self.date, self.time).hash(hasher);
|
|
- }
|
|
- }
|
|
-}
|
|
-
|
|
-impl<O: MaybeOffset> Add<Duration> for DateTime<O> {
|
|
- type Output = Self;
|
|
-
|
|
- fn add(self, duration: Duration) -> Self {
|
|
- self.checked_add(duration)
|
|
- .expect("resulting value is out of range")
|
|
- }
|
|
-}
|
|
-
|
|
-impl<O: MaybeOffset> Add<StdDuration> for DateTime<O> {
|
|
- type Output = Self;
|
|
-
|
|
- fn add(self, duration: StdDuration) -> Self::Output {
|
|
- let (is_next_day, time) = self.time.adjusting_add_std(duration);
|
|
-
|
|
- Self {
|
|
- date: if is_next_day {
|
|
- (self.date + duration)
|
|
- .next_day()
|
|
- .expect("resulting value is out of range")
|
|
- } else {
|
|
- self.date + duration
|
|
- },
|
|
- time,
|
|
- offset: self.offset,
|
|
- }
|
|
- }
|
|
-}
|
|
-
|
|
-impl<O: MaybeOffset> AddAssign<Duration> for DateTime<O> {
|
|
- fn add_assign(&mut self, rhs: Duration) {
|
|
- *self = *self + rhs;
|
|
- }
|
|
-}
|
|
-
|
|
-impl<O: MaybeOffset> AddAssign<StdDuration> for DateTime<O> {
|
|
- fn add_assign(&mut self, rhs: StdDuration) {
|
|
- *self = *self + rhs;
|
|
- }
|
|
-}
|
|
-
|
|
-impl<O: MaybeOffset> Sub<Duration> for DateTime<O> {
|
|
- type Output = Self;
|
|
-
|
|
- fn sub(self, duration: Duration) -> Self {
|
|
- self.checked_sub(duration)
|
|
- .expect("resulting value is out of range")
|
|
- }
|
|
-}
|
|
-
|
|
-impl<O: MaybeOffset> Sub<StdDuration> for DateTime<O> {
|
|
- type Output = Self;
|
|
-
|
|
- fn sub(self, duration: StdDuration) -> Self::Output {
|
|
- let (is_previous_day, time) = self.time.adjusting_sub_std(duration);
|
|
-
|
|
- Self {
|
|
- date: if is_previous_day {
|
|
- (self.date - duration)
|
|
- .previous_day()
|
|
- .expect("resulting value is out of range")
|
|
- } else {
|
|
- self.date - duration
|
|
- },
|
|
- time,
|
|
- offset: self.offset,
|
|
- }
|
|
- }
|
|
-}
|
|
-
|
|
-impl<O: MaybeOffset> SubAssign<Duration> for DateTime<O> {
|
|
- fn sub_assign(&mut self, rhs: Duration) {
|
|
- *self = *self - rhs;
|
|
- }
|
|
-}
|
|
-
|
|
-impl<O: MaybeOffset> SubAssign<StdDuration> for DateTime<O> {
|
|
- fn sub_assign(&mut self, rhs: StdDuration) {
|
|
- *self = *self - rhs;
|
|
- }
|
|
-}
|
|
-
|
|
-impl<O: MaybeOffset> Sub<Self> for DateTime<O> {
|
|
- type Output = Duration;
|
|
-
|
|
- fn sub(self, rhs: Self) -> Self::Output {
|
|
- let base = (self.date - rhs.date) + (self.time - rhs.time);
|
|
-
|
|
- match (
|
|
- maybe_offset_as_offset_opt::<O>(self.offset),
|
|
- maybe_offset_as_offset_opt::<O>(rhs.offset),
|
|
- ) {
|
|
- (Some(self_offset), Some(rhs_offset)) => {
|
|
- let adjustment = Duration::seconds(
|
|
- (self_offset.whole_seconds() - rhs_offset.whole_seconds()) as i64,
|
|
- );
|
|
- base - adjustment
|
|
- }
|
|
- (left, right) => {
|
|
- debug_assert!(
|
|
- left.is_none() && right.is_none(),
|
|
- "offset type should not be different for the same type"
|
|
- );
|
|
- base
|
|
- }
|
|
- }
|
|
- }
|
|
-}
|
|
-
|
|
-#[cfg(feature = "std")]
|
|
-impl Add<Duration> for SystemTime {
|
|
- type Output = Self;
|
|
-
|
|
- fn add(self, duration: Duration) -> Self::Output {
|
|
- if duration.is_zero() {
|
|
- self
|
|
- } else if duration.is_positive() {
|
|
- self + duration.unsigned_abs()
|
|
- } else {
|
|
- debug_assert!(duration.is_negative());
|
|
- self - duration.unsigned_abs()
|
|
- }
|
|
- }
|
|
-}
|
|
-
|
|
-impl_add_assign!(SystemTime: #[cfg(feature = "std")] Duration);
|
|
-
|
|
-#[cfg(feature = "std")]
|
|
-impl Sub<Duration> for SystemTime {
|
|
- type Output = Self;
|
|
-
|
|
- fn sub(self, duration: Duration) -> Self::Output {
|
|
- (DateTime::from(self) - duration).into()
|
|
- }
|
|
-}
|
|
-
|
|
-impl_sub_assign!(SystemTime: #[cfg(feature = "std")] Duration);
|
|
-
|
|
-#[cfg(feature = "std")]
|
|
-impl Sub<SystemTime> for DateTime<offset_kind::Fixed> {
|
|
- type Output = Duration;
|
|
-
|
|
- fn sub(self, rhs: SystemTime) -> Self::Output {
|
|
- self - Self::from(rhs)
|
|
- }
|
|
-}
|
|
-
|
|
-#[cfg(feature = "std")]
|
|
-impl Sub<DateTime<offset_kind::Fixed>> for SystemTime {
|
|
- type Output = Duration;
|
|
-
|
|
- fn sub(self, rhs: DateTime<offset_kind::Fixed>) -> Self::Output {
|
|
- DateTime::<offset_kind::Fixed>::from(self) - rhs
|
|
- }
|
|
-}
|
|
-
|
|
-#[cfg(feature = "std")]
|
|
-impl PartialEq<SystemTime> for DateTime<offset_kind::Fixed> {
|
|
- fn eq(&self, rhs: &SystemTime) -> bool {
|
|
- self == &Self::from(*rhs)
|
|
- }
|
|
-}
|
|
-
|
|
-#[cfg(feature = "std")]
|
|
-impl PartialEq<DateTime<offset_kind::Fixed>> for SystemTime {
|
|
- fn eq(&self, rhs: &DateTime<offset_kind::Fixed>) -> bool {
|
|
- &DateTime::<offset_kind::Fixed>::from(*self) == rhs
|
|
- }
|
|
-}
|
|
-
|
|
-#[cfg(feature = "std")]
|
|
-impl PartialOrd<SystemTime> for DateTime<offset_kind::Fixed> {
|
|
- fn partial_cmp(&self, other: &SystemTime) -> Option<Ordering> {
|
|
- self.partial_cmp(&Self::from(*other))
|
|
- }
|
|
-}
|
|
-
|
|
-#[cfg(feature = "std")]
|
|
-impl PartialOrd<DateTime<offset_kind::Fixed>> for SystemTime {
|
|
- fn partial_cmp(&self, other: &DateTime<offset_kind::Fixed>) -> Option<Ordering> {
|
|
- DateTime::<offset_kind::Fixed>::from(*self).partial_cmp(other)
|
|
- }
|
|
-}
|
|
-
|
|
-#[cfg(feature = "std")]
|
|
-impl From<SystemTime> for DateTime<offset_kind::Fixed> {
|
|
- fn from(system_time: SystemTime) -> Self {
|
|
- match system_time.duration_since(SystemTime::UNIX_EPOCH) {
|
|
- Ok(duration) => Self::UNIX_EPOCH + duration,
|
|
- Err(err) => Self::UNIX_EPOCH - err.duration(),
|
|
- }
|
|
- }
|
|
-}
|
|
-
|
|
-#[allow(clippy::fallible_impl_from)] // caused by `debug_assert!`
|
|
-#[cfg(feature = "std")]
|
|
-impl From<DateTime<offset_kind::Fixed>> for SystemTime {
|
|
- fn from(datetime: DateTime<offset_kind::Fixed>) -> Self {
|
|
- let duration = datetime - DateTime::<offset_kind::Fixed>::UNIX_EPOCH;
|
|
-
|
|
- if duration.is_zero() {
|
|
- Self::UNIX_EPOCH
|
|
- } else if duration.is_positive() {
|
|
- Self::UNIX_EPOCH + duration.unsigned_abs()
|
|
- } else {
|
|
- debug_assert!(duration.is_negative());
|
|
- Self::UNIX_EPOCH - duration.unsigned_abs()
|
|
- }
|
|
- }
|
|
-}
|
|
-
|
|
-#[allow(clippy::fallible_impl_from)]
|
|
-#[cfg(all(
|
|
- target_family = "wasm",
|
|
- not(any(target_os = "emscripten", target_os = "wasi")),
|
|
- feature = "wasm-bindgen"
|
|
-))]
|
|
-impl From<js_sys::Date> for DateTime<offset_kind::Fixed> {
|
|
- fn from(js_date: js_sys::Date) -> Self {
|
|
- // get_time() returns milliseconds
|
|
- let timestamp_nanos = (js_date.get_time() * Nanosecond::per(Millisecond) as f64) as i128;
|
|
- Self::from_unix_timestamp_nanos(timestamp_nanos)
|
|
- .expect("invalid timestamp: Timestamp cannot fit in range")
|
|
- }
|
|
-}
|
|
-
|
|
-#[cfg(all(
|
|
- target_family = "wasm",
|
|
- not(any(target_os = "emscripten", target_os = "wasi")),
|
|
- feature = "wasm-bindgen"
|
|
-))]
|
|
-impl From<DateTime<offset_kind::Fixed>> for js_sys::Date {
|
|
- fn from(datetime: DateTime<offset_kind::Fixed>) -> Self {
|
|
- // new Date() takes milliseconds
|
|
- let timestamp =
|
|
- (datetime.unix_timestamp_nanos() / Nanosecond::per(Millisecond) as i128) as f64;
|
|
- js_sys::Date::new(×tamp.into())
|
|
- }
|
|
-}
|
|
-// endregion trait impls
|
|
diff --git a/vendor/time/src/duration.rs b/vendor/time/src/duration.rs
|
|
index 4b4134f..0da8385 100644
|
|
--- a/vendor/time/src/duration.rs
|
|
+++ b/vendor/time/src/duration.rs
|
|
@@ -7,6 +7,7 @@ use core::ops::{Add, AddAssign, Div, Mul, Neg, Sub, SubAssign};
|
|
use core::time::Duration as StdDuration;
|
|
|
|
use deranged::RangedI32;
|
|
+use num_conv::prelude::*;
|
|
|
|
use crate::convert::*;
|
|
use crate::error;
|
|
@@ -14,6 +15,7 @@ use crate::internal_macros::{
|
|
const_try_opt, expect_opt, impl_add_assign, impl_div_assign, impl_mul_assign, impl_sub_assign,
|
|
};
|
|
#[cfg(feature = "std")]
|
|
+#[allow(deprecated)]
|
|
use crate::Instant;
|
|
|
|
/// By explicitly inserting this enum where padding is expected, the compiler is able to better
|
|
@@ -380,6 +382,10 @@ impl Duration {
|
|
/// assert_eq!(Duration::new(-1, 0), (-1).seconds());
|
|
/// assert_eq!(Duration::new(1, 2_000_000_000), 3.seconds());
|
|
/// ```
|
|
+ ///
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if an overflow occurs.
|
|
pub const fn new(mut seconds: i64, mut nanoseconds: i32) -> Self {
|
|
seconds = expect_opt!(
|
|
seconds.checked_add(nanoseconds as i64 / Nanosecond::per(Second) as i64),
|
|
@@ -431,6 +437,10 @@ impl Duration {
|
|
/// # use time::{Duration, ext::NumericalDuration};
|
|
/// assert_eq!(Duration::weeks(1), 604_800.seconds());
|
|
/// ```
|
|
+ ///
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if an overflow occurs.
|
|
pub const fn weeks(weeks: i64) -> Self {
|
|
Self::seconds(expect_opt!(
|
|
weeks.checked_mul(Second::per(Week) as _),
|
|
@@ -445,6 +455,10 @@ impl Duration {
|
|
/// # use time::{Duration, ext::NumericalDuration};
|
|
/// assert_eq!(Duration::days(1), 86_400.seconds());
|
|
/// ```
|
|
+ ///
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if an overflow occurs.
|
|
pub const fn days(days: i64) -> Self {
|
|
Self::seconds(expect_opt!(
|
|
days.checked_mul(Second::per(Day) as _),
|
|
@@ -459,6 +473,10 @@ impl Duration {
|
|
/// # use time::{Duration, ext::NumericalDuration};
|
|
/// assert_eq!(Duration::hours(1), 3_600.seconds());
|
|
/// ```
|
|
+ ///
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if an overflow occurs.
|
|
pub const fn hours(hours: i64) -> Self {
|
|
Self::seconds(expect_opt!(
|
|
hours.checked_mul(Second::per(Hour) as _),
|
|
@@ -473,6 +491,10 @@ impl Duration {
|
|
/// # use time::{Duration, ext::NumericalDuration};
|
|
/// assert_eq!(Duration::minutes(1), 60.seconds());
|
|
/// ```
|
|
+ ///
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if an overflow occurs.
|
|
pub const fn minutes(minutes: i64) -> Self {
|
|
Self::seconds(expect_opt!(
|
|
minutes.checked_mul(Second::per(Minute) as _),
|
|
@@ -836,7 +858,7 @@ impl Duration {
|
|
|
|
/// Get the number of milliseconds past the number of whole seconds.
|
|
///
|
|
- /// Always in the range `-1_000..1_000`.
|
|
+ /// Always in the range `-999..=999`.
|
|
///
|
|
/// ```rust
|
|
/// # use time::ext::NumericalDuration;
|
|
@@ -864,7 +886,7 @@ impl Duration {
|
|
|
|
/// Get the number of microseconds past the number of whole seconds.
|
|
///
|
|
- /// Always in the range `-1_000_000..1_000_000`.
|
|
+ /// Always in the range `-999_999..=999_999`.
|
|
///
|
|
/// ```rust
|
|
/// # use time::ext::NumericalDuration;
|
|
@@ -890,7 +912,7 @@ impl Duration {
|
|
|
|
/// Get the number of nanoseconds past the number of whole seconds.
|
|
///
|
|
- /// The returned value will always be in the range `-1_000_000_000..1_000_000_000`.
|
|
+ /// The returned value will always be in the range `-999_999_999..=999_999_999`.
|
|
///
|
|
/// ```rust
|
|
/// # use time::ext::NumericalDuration;
|
|
@@ -1002,6 +1024,25 @@ impl Duration {
|
|
// Safety: `nanoseconds` is in range.
|
|
unsafe { Some(Self::new_unchecked(secs, nanos)) }
|
|
}
|
|
+
|
|
+ /// Computes `-self`, returning `None` if the result would overflow.
|
|
+ ///
|
|
+ /// ```rust
|
|
+ /// # use time::ext::NumericalDuration;
|
|
+ /// # use time::Duration;
|
|
+ /// assert_eq!(5.seconds().checked_neg(), Some((-5).seconds()));
|
|
+ /// assert_eq!(Duration::MIN.checked_neg(), None);
|
|
+ /// ```
|
|
+ pub const fn checked_neg(self) -> Option<Self> {
|
|
+ if self.seconds == i64::MIN {
|
|
+ None
|
|
+ } else {
|
|
+ Some(Self::new_ranged_unchecked(
|
|
+ -self.seconds,
|
|
+ self.nanoseconds.neg(),
|
|
+ ))
|
|
+ }
|
|
+ }
|
|
// endregion checked arithmetic
|
|
|
|
// region: saturating arithmetic
|
|
@@ -1127,6 +1168,11 @@ impl Duration {
|
|
/// Runs a closure, returning the duration of time it took to run. The return value of the
|
|
/// closure is provided in the second part of the tuple.
|
|
#[cfg(feature = "std")]
|
|
+ #[deprecated(
|
|
+ since = "0.3.32",
|
|
+ note = "extremely limited use case, not intended for benchmarking"
|
|
+ )]
|
|
+ #[allow(deprecated)]
|
|
pub fn time_fn<T>(f: impl FnOnce() -> T) -> (Self, T) {
|
|
let start = Instant::now();
|
|
let return_value = f();
|
|
@@ -1205,23 +1251,26 @@ impl fmt::Display for Duration {
|
|
let seconds = self.seconds.unsigned_abs();
|
|
let nanoseconds = self.nanoseconds.get().unsigned_abs();
|
|
|
|
- item!("d", seconds / Second::per(Day) as u64)?;
|
|
+ item!("d", seconds / Second::per(Day).extend::<u64>())?;
|
|
item!(
|
|
"h",
|
|
- seconds / Second::per(Hour) as u64 % Hour::per(Day) as u64
|
|
+ seconds / Second::per(Hour).extend::<u64>() % Hour::per(Day).extend::<u64>()
|
|
)?;
|
|
item!(
|
|
"m",
|
|
- seconds / Second::per(Minute) as u64 % Minute::per(Hour) as u64
|
|
+ seconds / Second::per(Minute).extend::<u64>() % Minute::per(Hour).extend::<u64>()
|
|
)?;
|
|
- item!("s", seconds % Second::per(Minute) as u64)?;
|
|
+ item!("s", seconds % Second::per(Minute).extend::<u64>())?;
|
|
item!("ms", nanoseconds / Nanosecond::per(Millisecond))?;
|
|
item!(
|
|
"µs",
|
|
- nanoseconds / Nanosecond::per(Microsecond) as u32
|
|
- % Microsecond::per(Millisecond) as u32
|
|
+ nanoseconds / Nanosecond::per(Microsecond).extend::<u32>()
|
|
+ % Microsecond::per(Millisecond).extend::<u32>()
|
|
+ )?;
|
|
+ item!(
|
|
+ "ns",
|
|
+ nanoseconds % Nanosecond::per(Microsecond).extend::<u32>()
|
|
)?;
|
|
- item!("ns", nanoseconds % Nanosecond::per(Microsecond) as u32)?;
|
|
}
|
|
|
|
Ok(())
|
|
@@ -1237,7 +1286,7 @@ impl TryFrom<StdDuration> for Duration {
|
|
.as_secs()
|
|
.try_into()
|
|
.map_err(|_| error::ConversionRange)?,
|
|
- original.subsec_nanos() as _,
|
|
+ original.subsec_nanos().cast_signed(),
|
|
))
|
|
}
|
|
}
|
|
@@ -1263,6 +1312,9 @@ impl TryFrom<Duration> for StdDuration {
|
|
impl Add for Duration {
|
|
type Output = Self;
|
|
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if an overflow occurs.
|
|
fn add(self, rhs: Self) -> Self::Output {
|
|
self.checked_add(rhs)
|
|
.expect("overflow when adding durations")
|
|
@@ -1272,6 +1324,9 @@ impl Add for Duration {
|
|
impl Add<StdDuration> for Duration {
|
|
type Output = Self;
|
|
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if an overflow occurs.
|
|
fn add(self, std_duration: StdDuration) -> Self::Output {
|
|
self + Self::try_from(std_duration)
|
|
.expect("overflow converting `std::time::Duration` to `time::Duration`")
|
|
@@ -1289,6 +1344,9 @@ impl Add<Duration> for StdDuration {
|
|
impl_add_assign!(Duration: Self, StdDuration);
|
|
|
|
impl AddAssign<Duration> for StdDuration {
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if the resulting addition cannot be represented.
|
|
fn add_assign(&mut self, rhs: Duration) {
|
|
*self = (*self + rhs).try_into().expect(
|
|
"Cannot represent a resulting duration in std. Try `let x = x + rhs;`, which will \
|
|
@@ -1301,13 +1359,16 @@ impl Neg for Duration {
|
|
type Output = Self;
|
|
|
|
fn neg(self) -> Self::Output {
|
|
- Self::new_ranged_unchecked(-self.seconds, self.nanoseconds.neg())
|
|
+ self.checked_neg().expect("overflow when negating duration")
|
|
}
|
|
}
|
|
|
|
impl Sub for Duration {
|
|
type Output = Self;
|
|
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if an overflow occurs.
|
|
fn sub(self, rhs: Self) -> Self::Output {
|
|
self.checked_sub(rhs)
|
|
.expect("overflow when subtracting durations")
|
|
@@ -1317,6 +1378,9 @@ impl Sub for Duration {
|
|
impl Sub<StdDuration> for Duration {
|
|
type Output = Self;
|
|
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if an overflow occurs.
|
|
fn sub(self, rhs: StdDuration) -> Self::Output {
|
|
self - Self::try_from(rhs)
|
|
.expect("overflow converting `std::time::Duration` to `time::Duration`")
|
|
@@ -1326,6 +1390,9 @@ impl Sub<StdDuration> for Duration {
|
|
impl Sub<Duration> for StdDuration {
|
|
type Output = Duration;
|
|
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if an overflow occurs.
|
|
fn sub(self, rhs: Duration) -> Self::Output {
|
|
Duration::try_from(self)
|
|
.expect("overflow converting `std::time::Duration` to `time::Duration`")
|
|
@@ -1336,6 +1403,9 @@ impl Sub<Duration> for StdDuration {
|
|
impl_sub_assign!(Duration: Self, StdDuration);
|
|
|
|
impl SubAssign<Duration> for StdDuration {
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if the resulting subtraction can not be represented.
|
|
fn sub_assign(&mut self, rhs: Duration) {
|
|
*self = (*self - rhs).try_into().expect(
|
|
"Cannot represent a resulting duration in std. Try `let x = x - rhs;`, which will \
|
|
@@ -1353,7 +1423,7 @@ macro_rules! duration_mul_div_int {
|
|
fn mul(self, rhs: $type) -> Self::Output {
|
|
Self::nanoseconds_i128(
|
|
self.whole_nanoseconds()
|
|
- .checked_mul(rhs as _)
|
|
+ .checked_mul(rhs.cast_signed().extend::<i128>())
|
|
.expect("overflow when multiplying duration")
|
|
)
|
|
}
|
|
@@ -1371,7 +1441,9 @@ macro_rules! duration_mul_div_int {
|
|
type Output = Self;
|
|
|
|
fn div(self, rhs: $type) -> Self::Output {
|
|
- Self::nanoseconds_i128(self.whole_nanoseconds() / rhs as i128)
|
|
+ Self::nanoseconds_i128(
|
|
+ self.whole_nanoseconds() / rhs.cast_signed().extend::<i128>()
|
|
+ )
|
|
}
|
|
}
|
|
)+};
|
|
@@ -1468,14 +1540,18 @@ impl PartialEq<Duration> for StdDuration {
|
|
|
|
impl PartialOrd<StdDuration> for Duration {
|
|
fn partial_cmp(&self, rhs: &StdDuration) -> Option<Ordering> {
|
|
- if rhs.as_secs() > i64::MAX as _ {
|
|
+ if rhs.as_secs() > i64::MAX.cast_unsigned() {
|
|
return Some(Ordering::Less);
|
|
}
|
|
|
|
Some(
|
|
self.seconds
|
|
- .cmp(&(rhs.as_secs() as _))
|
|
- .then_with(|| self.nanoseconds.get().cmp(&(rhs.subsec_nanos() as _))),
|
|
+ .cmp(&rhs.as_secs().cast_signed())
|
|
+ .then_with(|| {
|
|
+ self.nanoseconds
|
|
+ .get()
|
|
+ .cmp(&rhs.subsec_nanos().cast_signed())
|
|
+ }),
|
|
)
|
|
}
|
|
}
|
|
diff --git a/vendor/time/src/ext.rs b/vendor/time/src/ext.rs
|
|
deleted file mode 100644
|
|
index 1b89d41..0000000
|
|
--- a/vendor/time/src/ext.rs
|
|
+++ /dev/null
|
|
@@ -1,319 +0,0 @@
|
|
-//! Extension traits.
|
|
-
|
|
-use core::time::Duration as StdDuration;
|
|
-
|
|
-use crate::convert::*;
|
|
-use crate::Duration;
|
|
-
|
|
-/// Sealed trait to prevent downstream implementations.
|
|
-mod sealed {
|
|
- /// A trait that cannot be implemented by downstream users.
|
|
- pub trait Sealed {}
|
|
- impl Sealed for i64 {}
|
|
- impl Sealed for u64 {}
|
|
- impl Sealed for f64 {}
|
|
-}
|
|
-
|
|
-// region: NumericalDuration
|
|
-/// Create [`Duration`]s from numeric literals.
|
|
-///
|
|
-/// # Examples
|
|
-///
|
|
-/// Basic construction of [`Duration`]s.
|
|
-///
|
|
-/// ```rust
|
|
-/// # use time::{Duration, ext::NumericalDuration};
|
|
-/// assert_eq!(5.nanoseconds(), Duration::nanoseconds(5));
|
|
-/// assert_eq!(5.microseconds(), Duration::microseconds(5));
|
|
-/// assert_eq!(5.milliseconds(), Duration::milliseconds(5));
|
|
-/// assert_eq!(5.seconds(), Duration::seconds(5));
|
|
-/// assert_eq!(5.minutes(), Duration::minutes(5));
|
|
-/// assert_eq!(5.hours(), Duration::hours(5));
|
|
-/// assert_eq!(5.days(), Duration::days(5));
|
|
-/// assert_eq!(5.weeks(), Duration::weeks(5));
|
|
-/// ```
|
|
-///
|
|
-/// Signed integers work as well!
|
|
-///
|
|
-/// ```rust
|
|
-/// # use time::{Duration, ext::NumericalDuration};
|
|
-/// assert_eq!((-5).nanoseconds(), Duration::nanoseconds(-5));
|
|
-/// assert_eq!((-5).microseconds(), Duration::microseconds(-5));
|
|
-/// assert_eq!((-5).milliseconds(), Duration::milliseconds(-5));
|
|
-/// assert_eq!((-5).seconds(), Duration::seconds(-5));
|
|
-/// assert_eq!((-5).minutes(), Duration::minutes(-5));
|
|
-/// assert_eq!((-5).hours(), Duration::hours(-5));
|
|
-/// assert_eq!((-5).days(), Duration::days(-5));
|
|
-/// assert_eq!((-5).weeks(), Duration::weeks(-5));
|
|
-/// ```
|
|
-///
|
|
-/// Just like any other [`Duration`], they can be added, subtracted, etc.
|
|
-///
|
|
-/// ```rust
|
|
-/// # use time::ext::NumericalDuration;
|
|
-/// assert_eq!(2.seconds() + 500.milliseconds(), 2_500.milliseconds());
|
|
-/// assert_eq!(2.seconds() - 500.milliseconds(), 1_500.milliseconds());
|
|
-/// ```
|
|
-///
|
|
-/// When called on floating point values, any remainder of the floating point value will be
|
|
-/// truncated. Keep in mind that floating point numbers are inherently imprecise and have limited
|
|
-/// capacity.
|
|
-pub trait NumericalDuration: sealed::Sealed {
|
|
- /// Create a [`Duration`] from the number of nanoseconds.
|
|
- fn nanoseconds(self) -> Duration;
|
|
- /// Create a [`Duration`] from the number of microseconds.
|
|
- fn microseconds(self) -> Duration;
|
|
- /// Create a [`Duration`] from the number of milliseconds.
|
|
- fn milliseconds(self) -> Duration;
|
|
- /// Create a [`Duration`] from the number of seconds.
|
|
- fn seconds(self) -> Duration;
|
|
- /// Create a [`Duration`] from the number of minutes.
|
|
- fn minutes(self) -> Duration;
|
|
- /// Create a [`Duration`] from the number of hours.
|
|
- fn hours(self) -> Duration;
|
|
- /// Create a [`Duration`] from the number of days.
|
|
- fn days(self) -> Duration;
|
|
- /// Create a [`Duration`] from the number of weeks.
|
|
- fn weeks(self) -> Duration;
|
|
-}
|
|
-
|
|
-impl NumericalDuration for i64 {
|
|
- fn nanoseconds(self) -> Duration {
|
|
- Duration::nanoseconds(self)
|
|
- }
|
|
-
|
|
- fn microseconds(self) -> Duration {
|
|
- Duration::microseconds(self)
|
|
- }
|
|
-
|
|
- fn milliseconds(self) -> Duration {
|
|
- Duration::milliseconds(self)
|
|
- }
|
|
-
|
|
- fn seconds(self) -> Duration {
|
|
- Duration::seconds(self)
|
|
- }
|
|
-
|
|
- fn minutes(self) -> Duration {
|
|
- Duration::minutes(self)
|
|
- }
|
|
-
|
|
- fn hours(self) -> Duration {
|
|
- Duration::hours(self)
|
|
- }
|
|
-
|
|
- fn days(self) -> Duration {
|
|
- Duration::days(self)
|
|
- }
|
|
-
|
|
- fn weeks(self) -> Duration {
|
|
- Duration::weeks(self)
|
|
- }
|
|
-}
|
|
-
|
|
-impl NumericalDuration for f64 {
|
|
- fn nanoseconds(self) -> Duration {
|
|
- Duration::nanoseconds(self as _)
|
|
- }
|
|
-
|
|
- fn microseconds(self) -> Duration {
|
|
- Duration::nanoseconds((self * Nanosecond::per(Microsecond) as Self) as _)
|
|
- }
|
|
-
|
|
- fn milliseconds(self) -> Duration {
|
|
- Duration::nanoseconds((self * Nanosecond::per(Millisecond) as Self) as _)
|
|
- }
|
|
-
|
|
- fn seconds(self) -> Duration {
|
|
- Duration::nanoseconds((self * Nanosecond::per(Second) as Self) as _)
|
|
- }
|
|
-
|
|
- fn minutes(self) -> Duration {
|
|
- Duration::nanoseconds((self * Nanosecond::per(Minute) as Self) as _)
|
|
- }
|
|
-
|
|
- fn hours(self) -> Duration {
|
|
- Duration::nanoseconds((self * Nanosecond::per(Hour) as Self) as _)
|
|
- }
|
|
-
|
|
- fn days(self) -> Duration {
|
|
- Duration::nanoseconds((self * Nanosecond::per(Day) as Self) as _)
|
|
- }
|
|
-
|
|
- fn weeks(self) -> Duration {
|
|
- Duration::nanoseconds((self * Nanosecond::per(Week) as Self) as _)
|
|
- }
|
|
-}
|
|
-// endregion NumericalDuration
|
|
-
|
|
-// region: NumericalStdDuration
|
|
-/// Create [`std::time::Duration`]s from numeric literals.
|
|
-///
|
|
-/// # Examples
|
|
-///
|
|
-/// Basic construction of [`std::time::Duration`]s.
|
|
-///
|
|
-/// ```rust
|
|
-/// # use time::ext::NumericalStdDuration;
|
|
-/// # use core::time::Duration;
|
|
-/// assert_eq!(5.std_nanoseconds(), Duration::from_nanos(5));
|
|
-/// assert_eq!(5.std_microseconds(), Duration::from_micros(5));
|
|
-/// assert_eq!(5.std_milliseconds(), Duration::from_millis(5));
|
|
-/// assert_eq!(5.std_seconds(), Duration::from_secs(5));
|
|
-/// assert_eq!(5.std_minutes(), Duration::from_secs(5 * 60));
|
|
-/// assert_eq!(5.std_hours(), Duration::from_secs(5 * 3_600));
|
|
-/// assert_eq!(5.std_days(), Duration::from_secs(5 * 86_400));
|
|
-/// assert_eq!(5.std_weeks(), Duration::from_secs(5 * 604_800));
|
|
-/// ```
|
|
-///
|
|
-/// Just like any other [`std::time::Duration`], they can be added, subtracted, etc.
|
|
-///
|
|
-/// ```rust
|
|
-/// # use time::ext::NumericalStdDuration;
|
|
-/// assert_eq!(
|
|
-/// 2.std_seconds() + 500.std_milliseconds(),
|
|
-/// 2_500.std_milliseconds()
|
|
-/// );
|
|
-/// assert_eq!(
|
|
-/// 2.std_seconds() - 500.std_milliseconds(),
|
|
-/// 1_500.std_milliseconds()
|
|
-/// );
|
|
-/// ```
|
|
-///
|
|
-/// When called on floating point values, any remainder of the floating point value will be
|
|
-/// truncated. Keep in mind that floating point numbers are inherently imprecise and have limited
|
|
-/// capacity.
|
|
-pub trait NumericalStdDuration: sealed::Sealed {
|
|
- /// Create a [`std::time::Duration`] from the number of nanoseconds.
|
|
- fn std_nanoseconds(self) -> StdDuration;
|
|
- /// Create a [`std::time::Duration`] from the number of microseconds.
|
|
- fn std_microseconds(self) -> StdDuration;
|
|
- /// Create a [`std::time::Duration`] from the number of milliseconds.
|
|
- fn std_milliseconds(self) -> StdDuration;
|
|
- /// Create a [`std::time::Duration`] from the number of seconds.
|
|
- fn std_seconds(self) -> StdDuration;
|
|
- /// Create a [`std::time::Duration`] from the number of minutes.
|
|
- fn std_minutes(self) -> StdDuration;
|
|
- /// Create a [`std::time::Duration`] from the number of hours.
|
|
- fn std_hours(self) -> StdDuration;
|
|
- /// Create a [`std::time::Duration`] from the number of days.
|
|
- fn std_days(self) -> StdDuration;
|
|
- /// Create a [`std::time::Duration`] from the number of weeks.
|
|
- fn std_weeks(self) -> StdDuration;
|
|
-}
|
|
-
|
|
-impl NumericalStdDuration for u64 {
|
|
- fn std_nanoseconds(self) -> StdDuration {
|
|
- StdDuration::from_nanos(self)
|
|
- }
|
|
-
|
|
- fn std_microseconds(self) -> StdDuration {
|
|
- StdDuration::from_micros(self)
|
|
- }
|
|
-
|
|
- fn std_milliseconds(self) -> StdDuration {
|
|
- StdDuration::from_millis(self)
|
|
- }
|
|
-
|
|
- fn std_seconds(self) -> StdDuration {
|
|
- StdDuration::from_secs(self)
|
|
- }
|
|
-
|
|
- fn std_minutes(self) -> StdDuration {
|
|
- StdDuration::from_secs(
|
|
- self.checked_mul(Second::per(Minute) as Self)
|
|
- .expect("overflow constructing `time::Duration`"),
|
|
- )
|
|
- }
|
|
-
|
|
- fn std_hours(self) -> StdDuration {
|
|
- StdDuration::from_secs(
|
|
- self.checked_mul(Second::per(Hour) as Self)
|
|
- .expect("overflow constructing `time::Duration`"),
|
|
- )
|
|
- }
|
|
-
|
|
- fn std_days(self) -> StdDuration {
|
|
- StdDuration::from_secs(
|
|
- self.checked_mul(Second::per(Day) as Self)
|
|
- .expect("overflow constructing `time::Duration`"),
|
|
- )
|
|
- }
|
|
-
|
|
- fn std_weeks(self) -> StdDuration {
|
|
- StdDuration::from_secs(
|
|
- self.checked_mul(Second::per(Week) as Self)
|
|
- .expect("overflow constructing `time::Duration`"),
|
|
- )
|
|
- }
|
|
-}
|
|
-
|
|
-impl NumericalStdDuration for f64 {
|
|
- fn std_nanoseconds(self) -> StdDuration {
|
|
- assert!(self >= 0.);
|
|
- StdDuration::from_nanos(self as _)
|
|
- }
|
|
-
|
|
- fn std_microseconds(self) -> StdDuration {
|
|
- assert!(self >= 0.);
|
|
- StdDuration::from_nanos((self * Nanosecond::per(Microsecond) as Self) as _)
|
|
- }
|
|
-
|
|
- fn std_milliseconds(self) -> StdDuration {
|
|
- assert!(self >= 0.);
|
|
- StdDuration::from_nanos((self * Nanosecond::per(Millisecond) as Self) as _)
|
|
- }
|
|
-
|
|
- fn std_seconds(self) -> StdDuration {
|
|
- assert!(self >= 0.);
|
|
- StdDuration::from_nanos((self * Nanosecond::per(Second) as Self) as _)
|
|
- }
|
|
-
|
|
- fn std_minutes(self) -> StdDuration {
|
|
- assert!(self >= 0.);
|
|
- StdDuration::from_nanos((self * Nanosecond::per(Minute) as Self) as _)
|
|
- }
|
|
-
|
|
- fn std_hours(self) -> StdDuration {
|
|
- assert!(self >= 0.);
|
|
- StdDuration::from_nanos((self * Nanosecond::per(Hour) as Self) as _)
|
|
- }
|
|
-
|
|
- fn std_days(self) -> StdDuration {
|
|
- assert!(self >= 0.);
|
|
- StdDuration::from_nanos((self * Nanosecond::per(Day) as Self) as _)
|
|
- }
|
|
-
|
|
- fn std_weeks(self) -> StdDuration {
|
|
- assert!(self >= 0.);
|
|
- StdDuration::from_nanos((self * Nanosecond::per(Week) as Self) as _)
|
|
- }
|
|
-}
|
|
-// endregion NumericalStdDuration
|
|
-
|
|
-// region: DigitCount
|
|
-/// A trait that indicates the formatted width of the value can be determined.
|
|
-///
|
|
-/// Note that this should not be implemented for any signed integers. This forces the caller to
|
|
-/// write the sign if desired.
|
|
-pub(crate) trait DigitCount {
|
|
- /// The number of digits in the stringified value.
|
|
- fn num_digits(self) -> u8;
|
|
-}
|
|
-
|
|
-/// A macro to generate implementations of `DigitCount` for unsigned integers.
|
|
-macro_rules! impl_digit_count {
|
|
- ($($t:ty),* $(,)?) => {
|
|
- $(impl DigitCount for $t {
|
|
- fn num_digits(self) -> u8 {
|
|
- match self.checked_ilog10() {
|
|
- Some(n) => (n as u8) + 1,
|
|
- None => 1,
|
|
- }
|
|
- }
|
|
- })*
|
|
- };
|
|
-}
|
|
-
|
|
-impl_digit_count!(u8, u16, u32);
|
|
-// endregion DigitCount
|
|
diff --git a/vendor/time/src/ext/digit_count.rs b/vendor/time/src/ext/digit_count.rs
|
|
new file mode 100644
|
|
index 0000000..fb42ce9
|
|
--- /dev/null
|
|
+++ b/vendor/time/src/ext/digit_count.rs
|
|
@@ -0,0 +1,26 @@
|
|
+use num_conv::prelude::*;
|
|
+
|
|
+/// A trait that indicates the formatted width of the value can be determined.
|
|
+///
|
|
+/// Note that this should not be implemented for any signed integers. This forces the caller to
|
|
+/// write the sign if desired.
|
|
+pub(crate) trait DigitCount {
|
|
+ /// The number of digits in the stringified value.
|
|
+ fn num_digits(self) -> u8;
|
|
+}
|
|
+
|
|
+/// A macro to generate implementations of `DigitCount` for unsigned integers.
|
|
+macro_rules! impl_digit_count {
|
|
+ ($($t:ty),* $(,)?) => {
|
|
+ $(impl DigitCount for $t {
|
|
+ fn num_digits(self) -> u8 {
|
|
+ match self.checked_ilog10() {
|
|
+ Some(n) => n.truncate::<u8>() + 1,
|
|
+ None => 1,
|
|
+ }
|
|
+ }
|
|
+ })*
|
|
+ };
|
|
+}
|
|
+
|
|
+impl_digit_count!(u8, u16, u32);
|
|
diff --git a/vendor/time/src/ext/instant.rs b/vendor/time/src/ext/instant.rs
|
|
new file mode 100644
|
|
index 0000000..dbc6a94
|
|
--- /dev/null
|
|
+++ b/vendor/time/src/ext/instant.rs
|
|
@@ -0,0 +1,100 @@
|
|
+use std::time::Instant as StdInstant;
|
|
+
|
|
+use crate::Duration;
|
|
+
|
|
+/// Sealed trait to prevent downstream implementations.
|
|
+mod sealed {
|
|
+ /// A trait that cannot be implemented by downstream users.
|
|
+ pub trait Sealed: Sized {}
|
|
+ impl Sealed for std::time::Instant {}
|
|
+}
|
|
+
|
|
+/// An extension trait for [`std::time::Instant`] that adds methods for
|
|
+/// [`time::Duration`](Duration)s.
|
|
+pub trait InstantExt: sealed::Sealed {
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This function may panic if the resulting point in time cannot be represented by the
|
|
+ /// underlying data structure. See [`InstantExt::checked_add_signed`] for a non-panicking
|
|
+ /// version.
|
|
+ fn add_signed(self, duration: Duration) -> Self {
|
|
+ self.checked_add_signed(duration)
|
|
+ .expect("overflow when adding duration to instant")
|
|
+ }
|
|
+
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This function may panic if the resulting point in time cannot be represented by the
|
|
+ /// underlying data structure. See [`InstantExt::checked_sub_signed`] for a non-panicking
|
|
+ /// version.
|
|
+ fn sub_signed(self, duration: Duration) -> Self {
|
|
+ self.checked_sub_signed(duration)
|
|
+ .expect("overflow when subtracting duration from instant")
|
|
+ }
|
|
+
|
|
+ /// Returns `Some(t)` where `t` is the time `self.checked_add_signed(duration)` if `t` can be
|
|
+ /// represented as `Instant` (which means it's inside the bounds of the underlying data
|
|
+ /// structure), `None` otherwise.
|
|
+ fn checked_add_signed(&self, duration: Duration) -> Option<Self>;
|
|
+
|
|
+ /// Returns `Some(t)` where `t` is the time `self.checked_sub_signed(duration)` if `t` can be
|
|
+ /// represented as `Instant` (which means it's inside the bounds of the underlying data
|
|
+ /// structure), `None` otherwise.
|
|
+ fn checked_sub_signed(&self, duration: Duration) -> Option<Self>;
|
|
+
|
|
+ /// Returns the amount of time elapsed from another instant to this one. This will be negative
|
|
+ /// if `earlier` is later than `self`.
|
|
+ ///
|
|
+ /// # Example
|
|
+ ///
|
|
+ /// ```rust
|
|
+ /// # use std::thread::sleep;
|
|
+ /// # use std::time::{Duration, Instant};
|
|
+ /// # use time::ext::InstantExt;
|
|
+ /// let now = Instant::now();
|
|
+ /// sleep(Duration::new(1, 0));
|
|
+ /// let new_now = Instant::now();
|
|
+ /// println!("{:?}", new_now.signed_duration_since(now)); // positive
|
|
+ /// println!("{:?}", now.signed_duration_since(new_now)); // negative
|
|
+ /// ```
|
|
+ fn signed_duration_since(&self, earlier: Self) -> Duration;
|
|
+}
|
|
+
|
|
+impl InstantExt for StdInstant {
|
|
+ fn checked_add_signed(&self, duration: Duration) -> Option<Self> {
|
|
+ if duration.is_positive() {
|
|
+ self.checked_add(duration.unsigned_abs())
|
|
+ } else if duration.is_negative() {
|
|
+ #[allow(clippy::unchecked_duration_subtraction)]
|
|
+ self.checked_sub(duration.unsigned_abs())
|
|
+ } else {
|
|
+ debug_assert!(duration.is_zero());
|
|
+ Some(*self)
|
|
+ }
|
|
+ }
|
|
+
|
|
+ fn checked_sub_signed(&self, duration: Duration) -> Option<Self> {
|
|
+ if duration.is_positive() {
|
|
+ #[allow(clippy::unchecked_duration_subtraction)]
|
|
+ self.checked_sub(duration.unsigned_abs())
|
|
+ } else if duration.is_negative() {
|
|
+ self.checked_add(duration.unsigned_abs())
|
|
+ } else {
|
|
+ debug_assert!(duration.is_zero());
|
|
+ Some(*self)
|
|
+ }
|
|
+ }
|
|
+
|
|
+ fn signed_duration_since(&self, earlier: Self) -> Duration {
|
|
+ if *self > earlier {
|
|
+ self.saturating_duration_since(earlier)
|
|
+ .try_into()
|
|
+ .unwrap_or(Duration::MAX)
|
|
+ } else {
|
|
+ earlier
|
|
+ .saturating_duration_since(*self)
|
|
+ .try_into()
|
|
+ .map_or(Duration::MIN, |d: Duration| -d)
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/vendor/time/src/ext/mod.rs b/vendor/time/src/ext/mod.rs
|
|
new file mode 100644
|
|
index 0000000..7cc2d0d
|
|
--- /dev/null
|
|
+++ b/vendor/time/src/ext/mod.rs
|
|
@@ -0,0 +1,13 @@
|
|
+//! Extension traits.
|
|
+
|
|
+mod digit_count;
|
|
+#[cfg(feature = "std")]
|
|
+mod instant;
|
|
+mod numerical_duration;
|
|
+mod numerical_std_duration;
|
|
+
|
|
+pub(crate) use self::digit_count::DigitCount;
|
|
+#[cfg(feature = "std")]
|
|
+pub use self::instant::InstantExt;
|
|
+pub use self::numerical_duration::NumericalDuration;
|
|
+pub use self::numerical_std_duration::NumericalStdDuration;
|
|
diff --git a/vendor/time/src/ext/numerical_duration.rs b/vendor/time/src/ext/numerical_duration.rs
|
|
new file mode 100644
|
|
index 0000000..fb9209d
|
|
--- /dev/null
|
|
+++ b/vendor/time/src/ext/numerical_duration.rs
|
|
@@ -0,0 +1,140 @@
|
|
+use crate::convert::*;
|
|
+use crate::Duration;
|
|
+
|
|
+/// Sealed trait to prevent downstream implementations.
|
|
+mod sealed {
|
|
+ /// A trait that cannot be implemented by downstream users.
|
|
+ pub trait Sealed {}
|
|
+ impl Sealed for i64 {}
|
|
+ impl Sealed for f64 {}
|
|
+}
|
|
+
|
|
+/// Create [`Duration`]s from numeric literals.
|
|
+///
|
|
+/// # Examples
|
|
+///
|
|
+/// Basic construction of [`Duration`]s.
|
|
+///
|
|
+/// ```rust
|
|
+/// # use time::{Duration, ext::NumericalDuration};
|
|
+/// assert_eq!(5.nanoseconds(), Duration::nanoseconds(5));
|
|
+/// assert_eq!(5.microseconds(), Duration::microseconds(5));
|
|
+/// assert_eq!(5.milliseconds(), Duration::milliseconds(5));
|
|
+/// assert_eq!(5.seconds(), Duration::seconds(5));
|
|
+/// assert_eq!(5.minutes(), Duration::minutes(5));
|
|
+/// assert_eq!(5.hours(), Duration::hours(5));
|
|
+/// assert_eq!(5.days(), Duration::days(5));
|
|
+/// assert_eq!(5.weeks(), Duration::weeks(5));
|
|
+/// ```
|
|
+///
|
|
+/// Signed integers work as well!
|
|
+///
|
|
+/// ```rust
|
|
+/// # use time::{Duration, ext::NumericalDuration};
|
|
+/// assert_eq!((-5).nanoseconds(), Duration::nanoseconds(-5));
|
|
+/// assert_eq!((-5).microseconds(), Duration::microseconds(-5));
|
|
+/// assert_eq!((-5).milliseconds(), Duration::milliseconds(-5));
|
|
+/// assert_eq!((-5).seconds(), Duration::seconds(-5));
|
|
+/// assert_eq!((-5).minutes(), Duration::minutes(-5));
|
|
+/// assert_eq!((-5).hours(), Duration::hours(-5));
|
|
+/// assert_eq!((-5).days(), Duration::days(-5));
|
|
+/// assert_eq!((-5).weeks(), Duration::weeks(-5));
|
|
+/// ```
|
|
+///
|
|
+/// Just like any other [`Duration`], they can be added, subtracted, etc.
|
|
+///
|
|
+/// ```rust
|
|
+/// # use time::ext::NumericalDuration;
|
|
+/// assert_eq!(2.seconds() + 500.milliseconds(), 2_500.milliseconds());
|
|
+/// assert_eq!(2.seconds() - 500.milliseconds(), 1_500.milliseconds());
|
|
+/// ```
|
|
+///
|
|
+/// When called on floating point values, any remainder of the floating point value will be
|
|
+/// truncated. Keep in mind that floating point numbers are inherently imprecise and have
|
|
+/// limited capacity.
|
|
+pub trait NumericalDuration: sealed::Sealed {
|
|
+ /// Create a [`Duration`] from the number of nanoseconds.
|
|
+ fn nanoseconds(self) -> Duration;
|
|
+ /// Create a [`Duration`] from the number of microseconds.
|
|
+ fn microseconds(self) -> Duration;
|
|
+ /// Create a [`Duration`] from the number of milliseconds.
|
|
+ fn milliseconds(self) -> Duration;
|
|
+ /// Create a [`Duration`] from the number of seconds.
|
|
+ fn seconds(self) -> Duration;
|
|
+ /// Create a [`Duration`] from the number of minutes.
|
|
+ fn minutes(self) -> Duration;
|
|
+ /// Create a [`Duration`] from the number of hours.
|
|
+ fn hours(self) -> Duration;
|
|
+ /// Create a [`Duration`] from the number of days.
|
|
+ fn days(self) -> Duration;
|
|
+ /// Create a [`Duration`] from the number of weeks.
|
|
+ fn weeks(self) -> Duration;
|
|
+}
|
|
+
|
|
+impl NumericalDuration for i64 {
|
|
+ fn nanoseconds(self) -> Duration {
|
|
+ Duration::nanoseconds(self)
|
|
+ }
|
|
+
|
|
+ fn microseconds(self) -> Duration {
|
|
+ Duration::microseconds(self)
|
|
+ }
|
|
+
|
|
+ fn milliseconds(self) -> Duration {
|
|
+ Duration::milliseconds(self)
|
|
+ }
|
|
+
|
|
+ fn seconds(self) -> Duration {
|
|
+ Duration::seconds(self)
|
|
+ }
|
|
+
|
|
+ fn minutes(self) -> Duration {
|
|
+ Duration::minutes(self)
|
|
+ }
|
|
+
|
|
+ fn hours(self) -> Duration {
|
|
+ Duration::hours(self)
|
|
+ }
|
|
+
|
|
+ fn days(self) -> Duration {
|
|
+ Duration::days(self)
|
|
+ }
|
|
+
|
|
+ fn weeks(self) -> Duration {
|
|
+ Duration::weeks(self)
|
|
+ }
|
|
+}
|
|
+
|
|
+impl NumericalDuration for f64 {
|
|
+ fn nanoseconds(self) -> Duration {
|
|
+ Duration::nanoseconds(self as _)
|
|
+ }
|
|
+
|
|
+ fn microseconds(self) -> Duration {
|
|
+ Duration::nanoseconds((self * Nanosecond::per(Microsecond) as Self) as _)
|
|
+ }
|
|
+
|
|
+ fn milliseconds(self) -> Duration {
|
|
+ Duration::nanoseconds((self * Nanosecond::per(Millisecond) as Self) as _)
|
|
+ }
|
|
+
|
|
+ fn seconds(self) -> Duration {
|
|
+ Duration::nanoseconds((self * Nanosecond::per(Second) as Self) as _)
|
|
+ }
|
|
+
|
|
+ fn minutes(self) -> Duration {
|
|
+ Duration::nanoseconds((self * Nanosecond::per(Minute) as Self) as _)
|
|
+ }
|
|
+
|
|
+ fn hours(self) -> Duration {
|
|
+ Duration::nanoseconds((self * Nanosecond::per(Hour) as Self) as _)
|
|
+ }
|
|
+
|
|
+ fn days(self) -> Duration {
|
|
+ Duration::nanoseconds((self * Nanosecond::per(Day) as Self) as _)
|
|
+ }
|
|
+
|
|
+ fn weeks(self) -> Duration {
|
|
+ Duration::nanoseconds((self * Nanosecond::per(Week) as Self) as _)
|
|
+ }
|
|
+}
|
|
diff --git a/vendor/time/src/ext/numerical_std_duration.rs b/vendor/time/src/ext/numerical_std_duration.rs
|
|
new file mode 100644
|
|
index 0000000..062b33f
|
|
--- /dev/null
|
|
+++ b/vendor/time/src/ext/numerical_std_duration.rs
|
|
@@ -0,0 +1,192 @@
|
|
+use core::time::Duration as StdDuration;
|
|
+
|
|
+use num_conv::prelude::*;
|
|
+
|
|
+use crate::convert::*;
|
|
+
|
|
+/// Sealed trait to prevent downstream implementations.
|
|
+mod sealed {
|
|
+ /// A trait that cannot be implemented by downstream users.
|
|
+ pub trait Sealed {}
|
|
+ impl Sealed for u64 {}
|
|
+ impl Sealed for f64 {}
|
|
+}
|
|
+
|
|
+/// Create [`std::time::Duration`]s from numeric literals.
|
|
+///
|
|
+/// # Examples
|
|
+///
|
|
+/// Basic construction of [`std::time::Duration`]s.
|
|
+///
|
|
+/// ```rust
|
|
+/// # use time::ext::NumericalStdDuration;
|
|
+/// # use core::time::Duration;
|
|
+/// assert_eq!(5.std_nanoseconds(), Duration::from_nanos(5));
|
|
+/// assert_eq!(5.std_microseconds(), Duration::from_micros(5));
|
|
+/// assert_eq!(5.std_milliseconds(), Duration::from_millis(5));
|
|
+/// assert_eq!(5.std_seconds(), Duration::from_secs(5));
|
|
+/// assert_eq!(5.std_minutes(), Duration::from_secs(5 * 60));
|
|
+/// assert_eq!(5.std_hours(), Duration::from_secs(5 * 3_600));
|
|
+/// assert_eq!(5.std_days(), Duration::from_secs(5 * 86_400));
|
|
+/// assert_eq!(5.std_weeks(), Duration::from_secs(5 * 604_800));
|
|
+/// ```
|
|
+///
|
|
+/// Just like any other [`std::time::Duration`], they can be added, subtracted, etc.
|
|
+///
|
|
+/// ```rust
|
|
+/// # use time::ext::NumericalStdDuration;
|
|
+/// assert_eq!(
|
|
+/// 2.std_seconds() + 500.std_milliseconds(),
|
|
+/// 2_500.std_milliseconds()
|
|
+/// );
|
|
+/// assert_eq!(
|
|
+/// 2.std_seconds() - 500.std_milliseconds(),
|
|
+/// 1_500.std_milliseconds()
|
|
+/// );
|
|
+/// ```
|
|
+///
|
|
+/// When called on floating point values, any remainder of the floating point value will be
|
|
+/// truncated. Keep in mind that floating point numbers are inherently imprecise and have
|
|
+/// limited capacity.
|
|
+pub trait NumericalStdDuration: sealed::Sealed {
|
|
+ /// Create a [`std::time::Duration`] from the number of nanoseconds.
|
|
+ fn std_nanoseconds(self) -> StdDuration;
|
|
+ /// Create a [`std::time::Duration`] from the number of microseconds.
|
|
+ fn std_microseconds(self) -> StdDuration;
|
|
+ /// Create a [`std::time::Duration`] from the number of milliseconds.
|
|
+ fn std_milliseconds(self) -> StdDuration;
|
|
+ /// Create a [`std::time::Duration`] from the number of seconds.
|
|
+ fn std_seconds(self) -> StdDuration;
|
|
+ /// Create a [`std::time::Duration`] from the number of minutes.
|
|
+ fn std_minutes(self) -> StdDuration;
|
|
+ /// Create a [`std::time::Duration`] from the number of hours.
|
|
+ fn std_hours(self) -> StdDuration;
|
|
+ /// Create a [`std::time::Duration`] from the number of days.
|
|
+ fn std_days(self) -> StdDuration;
|
|
+ /// Create a [`std::time::Duration`] from the number of weeks.
|
|
+ fn std_weeks(self) -> StdDuration;
|
|
+}
|
|
+
|
|
+impl NumericalStdDuration for u64 {
|
|
+ fn std_nanoseconds(self) -> StdDuration {
|
|
+ StdDuration::from_nanos(self)
|
|
+ }
|
|
+
|
|
+ fn std_microseconds(self) -> StdDuration {
|
|
+ StdDuration::from_micros(self)
|
|
+ }
|
|
+
|
|
+ fn std_milliseconds(self) -> StdDuration {
|
|
+ StdDuration::from_millis(self)
|
|
+ }
|
|
+
|
|
+ fn std_seconds(self) -> StdDuration {
|
|
+ StdDuration::from_secs(self)
|
|
+ }
|
|
+
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if an overflow occurs.
|
|
+ fn std_minutes(self) -> StdDuration {
|
|
+ StdDuration::from_secs(
|
|
+ self.checked_mul(Second::per(Minute).extend())
|
|
+ .expect("overflow constructing `time::Duration`"),
|
|
+ )
|
|
+ }
|
|
+
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if an overflow occurs.
|
|
+ fn std_hours(self) -> StdDuration {
|
|
+ StdDuration::from_secs(
|
|
+ self.checked_mul(Second::per(Hour).extend())
|
|
+ .expect("overflow constructing `time::Duration`"),
|
|
+ )
|
|
+ }
|
|
+
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if an overflow occurs.
|
|
+ fn std_days(self) -> StdDuration {
|
|
+ StdDuration::from_secs(
|
|
+ self.checked_mul(Second::per(Day).extend())
|
|
+ .expect("overflow constructing `time::Duration`"),
|
|
+ )
|
|
+ }
|
|
+
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if an overflow occurs.
|
|
+ fn std_weeks(self) -> StdDuration {
|
|
+ StdDuration::from_secs(
|
|
+ self.checked_mul(Second::per(Week).extend())
|
|
+ .expect("overflow constructing `time::Duration`"),
|
|
+ )
|
|
+ }
|
|
+}
|
|
+
|
|
+impl NumericalStdDuration for f64 {
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This will panic if self is negative.
|
|
+ fn std_nanoseconds(self) -> StdDuration {
|
|
+ assert!(self >= 0.);
|
|
+ StdDuration::from_nanos(self as _)
|
|
+ }
|
|
+
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This will panic if self is negative.
|
|
+ fn std_microseconds(self) -> StdDuration {
|
|
+ assert!(self >= 0.);
|
|
+ StdDuration::from_nanos((self * Nanosecond::per(Microsecond) as Self) as _)
|
|
+ }
|
|
+
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This will panic if self is negative.
|
|
+ fn std_milliseconds(self) -> StdDuration {
|
|
+ assert!(self >= 0.);
|
|
+ StdDuration::from_nanos((self * Nanosecond::per(Millisecond) as Self) as _)
|
|
+ }
|
|
+
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This will panic if self is negative.
|
|
+ fn std_seconds(self) -> StdDuration {
|
|
+ assert!(self >= 0.);
|
|
+ StdDuration::from_nanos((self * Nanosecond::per(Second) as Self) as _)
|
|
+ }
|
|
+
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This will panic if self is negative.
|
|
+ fn std_minutes(self) -> StdDuration {
|
|
+ assert!(self >= 0.);
|
|
+ StdDuration::from_nanos((self * Nanosecond::per(Minute) as Self) as _)
|
|
+ }
|
|
+
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This will panic if self is negative.
|
|
+ fn std_hours(self) -> StdDuration {
|
|
+ assert!(self >= 0.);
|
|
+ StdDuration::from_nanos((self * Nanosecond::per(Hour) as Self) as _)
|
|
+ }
|
|
+
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This will panic if self is negative.
|
|
+ fn std_days(self) -> StdDuration {
|
|
+ assert!(self >= 0.);
|
|
+ StdDuration::from_nanos((self * Nanosecond::per(Day) as Self) as _)
|
|
+ }
|
|
+
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This will panic if self is negative.
|
|
+ fn std_weeks(self) -> StdDuration {
|
|
+ assert!(self >= 0.);
|
|
+ StdDuration::from_nanos((self * Nanosecond::per(Week) as Self) as _)
|
|
+ }
|
|
+}
|
|
diff --git a/vendor/time/src/format_description/borrowed_format_item.rs b/vendor/time/src/format_description/borrowed_format_item.rs
|
|
index 425b902..4f3e638 100644
|
|
--- a/vendor/time/src/format_description/borrowed_format_item.rs
|
|
+++ b/vendor/time/src/format_description/borrowed_format_item.rs
|
|
@@ -5,6 +5,19 @@ use alloc::string::String;
|
|
#[cfg(feature = "alloc")]
|
|
use core::fmt;
|
|
|
|
+/// A complete description of how to format and parse a type.
|
|
+///
|
|
+/// This alias exists for backwards-compatibility. It is recommended to use `BorrowedFormatItem`
|
|
+/// for clarity, as it is more explicit that the data is borrowed rather than owned.
|
|
+#[cfg(doc)]
|
|
+#[deprecated(
|
|
+ since = "0.3.35",
|
|
+ note = "use `BorrowedFormatItem` instead for clarity"
|
|
+)]
|
|
+pub type FormatItem<'a> = BorrowedFormatItem<'a>;
|
|
+
|
|
+#[cfg(not(doc))]
|
|
+pub use self::BorrowedFormatItem as FormatItem;
|
|
use crate::error;
|
|
use crate::format_description::Component;
|
|
|
|
@@ -15,8 +28,8 @@ use crate::format_description::Component;
|
|
pub enum BorrowedFormatItem<'a> {
|
|
/// Bytes that are formatted as-is.
|
|
///
|
|
- /// **Note**: If you call the `format` method that returns a `String`, these bytes will be
|
|
- /// passed through `String::from_utf8_lossy`.
|
|
+ /// **Note**: These bytes **should** be UTF-8, but are not required to be. The value is passed
|
|
+ /// through `String::from_utf8_lossy` when necessary.
|
|
Literal(&'a [u8]),
|
|
/// A minimal representation of a single non-literal item.
|
|
Component(Component),
|
|
diff --git a/vendor/time/src/format_description/mod.rs b/vendor/time/src/format_description/mod.rs
|
|
index befae8b..67882af 100644
|
|
--- a/vendor/time/src/format_description/mod.rs
|
|
+++ b/vendor/time/src/format_description/mod.rs
|
|
@@ -15,7 +15,9 @@ mod owned_format_item;
|
|
#[cfg(feature = "alloc")]
|
|
mod parse;
|
|
|
|
-pub use borrowed_format_item::BorrowedFormatItem as FormatItem;
|
|
+pub use borrowed_format_item::BorrowedFormatItem;
|
|
+#[allow(deprecated)]
|
|
+pub use borrowed_format_item::FormatItem;
|
|
#[cfg(feature = "alloc")]
|
|
pub use owned_format_item::OwnedFormatItem;
|
|
|
|
diff --git a/vendor/time/src/format_description/owned_format_item.rs b/vendor/time/src/format_description/owned_format_item.rs
|
|
index 6f7f7c2..31ea9f9 100644
|
|
--- a/vendor/time/src/format_description/owned_format_item.rs
|
|
+++ b/vendor/time/src/format_description/owned_format_item.rs
|
|
@@ -6,7 +6,7 @@ use alloc::vec::Vec;
|
|
use core::fmt;
|
|
|
|
use crate::error;
|
|
-use crate::format_description::{Component, FormatItem};
|
|
+use crate::format_description::{BorrowedFormatItem, Component};
|
|
|
|
/// A complete description of how to format and parse a type.
|
|
#[non_exhaustive]
|
|
@@ -14,8 +14,8 @@ use crate::format_description::{Component, FormatItem};
|
|
pub enum OwnedFormatItem {
|
|
/// Bytes that are formatted as-is.
|
|
///
|
|
- /// **Note**: If you call the `format` method that returns a `String`, these bytes will be
|
|
- /// passed through `String::from_utf8_lossy`.
|
|
+ /// **Note**: These bytes **should** be UTF-8, but are not required to be. The value is passed
|
|
+ /// through `String::from_utf8_lossy` when necessary.
|
|
Literal(Box<[u8]>),
|
|
/// A minimal representation of a single non-literal item.
|
|
Component(Component),
|
|
@@ -46,18 +46,20 @@ impl fmt::Debug for OwnedFormatItem {
|
|
}
|
|
|
|
// region: conversions from FormatItem
|
|
-impl From<FormatItem<'_>> for OwnedFormatItem {
|
|
- fn from(item: FormatItem<'_>) -> Self {
|
|
+impl From<BorrowedFormatItem<'_>> for OwnedFormatItem {
|
|
+ fn from(item: BorrowedFormatItem<'_>) -> Self {
|
|
(&item).into()
|
|
}
|
|
}
|
|
|
|
-impl From<&FormatItem<'_>> for OwnedFormatItem {
|
|
- fn from(item: &FormatItem<'_>) -> Self {
|
|
+impl From<&BorrowedFormatItem<'_>> for OwnedFormatItem {
|
|
+ fn from(item: &BorrowedFormatItem<'_>) -> Self {
|
|
match item {
|
|
- FormatItem::Literal(literal) => Self::Literal(literal.to_vec().into_boxed_slice()),
|
|
- FormatItem::Component(component) => Self::Component(*component),
|
|
- FormatItem::Compound(compound) => Self::Compound(
|
|
+ BorrowedFormatItem::Literal(literal) => {
|
|
+ Self::Literal(literal.to_vec().into_boxed_slice())
|
|
+ }
|
|
+ BorrowedFormatItem::Component(component) => Self::Component(*component),
|
|
+ BorrowedFormatItem::Compound(compound) => Self::Compound(
|
|
compound
|
|
.iter()
|
|
.cloned()
|
|
@@ -65,8 +67,8 @@ impl From<&FormatItem<'_>> for OwnedFormatItem {
|
|
.collect::<Vec<_>>()
|
|
.into_boxed_slice(),
|
|
),
|
|
- FormatItem::Optional(item) => Self::Optional(Box::new((*item).into())),
|
|
- FormatItem::First(items) => Self::First(
|
|
+ BorrowedFormatItem::Optional(item) => Self::Optional(Box::new((*item).into())),
|
|
+ BorrowedFormatItem::First(items) => Self::First(
|
|
items
|
|
.iter()
|
|
.cloned()
|
|
@@ -78,13 +80,13 @@ impl From<&FormatItem<'_>> for OwnedFormatItem {
|
|
}
|
|
}
|
|
|
|
-impl From<Vec<FormatItem<'_>>> for OwnedFormatItem {
|
|
- fn from(items: Vec<FormatItem<'_>>) -> Self {
|
|
+impl From<Vec<BorrowedFormatItem<'_>>> for OwnedFormatItem {
|
|
+ fn from(items: Vec<BorrowedFormatItem<'_>>) -> Self {
|
|
items.as_slice().into()
|
|
}
|
|
}
|
|
|
|
-impl<'a, T: AsRef<[FormatItem<'a>]> + ?Sized> From<&T> for OwnedFormatItem {
|
|
+impl<'a, T: AsRef<[BorrowedFormatItem<'a>]> + ?Sized> From<&T> for OwnedFormatItem {
|
|
fn from(items: &T) -> Self {
|
|
Self::Compound(
|
|
items
|
|
diff --git a/vendor/time/src/format_description/parse/format_item.rs b/vendor/time/src/format_description/parse/format_item.rs
|
|
index f33078e..2e1ee6a 100644
|
|
--- a/vendor/time/src/format_description/parse/format_item.rs
|
|
+++ b/vendor/time/src/format_description/parse/format_item.rs
|
|
@@ -102,7 +102,7 @@ impl Item<'_> {
|
|
}
|
|
}
|
|
|
|
-impl<'a> TryFrom<Item<'a>> for crate::format_description::FormatItem<'a> {
|
|
+impl<'a> TryFrom<Item<'a>> for crate::format_description::BorrowedFormatItem<'a> {
|
|
type Error = Error;
|
|
|
|
fn try_from(item: Item<'a>) -> Result<Self, Self::Error> {
|
|
@@ -149,14 +149,9 @@ impl From<Item<'_>> for crate::format_description::OwnedFormatItem {
|
|
impl<'a> From<Box<[Item<'a>]>> for crate::format_description::OwnedFormatItem {
|
|
fn from(items: Box<[Item<'a>]>) -> Self {
|
|
let items = items.into_vec();
|
|
- if items.len() == 1 {
|
|
- if let Ok([item]) = <[_; 1]>::try_from(items) {
|
|
- item.into()
|
|
- } else {
|
|
- bug!("the length was just checked to be 1")
|
|
- }
|
|
- } else {
|
|
- Self::Compound(items.into_iter().map(Self::from).collect())
|
|
+ match <[_; 1]>::try_from(items) {
|
|
+ Ok([item]) => item.into(),
|
|
+ Err(vec) => Self::Compound(vec.into_iter().map(Into::into).collect()),
|
|
}
|
|
}
|
|
}
|
|
diff --git a/vendor/time/src/format_description/parse/lexer.rs b/vendor/time/src/format_description/parse/lexer.rs
|
|
index 1604fd4..2979fff 100644
|
|
--- a/vendor/time/src/format_description/parse/lexer.rs
|
|
+++ b/vendor/time/src/format_description/parse/lexer.rs
|
|
@@ -7,7 +7,7 @@ use super::{unused, Error, Location, Spanned, SpannedValue};
|
|
/// An iterator over the lexed tokens.
|
|
pub(super) struct Lexed<I: Iterator> {
|
|
/// The internal iterator.
|
|
- iter: core::iter::Peekable<I>,
|
|
+ iter: iter::Peekable<I>,
|
|
}
|
|
|
|
impl<I: Iterator> Iterator for Lexed<I> {
|
|
diff --git a/vendor/time/src/format_description/parse/mod.rs b/vendor/time/src/format_description/parse/mod.rs
|
|
index 2ab58f1..602ecf7 100644
|
|
--- a/vendor/time/src/format_description/parse/mod.rs
|
|
+++ b/vendor/time/src/format_description/parse/mod.rs
|
|
@@ -3,6 +3,8 @@
|
|
use alloc::boxed::Box;
|
|
use alloc::vec::Vec;
|
|
|
|
+use crate::{error, format_description};
|
|
+
|
|
/// A helper macro to make version restrictions simpler to read and write.
|
|
macro_rules! version {
|
|
($range:expr) => {
|
|
@@ -40,8 +42,7 @@ impl<const N: usize> Version<N> {
|
|
/// `parse_borrowed`.
|
|
pub fn parse(
|
|
s: &str,
|
|
-) -> Result<Vec<crate::format_description::FormatItem<'_>>, crate::error::InvalidFormatDescription>
|
|
-{
|
|
+) -> Result<Vec<format_description::BorrowedFormatItem<'_>>, error::InvalidFormatDescription> {
|
|
parse_borrowed::<1>(s)
|
|
}
|
|
|
|
@@ -52,8 +53,7 @@ pub fn parse(
|
|
/// description is provided as the const parameter. **It is recommended to use version 2.**
|
|
pub fn parse_borrowed<const VERSION: usize>(
|
|
s: &str,
|
|
-) -> Result<Vec<crate::format_description::FormatItem<'_>>, crate::error::InvalidFormatDescription>
|
|
-{
|
|
+) -> Result<Vec<format_description::BorrowedFormatItem<'_>>, error::InvalidFormatDescription> {
|
|
validate_version!(VERSION);
|
|
let mut lexed = lexer::lex::<VERSION>(s.as_bytes());
|
|
let ast = ast::parse::<_, VERSION>(&mut lexed);
|
|
@@ -75,14 +75,12 @@ pub fn parse_borrowed<const VERSION: usize>(
|
|
/// [`OwnedFormatItem`]: crate::format_description::OwnedFormatItem
|
|
pub fn parse_owned<const VERSION: usize>(
|
|
s: &str,
|
|
-) -> Result<crate::format_description::OwnedFormatItem, crate::error::InvalidFormatDescription> {
|
|
+) -> Result<format_description::OwnedFormatItem, error::InvalidFormatDescription> {
|
|
validate_version!(VERSION);
|
|
let mut lexed = lexer::lex::<VERSION>(s.as_bytes());
|
|
let ast = ast::parse::<_, VERSION>(&mut lexed);
|
|
let format_items = format_item::parse(ast);
|
|
- let items = format_items
|
|
- .map(|res| res.map(Into::into))
|
|
- .collect::<Result<Box<_>, _>>()?;
|
|
+ let items = format_items.collect::<Result<Box<_>, _>>()?;
|
|
Ok(items.into())
|
|
}
|
|
|
|
@@ -222,10 +220,10 @@ struct Error {
|
|
/// The internal error.
|
|
_inner: Unused<ErrorInner>,
|
|
/// The error needed for interoperability with the rest of `time`.
|
|
- public: crate::error::InvalidFormatDescription,
|
|
+ public: error::InvalidFormatDescription,
|
|
}
|
|
|
|
-impl From<Error> for crate::error::InvalidFormatDescription {
|
|
+impl From<Error> for error::InvalidFormatDescription {
|
|
fn from(error: Error) -> Self {
|
|
error.public
|
|
}
|
|
@@ -239,7 +237,6 @@ impl From<Error> for crate::error::InvalidFormatDescription {
|
|
struct Unused<T>(core::marker::PhantomData<T>);
|
|
|
|
/// Indicate that a value is currently unused.
|
|
-#[allow(clippy::missing_const_for_fn)] // false positive
|
|
fn unused<T>(_: T) -> Unused<T> {
|
|
Unused(core::marker::PhantomData)
|
|
}
|
|
diff --git a/vendor/time/src/format_description/well_known/iso8601.rs b/vendor/time/src/format_description/well_known/iso8601.rs
|
|
index 756f034..6b8ff2a 100644
|
|
--- a/vendor/time/src/format_description/well_known/iso8601.rs
|
|
+++ b/vendor/time/src/format_description/well_known/iso8601.rs
|
|
@@ -4,7 +4,7 @@ mod adt_hack;
|
|
|
|
use core::num::NonZeroU8;
|
|
|
|
-#[doc(hidden)]
|
|
+#[doc(hidden, no_inline)]
|
|
pub use self::adt_hack::DoNotRelyOnWhatThisIs;
|
|
pub use self::adt_hack::EncodedConfig;
|
|
|
|
diff --git a/vendor/time/src/formatting/formattable.rs b/vendor/time/src/formatting/formattable.rs
|
|
index cad1d48..7ee17a5 100644
|
|
--- a/vendor/time/src/formatting/formattable.rs
|
|
+++ b/vendor/time/src/formatting/formattable.rs
|
|
@@ -1,11 +1,15 @@
|
|
//! A trait that can be used to format an item from its components.
|
|
|
|
+use alloc::string::String;
|
|
+use alloc::vec::Vec;
|
|
use core::ops::Deref;
|
|
use std::io;
|
|
|
|
+use num_conv::prelude::*;
|
|
+
|
|
use crate::format_description::well_known::iso8601::EncodedConfig;
|
|
use crate::format_description::well_known::{Iso8601, Rfc2822, Rfc3339};
|
|
-use crate::format_description::{FormatItem, OwnedFormatItem};
|
|
+use crate::format_description::{BorrowedFormatItem, OwnedFormatItem};
|
|
use crate::formatting::{
|
|
format_component, format_number_pad_zero, iso8601, write, MONTH_NAMES, WEEKDAY_NAMES,
|
|
};
|
|
@@ -19,8 +23,8 @@ use crate::{error, Date, Time, UtcOffset};
|
|
/// a String from their data. See the respective methods for usage examples.
|
|
#[cfg_attr(__time_03_docs, doc(notable_trait))]
|
|
pub trait Formattable: sealed::Sealed {}
|
|
-impl Formattable for FormatItem<'_> {}
|
|
-impl Formattable for [FormatItem<'_>] {}
|
|
+impl Formattable for BorrowedFormatItem<'_> {}
|
|
+impl Formattable for [BorrowedFormatItem<'_>] {}
|
|
impl Formattable for OwnedFormatItem {}
|
|
impl Formattable for [OwnedFormatItem] {}
|
|
impl Formattable for Rfc3339 {}
|
|
@@ -59,7 +63,7 @@ mod sealed {
|
|
}
|
|
|
|
// region: custom formats
|
|
-impl sealed::Sealed for FormatItem<'_> {
|
|
+impl sealed::Sealed for BorrowedFormatItem<'_> {
|
|
fn format_into(
|
|
&self,
|
|
output: &mut impl io::Write,
|
|
@@ -80,7 +84,7 @@ impl sealed::Sealed for FormatItem<'_> {
|
|
}
|
|
}
|
|
|
|
-impl sealed::Sealed for [FormatItem<'_>] {
|
|
+impl sealed::Sealed for [BorrowedFormatItem<'_>] {
|
|
fn format_into(
|
|
&self,
|
|
output: &mut impl io::Write,
|
|
@@ -175,14 +179,17 @@ impl sealed::Sealed for Rfc2822 {
|
|
|
|
bytes += write(
|
|
output,
|
|
- &WEEKDAY_NAMES[date.weekday().number_days_from_monday() as usize][..3],
|
|
+ &WEEKDAY_NAMES[date.weekday().number_days_from_monday().extend::<usize>()][..3],
|
|
)?;
|
|
bytes += write(output, b", ")?;
|
|
bytes += format_number_pad_zero::<2>(output, day)?;
|
|
bytes += write(output, b" ")?;
|
|
- bytes += write(output, &MONTH_NAMES[month as usize - 1][..3])?;
|
|
+ bytes += write(
|
|
+ output,
|
|
+ &MONTH_NAMES[u8::from(month).extend::<usize>() - 1][..3],
|
|
+ )?;
|
|
bytes += write(output, b" ")?;
|
|
- bytes += format_number_pad_zero::<4>(output, year as u32)?;
|
|
+ bytes += format_number_pad_zero::<4>(output, year.cast_unsigned())?;
|
|
bytes += write(output, b" ")?;
|
|
bytes += format_number_pad_zero::<2>(output, time.hour())?;
|
|
bytes += write(output, b":")?;
|
|
@@ -217,13 +224,16 @@ impl sealed::Sealed for Rfc3339 {
|
|
if !(0..10_000).contains(&year) {
|
|
return Err(error::Format::InvalidComponent("year"));
|
|
}
|
|
+ if offset.whole_hours().unsigned_abs() > 23 {
|
|
+ return Err(error::Format::InvalidComponent("offset_hour"));
|
|
+ }
|
|
if offset.seconds_past_minute() != 0 {
|
|
return Err(error::Format::InvalidComponent("offset_second"));
|
|
}
|
|
|
|
- bytes += format_number_pad_zero::<4>(output, year as u32)?;
|
|
+ bytes += format_number_pad_zero::<4>(output, year.cast_unsigned())?;
|
|
bytes += write(output, b"-")?;
|
|
- bytes += format_number_pad_zero::<2>(output, date.month() as u8)?;
|
|
+ bytes += format_number_pad_zero::<2>(output, u8::from(date.month()))?;
|
|
bytes += write(output, b"-")?;
|
|
bytes += format_number_pad_zero::<2>(output, date.day())?;
|
|
bytes += write(output, b"T")?;
|
|
diff --git a/vendor/time/src/formatting/iso8601.rs b/vendor/time/src/formatting/iso8601.rs
|
|
index 67bc66b..ee49d7d 100644
|
|
--- a/vendor/time/src/formatting/iso8601.rs
|
|
+++ b/vendor/time/src/formatting/iso8601.rs
|
|
@@ -2,6 +2,8 @@
|
|
|
|
use std::io;
|
|
|
|
+use num_conv::prelude::*;
|
|
+
|
|
use crate::convert::*;
|
|
use crate::format_description::well_known::iso8601::{
|
|
DateKind, EncodedConfig, OffsetPrecision, TimePrecision,
|
|
@@ -26,10 +28,10 @@ pub(super) fn format_date<const CONFIG: EncodedConfig>(
|
|
} else if !(0..=9999).contains(&year) {
|
|
return Err(error::Format::InvalidComponent("year"));
|
|
} else {
|
|
- bytes += format_number_pad_zero::<4>(output, year as u32)?;
|
|
+ bytes += format_number_pad_zero::<4>(output, year.cast_unsigned())?;
|
|
}
|
|
bytes += write_if(output, Iso8601::<CONFIG>::USE_SEPARATORS, b"-")?;
|
|
- bytes += format_number_pad_zero::<2>(output, month as u8)?;
|
|
+ bytes += format_number_pad_zero::<2>(output, u8::from(month))?;
|
|
bytes += write_if(output, Iso8601::<CONFIG>::USE_SEPARATORS, b"-")?;
|
|
bytes += format_number_pad_zero::<2>(output, day)?;
|
|
}
|
|
@@ -41,7 +43,7 @@ pub(super) fn format_date<const CONFIG: EncodedConfig>(
|
|
} else if !(0..=9999).contains(&year) {
|
|
return Err(error::Format::InvalidComponent("year"));
|
|
} else {
|
|
- bytes += format_number_pad_zero::<4>(output, year as u32)?;
|
|
+ bytes += format_number_pad_zero::<4>(output, year.cast_unsigned())?;
|
|
}
|
|
bytes += write_if_else(output, Iso8601::<CONFIG>::USE_SEPARATORS, b"-W", b"W")?;
|
|
bytes += format_number_pad_zero::<2>(output, week)?;
|
|
@@ -56,7 +58,7 @@ pub(super) fn format_date<const CONFIG: EncodedConfig>(
|
|
} else if !(0..=9999).contains(&year) {
|
|
return Err(error::Format::InvalidComponent("year"));
|
|
} else {
|
|
- bytes += format_number_pad_zero::<4>(output, year as u32)?;
|
|
+ bytes += format_number_pad_zero::<4>(output, year.cast_unsigned())?;
|
|
}
|
|
bytes += write_if(output, Iso8601::<CONFIG>::USE_SEPARATORS, b"-")?;
|
|
bytes += format_number_pad_zero::<3>(output, day)?;
|
|
diff --git a/vendor/time/src/formatting/mod.rs b/vendor/time/src/formatting/mod.rs
|
|
index 77a5230..b57c152 100644
|
|
--- a/vendor/time/src/formatting/mod.rs
|
|
+++ b/vendor/time/src/formatting/mod.rs
|
|
@@ -5,6 +5,8 @@ mod iso8601;
|
|
use core::num::NonZeroU8;
|
|
use std::io;
|
|
|
|
+use num_conv::prelude::*;
|
|
+
|
|
pub use self::formattable::Formattable;
|
|
use crate::convert::*;
|
|
use crate::ext::DigitCount;
|
|
@@ -71,14 +73,14 @@ pub(crate) fn format_float(
|
|
) -> io::Result<usize> {
|
|
match digits_after_decimal {
|
|
Some(digits_after_decimal) => {
|
|
- let digits_after_decimal = digits_after_decimal.get() as usize;
|
|
- let width = digits_before_decimal as usize + 1 + digits_after_decimal;
|
|
+ let digits_after_decimal = digits_after_decimal.get().extend();
|
|
+ let width = digits_before_decimal.extend::<usize>() + 1 + digits_after_decimal;
|
|
write!(output, "{value:0>width$.digits_after_decimal$}")?;
|
|
Ok(width)
|
|
}
|
|
None => {
|
|
let value = value.trunc() as u64;
|
|
- let width = digits_before_decimal as usize;
|
|
+ let width = digits_before_decimal.extend();
|
|
write!(output, "{value:0>width$}")?;
|
|
Ok(width)
|
|
}
|
|
@@ -207,9 +209,17 @@ fn fmt_month(
|
|
}: modifier::Month,
|
|
) -> Result<usize, io::Error> {
|
|
match repr {
|
|
- modifier::MonthRepr::Numerical => format_number::<2>(output, date.month() as u8, padding),
|
|
- modifier::MonthRepr::Long => write(output, MONTH_NAMES[date.month() as usize - 1]),
|
|
- modifier::MonthRepr::Short => write(output, &MONTH_NAMES[date.month() as usize - 1][..3]),
|
|
+ modifier::MonthRepr::Numerical => {
|
|
+ format_number::<2>(output, u8::from(date.month()), padding)
|
|
+ }
|
|
+ modifier::MonthRepr::Long => write(
|
|
+ output,
|
|
+ MONTH_NAMES[u8::from(date.month()).extend::<usize>() - 1],
|
|
+ ),
|
|
+ modifier::MonthRepr::Short => write(
|
|
+ output,
|
|
+ &MONTH_NAMES[u8::from(date.month()).extend::<usize>() - 1][..3],
|
|
+ ),
|
|
}
|
|
}
|
|
|
|
@@ -235,20 +245,20 @@ fn fmt_weekday(
|
|
match repr {
|
|
modifier::WeekdayRepr::Short => write(
|
|
output,
|
|
- &WEEKDAY_NAMES[date.weekday().number_days_from_monday() as usize][..3],
|
|
+ &WEEKDAY_NAMES[date.weekday().number_days_from_monday().extend::<usize>()][..3],
|
|
),
|
|
modifier::WeekdayRepr::Long => write(
|
|
output,
|
|
- WEEKDAY_NAMES[date.weekday().number_days_from_monday() as usize],
|
|
+ WEEKDAY_NAMES[date.weekday().number_days_from_monday().extend::<usize>()],
|
|
),
|
|
modifier::WeekdayRepr::Sunday => format_number::<1>(
|
|
output,
|
|
- date.weekday().number_days_from_sunday() + one_indexed as u8,
|
|
+ date.weekday().number_days_from_sunday() + u8::from(one_indexed),
|
|
modifier::Padding::None,
|
|
),
|
|
modifier::WeekdayRepr::Monday => format_number::<1>(
|
|
output,
|
|
- date.weekday().number_days_from_monday() + one_indexed as u8,
|
|
+ date.weekday().number_days_from_monday() + u8::from(one_indexed),
|
|
modifier::Padding::None,
|
|
),
|
|
}
|
|
@@ -447,10 +457,7 @@ fn fmt_unix_timestamp(
|
|
sign_is_mandatory,
|
|
}: modifier::UnixTimestamp,
|
|
) -> Result<usize, io::Error> {
|
|
- let date_time = date
|
|
- .with_time(time)
|
|
- .assume_offset(offset)
|
|
- .to_offset(UtcOffset::UTC);
|
|
+ let date_time = OffsetDateTime::new_in_offset(date, time, offset).to_offset(UtcOffset::UTC);
|
|
|
|
if date_time < OffsetDateTime::UNIX_EPOCH {
|
|
write(output, b"-")?;
|
|
@@ -464,13 +471,15 @@ fn fmt_unix_timestamp(
|
|
}
|
|
modifier::UnixTimestampPrecision::Millisecond => format_number_pad_none(
|
|
output,
|
|
- (date_time.unix_timestamp_nanos() / Nanosecond::per(Millisecond) as i128)
|
|
- .unsigned_abs(),
|
|
+ (date_time.unix_timestamp_nanos()
|
|
+ / Nanosecond::per(Millisecond).cast_signed().extend::<i128>())
|
|
+ .unsigned_abs(),
|
|
),
|
|
modifier::UnixTimestampPrecision::Microsecond => format_number_pad_none(
|
|
output,
|
|
- (date_time.unix_timestamp_nanos() / Nanosecond::per(Microsecond) as i128)
|
|
- .unsigned_abs(),
|
|
+ (date_time.unix_timestamp_nanos()
|
|
+ / Nanosecond::per(Microsecond).cast_signed().extend::<i128>())
|
|
+ .unsigned_abs(),
|
|
),
|
|
modifier::UnixTimestampPrecision::Nanosecond => {
|
|
format_number_pad_none(output, date_time.unix_timestamp_nanos().unsigned_abs())
|
|
diff --git a/vendor/time/src/instant.rs b/vendor/time/src/instant.rs
|
|
index 706c759..4c2a16f 100644
|
|
--- a/vendor/time/src/instant.rs
|
|
+++ b/vendor/time/src/instant.rs
|
|
@@ -1,5 +1,7 @@
|
|
//! The [`Instant`] struct and its associated `impl`s.
|
|
|
|
+#![allow(deprecated)]
|
|
+
|
|
use core::borrow::Borrow;
|
|
use core::cmp::{Ord, Ordering, PartialEq, PartialOrd};
|
|
use core::ops::{Add, Sub};
|
|
@@ -26,6 +28,7 @@ use crate::Duration;
|
|
///
|
|
/// This implementation allows for operations with signed [`Duration`]s, but is otherwise identical
|
|
/// to [`std::time::Instant`].
|
|
+#[deprecated(since = "0.3.35", note = "import `time::ext::InstantExt` instead")]
|
|
#[repr(transparent)]
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
pub struct Instant(pub StdInstant);
|
|
@@ -35,6 +38,7 @@ impl Instant {
|
|
/// Returns an `Instant` corresponding to "now".
|
|
///
|
|
/// ```rust
|
|
+ /// # #![allow(deprecated)]
|
|
/// # use time::Instant;
|
|
/// println!("{:?}", Instant::now());
|
|
/// ```
|
|
@@ -46,6 +50,7 @@ impl Instant {
|
|
/// be nonnegative if the instant is not synthetically created.
|
|
///
|
|
/// ```rust
|
|
+ /// # #![allow(deprecated)]
|
|
/// # use time::{Instant, ext::{NumericalStdDuration, NumericalDuration}};
|
|
/// # use std::thread;
|
|
/// let instant = Instant::now();
|
|
@@ -63,6 +68,7 @@ impl Instant {
|
|
/// otherwise.
|
|
///
|
|
/// ```rust
|
|
+ /// # #![allow(deprecated)]
|
|
/// # use time::{Instant, ext::NumericalDuration};
|
|
/// let now = Instant::now();
|
|
/// assert_eq!(now.checked_add(5.seconds()), Some(now + 5.seconds()));
|
|
@@ -84,6 +90,7 @@ impl Instant {
|
|
/// otherwise.
|
|
///
|
|
/// ```rust
|
|
+ /// # #![allow(deprecated)]
|
|
/// # use time::{Instant, ext::NumericalDuration};
|
|
/// let now = Instant::now();
|
|
/// assert_eq!(now.checked_sub(5.seconds()), Some(now - 5.seconds()));
|
|
@@ -104,6 +111,7 @@ impl Instant {
|
|
/// Obtain the inner [`std::time::Instant`].
|
|
///
|
|
/// ```rust
|
|
+ /// # #![allow(deprecated)]
|
|
/// # use time::Instant;
|
|
/// let now = Instant::now();
|
|
/// assert_eq!(now.into_inner(), now.0);
|
|
@@ -129,6 +137,9 @@ impl From<Instant> for StdInstant {
|
|
impl Sub for Instant {
|
|
type Output = Duration;
|
|
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if an overflow occurs.
|
|
fn sub(self, other: Self) -> Self::Output {
|
|
match self.0.cmp(&other.0) {
|
|
Ordering::Equal => Duration::ZERO,
|
|
diff --git a/vendor/time/src/internal_macros.rs b/vendor/time/src/internal_macros.rs
|
|
index 8571389..e210573 100644
|
|
--- a/vendor/time/src/internal_macros.rs
|
|
+++ b/vendor/time/src/internal_macros.rs
|
|
@@ -184,6 +184,7 @@ macro_rules! expect_opt {
|
|
}
|
|
|
|
/// `unreachable!()`, but better.
|
|
+#[cfg(any(feature = "formatting", feature = "parsing"))]
|
|
macro_rules! bug {
|
|
() => { compile_error!("provide an error message to help fix a possible bug") };
|
|
($descr:literal $($rest:tt)?) => {
|
|
@@ -191,7 +192,9 @@ macro_rules! bug {
|
|
}
|
|
}
|
|
|
|
+#[cfg(any(feature = "formatting", feature = "parsing"))]
|
|
+pub(crate) use bug;
|
|
pub(crate) use {
|
|
- __impl_assign, bug, cascade, const_try, const_try_opt, div_floor, ensure_ranged, expect_opt,
|
|
+ __impl_assign, cascade, const_try, const_try_opt, div_floor, ensure_ranged, expect_opt,
|
|
impl_add_assign, impl_div_assign, impl_mul_assign, impl_sub_assign,
|
|
};
|
|
diff --git a/vendor/time/src/lib.rs b/vendor/time/src/lib.rs
|
|
index 110c286..511df04 100644
|
|
--- a/vendor/time/src/lib.rs
|
|
+++ b/vendor/time/src/lib.rs
|
|
@@ -52,14 +52,6 @@
|
|
//! Libraries should never enable this feature, as the decision of what format to use should be up
|
|
//! to the user.
|
|
//!
|
|
-//! - `serde-well-known` (_implicitly enables `serde-human-readable`_)
|
|
-//!
|
|
-//! _This feature flag is deprecated and will be removed in a future breaking release. Use the
|
|
-//! `serde-human-readable` feature instead._
|
|
-//!
|
|
-//! Enables support for serializing and deserializing well-known formats using serde's
|
|
-//! [`#[with]` attribute](https://serde.rs/field-attrs.html#with).
|
|
-//!
|
|
//! - `rand`
|
|
//!
|
|
//! Enables [rand](https://docs.rs/rand) support for all types.
|
|
@@ -76,7 +68,7 @@
|
|
|
|
#![doc(html_playground_url = "https://play.rust-lang.org")]
|
|
#![cfg_attr(__time_03_docs, feature(doc_auto_cfg, doc_notable_trait))]
|
|
-#![cfg_attr(not(feature = "std"), no_std)]
|
|
+#![no_std]
|
|
#![doc(html_favicon_url = "https://avatars0.githubusercontent.com/u/55999857")]
|
|
#![doc(html_logo_url = "https://avatars0.githubusercontent.com/u/55999857")]
|
|
#![doc(test(attr(deny(warnings))))]
|
|
@@ -85,8 +77,10 @@
|
|
#[cfg(feature = "alloc")]
|
|
extern crate alloc;
|
|
|
|
+#[cfg(feature = "std")]
|
|
+extern crate std;
|
|
+
|
|
mod date;
|
|
-mod date_time;
|
|
mod duration;
|
|
pub mod error;
|
|
pub mod ext;
|
|
@@ -122,10 +116,10 @@ mod weekday;
|
|
pub use time_core::convert;
|
|
|
|
pub use crate::date::Date;
|
|
-use crate::date_time::DateTime;
|
|
pub use crate::duration::Duration;
|
|
pub use crate::error::Error;
|
|
#[cfg(feature = "std")]
|
|
+#[allow(deprecated)]
|
|
pub use crate::instant::Instant;
|
|
pub use crate::month::Month;
|
|
pub use crate::offset_date_time::OffsetDateTime;
|
|
diff --git a/vendor/time/src/macros.rs b/vendor/time/src/macros.rs
|
|
index 4f295e2..d788645 100644
|
|
--- a/vendor/time/src/macros.rs
|
|
+++ b/vendor/time/src/macros.rs
|
|
@@ -51,8 +51,8 @@ pub use time_macros::date;
|
|
pub use time_macros::datetime;
|
|
/// Equivalent of performing [`format_description::parse()`] at compile time.
|
|
///
|
|
-/// Using the macro instead of the function results in a static slice rather than a [`Vec`],
|
|
-/// such that it can be used in `#![no_alloc]` situations.
|
|
+/// Using the macro instead of the function results in a static slice rather than a
|
|
+/// [`Vec`](alloc::vec::Vec), such that it can be used in `#![no_alloc]` situations.
|
|
///
|
|
/// The resulting expression can be used in `const` or `static` declarations, and implements
|
|
/// the sealed traits required for both formatting and parsing.
|
|
diff --git a/vendor/time/src/offset_date_time.rs b/vendor/time/src/offset_date_time.rs
|
|
index 79d91a6..52f1799 100644
|
|
--- a/vendor/time/src/offset_date_time.rs
|
|
+++ b/vendor/time/src/offset_date_time.rs
|
|
@@ -1,9 +1,8 @@
|
|
//! The [`OffsetDateTime`] struct and its associated `impl`s.
|
|
|
|
-#[cfg(feature = "std")]
|
|
+#[cfg(feature = "formatting")]
|
|
+use alloc::string::String;
|
|
use core::cmp::Ordering;
|
|
-#[cfg(feature = "std")]
|
|
-use core::convert::From;
|
|
use core::fmt;
|
|
use core::hash::Hash;
|
|
use core::ops::{Add, AddAssign, Sub, SubAssign};
|
|
@@ -13,24 +12,61 @@ use std::io;
|
|
#[cfg(feature = "std")]
|
|
use std::time::SystemTime;
|
|
|
|
-use powerfmt::smart_display::{FormatterOptions, Metadata, SmartDisplay};
|
|
+use deranged::RangedI64;
|
|
+use num_conv::prelude::*;
|
|
+use powerfmt::ext::FormatterExt as _;
|
|
+use powerfmt::smart_display::{self, FormatterOptions, Metadata, SmartDisplay};
|
|
+use time_core::convert::*;
|
|
|
|
-use crate::date_time::{offset_kind, DateTimeMetadata};
|
|
+use crate::date::{MAX_YEAR, MIN_YEAR};
|
|
#[cfg(feature = "formatting")]
|
|
use crate::formatting::Formattable;
|
|
-use crate::internal_macros::{const_try, const_try_opt};
|
|
+use crate::internal_macros::{
|
|
+ cascade, const_try, const_try_opt, div_floor, ensure_ranged, expect_opt,
|
|
+};
|
|
#[cfg(feature = "parsing")]
|
|
use crate::parsing::Parsable;
|
|
-use crate::{error, Date, DateTime, Duration, Month, PrimitiveDateTime, Time, UtcOffset, Weekday};
|
|
+use crate::{error, util, Date, Duration, Month, PrimitiveDateTime, Time, UtcOffset, Weekday};
|
|
|
|
-/// The actual type doing all the work.
|
|
-type Inner = DateTime<offset_kind::Fixed>;
|
|
+/// The Julian day of the Unix epoch.
|
|
+// Safety: `ordinal` is not zero.
|
|
+#[allow(clippy::undocumented_unsafe_blocks)]
|
|
+const UNIX_EPOCH_JULIAN_DAY: i32 =
|
|
+ unsafe { Date::__from_ordinal_date_unchecked(1970, 1) }.to_julian_day();
|
|
|
|
/// A [`PrimitiveDateTime`] with a [`UtcOffset`].
|
|
///
|
|
/// All comparisons are performed using the UTC time.
|
|
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
-pub struct OffsetDateTime(pub(crate) Inner);
|
|
+#[derive(Clone, Copy, Eq)]
|
|
+pub struct OffsetDateTime {
|
|
+ local_date_time: PrimitiveDateTime,
|
|
+ offset: UtcOffset,
|
|
+}
|
|
+
|
|
+impl PartialEq for OffsetDateTime {
|
|
+ fn eq(&self, other: &Self) -> bool {
|
|
+ self.to_offset_raw(UtcOffset::UTC) == other.to_offset_raw(UtcOffset::UTC)
|
|
+ }
|
|
+}
|
|
+
|
|
+impl PartialOrd for OffsetDateTime {
|
|
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
|
+ Some(self.cmp(other))
|
|
+ }
|
|
+}
|
|
+
|
|
+impl Ord for OffsetDateTime {
|
|
+ fn cmp(&self, other: &Self) -> Ordering {
|
|
+ self.to_offset_raw(UtcOffset::UTC)
|
|
+ .cmp(&other.to_offset_raw(UtcOffset::UTC))
|
|
+ }
|
|
+}
|
|
+
|
|
+impl Hash for OffsetDateTime {
|
|
+ fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
|
|
+ self.to_offset_raw(UtcOffset::UTC).hash(state);
|
|
+ }
|
|
+}
|
|
|
|
impl OffsetDateTime {
|
|
/// Midnight, 1 January, 1970 (UTC).
|
|
@@ -40,7 +76,12 @@ impl OffsetDateTime {
|
|
/// # use time_macros::datetime;
|
|
/// assert_eq!(OffsetDateTime::UNIX_EPOCH, datetime!(1970-01-01 0:00 UTC),);
|
|
/// ```
|
|
- pub const UNIX_EPOCH: Self = Self(Inner::UNIX_EPOCH);
|
|
+ pub const UNIX_EPOCH: Self = Self::new_in_offset(
|
|
+ // Safety: `ordinal` is not zero.
|
|
+ unsafe { Date::__from_ordinal_date_unchecked(1970, 1) },
|
|
+ Time::MIDNIGHT,
|
|
+ UtcOffset::UTC,
|
|
+ );
|
|
|
|
// region: now
|
|
/// Create a new `OffsetDateTime` with the current date and time in UTC.
|
|
@@ -53,7 +94,21 @@ impl OffsetDateTime {
|
|
/// ```
|
|
#[cfg(feature = "std")]
|
|
pub fn now_utc() -> Self {
|
|
- Self(Inner::now_utc())
|
|
+ #[cfg(all(
|
|
+ target_family = "wasm",
|
|
+ not(any(target_os = "emscripten", target_os = "wasi")),
|
|
+ feature = "wasm-bindgen"
|
|
+ ))]
|
|
+ {
|
|
+ js_sys::Date::new_0().into()
|
|
+ }
|
|
+
|
|
+ #[cfg(not(all(
|
|
+ target_family = "wasm",
|
|
+ not(any(target_os = "emscripten", target_os = "wasi")),
|
|
+ feature = "wasm-bindgen"
|
|
+ )))]
|
|
+ SystemTime::now().into()
|
|
}
|
|
|
|
/// Attempt to create a new `OffsetDateTime` with the current date and time in the local offset.
|
|
@@ -67,10 +122,47 @@ impl OffsetDateTime {
|
|
/// ```
|
|
#[cfg(feature = "local-offset")]
|
|
pub fn now_local() -> Result<Self, error::IndeterminateOffset> {
|
|
- Inner::now_local().map(Self)
|
|
+ let t = Self::now_utc();
|
|
+ Ok(t.to_offset(UtcOffset::local_offset_at(t)?))
|
|
}
|
|
// endregion now
|
|
|
|
+ /// Create a new `OffsetDateTime` with the given [`Date`], [`Time`], and [`UtcOffset`].
|
|
+ ///
|
|
+ /// ```
|
|
+ /// # use time::{Date, Month, OffsetDateTime, Time, UtcOffset};
|
|
+ /// # use time_macros::datetime;
|
|
+ /// let dt = OffsetDateTime::new_in_offset(
|
|
+ /// Date::from_calendar_date(2024, Month::January, 1)?,
|
|
+ /// Time::from_hms_nano(12, 59, 59, 500_000_000)?,
|
|
+ /// UtcOffset::from_hms(-5, 0, 0)?,
|
|
+ /// );
|
|
+ /// assert_eq!(dt, datetime!(2024-01-01 12:59:59.5 -5));
|
|
+ /// # Ok::<_, time::error::Error>(())
|
|
+ /// ```
|
|
+ pub const fn new_in_offset(date: Date, time: Time, offset: UtcOffset) -> Self {
|
|
+ Self {
|
|
+ local_date_time: date.with_time(time),
|
|
+ offset,
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /// Create a new `OffsetDateTime` with the given [`Date`] and [`Time`] in the UTC timezone.
|
|
+ ///
|
|
+ /// ```
|
|
+ /// # use time::{Date, Month, OffsetDateTime, Time};
|
|
+ /// # use time_macros::datetime;
|
|
+ /// let dt = OffsetDateTime::new_utc(
|
|
+ /// Date::from_calendar_date(2024, Month::January, 1)?,
|
|
+ /// Time::from_hms_nano(12, 59, 59, 500_000_000)?,
|
|
+ /// );
|
|
+ /// assert_eq!(dt, datetime!(2024-01-01 12:59:59.5 UTC));
|
|
+ /// # Ok::<_, time::error::Error>(())
|
|
+ /// ```
|
|
+ pub const fn new_utc(date: Date, time: Time) -> Self {
|
|
+ PrimitiveDateTime::new(date, time).assume_utc()
|
|
+ }
|
|
+
|
|
/// Convert the `OffsetDateTime` from the current [`UtcOffset`] to the provided [`UtcOffset`].
|
|
///
|
|
/// ```rust
|
|
@@ -97,7 +189,10 @@ impl OffsetDateTime {
|
|
///
|
|
/// This method panics if the local date-time in the new offset is outside the supported range.
|
|
pub const fn to_offset(self, offset: UtcOffset) -> Self {
|
|
- Self(self.0.to_offset(offset))
|
|
+ expect_opt!(
|
|
+ self.checked_to_offset(offset),
|
|
+ "local datetime out of valid range"
|
|
+ )
|
|
}
|
|
|
|
/// Convert the `OffsetDateTime` from the current [`UtcOffset`] to the provided [`UtcOffset`],
|
|
@@ -121,7 +216,74 @@ impl OffsetDateTime {
|
|
/// );
|
|
/// ```
|
|
pub const fn checked_to_offset(self, offset: UtcOffset) -> Option<Self> {
|
|
- Some(Self(const_try_opt!(self.0.checked_to_offset(offset))))
|
|
+ if self.offset.whole_hours() == offset.whole_hours()
|
|
+ && self.offset.minutes_past_hour() == offset.minutes_past_hour()
|
|
+ && self.offset.seconds_past_minute() == offset.seconds_past_minute()
|
|
+ {
|
|
+ return Some(self.replace_offset(offset));
|
|
+ }
|
|
+
|
|
+ let (year, ordinal, time) = self.to_offset_raw(offset);
|
|
+
|
|
+ if year > MAX_YEAR || year < MIN_YEAR {
|
|
+ return None;
|
|
+ }
|
|
+
|
|
+ Some(Self::new_in_offset(
|
|
+ // Safety: `ordinal` is not zero.
|
|
+ unsafe { Date::__from_ordinal_date_unchecked(year, ordinal) },
|
|
+ time,
|
|
+ offset,
|
|
+ ))
|
|
+ }
|
|
+
|
|
+ /// Equivalent to `.to_offset(UtcOffset::UTC)`, but returning the year, ordinal, and time. This
|
|
+ /// avoids constructing an invalid [`Date`] if the new value is out of range.
|
|
+ pub(crate) const fn to_offset_raw(self, offset: UtcOffset) -> (i32, u16, Time) {
|
|
+ let from = self.offset;
|
|
+ let to = offset;
|
|
+
|
|
+ // Fast path for when no conversion is necessary.
|
|
+ if from.whole_hours() == to.whole_hours()
|
|
+ && from.minutes_past_hour() == to.minutes_past_hour()
|
|
+ && from.seconds_past_minute() == to.seconds_past_minute()
|
|
+ {
|
|
+ return (self.year(), self.ordinal(), self.time());
|
|
+ }
|
|
+
|
|
+ let mut second = self.second() as i16 - from.seconds_past_minute() as i16
|
|
+ + to.seconds_past_minute() as i16;
|
|
+ let mut minute =
|
|
+ self.minute() as i16 - from.minutes_past_hour() as i16 + to.minutes_past_hour() as i16;
|
|
+ let mut hour = self.hour() as i8 - from.whole_hours() + to.whole_hours();
|
|
+ let (mut year, ordinal) = self.to_ordinal_date();
|
|
+ let mut ordinal = ordinal as i16;
|
|
+
|
|
+ // Cascade the values twice. This is needed because the values are adjusted twice above.
|
|
+ cascade!(second in 0..Second::per(Minute) as i16 => minute);
|
|
+ cascade!(second in 0..Second::per(Minute) as i16 => minute);
|
|
+ cascade!(minute in 0..Minute::per(Hour) as i16 => hour);
|
|
+ cascade!(minute in 0..Minute::per(Hour) as i16 => hour);
|
|
+ cascade!(hour in 0..Hour::per(Day) as i8 => ordinal);
|
|
+ cascade!(hour in 0..Hour::per(Day) as i8 => ordinal);
|
|
+ cascade!(ordinal => year);
|
|
+
|
|
+ debug_assert!(ordinal > 0);
|
|
+ debug_assert!(ordinal <= util::days_in_year(year) as i16);
|
|
+
|
|
+ (
|
|
+ year,
|
|
+ ordinal as _,
|
|
+ // Safety: The cascades above ensure the values are in range.
|
|
+ unsafe {
|
|
+ Time::__from_hms_nanos_unchecked(
|
|
+ hour as _,
|
|
+ minute as _,
|
|
+ second as _,
|
|
+ self.nanosecond(),
|
|
+ )
|
|
+ },
|
|
+ )
|
|
}
|
|
|
|
// region: constructors
|
|
@@ -154,7 +316,34 @@ impl OffsetDateTime {
|
|
/// # Ok::<_, time::Error>(())
|
|
/// ```
|
|
pub const fn from_unix_timestamp(timestamp: i64) -> Result<Self, error::ComponentRange> {
|
|
- Ok(Self(const_try!(Inner::from_unix_timestamp(timestamp))))
|
|
+ type Timestamp = RangedI64<
|
|
+ {
|
|
+ OffsetDateTime::new_in_offset(Date::MIN, Time::MIDNIGHT, UtcOffset::UTC)
|
|
+ .unix_timestamp()
|
|
+ },
|
|
+ {
|
|
+ OffsetDateTime::new_in_offset(Date::MAX, Time::MAX, UtcOffset::UTC).unix_timestamp()
|
|
+ },
|
|
+ >;
|
|
+ ensure_ranged!(Timestamp: timestamp);
|
|
+
|
|
+ // Use the unchecked method here, as the input validity has already been verified.
|
|
+ let date = Date::from_julian_day_unchecked(
|
|
+ UNIX_EPOCH_JULIAN_DAY + div_floor!(timestamp, Second::per(Day) as i64) as i32,
|
|
+ );
|
|
+
|
|
+ let seconds_within_day = timestamp.rem_euclid(Second::per(Day) as _);
|
|
+ // Safety: All values are in range.
|
|
+ let time = unsafe {
|
|
+ Time::__from_hms_nanos_unchecked(
|
|
+ (seconds_within_day / Second::per(Hour) as i64) as _,
|
|
+ ((seconds_within_day % Second::per(Hour) as i64) / Minute::per(Hour) as i64) as _,
|
|
+ (seconds_within_day % Second::per(Minute) as i64) as _,
|
|
+ 0,
|
|
+ )
|
|
+ };
|
|
+
|
|
+ Ok(Self::new_in_offset(date, time, UtcOffset::UTC))
|
|
}
|
|
|
|
/// Construct an `OffsetDateTime` from the provided Unix timestamp (in nanoseconds). Calling
|
|
@@ -173,9 +362,24 @@ impl OffsetDateTime {
|
|
/// );
|
|
/// ```
|
|
pub const fn from_unix_timestamp_nanos(timestamp: i128) -> Result<Self, error::ComponentRange> {
|
|
- Ok(Self(const_try!(Inner::from_unix_timestamp_nanos(
|
|
- timestamp
|
|
- ))))
|
|
+ let datetime = const_try!(Self::from_unix_timestamp(div_floor!(
|
|
+ timestamp,
|
|
+ Nanosecond::per(Second) as i128
|
|
+ ) as i64));
|
|
+
|
|
+ Ok(Self::new_in_offset(
|
|
+ datetime.date(),
|
|
+ // Safety: `nanosecond` is in range due to `rem_euclid`.
|
|
+ unsafe {
|
|
+ Time::__from_hms_nanos_unchecked(
|
|
+ datetime.hour(),
|
|
+ datetime.minute(),
|
|
+ datetime.second(),
|
|
+ timestamp.rem_euclid(Nanosecond::per(Second) as _) as u32,
|
|
+ )
|
|
+ },
|
|
+ UtcOffset::UTC,
|
|
+ ))
|
|
}
|
|
// endregion constructors
|
|
|
|
@@ -188,7 +392,7 @@ impl OffsetDateTime {
|
|
/// assert_eq!(datetime!(2019-01-01 0:00 +1).offset(), offset!(+1));
|
|
/// ```
|
|
pub const fn offset(self) -> UtcOffset {
|
|
- self.0.offset()
|
|
+ self.offset
|
|
}
|
|
|
|
/// Get the [Unix timestamp](https://en.wikipedia.org/wiki/Unix_time).
|
|
@@ -199,7 +403,13 @@ impl OffsetDateTime {
|
|
/// assert_eq!(datetime!(1970-01-01 0:00 -1).unix_timestamp(), 3_600);
|
|
/// ```
|
|
pub const fn unix_timestamp(self) -> i64 {
|
|
- self.0.unix_timestamp()
|
|
+ let days =
|
|
+ (self.to_julian_day() as i64 - UNIX_EPOCH_JULIAN_DAY as i64) * Second::per(Day) as i64;
|
|
+ let hours = self.hour() as i64 * Second::per(Hour) as i64;
|
|
+ let minutes = self.minute() as i64 * Second::per(Minute) as i64;
|
|
+ let seconds = self.second() as i64;
|
|
+ let offset_seconds = self.offset.whole_seconds() as i64;
|
|
+ days + hours + minutes + seconds - offset_seconds
|
|
}
|
|
|
|
/// Get the Unix timestamp in nanoseconds.
|
|
@@ -213,7 +423,12 @@ impl OffsetDateTime {
|
|
/// );
|
|
/// ```
|
|
pub const fn unix_timestamp_nanos(self) -> i128 {
|
|
- self.0.unix_timestamp_nanos()
|
|
+ self.unix_timestamp() as i128 * Nanosecond::per(Second) as i128 + self.nanosecond() as i128
|
|
+ }
|
|
+
|
|
+ /// Get the [`PrimitiveDateTime`] in the stored offset.
|
|
+ const fn date_time(self) -> PrimitiveDateTime {
|
|
+ self.local_date_time
|
|
}
|
|
|
|
/// Get the [`Date`] in the stored offset.
|
|
@@ -229,7 +444,7 @@ impl OffsetDateTime {
|
|
/// );
|
|
/// ```
|
|
pub const fn date(self) -> Date {
|
|
- self.0.date()
|
|
+ self.date_time().date()
|
|
}
|
|
|
|
/// Get the [`Time`] in the stored offset.
|
|
@@ -245,7 +460,7 @@ impl OffsetDateTime {
|
|
/// );
|
|
/// ```
|
|
pub const fn time(self) -> Time {
|
|
- self.0.time()
|
|
+ self.date_time().time()
|
|
}
|
|
|
|
// region: date getters
|
|
@@ -263,7 +478,7 @@ impl OffsetDateTime {
|
|
/// assert_eq!(datetime!(2020-01-01 0:00 UTC).year(), 2020);
|
|
/// ```
|
|
pub const fn year(self) -> i32 {
|
|
- self.0.year()
|
|
+ self.date().year()
|
|
}
|
|
|
|
/// Get the month of the date in the stored offset.
|
|
@@ -280,7 +495,7 @@ impl OffsetDateTime {
|
|
/// );
|
|
/// ```
|
|
pub const fn month(self) -> Month {
|
|
- self.0.month()
|
|
+ self.date().month()
|
|
}
|
|
|
|
/// Get the day of the date in the stored offset.
|
|
@@ -298,7 +513,7 @@ impl OffsetDateTime {
|
|
/// );
|
|
/// ```
|
|
pub const fn day(self) -> u8 {
|
|
- self.0.day()
|
|
+ self.date().day()
|
|
}
|
|
|
|
/// Get the day of the year of the date in the stored offset.
|
|
@@ -316,7 +531,7 @@ impl OffsetDateTime {
|
|
/// );
|
|
/// ```
|
|
pub const fn ordinal(self) -> u16 {
|
|
- self.0.ordinal()
|
|
+ self.date().ordinal()
|
|
}
|
|
|
|
/// Get the ISO week number of the date in the stored offset.
|
|
@@ -331,7 +546,7 @@ impl OffsetDateTime {
|
|
/// assert_eq!(datetime!(2021-01-01 0:00 UTC).iso_week(), 53);
|
|
/// ```
|
|
pub const fn iso_week(self) -> u8 {
|
|
- self.0.iso_week()
|
|
+ self.date().iso_week()
|
|
}
|
|
|
|
/// Get the week number where week 1 begins on the first Sunday.
|
|
@@ -346,7 +561,7 @@ impl OffsetDateTime {
|
|
/// assert_eq!(datetime!(2021-01-01 0:00 UTC).sunday_based_week(), 0);
|
|
/// ```
|
|
pub const fn sunday_based_week(self) -> u8 {
|
|
- self.0.sunday_based_week()
|
|
+ self.date().sunday_based_week()
|
|
}
|
|
|
|
/// Get the week number where week 1 begins on the first Monday.
|
|
@@ -361,7 +576,7 @@ impl OffsetDateTime {
|
|
/// assert_eq!(datetime!(2021-01-01 0:00 UTC).monday_based_week(), 0);
|
|
/// ```
|
|
pub const fn monday_based_week(self) -> u8 {
|
|
- self.0.monday_based_week()
|
|
+ self.date().monday_based_week()
|
|
}
|
|
|
|
/// Get the year, month, and day.
|
|
@@ -375,7 +590,7 @@ impl OffsetDateTime {
|
|
/// );
|
|
/// ```
|
|
pub const fn to_calendar_date(self) -> (i32, Month, u8) {
|
|
- self.0.to_calendar_date()
|
|
+ self.date().to_calendar_date()
|
|
}
|
|
|
|
/// Get the year and ordinal day number.
|
|
@@ -388,7 +603,7 @@ impl OffsetDateTime {
|
|
/// );
|
|
/// ```
|
|
pub const fn to_ordinal_date(self) -> (i32, u16) {
|
|
- self.0.to_ordinal_date()
|
|
+ self.date().to_ordinal_date()
|
|
}
|
|
|
|
/// Get the ISO 8601 year, week number, and weekday.
|
|
@@ -418,7 +633,7 @@ impl OffsetDateTime {
|
|
/// );
|
|
/// ```
|
|
pub const fn to_iso_week_date(self) -> (i32, u8, Weekday) {
|
|
- self.0.to_iso_week_date()
|
|
+ self.date().to_iso_week_date()
|
|
}
|
|
|
|
/// Get the weekday of the date in the stored offset.
|
|
@@ -431,7 +646,7 @@ impl OffsetDateTime {
|
|
/// assert_eq!(datetime!(2019-03-01 0:00 UTC).weekday(), Friday);
|
|
/// ```
|
|
pub const fn weekday(self) -> Weekday {
|
|
- self.0.weekday()
|
|
+ self.date().weekday()
|
|
}
|
|
|
|
/// Get the Julian day for the date. The time is not taken into account for this calculation.
|
|
@@ -447,7 +662,7 @@ impl OffsetDateTime {
|
|
/// assert_eq!(datetime!(2019-12-31 0:00 UTC).to_julian_day(), 2_458_849);
|
|
/// ```
|
|
pub const fn to_julian_day(self) -> i32 {
|
|
- self.0.to_julian_day()
|
|
+ self.date().to_julian_day()
|
|
}
|
|
// endregion date getters
|
|
|
|
@@ -460,7 +675,7 @@ impl OffsetDateTime {
|
|
/// assert_eq!(datetime!(2020-01-01 23:59:59 UTC).to_hms(), (23, 59, 59));
|
|
/// ```
|
|
pub const fn to_hms(self) -> (u8, u8, u8) {
|
|
- self.0.as_hms()
|
|
+ self.time().as_hms()
|
|
}
|
|
|
|
/// Get the clock hour, minute, second, and millisecond.
|
|
@@ -477,7 +692,7 @@ impl OffsetDateTime {
|
|
/// );
|
|
/// ```
|
|
pub const fn to_hms_milli(self) -> (u8, u8, u8, u16) {
|
|
- self.0.as_hms_milli()
|
|
+ self.time().as_hms_milli()
|
|
}
|
|
|
|
/// Get the clock hour, minute, second, and microsecond.
|
|
@@ -494,7 +709,7 @@ impl OffsetDateTime {
|
|
/// );
|
|
/// ```
|
|
pub const fn to_hms_micro(self) -> (u8, u8, u8, u32) {
|
|
- self.0.as_hms_micro()
|
|
+ self.time().as_hms_micro()
|
|
}
|
|
|
|
/// Get the clock hour, minute, second, and nanosecond.
|
|
@@ -511,7 +726,7 @@ impl OffsetDateTime {
|
|
/// );
|
|
/// ```
|
|
pub const fn to_hms_nano(self) -> (u8, u8, u8, u32) {
|
|
- self.0.as_hms_nano()
|
|
+ self.time().as_hms_nano()
|
|
}
|
|
|
|
/// Get the clock hour in the stored offset.
|
|
@@ -529,7 +744,7 @@ impl OffsetDateTime {
|
|
/// );
|
|
/// ```
|
|
pub const fn hour(self) -> u8 {
|
|
- self.0.hour()
|
|
+ self.time().hour()
|
|
}
|
|
|
|
/// Get the minute within the hour in the stored offset.
|
|
@@ -547,7 +762,7 @@ impl OffsetDateTime {
|
|
/// );
|
|
/// ```
|
|
pub const fn minute(self) -> u8 {
|
|
- self.0.minute()
|
|
+ self.time().minute()
|
|
}
|
|
|
|
/// Get the second within the minute in the stored offset.
|
|
@@ -565,7 +780,7 @@ impl OffsetDateTime {
|
|
/// );
|
|
/// ```
|
|
pub const fn second(self) -> u8 {
|
|
- self.0.second()
|
|
+ self.time().second()
|
|
}
|
|
|
|
// Because a `UtcOffset` is limited in resolution to one second, any subsecond value will not
|
|
@@ -581,7 +796,7 @@ impl OffsetDateTime {
|
|
/// assert_eq!(datetime!(2019-01-01 23:59:59.999 UTC).millisecond(), 999);
|
|
/// ```
|
|
pub const fn millisecond(self) -> u16 {
|
|
- self.0.millisecond()
|
|
+ self.time().millisecond()
|
|
}
|
|
|
|
/// Get the microseconds within the second in the stored offset.
|
|
@@ -597,7 +812,7 @@ impl OffsetDateTime {
|
|
/// );
|
|
/// ```
|
|
pub const fn microsecond(self) -> u32 {
|
|
- self.0.microsecond()
|
|
+ self.time().microsecond()
|
|
}
|
|
|
|
/// Get the nanoseconds within the second in the stored offset.
|
|
@@ -613,7 +828,7 @@ impl OffsetDateTime {
|
|
/// );
|
|
/// ```
|
|
pub const fn nanosecond(self) -> u32 {
|
|
- self.0.nanosecond()
|
|
+ self.time().nanosecond()
|
|
}
|
|
// endregion time getters
|
|
// endregion getters
|
|
@@ -636,7 +851,7 @@ impl OffsetDateTime {
|
|
/// );
|
|
/// ```
|
|
pub const fn checked_add(self, duration: Duration) -> Option<Self> {
|
|
- Some(Self(const_try_opt!(self.0.checked_add(duration))))
|
|
+ Some(const_try_opt!(self.date_time().checked_add(duration)).assume_offset(self.offset()))
|
|
}
|
|
|
|
/// Computes `self - duration`, returning `None` if an overflow occurred.
|
|
@@ -656,7 +871,7 @@ impl OffsetDateTime {
|
|
/// );
|
|
/// ```
|
|
pub const fn checked_sub(self, duration: Duration) -> Option<Self> {
|
|
- Some(Self(const_try_opt!(self.0.checked_sub(duration))))
|
|
+ Some(const_try_opt!(self.date_time().checked_sub(duration)).assume_offset(self.offset()))
|
|
}
|
|
// endregion: checked arithmetic
|
|
|
|
@@ -707,7 +922,13 @@ impl OffsetDateTime {
|
|
/// );
|
|
/// ```
|
|
pub const fn saturating_add(self, duration: Duration) -> Self {
|
|
- Self(self.0.saturating_add(duration))
|
|
+ if let Some(datetime) = self.checked_add(duration) {
|
|
+ datetime
|
|
+ } else if duration.is_negative() {
|
|
+ PrimitiveDateTime::MIN.assume_offset(self.offset())
|
|
+ } else {
|
|
+ PrimitiveDateTime::MAX.assume_offset(self.offset())
|
|
+ }
|
|
}
|
|
|
|
/// Computes `self - duration`, saturating value on overflow.
|
|
@@ -756,7 +977,13 @@ impl OffsetDateTime {
|
|
/// );
|
|
/// ```
|
|
pub const fn saturating_sub(self, duration: Duration) -> Self {
|
|
- Self(self.0.saturating_sub(duration))
|
|
+ if let Some(datetime) = self.checked_sub(duration) {
|
|
+ datetime
|
|
+ } else if duration.is_negative() {
|
|
+ PrimitiveDateTime::MAX.assume_offset(self.offset())
|
|
+ } else {
|
|
+ PrimitiveDateTime::MIN.assume_offset(self.offset())
|
|
+ }
|
|
}
|
|
// endregion: saturating arithmetic
|
|
}
|
|
@@ -784,7 +1011,7 @@ impl OffsetDateTime {
|
|
/// ```
|
|
#[must_use = "This method does not mutate the original `OffsetDateTime`."]
|
|
pub const fn replace_time(self, time: Time) -> Self {
|
|
- Self(self.0.replace_time(time))
|
|
+ Self::new_in_offset(self.date(), time, self.offset())
|
|
}
|
|
|
|
/// Replace the date, which is assumed to be in the stored offset. The time and offset
|
|
@@ -803,7 +1030,7 @@ impl OffsetDateTime {
|
|
/// ```
|
|
#[must_use = "This method does not mutate the original `OffsetDateTime`."]
|
|
pub const fn replace_date(self, date: Date) -> Self {
|
|
- Self(self.0.replace_date(date))
|
|
+ Self::new_in_offset(date, self.time(), self.offset())
|
|
}
|
|
|
|
/// Replace the date and time, which are assumed to be in the stored offset. The offset
|
|
@@ -822,7 +1049,7 @@ impl OffsetDateTime {
|
|
/// ```
|
|
#[must_use = "This method does not mutate the original `OffsetDateTime`."]
|
|
pub const fn replace_date_time(self, date_time: PrimitiveDateTime) -> Self {
|
|
- Self(self.0.replace_date_time(date_time.0))
|
|
+ date_time.assume_offset(self.offset())
|
|
}
|
|
|
|
/// Replace the offset. The date and time components remain unchanged.
|
|
@@ -836,7 +1063,7 @@ impl OffsetDateTime {
|
|
/// ```
|
|
#[must_use = "This method does not mutate the original `OffsetDateTime`."]
|
|
pub const fn replace_offset(self, offset: UtcOffset) -> Self {
|
|
- Self(self.0.replace_offset(offset))
|
|
+ self.date_time().assume_offset(offset)
|
|
}
|
|
|
|
/// Replace the year. The month and day will be unchanged.
|
|
@@ -850,8 +1077,9 @@ impl OffsetDateTime {
|
|
/// assert!(datetime!(2022 - 02 - 18 12:00 +01).replace_year(-1_000_000_000).is_err()); // -1_000_000_000 isn't a valid year
|
|
/// assert!(datetime!(2022 - 02 - 18 12:00 +01).replace_year(1_000_000_000).is_err()); // 1_000_000_000 isn't a valid year
|
|
/// ```
|
|
+ #[must_use = "This method does not mutate the original `OffsetDateTime`."]
|
|
pub const fn replace_year(self, year: i32) -> Result<Self, error::ComponentRange> {
|
|
- Ok(Self(const_try!(self.0.replace_year(year))))
|
|
+ Ok(const_try!(self.date_time().replace_year(year)).assume_offset(self.offset()))
|
|
}
|
|
|
|
/// Replace the month of the year.
|
|
@@ -865,8 +1093,9 @@ impl OffsetDateTime {
|
|
/// );
|
|
/// assert!(datetime!(2022 - 01 - 30 12:00 +01).replace_month(Month::February).is_err()); // 30 isn't a valid day in February
|
|
/// ```
|
|
+ #[must_use = "This method does not mutate the original `OffsetDateTime`."]
|
|
pub const fn replace_month(self, month: Month) -> Result<Self, error::ComponentRange> {
|
|
- Ok(Self(const_try!(self.0.replace_month(month))))
|
|
+ Ok(const_try!(self.date_time().replace_month(month)).assume_offset(self.offset()))
|
|
}
|
|
|
|
/// Replace the day of the month.
|
|
@@ -880,8 +1109,22 @@ impl OffsetDateTime {
|
|
/// assert!(datetime!(2022 - 02 - 18 12:00 +01).replace_day(0).is_err()); // 00 isn't a valid day
|
|
/// assert!(datetime!(2022 - 02 - 18 12:00 +01).replace_day(30).is_err()); // 30 isn't a valid day in February
|
|
/// ```
|
|
+ #[must_use = "This method does not mutate the original `OffsetDateTime`."]
|
|
pub const fn replace_day(self, day: u8) -> Result<Self, error::ComponentRange> {
|
|
- Ok(Self(const_try!(self.0.replace_day(day))))
|
|
+ Ok(const_try!(self.date_time().replace_day(day)).assume_offset(self.offset()))
|
|
+ }
|
|
+
|
|
+ /// Replace the day of the year.
|
|
+ ///
|
|
+ /// ```rust
|
|
+ /// # use time_macros::datetime;
|
|
+ /// assert_eq!(datetime!(2022-049 12:00 +01).replace_ordinal(1), Ok(datetime!(2022-001 12:00 +01)));
|
|
+ /// assert!(datetime!(2022-049 12:00 +01).replace_ordinal(0).is_err()); // 0 isn't a valid ordinal
|
|
+ /// assert!(datetime!(2022-049 12:00 +01).replace_ordinal(366).is_err()); // 2022 isn't a leap year
|
|
+ /// ```
|
|
+ #[must_use = "This method does not mutate the original `OffsetDateTime`."]
|
|
+ pub const fn replace_ordinal(self, ordinal: u16) -> Result<Self, error::ComponentRange> {
|
|
+ Ok(const_try!(self.date_time().replace_ordinal(ordinal)).assume_offset(self.offset()))
|
|
}
|
|
|
|
/// Replace the clock hour.
|
|
@@ -894,8 +1137,9 @@ impl OffsetDateTime {
|
|
/// );
|
|
/// assert!(datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01).replace_hour(24).is_err()); // 24 isn't a valid hour
|
|
/// ```
|
|
+ #[must_use = "This method does not mutate the original `OffsetDateTime`."]
|
|
pub const fn replace_hour(self, hour: u8) -> Result<Self, error::ComponentRange> {
|
|
- Ok(Self(const_try!(self.0.replace_hour(hour))))
|
|
+ Ok(const_try!(self.date_time().replace_hour(hour)).assume_offset(self.offset()))
|
|
}
|
|
|
|
/// Replace the minutes within the hour.
|
|
@@ -908,8 +1152,9 @@ impl OffsetDateTime {
|
|
/// );
|
|
/// assert!(datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01).replace_minute(60).is_err()); // 60 isn't a valid minute
|
|
/// ```
|
|
+ #[must_use = "This method does not mutate the original `OffsetDateTime`."]
|
|
pub const fn replace_minute(self, minute: u8) -> Result<Self, error::ComponentRange> {
|
|
- Ok(Self(const_try!(self.0.replace_minute(minute))))
|
|
+ Ok(const_try!(self.date_time().replace_minute(minute)).assume_offset(self.offset()))
|
|
}
|
|
|
|
/// Replace the seconds within the minute.
|
|
@@ -922,8 +1167,9 @@ impl OffsetDateTime {
|
|
/// );
|
|
/// assert!(datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01).replace_second(60).is_err()); // 60 isn't a valid second
|
|
/// ```
|
|
+ #[must_use = "This method does not mutate the original `OffsetDateTime`."]
|
|
pub const fn replace_second(self, second: u8) -> Result<Self, error::ComponentRange> {
|
|
- Ok(Self(const_try!(self.0.replace_second(second))))
|
|
+ Ok(const_try!(self.date_time().replace_second(second)).assume_offset(self.offset()))
|
|
}
|
|
|
|
/// Replace the milliseconds within the second.
|
|
@@ -936,11 +1182,15 @@ impl OffsetDateTime {
|
|
/// );
|
|
/// assert!(datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01).replace_millisecond(1_000).is_err()); // 1_000 isn't a valid millisecond
|
|
/// ```
|
|
+ #[must_use = "This method does not mutate the original `OffsetDateTime`."]
|
|
pub const fn replace_millisecond(
|
|
self,
|
|
millisecond: u16,
|
|
) -> Result<Self, error::ComponentRange> {
|
|
- Ok(Self(const_try!(self.0.replace_millisecond(millisecond))))
|
|
+ Ok(
|
|
+ const_try!(self.date_time().replace_millisecond(millisecond))
|
|
+ .assume_offset(self.offset()),
|
|
+ )
|
|
}
|
|
|
|
/// Replace the microseconds within the second.
|
|
@@ -953,11 +1203,15 @@ impl OffsetDateTime {
|
|
/// );
|
|
/// assert!(datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01).replace_microsecond(1_000_000).is_err()); // 1_000_000 isn't a valid microsecond
|
|
/// ```
|
|
+ #[must_use = "This method does not mutate the original `OffsetDateTime`."]
|
|
pub const fn replace_microsecond(
|
|
self,
|
|
microsecond: u32,
|
|
) -> Result<Self, error::ComponentRange> {
|
|
- Ok(Self(const_try!(self.0.replace_microsecond(microsecond))))
|
|
+ Ok(
|
|
+ const_try!(self.date_time().replace_microsecond(microsecond))
|
|
+ .assume_offset(self.offset()),
|
|
+ )
|
|
}
|
|
|
|
/// Replace the nanoseconds within the second.
|
|
@@ -970,8 +1224,12 @@ impl OffsetDateTime {
|
|
/// );
|
|
/// assert!(datetime!(2022 - 02 - 18 01:02:03.004_005_006 +01).replace_nanosecond(1_000_000_000).is_err()); // 1_000_000_000 isn't a valid nanosecond
|
|
/// ```
|
|
+ #[must_use = "This method does not mutate the original `OffsetDateTime`."]
|
|
pub const fn replace_nanosecond(self, nanosecond: u32) -> Result<Self, error::ComponentRange> {
|
|
- Ok(Self(const_try!(self.0.replace_nanosecond(nanosecond))))
|
|
+ Ok(
|
|
+ const_try!(self.date_time().replace_nanosecond(nanosecond))
|
|
+ .assume_offset(self.offset()),
|
|
+ )
|
|
}
|
|
}
|
|
// endregion replacement
|
|
@@ -986,7 +1244,12 @@ impl OffsetDateTime {
|
|
output: &mut impl io::Write,
|
|
format: &(impl Formattable + ?Sized),
|
|
) -> Result<usize, error::Format> {
|
|
- self.0.format_into(output, format)
|
|
+ format.format_into(
|
|
+ output,
|
|
+ Some(self.date()),
|
|
+ Some(self.time()),
|
|
+ Some(self.offset()),
|
|
+ )
|
|
}
|
|
|
|
/// Format the `OffsetDateTime` using the provided [format
|
|
@@ -1006,7 +1269,7 @@ impl OffsetDateTime {
|
|
/// # Ok::<_, time::Error>(())
|
|
/// ```
|
|
pub fn format(self, format: &(impl Formattable + ?Sized)) -> Result<String, error::Format> {
|
|
- self.0.format(format)
|
|
+ format.format(Some(self.date()), Some(self.time()), Some(self.offset()))
|
|
}
|
|
}
|
|
|
|
@@ -1032,15 +1295,39 @@ impl OffsetDateTime {
|
|
input: &str,
|
|
description: &(impl Parsable + ?Sized),
|
|
) -> Result<Self, error::Parse> {
|
|
- Inner::parse(input, description).map(Self)
|
|
+ description.parse_offset_date_time(input.as_bytes())
|
|
+ }
|
|
+
|
|
+ /// A helper method to check if the `OffsetDateTime` is a valid representation of a leap second.
|
|
+ /// Leap seconds, when parsed, are represented as the preceding nanosecond. However, leap
|
|
+ /// seconds can only occur as the last second of a month UTC.
|
|
+ #[cfg(feature = "parsing")]
|
|
+ pub(crate) const fn is_valid_leap_second_stand_in(self) -> bool {
|
|
+ // This comparison doesn't need to be adjusted for the stored offset, so check it first for
|
|
+ // speed.
|
|
+ if self.nanosecond() != 999_999_999 {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ let (year, ordinal, time) = self.to_offset_raw(UtcOffset::UTC);
|
|
+ let Ok(date) = Date::from_ordinal_date(year, ordinal) else {
|
|
+ return false;
|
|
+ };
|
|
+
|
|
+ time.hour() == 23
|
|
+ && time.minute() == 59
|
|
+ && time.second() == 59
|
|
+ && date.day() == util::days_in_year_month(year, date.month())
|
|
}
|
|
}
|
|
|
|
impl SmartDisplay for OffsetDateTime {
|
|
- type Metadata = DateTimeMetadata;
|
|
+ type Metadata = ();
|
|
|
|
- fn metadata(&self, f: FormatterOptions) -> Metadata<Self> {
|
|
- self.0.metadata(f).reuse()
|
|
+ fn metadata(&self, _: FormatterOptions) -> Metadata<Self> {
|
|
+ let width =
|
|
+ smart_display::padded_width_of!(self.date(), " ", self.time(), " ", self.offset());
|
|
+ Metadata::new(width, self, ())
|
|
}
|
|
|
|
fn fmt_with_metadata(
|
|
@@ -1048,7 +1335,10 @@ impl SmartDisplay for OffsetDateTime {
|
|
f: &mut fmt::Formatter<'_>,
|
|
metadata: Metadata<Self>,
|
|
) -> fmt::Result {
|
|
- self.0.fmt_with_metadata(f, metadata.reuse())
|
|
+ f.pad_with_width(
|
|
+ metadata.unpadded_width(),
|
|
+ format_args!("{} {} {}", self.date(), self.time(), self.offset()),
|
|
+ )
|
|
}
|
|
}
|
|
|
|
@@ -1069,64 +1359,121 @@ impl fmt::Debug for OffsetDateTime {
|
|
impl Add<Duration> for OffsetDateTime {
|
|
type Output = Self;
|
|
|
|
- fn add(self, rhs: Duration) -> Self::Output {
|
|
- Self(self.0.add(rhs))
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if an overflow occurs.
|
|
+ fn add(self, duration: Duration) -> Self::Output {
|
|
+ self.checked_add(duration)
|
|
+ .expect("resulting value is out of range")
|
|
}
|
|
}
|
|
|
|
impl Add<StdDuration> for OffsetDateTime {
|
|
type Output = Self;
|
|
|
|
- fn add(self, rhs: StdDuration) -> Self::Output {
|
|
- Self(self.0.add(rhs))
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if an overflow occurs.
|
|
+ fn add(self, duration: StdDuration) -> Self::Output {
|
|
+ let (is_next_day, time) = self.time().adjusting_add_std(duration);
|
|
+
|
|
+ Self::new_in_offset(
|
|
+ if is_next_day {
|
|
+ (self.date() + duration)
|
|
+ .next_day()
|
|
+ .expect("resulting value is out of range")
|
|
+ } else {
|
|
+ self.date() + duration
|
|
+ },
|
|
+ time,
|
|
+ self.offset,
|
|
+ )
|
|
}
|
|
}
|
|
|
|
impl AddAssign<Duration> for OffsetDateTime {
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if an overflow occurs.
|
|
fn add_assign(&mut self, rhs: Duration) {
|
|
- self.0.add_assign(rhs);
|
|
+ *self = *self + rhs;
|
|
}
|
|
}
|
|
|
|
impl AddAssign<StdDuration> for OffsetDateTime {
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if an overflow occurs.
|
|
fn add_assign(&mut self, rhs: StdDuration) {
|
|
- self.0.add_assign(rhs);
|
|
+ *self = *self + rhs;
|
|
}
|
|
}
|
|
|
|
impl Sub<Duration> for OffsetDateTime {
|
|
type Output = Self;
|
|
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if an overflow occurs.
|
|
fn sub(self, rhs: Duration) -> Self::Output {
|
|
- Self(self.0.sub(rhs))
|
|
+ self.checked_sub(rhs)
|
|
+ .expect("resulting value is out of range")
|
|
}
|
|
}
|
|
|
|
impl Sub<StdDuration> for OffsetDateTime {
|
|
type Output = Self;
|
|
|
|
- fn sub(self, rhs: StdDuration) -> Self::Output {
|
|
- Self(self.0.sub(rhs))
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if an overflow occurs.
|
|
+ fn sub(self, duration: StdDuration) -> Self::Output {
|
|
+ let (is_previous_day, time) = self.time().adjusting_sub_std(duration);
|
|
+
|
|
+ Self::new_in_offset(
|
|
+ if is_previous_day {
|
|
+ (self.date() - duration)
|
|
+ .previous_day()
|
|
+ .expect("resulting value is out of range")
|
|
+ } else {
|
|
+ self.date() - duration
|
|
+ },
|
|
+ time,
|
|
+ self.offset,
|
|
+ )
|
|
}
|
|
}
|
|
|
|
impl SubAssign<Duration> for OffsetDateTime {
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if an overflow occurs.
|
|
fn sub_assign(&mut self, rhs: Duration) {
|
|
- self.0.sub_assign(rhs);
|
|
+ *self = *self - rhs;
|
|
}
|
|
}
|
|
|
|
impl SubAssign<StdDuration> for OffsetDateTime {
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if an overflow occurs.
|
|
fn sub_assign(&mut self, rhs: StdDuration) {
|
|
- self.0.sub_assign(rhs);
|
|
+ *self = *self - rhs;
|
|
}
|
|
}
|
|
|
|
impl Sub for OffsetDateTime {
|
|
type Output = Duration;
|
|
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if an overflow occurs.
|
|
fn sub(self, rhs: Self) -> Self::Output {
|
|
- self.0.sub(rhs.0)
|
|
+ let base = self.date_time() - rhs.date_time();
|
|
+ let adjustment = Duration::seconds(
|
|
+ (self.offset.whole_seconds() - rhs.offset.whole_seconds()).extend::<i64>(),
|
|
+ );
|
|
+ base - adjustment
|
|
}
|
|
}
|
|
|
|
@@ -1134,8 +1481,11 @@ impl Sub for OffsetDateTime {
|
|
impl Sub<SystemTime> for OffsetDateTime {
|
|
type Output = Duration;
|
|
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if an overflow occurs.
|
|
fn sub(self, rhs: SystemTime) -> Self::Output {
|
|
- self.0.sub(rhs)
|
|
+ self - Self::from(rhs)
|
|
}
|
|
}
|
|
|
|
@@ -1143,50 +1493,94 @@ impl Sub<SystemTime> for OffsetDateTime {
|
|
impl Sub<OffsetDateTime> for SystemTime {
|
|
type Output = Duration;
|
|
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if an overflow occurs.
|
|
fn sub(self, rhs: OffsetDateTime) -> Self::Output {
|
|
- self.sub(rhs.0)
|
|
+ OffsetDateTime::from(self) - rhs
|
|
+ }
|
|
+}
|
|
+
|
|
+#[cfg(feature = "std")]
|
|
+impl Add<Duration> for SystemTime {
|
|
+ type Output = Self;
|
|
+
|
|
+ fn add(self, duration: Duration) -> Self::Output {
|
|
+ if duration.is_zero() {
|
|
+ self
|
|
+ } else if duration.is_positive() {
|
|
+ self + duration.unsigned_abs()
|
|
+ } else {
|
|
+ debug_assert!(duration.is_negative());
|
|
+ self - duration.unsigned_abs()
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+crate::internal_macros::impl_add_assign!(SystemTime: #[cfg(feature = "std")] Duration);
|
|
+
|
|
+#[cfg(feature = "std")]
|
|
+impl Sub<Duration> for SystemTime {
|
|
+ type Output = Self;
|
|
+
|
|
+ fn sub(self, duration: Duration) -> Self::Output {
|
|
+ (OffsetDateTime::from(self) - duration).into()
|
|
}
|
|
}
|
|
|
|
+crate::internal_macros::impl_sub_assign!(SystemTime: #[cfg(feature = "std")] Duration);
|
|
+
|
|
#[cfg(feature = "std")]
|
|
impl PartialEq<SystemTime> for OffsetDateTime {
|
|
fn eq(&self, rhs: &SystemTime) -> bool {
|
|
- self.0.eq(rhs)
|
|
+ self == &Self::from(*rhs)
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "std")]
|
|
impl PartialEq<OffsetDateTime> for SystemTime {
|
|
fn eq(&self, rhs: &OffsetDateTime) -> bool {
|
|
- self.eq(&rhs.0)
|
|
+ &OffsetDateTime::from(*self) == rhs
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "std")]
|
|
impl PartialOrd<SystemTime> for OffsetDateTime {
|
|
fn partial_cmp(&self, other: &SystemTime) -> Option<Ordering> {
|
|
- self.0.partial_cmp(other)
|
|
+ self.partial_cmp(&Self::from(*other))
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "std")]
|
|
impl PartialOrd<OffsetDateTime> for SystemTime {
|
|
fn partial_cmp(&self, other: &OffsetDateTime) -> Option<Ordering> {
|
|
- self.partial_cmp(&other.0)
|
|
+ OffsetDateTime::from(*self).partial_cmp(other)
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "std")]
|
|
impl From<SystemTime> for OffsetDateTime {
|
|
fn from(system_time: SystemTime) -> Self {
|
|
- Self(Inner::from(system_time))
|
|
+ match system_time.duration_since(SystemTime::UNIX_EPOCH) {
|
|
+ Ok(duration) => Self::UNIX_EPOCH + duration,
|
|
+ Err(err) => Self::UNIX_EPOCH - err.duration(),
|
|
+ }
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "std")]
|
|
impl From<OffsetDateTime> for SystemTime {
|
|
fn from(datetime: OffsetDateTime) -> Self {
|
|
- datetime.0.into()
|
|
+ let duration = datetime - OffsetDateTime::UNIX_EPOCH;
|
|
+
|
|
+ if duration.is_zero() {
|
|
+ Self::UNIX_EPOCH
|
|
+ } else if duration.is_positive() {
|
|
+ Self::UNIX_EPOCH + duration.unsigned_abs()
|
|
+ } else {
|
|
+ debug_assert!(duration.is_negative());
|
|
+ Self::UNIX_EPOCH - duration.unsigned_abs()
|
|
+ }
|
|
}
|
|
}
|
|
|
|
@@ -1196,8 +1590,14 @@ impl From<OffsetDateTime> for SystemTime {
|
|
feature = "wasm-bindgen"
|
|
))]
|
|
impl From<js_sys::Date> for OffsetDateTime {
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if the timestamp can not be represented.
|
|
fn from(js_date: js_sys::Date) -> Self {
|
|
- Self(Inner::from(js_date))
|
|
+ // get_time() returns milliseconds
|
|
+ let timestamp_nanos = (js_date.get_time() * Nanosecond::per(Millisecond) as f64) as i128;
|
|
+ Self::from_unix_timestamp_nanos(timestamp_nanos)
|
|
+ .expect("invalid timestamp: Timestamp cannot fit in range")
|
|
}
|
|
}
|
|
|
|
@@ -1208,8 +1608,11 @@ impl From<js_sys::Date> for OffsetDateTime {
|
|
))]
|
|
impl From<OffsetDateTime> for js_sys::Date {
|
|
fn from(datetime: OffsetDateTime) -> Self {
|
|
- datetime.0.into()
|
|
+ // new Date() takes milliseconds
|
|
+ let timestamp = (datetime.unix_timestamp_nanos()
|
|
+ / Nanosecond::per(Millisecond).cast_signed().extend::<i128>())
|
|
+ as f64;
|
|
+ Self::new(×tamp.into())
|
|
}
|
|
}
|
|
-
|
|
// endregion trait impls
|
|
diff --git a/vendor/time/src/parsing/combinator/mod.rs b/vendor/time/src/parsing/combinator/mod.rs
|
|
index 3b4bc7a..e3e1df7 100644
|
|
--- a/vendor/time/src/parsing/combinator/mod.rs
|
|
+++ b/vendor/time/src/parsing/combinator/mod.rs
|
|
@@ -2,6 +2,8 @@
|
|
|
|
pub(crate) mod rfc;
|
|
|
|
+use num_conv::prelude::*;
|
|
+
|
|
use crate::format_description::modifier::Padding;
|
|
use crate::parsing::shim::{Integer, IntegerParseBytes};
|
|
use crate::parsing::ParsedItem;
|
|
@@ -135,7 +137,7 @@ pub(crate) fn n_to_m_digits_padded<'a, const N: u8, const M: u8, T: Integer>(
|
|
None => break,
|
|
}
|
|
}
|
|
- let pad_width = (orig_input.len() - input.len()) as u8;
|
|
+ let pad_width = (orig_input.len() - input.len()).truncate::<u8>();
|
|
|
|
orig_input = input;
|
|
for _ in 0..(N - pad_width) {
|
|
diff --git a/vendor/time/src/parsing/combinator/rfc/iso8601.rs b/vendor/time/src/parsing/combinator/rfc/iso8601.rs
|
|
index 613a905..91eea2d 100644
|
|
--- a/vendor/time/src/parsing/combinator/rfc/iso8601.rs
|
|
+++ b/vendor/time/src/parsing/combinator/rfc/iso8601.rs
|
|
@@ -4,6 +4,8 @@
|
|
|
|
use core::num::{NonZeroU16, NonZeroU8};
|
|
|
|
+use num_conv::prelude::*;
|
|
+
|
|
use crate::parsing::combinator::{any_digit, ascii_char, exactly_n_digits, first_match, sign};
|
|
use crate::parsing::ParsedItem;
|
|
use crate::{Month, Weekday};
|
|
@@ -62,10 +64,10 @@ impl ExtendedKind {
|
|
pub(crate) fn year(input: &[u8]) -> Option<ParsedItem<'_, i32>> {
|
|
Some(match sign(input) {
|
|
Some(ParsedItem(input, sign)) => exactly_n_digits::<6, u32>(input)?.map(|val| {
|
|
- let val = val as i32;
|
|
+ let val = val.cast_signed();
|
|
if sign == b'-' { -val } else { val }
|
|
}),
|
|
- None => exactly_n_digits::<4, u32>(input)?.map(|val| val as _),
|
|
+ None => exactly_n_digits::<4, u32>(input)?.map(|val| val.cast_signed()),
|
|
})
|
|
}
|
|
|
|
diff --git a/vendor/time/src/parsing/component.rs b/vendor/time/src/parsing/component.rs
|
|
index 42d15e9..e2a7e7c 100644
|
|
--- a/vendor/time/src/parsing/component.rs
|
|
+++ b/vendor/time/src/parsing/component.rs
|
|
@@ -2,6 +2,8 @@
|
|
|
|
use core::num::{NonZeroU16, NonZeroU8};
|
|
|
|
+use num_conv::prelude::*;
|
|
+
|
|
use crate::convert::*;
|
|
use crate::format_description::modifier;
|
|
#[cfg(feature = "large-dates")]
|
|
@@ -25,14 +27,14 @@ pub(crate) fn parse_year(input: &[u8], modifiers: modifier::Year) -> Option<Pars
|
|
let ParsedItem(input, year) =
|
|
n_to_m_digits_padded::<4, 6, u32>(modifiers.padding)(input)?;
|
|
match sign {
|
|
- Some(b'-') => Some(ParsedItem(input, -(year as i32))),
|
|
+ Some(b'-') => Some(ParsedItem(input, -year.cast_signed())),
|
|
None if modifiers.sign_is_mandatory || year >= 10_000 => None,
|
|
- _ => Some(ParsedItem(input, year as i32)),
|
|
+ _ => Some(ParsedItem(input, year.cast_signed())),
|
|
}
|
|
}
|
|
- modifier::YearRepr::LastTwo => {
|
|
- Some(exactly_n_digits_padded::<2, u32>(modifiers.padding)(input)?.map(|v| v as i32))
|
|
- }
|
|
+ modifier::YearRepr::LastTwo => Some(
|
|
+ exactly_n_digits_padded::<2, u32>(modifiers.padding)(input)?.map(|v| v.cast_signed()),
|
|
+ ),
|
|
}
|
|
}
|
|
|
|
@@ -243,11 +245,11 @@ pub(crate) fn parse_subsecond(
|
|
Nine => exactly_n_digits::<9, _>(input)?,
|
|
OneOrMore => {
|
|
let ParsedItem(mut input, mut value) =
|
|
- any_digit(input)?.map(|v| (v - b'0') as u32 * 100_000_000);
|
|
+ any_digit(input)?.map(|v| (v - b'0').extend::<u32>() * 100_000_000);
|
|
|
|
let mut multiplier = 10_000_000;
|
|
while let Some(ParsedItem(new_input, digit)) = any_digit(input) {
|
|
- value += (digit - b'0') as u32 * multiplier;
|
|
+ value += (digit - b'0').extend::<u32>() * multiplier;
|
|
input = new_input;
|
|
multiplier /= 10;
|
|
}
|
|
@@ -269,9 +271,9 @@ pub(crate) fn parse_offset_hour(
|
|
let ParsedItem(input, sign) = opt(sign)(input);
|
|
let ParsedItem(input, hour) = exactly_n_digits_padded::<2, u8>(modifiers.padding)(input)?;
|
|
match sign {
|
|
- Some(b'-') => Some(ParsedItem(input, (-(hour as i8), true))),
|
|
+ Some(b'-') => Some(ParsedItem(input, (-hour.cast_signed(), true))),
|
|
None if modifiers.sign_is_mandatory => None,
|
|
- _ => Some(ParsedItem(input, (hour as i8, false))),
|
|
+ _ => Some(ParsedItem(input, (hour.cast_signed(), false))),
|
|
}
|
|
}
|
|
|
|
@@ -282,7 +284,7 @@ pub(crate) fn parse_offset_minute(
|
|
) -> Option<ParsedItem<'_, i8>> {
|
|
Some(
|
|
exactly_n_digits_padded::<2, u8>(modifiers.padding)(input)?
|
|
- .map(|offset_minute| offset_minute as _),
|
|
+ .map(|offset_minute| offset_minute.cast_signed()),
|
|
)
|
|
}
|
|
|
|
@@ -293,7 +295,7 @@ pub(crate) fn parse_offset_second(
|
|
) -> Option<ParsedItem<'_, i8>> {
|
|
Some(
|
|
exactly_n_digits_padded::<2, u8>(modifiers.padding)(input)?
|
|
- .map(|offset_second| offset_second as _),
|
|
+ .map(|offset_second| offset_second.cast_signed()),
|
|
)
|
|
}
|
|
// endregion offset components
|
|
@@ -304,7 +306,7 @@ pub(crate) fn parse_ignore(
|
|
modifiers: modifier::Ignore,
|
|
) -> Option<ParsedItem<'_, ()>> {
|
|
let modifier::Ignore { count } = modifiers;
|
|
- let input = input.get((count.get() as usize)..)?;
|
|
+ let input = input.get((count.get().extend())..)?;
|
|
Some(ParsedItem(input, ()))
|
|
}
|
|
|
|
@@ -315,20 +317,19 @@ pub(crate) fn parse_unix_timestamp(
|
|
) -> Option<ParsedItem<'_, i128>> {
|
|
let ParsedItem(input, sign) = opt(sign)(input);
|
|
let ParsedItem(input, nano_timestamp) = match modifiers.precision {
|
|
- modifier::UnixTimestampPrecision::Second => {
|
|
- n_to_m_digits::<1, 14, u128>(input)?.map(|val| val * Nanosecond::per(Second) as u128)
|
|
- }
|
|
+ modifier::UnixTimestampPrecision::Second => n_to_m_digits::<1, 14, u128>(input)?
|
|
+ .map(|val| val * Nanosecond::per(Second).extend::<u128>()),
|
|
modifier::UnixTimestampPrecision::Millisecond => n_to_m_digits::<1, 17, u128>(input)?
|
|
- .map(|val| val * Nanosecond::per(Millisecond) as u128),
|
|
+ .map(|val| val * Nanosecond::per(Millisecond).extend::<u128>()),
|
|
modifier::UnixTimestampPrecision::Microsecond => n_to_m_digits::<1, 20, u128>(input)?
|
|
- .map(|val| val * Nanosecond::per(Microsecond) as u128),
|
|
+ .map(|val| val * Nanosecond::per(Microsecond).extend::<u128>()),
|
|
modifier::UnixTimestampPrecision::Nanosecond => n_to_m_digits::<1, 23, _>(input)?,
|
|
};
|
|
|
|
match sign {
|
|
- Some(b'-') => Some(ParsedItem(input, -(nano_timestamp as i128))),
|
|
+ Some(b'-') => Some(ParsedItem(input, -nano_timestamp.cast_signed())),
|
|
None if modifiers.sign_is_mandatory => None,
|
|
- _ => Some(ParsedItem(input, nano_timestamp as _)),
|
|
+ _ => Some(ParsedItem(input, nano_timestamp.cast_signed())),
|
|
}
|
|
}
|
|
|
|
diff --git a/vendor/time/src/parsing/iso8601.rs b/vendor/time/src/parsing/iso8601.rs
|
|
index 048fc95..000835b 100644
|
|
--- a/vendor/time/src/parsing/iso8601.rs
|
|
+++ b/vendor/time/src/parsing/iso8601.rs
|
|
@@ -1,5 +1,7 @@
|
|
//! Parse parts of an ISO 8601-formatted value.
|
|
|
|
+use num_conv::prelude::*;
|
|
+
|
|
use crate::convert::*;
|
|
use crate::error;
|
|
use crate::error::ParseFromDescription::{InvalidComponent, InvalidLiteral};
|
|
@@ -19,7 +21,6 @@ impl<const CONFIG: EncodedConfig> Iso8601<CONFIG> {
|
|
// Basic: [year]["W"][week][dayk]
|
|
// Extended: [year]["-"]["W"][week]["-"][dayk]
|
|
/// Parse a date in the basic or extended format. Reduced precision is permitted.
|
|
- #[allow(clippy::needless_pass_by_ref_mut)] // rust-lang/rust-clippy#11620
|
|
pub(crate) fn parse_date<'a>(
|
|
parsed: &'a mut Parsed,
|
|
extended_kind: &'a mut ExtendedKind,
|
|
@@ -35,7 +36,7 @@ impl<const CONFIG: EncodedConfig> Iso8601<CONFIG> {
|
|
None => ExtendedKind::Basic, // no separator before mandatory month/ordinal/week
|
|
};
|
|
|
|
- let mut ret_error = match (|| {
|
|
+ let parsed_month_day = (|| {
|
|
let ParsedItem(mut input, month) = month(input).ok_or(InvalidComponent("month"))?;
|
|
if extended_kind.is_extended() {
|
|
input = ascii_char::<b'-'>(input)
|
|
@@ -44,7 +45,8 @@ impl<const CONFIG: EncodedConfig> Iso8601<CONFIG> {
|
|
}
|
|
let ParsedItem(input, day) = day(input).ok_or(InvalidComponent("day"))?;
|
|
Ok(ParsedItem(input, (month, day)))
|
|
- })() {
|
|
+ })();
|
|
+ let mut ret_error = match parsed_month_day {
|
|
Ok(ParsedItem(input, (month, day))) => {
|
|
*parsed = parsed
|
|
.with_year(year)
|
|
@@ -68,7 +70,7 @@ impl<const CONFIG: EncodedConfig> Iso8601<CONFIG> {
|
|
return Ok(input);
|
|
}
|
|
|
|
- match (|| {
|
|
+ let parsed_week_weekday = (|| {
|
|
let input = ascii_char::<b'W'>(input)
|
|
.ok_or((false, InvalidLiteral))?
|
|
.into_inner();
|
|
@@ -82,7 +84,8 @@ impl<const CONFIG: EncodedConfig> Iso8601<CONFIG> {
|
|
let ParsedItem(input, weekday) =
|
|
dayk(input).ok_or((true, InvalidComponent("weekday")))?;
|
|
Ok(ParsedItem(input, (week, weekday)))
|
|
- })() {
|
|
+ })();
|
|
+ match parsed_week_weekday {
|
|
Ok(ParsedItem(input, (week, weekday))) => {
|
|
*parsed = parsed
|
|
.with_iso_year(year)
|
|
@@ -255,9 +258,9 @@ impl<const CONFIG: EncodedConfig> Iso8601<CONFIG> {
|
|
.and_then(|parsed_item| {
|
|
parsed_item.consume_value(|hour| {
|
|
parsed.set_offset_hour(if sign == b'-' {
|
|
- -(hour as i8)
|
|
+ -hour.cast_signed()
|
|
} else {
|
|
- hour as _
|
|
+ hour.cast_signed()
|
|
})
|
|
})
|
|
})
|
|
@@ -277,9 +280,9 @@ impl<const CONFIG: EncodedConfig> Iso8601<CONFIG> {
|
|
input = new_input;
|
|
parsed
|
|
.set_offset_minute_signed(if sign == b'-' {
|
|
- -(min as i8)
|
|
+ -min.cast_signed()
|
|
} else {
|
|
- min as _
|
|
+ min.cast_signed()
|
|
})
|
|
.ok_or(InvalidComponent("offset minute"))?;
|
|
}
|
|
diff --git a/vendor/time/src/parsing/mod.rs b/vendor/time/src/parsing/mod.rs
|
|
index 4a2aa82..e65cfd5 100644
|
|
--- a/vendor/time/src/parsing/mod.rs
|
|
+++ b/vendor/time/src/parsing/mod.rs
|
|
@@ -31,6 +31,13 @@ impl<'a, T> ParsedItem<'a, T> {
|
|
f(self.1)?;
|
|
Some(self.0)
|
|
}
|
|
+
|
|
+ /// Filter the value with the provided function. If the function returns `false`, the value
|
|
+ /// is discarded and `None` is returned. Otherwise, the value is preserved and `Some(self)` is
|
|
+ /// returned.
|
|
+ pub(crate) fn filter(self, f: impl FnOnce(&T) -> bool) -> Option<ParsedItem<'a, T>> {
|
|
+ f(&self.1).then_some(self)
|
|
+ }
|
|
}
|
|
|
|
impl<'a> ParsedItem<'a, ()> {
|
|
diff --git a/vendor/time/src/parsing/parsable.rs b/vendor/time/src/parsing/parsable.rs
|
|
index 30fda4d..1679f63 100644
|
|
--- a/vendor/time/src/parsing/parsable.rs
|
|
+++ b/vendor/time/src/parsing/parsable.rs
|
|
@@ -2,22 +2,24 @@
|
|
|
|
use core::ops::Deref;
|
|
|
|
-use crate::date_time::{maybe_offset_from_offset, MaybeOffset};
|
|
+use num_conv::prelude::*;
|
|
+
|
|
use crate::error::TryFromParsed;
|
|
use crate::format_description::well_known::iso8601::EncodedConfig;
|
|
use crate::format_description::well_known::{Iso8601, Rfc2822, Rfc3339};
|
|
-use crate::format_description::FormatItem;
|
|
+use crate::format_description::BorrowedFormatItem;
|
|
#[cfg(feature = "alloc")]
|
|
use crate::format_description::OwnedFormatItem;
|
|
use crate::internal_macros::bug;
|
|
use crate::parsing::{Parsed, ParsedItem};
|
|
-use crate::{error, Date, DateTime, Month, Time, UtcOffset, Weekday};
|
|
+use crate::{error, Date, Month, OffsetDateTime, Time, UtcOffset, Weekday};
|
|
|
|
/// A type that can be parsed.
|
|
#[cfg_attr(__time_03_docs, doc(notable_trait))]
|
|
+#[doc(alias = "Parseable")]
|
|
pub trait Parsable: sealed::Sealed {}
|
|
-impl Parsable for FormatItem<'_> {}
|
|
-impl Parsable for [FormatItem<'_>] {}
|
|
+impl Parsable for BorrowedFormatItem<'_> {}
|
|
+impl Parsable for [BorrowedFormatItem<'_>] {}
|
|
#[cfg(feature = "alloc")]
|
|
impl Parsable for OwnedFormatItem {}
|
|
#[cfg(feature = "alloc")]
|
|
@@ -32,6 +34,7 @@ impl<T: Deref> Parsable for T where T::Target: Parsable {}
|
|
mod sealed {
|
|
#[allow(clippy::wildcard_imports)]
|
|
use super::*;
|
|
+ use crate::PrimitiveDateTime;
|
|
|
|
/// Parse the item using a format description and an input.
|
|
pub trait Sealed {
|
|
@@ -74,18 +77,23 @@ mod sealed {
|
|
Ok(self.parse(input)?.try_into()?)
|
|
}
|
|
|
|
- /// Parse a [`DateTime`] from the format description.
|
|
- fn parse_date_time<O: MaybeOffset>(
|
|
+ /// Parse a [`PrimitiveDateTime`] from the format description.
|
|
+ fn parse_primitive_date_time(
|
|
&self,
|
|
input: &[u8],
|
|
- ) -> Result<DateTime<O>, error::Parse> {
|
|
+ ) -> Result<PrimitiveDateTime, error::Parse> {
|
|
+ Ok(self.parse(input)?.try_into()?)
|
|
+ }
|
|
+
|
|
+ /// Parse a [`OffsetDateTime`] from the format description.
|
|
+ fn parse_offset_date_time(&self, input: &[u8]) -> Result<OffsetDateTime, error::Parse> {
|
|
Ok(self.parse(input)?.try_into()?)
|
|
}
|
|
}
|
|
}
|
|
|
|
// region: custom formats
|
|
-impl sealed::Sealed for FormatItem<'_> {
|
|
+impl sealed::Sealed for BorrowedFormatItem<'_> {
|
|
fn parse_into<'a>(
|
|
&self,
|
|
input: &'a [u8],
|
|
@@ -95,7 +103,7 @@ impl sealed::Sealed for FormatItem<'_> {
|
|
}
|
|
}
|
|
|
|
-impl sealed::Sealed for [FormatItem<'_>] {
|
|
+impl sealed::Sealed for [BorrowedFormatItem<'_>] {
|
|
fn parse_into<'a>(
|
|
&self,
|
|
input: &'a [u8],
|
|
@@ -157,8 +165,8 @@ impl sealed::Sealed for Rfc2822 {
|
|
let colon = ascii_char::<b':'>;
|
|
let comma = ascii_char::<b','>;
|
|
|
|
- let input = opt(fws)(input).into_inner();
|
|
- let input = first_match(
|
|
+ let input = opt(cfws)(input).into_inner();
|
|
+ let weekday = first_match(
|
|
[
|
|
(b"Mon".as_slice(), Weekday::Monday),
|
|
(b"Tue".as_slice(), Weekday::Tuesday),
|
|
@@ -169,11 +177,16 @@ impl sealed::Sealed for Rfc2822 {
|
|
(b"Sun".as_slice(), Weekday::Sunday),
|
|
],
|
|
false,
|
|
- )(input)
|
|
- .and_then(|item| item.consume_value(|value| parsed.set_weekday(value)))
|
|
- .ok_or(InvalidComponent("weekday"))?;
|
|
- let input = comma(input).ok_or(InvalidLiteral)?.into_inner();
|
|
- let input = cfws(input).ok_or(InvalidLiteral)?.into_inner();
|
|
+ )(input);
|
|
+ let input = if let Some(item) = weekday {
|
|
+ let input = item
|
|
+ .consume_value(|value| parsed.set_weekday(value))
|
|
+ .ok_or(InvalidComponent("weekday"))?;
|
|
+ let input = comma(input).ok_or(InvalidLiteral)?.into_inner();
|
|
+ opt(cfws)(input).into_inner()
|
|
+ } else {
|
|
+ input
|
|
+ };
|
|
let input = n_to_m_digits::<1, 2, _>(input)
|
|
.and_then(|item| item.consume_value(|value| parsed.set_day(value)))
|
|
.ok_or(InvalidComponent("day"))?;
|
|
@@ -202,7 +215,9 @@ impl sealed::Sealed for Rfc2822 {
|
|
Some(item) => {
|
|
let input = item
|
|
.flat_map(|year| if year >= 1900 { Some(year) } else { None })
|
|
- .and_then(|item| item.consume_value(|value| parsed.set_year(value as _)))
|
|
+ .and_then(|item| {
|
|
+ item.consume_value(|value| parsed.set_year(value.cast_signed()))
|
|
+ })
|
|
.ok_or(InvalidComponent("year"))?;
|
|
fws(input).ok_or(InvalidLiteral)?.into_inner()
|
|
}
|
|
@@ -210,7 +225,7 @@ impl sealed::Sealed for Rfc2822 {
|
|
let input = exactly_n_digits::<2, u32>(input)
|
|
.and_then(|item| {
|
|
item.map(|year| if year < 50 { year + 2000 } else { year + 1900 })
|
|
- .map(|year| year as _)
|
|
+ .map(|year| year.cast_signed())
|
|
.consume_value(|value| parsed.set_year(value))
|
|
})
|
|
.ok_or(InvalidComponent("year"))?;
|
|
@@ -283,9 +298,9 @@ impl sealed::Sealed for Rfc2822 {
|
|
.and_then(|item| {
|
|
item.map(|offset_hour| {
|
|
if offset_sign == b'-' {
|
|
- -(offset_hour as i8)
|
|
+ -offset_hour.cast_signed()
|
|
} else {
|
|
- offset_hour as _
|
|
+ offset_hour.cast_signed()
|
|
}
|
|
})
|
|
.consume_value(|value| parsed.set_offset_hour(value))
|
|
@@ -293,14 +308,16 @@ impl sealed::Sealed for Rfc2822 {
|
|
.ok_or(InvalidComponent("offset hour"))?;
|
|
let input = exactly_n_digits::<2, u8>(input)
|
|
.and_then(|item| {
|
|
- item.consume_value(|value| parsed.set_offset_minute_signed(value as _))
|
|
+ item.consume_value(|value| parsed.set_offset_minute_signed(value.cast_signed()))
|
|
})
|
|
.ok_or(InvalidComponent("offset minute"))?;
|
|
|
|
+ let input = opt(cfws)(input).into_inner();
|
|
+
|
|
Ok(input)
|
|
}
|
|
|
|
- fn parse_date_time<O: MaybeOffset>(&self, input: &[u8]) -> Result<DateTime<O>, error::Parse> {
|
|
+ fn parse_offset_date_time(&self, input: &[u8]) -> Result<OffsetDateTime, error::Parse> {
|
|
use crate::error::ParseFromDescription::{InvalidComponent, InvalidLiteral};
|
|
use crate::parsing::combinator::rfc::rfc2822::{cfws, fws};
|
|
use crate::parsing::combinator::{
|
|
@@ -310,10 +327,10 @@ impl sealed::Sealed for Rfc2822 {
|
|
let colon = ascii_char::<b':'>;
|
|
let comma = ascii_char::<b','>;
|
|
|
|
- let input = opt(fws)(input).into_inner();
|
|
+ let input = opt(cfws)(input).into_inner();
|
|
// This parses the weekday, but we don't actually use the value anywhere. Because of this,
|
|
// just return `()` to avoid unnecessary generated code.
|
|
- let ParsedItem(input, ()) = first_match(
|
|
+ let weekday = first_match(
|
|
[
|
|
(b"Mon".as_slice(), ()),
|
|
(b"Tue".as_slice(), ()),
|
|
@@ -324,10 +341,14 @@ impl sealed::Sealed for Rfc2822 {
|
|
(b"Sun".as_slice(), ()),
|
|
],
|
|
false,
|
|
- )(input)
|
|
- .ok_or(InvalidComponent("weekday"))?;
|
|
- let input = comma(input).ok_or(InvalidLiteral)?.into_inner();
|
|
- let input = cfws(input).ok_or(InvalidLiteral)?.into_inner();
|
|
+ )(input);
|
|
+ let input = if let Some(item) = weekday {
|
|
+ let input = item.into_inner();
|
|
+ let input = comma(input).ok_or(InvalidLiteral)?.into_inner();
|
|
+ opt(cfws)(input).into_inner()
|
|
+ } else {
|
|
+ input
|
|
+ };
|
|
let ParsedItem(input, day) =
|
|
n_to_m_digits::<1, 2, _>(input).ok_or(InvalidComponent("day"))?;
|
|
let input = cfws(input).ok_or(InvalidLiteral)?.into_inner();
|
|
@@ -420,18 +441,20 @@ impl sealed::Sealed for Rfc2822 {
|
|
.map(|item| {
|
|
item.map(|offset_hour| {
|
|
if offset_sign == b'-' {
|
|
- -(offset_hour as i8)
|
|
+ -offset_hour.cast_signed()
|
|
} else {
|
|
- offset_hour as _
|
|
+ offset_hour.cast_signed()
|
|
}
|
|
})
|
|
})
|
|
.ok_or(InvalidComponent("offset hour"))?;
|
|
let ParsedItem(input, offset_minute) =
|
|
exactly_n_digits::<2, u8>(input).ok_or(InvalidComponent("offset minute"))?;
|
|
- (input, offset_hour, offset_minute as i8)
|
|
+ (input, offset_hour, offset_minute.cast_signed())
|
|
};
|
|
|
|
+ let input = opt(cfws)(input).into_inner();
|
|
+
|
|
if !input.is_empty() {
|
|
return Err(error::Parse::ParseFromDescription(
|
|
error::ParseFromDescription::UnexpectedTrailingCharacters,
|
|
@@ -439,9 +462,7 @@ impl sealed::Sealed for Rfc2822 {
|
|
}
|
|
|
|
let mut nanosecond = 0;
|
|
- let leap_second_input = if !O::HAS_LOGICAL_OFFSET {
|
|
- false
|
|
- } else if second == 60 {
|
|
+ let leap_second_input = if second == 60 {
|
|
second = 59;
|
|
nanosecond = 999_999_999;
|
|
true
|
|
@@ -450,14 +471,10 @@ impl sealed::Sealed for Rfc2822 {
|
|
};
|
|
|
|
let dt = (|| {
|
|
- let date = Date::from_calendar_date(year as _, month, day)?;
|
|
+ let date = Date::from_calendar_date(year.cast_signed(), month, day)?;
|
|
let time = Time::from_hms_nano(hour, minute, second, nanosecond)?;
|
|
let offset = UtcOffset::from_hms(offset_hour, offset_minute, 0)?;
|
|
- Ok(DateTime {
|
|
- date,
|
|
- time,
|
|
- offset: maybe_offset_from_offset::<O>(offset),
|
|
- })
|
|
+ Ok(OffsetDateTime::new_in_offset(date, time, offset))
|
|
})()
|
|
.map_err(TryFromParsed::ComponentRange)?;
|
|
|
|
@@ -492,7 +509,7 @@ impl sealed::Sealed for Rfc3339 {
|
|
let colon = ascii_char::<b':'>;
|
|
|
|
let input = exactly_n_digits::<4, u32>(input)
|
|
- .and_then(|item| item.consume_value(|value| parsed.set_year(value as _)))
|
|
+ .and_then(|item| item.consume_value(|value| parsed.set_year(value.cast_signed())))
|
|
.ok_or(InvalidComponent("year"))?;
|
|
let input = dash(input).ok_or(InvalidLiteral)?.into_inner();
|
|
let input = exactly_n_digits::<2, _>(input)
|
|
@@ -520,11 +537,11 @@ impl sealed::Sealed for Rfc3339 {
|
|
let input = if let Some(ParsedItem(input, ())) = ascii_char::<b'.'>(input) {
|
|
let ParsedItem(mut input, mut value) = any_digit(input)
|
|
.ok_or(InvalidComponent("subsecond"))?
|
|
- .map(|v| (v - b'0') as u32 * 100_000_000);
|
|
+ .map(|v| (v - b'0').extend::<u32>() * 100_000_000);
|
|
|
|
let mut multiplier = 10_000_000;
|
|
while let Some(ParsedItem(new_input, digit)) = any_digit(input) {
|
|
- value += (digit - b'0') as u32 * multiplier;
|
|
+ value += (digit - b'0').extend::<u32>() * multiplier;
|
|
input = new_input;
|
|
multiplier /= 10;
|
|
}
|
|
@@ -556,14 +573,15 @@ impl sealed::Sealed for Rfc3339 {
|
|
let ParsedItem(input, offset_sign) = sign(input).ok_or(InvalidComponent("offset hour"))?;
|
|
let input = exactly_n_digits::<2, u8>(input)
|
|
.and_then(|item| {
|
|
- item.map(|offset_hour| {
|
|
- if offset_sign == b'-' {
|
|
- -(offset_hour as i8)
|
|
- } else {
|
|
- offset_hour as _
|
|
- }
|
|
- })
|
|
- .consume_value(|value| parsed.set_offset_hour(value))
|
|
+ item.filter(|&offset_hour| offset_hour <= 23)?
|
|
+ .map(|offset_hour| {
|
|
+ if offset_sign == b'-' {
|
|
+ -offset_hour.cast_signed()
|
|
+ } else {
|
|
+ offset_hour.cast_signed()
|
|
+ }
|
|
+ })
|
|
+ .consume_value(|value| parsed.set_offset_hour(value))
|
|
})
|
|
.ok_or(InvalidComponent("offset hour"))?;
|
|
let input = colon(input).ok_or(InvalidLiteral)?.into_inner();
|
|
@@ -571,9 +589,9 @@ impl sealed::Sealed for Rfc3339 {
|
|
.and_then(|item| {
|
|
item.map(|offset_minute| {
|
|
if offset_sign == b'-' {
|
|
- -(offset_minute as i8)
|
|
+ -offset_minute.cast_signed()
|
|
} else {
|
|
- offset_minute as _
|
|
+ offset_minute.cast_signed()
|
|
}
|
|
})
|
|
.consume_value(|value| parsed.set_offset_minute_signed(value))
|
|
@@ -583,7 +601,7 @@ impl sealed::Sealed for Rfc3339 {
|
|
Ok(input)
|
|
}
|
|
|
|
- fn parse_date_time<O: MaybeOffset>(&self, input: &[u8]) -> Result<DateTime<O>, error::Parse> {
|
|
+ fn parse_offset_date_time(&self, input: &[u8]) -> Result<OffsetDateTime, error::Parse> {
|
|
use crate::error::ParseFromDescription::{InvalidComponent, InvalidLiteral};
|
|
use crate::parsing::combinator::{
|
|
any_digit, ascii_char, ascii_char_ignore_case, exactly_n_digits, sign,
|
|
@@ -615,11 +633,11 @@ impl sealed::Sealed for Rfc3339 {
|
|
if let Some(ParsedItem(input, ())) = ascii_char::<b'.'>(input) {
|
|
let ParsedItem(mut input, mut value) = any_digit(input)
|
|
.ok_or(InvalidComponent("subsecond"))?
|
|
- .map(|v| (v - b'0') as u32 * 100_000_000);
|
|
+ .map(|v| (v - b'0').extend::<u32>() * 100_000_000);
|
|
|
|
let mut multiplier = 10_000_000;
|
|
while let Some(ParsedItem(new_input, digit)) = any_digit(input) {
|
|
- value += (digit - b'0') as u32 * multiplier;
|
|
+ value += (digit - b'0').extend::<u32>() * multiplier;
|
|
input = new_input;
|
|
multiplier /= 10;
|
|
}
|
|
@@ -634,21 +652,22 @@ impl sealed::Sealed for Rfc3339 {
|
|
} else {
|
|
let ParsedItem(input, offset_sign) =
|
|
sign(input).ok_or(InvalidComponent("offset hour"))?;
|
|
- let ParsedItem(input, offset_hour) =
|
|
- exactly_n_digits::<2, u8>(input).ok_or(InvalidComponent("offset hour"))?;
|
|
+ let ParsedItem(input, offset_hour) = exactly_n_digits::<2, u8>(input)
|
|
+ .and_then(|parsed| parsed.filter(|&offset_hour| offset_hour <= 23))
|
|
+ .ok_or(InvalidComponent("offset hour"))?;
|
|
let input = colon(input).ok_or(InvalidLiteral)?.into_inner();
|
|
let ParsedItem(input, offset_minute) =
|
|
exactly_n_digits::<2, u8>(input).ok_or(InvalidComponent("offset minute"))?;
|
|
UtcOffset::from_hms(
|
|
if offset_sign == b'-' {
|
|
- -(offset_hour as i8)
|
|
+ -offset_hour.cast_signed()
|
|
} else {
|
|
- offset_hour as _
|
|
+ offset_hour.cast_signed()
|
|
},
|
|
if offset_sign == b'-' {
|
|
- -(offset_minute as i8)
|
|
+ -offset_minute.cast_signed()
|
|
} else {
|
|
- offset_minute as _
|
|
+ offset_minute.cast_signed()
|
|
},
|
|
0,
|
|
)
|
|
@@ -684,12 +703,11 @@ impl sealed::Sealed for Rfc3339 {
|
|
};
|
|
|
|
let date = Month::from_number(month)
|
|
- .and_then(|month| Date::from_calendar_date(year as _, month, day))
|
|
+ .and_then(|month| Date::from_calendar_date(year.cast_signed(), month, day))
|
|
.map_err(TryFromParsed::ComponentRange)?;
|
|
let time = Time::from_hms_nano(hour, minute, second, nanosecond)
|
|
.map_err(TryFromParsed::ComponentRange)?;
|
|
- let offset = maybe_offset_from_offset::<O>(offset);
|
|
- let dt = DateTime { date, time, offset };
|
|
+ let dt = OffsetDateTime::new_in_offset(date, time, offset);
|
|
|
|
if leap_second_input && !dt.is_valid_leap_second_stand_in() {
|
|
return Err(error::Parse::TryFromParsed(TryFromParsed::ComponentRange(
|
|
@@ -721,6 +739,8 @@ impl<const CONFIG: EncodedConfig> sealed::Sealed for Iso8601<CONFIG> {
|
|
let mut offset_is_present = false;
|
|
let mut first_error = None;
|
|
|
|
+ parsed.leap_second_allowed = true;
|
|
+
|
|
match Self::parse_date(parsed, &mut extended_kind)(input) {
|
|
Ok(new_input) => {
|
|
input = new_input;
|
|
diff --git a/vendor/time/src/parsing/parsed.rs b/vendor/time/src/parsing/parsed.rs
|
|
index f31087f..3c6c4f5 100644
|
|
--- a/vendor/time/src/parsing/parsed.rs
|
|
+++ b/vendor/time/src/parsing/parsed.rs
|
|
@@ -6,15 +6,15 @@ use deranged::{
|
|
OptionRangedI128, OptionRangedI32, OptionRangedI8, OptionRangedU16, OptionRangedU32,
|
|
OptionRangedU8, RangedI128, RangedI32, RangedI8, RangedU16, RangedU32, RangedU8,
|
|
};
|
|
+use num_conv::prelude::*;
|
|
|
|
use crate::convert::{Day, Hour, Minute, Nanosecond, Second};
|
|
use crate::date::{MAX_YEAR, MIN_YEAR};
|
|
-use crate::date_time::{maybe_offset_from_offset, offset_kind, DateTime, MaybeOffset};
|
|
use crate::error::TryFromParsed::InsufficientInformation;
|
|
#[cfg(feature = "alloc")]
|
|
use crate::format_description::OwnedFormatItem;
|
|
-use crate::format_description::{modifier, Component, FormatItem};
|
|
-use crate::internal_macros::const_try_opt;
|
|
+use crate::format_description::{modifier, BorrowedFormatItem, Component};
|
|
+use crate::internal_macros::{bug, const_try_opt};
|
|
use crate::parsing::component::{
|
|
parse_day, parse_end, parse_hour, parse_ignore, parse_minute, parse_month, parse_offset_hour,
|
|
parse_offset_minute, parse_offset_second, parse_ordinal, parse_period, parse_second,
|
|
@@ -38,7 +38,7 @@ mod sealed {
|
|
}
|
|
}
|
|
|
|
-impl sealed::AnyFormatItem for FormatItem<'_> {
|
|
+impl sealed::AnyFormatItem for BorrowedFormatItem<'_> {
|
|
fn parse_item<'a>(
|
|
&self,
|
|
parsed: &mut Parsed,
|
|
@@ -159,13 +159,13 @@ pub struct Parsed {
|
|
offset_second:
|
|
OptionRangedI8<{ -((Second::per(Minute) - 1) as i8) }, { (Second::per(Minute) - 1) as _ }>,
|
|
/// The Unix timestamp in nanoseconds.
|
|
- // unix_timestamp_nanos: MaybeUninit<i128>,
|
|
unix_timestamp_nanos: OptionRangedI128<
|
|
- { Date::MIN.midnight().assume_utc().unix_timestamp_nanos() },
|
|
{
|
|
- Date::MAX
|
|
- .with_time(Time::MAX)
|
|
- .assume_utc()
|
|
+ OffsetDateTime::new_in_offset(Date::MIN, Time::MIDNIGHT, UtcOffset::UTC)
|
|
+ .unix_timestamp_nanos()
|
|
+ },
|
|
+ {
|
|
+ OffsetDateTime::new_in_offset(Date::MAX, Time::MAX, UtcOffset::UTC)
|
|
.unix_timestamp_nanos()
|
|
},
|
|
>,
|
|
@@ -177,6 +177,12 @@ pub struct Parsed {
|
|
pub(super) leap_second_allowed: bool,
|
|
}
|
|
|
|
+impl Default for Parsed {
|
|
+ fn default() -> Self {
|
|
+ Self::new()
|
|
+ }
|
|
+}
|
|
+
|
|
impl Parsed {
|
|
/// Create a new instance of `Parsed` with no information known.
|
|
pub const fn new() -> Self {
|
|
@@ -207,11 +213,11 @@ impl Parsed {
|
|
}
|
|
}
|
|
|
|
- /// Parse a single [`FormatItem`] or [`OwnedFormatItem`], mutating the struct. The remaining
|
|
- /// input is returned as the `Ok` value.
|
|
+ /// Parse a single [`BorrowedFormatItem`] or [`OwnedFormatItem`], mutating the struct. The
|
|
+ /// remaining input is returned as the `Ok` value.
|
|
///
|
|
- /// If a [`FormatItem::Optional`] or [`OwnedFormatItem::Optional`] is passed, parsing will not
|
|
- /// fail; the input will be returned as-is if the expected format is not present.
|
|
+ /// If a [`BorrowedFormatItem::Optional`] or [`OwnedFormatItem::Optional`] is passed, parsing
|
|
+ /// will not fail; the input will be returned as-is if the expected format is not present.
|
|
pub fn parse_item<'a>(
|
|
&mut self,
|
|
input: &'a [u8],
|
|
@@ -220,11 +226,11 @@ impl Parsed {
|
|
item.parse_item(self, input)
|
|
}
|
|
|
|
- /// Parse a sequence of [`FormatItem`]s or [`OwnedFormatItem`]s, mutating the struct. The
|
|
- /// remaining input is returned as the `Ok` value.
|
|
+ /// Parse a sequence of [`BorrowedFormatItem`]s or [`OwnedFormatItem`]s, mutating the struct.
|
|
+ /// The remaining input is returned as the `Ok` value.
|
|
///
|
|
- /// This method will fail if any of the contained [`FormatItem`]s or [`OwnedFormatItem`]s fail
|
|
- /// to parse. `self` will not be mutated in this instance.
|
|
+ /// This method will fail if any of the contained [`BorrowedFormatItem`]s or
|
|
+ /// [`OwnedFormatItem`]s fail to parse. `self` will not be mutated in this instance.
|
|
pub fn parse_items<'a>(
|
|
&mut self,
|
|
mut input: &'a [u8],
|
|
@@ -290,9 +296,13 @@ impl Parsed {
|
|
parse_year(input, modifiers).ok_or(InvalidComponent("year"))?;
|
|
match (modifiers.iso_week_based, modifiers.repr) {
|
|
(false, modifier::YearRepr::Full) => self.set_year(value),
|
|
- (false, modifier::YearRepr::LastTwo) => self.set_year_last_two(value as _),
|
|
+ (false, modifier::YearRepr::LastTwo) => {
|
|
+ self.set_year_last_two(value.cast_unsigned().truncate())
|
|
+ }
|
|
(true, modifier::YearRepr::Full) => self.set_iso_year(value),
|
|
- (true, modifier::YearRepr::LastTwo) => self.set_iso_year_last_two(value as _),
|
|
+ (true, modifier::YearRepr::LastTwo) => {
|
|
+ self.set_iso_year_last_two(value.cast_unsigned().truncate())
|
|
+ }
|
|
}
|
|
.ok_or(InvalidComponent("year"))?;
|
|
Ok(remaining)
|
|
@@ -533,10 +543,10 @@ impl Parsed {
|
|
note = "use `parsed.set_offset_minute_signed()` instead"
|
|
)]
|
|
pub fn set_offset_minute(&mut self, value: u8) -> Option<()> {
|
|
- if value > i8::MAX as u8 {
|
|
+ if value > i8::MAX.cast_unsigned() {
|
|
None
|
|
} else {
|
|
- self.set_offset_minute_signed(value as _)
|
|
+ self.set_offset_minute_signed(value.cast_signed())
|
|
}
|
|
}
|
|
|
|
@@ -547,10 +557,10 @@ impl Parsed {
|
|
note = "use `parsed.set_offset_second_signed()` instead"
|
|
)]
|
|
pub fn set_offset_second(&mut self, value: u8) -> Option<()> {
|
|
- if value > i8::MAX as u8 {
|
|
+ if value > i8::MAX.cast_unsigned() {
|
|
None
|
|
} else {
|
|
- self.set_offset_second_signed(value as _)
|
|
+ self.set_offset_second_signed(value.cast_signed())
|
|
}
|
|
}
|
|
}
|
|
@@ -761,15 +771,17 @@ impl TryFrom<Parsed> for Date {
|
|
)?),
|
|
(year, sunday_week_number, weekday) => Ok(Self::from_ordinal_date(
|
|
year,
|
|
- (sunday_week_number as i16 * 7 + weekday.number_days_from_sunday() as i16
|
|
+ (sunday_week_number.cast_signed().extend::<i16>() * 7
|
|
+ + weekday.number_days_from_sunday().cast_signed().extend::<i16>()
|
|
- adjustment(year)
|
|
- + 1) as u16,
|
|
+ + 1).cast_unsigned(),
|
|
)?),
|
|
(year, monday_week_number, weekday) => Ok(Self::from_ordinal_date(
|
|
year,
|
|
- (monday_week_number as i16 * 7 + weekday.number_days_from_monday() as i16
|
|
+ (monday_week_number.cast_signed().extend::<i16>() * 7
|
|
+ + weekday.number_days_from_monday().cast_signed().extend::<i16>()
|
|
- adjustment(year)
|
|
- + 1) as u16,
|
|
+ + 1).cast_unsigned(),
|
|
)?),
|
|
_ => Err(InsufficientInformation),
|
|
}
|
|
@@ -835,61 +847,45 @@ impl TryFrom<Parsed> for UtcOffset {
|
|
}
|
|
|
|
impl TryFrom<Parsed> for PrimitiveDateTime {
|
|
- type Error = <DateTime<offset_kind::None> as TryFrom<Parsed>>::Error;
|
|
+ type Error = error::TryFromParsed;
|
|
|
|
fn try_from(parsed: Parsed) -> Result<Self, Self::Error> {
|
|
- parsed.try_into().map(Self)
|
|
+ Ok(Self::new(parsed.try_into()?, parsed.try_into()?))
|
|
}
|
|
}
|
|
|
|
impl TryFrom<Parsed> for OffsetDateTime {
|
|
- type Error = <DateTime<offset_kind::Fixed> as TryFrom<Parsed>>::Error;
|
|
-
|
|
- fn try_from(parsed: Parsed) -> Result<Self, Self::Error> {
|
|
- parsed.try_into().map(Self)
|
|
- }
|
|
-}
|
|
-
|
|
-impl<O: MaybeOffset> TryFrom<Parsed> for DateTime<O> {
|
|
type Error = error::TryFromParsed;
|
|
|
|
- #[allow(clippy::unwrap_in_result)] // We know the values are valid.
|
|
fn try_from(mut parsed: Parsed) -> Result<Self, Self::Error> {
|
|
- if O::HAS_LOGICAL_OFFSET {
|
|
- if let Some(timestamp) = parsed.unix_timestamp_nanos() {
|
|
- let DateTime { date, time, offset } =
|
|
- DateTime::<offset_kind::Fixed>::from_unix_timestamp_nanos(timestamp)?;
|
|
-
|
|
- let mut value = Self {
|
|
- date,
|
|
- time,
|
|
- offset: maybe_offset_from_offset::<O>(offset),
|
|
- };
|
|
- if let Some(subsecond) = parsed.subsecond() {
|
|
- value = value.replace_nanosecond(subsecond)?;
|
|
- }
|
|
- return Ok(value);
|
|
+ if let Some(timestamp) = parsed.unix_timestamp_nanos() {
|
|
+ let mut value = Self::from_unix_timestamp_nanos(timestamp)?;
|
|
+ if let Some(subsecond) = parsed.subsecond() {
|
|
+ value = value.replace_nanosecond(subsecond)?;
|
|
}
|
|
+ return Ok(value);
|
|
}
|
|
|
|
// Some well-known formats explicitly allow leap seconds. We don't currently support them,
|
|
// so treat it as the nearest preceding moment that can be represented. Because leap seconds
|
|
// always fall at the end of a month UTC, reject any that are at other times.
|
|
let leap_second_input = if parsed.leap_second_allowed && parsed.second() == Some(60) {
|
|
- parsed.set_second(59).expect("59 is a valid second");
|
|
- parsed
|
|
- .set_subsecond(999_999_999)
|
|
- .expect("999_999_999 is a valid subsecond");
|
|
+ if parsed.set_second(59).is_none() {
|
|
+ bug!("59 is a valid second");
|
|
+ }
|
|
+ if parsed.set_subsecond(999_999_999).is_none() {
|
|
+ bug!("999_999_999 is a valid subsecond");
|
|
+ }
|
|
true
|
|
} else {
|
|
false
|
|
};
|
|
|
|
- let dt = Self {
|
|
- date: Date::try_from(parsed)?,
|
|
- time: Time::try_from(parsed)?,
|
|
- offset: O::try_from_parsed(parsed)?,
|
|
- };
|
|
+ let dt = Self::new_in_offset(
|
|
+ Date::try_from(parsed)?,
|
|
+ Time::try_from(parsed)?,
|
|
+ UtcOffset::try_from(parsed)?,
|
|
+ );
|
|
|
|
if leap_second_input && !dt.is_valid_leap_second_stand_in() {
|
|
return Err(error::TryFromParsed::ComponentRange(
|
|
diff --git a/vendor/time/src/primitive_date_time.rs b/vendor/time/src/primitive_date_time.rs
|
|
index 83a9461..85ae075 100644
|
|
--- a/vendor/time/src/primitive_date_time.rs
|
|
+++ b/vendor/time/src/primitive_date_time.rs
|
|
@@ -1,27 +1,29 @@
|
|
//! The [`PrimitiveDateTime`] struct and its associated `impl`s.
|
|
|
|
+#[cfg(feature = "formatting")]
|
|
+use alloc::string::String;
|
|
use core::fmt;
|
|
use core::ops::{Add, AddAssign, Sub, SubAssign};
|
|
use core::time::Duration as StdDuration;
|
|
#[cfg(feature = "formatting")]
|
|
use std::io;
|
|
|
|
-use powerfmt::smart_display::{FormatterOptions, Metadata, SmartDisplay};
|
|
+use powerfmt::ext::FormatterExt as _;
|
|
+use powerfmt::smart_display::{self, FormatterOptions, Metadata, SmartDisplay};
|
|
|
|
-use crate::date_time::{offset_kind, DateTimeMetadata};
|
|
#[cfg(feature = "formatting")]
|
|
use crate::formatting::Formattable;
|
|
use crate::internal_macros::{const_try, const_try_opt};
|
|
#[cfg(feature = "parsing")]
|
|
use crate::parsing::Parsable;
|
|
-use crate::{error, Date, DateTime, Duration, Month, OffsetDateTime, Time, UtcOffset, Weekday};
|
|
-
|
|
-/// The actual type doing all the work.
|
|
-type Inner = DateTime<offset_kind::None>;
|
|
+use crate::{error, util, Date, Duration, Month, OffsetDateTime, Time, UtcOffset, Weekday};
|
|
|
|
/// Combined date and time.
|
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
|
-pub struct PrimitiveDateTime(#[allow(clippy::missing_docs_in_private_items)] pub(crate) Inner);
|
|
+pub struct PrimitiveDateTime {
|
|
+ date: Date,
|
|
+ time: Time,
|
|
+}
|
|
|
|
impl PrimitiveDateTime {
|
|
/// The smallest value that can be represented by `PrimitiveDateTime`.
|
|
@@ -51,7 +53,10 @@ impl PrimitiveDateTime {
|
|
doc = "assert_eq!(PrimitiveDateTime::MIN, datetime!(-9999-01-01 0:00));"
|
|
)]
|
|
/// ```
|
|
- pub const MIN: Self = Self(Inner::MIN);
|
|
+ pub const MIN: Self = Self {
|
|
+ date: Date::MIN,
|
|
+ time: Time::MIDNIGHT,
|
|
+ };
|
|
|
|
/// The largest value that can be represented by `PrimitiveDateTime`.
|
|
///
|
|
@@ -80,7 +85,10 @@ impl PrimitiveDateTime {
|
|
doc = "assert_eq!(PrimitiveDateTime::MAX, datetime!(+9999-12-31 23:59:59.999_999_999));"
|
|
)]
|
|
/// ```
|
|
- pub const MAX: Self = Self(Inner::MAX);
|
|
+ pub const MAX: Self = Self {
|
|
+ date: Date::MAX,
|
|
+ time: Time::MAX,
|
|
+ };
|
|
|
|
/// Create a new `PrimitiveDateTime` from the provided [`Date`] and [`Time`].
|
|
///
|
|
@@ -93,7 +101,7 @@ impl PrimitiveDateTime {
|
|
/// );
|
|
/// ```
|
|
pub const fn new(date: Date, time: Time) -> Self {
|
|
- Self(Inner::new(date, time))
|
|
+ Self { date, time }
|
|
}
|
|
|
|
// region: component getters
|
|
@@ -104,7 +112,7 @@ impl PrimitiveDateTime {
|
|
/// assert_eq!(datetime!(2019-01-01 0:00).date(), date!(2019-01-01));
|
|
/// ```
|
|
pub const fn date(self) -> Date {
|
|
- self.0.date()
|
|
+ self.date
|
|
}
|
|
|
|
/// Get the [`Time`] component of the `PrimitiveDateTime`.
|
|
@@ -114,7 +122,7 @@ impl PrimitiveDateTime {
|
|
/// assert_eq!(datetime!(2019-01-01 0:00).time(), time!(0:00));
|
|
/// ```
|
|
pub const fn time(self) -> Time {
|
|
- self.0.time()
|
|
+ self.time
|
|
}
|
|
// endregion component getters
|
|
|
|
@@ -128,7 +136,7 @@ impl PrimitiveDateTime {
|
|
/// assert_eq!(datetime!(2020-01-01 0:00).year(), 2020);
|
|
/// ```
|
|
pub const fn year(self) -> i32 {
|
|
- self.0.year()
|
|
+ self.date().year()
|
|
}
|
|
|
|
/// Get the month of the date.
|
|
@@ -140,7 +148,7 @@ impl PrimitiveDateTime {
|
|
/// assert_eq!(datetime!(2019-12-31 0:00).month(), Month::December);
|
|
/// ```
|
|
pub const fn month(self) -> Month {
|
|
- self.0.month()
|
|
+ self.date().month()
|
|
}
|
|
|
|
/// Get the day of the date.
|
|
@@ -153,7 +161,7 @@ impl PrimitiveDateTime {
|
|
/// assert_eq!(datetime!(2019-12-31 0:00).day(), 31);
|
|
/// ```
|
|
pub const fn day(self) -> u8 {
|
|
- self.0.day()
|
|
+ self.date().day()
|
|
}
|
|
|
|
/// Get the day of the year.
|
|
@@ -166,7 +174,7 @@ impl PrimitiveDateTime {
|
|
/// assert_eq!(datetime!(2019-12-31 0:00).ordinal(), 365);
|
|
/// ```
|
|
pub const fn ordinal(self) -> u16 {
|
|
- self.0.ordinal()
|
|
+ self.date().ordinal()
|
|
}
|
|
|
|
/// Get the ISO week number.
|
|
@@ -182,7 +190,7 @@ impl PrimitiveDateTime {
|
|
/// assert_eq!(datetime!(2021-01-01 0:00).iso_week(), 53);
|
|
/// ```
|
|
pub const fn iso_week(self) -> u8 {
|
|
- self.0.iso_week()
|
|
+ self.date().iso_week()
|
|
}
|
|
|
|
/// Get the week number where week 1 begins on the first Sunday.
|
|
@@ -197,7 +205,7 @@ impl PrimitiveDateTime {
|
|
/// assert_eq!(datetime!(2021-01-01 0:00).sunday_based_week(), 0);
|
|
/// ```
|
|
pub const fn sunday_based_week(self) -> u8 {
|
|
- self.0.sunday_based_week()
|
|
+ self.date().sunday_based_week()
|
|
}
|
|
|
|
/// Get the week number where week 1 begins on the first Monday.
|
|
@@ -212,7 +220,7 @@ impl PrimitiveDateTime {
|
|
/// assert_eq!(datetime!(2021-01-01 0:00).monday_based_week(), 0);
|
|
/// ```
|
|
pub const fn monday_based_week(self) -> u8 {
|
|
- self.0.monday_based_week()
|
|
+ self.date().monday_based_week()
|
|
}
|
|
|
|
/// Get the year, month, and day.
|
|
@@ -226,7 +234,7 @@ impl PrimitiveDateTime {
|
|
/// );
|
|
/// ```
|
|
pub const fn to_calendar_date(self) -> (i32, Month, u8) {
|
|
- self.0.to_calendar_date()
|
|
+ self.date().to_calendar_date()
|
|
}
|
|
|
|
/// Get the year and ordinal day number.
|
|
@@ -236,7 +244,7 @@ impl PrimitiveDateTime {
|
|
/// assert_eq!(datetime!(2019-01-01 0:00).to_ordinal_date(), (2019, 1));
|
|
/// ```
|
|
pub const fn to_ordinal_date(self) -> (i32, u16) {
|
|
- self.0.to_ordinal_date()
|
|
+ self.date().to_ordinal_date()
|
|
}
|
|
|
|
/// Get the ISO 8601 year, week number, and weekday.
|
|
@@ -266,7 +274,7 @@ impl PrimitiveDateTime {
|
|
/// );
|
|
/// ```
|
|
pub const fn to_iso_week_date(self) -> (i32, u8, Weekday) {
|
|
- self.0.to_iso_week_date()
|
|
+ self.date().to_iso_week_date()
|
|
}
|
|
|
|
/// Get the weekday.
|
|
@@ -288,7 +296,7 @@ impl PrimitiveDateTime {
|
|
/// assert_eq!(datetime!(2019-12-01 0:00).weekday(), Sunday);
|
|
/// ```
|
|
pub const fn weekday(self) -> Weekday {
|
|
- self.0.weekday()
|
|
+ self.date().weekday()
|
|
}
|
|
|
|
/// Get the Julian day for the date. The time is not taken into account for this calculation.
|
|
@@ -304,7 +312,7 @@ impl PrimitiveDateTime {
|
|
/// assert_eq!(datetime!(2019-12-31 0:00).to_julian_day(), 2_458_849);
|
|
/// ```
|
|
pub const fn to_julian_day(self) -> i32 {
|
|
- self.0.to_julian_day()
|
|
+ self.date().to_julian_day()
|
|
}
|
|
// endregion date getters
|
|
|
|
@@ -317,7 +325,7 @@ impl PrimitiveDateTime {
|
|
/// assert_eq!(datetime!(2020-01-01 23:59:59).as_hms(), (23, 59, 59));
|
|
/// ```
|
|
pub const fn as_hms(self) -> (u8, u8, u8) {
|
|
- self.0.as_hms()
|
|
+ self.time().as_hms()
|
|
}
|
|
|
|
/// Get the clock hour, minute, second, and millisecond.
|
|
@@ -331,7 +339,7 @@ impl PrimitiveDateTime {
|
|
/// );
|
|
/// ```
|
|
pub const fn as_hms_milli(self) -> (u8, u8, u8, u16) {
|
|
- self.0.as_hms_milli()
|
|
+ self.time().as_hms_milli()
|
|
}
|
|
|
|
/// Get the clock hour, minute, second, and microsecond.
|
|
@@ -345,7 +353,7 @@ impl PrimitiveDateTime {
|
|
/// );
|
|
/// ```
|
|
pub const fn as_hms_micro(self) -> (u8, u8, u8, u32) {
|
|
- self.0.as_hms_micro()
|
|
+ self.time().as_hms_micro()
|
|
}
|
|
|
|
/// Get the clock hour, minute, second, and nanosecond.
|
|
@@ -359,7 +367,7 @@ impl PrimitiveDateTime {
|
|
/// );
|
|
/// ```
|
|
pub const fn as_hms_nano(self) -> (u8, u8, u8, u32) {
|
|
- self.0.as_hms_nano()
|
|
+ self.time().as_hms_nano()
|
|
}
|
|
|
|
/// Get the clock hour.
|
|
@@ -372,7 +380,7 @@ impl PrimitiveDateTime {
|
|
/// assert_eq!(datetime!(2019-01-01 23:59:59).hour(), 23);
|
|
/// ```
|
|
pub const fn hour(self) -> u8 {
|
|
- self.0.hour()
|
|
+ self.time().hour()
|
|
}
|
|
|
|
/// Get the minute within the hour.
|
|
@@ -385,7 +393,7 @@ impl PrimitiveDateTime {
|
|
/// assert_eq!(datetime!(2019-01-01 23:59:59).minute(), 59);
|
|
/// ```
|
|
pub const fn minute(self) -> u8 {
|
|
- self.0.minute()
|
|
+ self.time().minute()
|
|
}
|
|
|
|
/// Get the second within the minute.
|
|
@@ -398,7 +406,7 @@ impl PrimitiveDateTime {
|
|
/// assert_eq!(datetime!(2019-01-01 23:59:59).second(), 59);
|
|
/// ```
|
|
pub const fn second(self) -> u8 {
|
|
- self.0.second()
|
|
+ self.time().second()
|
|
}
|
|
|
|
/// Get the milliseconds within the second.
|
|
@@ -411,7 +419,7 @@ impl PrimitiveDateTime {
|
|
/// assert_eq!(datetime!(2019-01-01 23:59:59.999).millisecond(), 999);
|
|
/// ```
|
|
pub const fn millisecond(self) -> u16 {
|
|
- self.0.millisecond()
|
|
+ self.time().millisecond()
|
|
}
|
|
|
|
/// Get the microseconds within the second.
|
|
@@ -427,7 +435,7 @@ impl PrimitiveDateTime {
|
|
/// );
|
|
/// ```
|
|
pub const fn microsecond(self) -> u32 {
|
|
- self.0.microsecond()
|
|
+ self.time().microsecond()
|
|
}
|
|
|
|
/// Get the nanoseconds within the second.
|
|
@@ -443,7 +451,7 @@ impl PrimitiveDateTime {
|
|
/// );
|
|
/// ```
|
|
pub const fn nanosecond(self) -> u32 {
|
|
- self.0.nanosecond()
|
|
+ self.time().nanosecond()
|
|
}
|
|
// endregion time getters
|
|
|
|
@@ -467,7 +475,7 @@ impl PrimitiveDateTime {
|
|
/// );
|
|
/// ```
|
|
pub const fn assume_offset(self, offset: UtcOffset) -> OffsetDateTime {
|
|
- OffsetDateTime(self.0.assume_offset(offset))
|
|
+ OffsetDateTime::new_in_offset(self.date, self.time, offset)
|
|
}
|
|
|
|
/// Assuming that the existing `PrimitiveDateTime` represents a moment in UTC, return an
|
|
@@ -481,7 +489,7 @@ impl PrimitiveDateTime {
|
|
/// );
|
|
/// ```
|
|
pub const fn assume_utc(self) -> OffsetDateTime {
|
|
- OffsetDateTime(self.0.assume_utc())
|
|
+ self.assume_offset(UtcOffset::UTC)
|
|
}
|
|
// endregion attach offset
|
|
|
|
@@ -503,7 +511,17 @@ impl PrimitiveDateTime {
|
|
/// );
|
|
/// ```
|
|
pub const fn checked_add(self, duration: Duration) -> Option<Self> {
|
|
- Some(Self(const_try_opt!(self.0.checked_add(duration))))
|
|
+ let (date_adjustment, time) = self.time.adjusting_add(duration);
|
|
+ let date = const_try_opt!(self.date.checked_add(duration));
|
|
+
|
|
+ Some(Self {
|
|
+ date: match date_adjustment {
|
|
+ util::DateAdjustment::Previous => const_try_opt!(date.previous_day()),
|
|
+ util::DateAdjustment::Next => const_try_opt!(date.next_day()),
|
|
+ util::DateAdjustment::None => date,
|
|
+ },
|
|
+ time,
|
|
+ })
|
|
}
|
|
|
|
/// Computes `self - duration`, returning `None` if an overflow occurred.
|
|
@@ -523,7 +541,17 @@ impl PrimitiveDateTime {
|
|
/// );
|
|
/// ```
|
|
pub const fn checked_sub(self, duration: Duration) -> Option<Self> {
|
|
- Some(Self(const_try_opt!(self.0.checked_sub(duration))))
|
|
+ let (date_adjustment, time) = self.time.adjusting_sub(duration);
|
|
+ let date = const_try_opt!(self.date.checked_sub(duration));
|
|
+
|
|
+ Some(Self {
|
|
+ date: match date_adjustment {
|
|
+ util::DateAdjustment::Previous => const_try_opt!(date.previous_day()),
|
|
+ util::DateAdjustment::Next => const_try_opt!(date.next_day()),
|
|
+ util::DateAdjustment::None => date,
|
|
+ },
|
|
+ time,
|
|
+ })
|
|
}
|
|
// endregion: checked arithmetic
|
|
|
|
@@ -549,7 +577,13 @@ impl PrimitiveDateTime {
|
|
/// );
|
|
/// ```
|
|
pub const fn saturating_add(self, duration: Duration) -> Self {
|
|
- Self(self.0.saturating_add(duration))
|
|
+ if let Some(datetime) = self.checked_add(duration) {
|
|
+ datetime
|
|
+ } else if duration.is_negative() {
|
|
+ Self::MIN
|
|
+ } else {
|
|
+ Self::MAX
|
|
+ }
|
|
}
|
|
|
|
/// Computes `self - duration`, saturating value on overflow.
|
|
@@ -573,7 +607,13 @@ impl PrimitiveDateTime {
|
|
/// );
|
|
/// ```
|
|
pub const fn saturating_sub(self, duration: Duration) -> Self {
|
|
- Self(self.0.saturating_sub(duration))
|
|
+ if let Some(datetime) = self.checked_sub(duration) {
|
|
+ datetime
|
|
+ } else if duration.is_negative() {
|
|
+ Self::MAX
|
|
+ } else {
|
|
+ Self::MIN
|
|
+ }
|
|
}
|
|
// endregion: saturating arithmetic
|
|
}
|
|
@@ -592,7 +632,10 @@ impl PrimitiveDateTime {
|
|
/// ```
|
|
#[must_use = "This method does not mutate the original `PrimitiveDateTime`."]
|
|
pub const fn replace_time(self, time: Time) -> Self {
|
|
- Self(self.0.replace_time(time))
|
|
+ Self {
|
|
+ date: self.date,
|
|
+ time,
|
|
+ }
|
|
}
|
|
|
|
/// Replace the date, preserving the time.
|
|
@@ -606,7 +649,10 @@ impl PrimitiveDateTime {
|
|
/// ```
|
|
#[must_use = "This method does not mutate the original `PrimitiveDateTime`."]
|
|
pub const fn replace_date(self, date: Date) -> Self {
|
|
- Self(self.0.replace_date(date))
|
|
+ Self {
|
|
+ date,
|
|
+ time: self.time,
|
|
+ }
|
|
}
|
|
|
|
/// Replace the year. The month and day will be unchanged.
|
|
@@ -622,7 +668,10 @@ impl PrimitiveDateTime {
|
|
/// ```
|
|
#[must_use = "This method does not mutate the original `PrimitiveDateTime`."]
|
|
pub const fn replace_year(self, year: i32) -> Result<Self, error::ComponentRange> {
|
|
- Ok(Self(const_try!(self.0.replace_year(year))))
|
|
+ Ok(Self {
|
|
+ date: const_try!(self.date.replace_year(year)),
|
|
+ time: self.time,
|
|
+ })
|
|
}
|
|
|
|
/// Replace the month of the year.
|
|
@@ -638,7 +687,10 @@ impl PrimitiveDateTime {
|
|
/// ```
|
|
#[must_use = "This method does not mutate the original `PrimitiveDateTime`."]
|
|
pub const fn replace_month(self, month: Month) -> Result<Self, error::ComponentRange> {
|
|
- Ok(Self(const_try!(self.0.replace_month(month))))
|
|
+ Ok(Self {
|
|
+ date: const_try!(self.date.replace_month(month)),
|
|
+ time: self.time,
|
|
+ })
|
|
}
|
|
|
|
/// Replace the day of the month.
|
|
@@ -654,7 +706,26 @@ impl PrimitiveDateTime {
|
|
/// ```
|
|
#[must_use = "This method does not mutate the original `PrimitiveDateTime`."]
|
|
pub const fn replace_day(self, day: u8) -> Result<Self, error::ComponentRange> {
|
|
- Ok(Self(const_try!(self.0.replace_day(day))))
|
|
+ Ok(Self {
|
|
+ date: const_try!(self.date.replace_day(day)),
|
|
+ time: self.time,
|
|
+ })
|
|
+ }
|
|
+
|
|
+ /// Replace the day of the year.
|
|
+ ///
|
|
+ /// ```rust
|
|
+ /// # use time_macros::datetime;
|
|
+ /// assert_eq!(datetime!(2022-049 12:00).replace_ordinal(1), Ok(datetime!(2022-001 12:00)));
|
|
+ /// assert!(datetime!(2022-049 12:00).replace_ordinal(0).is_err()); // 0 isn't a valid ordinal
|
|
+ /// assert!(datetime!(2022-049 12:00).replace_ordinal(366).is_err()); // 2022 isn't a leap year
|
|
+ /// ````
|
|
+ #[must_use = "This method does not mutate the original `PrimitiveDateTime`."]
|
|
+ pub const fn replace_ordinal(self, ordinal: u16) -> Result<Self, error::ComponentRange> {
|
|
+ Ok(Self {
|
|
+ date: const_try!(self.date.replace_ordinal(ordinal)),
|
|
+ time: self.time,
|
|
+ })
|
|
}
|
|
|
|
/// Replace the clock hour.
|
|
@@ -669,7 +740,10 @@ impl PrimitiveDateTime {
|
|
/// ```
|
|
#[must_use = "This method does not mutate the original `PrimitiveDateTime`."]
|
|
pub const fn replace_hour(self, hour: u8) -> Result<Self, error::ComponentRange> {
|
|
- Ok(Self(const_try!(self.0.replace_hour(hour))))
|
|
+ Ok(Self {
|
|
+ date: self.date,
|
|
+ time: const_try!(self.time.replace_hour(hour)),
|
|
+ })
|
|
}
|
|
|
|
/// Replace the minutes within the hour.
|
|
@@ -684,7 +758,10 @@ impl PrimitiveDateTime {
|
|
/// ```
|
|
#[must_use = "This method does not mutate the original `PrimitiveDateTime`."]
|
|
pub const fn replace_minute(self, minute: u8) -> Result<Self, error::ComponentRange> {
|
|
- Ok(Self(const_try!(self.0.replace_minute(minute))))
|
|
+ Ok(Self {
|
|
+ date: self.date,
|
|
+ time: const_try!(self.time.replace_minute(minute)),
|
|
+ })
|
|
}
|
|
|
|
/// Replace the seconds within the minute.
|
|
@@ -699,7 +776,10 @@ impl PrimitiveDateTime {
|
|
/// ```
|
|
#[must_use = "This method does not mutate the original `PrimitiveDateTime`."]
|
|
pub const fn replace_second(self, second: u8) -> Result<Self, error::ComponentRange> {
|
|
- Ok(Self(const_try!(self.0.replace_second(second))))
|
|
+ Ok(Self {
|
|
+ date: self.date,
|
|
+ time: const_try!(self.time.replace_second(second)),
|
|
+ })
|
|
}
|
|
|
|
/// Replace the milliseconds within the second.
|
|
@@ -717,7 +797,10 @@ impl PrimitiveDateTime {
|
|
self,
|
|
millisecond: u16,
|
|
) -> Result<Self, error::ComponentRange> {
|
|
- Ok(Self(const_try!(self.0.replace_millisecond(millisecond))))
|
|
+ Ok(Self {
|
|
+ date: self.date,
|
|
+ time: const_try!(self.time.replace_millisecond(millisecond)),
|
|
+ })
|
|
}
|
|
|
|
/// Replace the microseconds within the second.
|
|
@@ -735,7 +818,10 @@ impl PrimitiveDateTime {
|
|
self,
|
|
microsecond: u32,
|
|
) -> Result<Self, error::ComponentRange> {
|
|
- Ok(Self(const_try!(self.0.replace_microsecond(microsecond))))
|
|
+ Ok(Self {
|
|
+ date: self.date,
|
|
+ time: const_try!(self.time.replace_microsecond(microsecond)),
|
|
+ })
|
|
}
|
|
|
|
/// Replace the nanoseconds within the second.
|
|
@@ -750,7 +836,10 @@ impl PrimitiveDateTime {
|
|
/// ```
|
|
#[must_use = "This method does not mutate the original `PrimitiveDateTime`."]
|
|
pub const fn replace_nanosecond(self, nanosecond: u32) -> Result<Self, error::ComponentRange> {
|
|
- Ok(Self(const_try!(self.0.replace_nanosecond(nanosecond))))
|
|
+ Ok(Self {
|
|
+ date: self.date,
|
|
+ time: const_try!(self.time.replace_nanosecond(nanosecond)),
|
|
+ })
|
|
}
|
|
}
|
|
// endregion replacement
|
|
@@ -765,7 +854,7 @@ impl PrimitiveDateTime {
|
|
output: &mut impl io::Write,
|
|
format: &(impl Formattable + ?Sized),
|
|
) -> Result<usize, error::Format> {
|
|
- self.0.format_into(output, format)
|
|
+ format.format_into(output, Some(self.date), Some(self.time), None)
|
|
}
|
|
|
|
/// Format the `PrimitiveDateTime` using the provided [format
|
|
@@ -782,7 +871,7 @@ impl PrimitiveDateTime {
|
|
/// # Ok::<_, time::Error>(())
|
|
/// ```
|
|
pub fn format(self, format: &(impl Formattable + ?Sized)) -> Result<String, error::Format> {
|
|
- self.0.format(format)
|
|
+ format.format(Some(self.date), Some(self.time), None)
|
|
}
|
|
}
|
|
|
|
@@ -805,15 +894,16 @@ impl PrimitiveDateTime {
|
|
input: &str,
|
|
description: &(impl Parsable + ?Sized),
|
|
) -> Result<Self, error::Parse> {
|
|
- Inner::parse(input, description).map(Self)
|
|
+ description.parse_primitive_date_time(input.as_bytes())
|
|
}
|
|
}
|
|
|
|
impl SmartDisplay for PrimitiveDateTime {
|
|
- type Metadata = DateTimeMetadata;
|
|
+ type Metadata = ();
|
|
|
|
- fn metadata(&self, f: FormatterOptions) -> Metadata<Self> {
|
|
- self.0.metadata(f).reuse()
|
|
+ fn metadata(&self, _: FormatterOptions) -> Metadata<Self> {
|
|
+ let width = smart_display::padded_width_of!(self.date, " ", self.time);
|
|
+ Metadata::new(width, self, ())
|
|
}
|
|
|
|
fn fmt_with_metadata(
|
|
@@ -821,7 +911,10 @@ impl SmartDisplay for PrimitiveDateTime {
|
|
f: &mut fmt::Formatter<'_>,
|
|
metadata: Metadata<Self>,
|
|
) -> fmt::Result {
|
|
- self.0.fmt_with_metadata(f, metadata.reuse())
|
|
+ f.pad_with_width(
|
|
+ metadata.unpadded_width(),
|
|
+ format_args!("{} {}", self.date, self.time),
|
|
+ )
|
|
}
|
|
}
|
|
|
|
@@ -842,64 +935,115 @@ impl fmt::Debug for PrimitiveDateTime {
|
|
impl Add<Duration> for PrimitiveDateTime {
|
|
type Output = Self;
|
|
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if an overflow occurs.
|
|
fn add(self, duration: Duration) -> Self::Output {
|
|
- Self(self.0.add(duration))
|
|
+ self.checked_add(duration)
|
|
+ .expect("resulting value is out of range")
|
|
}
|
|
}
|
|
|
|
impl Add<StdDuration> for PrimitiveDateTime {
|
|
type Output = Self;
|
|
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if an overflow occurs.
|
|
fn add(self, duration: StdDuration) -> Self::Output {
|
|
- Self(self.0.add(duration))
|
|
+ let (is_next_day, time) = self.time.adjusting_add_std(duration);
|
|
+
|
|
+ Self {
|
|
+ date: if is_next_day {
|
|
+ (self.date + duration)
|
|
+ .next_day()
|
|
+ .expect("resulting value is out of range")
|
|
+ } else {
|
|
+ self.date + duration
|
|
+ },
|
|
+ time,
|
|
+ }
|
|
}
|
|
}
|
|
|
|
impl AddAssign<Duration> for PrimitiveDateTime {
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if an overflow occurs.
|
|
fn add_assign(&mut self, duration: Duration) {
|
|
- self.0.add_assign(duration);
|
|
+ *self = *self + duration;
|
|
}
|
|
}
|
|
|
|
impl AddAssign<StdDuration> for PrimitiveDateTime {
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if an overflow occurs.
|
|
fn add_assign(&mut self, duration: StdDuration) {
|
|
- self.0.add_assign(duration);
|
|
+ *self = *self + duration;
|
|
}
|
|
}
|
|
|
|
impl Sub<Duration> for PrimitiveDateTime {
|
|
type Output = Self;
|
|
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if an overflow occurs.
|
|
fn sub(self, duration: Duration) -> Self::Output {
|
|
- Self(self.0.sub(duration))
|
|
+ self.checked_sub(duration)
|
|
+ .expect("resulting value is out of range")
|
|
}
|
|
}
|
|
|
|
impl Sub<StdDuration> for PrimitiveDateTime {
|
|
type Output = Self;
|
|
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if an overflow occurs.
|
|
fn sub(self, duration: StdDuration) -> Self::Output {
|
|
- Self(self.0.sub(duration))
|
|
+ let (is_previous_day, time) = self.time.adjusting_sub_std(duration);
|
|
+
|
|
+ Self {
|
|
+ date: if is_previous_day {
|
|
+ (self.date - duration)
|
|
+ .previous_day()
|
|
+ .expect("resulting value is out of range")
|
|
+ } else {
|
|
+ self.date - duration
|
|
+ },
|
|
+ time,
|
|
+ }
|
|
}
|
|
}
|
|
|
|
impl SubAssign<Duration> for PrimitiveDateTime {
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if an overflow occurs.
|
|
fn sub_assign(&mut self, duration: Duration) {
|
|
- self.0.sub_assign(duration);
|
|
+ *self = *self - duration;
|
|
}
|
|
}
|
|
|
|
impl SubAssign<StdDuration> for PrimitiveDateTime {
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if an overflow occurs.
|
|
fn sub_assign(&mut self, duration: StdDuration) {
|
|
- self.0.sub_assign(duration);
|
|
+ *self = *self - duration;
|
|
}
|
|
}
|
|
|
|
impl Sub for PrimitiveDateTime {
|
|
type Output = Duration;
|
|
|
|
+ /// # Panics
|
|
+ ///
|
|
+ /// This may panic if an overflow occurs.
|
|
fn sub(self, rhs: Self) -> Self::Output {
|
|
- self.0.sub(rhs.0)
|
|
+ (self.date - rhs.date) + (self.time - rhs.time)
|
|
}
|
|
}
|
|
// endregion trait impls
|
|
diff --git a/vendor/time/src/quickcheck.rs b/vendor/time/src/quickcheck.rs
|
|
index 02cc622..312a09e 100644
|
|
--- a/vendor/time/src/quickcheck.rs
|
|
+++ b/vendor/time/src/quickcheck.rs
|
|
@@ -38,7 +38,6 @@ use alloc::boxed::Box;
|
|
|
|
use quickcheck::{empty_shrinker, single_shrinker, Arbitrary, Gen};
|
|
|
|
-use crate::date_time::{DateTime, MaybeOffset};
|
|
use crate::{Date, Duration, Month, OffsetDateTime, PrimitiveDateTime, Time, UtcOffset, Weekday};
|
|
|
|
/// Obtain an arbitrary value between the minimum and maximum inclusive.
|
|
@@ -116,11 +115,15 @@ impl Arbitrary for Time {
|
|
|
|
impl Arbitrary for PrimitiveDateTime {
|
|
fn arbitrary(g: &mut Gen) -> Self {
|
|
- Self(<_>::arbitrary(g))
|
|
+ Self::new(<_>::arbitrary(g), <_>::arbitrary(g))
|
|
}
|
|
|
|
fn shrink(&self) -> Box<dyn Iterator<Item = Self>> {
|
|
- Box::new(self.0.shrink().map(Self))
|
|
+ Box::new(
|
|
+ (self.date(), self.time())
|
|
+ .shrink()
|
|
+ .map(|(date, time)| Self::new(date, time)),
|
|
+ )
|
|
}
|
|
}
|
|
|
|
@@ -140,28 +143,14 @@ impl Arbitrary for UtcOffset {
|
|
|
|
impl Arbitrary for OffsetDateTime {
|
|
fn arbitrary(g: &mut Gen) -> Self {
|
|
- Self(<_>::arbitrary(g))
|
|
- }
|
|
-
|
|
- fn shrink(&self) -> Box<dyn Iterator<Item = Self>> {
|
|
- Box::new(self.0.shrink().map(Self))
|
|
- }
|
|
-}
|
|
-
|
|
-impl<O: MaybeOffset + 'static> Arbitrary for DateTime<O> {
|
|
- fn arbitrary(g: &mut Gen) -> Self {
|
|
- Self {
|
|
- date: <_>::arbitrary(g),
|
|
- time: <_>::arbitrary(g),
|
|
- offset: <_>::arbitrary(g),
|
|
- }
|
|
+ Self::new_in_offset(<_>::arbitrary(g), <_>::arbitrary(g), <_>::arbitrary(g))
|
|
}
|
|
|
|
fn shrink(&self) -> Box<dyn Iterator<Item = Self>> {
|
|
Box::new(
|
|
- (self.date, self.time, self.offset)
|
|
+ (self.date(), self.time(), self.offset())
|
|
.shrink()
|
|
- .map(|(date, time, offset)| Self { date, time, offset }),
|
|
+ .map(|(date, time, offset)| Self::new_in_offset(date, time, offset)),
|
|
)
|
|
}
|
|
}
|
|
diff --git a/vendor/time/src/serde/mod.rs b/vendor/time/src/serde/mod.rs
|
|
index f94cf04..fadc443 100644
|
|
--- a/vendor/time/src/serde/mod.rs
|
|
+++ b/vendor/time/src/serde/mod.rs
|
|
@@ -22,6 +22,8 @@ pub mod rfc3339;
|
|
pub mod timestamp;
|
|
mod visitor;
|
|
|
|
+#[cfg(feature = "serde-human-readable")]
|
|
+use alloc::string::ToString;
|
|
use core::marker::PhantomData;
|
|
|
|
#[cfg(feature = "serde-human-readable")]
|
|
@@ -117,9 +119,9 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
|
doc = "use ::serde::Deserialize;"
|
|
)]
|
|
/// use time::serde;
|
|
-/// use time::format_description::FormatItem;
|
|
+/// use time::format_description::BorrowedFormatItem;
|
|
///
|
|
-/// const DATE_TIME_FORMAT: &[FormatItem<'_>] = time::macros::format_description!(
|
|
+/// const DATE_TIME_FORMAT: &[BorrowedFormatItem<'_>] = time::macros::format_description!(
|
|
/// "hour=[hour], minute=[minute]"
|
|
/// );
|
|
///
|
|
@@ -206,18 +208,18 @@ pub use time_macros::serde_format_description as format_description;
|
|
|
|
use self::visitor::Visitor;
|
|
#[cfg(feature = "parsing")]
|
|
-use crate::format_description::{modifier, Component, FormatItem};
|
|
+use crate::format_description::{modifier, BorrowedFormatItem, Component};
|
|
use crate::{Date, Duration, Month, OffsetDateTime, PrimitiveDateTime, Time, UtcOffset, Weekday};
|
|
|
|
// region: Date
|
|
/// The format used when serializing and deserializing a human-readable `Date`.
|
|
#[cfg(feature = "parsing")]
|
|
-const DATE_FORMAT: &[FormatItem<'_>] = &[
|
|
- FormatItem::Component(Component::Year(modifier::Year::default())),
|
|
- FormatItem::Literal(b"-"),
|
|
- FormatItem::Component(Component::Month(modifier::Month::default())),
|
|
- FormatItem::Literal(b"-"),
|
|
- FormatItem::Component(Component::Day(modifier::Day::default())),
|
|
+const DATE_FORMAT: &[BorrowedFormatItem<'_>] = &[
|
|
+ BorrowedFormatItem::Component(Component::Year(modifier::Year::default())),
|
|
+ BorrowedFormatItem::Literal(b"-"),
|
|
+ BorrowedFormatItem::Component(Component::Month(modifier::Month::default())),
|
|
+ BorrowedFormatItem::Literal(b"-"),
|
|
+ BorrowedFormatItem::Component(Component::Day(modifier::Day::default())),
|
|
];
|
|
|
|
impl Serialize for Date {
|
|
@@ -275,12 +277,12 @@ impl<'a> Deserialize<'a> for Duration {
|
|
// region: OffsetDateTime
|
|
/// The format used when serializing and deserializing a human-readable `OffsetDateTime`.
|
|
#[cfg(feature = "parsing")]
|
|
-const OFFSET_DATE_TIME_FORMAT: &[FormatItem<'_>] = &[
|
|
- FormatItem::Compound(DATE_FORMAT),
|
|
- FormatItem::Literal(b" "),
|
|
- FormatItem::Compound(TIME_FORMAT),
|
|
- FormatItem::Literal(b" "),
|
|
- FormatItem::Compound(UTC_OFFSET_FORMAT),
|
|
+const OFFSET_DATE_TIME_FORMAT: &[BorrowedFormatItem<'_>] = &[
|
|
+ BorrowedFormatItem::Compound(DATE_FORMAT),
|
|
+ BorrowedFormatItem::Literal(b" "),
|
|
+ BorrowedFormatItem::Compound(TIME_FORMAT),
|
|
+ BorrowedFormatItem::Literal(b" "),
|
|
+ BorrowedFormatItem::Compound(UTC_OFFSET_FORMAT),
|
|
];
|
|
|
|
impl Serialize for OffsetDateTime {
|
|
@@ -322,10 +324,10 @@ impl<'a> Deserialize<'a> for OffsetDateTime {
|
|
// region: PrimitiveDateTime
|
|
/// The format used when serializing and deserializing a human-readable `PrimitiveDateTime`.
|
|
#[cfg(feature = "parsing")]
|
|
-const PRIMITIVE_DATE_TIME_FORMAT: &[FormatItem<'_>] = &[
|
|
- FormatItem::Compound(DATE_FORMAT),
|
|
- FormatItem::Literal(b" "),
|
|
- FormatItem::Compound(TIME_FORMAT),
|
|
+const PRIMITIVE_DATE_TIME_FORMAT: &[BorrowedFormatItem<'_>] = &[
|
|
+ BorrowedFormatItem::Compound(DATE_FORMAT),
|
|
+ BorrowedFormatItem::Literal(b" "),
|
|
+ BorrowedFormatItem::Compound(TIME_FORMAT),
|
|
];
|
|
|
|
impl Serialize for PrimitiveDateTime {
|
|
@@ -364,14 +366,14 @@ impl<'a> Deserialize<'a> for PrimitiveDateTime {
|
|
// region: Time
|
|
/// The format used when serializing and deserializing a human-readable `Time`.
|
|
#[cfg(feature = "parsing")]
|
|
-const TIME_FORMAT: &[FormatItem<'_>] = &[
|
|
- FormatItem::Component(Component::Hour(<modifier::Hour>::default())),
|
|
- FormatItem::Literal(b":"),
|
|
- FormatItem::Component(Component::Minute(<modifier::Minute>::default())),
|
|
- FormatItem::Literal(b":"),
|
|
- FormatItem::Component(Component::Second(<modifier::Second>::default())),
|
|
- FormatItem::Literal(b"."),
|
|
- FormatItem::Component(Component::Subsecond(<modifier::Subsecond>::default())),
|
|
+const TIME_FORMAT: &[BorrowedFormatItem<'_>] = &[
|
|
+ BorrowedFormatItem::Component(Component::Hour(modifier::Hour::default())),
|
|
+ BorrowedFormatItem::Literal(b":"),
|
|
+ BorrowedFormatItem::Component(Component::Minute(modifier::Minute::default())),
|
|
+ BorrowedFormatItem::Literal(b":"),
|
|
+ BorrowedFormatItem::Component(Component::Second(modifier::Second::default())),
|
|
+ BorrowedFormatItem::Literal(b"."),
|
|
+ BorrowedFormatItem::Component(Component::Subsecond(modifier::Subsecond::default())),
|
|
];
|
|
|
|
impl Serialize for Time {
|
|
@@ -402,18 +404,20 @@ impl<'a> Deserialize<'a> for Time {
|
|
// region: UtcOffset
|
|
/// The format used when serializing and deserializing a human-readable `UtcOffset`.
|
|
#[cfg(feature = "parsing")]
|
|
-const UTC_OFFSET_FORMAT: &[FormatItem<'_>] = &[
|
|
- FormatItem::Component(Component::OffsetHour({
|
|
+const UTC_OFFSET_FORMAT: &[BorrowedFormatItem<'_>] = &[
|
|
+ BorrowedFormatItem::Component(Component::OffsetHour({
|
|
let mut m = modifier::OffsetHour::default();
|
|
m.sign_is_mandatory = true;
|
|
m
|
|
})),
|
|
- FormatItem::Optional(&FormatItem::Compound(&[
|
|
- FormatItem::Literal(b":"),
|
|
- FormatItem::Component(Component::OffsetMinute(modifier::OffsetMinute::default())),
|
|
- FormatItem::Optional(&FormatItem::Compound(&[
|
|
- FormatItem::Literal(b":"),
|
|
- FormatItem::Component(Component::OffsetSecond(modifier::OffsetSecond::default())),
|
|
+ BorrowedFormatItem::Optional(&BorrowedFormatItem::Compound(&[
|
|
+ BorrowedFormatItem::Literal(b":"),
|
|
+ BorrowedFormatItem::Component(Component::OffsetMinute(modifier::OffsetMinute::default())),
|
|
+ BorrowedFormatItem::Optional(&BorrowedFormatItem::Compound(&[
|
|
+ BorrowedFormatItem::Literal(b":"),
|
|
+ BorrowedFormatItem::Component(Component::OffsetSecond(
|
|
+ modifier::OffsetSecond::default(),
|
|
+ )),
|
|
])),
|
|
])),
|
|
];
|
|
@@ -483,7 +487,7 @@ impl Serialize for Month {
|
|
return self.to_string().serialize(serializer);
|
|
}
|
|
|
|
- (*self as u8).serialize(serializer)
|
|
+ u8::from(*self).serialize(serializer)
|
|
}
|
|
}
|
|
|
|
diff --git a/vendor/time/src/serde/timestamp/microseconds.rs b/vendor/time/src/serde/timestamp/microseconds.rs
|
|
new file mode 100644
|
|
index 0000000..65c603e
|
|
--- /dev/null
|
|
+++ b/vendor/time/src/serde/timestamp/microseconds.rs
|
|
@@ -0,0 +1,63 @@
|
|
+//! Treat an [`OffsetDateTime`] as a [Unix timestamp] with microseconds for
|
|
+//! the purposes of serde.
|
|
+//!
|
|
+//! Use this module in combination with serde's [`#[with]`][with] attribute.
|
|
+//!
|
|
+//! When deserializing, the offset is assumed to be UTC.
|
|
+//!
|
|
+//! [Unix timestamp]: https://en.wikipedia.org/wiki/Unix_time
|
|
+//! [with]: https://serde.rs/field-attrs.html#with
|
|
+
|
|
+use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
|
|
+
|
|
+use crate::OffsetDateTime;
|
|
+
|
|
+/// Serialize an `OffsetDateTime` as its Unix timestamp with microseconds
|
|
+pub fn serialize<S: Serializer>(
|
|
+ datetime: &OffsetDateTime,
|
|
+ serializer: S,
|
|
+) -> Result<S::Ok, S::Error> {
|
|
+ let timestamp = datetime.unix_timestamp_nanos() / 1_000;
|
|
+ timestamp.serialize(serializer)
|
|
+}
|
|
+
|
|
+/// Deserialize an `OffsetDateTime` from its Unix timestamp with microseconds
|
|
+pub fn deserialize<'a, D: Deserializer<'a>>(deserializer: D) -> Result<OffsetDateTime, D::Error> {
|
|
+ let value: i128 = <_>::deserialize(deserializer)?;
|
|
+ OffsetDateTime::from_unix_timestamp_nanos(value * 1_000)
|
|
+ .map_err(|err| de::Error::invalid_value(de::Unexpected::Signed(err.value), &err))
|
|
+}
|
|
+
|
|
+/// Treat an `Option<OffsetDateTime>` as a [Unix timestamp] with microseconds
|
|
+/// for the purposes of serde.
|
|
+///
|
|
+/// Use this module in combination with serde's [`#[with]`][with] attribute.
|
|
+///
|
|
+/// When deserializing, the offset is assumed to be UTC.
|
|
+///
|
|
+/// [Unix timestamp]: https://en.wikipedia.org/wiki/Unix_time
|
|
+/// [with]: https://serde.rs/field-attrs.html#with
|
|
+pub mod option {
|
|
+ #[allow(clippy::wildcard_imports)]
|
|
+ use super::*;
|
|
+
|
|
+ /// Serialize an `Option<OffsetDateTime>` as its Unix timestamp with microseconds
|
|
+ pub fn serialize<S: Serializer>(
|
|
+ option: &Option<OffsetDateTime>,
|
|
+ serializer: S,
|
|
+ ) -> Result<S::Ok, S::Error> {
|
|
+ option
|
|
+ .map(|timestamp| timestamp.unix_timestamp_nanos() / 1_000)
|
|
+ .serialize(serializer)
|
|
+ }
|
|
+
|
|
+ /// Deserialize an `Option<OffsetDateTime>` from its Unix timestamp with microseconds
|
|
+ pub fn deserialize<'a, D: Deserializer<'a>>(
|
|
+ deserializer: D,
|
|
+ ) -> Result<Option<OffsetDateTime>, D::Error> {
|
|
+ Option::deserialize(deserializer)?
|
|
+ .map(|value: i128| OffsetDateTime::from_unix_timestamp_nanos(value * 1_000))
|
|
+ .transpose()
|
|
+ .map_err(|err| de::Error::invalid_value(de::Unexpected::Signed(err.value), &err))
|
|
+ }
|
|
+}
|
|
diff --git a/vendor/time/src/serde/timestamp/milliseconds.rs b/vendor/time/src/serde/timestamp/milliseconds.rs
|
|
new file mode 100644
|
|
index 0000000..e571b6c
|
|
--- /dev/null
|
|
+++ b/vendor/time/src/serde/timestamp/milliseconds.rs
|
|
@@ -0,0 +1,63 @@
|
|
+//! Treat an [`OffsetDateTime`] as a [Unix timestamp] with milliseconds for
|
|
+//! the purposes of serde.
|
|
+//!
|
|
+//! Use this module in combination with serde's [`#[with]`][with] attribute.
|
|
+//!
|
|
+//! When deserializing, the offset is assumed to be UTC.
|
|
+//!
|
|
+//! [Unix timestamp]: https://en.wikipedia.org/wiki/Unix_time
|
|
+//! [with]: https://serde.rs/field-attrs.html#with
|
|
+
|
|
+use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
|
|
+
|
|
+use crate::OffsetDateTime;
|
|
+
|
|
+/// Serialize an `OffsetDateTime` as its Unix timestamp with milliseconds
|
|
+pub fn serialize<S: Serializer>(
|
|
+ datetime: &OffsetDateTime,
|
|
+ serializer: S,
|
|
+) -> Result<S::Ok, S::Error> {
|
|
+ let timestamp = datetime.unix_timestamp_nanos() / 1_000_000;
|
|
+ timestamp.serialize(serializer)
|
|
+}
|
|
+
|
|
+/// Deserialize an `OffsetDateTime` from its Unix timestamp with milliseconds
|
|
+pub fn deserialize<'a, D: Deserializer<'a>>(deserializer: D) -> Result<OffsetDateTime, D::Error> {
|
|
+ let value: i128 = <_>::deserialize(deserializer)?;
|
|
+ OffsetDateTime::from_unix_timestamp_nanos(value * 1_000_000)
|
|
+ .map_err(|err| de::Error::invalid_value(de::Unexpected::Signed(err.value), &err))
|
|
+}
|
|
+
|
|
+/// Treat an `Option<OffsetDateTime>` as a [Unix timestamp] with milliseconds
|
|
+/// for the purposes of serde.
|
|
+///
|
|
+/// Use this module in combination with serde's [`#[with]`][with] attribute.
|
|
+///
|
|
+/// When deserializing, the offset is assumed to be UTC.
|
|
+///
|
|
+/// [Unix timestamp]: https://en.wikipedia.org/wiki/Unix_time
|
|
+/// [with]: https://serde.rs/field-attrs.html#with
|
|
+pub mod option {
|
|
+ #[allow(clippy::wildcard_imports)]
|
|
+ use super::*;
|
|
+
|
|
+ /// Serialize an `Option<OffsetDateTime>` as its Unix timestamp with milliseconds
|
|
+ pub fn serialize<S: Serializer>(
|
|
+ option: &Option<OffsetDateTime>,
|
|
+ serializer: S,
|
|
+ ) -> Result<S::Ok, S::Error> {
|
|
+ option
|
|
+ .map(|timestamp| timestamp.unix_timestamp_nanos() / 1_000_000)
|
|
+ .serialize(serializer)
|
|
+ }
|
|
+
|
|
+ /// Deserialize an `Option<OffsetDateTime>` from its Unix timestamp with milliseconds
|
|
+ pub fn deserialize<'a, D: Deserializer<'a>>(
|
|
+ deserializer: D,
|
|
+ ) -> Result<Option<OffsetDateTime>, D::Error> {
|
|
+ Option::deserialize(deserializer)?
|
|
+ .map(|value: i128| OffsetDateTime::from_unix_timestamp_nanos(value * 1_000_000))
|
|
+ .transpose()
|
|
+ .map_err(|err| de::Error::invalid_value(de::Unexpected::Signed(err.value), &err))
|
|
+ }
|
|
+}
|
|
diff --git a/vendor/time/src/serde/timestamp.rs b/vendor/time/src/serde/timestamp/mod.rs
|
|
similarity index 97%
|
|
rename from vendor/time/src/serde/timestamp.rs
|
|
rename to vendor/time/src/serde/timestamp/mod.rs
|
|
index d86e6b9..6dd0db0 100644
|
|
--- a/vendor/time/src/serde/timestamp.rs
|
|
+++ b/vendor/time/src/serde/timestamp/mod.rs
|
|
@@ -7,6 +7,10 @@
|
|
//! [Unix timestamp]: https://en.wikipedia.org/wiki/Unix_time
|
|
//! [with]: https://serde.rs/field-attrs.html#with
|
|
|
|
+pub mod microseconds;
|
|
+pub mod milliseconds;
|
|
+pub mod nanoseconds;
|
|
+
|
|
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
|
|
|
|
use crate::OffsetDateTime;
|
|
diff --git a/vendor/time/src/serde/timestamp/nanoseconds.rs b/vendor/time/src/serde/timestamp/nanoseconds.rs
|
|
new file mode 100644
|
|
index 0000000..c71d1e7
|
|
--- /dev/null
|
|
+++ b/vendor/time/src/serde/timestamp/nanoseconds.rs
|
|
@@ -0,0 +1,61 @@
|
|
+//! Treat an [`OffsetDateTime`] as a [Unix timestamp] with nanoseconds for
|
|
+//! the purposes of serde.
|
|
+//!
|
|
+//! Use this module in combination with serde's [`#[with]`][with] attribute.
|
|
+//!
|
|
+//! When deserializing, the offset is assumed to be UTC.
|
|
+//!
|
|
+//! [Unix timestamp]: https://en.wikipedia.org/wiki/Unix_time
|
|
+//! [with]: https://serde.rs/field-attrs.html#with
|
|
+
|
|
+use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
|
|
+
|
|
+use crate::OffsetDateTime;
|
|
+
|
|
+/// Serialize an `OffsetDateTime` as its Unix timestamp with nanoseconds
|
|
+pub fn serialize<S: Serializer>(
|
|
+ datetime: &OffsetDateTime,
|
|
+ serializer: S,
|
|
+) -> Result<S::Ok, S::Error> {
|
|
+ datetime.unix_timestamp_nanos().serialize(serializer)
|
|
+}
|
|
+
|
|
+/// Deserialize an `OffsetDateTime` from its Unix timestamp with nanoseconds
|
|
+pub fn deserialize<'a, D: Deserializer<'a>>(deserializer: D) -> Result<OffsetDateTime, D::Error> {
|
|
+ OffsetDateTime::from_unix_timestamp_nanos(<_>::deserialize(deserializer)?)
|
|
+ .map_err(|err| de::Error::invalid_value(de::Unexpected::Signed(err.value), &err))
|
|
+}
|
|
+
|
|
+/// Treat an `Option<OffsetDateTime>` as a [Unix timestamp] with nanoseconds
|
|
+/// for the purposes of serde.
|
|
+///
|
|
+/// Use this module in combination with serde's [`#[with]`][with] attribute.
|
|
+///
|
|
+/// When deserializing, the offset is assumed to be UTC.
|
|
+///
|
|
+/// [Unix timestamp]: https://en.wikipedia.org/wiki/Unix_time
|
|
+/// [with]: https://serde.rs/field-attrs.html#with
|
|
+pub mod option {
|
|
+ #[allow(clippy::wildcard_imports)]
|
|
+ use super::*;
|
|
+
|
|
+ /// Serialize an `Option<OffsetDateTime>` as its Unix timestamp with nanoseconds
|
|
+ pub fn serialize<S: Serializer>(
|
|
+ option: &Option<OffsetDateTime>,
|
|
+ serializer: S,
|
|
+ ) -> Result<S::Ok, S::Error> {
|
|
+ option
|
|
+ .map(OffsetDateTime::unix_timestamp_nanos)
|
|
+ .serialize(serializer)
|
|
+ }
|
|
+
|
|
+ /// Deserialize an `Option<OffsetDateTime>` from its Unix timestamp with nanoseconds
|
|
+ pub fn deserialize<'a, D: Deserializer<'a>>(
|
|
+ deserializer: D,
|
|
+ ) -> Result<Option<OffsetDateTime>, D::Error> {
|
|
+ Option::deserialize(deserializer)?
|
|
+ .map(OffsetDateTime::from_unix_timestamp_nanos)
|
|
+ .transpose()
|
|
+ .map_err(|err| de::Error::invalid_value(de::Unexpected::Signed(err.value), &err))
|
|
+ }
|
|
+}
|
|
diff --git a/vendor/time/src/sys/local_offset_at/wasm_js.rs b/vendor/time/src/sys/local_offset_at/wasm_js.rs
|
|
index a0b59ac..a985e7c 100644
|
|
--- a/vendor/time/src/sys/local_offset_at/wasm_js.rs
|
|
+++ b/vendor/time/src/sys/local_offset_at/wasm_js.rs
|
|
@@ -1,3 +1,5 @@
|
|
+use num_conv::prelude::*;
|
|
+
|
|
use crate::convert::*;
|
|
use crate::{OffsetDateTime, UtcOffset};
|
|
|
|
@@ -7,7 +9,8 @@ pub(super) fn local_offset_at(datetime: OffsetDateTime) -> Option<UtcOffset> {
|
|
// The number of minutes returned by getTimezoneOffset() is positive if the local time zone
|
|
// is behind UTC, and negative if the local time zone is ahead of UTC. For example,
|
|
// for UTC+10, -600 will be returned.
|
|
- let timezone_offset = (js_date.get_timezone_offset() as i32) * -(Minute::per(Hour) as i32);
|
|
+ let timezone_offset =
|
|
+ (js_date.get_timezone_offset() as i32) * -Minute::per(Hour).cast_signed().extend::<i32>();
|
|
|
|
UtcOffset::from_whole_seconds(timezone_offset).ok()
|
|
}
|
|
diff --git a/vendor/time/src/sys/local_offset_at/windows.rs b/vendor/time/src/sys/local_offset_at/windows.rs
|
|
index 7fb41e0..d144292 100644
|
|
--- a/vendor/time/src/sys/local_offset_at/windows.rs
|
|
+++ b/vendor/time/src/sys/local_offset_at/windows.rs
|
|
@@ -2,6 +2,8 @@
|
|
|
|
use core::mem::MaybeUninit;
|
|
|
|
+use num_conv::prelude::*;
|
|
+
|
|
use crate::convert::*;
|
|
use crate::{OffsetDateTime, UtcOffset};
|
|
|
|
@@ -57,21 +59,22 @@ fn systemtime_to_filetime(systime: &SystemTime) -> Option<FileTime> {
|
|
/// Convert a `FILETIME` to an `i64`, representing a number of seconds.
|
|
fn filetime_to_secs(filetime: &FileTime) -> i64 {
|
|
/// FILETIME represents 100-nanosecond intervals
|
|
- const FT_TO_SECS: i64 = Nanosecond::per(Second) as i64 / 100;
|
|
- ((filetime.dwHighDateTime as i64) << 32 | filetime.dwLowDateTime as i64) / FT_TO_SECS
|
|
+ const FT_TO_SECS: u64 = Nanosecond::per(Second) as u64 / 100;
|
|
+ ((filetime.dwHighDateTime.extend::<u64>() << 32 | filetime.dwLowDateTime.extend::<u64>())
|
|
+ / FT_TO_SECS) as i64
|
|
}
|
|
|
|
/// Convert an [`OffsetDateTime`] to a `SYSTEMTIME`.
|
|
fn offset_to_systemtime(datetime: OffsetDateTime) -> SystemTime {
|
|
let (_, month, day_of_month) = datetime.to_offset(UtcOffset::UTC).date().to_calendar_date();
|
|
SystemTime {
|
|
- wYear: datetime.year() as _,
|
|
- wMonth: month as _,
|
|
- wDay: day_of_month as _,
|
|
+ wYear: datetime.year().cast_unsigned().truncate(),
|
|
+ wMonth: u8::from(month).extend(),
|
|
+ wDay: day_of_month.extend(),
|
|
wDayOfWeek: 0, // ignored
|
|
- wHour: datetime.hour() as _,
|
|
- wMinute: datetime.minute() as _,
|
|
- wSecond: datetime.second() as _,
|
|
+ wHour: datetime.hour().extend(),
|
|
+ wMinute: datetime.minute().extend(),
|
|
+ wSecond: datetime.second().extend(),
|
|
wMilliseconds: datetime.millisecond(),
|
|
}
|
|
}
|
|
diff --git a/vendor/time/src/tests.rs b/vendor/time/src/tests.rs
|
|
index 2f9dbfe..4ccd87b 100644
|
|
--- a/vendor/time/src/tests.rs
|
|
+++ b/vendor/time/src/tests.rs
|
|
@@ -25,6 +25,7 @@
|
|
//! This module should only be used when it is not possible to test the implementation in a
|
|
//! reasonable manner externally.
|
|
|
|
+use std::format;
|
|
use std::num::NonZeroU8;
|
|
|
|
use crate::ext::DigitCount;
|
|
diff --git a/vendor/time/src/time.rs b/vendor/time/src/time.rs
|
|
index 90abc01..2bd2fef 100644
|
|
--- a/vendor/time/src/time.rs
|
|
+++ b/vendor/time/src/time.rs
|
|
@@ -1,5 +1,7 @@
|
|
//! The [`Time`] struct and its associated `impl`s.
|
|
|
|
+#[cfg(feature = "formatting")]
|
|
+use alloc::string::String;
|
|
use core::fmt;
|
|
use core::ops::{Add, Sub};
|
|
use core::time::Duration as StdDuration;
|
|
@@ -7,6 +9,7 @@ use core::time::Duration as StdDuration;
|
|
use std::io;
|
|
|
|
use deranged::{RangedU32, RangedU8};
|
|
+use num_conv::prelude::*;
|
|
use powerfmt::ext::FormatterExt;
|
|
use powerfmt::smart_display::{self, FormatterOptions, Metadata, SmartDisplay};
|
|
|
|
@@ -717,7 +720,7 @@ impl Time {
|
|
self,
|
|
output: &mut impl io::Write,
|
|
format: &(impl Formattable + ?Sized),
|
|
- ) -> Result<usize, crate::error::Format> {
|
|
+ ) -> Result<usize, error::Format> {
|
|
format.format_into(output, None, Some(self), None)
|
|
}
|
|
|
|
@@ -730,10 +733,7 @@ impl Time {
|
|
/// assert_eq!(time!(12:00).format(&format)?, "12:00:00");
|
|
/// # Ok::<_, time::Error>(())
|
|
/// ```
|
|
- pub fn format(
|
|
- self,
|
|
- format: &(impl Formattable + ?Sized),
|
|
- ) -> Result<String, crate::error::Format> {
|
|
+ pub fn format(self, format: &(impl Formattable + ?Sized)) -> Result<String, error::Format> {
|
|
format.format(None, Some(self), None)
|
|
}
|
|
}
|
|
@@ -800,7 +800,7 @@ impl SmartDisplay for Time {
|
|
formatted_width,
|
|
self,
|
|
TimeMetadata {
|
|
- subsecond_width: subsecond_width as _,
|
|
+ subsecond_width: subsecond_width.truncate(),
|
|
subsecond_value,
|
|
},
|
|
)
|
|
@@ -811,7 +811,7 @@ impl SmartDisplay for Time {
|
|
f: &mut fmt::Formatter<'_>,
|
|
metadata: Metadata<Self>,
|
|
) -> fmt::Result {
|
|
- let subsecond_width = metadata.subsecond_width as usize;
|
|
+ let subsecond_width = metadata.subsecond_width.extend();
|
|
let subsecond_value = metadata.subsecond_value;
|
|
|
|
f.pad_with_width(
|
|
@@ -921,24 +921,25 @@ impl Sub for Time {
|
|
/// assert_eq!(time!(0:00) - time!(23:00), (-23).hours());
|
|
/// ```
|
|
fn sub(self, rhs: Self) -> Self::Output {
|
|
- let hour_diff = (self.hour.get() as i8) - (rhs.hour.get() as i8);
|
|
- let minute_diff = (self.minute.get() as i8) - (rhs.minute.get() as i8);
|
|
- let second_diff = (self.second.get() as i8) - (rhs.second.get() as i8);
|
|
- let nanosecond_diff = (self.nanosecond.get() as i32) - (rhs.nanosecond.get() as i32);
|
|
+ let hour_diff = self.hour.get().cast_signed() - rhs.hour.get().cast_signed();
|
|
+ let minute_diff = self.minute.get().cast_signed() - rhs.minute.get().cast_signed();
|
|
+ let second_diff = self.second.get().cast_signed() - rhs.second.get().cast_signed();
|
|
+ let nanosecond_diff =
|
|
+ self.nanosecond.get().cast_signed() - rhs.nanosecond.get().cast_signed();
|
|
|
|
- let seconds = hour_diff as i64 * Second::per(Hour) as i64
|
|
- + minute_diff as i64 * Second::per(Minute) as i64
|
|
- + second_diff as i64;
|
|
+ let seconds = hour_diff.extend::<i64>() * Second::per(Hour).cast_signed().extend::<i64>()
|
|
+ + minute_diff.extend::<i64>() * Second::per(Minute).cast_signed().extend::<i64>()
|
|
+ + second_diff.extend::<i64>();
|
|
|
|
let (seconds, nanoseconds) = if seconds > 0 && nanosecond_diff < 0 {
|
|
(
|
|
seconds - 1,
|
|
- nanosecond_diff + Nanosecond::per(Second) as i32,
|
|
+ nanosecond_diff + Nanosecond::per(Second).cast_signed(),
|
|
)
|
|
} else if seconds < 0 && nanosecond_diff > 0 {
|
|
(
|
|
seconds + 1,
|
|
- nanosecond_diff - Nanosecond::per(Second) as i32,
|
|
+ nanosecond_diff - Nanosecond::per(Second).cast_signed(),
|
|
)
|
|
} else {
|
|
(seconds, nanosecond_diff)
|
|
diff --git a/vendor/time/src/utc_offset.rs b/vendor/time/src/utc_offset.rs
|
|
index f4e6eaa..7cf24d1 100644
|
|
--- a/vendor/time/src/utc_offset.rs
|
|
+++ b/vendor/time/src/utc_offset.rs
|
|
@@ -1,5 +1,7 @@
|
|
//! The [`UtcOffset`] struct and its associated `impl`s.
|
|
|
|
+#[cfg(feature = "formatting")]
|
|
+use alloc::string::String;
|
|
use core::fmt;
|
|
use core::ops::Neg;
|
|
#[cfg(feature = "formatting")]
|
|
@@ -22,15 +24,28 @@ use crate::sys::local_offset_at;
|
|
use crate::OffsetDateTime;
|
|
|
|
/// The type of the `hours` field of `UtcOffset`.
|
|
-type Hours = RangedI8<{ -(Hour::per(Day) as i8 - 1) }, { Hour::per(Day) as i8 - 1 }>;
|
|
+type Hours = RangedI8<-25, 25>;
|
|
/// The type of the `minutes` field of `UtcOffset`.
|
|
type Minutes = RangedI8<{ -(Minute::per(Hour) as i8 - 1) }, { Minute::per(Hour) as i8 - 1 }>;
|
|
/// The type of the `seconds` field of `UtcOffset`.
|
|
type Seconds = RangedI8<{ -(Second::per(Minute) as i8 - 1) }, { Second::per(Minute) as i8 - 1 }>;
|
|
+/// The type capable of storing the range of whole seconds that a `UtcOffset` can encompass.
|
|
+type WholeSeconds = RangedI32<
|
|
+ {
|
|
+ Hours::MIN.get() as i32 * Second::per(Hour) as i32
|
|
+ + Minutes::MIN.get() as i32 * Second::per(Minute) as i32
|
|
+ + Seconds::MIN.get() as i32
|
|
+ },
|
|
+ {
|
|
+ Hours::MAX.get() as i32 * Second::per(Hour) as i32
|
|
+ + Minutes::MAX.get() as i32 * Second::per(Minute) as i32
|
|
+ + Seconds::MAX.get() as i32
|
|
+ },
|
|
+>;
|
|
|
|
/// An offset from UTC.
|
|
///
|
|
-/// This struct can store values up to ±23:59:59. If you need support outside this range, please
|
|
+/// This struct can store values up to ±25:59:59. If you need support outside this range, please
|
|
/// file an issue with your use case.
|
|
// All three components _must_ have the same sign.
|
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
|
@@ -51,9 +66,7 @@ impl UtcOffset {
|
|
/// # use time_macros::offset;
|
|
/// assert_eq!(UtcOffset::UTC, offset!(UTC));
|
|
/// ```
|
|
- #[allow(clippy::undocumented_unsafe_blocks)] // rust-lang/rust-clippy#11246
|
|
- // Safety: All values are in range.
|
|
- pub const UTC: Self = unsafe { Self::__from_hms_unchecked(0, 0, 0) };
|
|
+ pub const UTC: Self = Self::from_whole_seconds_ranged(WholeSeconds::new_static::<0>());
|
|
|
|
// region: constructors
|
|
/// Create a `UtcOffset` representing an offset of the hours, minutes, and seconds provided, the
|
|
@@ -62,7 +75,7 @@ impl UtcOffset {
|
|
///
|
|
/// # Safety
|
|
///
|
|
- /// - Hours must be in the range `-23..=23`.
|
|
+ /// - Hours must be in the range `-25..=25`.
|
|
/// - Minutes must be in the range `-59..=59`.
|
|
/// - Seconds must be in the range `-59..=59`.
|
|
///
|
|
@@ -169,28 +182,31 @@ impl UtcOffset {
|
|
/// # Ok::<_, time::Error>(())
|
|
/// ```
|
|
pub const fn from_whole_seconds(seconds: i32) -> Result<Self, error::ComponentRange> {
|
|
- type WholeSeconds = RangedI32<
|
|
- {
|
|
- Hours::MIN.get() as i32 * Second::per(Hour) as i32
|
|
- + Minutes::MIN.get() as i32 * Second::per(Minute) as i32
|
|
- + Seconds::MIN.get() as i32
|
|
- },
|
|
- {
|
|
- Hours::MAX.get() as i32 * Second::per(Hour) as i32
|
|
- + Minutes::MAX.get() as i32 * Second::per(Minute) as i32
|
|
- + Seconds::MAX.get() as i32
|
|
- },
|
|
- >;
|
|
- ensure_ranged!(WholeSeconds: seconds);
|
|
-
|
|
- // Safety: The value was checked to be in range.
|
|
- Ok(unsafe {
|
|
+ Ok(Self::from_whole_seconds_ranged(
|
|
+ ensure_ranged!(WholeSeconds: seconds),
|
|
+ ))
|
|
+ }
|
|
+
|
|
+ /// Create a `UtcOffset` representing an offset by the number of seconds provided.
|
|
+ // ignore because the function is crate-private
|
|
+ /// ```rust,ignore
|
|
+ /// # use time::UtcOffset;
|
|
+ /// # use deranged::RangedI32;
|
|
+ /// assert_eq!(
|
|
+ /// UtcOffset::from_whole_seconds_ranged(RangedI32::new_static::<3_723>()).as_hms(),
|
|
+ /// (1, 2, 3)
|
|
+ /// );
|
|
+ /// # Ok::<_, time::Error>(())
|
|
+ /// ```
|
|
+ pub(crate) const fn from_whole_seconds_ranged(seconds: WholeSeconds) -> Self {
|
|
+ // Safety: The type of `seconds` guarantees that all values are in range.
|
|
+ unsafe {
|
|
Self::__from_hms_unchecked(
|
|
- (seconds / Second::per(Hour) as i32) as _,
|
|
- ((seconds % Second::per(Hour) as i32) / Minute::per(Hour) as i32) as _,
|
|
- (seconds % Second::per(Minute) as i32) as _,
|
|
+ (seconds.get() / Second::per(Hour) as i32) as _,
|
|
+ ((seconds.get() % Second::per(Hour) as i32) / Minute::per(Hour) as i32) as _,
|
|
+ (seconds.get() % Second::per(Minute) as i32) as _,
|
|
)
|
|
- })
|
|
+ }
|
|
}
|
|
// endregion constructors
|
|
|
|
diff --git a/vendor/time/src/util.rs b/vendor/time/src/util.rs
|
|
index 857f5f2..9bb9b04 100644
|
|
--- a/vendor/time/src/util.rs
|
|
+++ b/vendor/time/src/util.rs
|
|
@@ -85,13 +85,13 @@ pub mod local_offset {
|
|
/// - [`UtcOffset::local_offset_at`](crate::UtcOffset::local_offset_at)
|
|
/// - [`UtcOffset::current_local_offset`](crate::UtcOffset::current_local_offset)
|
|
pub unsafe fn set_soundness(soundness: Soundness) {
|
|
- LOCAL_OFFSET_IS_SOUND.store(soundness == Soundness::Sound, Ordering::SeqCst);
|
|
+ LOCAL_OFFSET_IS_SOUND.store(soundness == Soundness::Sound, Ordering::Release);
|
|
}
|
|
|
|
/// Obtains the soundness of obtaining the local UTC offset. If it is [`Soundness::Unsound`],
|
|
/// it is allowed to invoke undefined behavior when obtaining the local UTC offset.
|
|
pub fn get_soundness() -> Soundness {
|
|
- match LOCAL_OFFSET_IS_SOUND.load(Ordering::SeqCst) {
|
|
+ match LOCAL_OFFSET_IS_SOUND.load(Ordering::Acquire) {
|
|
false => Soundness::Unsound,
|
|
true => Soundness::Sound,
|
|
}
|
|
--
|
|
2.45.2
|
|
|