implement api for computing timetable for given timezone
This commit is contained in:
parent
b6134ba299
commit
0cf6b1f99a
|
|
@ -0,0 +1,319 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.19.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.55"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "47b26a0954ae34af09b50f0de26458fa95369a0d478d8236d3f93082b219bd29"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fac4744fb15ae8337dc853fee7fb3f4e48c0fbaa23d0afe49c447b4fab126118"
|
||||
dependencies = [
|
||||
"iana-time-zone",
|
||||
"js-sys",
|
||||
"num-traits",
|
||||
"wasm-bindgen",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "chrono-tz"
|
||||
version = "0.10.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a6139a8597ed92cf816dfb33f5dd6cf0bb93a6adc938f11039f371bc5bcd26c3"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"phf",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
||||
|
||||
[[package]]
|
||||
name = "find-msvc-tools"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.65"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"core-foundation-sys",
|
||||
"iana-time-zone-haiku",
|
||||
"js-sys",
|
||||
"log",
|
||||
"wasm-bindgen",
|
||||
"windows-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone-haiku"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.85"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.180"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.21.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||
|
||||
[[package]]
|
||||
name = "phf"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "913273894cec178f401a31ec4b656318d95473527be05c0752cc41cdc32be8b7"
|
||||
dependencies = [
|
||||
"phf_shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_shared"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06005508882fb681fd97892ecff4b7fd0fee13ef1aa569f8695dae7ab9099981"
|
||||
dependencies = [
|
||||
"siphasher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.106"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.114"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tzhelp"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"chrono-tz",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.108"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
"rustversion",
|
||||
"wasm-bindgen-macro",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.108"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.108"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.108"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.62.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
|
||||
dependencies = [
|
||||
"windows-implement",
|
||||
"windows-interface",
|
||||
"windows-link",
|
||||
"windows-result",
|
||||
"windows-strings",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.60.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-interface"
|
||||
version = "0.59.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
|
@ -4,3 +4,5 @@ version = "0.1.0"
|
|||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
chrono = "0.4.43"
|
||||
chrono-tz = "0.10.4"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,176 @@
|
|||
use chrono::{TimeDelta, prelude::*};
|
||||
use chrono_tz::Tz;
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
enum CalendarError {
|
||||
UnknownTimezone(String),
|
||||
WrongTimeFormat,
|
||||
WrongDateFormat,
|
||||
TimezoneConversionFailed(String),
|
||||
}
|
||||
|
||||
impl fmt::Display for CalendarError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let message = match *self {
|
||||
Self::UnknownTimezone(ref tz) => format!("Unknown timezone: {}", tz),
|
||||
Self::WrongTimeFormat => "Wrong time format".to_string(),
|
||||
Self::WrongDateFormat => "Wrong date format".to_string(),
|
||||
Self::TimezoneConversionFailed(ref tz) => {
|
||||
format!("Could not convert time to timezone: {}", tz)
|
||||
}
|
||||
};
|
||||
|
||||
f.write_str(&message)
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for CalendarError {}
|
||||
|
||||
fn create_calendar_strings(time: &NaiveTime, padding_hrs: i8) -> Vec<String> {
|
||||
let start = -padding_hrs;
|
||||
let end = padding_hrs;
|
||||
(start..=end)
|
||||
.map(|v| time.overflowing_add_signed(TimeDelta::hours(v.into())).0)
|
||||
.map(|h| h.format("%H:%M").to_string())
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn create_timetable(
|
||||
target_time: &String,
|
||||
target_date: &String,
|
||||
in_timezone: &String,
|
||||
padding_hrs: i8,
|
||||
) -> Result<Vec<String>, CalendarError> {
|
||||
let parsed_timezone = in_timezone
|
||||
.parse::<Tz>()
|
||||
.map_err(|_| CalendarError::UnknownTimezone(in_timezone.clone()))?;
|
||||
|
||||
let parsed_time = if let Ok(hour) = target_time.parse::<u32>() {
|
||||
NaiveTime::from_hms_opt(hour, 0, 0).ok_or(CalendarError::WrongTimeFormat)?
|
||||
} else {
|
||||
NaiveTime::parse_from_str(target_time, "%H:%M")
|
||||
.map_err(|_| CalendarError::WrongTimeFormat)?
|
||||
};
|
||||
|
||||
let parsed_date = NaiveDate::parse_from_str(target_date, "%d-%m-%Y")
|
||||
.or_else(|_| NaiveDate::parse_from_str(target_date, "%d-%m"))
|
||||
.map_err(|_| CalendarError::WrongDateFormat)?;
|
||||
|
||||
let datetime = NaiveDateTime::new(parsed_date, parsed_time);
|
||||
let time_in_timezone = parsed_timezone
|
||||
.from_local_datetime(&datetime)
|
||||
.single()
|
||||
.ok_or(CalendarError::TimezoneConversionFailed(in_timezone.clone()))?;
|
||||
|
||||
Ok(create_calendar_strings(
|
||||
&time_in_timezone.time(),
|
||||
padding_hrs,
|
||||
))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_calendar_string() {
|
||||
assert_eq!(
|
||||
create_calendar_strings(&NaiveTime::from_hms_opt(10, 0, 0).unwrap(), 4),
|
||||
vec![
|
||||
"06:00", "07:00", "08:00", "09:00", "10:00", "11:00", "12:00", "13:00", "14:00"
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_calendar_string_overflow() {
|
||||
assert_eq!(
|
||||
create_calendar_strings(&NaiveTime::from_hms_opt(3, 0, 0).unwrap(), 4),
|
||||
vec![
|
||||
"23:00", "00:00", "01:00", "02:00", "03:00", "04:00", "05:00", "06:00", "07:00"
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_calendar_string_underflow() {
|
||||
assert_eq!(
|
||||
create_calendar_strings(&NaiveTime::from_hms_opt(22, 0, 0).unwrap(), 4),
|
||||
vec![
|
||||
"18:00", "19:00", "20:00", "21:00", "22:00", "23:00", "00:00", "01:00", "02:00"
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_create_timezone() {
|
||||
assert_eq!(
|
||||
create_timetable(
|
||||
&"10".to_string(),
|
||||
&"1-1-2000".to_string(),
|
||||
&"Europe/Prague".to_string(),
|
||||
2
|
||||
)
|
||||
.unwrap(),
|
||||
vec!["08:00", "09:00", "10:00", "11:00", "12:00"]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_create_timezone_nonzero_minutes() {
|
||||
assert_eq!(
|
||||
create_timetable(
|
||||
&"10:30".to_string(),
|
||||
&"1-1-2000".to_string(),
|
||||
&"Europe/Prague".to_string(),
|
||||
2
|
||||
)
|
||||
.unwrap(),
|
||||
vec!["08:30", "09:30", "10:30", "11:30", "12:30"]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_create_timezone_wrong_time() {
|
||||
assert_eq!(
|
||||
create_timetable(
|
||||
&"hello".to_string(),
|
||||
&"1-1-2000".to_string(),
|
||||
&"Europe/Prague".to_string(),
|
||||
2,
|
||||
)
|
||||
.unwrap_err(),
|
||||
CalendarError::WrongTimeFormat
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_create_timezone_wrong_date() {
|
||||
assert_eq!(
|
||||
create_timetable(
|
||||
&"10:00".to_string(),
|
||||
&"hello".to_string(),
|
||||
&"Europe/Prague".to_string(),
|
||||
2,
|
||||
)
|
||||
.unwrap_err(),
|
||||
CalendarError::WrongDateFormat
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_create_timezone_wrong_zone_name() {
|
||||
assert_eq!(
|
||||
create_timetable(
|
||||
&"10:00".to_string(),
|
||||
&"1-1-2000".to_string(),
|
||||
&"hello".to_string(),
|
||||
2,
|
||||
)
|
||||
.unwrap_err(),
|
||||
CalendarError::UnknownTimezone("hello".to_string())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
||||
mod calendar;
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
Loading…
Reference in New Issue