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()
|
||||
.encoding(Some(WINDOWS_1252))
|
||||
.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(())
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
use chrono::NaiveDateTime;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub mod types;
|
||||
pub use types::SiteData;
|
||||
|
||||
/// 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
|
||||
/// of the license.
|
||||
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};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
|
@ -19,7 +20,7 @@ pub struct SiteData {
|
|||
pub struct Name {
|
||||
pub name: String,
|
||||
#[serde(rename = "$value")]
|
||||
pub value: u8,
|
||||
pub value: u32,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
|
@ -28,16 +29,35 @@ pub struct DateTime {
|
|||
pub name: String,
|
||||
pub zone: String,
|
||||
#[serde(rename = "UTCOffset")]
|
||||
pub utc_offset: String,
|
||||
pub year: u16,
|
||||
pub utc_offset: i32,
|
||||
pub year: i32,
|
||||
pub month: Name,
|
||||
pub day: Name,
|
||||
pub hour: u8,
|
||||
pub minute: u8,
|
||||
pub hour: u32,
|
||||
pub minute: u32,
|
||||
pub time_stamp: 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)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Location {
|
||||
|
@ -73,6 +93,7 @@ pub struct MetricWithUnits {
|
|||
pub unit_type: Option<String>,
|
||||
pub change: Option<f64>,
|
||||
pub tendency: Option<String>,
|
||||
pub class: Option<String>,
|
||||
#[serde(rename = "$value")]
|
||||
pub value: Option<f64>,
|
||||
}
|
||||
|
@ -152,7 +173,7 @@ pub struct CloudPrecip {
|
|||
pub struct Forecast {
|
||||
pub period: Period,
|
||||
pub text_summary: String,
|
||||
pub cloud_precip: CloudPrecip,
|
||||
pub cloud_precip: Option<CloudPrecip>,
|
||||
pub abbreviated_forecast: AbbreviatedForecast,
|
||||
pub temperatures: Temperatures,
|
||||
pub winds: Winds,
|
||||
|
|
Loading…
Reference in New Issue