1use std::time::SystemTime;
5
6use chrono::naive::NaiveDate;
7use chrono::offset::FixedOffset;
8use chrono::offset::TimeZone as _;
9use chrono::DateTime;
10use chrono::ParseError;
11
12
13type DateFn = fn(&str) -> Result<DateTime<FixedOffset>, ParseError>;
14
15
16pub(crate) const TIME_PARSE_FNS: [DateFn; 3] = [
18 |s| FixedOffset::east(0).datetime_from_str(s, "%Y-%m-%dT%H:%M:%S%.fZ"),
19 |s| FixedOffset::east(0).datetime_from_str(s, "%Y-%m-%dT%H:%M:%SZ"),
20 |s| DateTime::parse_from_str(s, "%Y-%m-%dT%H:%M:%S%.f%z"),
21];
22
23pub(crate) const DATE_PARSE_FNS: [DateFn; 1] = [|s| {
24 NaiveDate::parse_from_str(s, "%Y-%m-%d")
25 .map(|date| DateTime::from_utc(date.and_hms(0, 0, 0), FixedOffset::east(0)))
26}];
27
28
29pub(crate) fn parse_system_time_from_str_impl(
32 time: &str,
33 parse_fns: &[DateFn],
34) -> Option<SystemTime> {
35 for parse_fn in parse_fns {
36 let datetime = match parse_fn(&time) {
39 Ok(datetime) => datetime,
40 Err(_) => continue,
41 };
42 return Some(SystemTime::from(
43 datetime.with_timezone(&FixedOffset::east(0)),
44 ))
45 }
46 None
47}
48
49
50pub fn parse_system_time_from_str(time: &str) -> Option<SystemTime> {
52 parse_system_time_from_str_impl(&time, &TIME_PARSE_FNS)
53}
54
55
56pub fn parse_system_time_from_date_str(time: &str) -> Option<SystemTime> {
58 parse_system_time_from_str_impl(&time, &DATE_PARSE_FNS)
59}
60
61
62#[cfg(test)]
63mod tests {
64 use super::*;
65
66 use std::time::Duration;
67 use std::time::UNIX_EPOCH;
68
69
70 #[test]
71 fn parse_time() {
72 let time = parse_system_time_from_str("2018-04-01T12:00:00.000Z").unwrap();
73 let expected = UNIX_EPOCH + Duration::from_secs(1_522_584_000);
74 assert_eq!(time, expected)
75 }
76
77 #[test]
79 fn parse_time_fail() {
80 let result = parse_system_time_from_str("2018-04-01TXX:00:00.000");
81 assert_eq!(result, None)
82 }
83
84 #[test]
85 fn parse_date() {
86 let time = parse_system_time_from_date_str("2019-08-01").unwrap();
87 let expected = UNIX_EPOCH + Duration::from_secs(1_564_617_600);
88 assert_eq!(time, expected)
89 }
90}