finance_query/constants/enums/
time_range.rs1use serde::{Deserialize, Serialize};
2
3use super::Interval;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
10pub enum TimeRange {
11 #[serde(rename = "1d")]
13 OneDay,
14 #[serde(rename = "5d", alias = "1wk")]
16 FiveDays,
17 #[serde(rename = "1mo")]
19 OneMonth,
20 #[serde(rename = "3mo")]
22 ThreeMonths,
23 #[serde(rename = "6mo")]
25 SixMonths,
26 #[serde(rename = "1y")]
28 OneYear,
29 #[serde(rename = "2y")]
31 TwoYears,
32 #[serde(rename = "5y")]
34 FiveYears,
35 #[serde(rename = "10y")]
37 TenYears,
38 #[serde(rename = "ytd")]
40 YearToDate,
41 #[serde(rename = "max")]
43 Max,
44}
45
46impl TimeRange {
47 pub fn as_str(&self) -> &'static str {
49 match self {
50 TimeRange::OneDay => "1d",
51 TimeRange::FiveDays => "5d",
52 TimeRange::OneMonth => "1mo",
53 TimeRange::ThreeMonths => "3mo",
54 TimeRange::SixMonths => "6mo",
55 TimeRange::OneYear => "1y",
56 TimeRange::TwoYears => "2y",
57 TimeRange::FiveYears => "5y",
58 TimeRange::TenYears => "10y",
59 TimeRange::YearToDate => "ytd",
60 TimeRange::Max => "max",
61 }
62 }
63
64 pub fn default_interval(&self) -> Interval {
68 match self {
69 TimeRange::OneDay => Interval::FiveMinutes,
70 TimeRange::FiveDays => Interval::FifteenMinutes,
71 TimeRange::OneMonth
72 | TimeRange::ThreeMonths
73 | TimeRange::SixMonths
74 | TimeRange::OneYear
75 | TimeRange::YearToDate => Interval::OneDay,
76 TimeRange::TwoYears | TimeRange::FiveYears => Interval::OneWeek,
77 TimeRange::TenYears | TimeRange::Max => Interval::OneMonth,
78 }
79 }
80
81 pub const fn approx_duration_secs(&self) -> i64 {
86 const DAY: i64 = 86_400;
87 match self {
88 TimeRange::OneDay => DAY,
89 TimeRange::FiveDays => 5 * DAY,
90 TimeRange::OneMonth => 30 * DAY,
91 TimeRange::ThreeMonths => 90 * DAY,
92 TimeRange::SixMonths => 180 * DAY,
93 TimeRange::OneYear | TimeRange::YearToDate => 365 * DAY,
94 TimeRange::TwoYears => 730 * DAY,
95 TimeRange::FiveYears => 1_825 * DAY,
96 TimeRange::TenYears => 3_650 * DAY,
97 TimeRange::Max => 36_500 * DAY,
98 }
99 }
100}
101
102impl std::fmt::Display for TimeRange {
103 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
104 f.write_str(self.as_str())
105 }
106}
107
108impl std::str::FromStr for TimeRange {
109 type Err = ();
110
111 fn from_str(s: &str) -> Result<Self, Self::Err> {
115 match s.trim().to_lowercase().as_str() {
116 "1d" => Ok(TimeRange::OneDay),
117 "5d" | "1wk" => Ok(TimeRange::FiveDays),
118 "1mo" => Ok(TimeRange::OneMonth),
119 "3mo" => Ok(TimeRange::ThreeMonths),
120 "6mo" => Ok(TimeRange::SixMonths),
121 "1y" => Ok(TimeRange::OneYear),
122 "2y" => Ok(TimeRange::TwoYears),
123 "5y" => Ok(TimeRange::FiveYears),
124 "10y" => Ok(TimeRange::TenYears),
125 "ytd" => Ok(TimeRange::YearToDate),
126 "max" => Ok(TimeRange::Max),
127 _ => Err(()),
128 }
129 }
130}
131
132#[cfg(test)]
133mod tests {
134 use super::*;
135
136 #[test]
137 fn test_time_range_as_str() {
138 assert_eq!(TimeRange::OneDay.as_str(), "1d");
139 assert_eq!(TimeRange::OneMonth.as_str(), "1mo");
140 assert_eq!(TimeRange::OneYear.as_str(), "1y");
141 assert_eq!(TimeRange::Max.as_str(), "max");
142 }
143
144 #[test]
145 fn test_time_range_from_str_round_trips_as_str() {
146 for range in [
147 TimeRange::OneDay,
148 TimeRange::FiveDays,
149 TimeRange::OneMonth,
150 TimeRange::ThreeMonths,
151 TimeRange::SixMonths,
152 TimeRange::OneYear,
153 TimeRange::TwoYears,
154 TimeRange::FiveYears,
155 TimeRange::TenYears,
156 TimeRange::YearToDate,
157 TimeRange::Max,
158 ] {
159 assert_eq!(range.as_str().parse(), Ok(range));
160 }
161 assert_eq!("1wk".parse(), Ok(TimeRange::FiveDays));
162 assert_eq!("YTD".parse(), Ok(TimeRange::YearToDate));
163 assert_eq!("bogus".parse::<TimeRange>(), Err(()));
164 }
165
166 #[test]
167 fn test_default_interval_buckets() {
168 assert_eq!(TimeRange::OneDay.default_interval(), Interval::FiveMinutes);
170 assert_eq!(
171 TimeRange::FiveDays.default_interval(),
172 Interval::FifteenMinutes
173 );
174 assert_eq!(TimeRange::OneMonth.default_interval(), Interval::OneDay);
175 assert_eq!(TimeRange::OneYear.default_interval(), Interval::OneDay);
176 assert_eq!(TimeRange::TwoYears.default_interval(), Interval::OneWeek);
177 assert_eq!(TimeRange::Max.default_interval(), Interval::OneMonth);
178 }
179}