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