diff --git a/src/calendar.rs b/src/calendar.rs index 87d7507..473570b 100644 --- a/src/calendar.rs +++ b/src/calendar.rs @@ -1,19 +1,16 @@ use chrono::{TimeDelta, prelude::*}; -use chrono_tz::Tz; use std::error::Error; use std::fmt; #[derive(PartialEq, Debug)] pub enum CalendarError { - TimezoneConversionFailed(String), + TimezoneConversionFailed, } impl fmt::Display for CalendarError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let message = match *self { - Self::TimezoneConversionFailed(ref tz) => { - format!("Could not convert time to timezone: {}", tz) - } + Self::TimezoneConversionFailed => "Could not convert time to timezone: {}", }; f.write_str(&message) @@ -30,11 +27,11 @@ fn create_timetable_vecs(time: &NaiveTime, padding_hrs: i8) -> Vec { .collect() } -pub fn create_timetable( +pub fn create_timetable( target_time: &NaiveTime, target_date: &NaiveDate, - local_timezone: &Tz, - target_timezone: &Tz, + local_timezone: &TzLocal, + target_timezone: &TzTarget, padding_hrs: i8, ) -> Result, CalendarError> { let datetime = local_timezone @@ -43,9 +40,7 @@ pub fn create_timetable( target_time.clone(), )) .single() - .ok_or_else(|| { - CalendarError::TimezoneConversionFailed(local_timezone.name().to_string()) - })?; + .ok_or_else(|| CalendarError::TimezoneConversionFailed)?; let time_in_timezone = datetime.with_timezone(target_timezone); Ok(create_timetable_vecs(&time_in_timezone.time(), padding_hrs)) diff --git a/src/cli.rs b/src/cli.rs index 8266691..a58bd29 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -1,8 +1,9 @@ use super::calendar::{create_timetable, get_todays_date}; +use chrono::Local; use chrono::NaiveDate; use chrono::NaiveTime; -use chrono_tz::Etc::UTC; +use chrono::TimeZone; use chrono_tz::Tz; use clap::Parser; use colored::Colorize; @@ -30,7 +31,7 @@ pub enum CliError { CouldNotParseTime, CouldNotParseDate, CouldNotParseTimezone(String), - CouldNoGenerateTimetable(String), + CouldNotGenerateTimetable(String), } impl fmt::Display for CliError { @@ -41,7 +42,7 @@ impl fmt::Display for CliError { Self::CouldNotParseTimezone(ref tz) => { format!("Couldn't parse timezone {}", tz).to_string() } - Self::CouldNoGenerateTimetable(ref er) => { + Self::CouldNotGenerateTimetable(ref er) => { format!("Could not generate timetable: {}", er) } }; @@ -52,11 +53,17 @@ impl fmt::Display for CliError { impl Error for CliError {} +// struct Timetable { +// pub name: String, +// pub values: Vec, +// } + pub fn print_timezones( timezones: &Vec, time: &String, date: Option<&String>, local_timezone: &String, + padding_hours: i8, ) -> Result<(), CliError> { let todays_date = &get_todays_date(); let date = date.unwrap_or(todays_date); @@ -71,13 +78,52 @@ pub fn print_timezones( .or_else(|_| NaiveDate::parse_from_str(date, "%d-%m")) .map_err(|_| CliError::CouldNotParseDate)?; - let parsed_local_timezone: Tz = if local_timezone == "Local" { - UTC // FIXME: use local timezone instead + if local_timezone == "Local" { + print_calendar( + parsed_time, + parsed_date, + Local, + &"Local".to_string(), + &timezones, + padding_hours, + ) } else { - local_timezone + let timezone = local_timezone .parse::() - .map_err(|_| CliError::CouldNoGenerateTimetable(local_timezone.to_string()))? - }; + .map_err(|_| CliError::CouldNotGenerateTimetable(local_timezone.to_string()))?; + print_calendar( + parsed_time, + parsed_date, + timezone, + &timezone.name().to_string(), + &timezones, + padding_hours, + ) + } +} + +fn print_calendar( + parsed_time: NaiveTime, + parsed_date: NaiveDate, + parsed_local_timezone: TzLocal, + local_timezone_name: &String, + timezones: &Vec, + padding_hours: i8, +) -> Result<(), CliError> { + let local_timetable = create_timetable( + &parsed_time, + &parsed_date, + &parsed_local_timezone, + &parsed_local_timezone, + padding_hours, + ) + .map_err(|_| CliError::CouldNotParseTimezone(local_timezone_name.to_string()))?; + + let longest_name_length = iter::once(local_timezone_name.to_string()) + .chain(timezones.iter().map(|tz| tz.to_string())) + .map(|t| t.len()) + .max() + .unwrap_or(0) as u32; let parsed_timezones: Vec = timezones .iter() @@ -87,31 +133,31 @@ pub fn print_timezones( }) .collect::, _>>()?; - let all_timezones: Vec = iter::once(parsed_local_timezone) - .chain(parsed_timezones) - .collect(); - - let max_len = all_timezones + let target_timetables = parsed_timezones .iter() - .map(|t| t.name().len()) - .max() - .unwrap_or(0) as u32; + .map(|tz| { + create_timetable( + &parsed_time, + &parsed_date, + &parsed_local_timezone, + tz, + padding_hours, + ) + .map(|tt| (tz.name().to_string(), tt)) + .map_err(|_| CliError::CouldNotGenerateTimetable(tz.name().to_string())) + }) + .collect::, _>>()?; - for timezone in all_timezones { - let timezone_name = timezone.name(); - let name_padding_len = max_len - timezone_name.len() as u32; - match create_timetable( - &parsed_time, - &parsed_date, - &parsed_local_timezone, - &timezone, - 5, - ) { - Ok(timetable) => { - print_timetable(&timezone_name.to_string(), name_padding_len, &timetable) - } - Err(error) => panic!("Failed: {}", error), - } + let all_timetables: Vec<(String, Vec)> = + iter::once((local_timezone_name.to_string(), local_timetable)) + .chain(target_timetables) + .collect(); + + for timezone in all_timetables { + let name: String = timezone.0; + let timetable = timezone.1; + let name_padding_len = longest_name_length - name.len() as u32; + print_timetable(&name, name_padding_len, &timetable) } Ok(()) } diff --git a/src/main.rs b/src/main.rs index 2363dda..ee2b9c2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,7 +8,13 @@ fn main() { let args = Args::parse(); if args.timezone.len() > 0 { - let res = print_timezones(&args.timezone, &args.time, args.date.as_ref(), &args.local); + let res = print_timezones( + &args.timezone, + &args.time, + args.date.as_ref(), + &args.local, + 5, + ); if let Err(error) = res { println!("Error: {}", error);