use crate::errors::{FindError, ParseError, RequestError};
use anyhow::{anyhow, Result};
use chrono::{DateTime, Duration, Utc};
use chrono_tz::Tz::{self, Europe__Kiev};
use dateparser::parse;
use now::DateTimeNow;
use regex::Regex;
use reqwest::blocking::Response;
use serde_json::Value;
use std::fmt;
#[derive(Debug, Clone)]
pub struct Period {
pub start_time: DateTime<Tz>,
pub end_time: DateTime<Tz>,
}
impl Period {
pub fn from_string(start_time_str: &str, end_time_str: &str) -> Result<Self> {
let start_time: DateTime<Tz> = match parse(start_time_str) {
Ok(parsed) => parsed.with_timezone(&Europe__Kiev),
Err(_) => {
return Err(anyhow!(ParseError::InvalidStringProvided(String::from(
start_time_str
))));
}
};
let end_time: DateTime<Tz> = match parse(end_time_str) {
Ok(parsed) => parsed.with_timezone(&Europe__Kiev),
Err(_) => {
return Err(anyhow!(ParseError::InvalidStringProvided(String::from(
end_time_str
))));
}
};
Ok(Self {
start_time,
end_time,
})
}
pub fn from_timestamp(start_time_i64: i64, end_time_i64: i64) -> Result<Self> {
let start_time_i64 = start_time_i64.to_string();
let end_time_i64 = end_time_i64.to_string();
let start_time: DateTime<Tz> = match parse(&start_time_i64) {
Ok(parsed) => parsed.with_timezone(&Europe__Kiev),
Err(_) => {
return Err(anyhow!(ParseError::InvalidTimestampProvided(
start_time_i64
)));
}
};
let end_time: DateTime<Tz> = match parse(&end_time_i64) {
Ok(parsed) => parsed.with_timezone(&Europe__Kiev),
Err(_) => {
return Err(anyhow!(ParseError::InvalidTimestampProvided(end_time_i64)));
}
};
Ok(Self {
start_time,
end_time,
})
}
pub fn this_day() -> Self {
let today_date: DateTime<Tz> = Utc::now().with_timezone(&Europe__Kiev);
let start_time: DateTime<Tz> = today_date.beginning_of_day();
let end_time: DateTime<Tz> = today_date.end_of_day();
Self {
start_time,
end_time,
}
}
pub fn now() -> Self {
let start_time: DateTime<Tz> = Utc::now()
.checked_sub_signed(Duration::minutes(90))
.unwrap()
.with_timezone(&Europe__Kiev);
let end_time: DateTime<Tz> = start_time.end_of_day();
Self {
start_time,
end_time,
}
}
pub fn next_day() -> Self {
let today_date: DateTime<Tz> = Utc::now()
.with_timezone(&Europe__Kiev)
.checked_add_signed(Duration::days(1))
.unwrap();
let start_time: DateTime<Tz> = today_date.beginning_of_day();
let end_time: DateTime<Tz> = today_date.end_of_day();
Self {
start_time,
end_time,
}
}
pub fn day_from(start_time_str: &str) -> Result<Self> {
let parsed_date: DateTime<Tz> = match parse(start_time_str) {
Ok(parsed) => parsed.with_timezone(&Europe__Kiev),
Err(_) => {
return Err(anyhow!(ParseError::InvalidStringProvided(String::from(
start_time_str
))));
}
};
let start_time: DateTime<Tz> = parsed_date.beginning_of_day();
let end_time: DateTime<Tz> = parsed_date.end_of_day();
Ok(Self {
start_time,
end_time,
})
}
pub fn this_week() -> Self {
let today_date: DateTime<Tz> = Utc::now().with_timezone(&Europe__Kiev);
let start_time: DateTime<Tz> = today_date.beginning_of_week();
let end_time: DateTime<Tz> = today_date.end_of_week();
Self {
start_time,
end_time,
}
}
pub fn next_week() -> Self {
let today_date: DateTime<Tz> = Utc::now()
.with_timezone(&Europe__Kiev)
.checked_add_signed(Duration::weeks(1))
.unwrap();
let start_time: DateTime<Tz> = today_date.beginning_of_week();
let end_time: DateTime<Tz> = today_date.end_of_week();
Self {
start_time,
end_time,
}
}
pub fn week_from(start_time_str: &str) -> Result<Self> {
let parsed_date: DateTime<Tz> = match parse(start_time_str) {
Ok(parsed) => parsed.with_timezone(&Europe__Kiev),
Err(_) => {
return Err(anyhow!(ParseError::InvalidStringProvided(String::from(
start_time_str
))));
}
};
let start_time: DateTime<Tz> = parsed_date.beginning_of_week();
let end_time = parsed_date.end_of_week();
Ok(Self {
start_time,
end_time,
})
}
}
impl fmt::Display for Period {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(
f,
"start_time: {}, end_time: {}",
self.start_time, self.end_time
)
}
}
pub fn find(find_it: &str, search_here: &str) -> Result<bool> {
let regex: Regex = match Regex::new(find_it.to_lowercase().as_str()) {
Ok(compiled) => compiled,
Err(_) => {
return Err(anyhow!(FindError::InvalidRegexString(String::from(
find_it
))));
}
};
Ok(regex.find(search_here.to_lowercase().as_str()).is_some())
}
pub fn get_wrapper(get_response: reqwest::Result<Response>) -> Result<Value> {
match get_response {
Ok(value) => match value.status().as_u16() {
200 => match value.json::<serde_json::Value>() {
Ok(value) => Ok(value),
Err(_) => Err(anyhow!(RequestError::NotJson)),
},
_ => Err(anyhow!(RequestError::BadResponse(
String::from(value.status().canonical_reason().unwrap_or("")),
value.status().as_u16()
))),
},
Err(_) => Err(anyhow!(RequestError::GetFailed)),
}
}