1use anyhow::Context;
2use time::{Date, OffsetDateTime, PrimitiveDateTime, Time, macros::format_description};
3
4use crate::{Error, Result};
5use std::cmp;
6
7pub trait Parse {
8 fn parse(value: impl AsRef<str>) -> Result<Self>
9 where
10 Self: Sized;
11}
12
13impl Parse for Box<[u8]> {
14 fn parse(value: impl AsRef<str>) -> Result<Self> {
15 let value = value.as_ref();
16 Err(Error::msg(format!(
17 "Could not decode blob pattern: `{}{}`",
18 &value[..cmp::min(value.len(), 497)],
19 if value.len() > 497 { "..." } else { "" }
20 )))
21 }
22}
23
24impl Parse for Date {
25 fn parse(value: impl AsRef<str>) -> Result<Self>
26 where
27 Self: Sized,
28 {
29 time::Date::parse(value.as_ref(), format_description!("[year]-[month]-[day]"))
30 .with_context(|| format!("Cannot convert '{}' to time::Time", value.as_ref()))
31 }
32}
33
34impl Parse for Time {
35 fn parse(value: impl AsRef<str>) -> Result<Self>
36 where
37 Self: Sized,
38 {
39 let value = value.as_ref();
40 time::Time::parse(
41 value,
42 format_description!("[hour]:[minute]:[second].[subsecond]"),
43 )
44 .or(time::Time::parse(
45 value,
46 format_description!("[hour]:[minute]:[second]"),
47 ))
48 .or(time::Time::parse(
49 value,
50 format_description!("[hour]:[minute]"),
51 ))
52 .with_context(|| format!("Cannot convert '{}' to time::Time", value))
53 }
54}
55
56impl Parse for PrimitiveDateTime {
57 fn parse(value: impl AsRef<str>) -> Result<Self>
58 where
59 Self: Sized,
60 {
61 let value = value.as_ref();
62 time::PrimitiveDateTime::parse(
63 value,
64 format_description!("[year]-[month]-[day]T[hour]:[minute]:[second].[subsecond]"),
65 )
66 .or(time::PrimitiveDateTime::parse(
67 value,
68 format_description!("[year]-[month]-[day]T[hour]:[minute]:[second]"),
69 ))
70 .or(time::PrimitiveDateTime::parse(
71 value,
72 format_description!("[year]-[month]-[day]T[hour]:[minute]"),
73 ))
74 .or(time::PrimitiveDateTime::parse(
75 value,
76 format_description!("[year]-[month]-[day] [hour]:[minute]:[second].[subsecond]"),
77 ))
78 .or(time::PrimitiveDateTime::parse(
79 value,
80 format_description!("[year]-[month]-[day] [hour]:[minute]:[second]"),
81 ))
82 .or(time::PrimitiveDateTime::parse(
83 value,
84 format_description!("[year]-[month]-[day] [hour]:[minute]"),
85 ))
86 .with_context(|| format!("Cannot convert '{}' to time::PrimitiveDateTime", value))
87 }
88}
89
90impl Parse for OffsetDateTime {
91 fn parse(value: impl AsRef<str>) -> Result<Self>
92 where
93 Self: Sized,
94 {
95 let value = value.as_ref();
96 time::OffsetDateTime::parse(
97 value,
98 format_description!("[year]-[month]-[day]T[hour]:[minute]:[second].[subsecond][offset_hour sign:mandatory]:[offset_minute]")
99 )
100 .or(time::OffsetDateTime::parse(
101 value,
102 format_description!("[year]-[month]-[day]T[hour]:[minute]:[second].[subsecond][offset_hour sign:mandatory]")
103 ))
104 .or(time::OffsetDateTime::parse(
105 value,
106 format_description!("[year]-[month]-[day]T[hour]:[minute]:[second][offset_hour sign:mandatory]:[offset_minute]")
107 ))
108 .or(time::OffsetDateTime::parse(
109 value,
110 format_description!("[year]-[month]-[day]T[hour]:[minute]:[second][offset_hour sign:mandatory]")
111 ))
112 .or(time::OffsetDateTime::parse(
113 value,
114 format_description!("[year]-[month]-[day]T[hour]:[minute][offset_hour sign:mandatory]:[offset_minute]")
115 ))
116 .or(time::OffsetDateTime::parse(
117 value,
118 format_description!("[year]-[month]-[day]T[hour]:[minute][offset_hour sign:mandatory]")
119 ))
120 .with_context(|| format!("Cannot convert '{}' to time::OffsetDateTime", value))
121 }
122}