Skip to main content

teaql_tool_std/
time.rs

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