dos_date_time/error/
dos_date_time.rs

1// SPDX-FileCopyrightText: 2025 Shun Sakai
2//
3// SPDX-License-Identifier: Apache-2.0 OR MIT
4
5//! Error types for [`DateTime`](crate::DateTime).
6
7use core::{error::Error, fmt};
8
9use crate::error::{DateRangeError, DateRangeErrorKind};
10
11/// The error type indicating that a [`DateTime`](crate::DateTime) was out of
12/// range.
13#[derive(Clone, Copy, Debug, Eq, PartialEq)]
14pub struct DateTimeRangeError(DateTimeRangeErrorKind);
15
16impl DateTimeRangeError {
17    pub(crate) const fn new(kind: DateTimeRangeErrorKind) -> Self {
18        Self(kind)
19    }
20
21    /// Returns the corresponding [`DateTimeRangeErrorKind`] for this error.
22    ///
23    /// # Examples
24    ///
25    /// ```
26    /// # use dos_date_time::{
27    /// #     DateTime,
28    /// #     error::DateTimeRangeErrorKind,
29    /// #     time::{
30    /// #         Time,
31    /// #         macros::{date, time},
32    /// #     },
33    /// # };
34    /// #
35    /// let err = DateTime::from_date_time(date!(1979-12-31), time!(23:59:59)).unwrap_err();
36    /// assert_eq!(err.kind(), DateTimeRangeErrorKind::Negative);
37    ///
38    /// let err = DateTime::from_date_time(date!(2108-01-01), Time::MIDNIGHT).unwrap_err();
39    /// assert_eq!(err.kind(), DateTimeRangeErrorKind::Overflow);
40    /// ```
41    #[must_use]
42    pub const fn kind(&self) -> DateTimeRangeErrorKind {
43        self.0
44    }
45}
46
47impl fmt::Display for DateTimeRangeError {
48    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49        self.kind().fmt(f)
50    }
51}
52
53impl Error for DateTimeRangeError {}
54
55impl From<DateTimeRangeErrorKind> for DateTimeRangeError {
56    fn from(kind: DateTimeRangeErrorKind) -> Self {
57        Self::new(kind)
58    }
59}
60
61impl From<DateRangeError> for DateTimeRangeError {
62    fn from(err: DateRangeError) -> Self {
63        match err.kind() {
64            DateRangeErrorKind::Negative => Self::new(DateTimeRangeErrorKind::Negative),
65            DateRangeErrorKind::Overflow => Self::new(DateTimeRangeErrorKind::Overflow),
66        }
67    }
68}
69
70/// Details of the error that caused a [`DateTimeRangeError`].
71#[derive(Clone, Copy, Debug, Eq, PartialEq)]
72pub enum DateTimeRangeErrorKind {
73    /// Value was negative.
74    ///
75    /// This means MS-DOS date and time were before "1980-01-01 00:00:00".
76    Negative,
77
78    /// Value was too big to be represented as [`DateTime`](crate::DateTime).
79    ///
80    /// This means MS-DOS date and time were after "2107-12-31 23:59:58".
81    Overflow,
82}
83
84impl fmt::Display for DateTimeRangeErrorKind {
85    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86        match self {
87            Self::Negative => write!(f, "MS-DOS date and time are before `1980-01-01 00:00:00`"),
88            Self::Overflow => write!(f, "MS-DOS date and time are after `2107-12-31 23:59:58`"),
89        }
90    }
91}
92
93#[cfg(test)]
94mod tests {
95    use super::*;
96
97    #[test]
98    fn clone_date_time_range_error() {
99        assert_eq!(
100            DateTimeRangeError::new(DateTimeRangeErrorKind::Negative).clone(),
101            DateTimeRangeError::new(DateTimeRangeErrorKind::Negative)
102        );
103        assert_eq!(
104            DateTimeRangeError::new(DateTimeRangeErrorKind::Overflow).clone(),
105            DateTimeRangeError::new(DateTimeRangeErrorKind::Overflow)
106        );
107    }
108
109    #[test]
110    fn copy_date_time_range_error() {
111        {
112            let a = DateTimeRangeError::new(DateTimeRangeErrorKind::Negative);
113            let b = a;
114            assert_eq!(a, b);
115        }
116
117        {
118            let a = DateTimeRangeError::new(DateTimeRangeErrorKind::Overflow);
119            let b = a;
120            assert_eq!(a, b);
121        }
122    }
123
124    #[test]
125    fn debug_date_time_range_error() {
126        assert_eq!(
127            format!(
128                "{:?}",
129                DateTimeRangeError::new(DateTimeRangeErrorKind::Negative)
130            ),
131            "DateTimeRangeError(Negative)"
132        );
133        assert_eq!(
134            format!(
135                "{:?}",
136                DateTimeRangeError::new(DateTimeRangeErrorKind::Overflow)
137            ),
138            "DateTimeRangeError(Overflow)"
139        );
140    }
141
142    #[test]
143    fn date_time_range_error_equality() {
144        assert_eq!(
145            DateTimeRangeError::new(DateTimeRangeErrorKind::Negative),
146            DateTimeRangeError::new(DateTimeRangeErrorKind::Negative)
147        );
148        assert_ne!(
149            DateTimeRangeError::new(DateTimeRangeErrorKind::Negative),
150            DateTimeRangeError::new(DateTimeRangeErrorKind::Overflow)
151        );
152        assert_ne!(
153            DateTimeRangeError::new(DateTimeRangeErrorKind::Overflow),
154            DateTimeRangeError::new(DateTimeRangeErrorKind::Negative)
155        );
156        assert_eq!(
157            DateTimeRangeError::new(DateTimeRangeErrorKind::Overflow),
158            DateTimeRangeError::new(DateTimeRangeErrorKind::Overflow)
159        );
160    }
161
162    #[test]
163    fn kind_date_time_range_error() {
164        assert_eq!(
165            DateTimeRangeError::new(DateTimeRangeErrorKind::Negative).kind(),
166            DateTimeRangeErrorKind::Negative
167        );
168        assert_eq!(
169            DateTimeRangeError::new(DateTimeRangeErrorKind::Overflow).kind(),
170            DateTimeRangeErrorKind::Overflow
171        );
172    }
173
174    #[test]
175    const fn kind_date_time_range_error_is_const_fn() {
176        const _: DateTimeRangeErrorKind =
177            DateTimeRangeError::new(DateTimeRangeErrorKind::Negative).kind();
178    }
179
180    #[test]
181    fn display_date_time_range_error() {
182        assert_eq!(
183            format!(
184                "{}",
185                DateTimeRangeError::new(DateTimeRangeErrorKind::Negative)
186            ),
187            "MS-DOS date and time are before `1980-01-01 00:00:00`"
188        );
189        assert_eq!(
190            format!(
191                "{}",
192                DateTimeRangeError::new(DateTimeRangeErrorKind::Overflow)
193            ),
194            "MS-DOS date and time are after `2107-12-31 23:59:58`"
195        );
196    }
197
198    #[test]
199    fn source_date_time_range_error() {
200        assert!(
201            DateTimeRangeError::new(DateTimeRangeErrorKind::Negative)
202                .source()
203                .is_none()
204        );
205        assert!(
206            DateTimeRangeError::new(DateTimeRangeErrorKind::Overflow)
207                .source()
208                .is_none()
209        );
210    }
211
212    #[test]
213    fn from_date_time_range_error_kind_to_date_time_range_error() {
214        assert_eq!(
215            DateTimeRangeError::from(DateTimeRangeErrorKind::Negative),
216            DateTimeRangeError::new(DateTimeRangeErrorKind::Negative)
217        );
218        assert_eq!(
219            DateTimeRangeError::from(DateTimeRangeErrorKind::Overflow),
220            DateTimeRangeError::new(DateTimeRangeErrorKind::Overflow)
221        );
222    }
223
224    #[test]
225    fn clone_date_time_range_error_kind() {
226        assert_eq!(
227            DateTimeRangeErrorKind::Negative.clone(),
228            DateTimeRangeErrorKind::Negative
229        );
230        assert_eq!(
231            DateTimeRangeErrorKind::Overflow.clone(),
232            DateTimeRangeErrorKind::Overflow
233        );
234    }
235
236    #[test]
237    fn copy_date_time_range_error_kind() {
238        {
239            let a = DateTimeRangeErrorKind::Negative;
240            let b = a;
241            assert_eq!(a, b);
242        }
243
244        {
245            let a = DateTimeRangeErrorKind::Overflow;
246            let b = a;
247            assert_eq!(a, b);
248        }
249    }
250
251    #[test]
252    fn debug_date_time_range_error_kind() {
253        assert_eq!(
254            format!("{:?}", DateTimeRangeErrorKind::Negative),
255            "Negative"
256        );
257        assert_eq!(
258            format!("{:?}", DateTimeRangeErrorKind::Overflow),
259            "Overflow"
260        );
261    }
262
263    #[test]
264    fn date_time_range_error_kind_equality() {
265        assert_eq!(
266            DateTimeRangeErrorKind::Negative,
267            DateTimeRangeErrorKind::Negative
268        );
269        assert_ne!(
270            DateTimeRangeErrorKind::Negative,
271            DateTimeRangeErrorKind::Overflow
272        );
273        assert_ne!(
274            DateTimeRangeErrorKind::Overflow,
275            DateTimeRangeErrorKind::Negative
276        );
277        assert_eq!(
278            DateTimeRangeErrorKind::Overflow,
279            DateTimeRangeErrorKind::Overflow
280        );
281    }
282
283    #[test]
284    fn display_date_time_range_error_kind() {
285        assert_eq!(
286            format!("{}", DateTimeRangeErrorKind::Negative),
287            "MS-DOS date and time are before `1980-01-01 00:00:00`"
288        );
289        assert_eq!(
290            format!("{}", DateTimeRangeErrorKind::Overflow),
291            "MS-DOS date and time are after `2107-12-31 23:59:58`"
292        );
293    }
294}