flexible_time/
primitives.rs1use crate::error::ParsingError;
4use crate::timestamp::ParsedTimestamp;
5use time::{macros::format_description, parsing::Parsed};
6
7pub fn parse_format_opt<F>(
8 input: &[u8],
9 items: &[::time::format_description::FormatItem<'_>],
10 f: F,
11) -> Result<ParsedTimestamp, ParsingError>
12where
13 F: FnOnce(Parsed) -> Option<ParsedTimestamp>,
14{
15 let mut parsed = Parsed::new();
16
17 let result = parsed.parse_items(input, items)?;
18
19 if !result.is_empty() {
20 return Err(ParsingError::RemainingInformation);
21 }
22
23 f(parsed).ok_or(ParsingError::MissingInformation)
24}
25
26pub fn parse_year(input: &[u8]) -> Result<ParsedTimestamp, ParsingError> {
28 let format = format_description!("[year]");
29
30 parse_format_opt(input, format, |parsed| {
31 Some(ParsedTimestamp::Year(parsed.year()?))
32 })
33}
34
35pub fn parse_year_month(input: &[u8]) -> Result<ParsedTimestamp, ParsingError> {
37 let format = format_description!("[year]-[month]");
38
39 parse_format_opt(input, format, |parsed| {
40 Some(ParsedTimestamp::YearMonth(parsed.year()?, parsed.month()?))
41 })
42}
43
44pub fn parse_year_month_day(input: &[u8]) -> Result<ParsedTimestamp, ParsingError> {
46 let format = format_description!("[year]-[month]-[day]");
47
48 parse_format_opt(input, format, |parsed| {
49 Some(ParsedTimestamp::YearMonthDay(
50 parsed.year()?,
51 parsed.month()?,
52 parsed.day()?,
53 ))
54 })
55}
56
57pub fn parse_year_month_day_hour(input: &[u8]) -> Result<ParsedTimestamp, ParsingError> {
59 let format = format_description!("[year]-[month]-[day][first [T] [ ]][hour padding:none]");
60
61 parse_format_opt(input, format, |parsed| {
62 Some(ParsedTimestamp::YearMonthDayHour(
63 parsed.year()?,
64 parsed.month()?,
65 parsed.day()?,
66 parsed.hour_24()?,
67 ))
68 })
69}
70
71pub fn parse_year_month_day_hour_minute(input: &[u8]) -> Result<ParsedTimestamp, ParsingError> {
73 let format =
74 format_description!("[year]-[month]-[day][first [T] [ ]][hour padding:none]:[minute]");
75
76 parse_format_opt(input, format, |parsed| {
77 Some(ParsedTimestamp::YearMonthDayHourMinute(
78 parsed.year()?,
79 parsed.month()?,
80 parsed.day()?,
81 parsed.hour_24()?,
82 parsed.minute()?,
83 ))
84 })
85}
86
87pub fn parse_year_month_day_hour_minute_second(
89 input: &[u8],
90) -> Result<ParsedTimestamp, ParsingError> {
91 let format = format_description!(
92 "[year]-[month]-[day][first [T] [ ]][hour padding:none]:[minute]:[second]"
93 );
94
95 parse_format_opt(input, format, |parsed| {
96 Some(ParsedTimestamp::YearMonthDayHourMinuteSecond(
97 parsed.year()?,
98 parsed.month()?,
99 parsed.day()?,
100 parsed.hour_24()?,
101 parsed.minute()?,
102 parsed.second()?,
103 ))
104 })
105}
106
107#[cfg(test)]
108mod test {
109 use super::*;
110
111 #[test]
112 fn test_optional() {
113 let format =
114 format_description!("[year]-[month]-[day][first [T] [ ]][hour]:[minute]:[second]");
115 let mut parsed = Parsed::new();
116 parsed.parse_items(b"2023-01-01 12:34:56", &format).unwrap();
117 parsed.parse_items(b"2023-01-01T12:34:56", &format).unwrap();
118 }
119}