irox_time/format/
mod.rs

1// SPDX-License-Identifier: MIT
2// Copyright 2023 IROX Contributors
3
4//!
5//! Date Formatters
6//!
7//! | Letter | Component    | Description                                         | Repeated Ex.   | Example        |
8//! |--------|--------------|-----------------------------------------------------|----------------|----------------|
9//! |   Y    | Year         | Proleptic Gregorian Calendar Year                   | `YY` or `YYYY` | `05` or `2005` |
10//! |   M    | Month        | Month of the year as decimal 01-12                  | `M` or `MM`    | `01`           |
11//! |   D    | Day of Year  | Day of the year as decimal 01-366                   | `D` or `DDD`   | `075`          |
12//! |   d    | Day of Month | Day of the month as decimal 01-31                   | `d` or `dd`    | `09`           |
13//! |   H    | Hour         | Hour of day as decimal 00-24                        | `H` or `HH`    | `08`           |
14//! |   m    | Minute       | Minute of hour as decimal 00-59                     | `m` or `mm`    | `07`           |
15//! |   s    | Second       | Second of minute as decimal 00-59                   | `s` or `ss`    | `06`           |
16//! |   S    | Millis       | Millisecond of Second as decimal 000-999            | `S` or `SSS`   | `051`          |
17//! |   U    | Micros       | Microsecond of Second as decimal 000000-999999      | `U`            | `051020`       |
18//! |   N    | Nanos        | Nanosecond of Second as decimal 000000000-999999999 | `N`            | `051020946`    |
19//!
20//!
21
22use core::fmt::{Display, Formatter};
23use core::num::{ParseFloatError, ParseIntError};
24
25pub use alloc::string::{String, ToString};
26use irox_units::bounds::GreaterThanEqualToValueError;
27
28pub mod iso8601;
29pub mod rfc3339;
30
31///
32/// Provides a mechanism to translate a date or a time to a [`String`]
33pub trait Format<T> {
34    ///
35    /// Implementation-specific format of a date or time
36    fn format(&self, date: &T) -> alloc::string::String;
37}
38
39///
40/// Provides a mechanism to parse a date or time from a string.
41///
42pub trait FormatParser<T> {
43    ///
44    /// Tries to parse the specified string into the resultant item.
45    fn try_from(&self, data: &str) -> Result<T, FormatError>;
46}
47
48///
49/// Different format error conditions
50#[derive(Debug, Copy, Clone, Eq, PartialEq)]
51pub enum FormatErrorType {
52    IOError,
53    NumberFormatError,
54    OutOfRangeError,
55    Other,
56}
57
58///
59/// Error type returned by the [`FormatParser`]s and [`Format`]ters
60#[derive(Debug)]
61pub struct FormatError {
62    error_type: FormatErrorType,
63    msg: alloc::string::String,
64}
65
66impl Display for FormatError {
67    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
68        f.write_fmt(format_args!("{:?}{}", self.error_type, self.msg))
69    }
70}
71
72impl core::error::Error for FormatError {}
73
74impl FormatError {
75    /// Creates a new format error
76    #[must_use]
77    pub fn new(error_type: FormatErrorType, msg: alloc::string::String) -> FormatError {
78        FormatError { error_type, msg }
79    }
80
81    /// Helper for returning errors
82    pub fn err<T>(msg: alloc::string::String) -> Result<T, Self> {
83        Err(Self::new(FormatErrorType::Other, msg))
84    }
85
86    /// Helper for returning errors
87    pub fn err_str<T>(msg: &'static str) -> Result<T, Self> {
88        Err(Self::new(FormatErrorType::Other, msg.to_string()))
89    }
90}
91
92#[cfg(feature = "std")]
93impl From<std::io::Error> for FormatError {
94    fn from(value: std::io::Error) -> Self {
95        FormatError {
96            error_type: FormatErrorType::IOError,
97            msg: value.to_string(),
98        }
99    }
100}
101impl From<ParseIntError> for FormatError {
102    fn from(value: ParseIntError) -> Self {
103        FormatError {
104            error_type: FormatErrorType::NumberFormatError,
105            msg: value.to_string(),
106        }
107    }
108}
109impl From<ParseFloatError> for FormatError {
110    fn from(value: ParseFloatError) -> Self {
111        FormatError {
112            error_type: FormatErrorType::NumberFormatError,
113            msg: value.to_string(),
114        }
115    }
116}
117impl From<GreaterThanEqualToValueError<u8>> for FormatError {
118    fn from(value: GreaterThanEqualToValueError<u8>) -> Self {
119        FormatError {
120            error_type: FormatErrorType::OutOfRangeError,
121            msg: value.to_string(),
122        }
123    }
124}
125
126impl From<GreaterThanEqualToValueError<u16>> for FormatError {
127    fn from(value: GreaterThanEqualToValueError<u16>) -> Self {
128        FormatError {
129            error_type: FormatErrorType::OutOfRangeError,
130            msg: value.to_string(),
131        }
132    }
133}
134
135impl From<GreaterThanEqualToValueError<f64>> for FormatError {
136    fn from(value: GreaterThanEqualToValueError<f64>) -> Self {
137        FormatError {
138            error_type: FormatErrorType::OutOfRangeError,
139            msg: value.to_string(),
140        }
141    }
142}
143
144impl From<GreaterThanEqualToValueError<u32>> for FormatError {
145    fn from(value: GreaterThanEqualToValueError<u32>) -> Self {
146        FormatError {
147            error_type: FormatErrorType::OutOfRangeError,
148            msg: value.to_string(),
149        }
150    }
151}