From ea40f62c8bb6db67384aa426e1ae72e3698ccbfa Mon Sep 17 00:00:00 2001 From: MSVSphere Packaging Team Date: Mon, 25 Nov 2024 09:41:00 +0300 Subject: [PATCH] import librsvg2-2.57.1-9.el10 --- SOURCES/0001-Update-time-crate.patch | 8023 ++++++++++++++++++++++++++ SPECS/librsvg2.spec | 14 +- 2 files changed, 8032 insertions(+), 5 deletions(-) create mode 100644 SOURCES/0001-Update-time-crate.patch diff --git a/SOURCES/0001-Update-time-crate.patch b/SOURCES/0001-Update-time-crate.patch new file mode 100644 index 0000000..ab0c13d --- /dev/null +++ b/SOURCES/0001-Update-time-crate.patch @@ -0,0 +1,8023 @@ +From 7dead1c8d1b8438196d0bafbd6c4a94d9eeb911a Mon Sep 17 00:00:00 2001 +From: 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 "] ++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 { ++ fn extend(self) -> T; ++ } ++ ++ pub trait TruncateTargetSealed { ++ 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: sealed::ExtendTargetSealed {} ++ ++/// 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: sealed::TruncateTargetSealed {} ++ ++/// Extend to an integer of the same size or larger, preserving its value. ++/// ++/// ```rust ++/// # use num_conv::Extend; ++/// assert_eq!(0_u8.extend::(), 0_u16); ++/// assert_eq!(0_u16.extend::(), 0_u32); ++/// assert_eq!(0_u32.extend::(), 0_u64); ++/// assert_eq!(0_u64.extend::(), 0_u128); ++/// ``` ++/// ++/// ```rust ++/// # use num_conv::Extend; ++/// assert_eq!((-1_i8).extend::(), -1_i16); ++/// assert_eq!((-1_i16).extend::(), -1_i32); ++/// assert_eq!((-1_i32).extend::(), -1_i64); ++/// assert_eq!((-1_i64).extend::(), -1_i128); ++/// ``` ++pub trait Extend: sealed::Integer { ++ /// Extend an integer to an integer of the same size or larger, preserving its value. ++ fn extend(self) -> T ++ where ++ Self: ExtendTarget; ++} ++ ++impl Extend for T { ++ fn extend(self) -> U ++ where ++ T: ExtendTarget, ++ { ++ 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::MAX); ++/// assert_eq!(u32::MAX.truncate::(), u16::MAX); ++/// assert_eq!(u64::MAX.truncate::(), u32::MAX); ++/// assert_eq!(u128::MAX.truncate::(), u64::MAX); ++/// ``` ++/// ++/// ```rust ++/// # use num_conv::Truncate; ++/// assert_eq!((-1_i16).truncate::(), -1_i8); ++/// assert_eq!((-1_i32).truncate::(), -1_i16); ++/// assert_eq!((-1_i64).truncate::(), -1_i32); ++/// assert_eq!((-1_i128).truncate::(), -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(self) -> T ++ where ++ Self: TruncateTarget; ++} ++ ++impl Truncate for T { ++ fn truncate(self) -> U ++ where ++ T: TruncateTarget, ++ { ++ 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 ", + "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) -> Result 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> for crate::format_description::public::OwnedFormatItem { + impl<'a> From]>> 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 { +- iter: core::iter::Peekable, ++ iter: iter::Peekable, + } + + impl Iterator for Lexed { +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, + s: &[u8], + proc_span: proc_macro::Span, +-) -> Result, crate::Error> { ++) -> Result, 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( + s: &[u8], + proc_span: proc_macro::Span, +-) -> Result, crate::Error> { ++) -> Result, crate::Error> { + let mut lexed = lexer::lex::(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::(); + 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::(); + 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::() - 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::() - 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) -> Result= 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 ", + "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 { ++ 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::() + + 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 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 for Date { + impl Add 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 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 for Date { + impl Sub 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` 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::() == size_of::(); +- /// True if and only if `Self::MemoryOffsetType` is `UtcOffset`. +- const HAS_MEMORY_OFFSET: bool = +- size_of::() == size_of::(); +- +- /// `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; +- +- #[cfg(feature = "parsing")] +- fn try_from_parsed(parsed: Parsed) -> Result; +- } +- +- // Traits to indicate whether a `MaybeOffset` has a logical offset type of `UtcOffset` or not. +- +- pub trait HasLogicalOffset: MaybeOffset {} +- impl> HasLogicalOffset for T {} +- +- pub trait NoLogicalOffset: MaybeOffset {} +- impl> NoLogicalOffset for T {} +- +- // Traits to indicate whether a `MaybeOffset` has a memory offset type of `UtcOffset` or not. +- +- pub trait HasMemoryOffset: MaybeOffset {} +- impl> HasMemoryOffset for T {} +- +- pub trait NoMemoryOffset: MaybeOffset {} +- impl> NoMemoryOffset for T {} +- +- // Traits to indicate backing type being implemented. +- +- pub trait IsOffsetKindNone: +- MaybeOffset +- { +- } +- 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 = 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 = None; +- +- #[cfg(feature = "parsing")] +- fn try_from_parsed(parsed: Parsed) -> Result { +- 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( +- offset: O::MemoryOffsetType, +-) -> Option { +- 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 { +- 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:: { input: offset }.output }) +- } else { +- None +- } +-} +- +-const fn maybe_offset_as_offset( +- offset: O::MemoryOffsetType, +-) -> UtcOffset { +- match maybe_offset_as_offset_opt::(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( +- offset: UtcOffset, +-) -> O::MemoryOffsetType { +- #[repr(C)] // needed to guarantee the types align at the start +- union Convert { +- 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:: { 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 { +- pub(crate) date: Date, +- pub(crate) time: Time, +- pub(crate) offset: O::MemoryOffsetType, +-} +- +-// Manual impl to remove extraneous bounds. +-impl Clone for DateTime { +- fn clone(&self) -> Self { +- *self +- } +-} +- +-// Manual impl to remove extraneous bounds. +-impl Copy for DateTime {} +- +-// region: constructors +-impl DateTime { +- 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 { +- 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 DateTime { +- 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 +- 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::(UtcOffset::UTC), +- }) +- } +- +- pub const fn from_unix_timestamp_nanos(timestamp: i128) -> Result +- 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::(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 +- 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, error::IndeterminateOffset> +- where +- O: IsOffsetKindFixed, +- { +- let t = DateTime::::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::(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::(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 +- where +- O: NoLogicalOffset, +- { +- DateTime { +- date: self.date, +- time: self.time, +- offset, +- } +- } +- +- pub const fn assume_utc(self) -> DateTime +- where +- O: NoLogicalOffset, +- { +- self.assume_offset(UtcOffset::UTC) +- } +- // endregion attach offset +- +- // region: to offset +- pub const fn to_offset(self, offset: UtcOffset) -> DateTime +- 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> +- where +- O: HasLogicalOffset, +- { +- let self_offset = maybe_offset_as_offset::(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::(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 { +- 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 { +- 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) -> 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 { +- 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 { +- 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 { +- 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 { +- 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 { +- 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 { +- 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 { +- 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 { +- 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 { +- 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 +- 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 { +- format.format_into( +- output, +- Some(self.date), +- Some(self.time), +- maybe_offset_as_offset_opt::(self.offset), +- ) +- } +- +- #[cfg(feature = "formatting")] +- pub fn format(self, format: &(impl Formattable + ?Sized)) -> Result { +- format.format( +- Some(self.date), +- Some(self.time), +- maybe_offset_as_offset_opt::(self.offset), +- ) +- } +- +- #[cfg(feature = "parsing")] +- pub fn parse( +- input: &str, +- description: &(impl Parsable + ?Sized), +- ) -> Result { +- 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`. 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, +- } +-} +-pub(crate) use private::DateTimeMetadata; +- +-impl SmartDisplay for DateTime { +- type Metadata = DateTimeMetadata; +- +- fn metadata(&self, _: FormatterOptions) -> Metadata { +- let maybe_offset = maybe_offset_as_offset_opt::(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, +- ) -> 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 fmt::Display for DateTime { +- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +- SmartDisplay::fmt(self, f) +- } +-} +- +-impl fmt::Debug for DateTime { +- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +- fmt::Display::fmt(self, f) +- } +-} +- +-impl PartialEq for DateTime { +- 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 Eq for DateTime {} +- +-impl PartialOrd for DateTime { +- fn partial_cmp(&self, rhs: &Self) -> Option { +- Some(self.cmp(rhs)) +- } +-} +- +-impl Ord for DateTime { +- 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 Hash for DateTime { +- fn hash(&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 Add for DateTime { +- type Output = Self; +- +- fn add(self, duration: Duration) -> Self { +- self.checked_add(duration) +- .expect("resulting value is out of range") +- } +-} +- +-impl Add for DateTime { +- 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 AddAssign for DateTime { +- fn add_assign(&mut self, rhs: Duration) { +- *self = *self + rhs; +- } +-} +- +-impl AddAssign for DateTime { +- fn add_assign(&mut self, rhs: StdDuration) { +- *self = *self + rhs; +- } +-} +- +-impl Sub for DateTime { +- type Output = Self; +- +- fn sub(self, duration: Duration) -> Self { +- self.checked_sub(duration) +- .expect("resulting value is out of range") +- } +-} +- +-impl Sub for DateTime { +- 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 SubAssign for DateTime { +- fn sub_assign(&mut self, rhs: Duration) { +- *self = *self - rhs; +- } +-} +- +-impl SubAssign for DateTime { +- fn sub_assign(&mut self, rhs: StdDuration) { +- *self = *self - rhs; +- } +-} +- +-impl Sub for DateTime { +- 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::(self.offset), +- maybe_offset_as_offset_opt::(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 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 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 for DateTime { +- type Output = Duration; +- +- fn sub(self, rhs: SystemTime) -> Self::Output { +- self - Self::from(rhs) +- } +-} +- +-#[cfg(feature = "std")] +-impl Sub> for SystemTime { +- type Output = Duration; +- +- fn sub(self, rhs: DateTime) -> Self::Output { +- DateTime::::from(self) - rhs +- } +-} +- +-#[cfg(feature = "std")] +-impl PartialEq for DateTime { +- fn eq(&self, rhs: &SystemTime) -> bool { +- self == &Self::from(*rhs) +- } +-} +- +-#[cfg(feature = "std")] +-impl PartialEq> for SystemTime { +- fn eq(&self, rhs: &DateTime) -> bool { +- &DateTime::::from(*self) == rhs +- } +-} +- +-#[cfg(feature = "std")] +-impl PartialOrd for DateTime { +- fn partial_cmp(&self, other: &SystemTime) -> Option { +- self.partial_cmp(&Self::from(*other)) +- } +-} +- +-#[cfg(feature = "std")] +-impl PartialOrd> for SystemTime { +- fn partial_cmp(&self, other: &DateTime) -> Option { +- DateTime::::from(*self).partial_cmp(other) +- } +-} +- +-#[cfg(feature = "std")] +-impl From for DateTime { +- 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> for SystemTime { +- fn from(datetime: DateTime) -> Self { +- let duration = datetime - DateTime::::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 for DateTime { +- 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> for js_sys::Date { +- fn from(datetime: DateTime) -> 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 { ++ 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(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::())?; + item!( + "h", +- seconds / Second::per(Hour) as u64 % Hour::per(Day) as u64 ++ seconds / Second::per(Hour).extend::() % Hour::per(Day).extend::() + )?; + item!( + "m", +- seconds / Second::per(Minute) as u64 % Minute::per(Hour) as u64 ++ seconds / Second::per(Minute).extend::() % Minute::per(Hour).extend::() + )?; +- item!("s", seconds % Second::per(Minute) as u64)?; ++ item!("s", seconds % Second::per(Minute).extend::())?; + item!("ms", nanoseconds / Nanosecond::per(Millisecond))?; + item!( + "µs", +- nanoseconds / Nanosecond::per(Microsecond) as u32 +- % Microsecond::per(Millisecond) as u32 ++ nanoseconds / Nanosecond::per(Microsecond).extend::() ++ % Microsecond::per(Millisecond).extend::() ++ )?; ++ item!( ++ "ns", ++ nanoseconds % Nanosecond::per(Microsecond).extend::() + )?; +- item!("ns", nanoseconds % Nanosecond::per(Microsecond) as u32)?; + } + + Ok(()) +@@ -1237,7 +1286,7 @@ impl TryFrom 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 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 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 for StdDuration { + impl_add_assign!(Duration: Self, StdDuration); + + impl AddAssign 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 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 for Duration { + impl Sub 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 for StdDuration { + impl_sub_assign!(Duration: Self, StdDuration); + + impl SubAssign 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::()) + .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::() ++ ) + } + } + )+}; +@@ -1468,14 +1540,18 @@ impl PartialEq for StdDuration { + + impl PartialOrd for Duration { + fn partial_cmp(&self, rhs: &StdDuration) -> Option { +- 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::() + 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; ++ ++ /// 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; ++ ++ /// 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 { ++ 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 { ++ 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> for OwnedFormatItem { +- fn from(item: FormatItem<'_>) -> Self { ++impl From> 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::>() + .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>> for OwnedFormatItem { +- fn from(items: Vec>) -> Self { ++impl From>> for OwnedFormatItem { ++ fn from(items: Vec>) -> 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> for crate::format_description::FormatItem<'a> { ++impl<'a> TryFrom> for crate::format_description::BorrowedFormatItem<'a> { + type Error = Error; + + fn try_from(item: Item<'a>) -> Result { +@@ -149,14 +149,9 @@ impl From> for crate::format_description::OwnedFormatItem { + impl<'a> From]>> 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 { + /// The internal iterator. +- iter: core::iter::Peekable, ++ iter: iter::Peekable, + } + + impl Iterator for Lexed { +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 Version { + /// `parse_borrowed`. + pub fn parse( + s: &str, +-) -> Result>, crate::error::InvalidFormatDescription> +-{ ++) -> Result>, 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( + s: &str, +-) -> Result>, crate::error::InvalidFormatDescription> +-{ ++) -> Result>, error::InvalidFormatDescription> { + validate_version!(VERSION); + let mut lexed = lexer::lex::(s.as_bytes()); + let ast = ast::parse::<_, VERSION>(&mut lexed); +@@ -75,14 +75,12 @@ pub fn parse_borrowed( + /// [`OwnedFormatItem`]: crate::format_description::OwnedFormatItem + pub fn parse_owned( + s: &str, +-) -> Result { ++) -> Result { + validate_version!(VERSION); + let mut lexed = lexer::lex::(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::, _>>()?; ++ let items = format_items.collect::, _>>()?; + Ok(items.into()) + } + +@@ -222,10 +220,10 @@ struct Error { + /// The internal error. + _inner: Unused, + /// The error needed for interoperability with the rest of `time`. +- public: crate::error::InvalidFormatDescription, ++ public: error::InvalidFormatDescription, + } + +-impl From for crate::error::InvalidFormatDescription { ++impl From for error::InvalidFormatDescription { + fn from(error: Error) -> Self { + error.public + } +@@ -239,7 +237,6 @@ impl From for crate::error::InvalidFormatDescription { + struct Unused(core::marker::PhantomData); + + /// Indicate that a value is currently unused. +-#[allow(clippy::missing_const_for_fn)] // false positive + fn unused(_: T) -> Unused { + 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::()][..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::() - 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( + } 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::::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::::USE_SEPARATORS, b"-")?; + bytes += format_number_pad_zero::<2>(output, day)?; + } +@@ -41,7 +43,7 @@ pub(super) fn format_date( + } 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::::USE_SEPARATORS, b"-W", b"W")?; + bytes += format_number_pad_zero::<2>(output, week)?; +@@ -56,7 +58,7 @@ pub(super) fn format_date( + } 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::::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 { + 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::() + 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 { + 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::() - 1], ++ ), ++ modifier::MonthRepr::Short => write( ++ output, ++ &MONTH_NAMES[u8::from(date.month()).extend::() - 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::()][..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::()], + ), + 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 { +- 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::()) ++ .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::()) ++ .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 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; ++/// 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 { ++ 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(&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 { +- 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 { +- 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 { +- 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 { +- 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 { +- 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 { +- 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 { +- 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 { +- 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 { +- 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 { ++ 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 { +- 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 { +- 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 { +- 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 { +- 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 { +- 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 { +- 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 { +- 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 { +- 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 { +- 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.0.metadata(f).reuse() ++ fn metadata(&self, _: FormatterOptions) -> Metadata { ++ 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, + ) -> 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 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 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 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 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 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 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 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 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::(), ++ ); ++ base - adjustment + } + } + +@@ -1134,8 +1481,11 @@ impl Sub for OffsetDateTime { + impl Sub 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 for OffsetDateTime { + impl Sub 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 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 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 for OffsetDateTime { + fn eq(&self, rhs: &SystemTime) -> bool { +- self.0.eq(rhs) ++ self == &Self::from(*rhs) + } + } + + #[cfg(feature = "std")] + impl PartialEq for SystemTime { + fn eq(&self, rhs: &OffsetDateTime) -> bool { +- self.eq(&rhs.0) ++ &OffsetDateTime::from(*self) == rhs + } + } + + #[cfg(feature = "std")] + impl PartialOrd for OffsetDateTime { + fn partial_cmp(&self, other: &SystemTime) -> Option { +- self.0.partial_cmp(other) ++ self.partial_cmp(&Self::from(*other)) + } + } + + #[cfg(feature = "std")] + impl PartialOrd for SystemTime { + fn partial_cmp(&self, other: &OffsetDateTime) -> Option { +- self.partial_cmp(&other.0) ++ OffsetDateTime::from(*self).partial_cmp(other) + } + } + + #[cfg(feature = "std")] + impl From 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 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 for SystemTime { + feature = "wasm-bindgen" + ))] + impl From 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 for OffsetDateTime { + ))] + impl From 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::()) ++ 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::(); + + 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> { + 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(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::() * 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::() * 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> { + 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> { + 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> { + 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> { + 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::()), + 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::()), + 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::()), + 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 Iso8601 { + // 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 Iso8601 { + 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::(input) +@@ -44,7 +45,8 @@ impl Iso8601 { + } + 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 Iso8601 { + return Ok(input); + } + +- match (|| { ++ let parsed_week_weekday = (|| { + let input = ascii_char::(input) + .ok_or((false, InvalidLiteral))? + .into_inner(); +@@ -82,7 +84,8 @@ impl Iso8601 { + 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 Iso8601 { + .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 Iso8601 { + 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> { ++ 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 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( ++ /// Parse a [`PrimitiveDateTime`] from the format description. ++ fn parse_primitive_date_time( + &self, + input: &[u8], +- ) -> Result, error::Parse> { ++ ) -> Result { ++ Ok(self.parse(input)?.try_into()?) ++ } ++ ++ /// Parse a [`OffsetDateTime`] from the format description. ++ fn parse_offset_date_time(&self, input: &[u8]) -> Result { + 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::; + let comma = ascii_char::; + +- 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(&self, input: &[u8]) -> Result, error::Parse> { ++ fn parse_offset_date_time(&self, input: &[u8]) -> Result { + 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::; + let comma = ascii_char::; + +- 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::(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::; + + 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::(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::() * 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::() * 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(&self, input: &[u8]) -> Result, error::Parse> { ++ fn parse_offset_date_time(&self, input: &[u8]) -> Result { + 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::(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::() * 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::() * 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::(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 sealed::Sealed for Iso8601 { + 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, + 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 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::() * 7 ++ + weekday.number_days_from_sunday().cast_signed().extend::() + - 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::() * 7 ++ + weekday.number_days_from_monday().cast_signed().extend::() + - adjustment(year) +- + 1) as u16, ++ + 1).cast_unsigned(), + )?), + _ => Err(InsufficientInformation), + } +@@ -835,61 +847,45 @@ impl TryFrom for UtcOffset { + } + + impl TryFrom for PrimitiveDateTime { +- type Error = as TryFrom>::Error; ++ type Error = error::TryFromParsed; + + fn try_from(parsed: Parsed) -> Result { +- parsed.try_into().map(Self) ++ Ok(Self::new(parsed.try_into()?, parsed.try_into()?)) + } + } + + impl TryFrom for OffsetDateTime { +- type Error = as TryFrom>::Error; +- +- fn try_from(parsed: Parsed) -> Result { +- parsed.try_into().map(Self) +- } +-} +- +-impl TryFrom for DateTime { + type Error = error::TryFromParsed; + +- #[allow(clippy::unwrap_in_result)] // We know the values are valid. + fn try_from(mut parsed: Parsed) -> Result { +- if O::HAS_LOGICAL_OFFSET { +- if let Some(timestamp) = parsed.unix_timestamp_nanos() { +- let DateTime { date, time, offset } = +- DateTime::::from_unix_timestamp_nanos(timestamp)?; +- +- let mut value = Self { +- date, +- time, +- offset: maybe_offset_from_offset::(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; ++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 { +- 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 { +- 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 { +- 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 { +- 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 { +- 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 { ++ 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 { +- 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 { +- 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 { +- 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 { +- 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 { +- 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 { +- 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 { +- 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 { +- 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 { +- 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.0.metadata(f).reuse() ++ fn metadata(&self, _: FormatterOptions) -> Metadata { ++ 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, + ) -> 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 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 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 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 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 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 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 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 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> { +- 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> { +- Box::new(self.0.shrink().map(Self)) +- } +-} +- +-impl Arbitrary for DateTime { +- 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> { + 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(::default())), +- FormatItem::Literal(b":"), +- FormatItem::Component(Component::Minute(::default())), +- FormatItem::Literal(b":"), +- FormatItem::Component(Component::Second(::default())), +- FormatItem::Literal(b"."), +- FormatItem::Component(Component::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( ++ datetime: &OffsetDateTime, ++ serializer: S, ++) -> Result { ++ 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 { ++ 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` 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` as its Unix timestamp with microseconds ++ pub fn serialize( ++ option: &Option, ++ serializer: S, ++ ) -> Result { ++ option ++ .map(|timestamp| timestamp.unix_timestamp_nanos() / 1_000) ++ .serialize(serializer) ++ } ++ ++ /// Deserialize an `Option` from its Unix timestamp with microseconds ++ pub fn deserialize<'a, D: Deserializer<'a>>( ++ deserializer: D, ++ ) -> Result, 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( ++ datetime: &OffsetDateTime, ++ serializer: S, ++) -> Result { ++ 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 { ++ 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` 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` as its Unix timestamp with milliseconds ++ pub fn serialize( ++ option: &Option, ++ serializer: S, ++ ) -> Result { ++ option ++ .map(|timestamp| timestamp.unix_timestamp_nanos() / 1_000_000) ++ .serialize(serializer) ++ } ++ ++ /// Deserialize an `Option` from its Unix timestamp with milliseconds ++ pub fn deserialize<'a, D: Deserializer<'a>>( ++ deserializer: D, ++ ) -> Result, 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( ++ datetime: &OffsetDateTime, ++ serializer: S, ++) -> Result { ++ 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::from_unix_timestamp_nanos(<_>::deserialize(deserializer)?) ++ .map_err(|err| de::Error::invalid_value(de::Unexpected::Signed(err.value), &err)) ++} ++ ++/// Treat an `Option` 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` as its Unix timestamp with nanoseconds ++ pub fn serialize( ++ option: &Option, ++ serializer: S, ++ ) -> Result { ++ option ++ .map(OffsetDateTime::unix_timestamp_nanos) ++ .serialize(serializer) ++ } ++ ++ /// Deserialize an `Option` from its Unix timestamp with nanoseconds ++ pub fn deserialize<'a, D: Deserializer<'a>>( ++ deserializer: D, ++ ) -> Result, 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 { + // 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::(); + + 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 { + /// 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::() << 32 | filetime.dwLowDateTime.extend::()) ++ / 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 { ++ ) -> Result { + 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 { ++ pub fn format(self, format: &(impl Formattable + ?Sized)) -> Result { + 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, + ) -> 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::() * Second::per(Hour).cast_signed().extend::() ++ + minute_diff.extend::() * Second::per(Minute).cast_signed().extend::() ++ + second_diff.extend::(); + + 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 { +- 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 + diff --git a/SPECS/librsvg2.spec b/SPECS/librsvg2.spec index 4fbf198..75f173c 100644 --- a/SPECS/librsvg2.spec +++ b/SPECS/librsvg2.spec @@ -2,7 +2,7 @@ ## (rpmautospec version 0.6.5) ## RPMAUTOSPEC: autorelease, autochangelog %define autorelease(e:s:pb:n) %{?-p:0.}%{lua: - release_number = 7; + release_number = 9; base_release_number = tonumber(rpm.expand("%{?-b*}%{!?-b:1}")); print(release_number + base_release_number - 1); }%{?-e:.%{-e*}}%{?-s:.%{-s*}}%{!?-n:%{?dist}} @@ -54,10 +54,8 @@ Source0: https://download.gnome.org/sources/librsvg/2.57/librsvg-%{versio # cargo vendor && tar Jcvf ../librsvg-%%{version}-vendor.tar.xz vendor/ ; popd Source1: librsvg-%{version}-vendor.tar.xz -%if ! 0%{?bundled_rust_deps} -# Patches to build with Fedora-packaged rust crates -Patch: 0001-Fedora-Drop-dependencies-required-for-benchmarking.patch -%endif +# https://github.com/rust-lang/rust/issues/127343 +Patch: 0001-Update-time-crate.patch # skip a reference test where the reference image appears to have font issues Patch: 0001-skip-broken-reference-tests.patch @@ -200,6 +198,12 @@ rm -f %{buildroot}%{_pkgdocdir}/COMPILING.md %changelog ## START: Generated by rpmautospec +* Thu Nov 21 2024 Tomas Popela - 2.57.1-9 +- Fix FTBFS by updating time crate + +* Tue Oct 29 2024 Troy Dawson - 2.57.1-8 +- Bump release for October 2024 mass rebuild: + * Wed Jul 31 2024 Brian Stinson - 2.57.1-7 - Backport a patch from rawhide disabling broken tests