use std::io::Write;
use chrono::{DateTime, Utc, Local, LocalResult, TimeZone};
use ansi_term::{Color::Yellow, Style};
use crate::error::{Error::*, Result};
use crate::models::Entry;
use crate::database::{Database, DBVersion};
use crate::env::Env;
fn local_to_utc(t: DateTime<Utc>) -> Result<DateTime<Utc>> {
let local_time = match Local.from_local_datetime(&t.naive_utc()) {
LocalResult::None => return Err(NoneLocalTime(t.naive_utc().to_string())),
LocalResult::Single(t) => t,
LocalResult::Ambiguous(t1, t2) => return Err(AmbiguousLocalTime {
orig: t.naive_utc().to_string(),
t1: t1.naive_local(),
t2: t2.naive_local(),
}),
};
Ok(Utc.from_utc_datetime(&local_time.naive_utc()))
}
fn utc_to_local(t: DateTime<Utc>) -> DateTime<Utc> {
Utc.from_utc_datetime(&t.with_timezone(&Local).naive_local())
}
fn local_to_utc_vec(entries: Vec<Entry>) -> Result<Vec<Entry>> {
entries
.into_iter()
.map(|e| {
Ok(Entry {
start: local_to_utc(e.start)?,
end: e.end.map(local_to_utc).transpose()?,
..e
})
})
.collect()
}
pub fn entries_or_warning<D: Database>(entries: Vec<Entry>, db: &D) -> Result<(Vec<Entry>, bool)> {
if let DBVersion::Timetrap = db.version()? {
Ok((local_to_utc_vec(entries)?, true))
} else {
Ok((entries, false))
}
}
pub fn time_or_warning<D: Database>(time: DateTime<Utc>, db: &D) -> Result<(DateTime<Utc>, bool)> {
if let DBVersion::Timetrap = db.version()? {
Ok((utc_to_local(time), true))
} else {
Ok((time, false))
}
}
pub fn warn_if_needed<E: Write>(err: &mut E, needs_warning: bool, env: &Env) -> Result<()> {
if needs_warning && !env.supress_warming {
writeln!(
err,
"{} You are using the old timetrap format, it is advised that \
you update your database using t migrate. To supress this warning \
set TIEMPO_SUPRESS_TIMETRAP_WARNING=1",
if env.stderr_is_tty {
Yellow.bold().paint("[WARNING]")
} else {
Style::new().paint("[WARNING]")
},
).map_err(IOError)?;
}
Ok(())
}