teaql_tool_std/
daterange.rs1use chrono::{DateTime, Duration, Local, NaiveTime, Timelike};
2
3#[derive(Debug, Clone, PartialEq)]
4pub struct DateRange {
5 pub start: DateTime<Local>,
6 pub end: DateTime<Local>,
7}
8
9impl DateRange {
10 pub fn new(start: DateTime<Local>, end: DateTime<Local>) -> Self {
11 Self { start, end }
12 }
13}
14
15pub struct DateRangeTool;
16
17impl DateRangeTool {
18 pub fn new() -> Self {
19 Self
20 }
21
22 fn begin_of_day(&self, dt: DateTime<Local>) -> DateTime<Local> {
24 dt.with_time(NaiveTime::from_hms_opt(0, 0, 0).unwrap()).unwrap()
25 }
26
27 fn end_of_day(&self, dt: DateTime<Local>) -> DateTime<Local> {
29 dt.with_time(NaiveTime::from_hms_nano_opt(23, 59, 59, 999_999_999).unwrap()).unwrap()
30 }
31
32 pub fn today(&self) -> DateRange {
33 self.offset_day(0)
34 }
35
36 pub fn yesterday(&self) -> DateRange {
37 self.offset_day(-1)
38 }
39
40 pub fn tomorrow(&self) -> DateRange {
41 self.offset_day(1)
42 }
43
44 pub fn offset_day(&self, n: i64) -> DateRange {
45 let the_day = Local::now() + Duration::days(n);
46 DateRange::new(self.begin_of_day(the_day), self.end_of_day(the_day))
47 }
48
49 pub fn last_n_days(&self, n: i64) -> Option<DateRange> {
50 if n <= 0 {
51 return None;
52 }
53 let yesterday = Local::now() - Duration::days(1);
54 let start_day = yesterday - Duration::days(n - 1);
55 Some(DateRange::new(self.begin_of_day(start_day), self.end_of_day(yesterday)))
56 }
57
58 pub fn next_n_days(&self, n: i64) -> Option<DateRange> {
59 if n <= 0 {
60 return None;
61 }
62 let tomorrow = Local::now() + Duration::days(1);
63 let end_day = tomorrow + Duration::days(n - 1);
64 Some(DateRange::new(self.begin_of_day(tomorrow), self.end_of_day(end_day)))
65 }
66
67 fn begin_of_hour(&self, dt: DateTime<Local>) -> DateTime<Local> {
69 dt.with_time(NaiveTime::from_hms_opt(dt.time().hour(), 0, 0).unwrap()).unwrap()
70 }
71
72 fn end_of_hour(&self, dt: DateTime<Local>) -> DateTime<Local> {
74 dt.with_time(NaiveTime::from_hms_nano_opt(dt.time().hour(), 59, 59, 999_999_999).unwrap()).unwrap()
75 }
76
77 pub fn this_hour(&self) -> DateRange {
78 self.offset_hour(0)
79 }
80
81 pub fn last_hour(&self) -> DateRange {
82 self.offset_hour(-1)
83 }
84
85 pub fn next_hour(&self) -> DateRange {
86 self.offset_hour(1)
87 }
88
89 pub fn offset_hour(&self, n: i64) -> DateRange {
90 let the_hour = Local::now() + Duration::hours(n);
91 DateRange::new(self.begin_of_hour(the_hour), self.end_of_hour(the_hour))
92 }
93
94 pub fn last_n_hours(&self, n: i64) -> Option<DateRange> {
95 if n <= 0 {
96 return None;
97 }
98 let last_hr = Local::now() - Duration::hours(1);
99 let start_hr = last_hr - Duration::hours(n - 1);
100 Some(DateRange::new(self.begin_of_hour(start_hr), self.end_of_hour(last_hr)))
101 }
102
103 pub fn next_n_hours(&self, n: i64) -> Option<DateRange> {
104 if n <= 0 {
105 return None;
106 }
107 let next_hr = Local::now() + Duration::hours(1);
108 let end_hr = next_hr + Duration::hours(n - 1);
109 Some(DateRange::new(self.begin_of_hour(next_hr), self.end_of_hour(end_hr)))
110 }
111}
112
113impl Default for DateRangeTool {
114 fn default() -> Self {
115 Self::new()
116 }
117}