continue on the simplified view of weather
Signed-off-by: Christine Dodrill <me@christine.website>
This commit is contained in:
parent
76611d657a
commit
02ef9809c7
|
@ -32,9 +32,10 @@ fn main() -> Result<()> {
|
||||||
let fin = DecodeReaderBytesBuilder::new()
|
let fin = DecodeReaderBytesBuilder::new()
|
||||||
.encoding(Some(WINDOWS_1252))
|
.encoding(Some(WINDOWS_1252))
|
||||||
.build(resp.into_reader());
|
.build(resp.into_reader());
|
||||||
let data: web::canada_weather::SiteData = from_reader(fin)?;
|
let data: web::canada_weather::types::SiteData = from_reader(fin)?;
|
||||||
|
let data: web::canada_weather::Report = data.into();
|
||||||
|
|
||||||
println!("{:#?}", data);
|
println!("{}", serde_json::to_string_pretty(&data)?);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
|
use chrono::NaiveDateTime;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
pub mod types;
|
pub mod types;
|
||||||
pub use types::SiteData;
|
|
||||||
|
|
||||||
/// The credit string for this data.
|
/// The credit string for this data.
|
||||||
///
|
///
|
||||||
|
@ -8,3 +10,122 @@ pub use types::SiteData;
|
||||||
/// This must be manually included in each response to remain within the scope
|
/// This must be manually included in each response to remain within the scope
|
||||||
/// of the license.
|
/// of the license.
|
||||||
pub const DATA_SOURCE: &'static str = "Data Source: Environment and Climate Change Canada";
|
pub const DATA_SOURCE: &'static str = "Data Source: Environment and Climate Change Canada";
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
pub struct Report {
|
||||||
|
pub data_source: String,
|
||||||
|
pub location: Location,
|
||||||
|
pub conditions: Conditions,
|
||||||
|
pub forecast: Vec<Forecast>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<types::SiteData> for Report {
|
||||||
|
fn from(sd: types::SiteData) -> Self {
|
||||||
|
let forecast: Vec<Forecast> = sd
|
||||||
|
.forecast_group
|
||||||
|
.forecast
|
||||||
|
.into_iter()
|
||||||
|
.map(Into::into)
|
||||||
|
.collect();
|
||||||
|
Report {
|
||||||
|
data_source: DATA_SOURCE.to_string(),
|
||||||
|
location: sd.location.into(),
|
||||||
|
conditions: sd.current_conditions.into(),
|
||||||
|
forecast: forecast,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
pub struct Location {
|
||||||
|
pub lat: String,
|
||||||
|
pub lon: String,
|
||||||
|
pub code: String,
|
||||||
|
pub name: String,
|
||||||
|
pub region: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<types::Location> for Location {
|
||||||
|
fn from(l: types::Location) -> Self {
|
||||||
|
Location {
|
||||||
|
lat: l.name.lat.unwrap(),
|
||||||
|
lon: l.name.lon.unwrap(),
|
||||||
|
code: l.name.code,
|
||||||
|
name: l.name.name,
|
||||||
|
region: l.region,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
pub struct Conditions {
|
||||||
|
pub as_of_utc: NaiveDateTime,
|
||||||
|
pub as_of_local: NaiveDateTime,
|
||||||
|
pub condition: String,
|
||||||
|
pub temperature: f64,
|
||||||
|
pub dewpoint: f64,
|
||||||
|
pub windchill: Option<f64>,
|
||||||
|
/// This is in kilo-Pascals
|
||||||
|
pub pressure: f64,
|
||||||
|
pub humidity: f64,
|
||||||
|
pub icon_url: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<types::CurrentConditions> for Conditions {
|
||||||
|
fn from(cc: types::CurrentConditions) -> Self {
|
||||||
|
let dt: Vec<NaiveDateTime> = cc.date_time.clone().into_iter().map(Into::into).collect();
|
||||||
|
Conditions {
|
||||||
|
as_of_utc: dt[0],
|
||||||
|
as_of_local: dt[1],
|
||||||
|
condition: cc.condition,
|
||||||
|
temperature: cc.temperature.value.unwrap(),
|
||||||
|
dewpoint: cc.dewpoint.value.unwrap(),
|
||||||
|
windchill: match cc.wind_chill {
|
||||||
|
None => None,
|
||||||
|
Some(wc) => Some(wc.value.unwrap()),
|
||||||
|
},
|
||||||
|
pressure: cc.pressure.value.unwrap(),
|
||||||
|
humidity: cc.relative_humidity.value.unwrap(),
|
||||||
|
icon_url: format!(
|
||||||
|
"https://weather.gc.ca/weathericons/{}.{}",
|
||||||
|
cc.icon_code.value, cc.icon_code.format
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
pub struct Forecast {
|
||||||
|
pub period: String,
|
||||||
|
pub summary: String,
|
||||||
|
pub icon_url: String,
|
||||||
|
pub temp_summary: String,
|
||||||
|
pub high: Option<f64>,
|
||||||
|
pub low: Option<f64>,
|
||||||
|
pub humidity: f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<types::Forecast> for Forecast {
|
||||||
|
fn from(f: types::Forecast) -> Self {
|
||||||
|
Self {
|
||||||
|
period: f.period.value,
|
||||||
|
summary: f.text_summary,
|
||||||
|
icon_url: format!(
|
||||||
|
"https://weather.gc.ca/weathericons/{}.{}",
|
||||||
|
f.abbreviated_forecast.icon_code.value, f.abbreviated_forecast.icon_code.format
|
||||||
|
),
|
||||||
|
temp_summary: f.temperatures.text_summary,
|
||||||
|
high: if f.temperatures.temperature.class.as_ref().unwrap() == "high" {
|
||||||
|
f.temperatures.temperature.value
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
low: if f.temperatures.temperature.class.as_ref().unwrap() == "low" {
|
||||||
|
f.temperatures.temperature.value
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
humidity: f.relative_humidity.value.unwrap(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use chrono::{FixedOffset, NaiveDate, NaiveDateTime, TimeZone};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
@ -19,7 +20,7 @@ pub struct SiteData {
|
||||||
pub struct Name {
|
pub struct Name {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
#[serde(rename = "$value")]
|
#[serde(rename = "$value")]
|
||||||
pub value: u8,
|
pub value: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
@ -28,16 +29,35 @@ pub struct DateTime {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub zone: String,
|
pub zone: String,
|
||||||
#[serde(rename = "UTCOffset")]
|
#[serde(rename = "UTCOffset")]
|
||||||
pub utc_offset: String,
|
pub utc_offset: i32,
|
||||||
pub year: u16,
|
pub year: i32,
|
||||||
pub month: Name,
|
pub month: Name,
|
||||||
pub day: Name,
|
pub day: Name,
|
||||||
pub hour: u8,
|
pub hour: u32,
|
||||||
pub minute: u8,
|
pub minute: u32,
|
||||||
pub time_stamp: String,
|
pub time_stamp: String,
|
||||||
pub text_summary: String,
|
pub text_summary: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Into<NaiveDateTime> for DateTime {
|
||||||
|
fn into(self) -> NaiveDateTime {
|
||||||
|
NaiveDate::from_ymd(self.year, self.month.value, self.day.value).and_hms(
|
||||||
|
self.hour,
|
||||||
|
self.minute,
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<chrono::DateTime<FixedOffset>> for DateTime {
|
||||||
|
fn into(self) -> chrono::DateTime<FixedOffset> {
|
||||||
|
let hour = 3600;
|
||||||
|
FixedOffset::east(self.utc_offset * hour)
|
||||||
|
.ymd(self.year, self.month.value, self.day.value)
|
||||||
|
.and_hms(self.hour, self.minute, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct Location {
|
pub struct Location {
|
||||||
|
@ -73,6 +93,7 @@ pub struct MetricWithUnits {
|
||||||
pub unit_type: Option<String>,
|
pub unit_type: Option<String>,
|
||||||
pub change: Option<f64>,
|
pub change: Option<f64>,
|
||||||
pub tendency: Option<String>,
|
pub tendency: Option<String>,
|
||||||
|
pub class: Option<String>,
|
||||||
#[serde(rename = "$value")]
|
#[serde(rename = "$value")]
|
||||||
pub value: Option<f64>,
|
pub value: Option<f64>,
|
||||||
}
|
}
|
||||||
|
@ -152,7 +173,7 @@ pub struct CloudPrecip {
|
||||||
pub struct Forecast {
|
pub struct Forecast {
|
||||||
pub period: Period,
|
pub period: Period,
|
||||||
pub text_summary: String,
|
pub text_summary: String,
|
||||||
pub cloud_precip: CloudPrecip,
|
pub cloud_precip: Option<CloudPrecip>,
|
||||||
pub abbreviated_forecast: AbbreviatedForecast,
|
pub abbreviated_forecast: AbbreviatedForecast,
|
||||||
pub temperatures: Temperatures,
|
pub temperatures: Temperatures,
|
||||||
pub winds: Winds,
|
pub winds: Winds,
|
||||||
|
|
Loading…
Reference in New Issue