use 'icalendar' crate (standard is too complex to implement myself)

This commit is contained in:
Joeri Exelmans 2025-09-23 15:17:55 +02:00
parent 1aa2e60870
commit 32d4c24702
4 changed files with 66 additions and 13 deletions

52
Cargo.lock generated
View file

@ -386,11 +386,25 @@ dependencies = [
"cc", "cc",
] ]
[[package]]
name = "icalendar"
version = "0.17.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0aece6c6edc66265bb0e797dbc9893d63115e448433505f3f685c02a43d0111"
dependencies = [
"chrono",
"iso8601",
"nom",
"nom-language",
"uuid",
]
[[package]] [[package]]
name = "icomidal" name = "icomidal"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"chrono", "chrono",
"icalendar",
"reqwest", "reqwest",
"serde", "serde",
] ]
@ -529,6 +543,15 @@ version = "2.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130"
[[package]]
name = "iso8601"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1082f0c48f143442a1ac6122f67e360ceee130b967af4d50996e5154a45df46"
dependencies = [
"nom",
]
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "1.0.15" version = "1.0.15"
@ -618,6 +641,24 @@ dependencies = [
"tempfile", "tempfile",
] ]
[[package]]
name = "nom"
version = "8.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405"
dependencies = [
"memchr",
]
[[package]]
name = "nom-language"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2de2bc5b451bfedaef92c90b8939a8fff5770bdcc1fafd6239d086aab8fa6b29"
dependencies = [
"nom",
]
[[package]] [[package]]
name = "num-traits" name = "num-traits"
version = "0.2.19" version = "0.2.19"
@ -1121,6 +1162,17 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
[[package]]
name = "uuid"
version = "1.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2"
dependencies = [
"getrandom",
"js-sys",
"wasm-bindgen",
]
[[package]] [[package]]
name = "vcpkg" name = "vcpkg"
version = "0.2.15" version = "0.2.15"

View file

@ -7,3 +7,4 @@ edition = "2024"
reqwest = { version = "0.11", features = ["blocking", "json"] } reqwest = { version = "0.11", features = ["blocking", "json"] }
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
chrono = "0.4" chrono = "0.4"
icalendar = "0.17.3"

View file

@ -10,6 +10,7 @@ Hardcoded features:
- soup - soup
- menu items are in Dutch - menu items are in Dutch
- calendar items match the opening hours of Komida (11:30 - 13:45) - calendar items match the opening hours of Komida (11:30 - 13:45)
- prints iCalendar output to stdout
The output of this program (updated daily) is available as-a-service at: The output of this program (updated daily) is available as-a-service at:

View file

@ -1,5 +1,7 @@
use reqwest::blocking::get; use reqwest::blocking::get;
use serde::Deserialize; use serde::Deserialize;
use icalendar::Component;
use icalendar::EventLike;
const location_id: &str = "8199"; // Middelheim? const location_id: &str = "8199"; // Middelheim?
const customer_id: &str = "7622"; // Me? const customer_id: &str = "7622"; // Me?
@ -23,7 +25,9 @@ struct Response {
fn main() -> Result<(), Box<dyn std::error::Error>> { fn main() -> Result<(), Box<dyn std::error::Error>> {
let now = chrono::Local::now(); let now = chrono::Local::now();
println!("BEGIN:VCALENDAR"); let mut calendar = icalendar::Calendar::new();
calendar.name("Komida Menu");
for days_in_future in 0..14 { for days_in_future in 0..14 {
let date = now + chrono::Days::new(days_in_future); let date = now + chrono::Days::new(days_in_future);
@ -46,22 +50,17 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
if item.SectionName.contains("Streetfood") if item.SectionName.contains("Streetfood")
|| item.SectionName.contains("Dailyfood") || item.SectionName.contains("Dailyfood")
|| item.SectionName.contains("Soep") { || item.SectionName.contains("Soep") {
// let d = NaiveDate::parse_from_str(&e.date, "%Y-%m-%d")?; calendar.push(
println!("BEGIN:VEVENT"); icalendar::Event::new()
println!("SUMMARY:{}", item.MenuName); .summary(item.MenuName.as_str())
println!("DTSTART:{}T{}Z", .starts(lunch_starts_at)
lunch_starts_at.format("%Y%m%d"), .ends(lunch_ends_at)
lunch_starts_at.format("%H%M%S"),
); );
println!("DTEND:{}T{}Z",
lunch_ends_at.format("%Y%m%d"),
lunch_ends_at.format("%H%M%S"),
);
println!("END:VEVENT");
} }
} }
} }
println!("END:VCALENDAR"); println!("{}", calendar);
Ok(()) Ok(())
} }