|
3 | 3 | use bitflags::bitflags;
|
4 | 4 | use core::fmt::{self, Display, Formatter};
|
5 | 5 |
|
| 6 | +newtype_enum! { |
| 7 | + /// Error returned by [`Time`] methods if the specified field |
| 8 | + /// is outside of the valid range. |
| 9 | + pub enum TimeError: u32 => { |
| 10 | + YEAR = 0, |
| 11 | + MONTH = 1, |
| 12 | + DAY = 2, |
| 13 | + HOUR = 3 , |
| 14 | + MINUTE = 4 , |
| 15 | + SECOND = 5, |
| 16 | + NANOSECOND = 6, |
| 17 | + TIMEZONE = 7 , |
| 18 | + DAYLIGHT = 8, |
| 19 | + } |
| 20 | +} |
| 21 | + |
| 22 | +impl Display for TimeError { |
| 23 | + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { |
| 24 | + match *self { |
| 25 | + Self::YEAR => write!(f, "year not within `1900..=9999`"), |
| 26 | + Self::MONTH => write!(f, "month not within `1..=12"), |
| 27 | + Self::DAY => write!(f, "day not within `1..=31`"), |
| 28 | + Self::HOUR => write!(f, "hour not within `0..=23`"), |
| 29 | + Self::MINUTE => write!(f, "minute not within `0..=59`"), |
| 30 | + Self::SECOND => write!(f, "second not within `0..=59`"), |
| 31 | + Self::NANOSECOND => write!(f, "nanosecond not within `0..=999_999_999`"), |
| 32 | + Self::TIMEZONE => write!( |
| 33 | + f, |
| 34 | + "time_zone not `Time::UNSPECIFIED_TIMEZONE` nor within `-1440..=1440`" |
| 35 | + ), |
| 36 | + Self::DAYLIGHT => write!(f, "unknown bits set for daylight"), |
| 37 | + Self(9_u32..=u32::MAX) => panic!(), |
| 38 | + } |
| 39 | + } |
| 40 | +} |
| 41 | + |
6 | 42 | /// Date and time representation.
|
7 | 43 | #[derive(Debug, Default, Copy, Clone, Eq)]
|
8 | 44 | #[repr(C)]
|
@@ -64,18 +100,29 @@ impl Time {
|
64 | 100 | }
|
65 | 101 | }
|
66 | 102 |
|
67 |
| - /// True if all fields are within valid ranges, false otherwise. |
68 |
| - #[must_use] |
69 |
| - pub fn is_valid(&self) -> bool { |
70 |
| - (1900..=9999).contains(&self.year) |
71 |
| - && (1..=12).contains(&self.month) |
72 |
| - && (1..=31).contains(&self.day) |
73 |
| - && self.hour <= 23 |
74 |
| - && self.minute <= 59 |
75 |
| - && self.second <= 59 |
76 |
| - && self.nanosecond <= 999_999_999 |
77 |
| - && ((-1440..=1440).contains(&self.time_zone) |
78 |
| - || self.time_zone == Self::UNSPECIFIED_TIMEZONE) |
| 103 | + /// `Ok()` if all fields are within valid ranges, `Err(TimeError)` otherwise. |
| 104 | + pub fn is_valid(&self) -> Result<(), TimeError> { |
| 105 | + if !(1900..=9999).contains(&self.year) { |
| 106 | + Err(TimeError::YEAR) |
| 107 | + } else if !(1..=12).contains(&self.month) { |
| 108 | + Err(TimeError::MONTH) |
| 109 | + } else if !(1..=31).contains(&self.day) { |
| 110 | + Err(TimeError::DAY) |
| 111 | + } else if self.hour > 23 { |
| 112 | + Err(TimeError::HOUR) |
| 113 | + } else if self.minute > 59 { |
| 114 | + Err(TimeError::MINUTE) |
| 115 | + } else if self.second > 59 { |
| 116 | + Err(TimeError::SECOND) |
| 117 | + } else if self.nanosecond > 999_999_999 { |
| 118 | + Err(TimeError::NANOSECOND) |
| 119 | + } else if !((-1440..=1440).contains(&self.time_zone) |
| 120 | + || self.time_zone == Self::UNSPECIFIED_TIMEZONE) |
| 121 | + { |
| 122 | + Err(TimeError::TIMEZONE) |
| 123 | + } else { |
| 124 | + Ok(()) |
| 125 | + } |
79 | 126 | }
|
80 | 127 | }
|
81 | 128 |
|
|
0 commit comments