use crate::calendar::CalendarError; use super::calendar::{create_timetable, get_local_timezone_offset, get_todays_date}; use chrono::NaiveDate; use chrono::NaiveTime; use clap::Parser; use std::error::Error; use std::fmt; use std::iter; #[derive(Parser, Debug)] #[command(version, about, long_about = None)] pub struct Args { #[arg(short, long)] pub timezone: Vec, #[arg(short, long)] pub date: Option, #[arg(short, long, default_value = "Local")] pub local: String, pub time: String, } #[derive(PartialEq, Debug)] pub enum CliError { CouldNotParseTime, CouldNotParseDate, CouldNoGenerateTimetable(CalendarError), } impl fmt::Display for CliError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let message = match *self { Self::CouldNotParseTime => "Couldn't parse time".to_string(), Self::CouldNotParseDate => "Couldn't parse date".to_string(), Self::CouldNoGenerateTimetable(ref er) => { format!("Could not generate timetable: {}", er) } }; f.write_str(&message) } } impl Error for CliError {} pub fn print_timezones( timezones: &Vec, time: &String, date: Option<&String>, local_timezone: &String, ) -> Result<(), CliError> { let todays_date = &get_todays_date(); let date = date.unwrap_or(todays_date); let parsed_time = if let Ok(hour) = time.parse::() { NaiveTime::from_hms_opt(hour, 0, 0).ok_or(CliError::CouldNotParseTime)? } else { NaiveTime::parse_from_str(time, "%H:%M").map_err(|_| CliError::CouldNotParseTime)? }; let parsed_date = NaiveDate::parse_from_str(date, "%d-%m-%Y") .or_else(|_| NaiveDate::parse_from_str(date, "%d-%m")) .map_err(|_| CliError::CouldNotParseDate)?; let local_timezone_offset = &get_local_timezone_offset(&parsed_time, local_timezone) .map_err(|e| CliError::CouldNoGenerateTimetable(e))?; let all_timezones: Vec<&String> = iter::once(&local_timezone_offset.name) .chain(timezones) .collect(); let max_len = all_timezones.iter().map(|t| t.len()).max().unwrap_or(0) as u32; for timezone in all_timezones { let name_padding = (0..(max_len - timezone.len() as u32)) .map(|_| " ".to_string()) .collect::>() .join(""); match create_timetable( &parsed_time, &parsed_date, &local_timezone_offset.offset, timezone, 5, ) { Ok(timetable) => println!("{}:{}\t{}", timezone, name_padding, timetable.join("\t")), Err(error) => panic!("Failed: {}", error), } } Ok(()) }