summaryrefslogtreecommitdiff
path: root/vendor/time/src/time.rs
diff options
context:
space:
mode:
authormo khan <mo@mokhan.ca>2025-07-15 16:37:08 -0600
committermo khan <mo@mokhan.ca>2025-07-17 16:30:22 -0600
commit45df4d0d9b577fecee798d672695fe24ff57fb1b (patch)
tree1b99bf645035b58e0d6db08c7a83521f41f7a75b /vendor/time/src/time.rs
parentf94f79608393d4ab127db63cc41668445ef6b243 (diff)
feat: migrate from Cedar to SpiceDB authorization system
This is a major architectural change that replaces the Cedar policy-based authorization system with SpiceDB's relation-based authorization. Key changes: - Migrate from Rust to Go implementation - Replace Cedar policies with SpiceDB schema and relationships - Switch from envoy `ext_authz` with Cedar to SpiceDB permission checks - Update build system and dependencies for Go ecosystem - Maintain Envoy integration for external authorization This change enables more flexible permission modeling through SpiceDB's Google Zanzibar inspired relation-based system, supporting complex hierarchical permissions that were difficult to express in Cedar. Breaking change: Existing Cedar policies and Rust-based configuration will no longer work and need to be migrated to SpiceDB schema.
Diffstat (limited to 'vendor/time/src/time.rs')
-rw-r--r--vendor/time/src/time.rs937
1 files changed, 0 insertions, 937 deletions
diff --git a/vendor/time/src/time.rs b/vendor/time/src/time.rs
deleted file mode 100644
index 627a2504..00000000
--- a/vendor/time/src/time.rs
+++ /dev/null
@@ -1,937 +0,0 @@
-//! 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;
-#[cfg(feature = "formatting")]
-use std::io;
-
-use deranged::{RangedU32, RangedU8};
-use num_conv::prelude::*;
-use powerfmt::ext::FormatterExt;
-use powerfmt::smart_display::{self, FormatterOptions, Metadata, SmartDisplay};
-
-use crate::convert::*;
-#[cfg(feature = "formatting")]
-use crate::formatting::Formattable;
-use crate::internal_macros::{cascade, ensure_ranged, impl_add_assign, impl_sub_assign};
-#[cfg(feature = "parsing")]
-use crate::parsing::Parsable;
-use crate::util::DateAdjustment;
-use crate::{error, Duration};
-
-/// By explicitly inserting this enum where padding is expected, the compiler is able to better
-/// perform niche value optimization.
-#[repr(u8)]
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub(crate) enum Padding {
- #[allow(clippy::missing_docs_in_private_items)]
- Optimize,
-}
-
-/// The type of the `hour` field of `Time`.
-type Hours = RangedU8<0, { Hour::per(Day) - 1 }>;
-/// The type of the `minute` field of `Time`.
-type Minutes = RangedU8<0, { Minute::per(Hour) - 1 }>;
-/// The type of the `second` field of `Time`.
-type Seconds = RangedU8<0, { Second::per(Minute) - 1 }>;
-/// The type of the `nanosecond` field of `Time`.
-type Nanoseconds = RangedU32<0, { Nanosecond::per(Second) - 1 }>;
-
-/// The clock time within a given date. Nanosecond precision.
-///
-/// All minutes are assumed to have exactly 60 seconds; no attempt is made to handle leap seconds
-/// (either positive or negative).
-///
-/// When comparing two `Time`s, they are assumed to be in the same calendar date.
-#[derive(Clone, Copy, Eq)]
-#[repr(C)]
-pub struct Time {
- // The order of this struct's fields matter!
- // Do not change them.
-
- // Little endian version
- #[cfg(target_endian = "little")]
- nanosecond: Nanoseconds,
- #[cfg(target_endian = "little")]
- second: Seconds,
- #[cfg(target_endian = "little")]
- minute: Minutes,
- #[cfg(target_endian = "little")]
- hour: Hours,
- #[cfg(target_endian = "little")]
- padding: Padding,
-
- // Big endian version
- #[cfg(target_endian = "big")]
- padding: Padding,
- #[cfg(target_endian = "big")]
- hour: Hours,
- #[cfg(target_endian = "big")]
- minute: Minutes,
- #[cfg(target_endian = "big")]
- second: Seconds,
- #[cfg(target_endian = "big")]
- nanosecond: Nanoseconds,
-}
-
-impl core::hash::Hash for Time {
- fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
- self.as_u64().hash(state)
- }
-}
-
-impl PartialEq for Time {
- fn eq(&self, other: &Self) -> bool {
- self.as_u64().eq(&other.as_u64())
- }
-}
-
-impl PartialOrd for Time {
- fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
- Some(self.cmp(other))
- }
-}
-
-impl Ord for Time {
- fn cmp(&self, other: &Self) -> core::cmp::Ordering {
- self.as_u64().cmp(&other.as_u64())
- }
-}
-
-impl Time {
- /// Provides an u64 based representation **of the correct endianness**
- ///
- /// This representation can be used to do comparisons equality testing or hashing.
- const fn as_u64(self) -> u64 {
- let nano_bytes = self.nanosecond.get().to_ne_bytes();
-
- #[cfg(target_endian = "big")]
- return u64::from_be_bytes([
- self.padding as u8,
- self.hour.get(),
- self.minute.get(),
- self.second.get(),
- nano_bytes[0],
- nano_bytes[1],
- nano_bytes[2],
- nano_bytes[3],
- ]);
-
- #[cfg(target_endian = "little")]
- return u64::from_le_bytes([
- nano_bytes[0],
- nano_bytes[1],
- nano_bytes[2],
- nano_bytes[3],
- self.second.get(),
- self.minute.get(),
- self.hour.get(),
- self.padding as u8,
- ]);
- }
-
- /// A `Time` that is exactly midnight. This is the smallest possible value for a `Time`.
- ///
- /// ```rust
- /// # use time::Time;
- /// # use time_macros::time;
- /// assert_eq!(Time::MIDNIGHT, time!(0:00));
- /// ```
- #[doc(alias = "MIN")]
- pub const MIDNIGHT: Self =
- Self::from_hms_nanos_ranged(Hours::MIN, Minutes::MIN, Seconds::MIN, Nanoseconds::MIN);
-
- /// A `Time` that is one nanosecond before midnight. This is the largest possible value for a
- /// `Time`.
- ///
- /// ```rust
- /// # use time::Time;
- /// # use time_macros::time;
- /// assert_eq!(Time::MAX, time!(23:59:59.999_999_999));
- /// ```
- pub const MAX: Self =
- Self::from_hms_nanos_ranged(Hours::MAX, Minutes::MAX, Seconds::MAX, Nanoseconds::MAX);
-
- /// Create a `Time` from its components.
- ///
- /// # Safety
- ///
- /// - `hours` must be in the range `0..=23`.
- /// - `minutes` must be in the range `0..=59`.
- /// - `seconds` must be in the range `0..=59`.
- /// - `nanoseconds` must be in the range `0..=999_999_999`.
- #[doc(hidden)]
- pub const unsafe fn __from_hms_nanos_unchecked(
- hour: u8,
- minute: u8,
- second: u8,
- nanosecond: u32,
- ) -> Self {
- // Safety: The caller must uphold the safety invariants.
- unsafe {
- Self::from_hms_nanos_ranged(
- Hours::new_unchecked(hour),
- Minutes::new_unchecked(minute),
- Seconds::new_unchecked(second),
- Nanoseconds::new_unchecked(nanosecond),
- )
- }
- }
-
- /// Attempt to create a `Time` from the hour, minute, and second.
- ///
- /// ```rust
- /// # use time::Time;
- /// assert!(Time::from_hms(1, 2, 3).is_ok());
- /// ```
- ///
- /// ```rust
- /// # use time::Time;
- /// assert!(Time::from_hms(24, 0, 0).is_err()); // 24 isn't a valid hour.
- /// assert!(Time::from_hms(0, 60, 0).is_err()); // 60 isn't a valid minute.
- /// assert!(Time::from_hms(0, 0, 60).is_err()); // 60 isn't a valid second.
- /// ```
- pub const fn from_hms(hour: u8, minute: u8, second: u8) -> Result<Self, error::ComponentRange> {
- Ok(Self::from_hms_nanos_ranged(
- ensure_ranged!(Hours: hour),
- ensure_ranged!(Minutes: minute),
- ensure_ranged!(Seconds: second),
- Nanoseconds::MIN,
- ))
- }
-
- /// Create a `Time` from the hour, minute, second, and nanosecond.
- pub(crate) const fn from_hms_nanos_ranged(
- hour: Hours,
- minute: Minutes,
- second: Seconds,
- nanosecond: Nanoseconds,
- ) -> Self {
- Self {
- hour,
- minute,
- second,
- nanosecond,
- padding: Padding::Optimize,
- }
- }
-
- /// Attempt to create a `Time` from the hour, minute, second, and millisecond.
- ///
- /// ```rust
- /// # use time::Time;
- /// assert!(Time::from_hms_milli(1, 2, 3, 4).is_ok());
- /// ```
- ///
- /// ```rust
- /// # use time::Time;
- /// assert!(Time::from_hms_milli(24, 0, 0, 0).is_err()); // 24 isn't a valid hour.
- /// assert!(Time::from_hms_milli(0, 60, 0, 0).is_err()); // 60 isn't a valid minute.
- /// assert!(Time::from_hms_milli(0, 0, 60, 0).is_err()); // 60 isn't a valid second.
- /// assert!(Time::from_hms_milli(0, 0, 0, 1_000).is_err()); // 1_000 isn't a valid millisecond.
- /// ```
- pub const fn from_hms_milli(
- hour: u8,
- minute: u8,
- second: u8,
- millisecond: u16,
- ) -> Result<Self, error::ComponentRange> {
- Ok(Self::from_hms_nanos_ranged(
- ensure_ranged!(Hours: hour),
- ensure_ranged!(Minutes: minute),
- ensure_ranged!(Seconds: second),
- ensure_ranged!(Nanoseconds: millisecond as u32 * Nanosecond::per(Millisecond)),
- ))
- }
-
- /// Attempt to create a `Time` from the hour, minute, second, and microsecond.
- ///
- /// ```rust
- /// # use time::Time;
- /// assert!(Time::from_hms_micro(1, 2, 3, 4).is_ok());
- /// ```
- ///
- /// ```rust
- /// # use time::Time;
- /// assert!(Time::from_hms_micro(24, 0, 0, 0).is_err()); // 24 isn't a valid hour.
- /// assert!(Time::from_hms_micro(0, 60, 0, 0).is_err()); // 60 isn't a valid minute.
- /// assert!(Time::from_hms_micro(0, 0, 60, 0).is_err()); // 60 isn't a valid second.
- /// assert!(Time::from_hms_micro(0, 0, 0, 1_000_000).is_err()); // 1_000_000 isn't a valid microsecond.
- /// ```
- pub const fn from_hms_micro(
- hour: u8,
- minute: u8,
- second: u8,
- microsecond: u32,
- ) -> Result<Self, error::ComponentRange> {
- Ok(Self::from_hms_nanos_ranged(
- ensure_ranged!(Hours: hour),
- ensure_ranged!(Minutes: minute),
- ensure_ranged!(Seconds: second),
- ensure_ranged!(Nanoseconds: microsecond * Nanosecond::per(Microsecond) as u32),
- ))
- }
-
- /// Attempt to create a `Time` from the hour, minute, second, and nanosecond.
- ///
- /// ```rust
- /// # use time::Time;
- /// assert!(Time::from_hms_nano(1, 2, 3, 4).is_ok());
- /// ```
- ///
- /// ```rust
- /// # use time::Time;
- /// assert!(Time::from_hms_nano(24, 0, 0, 0).is_err()); // 24 isn't a valid hour.
- /// assert!(Time::from_hms_nano(0, 60, 0, 0).is_err()); // 60 isn't a valid minute.
- /// assert!(Time::from_hms_nano(0, 0, 60, 0).is_err()); // 60 isn't a valid second.
- /// assert!(Time::from_hms_nano(0, 0, 0, 1_000_000_000).is_err()); // 1_000_000_000 isn't a valid nanosecond.
- /// ```
- pub const fn from_hms_nano(
- hour: u8,
- minute: u8,
- second: u8,
- nanosecond: u32,
- ) -> Result<Self, error::ComponentRange> {
- Ok(Self::from_hms_nanos_ranged(
- ensure_ranged!(Hours: hour),
- ensure_ranged!(Minutes: minute),
- ensure_ranged!(Seconds: second),
- ensure_ranged!(Nanoseconds: nanosecond),
- ))
- }
-
- /// Get the clock hour, minute, and second.
- ///
- /// ```rust
- /// # use time_macros::time;
- /// assert_eq!(time!(0:00:00).as_hms(), (0, 0, 0));
- /// assert_eq!(time!(23:59:59).as_hms(), (23, 59, 59));
- /// ```
- pub const fn as_hms(self) -> (u8, u8, u8) {
- (self.hour.get(), self.minute.get(), self.second.get())
- }
-
- /// Get the clock hour, minute, second, and millisecond.
- ///
- /// ```rust
- /// # use time_macros::time;
- /// assert_eq!(time!(0:00:00).as_hms_milli(), (0, 0, 0, 0));
- /// assert_eq!(time!(23:59:59.999).as_hms_milli(), (23, 59, 59, 999));
- /// ```
- pub const fn as_hms_milli(self) -> (u8, u8, u8, u16) {
- (
- self.hour.get(),
- self.minute.get(),
- self.second.get(),
- (self.nanosecond.get() / Nanosecond::per(Millisecond)) as u16,
- )
- }
-
- /// Get the clock hour, minute, second, and microsecond.
- ///
- /// ```rust
- /// # use time_macros::time;
- /// assert_eq!(time!(0:00:00).as_hms_micro(), (0, 0, 0, 0));
- /// assert_eq!(
- /// time!(23:59:59.999_999).as_hms_micro(),
- /// (23, 59, 59, 999_999)
- /// );
- /// ```
- pub const fn as_hms_micro(self) -> (u8, u8, u8, u32) {
- (
- self.hour.get(),
- self.minute.get(),
- self.second.get(),
- self.nanosecond.get() / Nanosecond::per(Microsecond) as u32,
- )
- }
-
- /// Get the clock hour, minute, second, and nanosecond.
- ///
- /// ```rust
- /// # use time_macros::time;
- /// assert_eq!(time!(0:00:00).as_hms_nano(), (0, 0, 0, 0));
- /// assert_eq!(
- /// time!(23:59:59.999_999_999).as_hms_nano(),
- /// (23, 59, 59, 999_999_999)
- /// );
- /// ```
- pub const fn as_hms_nano(self) -> (u8, u8, u8, u32) {
- (
- self.hour.get(),
- self.minute.get(),
- self.second.get(),
- self.nanosecond.get(),
- )
- }
-
- /// Get the clock hour, minute, second, and nanosecond.
- #[cfg(feature = "quickcheck")]
- pub(crate) const fn as_hms_nano_ranged(self) -> (Hours, Minutes, Seconds, Nanoseconds) {
- (self.hour, self.minute, self.second, self.nanosecond)
- }
-
- /// Get the clock hour.
- ///
- /// The returned value will always be in the range `0..24`.
- ///
- /// ```rust
- /// # use time_macros::time;
- /// assert_eq!(time!(0:00:00).hour(), 0);
- /// assert_eq!(time!(23:59:59).hour(), 23);
- /// ```
- pub const fn hour(self) -> u8 {
- self.hour.get()
- }
-
- /// Get the minute within the hour.
- ///
- /// The returned value will always be in the range `0..60`.
- ///
- /// ```rust
- /// # use time_macros::time;
- /// assert_eq!(time!(0:00:00).minute(), 0);
- /// assert_eq!(time!(23:59:59).minute(), 59);
- /// ```
- pub const fn minute(self) -> u8 {
- self.minute.get()
- }
-
- /// Get the second within the minute.
- ///
- /// The returned value will always be in the range `0..60`.
- ///
- /// ```rust
- /// # use time_macros::time;
- /// assert_eq!(time!(0:00:00).second(), 0);
- /// assert_eq!(time!(23:59:59).second(), 59);
- /// ```
- pub const fn second(self) -> u8 {
- self.second.get()
- }
-
- /// Get the milliseconds within the second.
- ///
- /// The returned value will always be in the range `0..1_000`.
- ///
- /// ```rust
- /// # use time_macros::time;
- /// assert_eq!(time!(0:00).millisecond(), 0);
- /// assert_eq!(time!(23:59:59.999).millisecond(), 999);
- /// ```
- pub const fn millisecond(self) -> u16 {
- (self.nanosecond.get() / Nanosecond::per(Millisecond)) as u16
- }
-
- /// Get the microseconds within the second.
- ///
- /// The returned value will always be in the range `0..1_000_000`.
- ///
- /// ```rust
- /// # use time_macros::time;
- /// assert_eq!(time!(0:00).microsecond(), 0);
- /// assert_eq!(time!(23:59:59.999_999).microsecond(), 999_999);
- /// ```
- pub const fn microsecond(self) -> u32 {
- self.nanosecond.get() / Nanosecond::per(Microsecond) as u32
- }
-
- /// Get the nanoseconds within the second.
- ///
- /// The returned value will always be in the range `0..1_000_000_000`.
- ///
- /// ```rust
- /// # use time_macros::time;
- /// assert_eq!(time!(0:00).nanosecond(), 0);
- /// assert_eq!(time!(23:59:59.999_999_999).nanosecond(), 999_999_999);
- /// ```
- pub const fn nanosecond(self) -> u32 {
- self.nanosecond.get()
- }
-
- /// Add the sub-day time of the [`Duration`] to the `Time`. Wraps on overflow, returning whether
- /// the date is different.
- pub(crate) const fn adjusting_add(self, duration: Duration) -> (DateAdjustment, Self) {
- let mut nanoseconds = self.nanosecond.get() as i32 + duration.subsec_nanoseconds();
- let mut seconds =
- self.second.get() as i8 + (duration.whole_seconds() % Second::per(Minute) as i64) as i8;
- let mut minutes =
- self.minute.get() as i8 + (duration.whole_minutes() % Minute::per(Hour) as i64) as i8;
- let mut hours =
- self.hour.get() as i8 + (duration.whole_hours() % Hour::per(Day) as i64) as i8;
- let mut date_adjustment = DateAdjustment::None;
-
- cascade!(nanoseconds in 0..Nanosecond::per(Second) as i32 => seconds);
- cascade!(seconds in 0..Second::per(Minute) as i8 => minutes);
- cascade!(minutes in 0..Minute::per(Hour) as i8 => hours);
- if hours >= Hour::per(Day) as i8 {
- hours -= Hour::per(Day) as i8;
- date_adjustment = DateAdjustment::Next;
- } else if hours < 0 {
- hours += Hour::per(Day) as i8;
- date_adjustment = DateAdjustment::Previous;
- }
-
- (
- date_adjustment,
- // Safety: The cascades above ensure the values are in range.
- unsafe {
- Self::__from_hms_nanos_unchecked(
- hours as u8,
- minutes as u8,
- seconds as u8,
- nanoseconds as u32,
- )
- },
- )
- }
-
- /// Subtract the sub-day time of the [`Duration`] to the `Time`. Wraps on overflow, returning
- /// whether the date is different.
- pub(crate) const fn adjusting_sub(self, duration: Duration) -> (DateAdjustment, Self) {
- let mut nanoseconds = self.nanosecond.get() as i32 - duration.subsec_nanoseconds();
- let mut seconds =
- self.second.get() as i8 - (duration.whole_seconds() % Second::per(Minute) as i64) as i8;
- let mut minutes =
- self.minute.get() as i8 - (duration.whole_minutes() % Minute::per(Hour) as i64) as i8;
- let mut hours =
- self.hour.get() as i8 - (duration.whole_hours() % Hour::per(Day) as i64) as i8;
- let mut date_adjustment = DateAdjustment::None;
-
- cascade!(nanoseconds in 0..Nanosecond::per(Second) as i32 => seconds);
- cascade!(seconds in 0..Second::per(Minute) as i8 => minutes);
- cascade!(minutes in 0..Minute::per(Hour) as i8 => hours);
- if hours >= Hour::per(Day) as i8 {
- hours -= Hour::per(Day) as i8;
- date_adjustment = DateAdjustment::Next;
- } else if hours < 0 {
- hours += Hour::per(Day) as i8;
- date_adjustment = DateAdjustment::Previous;
- }
-
- (
- date_adjustment,
- // Safety: The cascades above ensure the values are in range.
- unsafe {
- Self::__from_hms_nanos_unchecked(
- hours as u8,
- minutes as u8,
- seconds as u8,
- nanoseconds as u32,
- )
- },
- )
- }
-
- /// Add the sub-day time of the [`std::time::Duration`] to the `Time`. Wraps on overflow,
- /// returning whether the date is the previous date as the first element of the tuple.
- pub(crate) const fn adjusting_add_std(self, duration: StdDuration) -> (bool, Self) {
- let mut nanosecond = self.nanosecond.get() + duration.subsec_nanos();
- let mut second =
- self.second.get() + (duration.as_secs() % Second::per(Minute) as u64) as u8;
- let mut minute = self.minute.get()
- + ((duration.as_secs() / Second::per(Minute) as u64) % Minute::per(Hour) as u64) as u8;
- let mut hour = self.hour.get()
- + ((duration.as_secs() / Second::per(Hour) as u64) % Hour::per(Day) as u64) as u8;
- let mut is_next_day = false;
-
- cascade!(nanosecond in 0..Nanosecond::per(Second) => second);
- cascade!(second in 0..Second::per(Minute) => minute);
- cascade!(minute in 0..Minute::per(Hour) => hour);
- if hour >= Hour::per(Day) {
- hour -= Hour::per(Day);
- is_next_day = true;
- }
-
- (
- is_next_day,
- // Safety: The cascades above ensure the values are in range.
- unsafe { Self::__from_hms_nanos_unchecked(hour, minute, second, nanosecond) },
- )
- }
-
- /// Subtract the sub-day time of the [`std::time::Duration`] to the `Time`. Wraps on overflow,
- /// returning whether the date is the previous date as the first element of the tuple.
- pub(crate) const fn adjusting_sub_std(self, duration: StdDuration) -> (bool, Self) {
- let mut nanosecond = self.nanosecond.get() as i32 - duration.subsec_nanos() as i32;
- let mut second =
- self.second.get() as i8 - (duration.as_secs() % Second::per(Minute) as u64) as i8;
- let mut minute = self.minute.get() as i8
- - ((duration.as_secs() / Second::per(Minute) as u64) % Minute::per(Hour) as u64) as i8;
- let mut hour = self.hour.get() as i8
- - ((duration.as_secs() / Second::per(Hour) as u64) % Hour::per(Day) as u64) as i8;
- let mut is_previous_day = false;
-
- cascade!(nanosecond in 0..Nanosecond::per(Second) as i32 => second);
- cascade!(second in 0..Second::per(Minute) as i8 => minute);
- cascade!(minute in 0..Minute::per(Hour) as i8 => hour);
- if hour < 0 {
- hour += Hour::per(Day) as i8;
- is_previous_day = true;
- }
-
- (
- is_previous_day,
- // Safety: The cascades above ensure the values are in range.
- unsafe {
- Self::__from_hms_nanos_unchecked(
- hour as u8,
- minute as u8,
- second as u8,
- nanosecond as u32,
- )
- },
- )
- }
-
- /// Replace the clock hour.
- ///
- /// ```rust
- /// # use time_macros::time;
- /// assert_eq!(
- /// time!(01:02:03.004_005_006).replace_hour(7),
- /// Ok(time!(07:02:03.004_005_006))
- /// );
- /// assert!(time!(01:02:03.004_005_006).replace_hour(24).is_err()); // 24 isn't a valid hour
- /// ```
- #[must_use = "This method does not mutate the original `Time`."]
- pub const fn replace_hour(mut self, hour: u8) -> Result<Self, error::ComponentRange> {
- self.hour = ensure_ranged!(Hours: hour);
- Ok(self)
- }
-
- /// Replace the minutes within the hour.
- ///
- /// ```rust
- /// # use time_macros::time;
- /// assert_eq!(
- /// time!(01:02:03.004_005_006).replace_minute(7),
- /// Ok(time!(01:07:03.004_005_006))
- /// );
- /// assert!(time!(01:02:03.004_005_006).replace_minute(60).is_err()); // 60 isn't a valid minute
- /// ```
- #[must_use = "This method does not mutate the original `Time`."]
- pub const fn replace_minute(mut self, minute: u8) -> Result<Self, error::ComponentRange> {
- self.minute = ensure_ranged!(Minutes: minute);
- Ok(self)
- }
-
- /// Replace the seconds within the minute.
- ///
- /// ```rust
- /// # use time_macros::time;
- /// assert_eq!(
- /// time!(01:02:03.004_005_006).replace_second(7),
- /// Ok(time!(01:02:07.004_005_006))
- /// );
- /// assert!(time!(01:02:03.004_005_006).replace_second(60).is_err()); // 60 isn't a valid second
- /// ```
- #[must_use = "This method does not mutate the original `Time`."]
- pub const fn replace_second(mut self, second: u8) -> Result<Self, error::ComponentRange> {
- self.second = ensure_ranged!(Seconds: second);
- Ok(self)
- }
-
- /// Replace the milliseconds within the second.
- ///
- /// ```rust
- /// # use time_macros::time;
- /// assert_eq!(
- /// time!(01:02:03.004_005_006).replace_millisecond(7),
- /// Ok(time!(01:02:03.007))
- /// );
- /// assert!(time!(01:02:03.004_005_006)
- /// .replace_millisecond(1_000)
- /// .is_err()); // 1_000 isn't a valid millisecond
- /// ```
- #[must_use = "This method does not mutate the original `Time`."]
- pub const fn replace_millisecond(
- mut self,
- millisecond: u16,
- ) -> Result<Self, error::ComponentRange> {
- self.nanosecond =
- ensure_ranged!(Nanoseconds: millisecond as u32 * Nanosecond::per(Millisecond));
- Ok(self)
- }
-
- /// Replace the microseconds within the second.
- ///
- /// ```rust
- /// # use time_macros::time;
- /// assert_eq!(
- /// time!(01:02:03.004_005_006).replace_microsecond(7_008),
- /// Ok(time!(01:02:03.007_008))
- /// );
- /// assert!(time!(01:02:03.004_005_006)
- /// .replace_microsecond(1_000_000)
- /// .is_err()); // 1_000_000 isn't a valid microsecond
- /// ```
- #[must_use = "This method does not mutate the original `Time`."]
- pub const fn replace_microsecond(
- mut self,
- microsecond: u32,
- ) -> Result<Self, error::ComponentRange> {
- self.nanosecond =
- ensure_ranged!(Nanoseconds: microsecond * Nanosecond::per(Microsecond) as u32);
- Ok(self)
- }
-
- /// Replace the nanoseconds within the second.
- ///
- /// ```rust
- /// # use time_macros::time;
- /// assert_eq!(
- /// time!(01:02:03.004_005_006).replace_nanosecond(7_008_009),
- /// Ok(time!(01:02:03.007_008_009))
- /// );
- /// assert!(time!(01:02:03.004_005_006)
- /// .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 `Time`."]
- pub const fn replace_nanosecond(
- mut self,
- nanosecond: u32,
- ) -> Result<Self, error::ComponentRange> {
- self.nanosecond = ensure_ranged!(Nanoseconds: nanosecond);
- Ok(self)
- }
-}
-
-#[cfg(feature = "formatting")]
-impl Time {
- /// Format the `Time` using the provided [format description](crate::format_description).
- pub fn format_into(
- self,
- output: &mut (impl io::Write + ?Sized),
- format: &(impl Formattable + ?Sized),
- ) -> Result<usize, error::Format> {
- format.format_into(output, None, Some(self), None)
- }
-
- /// Format the `Time` using the provided [format description](crate::format_description).
- ///
- /// ```rust
- /// # use time::format_description;
- /// # use time_macros::time;
- /// let format = format_description::parse("[hour]:[minute]:[second]")?;
- /// assert_eq!(time!(12:00).format(&format)?, "12:00:00");
- /// # Ok::<_, time::Error>(())
- /// ```
- pub fn format(self, format: &(impl Formattable + ?Sized)) -> Result<String, error::Format> {
- format.format(None, Some(self), None)
- }
-}
-
-#[cfg(feature = "parsing")]
-impl Time {
- /// Parse a `Time` from the input using the provided [format
- /// description](crate::format_description).
- ///
- /// ```rust
- /// # use time::Time;
- /// # use time_macros::{time, format_description};
- /// let format = format_description!("[hour]:[minute]:[second]");
- /// assert_eq!(Time::parse("12:00:00", &format)?, time!(12:00));
- /// # Ok::<_, time::Error>(())
- /// ```
- pub fn parse(
- input: &str,
- description: &(impl Parsable + ?Sized),
- ) -> Result<Self, error::Parse> {
- description.parse_time(input.as_bytes())
- }
-}
-
-mod private {
- #[non_exhaustive]
- #[derive(Debug, Clone, Copy)]
- pub struct TimeMetadata {
- /// How many characters wide the formatted subsecond is.
- pub(super) subsecond_width: u8,
- /// The value to use when formatting the subsecond. Leading zeroes will be added as
- /// necessary.
- pub(super) subsecond_value: u32,
- }
-}
-use private::TimeMetadata;
-
-impl SmartDisplay for Time {
- type Metadata = TimeMetadata;
-
- fn metadata(&self, _: FormatterOptions) -> Metadata<Self> {
- let (subsecond_value, subsecond_width) = match self.nanosecond() {
- nanos if nanos % 10 != 0 => (nanos, 9),
- nanos if (nanos / 10) % 10 != 0 => (nanos / 10, 8),
- nanos if (nanos / 100) % 10 != 0 => (nanos / 100, 7),
- nanos if (nanos / 1_000) % 10 != 0 => (nanos / 1_000, 6),
- nanos if (nanos / 10_000) % 10 != 0 => (nanos / 10_000, 5),
- nanos if (nanos / 100_000) % 10 != 0 => (nanos / 100_000, 4),
- nanos if (nanos / 1_000_000) % 10 != 0 => (nanos / 1_000_000, 3),
- nanos if (nanos / 10_000_000) % 10 != 0 => (nanos / 10_000_000, 2),
- nanos => (nanos / 100_000_000, 1),
- };
-
- let formatted_width = smart_display::padded_width_of!(
- self.hour.get(),
- ":",
- self.minute.get() => width(2) fill('0'),
- ":",
- self.second.get() => width(2) fill('0'),
- ".",
- ) + subsecond_width;
-
- Metadata::new(
- formatted_width,
- self,
- TimeMetadata {
- subsecond_width: subsecond_width.truncate(),
- subsecond_value,
- },
- )
- }
-
- fn fmt_with_metadata(
- &self,
- f: &mut fmt::Formatter<'_>,
- metadata: Metadata<Self>,
- ) -> fmt::Result {
- let subsecond_width = metadata.subsecond_width.extend();
- let subsecond_value = metadata.subsecond_value;
-
- f.pad_with_width(
- metadata.unpadded_width(),
- format_args!(
- "{}:{:02}:{:02}.{subsecond_value:0subsecond_width$}",
- self.hour, self.minute, self.second
- ),
- )
- }
-}
-
-impl fmt::Display for Time {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- SmartDisplay::fmt(self, f)
- }
-}
-
-impl fmt::Debug for Time {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- fmt::Display::fmt(self, f)
- }
-}
-
-impl Add<Duration> for Time {
- type Output = Self;
-
- /// Add the sub-day time of the [`Duration`] to the `Time`. Wraps on overflow.
- ///
- /// ```rust
- /// # use time::ext::NumericalDuration;
- /// # use time_macros::time;
- /// assert_eq!(time!(12:00) + 2.hours(), time!(14:00));
- /// assert_eq!(time!(0:00:01) + (-2).seconds(), time!(23:59:59));
- /// ```
- fn add(self, duration: Duration) -> Self::Output {
- self.adjusting_add(duration).1
- }
-}
-
-impl Add<StdDuration> for Time {
- type Output = Self;
-
- /// Add the sub-day time of the [`std::time::Duration`] to the `Time`. Wraps on overflow.
- ///
- /// ```rust
- /// # use time::ext::NumericalStdDuration;
- /// # use time_macros::time;
- /// assert_eq!(time!(12:00) + 2.std_hours(), time!(14:00));
- /// assert_eq!(time!(23:59:59) + 2.std_seconds(), time!(0:00:01));
- /// ```
- fn add(self, duration: StdDuration) -> Self::Output {
- self.adjusting_add_std(duration).1
- }
-}
-
-impl_add_assign!(Time: Duration, StdDuration);
-
-impl Sub<Duration> for Time {
- type Output = Self;
-
- /// Subtract the sub-day time of the [`Duration`] from the `Time`. Wraps on overflow.
- ///
- /// ```rust
- /// # use time::ext::NumericalDuration;
- /// # use time_macros::time;
- /// assert_eq!(time!(14:00) - 2.hours(), time!(12:00));
- /// assert_eq!(time!(23:59:59) - (-2).seconds(), time!(0:00:01));
- /// ```
- fn sub(self, duration: Duration) -> Self::Output {
- self.adjusting_sub(duration).1
- }
-}
-
-impl Sub<StdDuration> for Time {
- type Output = Self;
-
- /// Subtract the sub-day time of the [`std::time::Duration`] from the `Time`. Wraps on overflow.
- ///
- /// ```rust
- /// # use time::ext::NumericalStdDuration;
- /// # use time_macros::time;
- /// assert_eq!(time!(14:00) - 2.std_hours(), time!(12:00));
- /// assert_eq!(time!(0:00:01) - 2.std_seconds(), time!(23:59:59));
- /// ```
- fn sub(self, duration: StdDuration) -> Self::Output {
- self.adjusting_sub_std(duration).1
- }
-}
-
-impl_sub_assign!(Time: Duration, StdDuration);
-
-impl Sub for Time {
- type Output = Duration;
-
- /// Subtract two `Time`s, returning the [`Duration`] between. This assumes both `Time`s are in
- /// the same calendar day.
- ///
- /// ```rust
- /// # use time::ext::NumericalDuration;
- /// # use time_macros::time;
- /// assert_eq!(time!(0:00) - time!(0:00), 0.seconds());
- /// assert_eq!(time!(1:00) - time!(0:00), 1.hours());
- /// assert_eq!(time!(0:00) - time!(1:00), (-1).hours());
- /// assert_eq!(time!(0:00) - time!(23:00), (-23).hours());
- /// ```
- fn sub(self, rhs: Self) -> Self::Output {
- 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.extend::<i64>() * Second::per(Hour).cast_signed().extend::<i64>()
- + minute_diff.extend::<i64>() * Second::per(Minute).cast_signed().extend::<i64>()
- + second_diff.extend::<i64>();
-
- let (seconds, nanoseconds) = if seconds > 0 && nanosecond_diff < 0 {
- (
- seconds - 1,
- nanosecond_diff + Nanosecond::per(Second).cast_signed(),
- )
- } else if seconds < 0 && nanosecond_diff > 0 {
- (
- seconds + 1,
- nanosecond_diff - Nanosecond::per(Second).cast_signed(),
- )
- } else {
- (seconds, nanosecond_diff)
- };
-
- // Safety: `nanoseconds` is in range due to the overflow handling.
- unsafe { Duration::new_unchecked(seconds, nanoseconds) }
- }
-}