flexible_time/timestamp/
start.rs1use crate::{
2 error::{ConversionError, Error},
3 timestamp::ParsedTimestamp,
4};
5use std::str::FromStr;
6use std::time::SystemTime;
7use time::{Date, Month, OffsetDateTime};
8
9#[derive(Copy, Clone, Debug, PartialEq, Eq)]
12pub struct StartTimestamp(pub OffsetDateTime);
13
14impl From<StartTimestamp> for OffsetDateTime {
15 fn from(value: StartTimestamp) -> Self {
16 value.0
17 }
18}
19
20impl From<StartTimestamp> for SystemTime {
21 fn from(value: StartTimestamp) -> Self {
22 value.0.into()
23 }
24}
25
26impl TryFrom<ParsedTimestamp> for StartTimestamp {
27 type Error = ConversionError;
28
29 fn try_from(value: ParsedTimestamp) -> Result<Self, Self::Error> {
30 Ok(StartTimestamp(match value {
31 ParsedTimestamp::Year(year) => Date::from_calendar_date(year, Month::January, 1)?
32 .midnight()
33 .assume_utc(),
34 ParsedTimestamp::YearMonth(year, month) => Date::from_calendar_date(year, month, 1)?
35 .midnight()
36 .assume_utc(),
37 ParsedTimestamp::YearMonthDay(year, month, day) => {
38 Date::from_calendar_date(year, month, day.get())?
39 .midnight()
40 .assume_utc()
41 }
42
43 ParsedTimestamp::YearMonthDayHour(year, month, day, hour) => {
44 Date::from_calendar_date(year, month, day.get())?
45 .with_hms(hour, 0, 0)?
46 .assume_utc()
47 }
48 ParsedTimestamp::YearMonthDayHourMinute(year, month, day, hour, minute) => {
49 Date::from_calendar_date(year, month, day.get())?
50 .with_hms(hour, minute, 0)?
51 .assume_utc()
52 }
53 ParsedTimestamp::YearMonthDayHourMinuteSecond(
54 year,
55 month,
56 day,
57 hour,
58 minute,
59 second,
60 ) => Date::from_calendar_date(year, month, day.get())?
61 .with_hms(hour, minute, second)?
62 .assume_utc(),
63 }))
64 }
65}
66
67impl FromStr for StartTimestamp {
68 type Err = Error;
69
70 fn from_str(s: &str) -> Result<Self, Self::Err> {
71 Ok(StartTimestamp::try_from(ParsedTimestamp::from_str(s)?)?)
72 }
73}
74
75#[cfg(test)]
76mod test {
77 use super::*;
78 use time::macros::datetime;
79 use time::OffsetDateTime;
80
81 macro_rules! assert_start {
82 ($name:ident, $s:literal, $dt:expr) => {
83 #[test]
84 fn $name() {
85 assert_eq!(
86 $dt,
87 OffsetDateTime::from(StartTimestamp::from_str($s).unwrap())
88 )
89 }
90 };
91 }
92
93 assert_start!(start_year, "2023", datetime!(2023-01-01 0:00 UTC));
94 assert_start!(start_year_month, "2023-02", datetime!(2023-02-01 0:00 UTC));
95 assert_start!(
96 start_year_month_day,
97 "2023-02-03",
98 datetime!(2023-02-03 0:00 UTC)
99 );
100
101 assert_start!(
102 start_year_month_day_hour_single,
103 "2023-02-03 4",
104 datetime!(2023-02-03 4:00 UTC)
105 );
106 assert_start!(
107 start_year_month_day_hour,
108 "2023-02-03 04",
109 datetime!(2023-02-03 4:00 UTC)
110 );
111
112 assert_start!(
113 start_year_month_day_hour_single_minute,
114 "2023-02-03 4:05",
115 datetime!(2023-02-03 4:05 UTC)
116 );
117 assert_start!(
118 start_year_month_day_hour_minute,
119 "2023-02-03 04:05",
120 datetime!(2023-02-03 4:05 UTC)
121 );
122
123 assert_start!(
124 start_year_month_day_hour_minute_second,
125 "2023-02-03 04:05:06",
126 datetime!(2023-02-03 4:05:06 UTC)
127 );
128 assert_start!(
129 start_year_month_day_hour_single_minute_second,
130 "2023-02-03 4:05:06",
131 datetime!(2023-02-03 4:05:06 UTC)
132 );
133
134 assert_start!(
135 start_year_month_day_hour_24h_minute_second,
136 "2023-02-03 16:05:06",
137 datetime!(2023-02-03 16:05:06 UTC)
138 );
139}