2020-08-29 23:16:33 +00:00
|
|
|
use std::time::{
|
|
|
|
SystemTime,
|
|
|
|
UNIX_EPOCH,
|
|
|
|
};
|
|
|
|
|
|
|
|
use chrono_tz::Tz;
|
2020-08-30 20:08:08 +00:00
|
|
|
use chrono::offset::Utc;
|
|
|
|
use chrono::{Timelike, Datelike, TimeZone};
|
2020-08-29 23:16:33 +00:00
|
|
|
|
|
|
|
enum ParseType {
|
|
|
|
Explicit,
|
|
|
|
Displacement,
|
|
|
|
}
|
|
|
|
|
|
|
|
struct TimeParser {
|
|
|
|
timezone: Tz,
|
|
|
|
inverted: bool,
|
|
|
|
time_string: String,
|
|
|
|
parse_type: ParseType,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl TimeParser {
|
|
|
|
pub fn new(input: String, timezone: Tz) -> Self {
|
|
|
|
let inverted = if input.starts_with("-") {
|
|
|
|
true
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
false
|
|
|
|
};
|
|
|
|
|
|
|
|
let parse_type = if input.contains("/") || input.contains(":") {
|
|
|
|
ParseType::Explicit
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ParseType::Displacement
|
|
|
|
};
|
|
|
|
|
|
|
|
Self {
|
|
|
|
timezone,
|
|
|
|
inverted,
|
|
|
|
time_string: input.trim_start_matches("-").to_string(),
|
|
|
|
parse_type,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn timestamp(&self) -> i32 {
|
2020-08-30 20:08:08 +00:00
|
|
|
0
|
2020-08-29 23:16:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn displacement(&self) -> i32 {
|
2020-08-30 20:08:08 +00:00
|
|
|
0
|
2020-08-29 23:16:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn process(&self) -> i32 {
|
|
|
|
match self.parse_type {
|
|
|
|
ParseType::Explicit => {
|
2020-08-30 20:08:08 +00:00
|
|
|
// TODO remove unwrap from here
|
|
|
|
self.process_explicit().unwrap()
|
2020-08-29 23:16:33 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
ParseType::Displacement => {
|
|
|
|
let now = SystemTime::now();
|
|
|
|
let since_epoch = now
|
|
|
|
.duration_since(UNIX_EPOCH)
|
|
|
|
.expect("Time calculated as going backwards. Very bad");
|
|
|
|
|
2020-08-30 20:08:08 +00:00
|
|
|
since_epoch.as_secs() as i32 + self.process_displacement()
|
2020-08-29 23:16:33 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-30 20:08:08 +00:00
|
|
|
fn process_explicit(&self) -> Result<i32, Box<dyn std::error::Error>> {
|
|
|
|
let dt = self.timezone.datetime_from_str(self.time_string.as_str(), "%d/%m/%Y-%H:%M:%S")?;
|
2020-08-29 23:16:33 +00:00
|
|
|
|
2020-08-30 20:08:08 +00:00
|
|
|
Ok(dt.timestamp() as i32)
|
2020-08-29 23:16:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn process_displacement(&self) -> i32 {
|
|
|
|
let mut current_buffer = "0".to_string();
|
|
|
|
|
2020-08-30 20:08:08 +00:00
|
|
|
let mut seconds = 0 as i32;
|
|
|
|
let mut minutes = 0 as i32;
|
|
|
|
let mut hours = 0 as i32;
|
|
|
|
let mut days = 0 as i32;
|
2020-08-29 23:16:33 +00:00
|
|
|
|
|
|
|
for character in self.time_string.chars() {
|
|
|
|
match character {
|
|
|
|
|
|
|
|
's' => {
|
2020-08-30 20:08:08 +00:00
|
|
|
seconds = current_buffer.parse::<i32>().unwrap();
|
2020-08-29 23:16:33 +00:00
|
|
|
current_buffer = String::from("0");
|
|
|
|
},
|
|
|
|
|
|
|
|
'm' => {
|
2020-08-30 20:08:08 +00:00
|
|
|
minutes = current_buffer.parse::<i32>().unwrap();
|
2020-08-29 23:16:33 +00:00
|
|
|
current_buffer = String::from("0");
|
|
|
|
},
|
|
|
|
|
|
|
|
'h' => {
|
2020-08-30 20:08:08 +00:00
|
|
|
hours = current_buffer.parse::<i32>().unwrap();
|
2020-08-29 23:16:33 +00:00
|
|
|
current_buffer = String::from("0");
|
|
|
|
},
|
|
|
|
|
|
|
|
'd' => {
|
2020-08-30 20:08:08 +00:00
|
|
|
days = current_buffer.parse::<i32>().unwrap();
|
2020-08-29 23:16:33 +00:00
|
|
|
current_buffer = String::from("0");
|
|
|
|
},
|
|
|
|
|
|
|
|
c => {
|
|
|
|
if c.is_digit(10) {
|
2020-08-30 20:08:08 +00:00
|
|
|
current_buffer += &c.to_string();
|
2020-08-29 23:16:33 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
// raise exception
|
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-30 20:08:08 +00:00
|
|
|
let full = seconds + (minutes * 60) + (hours * 3600) + (days * 86400) + current_buffer.parse::<i32>().unwrap() *
|
2020-08-29 23:16:33 +00:00
|
|
|
if self.inverted { -1 } else { 1 };
|
|
|
|
|
|
|
|
full
|
|
|
|
}
|
|
|
|
}
|