๐Ÿ“ฆ rparrett / weather_dashboard

๐Ÿ“„ forecast.rs ยท 87 lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87use anyhow::Context;
use chrono::{Datelike, TimeZone, Weekday};
use chrono_tz::Tz;
use pirate_weather::apis::weather_api::{WeatherApi, WeatherApiClient};
use serde::Serialize;

use crate::config::Location;

#[derive(Serialize)]
pub(crate) struct TemplateForecast {
    pub(crate) days: Vec<TemplateDay>,
    pub(crate) location: Location,
}

#[derive(Serialize)]
pub(crate) struct TemplateDay {
    pub(crate) time_formatted: String,
    pub(crate) time_is_weekend: bool,
    pub(crate) icon: String,
    pub(crate) summary: String,
    pub(crate) apparent_temperature_low: f64,
    pub(crate) apparent_temperature_high: f64,
    pub(crate) temperature_low: f64,
    pub(crate) temperature_high: f64,
    pub(crate) precip_probability: f64,
    pub(crate) wind_speed: f64,
}

pub(crate) async fn get_forecast(
    client: &WeatherApiClient,
    key: &str,
    location: &Location,
) -> anyhow::Result<TemplateForecast> {
    let weather = client
        .weather(
            key,
            &format!("{},{}", location.latitude, location.longitude),
            Some("currently,minutely,alerts,hourly"),
            None,
            None,
            None,
            None,
            None,
            None,
        )
        .await?;

    let mut days = vec![];

    let tz: Tz = weather.timezone.unwrap().parse().unwrap();

    let daily = weather
        .daily
        .with_context(|| "No daily object in response")?;

    let data = daily.data.with_context(|| "No daily data in response")?;

    for day in data {
        let time = day
            .time
            .map(|timestamp| tz.timestamp_opt(timestamp as i64, 0))
            .with_context(|| "No day time")?;

        let time = time
            .single()
            .with_context(|| "Time zone conversion failed")?;

        days.push(TemplateDay {
            time_formatted: time.format("%a %b %d").to_string(),
            time_is_weekend: time.weekday() == Weekday::Sat || time.weekday() == Weekday::Sun,
            icon: day.icon.unwrap(),
            summary: day.summary.unwrap(),
            apparent_temperature_low: day.apparent_temperature_low.unwrap(),
            apparent_temperature_high: day.apparent_temperature_high.unwrap(),
            temperature_low: day.temperature_low.unwrap(),
            temperature_high: day.temperature_high.unwrap(),
            precip_probability: day.precip_probability.unwrap(),
            wind_speed: day.wind_speed.unwrap(),
        })
    }

    Ok(TemplateForecast {
        days,
        location: location.clone(),
    })
}