diff --git a/Cargo.lock b/Cargo.lock index 83eeeac..3a27f10 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,21 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[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.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + [[package]] name = "base64" version = "0.13.1" @@ -32,12 +47,43 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-integer", + "num-traits", + "time", + "wasm-bindgen", + "winapi", +] + [[package]] name = "chunked_transfer" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fff857943da45f546682664a79488be82e69e43c1a7a2307679ab9afb3a66d2e" +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + [[package]] name = "crc32fast" version = "1.3.2" @@ -47,6 +93,50 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "cxx" +version = "1.0.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "322296e2f2e5af4270b54df9e85a02ff037e271af20ba3e7fe1575515dc840b8" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "017a1385b05d631e7875b1f151c9f012d37b53491e2a87f65bff5c262b2111d8" +dependencies = [ + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2", + "quote", + "scratch", + "syn", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c26bbb078acf09bc1ecda02d4223f03bdd28bd4874edcb0379138efc499ce971" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357f40d1f06a24b60ae1fe122542c1fb05d28d32acb2aed064e84bc2ad1e252e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "flate2" version = "1.0.25" @@ -66,6 +156,30 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "iana-time-zone" +version = "0.1.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "winapi", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" +dependencies = [ + "cxx", + "cxx-build", +] + [[package]] name = "idna" version = "0.3.0" @@ -91,6 +205,15 @@ version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" +[[package]] +name = "link-cplusplus" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" +dependencies = [ + "cc", +] + [[package]] name = "log" version = "0.4.17" @@ -109,6 +232,25 @@ dependencies = [ "adler", ] +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + [[package]] name = "once_cell" version = "1.16.0" @@ -166,6 +308,12 @@ dependencies = [ "webpki", ] +[[package]] +name = "scratch" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2" + [[package]] name = "sct" version = "0.7.0" @@ -225,6 +373,15 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "termcolor" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +dependencies = [ + "winapi-util", +] + [[package]] name = "thiserror" version = "1.0.38" @@ -245,6 +402,17 @@ dependencies = [ "syn", ] +[[package]] +name = "time" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" +dependencies = [ + "libc", + "wasi", + "winapi", +] + [[package]] name = "tinyvec" version = "1.6.0" @@ -281,6 +449,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + [[package]] name = "untrusted" version = "0.7.1" @@ -315,6 +489,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + [[package]] name = "wasm-bindgen" version = "0.2.83" @@ -373,6 +553,7 @@ checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" name = "weather" version = "0.1.1" dependencies = [ + "chrono", "serde", "serde-xml-rs", "ureq", @@ -423,6 +604,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" diff --git a/Cargo.toml b/Cargo.toml index 799c7cc..af65c15 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +chrono = "0.4.23" serde = { version = "1.0.151", features = ["derive"]} serde-xml-rs = "0.6.0" ureq = "2.5.0" diff --git a/src/lib.rs b/src/lib.rs index c7a2e0f..da2257f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +use chrono::{DateTime, Utc, NaiveDateTime, LocalResult}; use serde::{Deserialize, Serialize}; use serde_xml_rs::{from_str}; use std::time::Duration; @@ -55,10 +56,15 @@ pub struct Forecast { static WEATHER_URL: &str = "https://ims.gov.il/sites/default/files/ims_data/xml_files/isr_cities_1week_6hr_forecast.xml"; -static duration: Duration = Duration::new(180, 0); -pub fn get_israeli_weather_forecast() -> Result { - let forecast_xml = ureq::get(WEATHER_URL) - .timeout(duration) +static DURATION: Duration = Duration::new(180, 0); + +pub fn get_israeli_weather_forecast() -> Result { + let agent = ureq::AgentBuilder::new() + .timeout_connect(DURATION) + .timeout_read(DURATION) + .build(); + + let forecast_xml = agent.get(WEATHER_URL) .call() .expect("failed to fetch forecast") .into_string() @@ -66,5 +72,36 @@ pub fn get_israeli_weather_forecast() -> Result = from_str(&forecast_xml); - return forecasts; + if let Ok(mut forecasts) = forecasts { + transform_forecast_times_to_datetimes(&mut forecasts); + return Ok(forecasts); + } else { + return Err(0); + } +} + +fn parse_time(time: &str) -> Result, LocalResult> { + let possible_time = NaiveDateTime::parse_from_str(time, "%Y-%m-%d %H:%M:%S").expect("failed to parse forecast time").and_local_timezone(Utc).latest(); + if let Some(time) = possible_time { + return Ok(time); + } else { + return Err(LocalResult::None); + } +} + +fn transform_forecast_times_to_datetimes(forecast: &mut LocationForecasts) { + forecast.location.iter_mut().for_each(|location| { + location.location_data.forecast.iter_mut().for_each(|forecast| { + forecast.forecast_time = parse_time(&forecast.forecast_time).expect("failed to parse forecast time").to_rfc3339(); + }); + }); +} + +#[cfg(test)] +mod tests { + #[test] + fn parse_time() { + let time = "2023-01-31 02:00:00"; + assert_eq!(super::parse_time(time).expect("failed to parse").to_rfc3339(), "2023-01-31T02:00:00+00:00"); + } } diff --git a/src/main.rs b/src/main.rs index c9d94f5..833ce2b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,5 +11,14 @@ fn main() { fn print_location(location: &weather::Location) { println!(""); println!("Location: {}", location.location_meta_data.location_name_eng); - println!("Average Temperature: {}", location.location_data.forecast.iter().map(|f| f.temperature).sum::() / location.location_data.forecast.len() as i16); + println!("Most Recent Forecast:"); + let most_recent_forecast = location.location_data.forecast.last().expect("failed to get most recent forecast"); + if Some(most_recent_forecast) != None { + println!("Time: {}", most_recent_forecast.forecast_time); + println!("Temperature: {}", most_recent_forecast.temperature); + println!("Wind Direction: {}", most_recent_forecast.wind_direction); + println!("Wind Speed: {}", most_recent_forecast.wind_speed); + println!("Rain: {}", most_recent_forecast.rain); + println!(""); + } } \ No newline at end of file