/rust/registry/src/index.crates.io-1949cf8c6b5b557f/time-0.3.55/src/time.rs
Line | Count | Source |
1 | | //! The [`Time`] struct and its associated `impl`s. |
2 | | |
3 | | #[cfg(feature = "formatting")] |
4 | | use alloc::string::String; |
5 | | use core::cmp::Ordering; |
6 | | use core::hash::{Hash, Hasher}; |
7 | | use core::mem::MaybeUninit; |
8 | | use core::ops::{Add, AddAssign, Sub, SubAssign}; |
9 | | use core::time::Duration as StdDuration; |
10 | | use core::{fmt, hint}; |
11 | | #[cfg(feature = "formatting")] |
12 | | use std::io; |
13 | | |
14 | | use deranged::{ru8, ru32}; |
15 | | use num_conv::prelude::*; |
16 | | use powerfmt::smart_display::{FormatterOptions, Metadata, SmartDisplay}; |
17 | | |
18 | | #[cfg(any(feature = "formatting", feature = "parsing"))] |
19 | | use crate::PrivateMethod; |
20 | | #[cfg(feature = "formatting")] |
21 | | use crate::formatting::Formattable; |
22 | | use crate::internal_macros::{cascade, ensure_ranged}; |
23 | | use crate::num_fmt::{ |
24 | | one_to_two_digits_no_padding, str_from_raw_parts, truncated_subsecond_from_nanos, |
25 | | two_digits_zero_padded, |
26 | | }; |
27 | | #[cfg(feature = "parsing")] |
28 | | use crate::parsing::{Parsable, Parsed}; |
29 | | use crate::unit::*; |
30 | | use crate::util::DateAdjustment; |
31 | | use crate::{SignedDuration, error}; |
32 | | |
33 | | /// By explicitly inserting this enum where padding is expected, the compiler is able to better |
34 | | /// perform niche value optimization. |
35 | | #[repr(u8)] |
36 | | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] |
37 | | pub(crate) enum Padding { |
38 | | #[allow(clippy::missing_docs_in_private_items)] |
39 | | Optimize, |
40 | | } |
41 | | |
42 | | /// The type of the `hour` field of `Time`. |
43 | | pub(crate) type Hours = ru8<0, { Hour::per_t::<u8>(Day) - 1 }>; |
44 | | /// The type of the `minute` field of `Time`. |
45 | | pub(crate) type Minutes = ru8<0, { Minute::per_t::<u8>(Hour) - 1 }>; |
46 | | /// The type of the `second` field of `Time`. |
47 | | pub(crate) type Seconds = ru8<0, { Second::per_t::<u8>(Minute) - 1 }>; |
48 | | /// The type of the `nanosecond` field of `Time`. |
49 | | pub(crate) type Nanoseconds = ru32<0, { Nanosecond::per_t::<u32>(Second) - 1 }>; |
50 | | |
51 | | /// The clock time within a given date. Nanosecond precision. |
52 | | /// |
53 | | /// All minutes are assumed to have exactly 60 seconds; no attempt is made to handle leap seconds |
54 | | /// (either positive or negative). |
55 | | /// |
56 | | /// When comparing two `Time`s, they are assumed to be in the same calendar date. |
57 | | #[derive(Clone, Copy, Eq)] |
58 | | #[cfg_attr(not(docsrs), repr(C))] |
59 | | pub struct Time { |
60 | | // The order of this struct's fields matter! Do not reorder them. |
61 | | |
62 | | // Little endian version |
63 | | #[cfg(target_endian = "little")] |
64 | | nanosecond: Nanoseconds, |
65 | | #[cfg(target_endian = "little")] |
66 | | second: Seconds, |
67 | | #[cfg(target_endian = "little")] |
68 | | minute: Minutes, |
69 | | #[cfg(target_endian = "little")] |
70 | | hour: Hours, |
71 | | #[cfg(target_endian = "little")] |
72 | | padding: Padding, |
73 | | |
74 | | // Big endian version |
75 | | #[cfg(target_endian = "big")] |
76 | | padding: Padding, |
77 | | #[cfg(target_endian = "big")] |
78 | | hour: Hours, |
79 | | #[cfg(target_endian = "big")] |
80 | | minute: Minutes, |
81 | | #[cfg(target_endian = "big")] |
82 | | second: Seconds, |
83 | | #[cfg(target_endian = "big")] |
84 | | nanosecond: Nanoseconds, |
85 | | } |
86 | | |
87 | | impl Hash for Time { |
88 | | #[inline] |
89 | 0 | fn hash<H>(&self, state: &mut H) |
90 | 0 | where |
91 | 0 | H: Hasher, |
92 | | { |
93 | 0 | self.as_u64().hash(state) |
94 | 0 | } |
95 | | } |
96 | | |
97 | | impl PartialEq for Time { |
98 | | #[inline] |
99 | 0 | fn eq(&self, other: &Self) -> bool { |
100 | 0 | self.as_u64().eq(&other.as_u64()) |
101 | 0 | } |
102 | | } |
103 | | |
104 | | impl PartialOrd for Time { |
105 | | #[inline] |
106 | 0 | fn partial_cmp(&self, other: &Self) -> Option<Ordering> { |
107 | 0 | Some(self.cmp(other)) |
108 | 0 | } |
109 | | } |
110 | | |
111 | | impl Ord for Time { |
112 | | #[inline] |
113 | 0 | fn cmp(&self, other: &Self) -> Ordering { |
114 | 0 | self.as_u64().cmp(&other.as_u64()) |
115 | 0 | } |
116 | | } |
117 | | |
118 | | impl Time { |
119 | | /// Provide a representation of `Time` as a `u64`. This value can be used for equality, hashing, |
120 | | /// and ordering. |
121 | | #[inline] |
122 | 0 | pub(crate) const fn as_u64(self) -> u64 { |
123 | | // Safety: `self` is presumed valid because it exists, and any value of `u64` is valid. Size |
124 | | // and alignment are enforced by the compiler. There is no implicit padding in either `Time` |
125 | | // or `u64`. |
126 | 0 | unsafe { core::mem::transmute(self) } |
127 | 0 | } |
128 | | |
129 | | /// A `Time` that is exactly midnight. This is the smallest possible value for a `Time`. |
130 | | /// |
131 | | /// ```rust |
132 | | /// # use time::Time; |
133 | | /// # use time_macros::time; |
134 | | /// assert_eq!(Time::MIDNIGHT, time!(0:00)); |
135 | | /// ``` |
136 | | #[doc(alias = "MIN")] |
137 | | pub const MIDNIGHT: Self = |
138 | | Self::from_hms_nanos_ranged(Hours::MIN, Minutes::MIN, Seconds::MIN, Nanoseconds::MIN); |
139 | | |
140 | | /// A `Time` that is one nanosecond before midnight. This is the largest possible value for a |
141 | | /// `Time`. |
142 | | /// |
143 | | /// ```rust |
144 | | /// # use time::Time; |
145 | | /// # use time_macros::time; |
146 | | /// assert_eq!(Time::MAX, time!(23:59:59.999_999_999)); |
147 | | /// ``` |
148 | | pub const MAX: Self = |
149 | | Self::from_hms_nanos_ranged(Hours::MAX, Minutes::MAX, Seconds::MAX, Nanoseconds::MAX); |
150 | | |
151 | | /// Create a `Time` from its components. |
152 | | /// |
153 | | /// # Safety |
154 | | /// |
155 | | /// - `hours` must be in the range `0..=23`. |
156 | | /// - `minutes` must be in the range `0..=59`. |
157 | | /// - `seconds` must be in the range `0..=59`. |
158 | | /// - `nanoseconds` must be in the range `0..=999_999_999`. |
159 | | #[doc(hidden)] |
160 | | #[inline] |
161 | | #[track_caller] |
162 | 85.8k | pub const unsafe fn __from_hms_nanos_unchecked( |
163 | 85.8k | hour: u8, |
164 | 85.8k | minute: u8, |
165 | 85.8k | second: u8, |
166 | 85.8k | nanosecond: u32, |
167 | 85.8k | ) -> Self { |
168 | | // Safety: The caller must uphold the safety invariants. |
169 | | unsafe { |
170 | 85.8k | Self::from_hms_nanos_ranged( |
171 | 85.8k | Hours::new_unchecked(hour), |
172 | 85.8k | Minutes::new_unchecked(minute), |
173 | 85.8k | Seconds::new_unchecked(second), |
174 | 85.8k | Nanoseconds::new_unchecked(nanosecond), |
175 | | ) |
176 | | } |
177 | 85.8k | } <time::time::Time>::__from_hms_nanos_unchecked Line | Count | Source | 162 | 85.8k | pub const unsafe fn __from_hms_nanos_unchecked( | 163 | 85.8k | hour: u8, | 164 | 85.8k | minute: u8, | 165 | 85.8k | second: u8, | 166 | 85.8k | nanosecond: u32, | 167 | 85.8k | ) -> Self { | 168 | | // Safety: The caller must uphold the safety invariants. | 169 | | unsafe { | 170 | 85.8k | Self::from_hms_nanos_ranged( | 171 | 85.8k | Hours::new_unchecked(hour), | 172 | 85.8k | Minutes::new_unchecked(minute), | 173 | 85.8k | Seconds::new_unchecked(second), | 174 | 85.8k | Nanoseconds::new_unchecked(nanosecond), | 175 | | ) | 176 | | } | 177 | 85.8k | } |
Unexecuted instantiation: <time::time::Time>::__from_hms_nanos_unchecked |
178 | | |
179 | | /// Attempt to create a `Time` from the hour, minute, and second. |
180 | | /// |
181 | | /// ```rust |
182 | | /// # use time::Time; |
183 | | /// assert!(Time::from_hms(1, 2, 3).is_ok()); |
184 | | /// ``` |
185 | | /// |
186 | | /// ```rust |
187 | | /// # use time::Time; |
188 | | /// assert!(Time::from_hms(24, 0, 0).is_err()); // 24 isn't a valid hour. |
189 | | /// assert!(Time::from_hms(0, 60, 0).is_err()); // 60 isn't a valid minute. |
190 | | /// assert!(Time::from_hms(0, 0, 60).is_err()); // 60 isn't a valid second. |
191 | | /// ``` |
192 | | #[inline] |
193 | 0 | pub const fn from_hms(hour: u8, minute: u8, second: u8) -> Result<Self, error::ComponentRange> { |
194 | 0 | Ok(Self::from_hms_nanos_ranged( |
195 | 0 | ensure_ranged!(Hours: hour), |
196 | 0 | ensure_ranged!(Minutes: minute), |
197 | 0 | ensure_ranged!(Seconds: second), |
198 | | Nanoseconds::MIN, |
199 | | )) |
200 | 0 | } Unexecuted instantiation: <time::time::Time>::from_hms Unexecuted instantiation: <time::time::Time>::from_hms |
201 | | |
202 | | /// Create a `Time` from the hour, minute, second, and nanosecond. |
203 | | #[inline] |
204 | 85.8k | pub(crate) const fn from_hms_nanos_ranged( |
205 | 85.8k | hour: Hours, |
206 | 85.8k | minute: Minutes, |
207 | 85.8k | second: Seconds, |
208 | 85.8k | nanosecond: Nanoseconds, |
209 | 85.8k | ) -> Self { |
210 | 85.8k | Self { |
211 | 85.8k | hour, |
212 | 85.8k | minute, |
213 | 85.8k | second, |
214 | 85.8k | nanosecond, |
215 | 85.8k | padding: Padding::Optimize, |
216 | 85.8k | } |
217 | 85.8k | } <time::time::Time>::from_hms_nanos_ranged Line | Count | Source | 204 | 85.8k | pub(crate) const fn from_hms_nanos_ranged( | 205 | 85.8k | hour: Hours, | 206 | 85.8k | minute: Minutes, | 207 | 85.8k | second: Seconds, | 208 | 85.8k | nanosecond: Nanoseconds, | 209 | 85.8k | ) -> Self { | 210 | 85.8k | Self { | 211 | 85.8k | hour, | 212 | 85.8k | minute, | 213 | 85.8k | second, | 214 | 85.8k | nanosecond, | 215 | 85.8k | padding: Padding::Optimize, | 216 | 85.8k | } | 217 | 85.8k | } |
Unexecuted instantiation: <time::time::Time>::from_hms_nanos_ranged |
218 | | |
219 | | /// Attempt to create a `Time` from the hour, minute, second, and millisecond. |
220 | | /// |
221 | | /// ```rust |
222 | | /// # use time::Time; |
223 | | /// assert!(Time::from_hms_milli(1, 2, 3, 4).is_ok()); |
224 | | /// ``` |
225 | | /// |
226 | | /// ```rust |
227 | | /// # use time::Time; |
228 | | /// assert!(Time::from_hms_milli(24, 0, 0, 0).is_err()); // 24 isn't a valid hour. |
229 | | /// assert!(Time::from_hms_milli(0, 60, 0, 0).is_err()); // 60 isn't a valid minute. |
230 | | /// assert!(Time::from_hms_milli(0, 0, 60, 0).is_err()); // 60 isn't a valid second. |
231 | | /// assert!(Time::from_hms_milli(0, 0, 0, 1_000).is_err()); // 1_000 isn't a valid millisecond. |
232 | | /// ``` |
233 | | #[inline] |
234 | 0 | pub const fn from_hms_milli( |
235 | 0 | hour: u8, |
236 | 0 | minute: u8, |
237 | 0 | second: u8, |
238 | 0 | millisecond: u16, |
239 | 0 | ) -> Result<Self, error::ComponentRange> { |
240 | 0 | Ok(Self::from_hms_nanos_ranged( |
241 | 0 | ensure_ranged!(Hours: hour), |
242 | 0 | ensure_ranged!(Minutes: minute), |
243 | 0 | ensure_ranged!(Seconds: second), |
244 | 0 | ensure_ranged!(Nanoseconds: millisecond as u32 * Nanosecond::per_t::<u32>(Millisecond)), |
245 | | )) |
246 | 0 | } |
247 | | |
248 | | /// Attempt to create a `Time` from the hour, minute, second, and microsecond. |
249 | | /// |
250 | | /// ```rust |
251 | | /// # use time::Time; |
252 | | /// assert!(Time::from_hms_micro(1, 2, 3, 4).is_ok()); |
253 | | /// ``` |
254 | | /// |
255 | | /// ```rust |
256 | | /// # use time::Time; |
257 | | /// assert!(Time::from_hms_micro(24, 0, 0, 0).is_err()); // 24 isn't a valid hour. |
258 | | /// assert!(Time::from_hms_micro(0, 60, 0, 0).is_err()); // 60 isn't a valid minute. |
259 | | /// assert!(Time::from_hms_micro(0, 0, 60, 0).is_err()); // 60 isn't a valid second. |
260 | | /// assert!(Time::from_hms_micro(0, 0, 0, 1_000_000).is_err()); // 1_000_000 isn't a valid microsecond. |
261 | | /// ``` |
262 | | #[inline] |
263 | 0 | pub const fn from_hms_micro( |
264 | 0 | hour: u8, |
265 | 0 | minute: u8, |
266 | 0 | second: u8, |
267 | 0 | microsecond: u32, |
268 | 0 | ) -> Result<Self, error::ComponentRange> { |
269 | 0 | Ok(Self::from_hms_nanos_ranged( |
270 | 0 | ensure_ranged!(Hours: hour), |
271 | 0 | ensure_ranged!(Minutes: minute), |
272 | 0 | ensure_ranged!(Seconds: second), |
273 | 0 | ensure_ranged!(Nanoseconds: microsecond * Nanosecond::per_t::<u32>(Microsecond)), |
274 | | )) |
275 | 0 | } |
276 | | |
277 | | /// Attempt to create a `Time` from the hour, minute, second, and nanosecond. |
278 | | /// |
279 | | /// ```rust |
280 | | /// # use time::Time; |
281 | | /// assert!(Time::from_hms_nano(1, 2, 3, 4).is_ok()); |
282 | | /// ``` |
283 | | /// |
284 | | /// ```rust |
285 | | /// # use time::Time; |
286 | | /// assert!(Time::from_hms_nano(24, 0, 0, 0).is_err()); // 24 isn't a valid hour. |
287 | | /// assert!(Time::from_hms_nano(0, 60, 0, 0).is_err()); // 60 isn't a valid minute. |
288 | | /// assert!(Time::from_hms_nano(0, 0, 60, 0).is_err()); // 60 isn't a valid second. |
289 | | /// assert!(Time::from_hms_nano(0, 0, 0, 1_000_000_000).is_err()); // 1_000_000_000 isn't a valid nanosecond. |
290 | | /// ``` |
291 | | #[inline] |
292 | 0 | pub const fn from_hms_nano( |
293 | 0 | hour: u8, |
294 | 0 | minute: u8, |
295 | 0 | second: u8, |
296 | 0 | nanosecond: u32, |
297 | 0 | ) -> Result<Self, error::ComponentRange> { |
298 | 0 | Ok(Self::from_hms_nanos_ranged( |
299 | 0 | ensure_ranged!(Hours: hour), |
300 | 0 | ensure_ranged!(Minutes: minute), |
301 | 0 | ensure_ranged!(Seconds: second), |
302 | 0 | ensure_ranged!(Nanoseconds: nanosecond), |
303 | | )) |
304 | 0 | } |
305 | | |
306 | | /// Get the clock hour, minute, and second. |
307 | | /// |
308 | | /// ```rust |
309 | | /// # use time_macros::time; |
310 | | /// assert_eq!(time!(0:00:00).as_hms(), (0, 0, 0)); |
311 | | /// assert_eq!(time!(23:59:59).as_hms(), (23, 59, 59)); |
312 | | /// ``` |
313 | | #[inline] |
314 | 0 | pub const fn as_hms(self) -> (u8, u8, u8) { |
315 | 0 | (self.hour.get(), self.minute.get(), self.second.get()) |
316 | 0 | } |
317 | | |
318 | | /// Get the clock hour, minute, second, and millisecond. |
319 | | /// |
320 | | /// ```rust |
321 | | /// # use time_macros::time; |
322 | | /// assert_eq!(time!(0:00:00).as_hms_milli(), (0, 0, 0, 0)); |
323 | | /// assert_eq!(time!(23:59:59.999).as_hms_milli(), (23, 59, 59, 999)); |
324 | | /// ``` |
325 | | #[inline] |
326 | 0 | pub const fn as_hms_milli(self) -> (u8, u8, u8, u16) { |
327 | 0 | ( |
328 | 0 | self.hour.get(), |
329 | 0 | self.minute.get(), |
330 | 0 | self.second.get(), |
331 | 0 | (self.nanosecond.get() / Nanosecond::per_t::<u32>(Millisecond)) as u16, |
332 | 0 | ) |
333 | 0 | } |
334 | | |
335 | | /// Get the clock hour, minute, second, and microsecond. |
336 | | /// |
337 | | /// ```rust |
338 | | /// # use time_macros::time; |
339 | | /// assert_eq!(time!(0:00:00).as_hms_micro(), (0, 0, 0, 0)); |
340 | | /// assert_eq!( |
341 | | /// time!(23:59:59.999_999).as_hms_micro(), |
342 | | /// (23, 59, 59, 999_999) |
343 | | /// ); |
344 | | /// ``` |
345 | | #[inline] |
346 | 0 | pub const fn as_hms_micro(self) -> (u8, u8, u8, u32) { |
347 | 0 | ( |
348 | 0 | self.hour.get(), |
349 | 0 | self.minute.get(), |
350 | 0 | self.second.get(), |
351 | 0 | self.nanosecond.get() / Nanosecond::per_t::<u32>(Microsecond), |
352 | 0 | ) |
353 | 0 | } |
354 | | |
355 | | /// Get the clock hour, minute, second, and nanosecond. |
356 | | /// |
357 | | /// ```rust |
358 | | /// # use time_macros::time; |
359 | | /// assert_eq!(time!(0:00:00).as_hms_nano(), (0, 0, 0, 0)); |
360 | | /// assert_eq!( |
361 | | /// time!(23:59:59.999_999_999).as_hms_nano(), |
362 | | /// (23, 59, 59, 999_999_999) |
363 | | /// ); |
364 | | /// ``` |
365 | | #[inline] |
366 | 0 | pub const fn as_hms_nano(self) -> (u8, u8, u8, u32) { |
367 | 0 | ( |
368 | 0 | self.hour.get(), |
369 | 0 | self.minute.get(), |
370 | 0 | self.second.get(), |
371 | 0 | self.nanosecond.get(), |
372 | 0 | ) |
373 | 0 | } |
374 | | |
375 | | /// Get the clock hour, minute, second, and nanosecond. |
376 | | #[inline] |
377 | | #[cfg(any(feature = "formatting", feature = "quickcheck"))] |
378 | | pub(crate) const fn as_hms_nano_ranged(self) -> (Hours, Minutes, Seconds, Nanoseconds) { |
379 | | (self.hour, self.minute, self.second, self.nanosecond) |
380 | | } |
381 | | |
382 | | /// Get the clock hour. |
383 | | /// |
384 | | /// The returned value will always be in the range `0..24`. |
385 | | /// |
386 | | /// ```rust |
387 | | /// # use time_macros::time; |
388 | | /// assert_eq!(time!(0:00:00).hour(), 0); |
389 | | /// assert_eq!(time!(23:59:59).hour(), 23); |
390 | | /// ``` |
391 | | #[inline] |
392 | 85.8k | pub const fn hour(self) -> u8 { |
393 | 85.8k | self.hour.get() |
394 | 85.8k | } Line | Count | Source | 392 | 85.8k | pub const fn hour(self) -> u8 { | 393 | 85.8k | self.hour.get() | 394 | 85.8k | } |
Unexecuted instantiation: <time::time::Time>::hour |
395 | | |
396 | | /// Get the minute within the hour. |
397 | | /// |
398 | | /// The returned value will always be in the range `0..60`. |
399 | | /// |
400 | | /// ```rust |
401 | | /// # use time_macros::time; |
402 | | /// assert_eq!(time!(0:00:00).minute(), 0); |
403 | | /// assert_eq!(time!(23:59:59).minute(), 59); |
404 | | /// ``` |
405 | | #[inline] |
406 | 85.8k | pub const fn minute(self) -> u8 { |
407 | 85.8k | self.minute.get() |
408 | 85.8k | } <time::time::Time>::minute Line | Count | Source | 406 | 85.8k | pub const fn minute(self) -> u8 { | 407 | 85.8k | self.minute.get() | 408 | 85.8k | } |
Unexecuted instantiation: <time::time::Time>::minute |
409 | | |
410 | | /// Get the second within the minute. |
411 | | /// |
412 | | /// The returned value will always be in the range `0..60`. |
413 | | /// |
414 | | /// ```rust |
415 | | /// # use time_macros::time; |
416 | | /// assert_eq!(time!(0:00:00).second(), 0); |
417 | | /// assert_eq!(time!(23:59:59).second(), 59); |
418 | | /// ``` |
419 | | #[inline] |
420 | 85.8k | pub const fn second(self) -> u8 { |
421 | 85.8k | self.second.get() |
422 | 85.8k | } <time::time::Time>::second Line | Count | Source | 420 | 85.8k | pub const fn second(self) -> u8 { | 421 | 85.8k | self.second.get() | 422 | 85.8k | } |
Unexecuted instantiation: <time::time::Time>::second |
423 | | |
424 | | /// Get the milliseconds within the second. |
425 | | /// |
426 | | /// The returned value will always be in the range `0..1_000`. |
427 | | /// |
428 | | /// ```rust |
429 | | /// # use time_macros::time; |
430 | | /// assert_eq!(time!(0:00).millisecond(), 0); |
431 | | /// assert_eq!(time!(23:59:59.999).millisecond(), 999); |
432 | | /// ``` |
433 | | #[inline] |
434 | 0 | pub const fn millisecond(self) -> u16 { |
435 | 0 | (self.nanosecond.get() / Nanosecond::per_t::<u32>(Millisecond)) as u16 |
436 | 0 | } |
437 | | |
438 | | /// Get the microseconds within the second. |
439 | | /// |
440 | | /// The returned value will always be in the range `0..1_000_000`. |
441 | | /// |
442 | | /// ```rust |
443 | | /// # use time_macros::time; |
444 | | /// assert_eq!(time!(0:00).microsecond(), 0); |
445 | | /// assert_eq!(time!(23:59:59.999_999).microsecond(), 999_999); |
446 | | /// ``` |
447 | | #[inline] |
448 | 0 | pub const fn microsecond(self) -> u32 { |
449 | 0 | self.nanosecond.get() / Nanosecond::per_t::<u32>(Microsecond) |
450 | 0 | } |
451 | | |
452 | | /// Get the nanoseconds within the second. |
453 | | /// |
454 | | /// The returned value will always be in the range `0..1_000_000_000`. |
455 | | /// |
456 | | /// ```rust |
457 | | /// # use time_macros::time; |
458 | | /// assert_eq!(time!(0:00).nanosecond(), 0); |
459 | | /// assert_eq!(time!(23:59:59.999_999_999).nanosecond(), 999_999_999); |
460 | | /// ``` |
461 | | #[inline] |
462 | 0 | pub const fn nanosecond(self) -> u32 { |
463 | 0 | self.nanosecond.get() |
464 | 0 | } |
465 | | |
466 | | /// Determine the [`SignedDuration`] that, if added to `self`, would result in the parameter. |
467 | | /// |
468 | | /// ```rust |
469 | | /// # use time::Time; |
470 | | /// # use time::ext::NumericalDuration; |
471 | | /// # use time_macros::time; |
472 | | /// assert_eq!(time!(18:00).duration_until(Time::MIDNIGHT), 6.hours()); |
473 | | /// assert_eq!(time!(23:00).duration_until(time!(1:00)), 2.hours()); |
474 | | /// ``` |
475 | | #[inline] |
476 | 0 | pub const fn duration_until(self, other: Self) -> SignedDuration { |
477 | 0 | let mut nanoseconds = |
478 | 0 | other.nanosecond.get().cast_signed() - self.nanosecond.get().cast_signed(); |
479 | 0 | let seconds = other.second.get().cast_signed() - self.second.get().cast_signed(); |
480 | 0 | let minutes = other.minute.get().cast_signed() - self.minute.get().cast_signed(); |
481 | 0 | let hours = other.hour.get().cast_signed() - self.hour.get().cast_signed(); |
482 | | |
483 | | // Safety: For all four variables, the bounds are obviously true given the previous bounds |
484 | | // and nature of subtraction. |
485 | 0 | unsafe { |
486 | 0 | hint::assert_unchecked( |
487 | 0 | nanoseconds |
488 | 0 | >= Nanoseconds::MIN.get().cast_signed() - Nanoseconds::MAX.get().cast_signed(), |
489 | 0 | ); |
490 | 0 | hint::assert_unchecked( |
491 | 0 | nanoseconds |
492 | 0 | <= Nanoseconds::MAX.get().cast_signed() - Nanoseconds::MIN.get().cast_signed(), |
493 | 0 | ); |
494 | 0 | hint::assert_unchecked( |
495 | 0 | seconds >= Seconds::MIN.get().cast_signed() - Seconds::MAX.get().cast_signed(), |
496 | 0 | ); |
497 | 0 | hint::assert_unchecked( |
498 | 0 | seconds <= Seconds::MAX.get().cast_signed() - Seconds::MIN.get().cast_signed(), |
499 | 0 | ); |
500 | 0 | hint::assert_unchecked( |
501 | 0 | minutes >= Minutes::MIN.get().cast_signed() - Minutes::MAX.get().cast_signed(), |
502 | 0 | ); |
503 | 0 | hint::assert_unchecked( |
504 | 0 | minutes <= Minutes::MAX.get().cast_signed() - Minutes::MIN.get().cast_signed(), |
505 | 0 | ); |
506 | 0 | hint::assert_unchecked( |
507 | 0 | hours >= Hours::MIN.get().cast_signed() - Hours::MAX.get().cast_signed(), |
508 | 0 | ); |
509 | 0 | hint::assert_unchecked( |
510 | 0 | hours <= Hours::MAX.get().cast_signed() - Hours::MIN.get().cast_signed(), |
511 | 0 | ); |
512 | 0 | } |
513 | | |
514 | 0 | let mut total_seconds = hours as i32 * Second::per_t::<i32>(Hour) |
515 | 0 | + minutes as i32 * Second::per_t::<i32>(Minute) |
516 | 0 | + seconds as i32; |
517 | | |
518 | 0 | cascade!(nanoseconds in 0..Nanosecond::per_t(Second) => total_seconds); |
519 | | |
520 | 0 | if total_seconds < 0 { |
521 | 0 | total_seconds += Second::per_t::<i32>(Day); |
522 | 0 | } |
523 | | |
524 | | // Safety: The range of `nanoseconds` is guaranteed by the cascades above. |
525 | 0 | unsafe { SignedDuration::new_unchecked(total_seconds as i64, nanoseconds) } |
526 | 0 | } |
527 | | |
528 | | /// Determine the [`SignedDuration`] that, if added to the parameter, would result in `self`. |
529 | | /// |
530 | | /// ```rust |
531 | | /// # use time::Time; |
532 | | /// # use time::ext::NumericalDuration; |
533 | | /// # use time_macros::time; |
534 | | /// assert_eq!(Time::MIDNIGHT.duration_since(time!(18:00)), 6.hours()); |
535 | | /// assert_eq!(time!(1:00).duration_since(time!(23:00)), 2.hours()); |
536 | | /// ``` |
537 | | #[inline] |
538 | 0 | pub const fn duration_since(self, other: Self) -> SignedDuration { |
539 | 0 | other.duration_until(self) |
540 | 0 | } |
541 | | |
542 | | /// Add the sub-day time of the [`SignedDuration`] to the `Time`. Wraps on overflow, returning |
543 | | /// whether the date is different. |
544 | | #[inline] |
545 | 0 | pub(crate) const fn adjusting_add(self, duration: SignedDuration) -> (DateAdjustment, Self) { |
546 | 0 | let mut nanoseconds = self.nanosecond.get().cast_signed() + duration.subsec_nanoseconds(); |
547 | 0 | let mut seconds = self.second.get().cast_signed() |
548 | 0 | + (duration.whole_seconds() % Second::per_t::<i64>(Minute)) as i8; |
549 | 0 | let mut minutes = self.minute.get().cast_signed() |
550 | 0 | + (duration.whole_minutes() % Minute::per_t::<i64>(Hour)) as i8; |
551 | 0 | let mut hours = self.hour.get().cast_signed() |
552 | 0 | + (duration.whole_hours() % Hour::per_t::<i64>(Day)) as i8; |
553 | 0 | let mut date_adjustment = DateAdjustment::None; |
554 | | |
555 | 0 | cascade!(nanoseconds in 0..Nanosecond::per_t(Second) => seconds); |
556 | 0 | cascade!(seconds in 0..Second::per_t(Minute) => minutes); |
557 | 0 | cascade!(minutes in 0..Minute::per_t(Hour) => hours); |
558 | 0 | if hours >= Hour::per_t(Day) { |
559 | 0 | hours -= Hour::per_t::<i8>(Day); |
560 | 0 | date_adjustment = DateAdjustment::Next; |
561 | 0 | } else if hours < 0 { |
562 | 0 | hours += Hour::per_t::<i8>(Day); |
563 | 0 | date_adjustment = DateAdjustment::Previous; |
564 | 0 | } |
565 | | |
566 | 0 | ( |
567 | 0 | date_adjustment, |
568 | 0 | // Safety: The cascades above ensure the values are in range. |
569 | 0 | unsafe { |
570 | 0 | Self::__from_hms_nanos_unchecked( |
571 | 0 | hours.cast_unsigned(), |
572 | 0 | minutes.cast_unsigned(), |
573 | 0 | seconds.cast_unsigned(), |
574 | 0 | nanoseconds.cast_unsigned(), |
575 | 0 | ) |
576 | 0 | }, |
577 | 0 | ) |
578 | 0 | } |
579 | | |
580 | | /// Subtract the sub-day time of the [`SignedDuration`] to the `Time`. Wraps on overflow, |
581 | | /// returning whether the date is different. |
582 | | #[inline] |
583 | 0 | pub(crate) const fn adjusting_sub(self, duration: SignedDuration) -> (DateAdjustment, Self) { |
584 | 0 | let mut nanoseconds = self.nanosecond.get().cast_signed() - duration.subsec_nanoseconds(); |
585 | 0 | let mut seconds = self.second.get().cast_signed() |
586 | 0 | - (duration.whole_seconds() % Second::per_t::<i64>(Minute)) as i8; |
587 | 0 | let mut minutes = self.minute.get().cast_signed() |
588 | 0 | - (duration.whole_minutes() % Minute::per_t::<i64>(Hour)) as i8; |
589 | 0 | let mut hours = self.hour.get().cast_signed() |
590 | 0 | - (duration.whole_hours() % Hour::per_t::<i64>(Day)) as i8; |
591 | 0 | let mut date_adjustment = DateAdjustment::None; |
592 | | |
593 | 0 | cascade!(nanoseconds in 0..Nanosecond::per_t(Second) => seconds); |
594 | 0 | cascade!(seconds in 0..Second::per_t(Minute) => minutes); |
595 | 0 | cascade!(minutes in 0..Minute::per_t(Hour) => hours); |
596 | 0 | if hours >= Hour::per_t(Day) { |
597 | 0 | hours -= Hour::per_t::<i8>(Day); |
598 | 0 | date_adjustment = DateAdjustment::Next; |
599 | 0 | } else if hours < 0 { |
600 | 0 | hours += Hour::per_t::<i8>(Day); |
601 | 0 | date_adjustment = DateAdjustment::Previous; |
602 | 0 | } |
603 | | |
604 | 0 | ( |
605 | 0 | date_adjustment, |
606 | 0 | // Safety: The cascades above ensure the values are in range. |
607 | 0 | unsafe { |
608 | 0 | Self::__from_hms_nanos_unchecked( |
609 | 0 | hours.cast_unsigned(), |
610 | 0 | minutes.cast_unsigned(), |
611 | 0 | seconds.cast_unsigned(), |
612 | 0 | nanoseconds.cast_unsigned(), |
613 | 0 | ) |
614 | 0 | }, |
615 | 0 | ) |
616 | 0 | } |
617 | | |
618 | | /// Add the sub-day time of the [`std::time::Duration`] to the `Time`. Wraps on overflow, |
619 | | /// returning whether the date is the previous date as the first element of the tuple. |
620 | | #[inline] |
621 | 85.8k | pub(crate) const fn adjusting_add_std(self, duration: StdDuration) -> (bool, Self) { |
622 | 85.8k | let mut nanosecond = self.nanosecond.get() + duration.subsec_nanos(); |
623 | 85.8k | let mut second = |
624 | 85.8k | self.second.get() + (duration.as_secs() % Second::per_t::<u64>(Minute)) as u8; |
625 | 85.8k | let mut minute = self.minute.get() |
626 | 85.8k | + ((duration.as_secs() / Second::per_t::<u64>(Minute)) % Minute::per_t::<u64>(Hour)) |
627 | 85.8k | as u8; |
628 | 85.8k | let mut hour = self.hour.get() |
629 | 85.8k | + ((duration.as_secs() / Second::per_t::<u64>(Hour)) % Hour::per_t::<u64>(Day)) as u8; |
630 | 85.8k | let mut is_next_day = false; |
631 | | |
632 | 85.8k | cascade!(nanosecond in 0..Nanosecond::per_t(Second) => second); |
633 | 85.8k | cascade!(second in 0..Second::per_t(Minute) => minute); |
634 | 85.8k | cascade!(minute in 0..Minute::per_t(Hour) => hour); |
635 | 85.8k | if hour >= Hour::per_t::<u8>(Day) { |
636 | 0 | hour -= Hour::per_t::<u8>(Day); |
637 | 0 | is_next_day = true; |
638 | 85.8k | } |
639 | | |
640 | 85.8k | ( |
641 | 85.8k | is_next_day, |
642 | 85.8k | // Safety: The cascades above ensure the values are in range. |
643 | 85.8k | unsafe { Self::__from_hms_nanos_unchecked(hour, minute, second, nanosecond) }, |
644 | 85.8k | ) |
645 | 85.8k | } <time::time::Time>::adjusting_add_std Line | Count | Source | 621 | 85.8k | pub(crate) const fn adjusting_add_std(self, duration: StdDuration) -> (bool, Self) { | 622 | 85.8k | let mut nanosecond = self.nanosecond.get() + duration.subsec_nanos(); | 623 | 85.8k | let mut second = | 624 | 85.8k | self.second.get() + (duration.as_secs() % Second::per_t::<u64>(Minute)) as u8; | 625 | 85.8k | let mut minute = self.minute.get() | 626 | 85.8k | + ((duration.as_secs() / Second::per_t::<u64>(Minute)) % Minute::per_t::<u64>(Hour)) | 627 | 85.8k | as u8; | 628 | 85.8k | let mut hour = self.hour.get() | 629 | 85.8k | + ((duration.as_secs() / Second::per_t::<u64>(Hour)) % Hour::per_t::<u64>(Day)) as u8; | 630 | 85.8k | let mut is_next_day = false; | 631 | | | 632 | 85.8k | cascade!(nanosecond in 0..Nanosecond::per_t(Second) => second); | 633 | 85.8k | cascade!(second in 0..Second::per_t(Minute) => minute); | 634 | 85.8k | cascade!(minute in 0..Minute::per_t(Hour) => hour); | 635 | 85.8k | if hour >= Hour::per_t::<u8>(Day) { | 636 | 0 | hour -= Hour::per_t::<u8>(Day); | 637 | 0 | is_next_day = true; | 638 | 85.8k | } | 639 | | | 640 | 85.8k | ( | 641 | 85.8k | is_next_day, | 642 | 85.8k | // Safety: The cascades above ensure the values are in range. | 643 | 85.8k | unsafe { Self::__from_hms_nanos_unchecked(hour, minute, second, nanosecond) }, | 644 | 85.8k | ) | 645 | 85.8k | } |
Unexecuted instantiation: <time::time::Time>::adjusting_add_std |
646 | | |
647 | | /// Subtract the sub-day time of the [`std::time::Duration`] to the `Time`. Wraps on overflow, |
648 | | /// returning whether the date is the previous date as the first element of the tuple. |
649 | | #[inline] |
650 | 0 | pub(crate) const fn adjusting_sub_std(self, duration: StdDuration) -> (bool, Self) { |
651 | 0 | let mut nanosecond = |
652 | 0 | self.nanosecond.get().cast_signed() - duration.subsec_nanos().cast_signed(); |
653 | 0 | let mut second = self.second.get().cast_signed() |
654 | 0 | - (duration.as_secs() % Second::per_t::<u64>(Minute)) as i8; |
655 | 0 | let mut minute = self.minute.get().cast_signed() |
656 | 0 | - ((duration.as_secs() / Second::per_t::<u64>(Minute)) % Minute::per_t::<u64>(Hour)) |
657 | 0 | as i8; |
658 | 0 | let mut hour = self.hour.get().cast_signed() |
659 | 0 | - ((duration.as_secs() / Second::per_t::<u64>(Hour)) % Hour::per_t::<u64>(Day)) as i8; |
660 | 0 | let mut is_previous_day = false; |
661 | | |
662 | 0 | cascade!(nanosecond in 0..Nanosecond::per_t(Second) => second); |
663 | 0 | cascade!(second in 0..Second::per_t(Minute) => minute); |
664 | 0 | cascade!(minute in 0..Minute::per_t(Hour) => hour); |
665 | 0 | if hour < 0 { |
666 | 0 | hour += Hour::per_t::<i8>(Day); |
667 | 0 | is_previous_day = true; |
668 | 0 | } |
669 | | |
670 | 0 | ( |
671 | 0 | is_previous_day, |
672 | 0 | // Safety: The cascades above ensure the values are in range. |
673 | 0 | unsafe { |
674 | 0 | Self::__from_hms_nanos_unchecked( |
675 | 0 | hour.cast_unsigned(), |
676 | 0 | minute.cast_unsigned(), |
677 | 0 | second.cast_unsigned(), |
678 | 0 | nanosecond.cast_unsigned(), |
679 | 0 | ) |
680 | 0 | }, |
681 | 0 | ) |
682 | 0 | } Unexecuted instantiation: <time::time::Time>::adjusting_sub_std Unexecuted instantiation: <time::time::Time>::adjusting_sub_std |
683 | | |
684 | | /// Replace the clock hour. |
685 | | /// |
686 | | /// ```rust |
687 | | /// # use time_macros::time; |
688 | | /// assert_eq!( |
689 | | /// time!(01:02:03.004_005_006).replace_hour(7), |
690 | | /// Ok(time!(07:02:03.004_005_006)) |
691 | | /// ); |
692 | | /// assert!(time!(01:02:03.004_005_006).replace_hour(24).is_err()); // 24 isn't a valid hour |
693 | | /// ``` |
694 | | #[must_use = "This method does not mutate the original `Time`."] |
695 | | #[inline] |
696 | 0 | pub const fn replace_hour(mut self, hour: u8) -> Result<Self, error::ComponentRange> { |
697 | 0 | self.hour = ensure_ranged!(Hours: hour); |
698 | 0 | Ok(self) |
699 | 0 | } |
700 | | |
701 | | /// Truncate the time to the hour, setting the minute, second, and subsecond components to zero. |
702 | | /// |
703 | | /// ```rust |
704 | | /// # use time_macros::time; |
705 | | /// assert_eq!(time!(01:02:03.004_005_006).truncate_to_hour(), time!(01:00)); |
706 | | /// ``` |
707 | | #[must_use = "This method does not mutate the original `Time`."] |
708 | | #[inline] |
709 | 0 | pub const fn truncate_to_hour(mut self) -> Self { |
710 | 0 | self.minute = Minutes::MIN; |
711 | 0 | self.second = Seconds::MIN; |
712 | 0 | self.nanosecond = Nanoseconds::MIN; |
713 | 0 | self |
714 | 0 | } |
715 | | |
716 | | /// Replace the minutes within the hour. |
717 | | /// |
718 | | /// ```rust |
719 | | /// # use time_macros::time; |
720 | | /// assert_eq!( |
721 | | /// time!(01:02:03.004_005_006).replace_minute(7), |
722 | | /// Ok(time!(01:07:03.004_005_006)) |
723 | | /// ); |
724 | | /// assert!(time!(01:02:03.004_005_006).replace_minute(60).is_err()); // 60 isn't a valid minute |
725 | | /// ``` |
726 | | #[must_use = "This method does not mutate the original `Time`."] |
727 | | #[inline] |
728 | 0 | pub const fn replace_minute(mut self, minute: u8) -> Result<Self, error::ComponentRange> { |
729 | 0 | self.minute = ensure_ranged!(Minutes: minute); |
730 | 0 | Ok(self) |
731 | 0 | } |
732 | | |
733 | | /// Truncate the time to the minute, setting the second and subsecond components to zero. |
734 | | /// |
735 | | /// ```rust |
736 | | /// # use time_macros::time; |
737 | | /// assert_eq!( |
738 | | /// time!(01:02:03.004_005_006).truncate_to_minute(), |
739 | | /// time!(01:02) |
740 | | /// ); |
741 | | /// ``` |
742 | | #[must_use = "This method does not mutate the original `Time`."] |
743 | | #[inline] |
744 | 0 | pub const fn truncate_to_minute(mut self) -> Self { |
745 | 0 | self.second = Seconds::MIN; |
746 | 0 | self.nanosecond = Nanoseconds::MIN; |
747 | 0 | self |
748 | 0 | } |
749 | | |
750 | | /// Replace the seconds within the minute. |
751 | | /// |
752 | | /// ```rust |
753 | | /// # use time_macros::time; |
754 | | /// assert_eq!( |
755 | | /// time!(01:02:03.004_005_006).replace_second(7), |
756 | | /// Ok(time!(01:02:07.004_005_006)) |
757 | | /// ); |
758 | | /// assert!(time!(01:02:03.004_005_006).replace_second(60).is_err()); // 60 isn't a valid second |
759 | | /// ``` |
760 | | #[must_use = "This method does not mutate the original `Time`."] |
761 | | #[inline] |
762 | 0 | pub const fn replace_second(mut self, second: u8) -> Result<Self, error::ComponentRange> { |
763 | 0 | self.second = ensure_ranged!(Seconds: second); |
764 | 0 | Ok(self) |
765 | 0 | } |
766 | | |
767 | | /// Truncate the time to the second, setting the subsecond component to zero. |
768 | | /// |
769 | | /// ```rust |
770 | | /// # use time_macros::time; |
771 | | /// assert_eq!( |
772 | | /// time!(01:02:03.004_005_006).truncate_to_second(), |
773 | | /// time!(01:02:03) |
774 | | /// ); |
775 | | /// ``` |
776 | | #[must_use = "This method does not mutate the original `Time`."] |
777 | | #[inline] |
778 | 0 | pub const fn truncate_to_second(mut self) -> Self { |
779 | 0 | self.nanosecond = Nanoseconds::MIN; |
780 | 0 | self |
781 | 0 | } |
782 | | |
783 | | /// Replace the milliseconds within the second. |
784 | | /// |
785 | | /// ```rust |
786 | | /// # use time_macros::time; |
787 | | /// assert_eq!( |
788 | | /// time!(01:02:03.004_005_006).replace_millisecond(7), |
789 | | /// Ok(time!(01:02:03.007)) |
790 | | /// ); |
791 | | /// assert!( |
792 | | /// time!(01:02:03.004_005_006) |
793 | | /// .replace_millisecond(1_000) |
794 | | /// .is_err() // 1_000 isn't a valid millisecond |
795 | | /// ); |
796 | | /// ``` |
797 | | #[must_use = "This method does not mutate the original `Time`."] |
798 | | #[inline] |
799 | 0 | pub const fn replace_millisecond( |
800 | 0 | mut self, |
801 | 0 | millisecond: u16, |
802 | 0 | ) -> Result<Self, error::ComponentRange> { |
803 | | self.nanosecond = |
804 | 0 | ensure_ranged!(Nanoseconds: millisecond as u32 * Nanosecond::per_t::<u32>(Millisecond)); |
805 | 0 | Ok(self) |
806 | 0 | } |
807 | | |
808 | | /// Truncate the time to the millisecond, setting the microsecond and nanosecond components to |
809 | | /// zero. |
810 | | /// |
811 | | /// ```rust |
812 | | /// # use time_macros::time; |
813 | | /// assert_eq!( |
814 | | /// time!(01:02:03.004_005_006).truncate_to_millisecond(), |
815 | | /// time!(01:02:03.004) |
816 | | /// ); |
817 | | /// ``` |
818 | | #[must_use = "This method does not mutate the original `Time`."] |
819 | | #[inline] |
820 | 0 | pub const fn truncate_to_millisecond(mut self) -> Self { |
821 | | // Safety: Truncating to the millisecond will always produce a valid nanosecond. |
822 | 0 | self.nanosecond = unsafe { |
823 | 0 | Nanoseconds::new_unchecked(self.nanosecond.get() - (self.nanosecond.get() % 1_000_000)) |
824 | 0 | }; |
825 | 0 | self |
826 | 0 | } |
827 | | |
828 | | /// Replace the microseconds within the second. |
829 | | /// |
830 | | /// ```rust |
831 | | /// # use time_macros::time; |
832 | | /// assert_eq!( |
833 | | /// time!(01:02:03.004_005_006).replace_microsecond(7_008), |
834 | | /// Ok(time!(01:02:03.007_008)) |
835 | | /// ); |
836 | | /// assert!( |
837 | | /// time!(01:02:03.004_005_006) |
838 | | /// .replace_microsecond(1_000_000) |
839 | | /// .is_err() // 1_000_000 isn't a valid microsecond |
840 | | /// ); |
841 | | /// ``` |
842 | | #[must_use = "This method does not mutate the original `Time`."] |
843 | | #[inline] |
844 | 0 | pub const fn replace_microsecond( |
845 | 0 | mut self, |
846 | 0 | microsecond: u32, |
847 | 0 | ) -> Result<Self, error::ComponentRange> { |
848 | | self.nanosecond = |
849 | 0 | ensure_ranged!(Nanoseconds: microsecond * Nanosecond::per_t::<u32>(Microsecond)); |
850 | 0 | Ok(self) |
851 | 0 | } |
852 | | |
853 | | /// Truncate the time to the microsecond, setting the nanosecond component to zero. |
854 | | /// |
855 | | /// ```rust |
856 | | /// # use time_macros::time; |
857 | | /// assert_eq!( |
858 | | /// time!(01:02:03.004_005_006).truncate_to_microsecond(), |
859 | | /// time!(01:02:03.004_005) |
860 | | /// ); |
861 | | /// ``` |
862 | | #[must_use = "This method does not mutate the original `Time`."] |
863 | | #[inline] |
864 | 0 | pub const fn truncate_to_microsecond(mut self) -> Self { |
865 | | // Safety: Truncating to the microsecond will always produce a valid nanosecond. |
866 | 0 | self.nanosecond = unsafe { |
867 | 0 | Nanoseconds::new_unchecked(self.nanosecond.get() - (self.nanosecond.get() % 1_000)) |
868 | 0 | }; |
869 | 0 | self |
870 | 0 | } |
871 | | |
872 | | /// Replace the nanoseconds within the second. |
873 | | /// |
874 | | /// ```rust |
875 | | /// # use time_macros::time; |
876 | | /// assert_eq!( |
877 | | /// time!(01:02:03.004_005_006).replace_nanosecond(7_008_009), |
878 | | /// Ok(time!(01:02:03.007_008_009)) |
879 | | /// ); |
880 | | /// assert!( |
881 | | /// time!(01:02:03.004_005_006) |
882 | | /// .replace_nanosecond(1_000_000_000) |
883 | | /// .is_err() // 1_000_000_000 isn't a valid nanosecond |
884 | | /// ); |
885 | | /// ``` |
886 | | #[must_use = "This method does not mutate the original `Time`."] |
887 | | #[inline] |
888 | 0 | pub const fn replace_nanosecond( |
889 | 0 | mut self, |
890 | 0 | nanosecond: u32, |
891 | 0 | ) -> Result<Self, error::ComponentRange> { |
892 | 0 | self.nanosecond = ensure_ranged!(Nanoseconds: nanosecond); |
893 | 0 | Ok(self) |
894 | 0 | } |
895 | | } |
896 | | |
897 | | #[cfg(feature = "formatting")] |
898 | | impl Time { |
899 | | /// Format the `Time` using the provided [format description](crate::format_description). |
900 | | #[inline] |
901 | | pub fn format_into( |
902 | | self, |
903 | | output: &mut (impl io::Write + ?Sized), |
904 | | format: &(impl Formattable + ?Sized), |
905 | | ) -> Result<usize, error::Format> { |
906 | | format.format_into(output, &self, &mut Default::default(), PrivateMethod) |
907 | | } |
908 | | |
909 | | /// Format the `Time` using the provided [format description](crate::format_description). |
910 | | /// |
911 | | /// ```rust |
912 | | /// # use time::format_description; |
913 | | /// # use time_macros::time; |
914 | | /// let format = format_description::parse_borrowed::<3>("[hour]:[minute]:[second]")?; |
915 | | /// assert_eq!(time!(12:00).format(&format)?, "12:00:00"); |
916 | | /// # Ok::<_, time::Error>(()) |
917 | | /// ``` |
918 | | #[inline] |
919 | | pub fn format(self, format: &(impl Formattable + ?Sized)) -> Result<String, error::Format> { |
920 | | format.format(&self, &mut Default::default(), PrivateMethod) |
921 | | } |
922 | | } |
923 | | |
924 | | #[cfg(feature = "parsing")] |
925 | | impl Time { |
926 | | /// Parse a `Time` from the input using the provided [format |
927 | | /// description](crate::format_description). |
928 | | /// |
929 | | /// ```rust |
930 | | /// # use time::Time; |
931 | | /// # use time_macros::{time, format_description}; |
932 | | /// let format = format_description!("[hour]:[minute]:[second]"); |
933 | | /// assert_eq!(Time::parse("12:00:00", &format)?, time!(12:00)); |
934 | | /// # Ok::<_, time::Error>(()) |
935 | | /// ``` |
936 | | #[inline] |
937 | | pub fn parse( |
938 | | input: &str, |
939 | | description: &(impl Parsable + ?Sized), |
940 | | ) -> Result<Self, error::Parse> { |
941 | | description.parse_time(input.as_bytes(), None, PrivateMethod) |
942 | | } |
943 | | |
944 | | /// Parse a `Time` from the input using the provided [format |
945 | | /// description](crate::format_description) and default values. |
946 | | /// |
947 | | /// ```rust |
948 | | /// # use time::Time; |
949 | | /// # use time::parsing::Parsed; |
950 | | /// # use time_macros::{time, format_description}; |
951 | | /// let format = format_description!("[hour]"); |
952 | | /// let defaults = Parsed::new().with_minute(30).expect("30 is a valid minute"); |
953 | | /// assert_eq!( |
954 | | /// Time::parse_with_defaults(b"12", &format, defaults)?, |
955 | | /// time!(12:30) |
956 | | /// ); |
957 | | /// # Ok::<_, time::Error>(()) |
958 | | /// ``` |
959 | | #[inline] |
960 | | pub fn parse_with_defaults( |
961 | | input: &[u8], |
962 | | description: &(impl Parsable + ?Sized), |
963 | | defaults: Parsed, |
964 | | ) -> Result<Self, error::Parse> { |
965 | | description.parse_time(input, Some(defaults), PrivateMethod) |
966 | | } |
967 | | } |
968 | | |
969 | | // This no longer needs special handling, as the format is fixed and doesn't require anything |
970 | | // advanced. Trait impls can't be deprecated and the info is still useful for other types |
971 | | // implementing `SmartDisplay`, so leave it as-is for now. |
972 | | impl SmartDisplay for Time { |
973 | | type Metadata = (); |
974 | | |
975 | | #[inline] |
976 | 0 | fn metadata(&self, _: FormatterOptions) -> Metadata<'_, Self> { |
977 | 0 | let hour_width = if self.hour() < 10 { 1 } else { 2 }; |
978 | 0 | let subsecond_width = match self.nanosecond() { |
979 | 0 | nanos if nanos % 10 != 0 => 9, |
980 | 0 | nanos if (nanos / 10) % 10 != 0 => 8, |
981 | 0 | nanos if (nanos / 100) % 10 != 0 => 7, |
982 | 0 | nanos if (nanos / 1_000) % 10 != 0 => 6, |
983 | 0 | nanos if (nanos / 10_000) % 10 != 0 => 5, |
984 | 0 | nanos if (nanos / 100_000) % 10 != 0 => 4, |
985 | 0 | nanos if (nanos / 1_000_000) % 10 != 0 => 3, |
986 | 0 | nanos if (nanos / 10_000_000) % 10 != 0 => 2, |
987 | 0 | _ => 1, |
988 | | }; |
989 | 0 | let total_width = hour_width + subsecond_width + 7; |
990 | | |
991 | 0 | Metadata::new(total_width, self, ()) |
992 | 0 | } |
993 | | |
994 | | #[inline] |
995 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
996 | 0 | fmt::Display::fmt(self, f) |
997 | 0 | } |
998 | | } |
999 | | |
1000 | | impl Time { |
1001 | | /// The maximum number of bytes that the `fmt_into_buffer` method will write, which is also used |
1002 | | /// for the `Display` implementation. |
1003 | | pub(crate) const DISPLAY_BUFFER_SIZE: usize = 18; |
1004 | | |
1005 | | /// Format the `Time` into the provided buffer, returning the number of bytes written. |
1006 | | #[inline] |
1007 | 0 | pub(crate) fn fmt_into_buffer( |
1008 | 0 | self, |
1009 | 0 | buf: &mut [MaybeUninit<u8>; Self::DISPLAY_BUFFER_SIZE], |
1010 | 0 | ) -> usize { |
1011 | 0 | let mut idx = 0; |
1012 | | |
1013 | | // Safety: `self.hour()` is in the range required by its type. |
1014 | 0 | let hour = |
1015 | 0 | one_to_two_digits_no_padding(unsafe { Hours::new_unchecked(self.hour()) }.expand()); |
1016 | | // Safety: |
1017 | | // - both `hour` and `buf` are valid for reads and writes of up to 2 bytes. |
1018 | | // - `u8` is 1-aligned, so that is not a concern. |
1019 | | // - `hour` points to static memory, while `buf` is a local variable, so they do not |
1020 | | // overlap. |
1021 | | unsafe { |
1022 | 0 | hour.as_ptr() |
1023 | 0 | .copy_to_nonoverlapping(buf.as_mut_ptr().add(idx).cast(), hour.len()) |
1024 | | }; |
1025 | 0 | idx += hour.len(); |
1026 | | |
1027 | 0 | buf[idx] = MaybeUninit::new(b':'); |
1028 | 0 | idx += 1; |
1029 | | |
1030 | | // Safety: See above. |
1031 | | unsafe { |
1032 | 0 | two_digits_zero_padded(Minutes::new_unchecked(self.minute()).expand()) |
1033 | 0 | .as_ptr() |
1034 | 0 | .copy_to_nonoverlapping(buf.as_mut_ptr().add(idx).cast(), 2) |
1035 | | }; |
1036 | 0 | idx += 2; |
1037 | | |
1038 | 0 | buf[idx] = MaybeUninit::new(b':'); |
1039 | 0 | idx += 1; |
1040 | | |
1041 | | // Safety: See above. |
1042 | | unsafe { |
1043 | 0 | two_digits_zero_padded(Seconds::new_unchecked(self.second()).expand()) |
1044 | 0 | .as_ptr() |
1045 | 0 | .copy_to_nonoverlapping(buf.as_mut_ptr().add(idx).cast(), 2) |
1046 | | }; |
1047 | 0 | idx += 2; |
1048 | | |
1049 | 0 | buf[idx] = MaybeUninit::new(b'.'); |
1050 | 0 | idx += 1; |
1051 | | |
1052 | | // Safety: `self.nanosecond()` is guaranteed to be less than 1,000,000,000. |
1053 | 0 | let subsecond = truncated_subsecond_from_nanos(unsafe { |
1054 | 0 | Nanoseconds::new_unchecked(self.nanosecond()) |
1055 | | }); |
1056 | | // Safety: See above, except `subsecond` is valid for 9 bytes. |
1057 | | unsafe { |
1058 | 0 | subsecond |
1059 | 0 | .as_ptr() |
1060 | 0 | .copy_to_nonoverlapping(buf.as_mut_ptr().add(idx).cast(), subsecond.len()) |
1061 | | }; |
1062 | 0 | idx += subsecond.len(); |
1063 | | |
1064 | 0 | idx |
1065 | 0 | } |
1066 | | } |
1067 | | |
1068 | | impl fmt::Display for Time { |
1069 | | #[inline] |
1070 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1071 | 0 | let mut buf = [MaybeUninit::uninit(); Self::DISPLAY_BUFFER_SIZE]; |
1072 | 0 | let len = self.fmt_into_buffer(&mut buf); |
1073 | | // Safety: All bytes up to `len` have been initialized with ASCII characters. |
1074 | 0 | let s = unsafe { str_from_raw_parts(buf.as_ptr().cast(), len) }; |
1075 | 0 | f.pad(s) |
1076 | 0 | } |
1077 | | } |
1078 | | |
1079 | | impl fmt::Debug for Time { |
1080 | | #[inline] |
1081 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1082 | 0 | fmt::Display::fmt(self, f) |
1083 | 0 | } |
1084 | | } |
1085 | | |
1086 | | impl Add<SignedDuration> for Time { |
1087 | | type Output = Self; |
1088 | | |
1089 | | /// Add the sub-day time of the [`SignedDuration`] to the `Time`. Wraps on overflow. |
1090 | | /// |
1091 | | /// ```rust |
1092 | | /// # use time::ext::NumericalDuration; |
1093 | | /// # use time_macros::time; |
1094 | | /// assert_eq!(time!(12:00) + 2.hours(), time!(14:00)); |
1095 | | /// assert_eq!(time!(0:00:01) + (-2).seconds(), time!(23:59:59)); |
1096 | | /// ``` |
1097 | | #[inline] |
1098 | 0 | fn add(self, duration: SignedDuration) -> Self::Output { |
1099 | 0 | self.adjusting_add(duration).1 |
1100 | 0 | } |
1101 | | } |
1102 | | |
1103 | | impl AddAssign<SignedDuration> for Time { |
1104 | | #[inline] |
1105 | 0 | fn add_assign(&mut self, rhs: SignedDuration) { |
1106 | 0 | *self = *self + rhs; |
1107 | 0 | } |
1108 | | } |
1109 | | |
1110 | | impl Add<StdDuration> for Time { |
1111 | | type Output = Self; |
1112 | | |
1113 | | /// Add the sub-day time of the [`std::time::Duration`] to the `Time`. Wraps on overflow. |
1114 | | /// |
1115 | | /// ```rust |
1116 | | /// # use time::ext::NumericalStdDuration; |
1117 | | /// # use time_macros::time; |
1118 | | /// assert_eq!(time!(12:00) + 2.std_hours(), time!(14:00)); |
1119 | | /// assert_eq!(time!(23:59:59) + 2.std_seconds(), time!(0:00:01)); |
1120 | | /// ``` |
1121 | | #[inline] |
1122 | 0 | fn add(self, duration: StdDuration) -> Self::Output { |
1123 | 0 | self.adjusting_add_std(duration).1 |
1124 | 0 | } |
1125 | | } |
1126 | | |
1127 | | impl AddAssign<StdDuration> for Time { |
1128 | | #[inline] |
1129 | 0 | fn add_assign(&mut self, rhs: StdDuration) { |
1130 | 0 | *self = *self + rhs; |
1131 | 0 | } |
1132 | | } |
1133 | | |
1134 | | impl Sub<SignedDuration> for Time { |
1135 | | type Output = Self; |
1136 | | |
1137 | | /// Subtract the sub-day time of the [`SignedDuration`] from the `Time`. Wraps on overflow. |
1138 | | /// |
1139 | | /// ```rust |
1140 | | /// # use time::ext::NumericalDuration; |
1141 | | /// # use time_macros::time; |
1142 | | /// assert_eq!(time!(14:00) - 2.hours(), time!(12:00)); |
1143 | | /// assert_eq!(time!(23:59:59) - (-2).seconds(), time!(0:00:01)); |
1144 | | /// ``` |
1145 | | #[inline] |
1146 | 0 | fn sub(self, duration: SignedDuration) -> Self::Output { |
1147 | 0 | self.adjusting_sub(duration).1 |
1148 | 0 | } |
1149 | | } |
1150 | | |
1151 | | impl SubAssign<SignedDuration> for Time { |
1152 | | #[inline] |
1153 | 0 | fn sub_assign(&mut self, rhs: SignedDuration) { |
1154 | 0 | *self = *self - rhs; |
1155 | 0 | } |
1156 | | } |
1157 | | |
1158 | | impl Sub<StdDuration> for Time { |
1159 | | type Output = Self; |
1160 | | |
1161 | | /// Subtract the sub-day time of the [`std::time::Duration`] from the `Time`. Wraps on overflow. |
1162 | | /// |
1163 | | /// ```rust |
1164 | | /// # use time::ext::NumericalStdDuration; |
1165 | | /// # use time_macros::time; |
1166 | | /// assert_eq!(time!(14:00) - 2.std_hours(), time!(12:00)); |
1167 | | /// assert_eq!(time!(0:00:01) - 2.std_seconds(), time!(23:59:59)); |
1168 | | /// ``` |
1169 | | #[inline] |
1170 | 0 | fn sub(self, duration: StdDuration) -> Self::Output { |
1171 | 0 | self.adjusting_sub_std(duration).1 |
1172 | 0 | } |
1173 | | } |
1174 | | |
1175 | | impl SubAssign<StdDuration> for Time { |
1176 | | #[inline] |
1177 | 0 | fn sub_assign(&mut self, rhs: StdDuration) { |
1178 | 0 | *self = *self - rhs; |
1179 | 0 | } |
1180 | | } |
1181 | | |
1182 | | impl Sub for Time { |
1183 | | type Output = SignedDuration; |
1184 | | |
1185 | | /// Subtract two `Time`s, returning the [`SignedDuration`] between. This assumes both `Time`s |
1186 | | /// are in the same calendar day. |
1187 | | /// |
1188 | | /// ```rust |
1189 | | /// # use time::ext::NumericalDuration; |
1190 | | /// # use time_macros::time; |
1191 | | /// assert_eq!(time!(0:00) - time!(0:00), 0.seconds()); |
1192 | | /// assert_eq!(time!(1:00) - time!(0:00), 1.hours()); |
1193 | | /// assert_eq!(time!(0:00) - time!(1:00), (-1).hours()); |
1194 | | /// assert_eq!(time!(0:00) - time!(23:00), (-23).hours()); |
1195 | | /// ``` |
1196 | | #[inline] |
1197 | 0 | fn sub(self, rhs: Self) -> Self::Output { |
1198 | 0 | let hour_diff = self.hour.get().cast_signed() - rhs.hour.get().cast_signed(); |
1199 | 0 | let minute_diff = self.minute.get().cast_signed() - rhs.minute.get().cast_signed(); |
1200 | 0 | let second_diff = self.second.get().cast_signed() - rhs.second.get().cast_signed(); |
1201 | 0 | let nanosecond_diff = |
1202 | 0 | self.nanosecond.get().cast_signed() - rhs.nanosecond.get().cast_signed(); |
1203 | | |
1204 | 0 | let seconds = hour_diff.widen::<i32>() * Second::per_t::<i32>(Hour) |
1205 | 0 | + minute_diff.widen::<i32>() * Second::per_t::<i32>(Minute) |
1206 | 0 | + second_diff.widen::<i32>(); |
1207 | | |
1208 | 0 | let (seconds, nanoseconds) = if seconds > 0 && nanosecond_diff < 0 { |
1209 | 0 | ( |
1210 | 0 | seconds - 1, |
1211 | 0 | nanosecond_diff + Nanosecond::per_t::<i32>(Second), |
1212 | 0 | ) |
1213 | 0 | } else if seconds < 0 && nanosecond_diff > 0 { |
1214 | 0 | ( |
1215 | 0 | seconds + 1, |
1216 | 0 | nanosecond_diff - Nanosecond::per_t::<i32>(Second), |
1217 | 0 | ) |
1218 | | } else { |
1219 | 0 | (seconds, nanosecond_diff) |
1220 | | }; |
1221 | | |
1222 | | // Safety: `nanoseconds` is in range due to the overflow handling. |
1223 | 0 | unsafe { SignedDuration::new_unchecked(seconds.widen(), nanoseconds) } |
1224 | 0 | } |
1225 | | } |