use std::path::PathBuf;
use chrono::naive::NaiveDateTime;
use chrono::Datelike;
use chrono::Timelike;
use libimagstore::storeid::StoreId;
use crate::datepath::accuracy::Accuracy;
use crate::datepath::format::Format;
use failure::Fallible as Result;
pub struct DatePathCompiler {
accuracy : Accuracy,
format : Format,
}
impl DatePathCompiler {
pub fn new(accuracy: Accuracy, format: Format) -> DatePathCompiler {
DatePathCompiler {
accuracy,
format,
}
}
pub fn compile(&self, module_name: &str, datetime: &NaiveDateTime) -> Result<StoreId> {
let mut s = format!("{}/", module_name);
if self.accuracy.has_year_accuracy() {
s.push_str(&format!("{:04}", datetime.year()));
}
if self.accuracy.has_month_accuracy() {
match self.format {
Format::ElementIsFolder
| Format::DaysAreFolder
| Format::MonthIsFolder
| Format::YearIsFolder
=> s.push_str(&format!("/{:02}", datetime.month())),
}
}
if self.accuracy.has_day_accuracy() {
match self.format {
Format::ElementIsFolder
| Format::DaysAreFolder
| Format::MonthIsFolder
=> s.push_str(&format!("/{:02}", datetime.day())),
Format::YearIsFolder
=> s.push_str(&format!("-{:02}", datetime.day())),
}
}
if self.accuracy.has_hour_accuracy() {
match self.format {
Format::ElementIsFolder
| Format::DaysAreFolder
=> s.push_str(&format!("/{:02}", datetime.hour())),
Format::YearIsFolder
| Format::MonthIsFolder
=> s.push_str(&format!("-{:02}", datetime.hour())),
}
}
if self.accuracy.has_minute_accuracy() {
match self.format {
Format::ElementIsFolder
=> s.push_str(&format!("/{:02}", datetime.minute())),
Format::YearIsFolder
| Format::MonthIsFolder
| Format::DaysAreFolder
=> s.push_str(&format!("-{:02}", datetime.minute())),
}
}
if self.accuracy.has_second_accuracy() {
match self.format {
Format::ElementIsFolder
=> s.push_str(&format!("/{:02}", datetime.second())),
Format::YearIsFolder
| Format::MonthIsFolder
| Format::DaysAreFolder
=> s.push_str(&format!("-{:02}", datetime.second())),
}
}
StoreId::new(PathBuf::from(s))
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::datepath::accuracy::Accuracy;
use crate::datepath::format::Format;
use chrono::naive::NaiveDate;
use chrono::naive::NaiveDateTime;
#[test]
fn test_compiler_compile_simple() {
let dt = NaiveDate::from_ymd(2000, 1, 1).and_hms(0, 0, 0);
let compiler = DatePathCompiler::new(Accuracy::default(), Format::default());
let res = compiler.compile("testmodule", &dt);
assert!(res.is_ok());
let res = res.unwrap();
let s = res.to_str();
assert!(s.is_ok());
let s = s.unwrap();
assert_eq!("testmodule/2000/01/01/00/00/00", s);
}
fn test_accuracy(acc: Accuracy, dt: NaiveDateTime, modname: &str, matchstr: &str) {
let compiler = DatePathCompiler::new(acc, Format::default());
let res = compiler.compile(modname, &dt);
assert!(res.is_ok());
let res = res.unwrap();
let s = res.to_str();
assert!(s.is_ok());
let s = s.unwrap();
assert_eq!(matchstr, s);
}
#[test]
fn test_compiler_compile_year_accuracy() {
let dt = NaiveDate::from_ymd(2000, 1, 1).and_hms(0, 0, 0);
test_accuracy(Accuracy::Year, dt, "module", "module/2000");
}
#[test]
fn test_compiler_compile_month_accuracy() {
let dt = NaiveDate::from_ymd(2000, 1, 1).and_hms(0, 0, 0);
test_accuracy(Accuracy::Month, dt, "module", "module/2000/01");
}
#[test]
fn test_compiler_compile_day_accuracy() {
let dt = NaiveDate::from_ymd(2000, 1, 1).and_hms(0, 0, 0);
test_accuracy(Accuracy::Day, dt, "module", "module/2000/01/01");
}
#[test]
fn test_compiler_compile_year_paddning() {
let dt = NaiveDate::from_ymd(1, 1, 1).and_hms(0, 0, 0);
test_accuracy(Accuracy::Day, dt, "module", "module/0001/01/01");
}
}