1//! The [`Time`] struct and its associated `impl`s.
2
3use core::fmt;
4use core::ops::{Add, Sub};
5use core::time::Duration as StdDuration;
6#[cfg(feature = "formatting")]
7use std::io;
8
9use crate::convert::*;
10#[cfg(feature = "formatting")]
11use crate::formatting::Formattable;
12#[cfg(feature = "parsing")]
13use crate::parsing::Parsable;
14use crate::util::DateAdjustment;
15use crate::{error, Duration};
16
17/// By explicitly inserting this enum where padding is expected, the compiler is able to better
18/// perform niche value optimization.
19#[repr(u8)]
20#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
21pub(crate) enum Padding {
22 #[allow(clippy::missing_docs_in_private_items)]
23 Optimize,
24}
25
26/// The clock time within a given date. Nanosecond precision.
27///
28/// All minutes are assumed to have exactly 60 seconds; no attempt is made to handle leap seconds
29/// (either positive or negative).
30///
31/// When comparing two `Time`s, they are assumed to be in the same calendar date.
32#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
33pub struct Time {
34 #[allow(clippy::missing_docs_in_private_items)]
35 hour: u8,
36 #[allow(clippy::missing_docs_in_private_items)]
37 minute: u8,
38 #[allow(clippy::missing_docs_in_private_items)]
39 second: u8,
40 #[allow(clippy::missing_docs_in_private_items)]
41 nanosecond: u32,
42 #[allow(clippy::missing_docs_in_private_items)]
43 padding: Padding,
44}
45
46impl Time {
47 /// Create a `Time` that is exactly midnight.
48 ///
49 /// ```rust
50 /// # use time::Time;
51 /// # use time_macros::time;
52 /// assert_eq!(Time::MIDNIGHT, time!(0:00));
53 /// ```
54 pub const MIDNIGHT: Self = Self::__from_hms_nanos_unchecked(0, 0, 0, 0);
55
56 /// The smallest value that can be represented by `Time`.
57 ///
58 /// `00:00:00.0`
59 pub(crate) const MIN: Self = Self::__from_hms_nanos_unchecked(0, 0, 0, 0);
60
61 /// The largest value that can be represented by `Time`.
62 ///
63 /// `23:59:59.999_999_999`
64 pub(crate) const MAX: Self = Self::__from_hms_nanos_unchecked(23, 59, 59, 999_999_999);
65
66 // region: constructors
67 /// Create a `Time` from its components.
68 #[doc(hidden)]
69 pub const fn __from_hms_nanos_unchecked(
70 hour: u8,
71 minute: u8,
72 second: u8,
73 nanosecond: u32,
74 ) -> Self {
75 debug_assert!(hour < Hour.per(Day));
76 debug_assert!(minute < Minute.per(Hour));
77 debug_assert!(second < Second.per(Minute));
78 debug_assert!(nanosecond < Nanosecond.per(Second));
79
80 Self {
81 hour,
82 minute,
83 second,
84 nanosecond,
85 padding: Padding::Optimize,
86 }
87 }
88
89 /// Attempt to create a `Time` from the hour, minute, and second.
90 ///
91 /// ```rust
92 /// # use time::Time;
93 /// assert!(Time::from_hms(1, 2, 3).is_ok());
94 /// ```
95 ///
96 /// ```rust
97 /// # use time::Time;
98 /// assert!(Time::from_hms(24, 0, 0).is_err()); // 24 isn't a valid hour.
99 /// assert!(Time::from_hms(0, 60, 0).is_err()); // 60 isn't a valid minute.
100 /// assert!(Time::from_hms(0, 0, 60).is_err()); // 60 isn't a valid second.
101 /// ```
102 pub const fn from_hms(hour: u8, minute: u8, second: u8) -> Result<Self, error::ComponentRange> {
103 ensure_value_in_range!(hour in 0 => Hour.per(Day) - 1);
104 ensure_value_in_range!(minute in 0 => Minute.per(Hour) - 1);
105 ensure_value_in_range!(second in 0 => Second.per(Minute) - 1);
106 Ok(Self::__from_hms_nanos_unchecked(hour, minute, second, 0))
107 }
108
109 /// Attempt to create a `Time` from the hour, minute, second, and millisecond.
110 ///
111 /// ```rust
112 /// # use time::Time;
113 /// assert!(Time::from_hms_milli(1, 2, 3, 4).is_ok());
114 /// ```
115 ///
116 /// ```rust
117 /// # use time::Time;
118 /// assert!(Time::from_hms_milli(24, 0, 0, 0).is_err()); // 24 isn't a valid hour.
119 /// assert!(Time::from_hms_milli(0, 60, 0, 0).is_err()); // 60 isn't a valid minute.
120 /// assert!(Time::from_hms_milli(0, 0, 60, 0).is_err()); // 60 isn't a valid second.
121 /// assert!(Time::from_hms_milli(0, 0, 0, 1_000).is_err()); // 1_000 isn't a valid millisecond.
122 /// ```
123 pub const fn from_hms_milli(
124 hour: u8,
125 minute: u8,
126 second: u8,
127 millisecond: u16,
128 ) -> Result<Self, error::ComponentRange> {
129 ensure_value_in_range!(hour in 0 => Hour.per(Day) - 1);
130 ensure_value_in_range!(minute in 0 => Minute.per(Hour) - 1);
131 ensure_value_in_range!(second in 0 => Second.per(Minute) - 1);
132 ensure_value_in_range!(millisecond in 0 => Millisecond.per(Second) - 1);
133 Ok(Self::__from_hms_nanos_unchecked(
134 hour,
135 minute,
136 second,
137 millisecond as u32 * Nanosecond.per(Millisecond),
138 ))
139 }
140
141 /// Attempt to create a `Time` from the hour, minute, second, and microsecond.
142 ///
143 /// ```rust
144 /// # use time::Time;
145 /// assert!(Time::from_hms_micro(1, 2, 3, 4).is_ok());
146 /// ```
147 ///
148 /// ```rust
149 /// # use time::Time;
150 /// assert!(Time::from_hms_micro(24, 0, 0, 0).is_err()); // 24 isn't a valid hour.
151 /// assert!(Time::from_hms_micro(0, 60, 0, 0).is_err()); // 60 isn't a valid minute.
152 /// assert!(Time::from_hms_micro(0, 0, 60, 0).is_err()); // 60 isn't a valid second.
153 /// assert!(Time::from_hms_micro(0, 0, 0, 1_000_000).is_err()); // 1_000_000 isn't a valid microsecond.
154 /// ```
155 pub const fn from_hms_micro(
156 hour: u8,
157 minute: u8,
158 second: u8,
159 microsecond: u32,
160 ) -> Result<Self, error::ComponentRange> {
161 ensure_value_in_range!(hour in 0 => Hour.per(Day) - 1);
162 ensure_value_in_range!(minute in 0 => Minute.per(Hour) - 1);
163 ensure_value_in_range!(second in 0 => Second.per(Minute) - 1);
164 ensure_value_in_range!(microsecond in 0 => Microsecond.per(Second) - 1);
165 Ok(Self::__from_hms_nanos_unchecked(
166 hour,
167 minute,
168 second,
169 microsecond * Nanosecond.per(Microsecond) as u32,
170 ))
171 }
172
173 /// Attempt to create a `Time` from the hour, minute, second, and nanosecond.
174 ///
175 /// ```rust
176 /// # use time::Time;
177 /// assert!(Time::from_hms_nano(1, 2, 3, 4).is_ok());
178 /// ```
179 ///
180 /// ```rust
181 /// # use time::Time;
182 /// assert!(Time::from_hms_nano(24, 0, 0, 0).is_err()); // 24 isn't a valid hour.
183 /// assert!(Time::from_hms_nano(0, 60, 0, 0).is_err()); // 60 isn't a valid minute.
184 /// assert!(Time::from_hms_nano(0, 0, 60, 0).is_err()); // 60 isn't a valid second.
185 /// assert!(Time::from_hms_nano(0, 0, 0, 1_000_000_000).is_err()); // 1_000_000_000 isn't a valid nanosecond.
186 /// ```
187 pub const fn from_hms_nano(
188 hour: u8,
189 minute: u8,
190 second: u8,
191 nanosecond: u32,
192 ) -> Result<Self, error::ComponentRange> {
193 ensure_value_in_range!(hour in 0 => Hour.per(Day) - 1);
194 ensure_value_in_range!(minute in 0 => Minute.per(Hour) - 1);
195 ensure_value_in_range!(second in 0 => Second.per(Minute) - 1);
196 ensure_value_in_range!(nanosecond in 0 => Nanosecond.per(Second) - 1);
197 Ok(Self::__from_hms_nanos_unchecked(
198 hour, minute, second, nanosecond,
199 ))
200 }
201 // endregion constructors
202
203 // region: getters
204 /// Get the clock hour, minute, and second.
205 ///
206 /// ```rust
207 /// # use time_macros::time;
208 /// assert_eq!(time!(0:00:00).as_hms(), (0, 0, 0));
209 /// assert_eq!(time!(23:59:59).as_hms(), (23, 59, 59));
210 /// ```
211 pub const fn as_hms(self) -> (u8, u8, u8) {
212 (self.hour, self.minute, self.second)
213 }
214
215 /// Get the clock hour, minute, second, and millisecond.
216 ///
217 /// ```rust
218 /// # use time_macros::time;
219 /// assert_eq!(time!(0:00:00).as_hms_milli(), (0, 0, 0, 0));
220 /// assert_eq!(time!(23:59:59.999).as_hms_milli(), (23, 59, 59, 999));
221 /// ```
222 pub const fn as_hms_milli(self) -> (u8, u8, u8, u16) {
223 (
224 self.hour,
225 self.minute,
226 self.second,
227 (self.nanosecond / Nanosecond.per(Millisecond)) as u16,
228 )
229 }
230
231 /// Get the clock hour, minute, second, and microsecond.
232 ///
233 /// ```rust
234 /// # use time_macros::time;
235 /// assert_eq!(time!(0:00:00).as_hms_micro(), (0, 0, 0, 0));
236 /// assert_eq!(
237 /// time!(23:59:59.999_999).as_hms_micro(),
238 /// (23, 59, 59, 999_999)
239 /// );
240 /// ```
241 pub const fn as_hms_micro(self) -> (u8, u8, u8, u32) {
242 (
243 self.hour,
244 self.minute,
245 self.second,
246 self.nanosecond / Nanosecond.per(Microsecond) as u32,
247 )
248 }
249
250 /// Get the clock hour, minute, second, and nanosecond.
251 ///
252 /// ```rust
253 /// # use time_macros::time;
254 /// assert_eq!(time!(0:00:00).as_hms_nano(), (0, 0, 0, 0));
255 /// assert_eq!(
256 /// time!(23:59:59.999_999_999).as_hms_nano(),
257 /// (23, 59, 59, 999_999_999)
258 /// );
259 /// ```
260 pub const fn as_hms_nano(self) -> (u8, u8, u8, u32) {
261 (self.hour, self.minute, self.second, self.nanosecond)
262 }
263
264 /// Get the clock hour.
265 ///
266 /// The returned value will always be in the range `0..24`.
267 ///
268 /// ```rust
269 /// # use time_macros::time;
270 /// assert_eq!(time!(0:00:00).hour(), 0);
271 /// assert_eq!(time!(23:59:59).hour(), 23);
272 /// ```
273 pub const fn hour(self) -> u8 {
274 self.hour
275 }
276
277 /// Get the minute within the hour.
278 ///
279 /// The returned value will always be in the range `0..60`.
280 ///
281 /// ```rust
282 /// # use time_macros::time;
283 /// assert_eq!(time!(0:00:00).minute(), 0);
284 /// assert_eq!(time!(23:59:59).minute(), 59);
285 /// ```
286 pub const fn minute(self) -> u8 {
287 self.minute
288 }
289
290 /// Get the second within the minute.
291 ///
292 /// The returned value will always be in the range `0..60`.
293 ///
294 /// ```rust
295 /// # use time_macros::time;
296 /// assert_eq!(time!(0:00:00).second(), 0);
297 /// assert_eq!(time!(23:59:59).second(), 59);
298 /// ```
299 pub const fn second(self) -> u8 {
300 self.second
301 }
302
303 /// Get the milliseconds within the second.
304 ///
305 /// The returned value will always be in the range `0..1_000`.
306 ///
307 /// ```rust
308 /// # use time_macros::time;
309 /// assert_eq!(time!(0:00).millisecond(), 0);
310 /// assert_eq!(time!(23:59:59.999).millisecond(), 999);
311 /// ```
312 pub const fn millisecond(self) -> u16 {
313 (self.nanosecond / Nanosecond.per(Millisecond)) as _
314 }
315
316 /// Get the microseconds within the second.
317 ///
318 /// The returned value will always be in the range `0..1_000_000`.
319 ///
320 /// ```rust
321 /// # use time_macros::time;
322 /// assert_eq!(time!(0:00).microsecond(), 0);
323 /// assert_eq!(time!(23:59:59.999_999).microsecond(), 999_999);
324 /// ```
325 pub const fn microsecond(self) -> u32 {
326 self.nanosecond / Nanosecond.per(Microsecond) as u32
327 }
328
329 /// Get the nanoseconds within the second.
330 ///
331 /// The returned value will always be in the range `0..1_000_000_000`.
332 ///
333 /// ```rust
334 /// # use time_macros::time;
335 /// assert_eq!(time!(0:00).nanosecond(), 0);
336 /// assert_eq!(time!(23:59:59.999_999_999).nanosecond(), 999_999_999);
337 /// ```
338 pub const fn nanosecond(self) -> u32 {
339 self.nanosecond
340 }
341 // endregion getters
342
343 // region: arithmetic helpers
344 /// Add the sub-day time of the [`Duration`] to the `Time`. Wraps on overflow, returning whether
345 /// the date is different.
346 pub(crate) const fn adjusting_add(self, duration: Duration) -> (DateAdjustment, Self) {
347 let mut nanoseconds = self.nanosecond as i32 + duration.subsec_nanoseconds();
348 let mut seconds =
349 self.second as i8 + (duration.whole_seconds() % Second.per(Minute) as i64) as i8;
350 let mut minutes =
351 self.minute as i8 + (duration.whole_minutes() % Minute.per(Hour) as i64) as i8;
352 let mut hours = self.hour as i8 + (duration.whole_hours() % Hour.per(Day) as i64) as i8;
353 let mut date_adjustment = DateAdjustment::None;
354
355 cascade!(nanoseconds in 0..Nanosecond.per(Second) as _ => seconds);
356 cascade!(seconds in 0..Second.per(Minute) as _ => minutes);
357 cascade!(minutes in 0..Minute.per(Hour) as _ => hours);
358 if hours >= Hour.per(Day) as _ {
359 hours -= Hour.per(Day) as i8;
360 date_adjustment = DateAdjustment::Next;
361 } else if hours < 0 {
362 hours += Hour.per(Day) as i8;
363 date_adjustment = DateAdjustment::Previous;
364 }
365
366 (
367 date_adjustment,
368 Self::__from_hms_nanos_unchecked(
369 hours as _,
370 minutes as _,
371 seconds as _,
372 nanoseconds as _,
373 ),
374 )
375 }
376
377 /// Subtract the sub-day time of the [`Duration`] to the `Time`. Wraps on overflow, returning
378 /// whether the date is different.
379 pub(crate) const fn adjusting_sub(self, duration: Duration) -> (DateAdjustment, Self) {
380 let mut nanoseconds = self.nanosecond as i32 - duration.subsec_nanoseconds();
381 let mut seconds =
382 self.second as i8 - (duration.whole_seconds() % Second.per(Minute) as i64) as i8;
383 let mut minutes =
384 self.minute as i8 - (duration.whole_minutes() % Minute.per(Hour) as i64) as i8;
385 let mut hours = self.hour as i8 - (duration.whole_hours() % Hour.per(Day) as i64) as i8;
386 let mut date_adjustment = DateAdjustment::None;
387
388 cascade!(nanoseconds in 0..Nanosecond.per(Second) as _ => seconds);
389 cascade!(seconds in 0..Second.per(Minute) as _ => minutes);
390 cascade!(minutes in 0..Minute.per(Hour) as _ => hours);
391 if hours >= Hour.per(Day) as _ {
392 hours -= Hour.per(Day) as i8;
393 date_adjustment = DateAdjustment::Next;
394 } else if hours < 0 {
395 hours += Hour.per(Day) as i8;
396 date_adjustment = DateAdjustment::Previous;
397 }
398
399 (
400 date_adjustment,
401 Self::__from_hms_nanos_unchecked(
402 hours as _,
403 minutes as _,
404 seconds as _,
405 nanoseconds as _,
406 ),
407 )
408 }
409
410 /// Add the sub-day time of the [`std::time::Duration`] to the `Time`. Wraps on overflow,
411 /// returning whether the date is the previous date as the first element of the tuple.
412 pub(crate) const fn adjusting_add_std(self, duration: StdDuration) -> (bool, Self) {
413 let mut nanosecond = self.nanosecond + duration.subsec_nanos();
414 let mut second = self.second + (duration.as_secs() % Second.per(Minute) as u64) as u8;
415 let mut minute = self.minute
416 + ((duration.as_secs() / Second.per(Minute) as u64) % Minute.per(Hour) as u64) as u8;
417 let mut hour = self.hour
418 + ((duration.as_secs() / Second.per(Hour) as u64) % Hour.per(Day) as u64) as u8;
419 let mut is_next_day = false;
420
421 cascade!(nanosecond in 0..Nanosecond.per(Second) => second);
422 cascade!(second in 0..Second.per(Minute) => minute);
423 cascade!(minute in 0..Minute.per(Hour) => hour);
424 if hour >= Hour.per(Day) {
425 hour -= Hour.per(Day);
426 is_next_day = true;
427 }
428
429 (
430 is_next_day,
431 Self::__from_hms_nanos_unchecked(hour, minute, second, nanosecond),
432 )
433 }
434
435 /// Subtract the sub-day time of the [`std::time::Duration`] to the `Time`. Wraps on overflow,
436 /// returning whether the date is the previous date as the first element of the tuple.
437 pub(crate) const fn adjusting_sub_std(self, duration: StdDuration) -> (bool, Self) {
438 let mut nanosecond = self.nanosecond as i32 - duration.subsec_nanos() as i32;
439 let mut second = self.second as i8 - (duration.as_secs() % Second.per(Minute) as u64) as i8;
440 let mut minute = self.minute as i8
441 - ((duration.as_secs() / Second.per(Minute) as u64) % Minute.per(Hour) as u64) as i8;
442 let mut hour = self.hour as i8
443 - ((duration.as_secs() / Second.per(Hour) as u64) % Hour.per(Day) as u64) as i8;
444 let mut is_previous_day = false;
445
446 cascade!(nanosecond in 0..Nanosecond.per(Second) as _ => second);
447 cascade!(second in 0..Second.per(Minute) as _ => minute);
448 cascade!(minute in 0..Minute.per(Hour) as _ => hour);
449 if hour < 0 {
450 hour += Hour.per(Day) as i8;
451 is_previous_day = true;
452 }
453
454 (
455 is_previous_day,
456 Self::__from_hms_nanos_unchecked(hour as _, minute as _, second as _, nanosecond as _),
457 )
458 }
459 // endregion arithmetic helpers
460
461 // region: replacement
462 /// Replace the clock hour.
463 ///
464 /// ```rust
465 /// # use time_macros::time;
466 /// assert_eq!(
467 /// time!(01:02:03.004_005_006).replace_hour(7),
468 /// Ok(time!(07:02:03.004_005_006))
469 /// );
470 /// assert!(time!(01:02:03.004_005_006).replace_hour(24).is_err()); // 24 isn't a valid hour
471 /// ```
472 #[must_use = "This method does not mutate the original `Time`."]
473 pub const fn replace_hour(self, hour: u8) -> Result<Self, error::ComponentRange> {
474 ensure_value_in_range!(hour in 0 => Hour.per(Day) - 1);
475 Ok(Self::__from_hms_nanos_unchecked(
476 hour,
477 self.minute,
478 self.second,
479 self.nanosecond,
480 ))
481 }
482
483 /// Replace the minutes within the hour.
484 ///
485 /// ```rust
486 /// # use time_macros::time;
487 /// assert_eq!(
488 /// time!(01:02:03.004_005_006).replace_minute(7),
489 /// Ok(time!(01:07:03.004_005_006))
490 /// );
491 /// assert!(time!(01:02:03.004_005_006).replace_minute(60).is_err()); // 60 isn't a valid minute
492 /// ```
493 #[must_use = "This method does not mutate the original `Time`."]
494 pub const fn replace_minute(self, minute: u8) -> Result<Self, error::ComponentRange> {
495 ensure_value_in_range!(minute in 0 => Minute.per(Hour) - 1);
496 Ok(Self::__from_hms_nanos_unchecked(
497 self.hour,
498 minute,
499 self.second,
500 self.nanosecond,
501 ))
502 }
503
504 /// Replace the seconds within the minute.
505 ///
506 /// ```rust
507 /// # use time_macros::time;
508 /// assert_eq!(
509 /// time!(01:02:03.004_005_006).replace_second(7),
510 /// Ok(time!(01:02:07.004_005_006))
511 /// );
512 /// assert!(time!(01:02:03.004_005_006).replace_second(60).is_err()); // 60 isn't a valid second
513 /// ```
514 #[must_use = "This method does not mutate the original `Time`."]
515 pub const fn replace_second(self, second: u8) -> Result<Self, error::ComponentRange> {
516 ensure_value_in_range!(second in 0 => Second.per(Minute) - 1);
517 Ok(Self::__from_hms_nanos_unchecked(
518 self.hour,
519 self.minute,
520 second,
521 self.nanosecond,
522 ))
523 }
524
525 /// Replace the milliseconds within the second.
526 ///
527 /// ```rust
528 /// # use time_macros::time;
529 /// assert_eq!(
530 /// time!(01:02:03.004_005_006).replace_millisecond(7),
531 /// Ok(time!(01:02:03.007))
532 /// );
533 /// assert!(time!(01:02:03.004_005_006).replace_millisecond(1_000).is_err()); // 1_000 isn't a valid millisecond
534 /// ```
535 #[must_use = "This method does not mutate the original `Time`."]
536 pub const fn replace_millisecond(
537 self,
538 millisecond: u16,
539 ) -> Result<Self, error::ComponentRange> {
540 ensure_value_in_range!(millisecond in 0 => Millisecond.per(Second) - 1);
541 Ok(Self::__from_hms_nanos_unchecked(
542 self.hour,
543 self.minute,
544 self.second,
545 millisecond as u32 * Nanosecond.per(Millisecond),
546 ))
547 }
548
549 /// Replace the microseconds within the second.
550 ///
551 /// ```rust
552 /// # use time_macros::time;
553 /// assert_eq!(
554 /// time!(01:02:03.004_005_006).replace_microsecond(7_008),
555 /// Ok(time!(01:02:03.007_008))
556 /// );
557 /// assert!(time!(01:02:03.004_005_006).replace_microsecond(1_000_000).is_err()); // 1_000_000 isn't a valid microsecond
558 /// ```
559 #[must_use = "This method does not mutate the original `Time`."]
560 pub const fn replace_microsecond(
561 self,
562 microsecond: u32,
563 ) -> Result<Self, error::ComponentRange> {
564 ensure_value_in_range!(microsecond in 0 => Microsecond.per(Second) - 1);
565 Ok(Self::__from_hms_nanos_unchecked(
566 self.hour,
567 self.minute,
568 self.second,
569 microsecond * Nanosecond.per(Microsecond) as u32,
570 ))
571 }
572
573 /// Replace the nanoseconds within the second.
574 ///
575 /// ```rust
576 /// # use time_macros::time;
577 /// assert_eq!(
578 /// time!(01:02:03.004_005_006).replace_nanosecond(7_008_009),
579 /// Ok(time!(01:02:03.007_008_009))
580 /// );
581 /// 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
582 /// ```
583 #[must_use = "This method does not mutate the original `Time`."]
584 pub const fn replace_nanosecond(self, nanosecond: u32) -> Result<Self, error::ComponentRange> {
585 ensure_value_in_range!(nanosecond in 0 => Nanosecond.per(Second) - 1);
586 Ok(Self::__from_hms_nanos_unchecked(
587 self.hour,
588 self.minute,
589 self.second,
590 nanosecond,
591 ))
592 }
593 // endregion replacement
594}
595
596// region: formatting & parsing
597#[cfg(feature = "formatting")]
598impl Time {
599 /// Format the `Time` using the provided [format description](crate::format_description).
600 pub fn format_into(
601 self,
602 output: &mut impl io::Write,
603 format: &(impl Formattable + ?Sized),
604 ) -> Result<usize, crate::error::Format> {
605 format.format_into(output, None, Some(self), None)
606 }
607
608 /// Format the `Time` using the provided [format description](crate::format_description).
609 ///
610 /// ```rust
611 /// # use time::format_description;
612 /// # use time_macros::time;
613 /// let format = format_description::parse("[hour]:[minute]:[second]")?;
614 /// assert_eq!(time!(12:00).format(&format)?, "12:00:00");
615 /// # Ok::<_, time::Error>(())
616 /// ```
617 pub fn format(
618 self,
619 format: &(impl Formattable + ?Sized),
620 ) -> Result<String, crate::error::Format> {
621 format.format(None, Some(self), None)
622 }
623}
624
625#[cfg(feature = "parsing")]
626impl Time {
627 /// Parse a `Time` from the input using the provided [format
628 /// description](crate::format_description).
629 ///
630 /// ```rust
631 /// # use time::Time;
632 /// # use time_macros::{time, format_description};
633 /// let format = format_description!("[hour]:[minute]:[second]");
634 /// assert_eq!(Time::parse("12:00:00", &format)?, time!(12:00));
635 /// # Ok::<_, time::Error>(())
636 /// ```
637 pub fn parse(
638 input: &str,
639 description: &(impl Parsable + ?Sized),
640 ) -> Result<Self, error::Parse> {
641 description.parse_time(input.as_bytes())
642 }
643}
644
645impl fmt::Display for Time {
646 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
647 let (value: u32, width: usize) = match self.nanosecond() {
648 nanos: u32 if nanos % 10 != 0 => (nanos, 9),
649 nanos: u32 if (nanos / 10) % 10 != 0 => (nanos / 10, 8),
650 nanos: u32 if (nanos / 100) % 10 != 0 => (nanos / 100, 7),
651 nanos: u32 if (nanos / 1_000) % 10 != 0 => (nanos / 1_000, 6),
652 nanos: u32 if (nanos / 10_000) % 10 != 0 => (nanos / 10_000, 5),
653 nanos: u32 if (nanos / 100_000) % 10 != 0 => (nanos / 100_000, 4),
654 nanos: u32 if (nanos / 1_000_000) % 10 != 0 => (nanos / 1_000_000, 3),
655 nanos: u32 if (nanos / 10_000_000) % 10 != 0 => (nanos / 10_000_000, 2),
656 nanos: u32 => (nanos / 100_000_000, 1),
657 };
658 write!(
659 f,
660 "{}:{:02}:{:02}.{value:0width$}",
661 self.hour, self.minute, self.second,
662 )
663 }
664}
665
666impl fmt::Debug for Time {
667 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
668 fmt::Display::fmt(self, f)
669 }
670}
671// endregion formatting & parsing
672
673// region: trait impls
674impl Add<Duration> for Time {
675 type Output = Self;
676
677 /// Add the sub-day time of the [`Duration`] to the `Time`. Wraps on overflow.
678 ///
679 /// ```rust
680 /// # use time::ext::NumericalDuration;
681 /// # use time_macros::time;
682 /// assert_eq!(time!(12:00) + 2.hours(), time!(14:00));
683 /// assert_eq!(time!(0:00:01) + (-2).seconds(), time!(23:59:59));
684 /// ```
685 fn add(self, duration: Duration) -> Self::Output {
686 self.adjusting_add(duration).1
687 }
688}
689
690impl Add<StdDuration> for Time {
691 type Output = Self;
692
693 /// Add the sub-day time of the [`std::time::Duration`] to the `Time`. Wraps on overflow.
694 ///
695 /// ```rust
696 /// # use time::ext::NumericalStdDuration;
697 /// # use time_macros::time;
698 /// assert_eq!(time!(12:00) + 2.std_hours(), time!(14:00));
699 /// assert_eq!(time!(23:59:59) + 2.std_seconds(), time!(0:00:01));
700 /// ```
701 fn add(self, duration: StdDuration) -> Self::Output {
702 self.adjusting_add_std(duration).1
703 }
704}
705
706impl_add_assign!(Time: Duration, StdDuration);
707
708impl Sub<Duration> for Time {
709 type Output = Self;
710
711 /// Subtract the sub-day time of the [`Duration`] from the `Time`. Wraps on overflow.
712 ///
713 /// ```rust
714 /// # use time::ext::NumericalDuration;
715 /// # use time_macros::time;
716 /// assert_eq!(time!(14:00) - 2.hours(), time!(12:00));
717 /// assert_eq!(time!(23:59:59) - (-2).seconds(), time!(0:00:01));
718 /// ```
719 fn sub(self, duration: Duration) -> Self::Output {
720 self.adjusting_sub(duration).1
721 }
722}
723
724impl Sub<StdDuration> for Time {
725 type Output = Self;
726
727 /// Subtract the sub-day time of the [`std::time::Duration`] from the `Time`. Wraps on overflow.
728 ///
729 /// ```rust
730 /// # use time::ext::NumericalStdDuration;
731 /// # use time_macros::time;
732 /// assert_eq!(time!(14:00) - 2.std_hours(), time!(12:00));
733 /// assert_eq!(time!(0:00:01) - 2.std_seconds(), time!(23:59:59));
734 /// ```
735 fn sub(self, duration: StdDuration) -> Self::Output {
736 self.adjusting_sub_std(duration).1
737 }
738}
739
740impl_sub_assign!(Time: Duration, StdDuration);
741
742impl Sub for Time {
743 type Output = Duration;
744
745 /// Subtract two `Time`s, returning the [`Duration`] between. This assumes both `Time`s are in
746 /// the same calendar day.
747 ///
748 /// ```rust
749 /// # use time::ext::NumericalDuration;
750 /// # use time_macros::time;
751 /// assert_eq!(time!(0:00) - time!(0:00), 0.seconds());
752 /// assert_eq!(time!(1:00) - time!(0:00), 1.hours());
753 /// assert_eq!(time!(0:00) - time!(1:00), (-1).hours());
754 /// assert_eq!(time!(0:00) - time!(23:00), (-23).hours());
755 /// ```
756 fn sub(self, rhs: Self) -> Self::Output {
757 let hour_diff = (self.hour as i8) - (rhs.hour as i8);
758 let minute_diff = (self.minute as i8) - (rhs.minute as i8);
759 let second_diff = (self.second as i8) - (rhs.second as i8);
760 let nanosecond_diff = (self.nanosecond as i32) - (rhs.nanosecond as i32);
761
762 let seconds = hour_diff as i64 * Second.per(Hour) as i64
763 + minute_diff as i64 * Second.per(Minute) as i64
764 + second_diff as i64;
765
766 let (seconds, nanoseconds) = if seconds > 0 && nanosecond_diff < 0 {
767 (seconds - 1, nanosecond_diff + Nanosecond.per(Second) as i32)
768 } else if seconds < 0 && nanosecond_diff > 0 {
769 (seconds + 1, nanosecond_diff - Nanosecond.per(Second) as i32)
770 } else {
771 (seconds, nanosecond_diff)
772 };
773
774 Duration::new_unchecked(seconds, nanoseconds)
775 }
776}
777// endregion trait impls
778