1use chrono::{DateTime, Datelike, Duration, Months, NaiveDate, TimeZone, Utc};
2use chrono_tz::Tz;
3use std::str::FromStr;
4use teaql_tool_core::{MustPurpose, Result, TeaQLToolError};
5
6pub struct TimeTool;
7
8impl TimeTool {
9 pub fn new() -> Self {
10 Self
11 }
12
13 pub fn now(&self) -> MustPurpose<DateTime<Utc>> {
14 MustPurpose::new(Utc::now())
15 }
16
17 pub fn today(&self) -> MustPurpose<NaiveDate> {
18 MustPurpose::new(Utc::now().date_naive())
19 }
20
21 pub fn parse_date(&self, s: &str) -> Result<MustPurpose<NaiveDate>> {
22 NaiveDate::from_str(s)
23 .map(MustPurpose::new)
24 .map_err(|e| TeaQLToolError::ParseError(e.to_string()))
25 }
26
27 pub fn parse_datetime(&self, s: &str) -> Result<MustPurpose<DateTime<Utc>>> {
28 s.parse::<DateTime<Utc>>()
29 .map(MustPurpose::new)
30 .map_err(|e| TeaQLToolError::ParseError(e.to_string()))
31 }
32
33 pub fn add_days(&self, dt: DateTime<Utc>, days: i64) -> MustPurpose<DateTime<Utc>> {
34 MustPurpose::new(dt + Duration::days(days))
35 }
36
37 pub fn add_months(&self, dt: DateTime<Utc>, months: u32) -> MustPurpose<DateTime<Utc>> {
38 MustPurpose::new(dt.checked_add_months(Months::new(months)).unwrap_or(dt))
39 }
40
41 pub fn start_of_day(&self, dt: DateTime<Utc>) -> MustPurpose<DateTime<Utc>> {
42 MustPurpose::new(
43 Utc.with_ymd_and_hms(dt.year(), dt.month(), dt.day(), 0, 0, 0)
44 .unwrap(),
45 )
46 }
47
48 pub fn end_of_day(&self, dt: DateTime<Utc>) -> MustPurpose<DateTime<Utc>> {
49 MustPurpose::new(self.start_of_day(dt).purpose("internal") + Duration::days(1) - Duration::nanoseconds(1))
50 }
51
52 pub fn days_between(&self, dt1: DateTime<Utc>, dt2: DateTime<Utc>) -> MustPurpose<i64> {
53 let dur = dt2.signed_duration_since(dt1);
54 MustPurpose::new(dur.num_days())
55 }
56
57 pub fn to_timezone(&self, dt: DateTime<Utc>, tz_str: &str) -> Result<MustPurpose<DateTime<Tz>>> {
58 let tz: Tz = tz_str
59 .parse()
60 .map_err(|e| TeaQLToolError::InvalidArgument(format!("{}", e)))?;
61 Ok(MustPurpose::new(dt.with_timezone(&tz)))
62 }
63}
64
65impl Default for TimeTool {
66 fn default() -> Self {
67 Self::new()
68 }
69}