@@ -2,8 +2,8 @@ use super::open_meteo::OpenMeteo;
22use crate :: config:: Config ;
33use crate :: display:: translations:: ll;
44use crate :: errors:: RustormyError ;
5- use crate :: models:: { Language , Location , Provider , Weather , WeatherConditionIcon } ;
6- use crate :: weather:: tools:: { apparent_temperature, dew_point} ;
5+ use crate :: models:: { Language , Location , Provider , Units , Weather , WeatherConditionIcon } ;
6+ use crate :: weather:: tools:: { apparent_temperature, c_to_f , dew_point, mm_to_inch , ms_to_mph } ;
77use crate :: weather:: { GetWeather , LookUpCity , http} ;
88use reqwest:: blocking:: Client ;
99use serde:: { Deserialize , Serialize } ;
@@ -90,6 +90,7 @@ impl YrResponse {
9090 config : & Config ,
9191 location : & Location ,
9292 ) -> Result < Weather , RustormyError > {
93+ let units = config. units ( ) ;
9394 let timeseries = self
9495 . first_timeseries ( )
9596 . ok_or ( RustormyError :: ApiReturnedError (
@@ -109,9 +110,33 @@ impl YrResponse {
109110 let icon = symbol_code_to_icon ( symbol_code) ;
110111 let is_day = symbol_code_to_is_day ( symbol_code) ;
111112
113+ let feels_like_c = apparent_temperature (
114+ details. air_temperature ,
115+ details. wind_speed ,
116+ details. relative_humidity ,
117+ ) ;
118+ let precipitation_mm = details
119+ . precipitation_amount
120+ . unwrap_or_else ( || next_hours. details . precipitation_amount . unwrap_or ( 0.0 ) ) ;
121+
122+ let ( temperature, feels_like, wind_speed, precipitation) = match units {
123+ Units :: Metric => (
124+ details. air_temperature ,
125+ feels_like_c,
126+ details. wind_speed ,
127+ precipitation_mm,
128+ ) ,
129+ Units :: Imperial => (
130+ c_to_f ( details. air_temperature ) ,
131+ c_to_f ( feels_like_c) ,
132+ ms_to_mph ( details. wind_speed ) ,
133+ mm_to_inch ( precipitation_mm) ,
134+ ) ,
135+ } ;
136+
112137 Ok ( Weather {
113- temperature : details . air_temperature ,
114- wind_speed : details . wind_speed ,
138+ temperature,
139+ wind_speed,
115140 wind_direction : details
116141 . wind_from_direction
117142 . ok_or ( RustormyError :: ApiReturnedError (
@@ -124,19 +149,9 @@ impl YrResponse {
124149 icon,
125150 humidity : details. relative_humidity . round ( ) as u8 ,
126151 pressure : details. air_pressure_at_sea_level . round ( ) as u32 ,
127- dew_point : dew_point (
128- details. air_temperature ,
129- details. relative_humidity ,
130- config. units ( ) ,
131- ) ,
132- feels_like : apparent_temperature (
133- details. air_temperature ,
134- details. wind_speed ,
135- details. relative_humidity ,
136- ) ,
137- precipitation : details
138- . precipitation_amount
139- . unwrap_or_else ( || next_hours. details . precipitation_amount . unwrap_or ( 0.0 ) ) ,
152+ dew_point : dew_point ( temperature, details. relative_humidity , units) ,
153+ feels_like,
154+ precipitation,
140155 location : location. clone ( ) ,
141156 } )
142157 }
@@ -496,4 +511,58 @@ mod test {
496511 assert_eq ! ( weather. dew_point, 5.4 ) ;
497512 assert_eq ! ( weather. precipitation, 1.2 ) ;
498513 }
514+
515+ #[ test]
516+ fn test_parse_yr_response_imperial ( ) {
517+ use crate :: config:: FormatterConfig ;
518+ use crate :: models:: Units ;
519+
520+ let data: YrResponse =
521+ serde_json:: from_str ( TEST_API_RESPONSE ) . expect ( "Failed to parse JSON" ) ;
522+ let mut config = Config :: default ( ) ;
523+ config. set_format ( FormatterConfig {
524+ units : Units :: Imperial ,
525+ ..Default :: default ( )
526+ } ) ;
527+ let weather = data
528+ . into_weather (
529+ & config,
530+ & Location {
531+ name : "Test Location" . to_string ( ) ,
532+ latitude : 0.0 ,
533+ longitude : 0.0 ,
534+ } ,
535+ )
536+ . expect ( "Failed to convert to Weather" ) ;
537+
538+ // Fixture is 6.4 °C, 7.3 m/s, 1.2 mm precip — all must be converted to imperial.
539+ assert ! (
540+ ( weather. temperature - 43.52 ) . abs( ) < 0.01 ,
541+ "temperature: {}" ,
542+ weather. temperature
543+ ) ;
544+ assert ! (
545+ ( weather. feels_like - 32.54 ) . abs( ) < 0.05 ,
546+ "feels_like: {}" ,
547+ weather. feels_like
548+ ) ;
549+ assert ! (
550+ ( weather. dew_point - 41.8 ) . abs( ) < 0.05 ,
551+ "dew_point: {}" ,
552+ weather. dew_point
553+ ) ;
554+ assert ! (
555+ ( weather. wind_speed - 16.3 ) . abs( ) < 0.05 ,
556+ "wind_speed: {}" ,
557+ weather. wind_speed
558+ ) ;
559+ assert ! (
560+ ( weather. precipitation - 0.05 ) . abs( ) < 0.001 ,
561+ "precipitation: {}" ,
562+ weather. precipitation
563+ ) ;
564+ // Humidity and pressure are unit-independent.
565+ assert_eq ! ( weather. humidity, 94 ) ;
566+ assert_eq ! ( weather. pressure, 985 ) ;
567+ }
499568}
0 commit comments