Skip to content

Commit 2d74f29

Browse files
authored
Merge pull request #11 from yagui/feat/add-minutely-15
Add minutely 15 forecast option
2 parents 735991f + 36f7774 commit 2d74f29

1 file changed

Lines changed: 70 additions & 0 deletions

File tree

src/forecast.rs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,8 @@ impl TryFrom<&str> for CellSelection {
201201
pub struct Options {
202202
pub location: location::Location,
203203
pub elevation: Option<Elevation>,
204+
/// Attributes to request for minutely_15 forecast
205+
pub minutely_15: Vec<String>,
204206
/// Attributes to request in hourly intervals
205207
pub hourly: Vec<String>,
206208
/// Attributes to request in daily intervals
@@ -213,6 +215,8 @@ pub struct Options {
213215
pub time_zone: Option<String>,
214216
pub past_days: Option<u8>,
215217
pub forecast_days: Option<u8>,
218+
// max minutely_15 data points is 1536
219+
pub forecast_minutely_15: Option<u16>,
216220
pub start_date: Option<chrono::NaiveDate>,
217221
pub end_date: Option<chrono::NaiveDate>,
218222
pub models: Option<Vec<String>>,
@@ -225,6 +229,7 @@ impl Default for Options {
225229
Self {
226230
location: location::Location::default(),
227231
elevation: None,
232+
minutely_15: Vec::new(),
228233
hourly: Vec::new(),
229234
daily: Vec::new(),
230235
current: Vec::new(),
@@ -234,6 +239,7 @@ impl Default for Options {
234239
time_zone: Some("UTC".into()),
235240
past_days: None,
236241
forecast_days: None,
242+
forecast_minutely_15: None,
237243
start_date: None,
238244
end_date: None,
239245
models: None,
@@ -275,6 +281,10 @@ impl Options {
275281
if let Some(v) = self.past_days {
276282
params.push(("past_days".into(), v.to_string()));
277283
}
284+
285+
if let Some(v) = self.forecast_minutely_15 {
286+
params.push(("forecast_minutely_15".into(), v.to_string()));
287+
}
278288

279289
if let Some(v) = self.forecast_days {
280290
params.push(("forecast_days".into(), v.to_string()));
@@ -292,6 +302,10 @@ impl Options {
292302
params.push(("current".into(), self.current.join(",")));
293303
}
294304

305+
if !self.minutely_15.is_empty() {
306+
params.push(("minutely_15".into(), self.minutely_15.join(",")));
307+
}
308+
295309
if !self.hourly.is_empty() {
296310
params.push(("hourly".into(), self.hourly.join(",")));
297311
}
@@ -329,6 +343,8 @@ struct ApiForecastResponse {
329343
pub timezone_abbreviation: Option<String>,
330344
pub current_units: Option<HashMap<String, String>>,
331345
pub current: Option<HashMap<String, serde_json::Value>>,
346+
pub minutely_15_units: Option<HashMap<String, String>>,
347+
pub minutely_15: Option<HashMap<String, serde_json::Value>>,
332348
pub hourly_units: Option<HashMap<String, String>>,
333349
pub hourly: Option<HashMap<String, serde_json::Value>>,
334350
pub daily_units: Option<HashMap<String, String>>,
@@ -348,6 +364,7 @@ pub struct ForecastResultHourly {
348364
}
349365

350366
pub type CurrentResult = ForecastResultHourly;
367+
pub type ForecastResultMinutely15 = ForecastResultHourly;
351368

352369
#[derive(Debug, Serialize, Deserialize, Default)]
353370
pub struct ForecastResultDaily {
@@ -358,6 +375,7 @@ pub struct ForecastResultDaily {
358375
#[derive(Debug, Serialize, Deserialize, Default)]
359376
pub struct ForecastResult {
360377
pub current: Option<CurrentResult>,
378+
pub minutely_15: Option<Vec<ForecastResultMinutely15>>,
361379
pub hourly: Option<Vec<ForecastResultHourly>>,
362380
pub daily: Option<Vec<ForecastResultDaily>>,
363381
}
@@ -425,6 +443,56 @@ impl client::Client {
425443
// Get utc offset
426444
let utc_offset_seconds = api_res.utc_offset_seconds.unwrap_or(0);
427445

446+
// Minutely 15
447+
if let Some(minutely_15) = api_res.minutely_15 {
448+
if let Some(minutely_15_date_times) =
449+
extract_times(&minutely_15, utc_offset_seconds)?
450+
{
451+
if let Some(minutely_15_units) = api_res.minutely_15_units {
452+
let mut minutely_15_result = Vec::new();
453+
454+
// Iterate on times
455+
for (idx, time) in minutely_15_date_times.iter().enumerate() {
456+
let mut minutely_15_rec = ForecastResultMinutely15 {
457+
datetime: *time,
458+
..Default::default()
459+
};
460+
461+
// Iterates on values
462+
for (k, v) in minutely_15.iter() {
463+
if k == "time" {
464+
continue;
465+
}
466+
467+
let mut item = ForecastResultItem::default();
468+
let v_arr = match v.as_array() {
469+
Some(v) => v,
470+
None => {
471+
return Err("cannot decode properly json input".into());
472+
}
473+
};
474+
475+
let v_val = v_arr[idx].clone();
476+
item.value = v_val;
477+
478+
// Try to find unit
479+
if let Some(unit) = minutely_15_units.get(k) {
480+
item.unit = Some(unit.clone());
481+
}
482+
483+
// Push to minutely_15 record
484+
minutely_15_rec.values.insert(k.clone(), item);
485+
}
486+
487+
// Push minutely_15 rec
488+
minutely_15_result.push(minutely_15_rec);
489+
}
490+
491+
result.minutely_15 = Some(minutely_15_result);
492+
}
493+
}
494+
}
495+
428496
// Hourly
429497
if let Some(hourly) = api_res.hourly {
430498
if let Some(hourly_date_times) = extract_times(&hourly, utc_offset_seconds)? {
@@ -586,6 +654,8 @@ mod tests {
586654

587655
opts.elevation = Some("nan".try_into().unwrap());
588656

657+
opts.minutely_15.push("temperature_2m".into());
658+
opts.minutely_15.push("windspeed_10m".into());
589659
opts.hourly.push("temperature_2m".into());
590660
opts.hourly.push("windspeed_120m".into());
591661
opts.daily.push("temperature_2m_max".into());

0 commit comments

Comments
 (0)