diff options
Diffstat (limited to 'library.py')
-rw-r--r-- | library.py | 430 |
1 files changed, 48 insertions, 382 deletions
@@ -2,59 +2,68 @@ | |||
2 | import datetime, requests, json, pytz, sys | 2 | import datetime, requests, json, pytz, sys |
3 | from geopy.geocoders import Nominatim, GeoNames | 3 | from geopy.geocoders import Nominatim, GeoNames |
4 | 4 | ||
5 | weather_codes = {0:"Clear Sky", 1:"Mainly Clear",2:"Partly Cloudy",3:"Overcast",45:"Fog",48:"Fog",51:"Light Drizzle",\ | ||
6 | 53:"Moderate Drizzle",55:"Dense Drizzle",56:"Light Freezing Drizzle",57:"Freezing Drizzle",\ | ||
7 | 61:"Light Rain",63:"Moderate Rain",65:"Heavy Rain",66:"Light Freezing Rain",67:"Freezing Rain",\ | ||
8 | 71:"Light Snowfall",73:"Moderate Snowfall",75:"Heavy Snowfall",77:"Snow Grains",80:"Slight Rain Showers",\ | ||
9 | 81:"Moderate Rain Showers",82:"Heavy Rain Showers",85:"Slight Snow Showers",86:"Heavy Snow Showers",\ | ||
10 | 95:"Thunderstorm",96:"Strong Thunderstrom",99:"Heavy Thunderstrom"} | ||
11 | |||
12 | weather_icons = {0:('wi-day-sunny','wi-night-clear'), 1:('wi-day-sunny','wi-night-clear'), 2:('wi-cloudy','wi-night-partly-cloudy'),\ | ||
13 | 3:('wi-day-sunny-overcast','wi-night-cloudy'), 45:('wi-day-fog','wi-night-fog'), 48:('wi-day-fog','wi-night-fog'), \ | ||
14 | 51:('wi-day-rain','wi-night-rain'),53:('wi-day-rain','wi-night-rain'),55:('wi-day-rain','wi-night-rain'),\ | ||
15 | 56:('wi-day-rain','wi-night-rain'),57:('wi-day-rain','wi-night-rain'),61:('wi-day-rain','wi-night-rain'),\ | ||
16 | 63:('wi-day-rain','wi-night-rain'),65:('wi-day-rain','wi-night-rain'),66:('wi-day-rain','wi-night-rain'),\ | ||
17 | 67:('wi-day-rain','wi-night-rain'),71:('wi-day-snow','wi-night-snow'),73:('wi-day-snow','wi-night-snow'),\ | ||
18 | 71:('wi-day-snow','wi-night-snow'),75:('wi-day-snow','wi-night-snow'),77:('wi-day-snow','wi-night-snow'),\ | ||
19 | 80:('wi-day-showers','wi-night-showers'),81:('wi-day-showers','wi-night-showers'),82:('wi-day-showers','wi-night-showers'),\ | ||
20 | 85:('wi-day-snow','wi-night-snow'),86:('wi-day-snow','wi-night-snow'),95:('wi-day-storm-showers','wi-night-storm-showers'),\ | ||
21 | 96:('wi-day-storm-showers','wi-night-storm-showers'),99:('wi-day-storm-showers','wi-night-storm-showers')} | ||
22 | |||
5 | def get_lat_long(location): | 23 | def get_lat_long(location): |
6 | # Converts a location into latitude and longitude | 24 | # Converts a location into latitude and longitude |
7 | geolocator = Nominatim(user_agent="pywttr") | 25 | url = f"https://geocoding-api.open-meteo.com/v1/search?name={location}&count=1&language=en&format=json" |
8 | location = geolocator.geocode(location) | 26 | headers = {"User-Agent": "pywttr 0.1"} |
9 | return location.latitude, location.longitude | 27 | data = requests.get(url, headers=headers).json() |
28 | latitude = data["results"][0]["latitude"] | ||
29 | longitude = data["results"][0]["longitude"] | ||
30 | return latitude, longitude | ||
10 | 31 | ||
11 | def get_time_zone(latitude, longitude): | ||
12 | #TODO | ||
13 | pass | ||
14 | 32 | ||
33 | def get_data(latitude, longitude): | ||
34 | headers = {"User-Agent": "pywttr 0.1"} | ||
35 | now = datetime.datetime.now() | ||
36 | now_str = now.strftime("%Y-%m-%d") | ||
37 | end_str = (now + datetime.timedelta(days=7)).strftime("%Y-%m-%d") | ||
15 | 38 | ||
16 | def get_grid_data(latitude, longitude): | 39 | url_base = f"https://api.open-meteo.com/v1/forecast?latitude={latitude}&longitude={longitude}" |
17 | # Returns id,x,y for a given latitude and longitude | 40 | url_weather_params = "¤t_weather=true&hourly=temperature_2m&hourly=relativehumidity_2m&hourly=apparent_temperature&hourly=precipitation_probability&hourly=precipitation&hourly=weathercode&hourly=windspeed_10m&hourly=winddirection_10m&daily=weathercode&daily=temperature_2m_max&daily=temperature_2m_min&daily=sunrise&daily=sunset&daily=precipitation_sum&daily=precipitation_probability_max&temperature_unit=fahrenheit&windspeed_unit=mph&precipitation_unit=inch&timeformat=iso8601&past_days=0&forecast_days=7" |
18 | grid_data = json.loads(requests.get(f"https://api.weather.gov/points/{latitude},{longitude}").text) | 41 | url_date_time = f"&start_date={now_str}&end_date={end_str}&timezone=auto" |
19 | grid_id = grid_data["properties"]["gridId"] | 42 | url = url_base + url_weather_params + url_date_time |
20 | grid_x = grid_data["properties"]["gridX"] | 43 | data = requests.get(url, headers=headers).json() |
21 | grid_y = grid_data["properties"]["gridY"] | ||
22 | return {"grid_id": grid_id, "grid_x": grid_x, "grid_y":grid_y} | ||
23 | 44 | ||
45 | for i in range(len(data["hourly"]["time"])): | ||
46 | data["hourly"]["time"][i] = datetime.datetime.strptime(data["hourly"]["time"][i], '%Y-%m-%dT%H:%M').strftime('%a %x %I:%M %p') | ||
47 | for i in range(len(data["daily"]["time"])): | ||
48 | data["daily"]["time"][i] = datetime.datetime.strptime(data["daily"]["time"][i], '%Y-%m-%d').strftime('%a %x') | ||
49 | for i in range(len(data["daily"]["sunrise"])): | ||
50 | data["daily"]["sunrise"][i] = datetime.datetime.strptime(data["daily"]["sunrise"][i], '%Y-%m-%dT%H:%M').strftime('%I:%M %p') | ||
51 | for i in range(len(data["daily"]["sunset"])): | ||
52 | data["daily"]["sunset"][i] = datetime.datetime.strptime(data["daily"]["sunset"][i], '%Y-%m-%dT%H:%M').strftime('%I:%M %p') | ||
24 | 53 | ||
25 | def get_raw_data(grid_id, grid_x, grid_y): | 54 | data["current_weather"]["time"] = datetime.datetime.strptime(data["current_weather"]["time"], '%Y-%m-%dT%H:%M').strftime('%a %x %I:%M %p') |
26 | headers = {"User-Agent": "pywttr 0.1"} | ||
27 | raw_data = json.loads(requests.get(f"https://api.weather.gov/gridpoints/{grid_id}/{grid_x},{grid_y}", headers=headers).text) | ||
28 | return raw_data | ||
29 | 55 | ||
30 | 56 | return data | |
31 | def get_raw_forecast(grid_id, grid_x, grid_y): | ||
32 | headers = {"User-Agent": "pywttr 0.1"} | ||
33 | raw_data = json.loads(requests.get(f"https://api.weather.gov/gridpoints/{grid_id}/{grid_x},{grid_y}/forecast", headers=headers).text) | ||
34 | return raw_data | ||
35 | 57 | ||
36 | 58 | ||
37 | def get_current_rounded_time(): | 59 | def get_current_rounded_time(tz_str): |
38 | # Gets current time rounded down to the hour | 60 | # Gets current time rounded down to the hour |
39 | 61 | tz = pytz.timezone(tz_str) | |
40 | tz = pytz.timezone("America/New_York") #temp | ||
41 | cur_time = datetime.datetime.now(tz=tz) | 62 | cur_time = datetime.datetime.now(tz=tz) |
42 | cur_time_rounded = cur_time.replace(second=0, microsecond=0, minute=0, hour=cur_time.hour) | 63 | cur_time_rounded = cur_time.replace(second=0, microsecond=0, minute=0, hour=cur_time.hour) |
43 | return cur_time_rounded | 64 | return cur_time_rounded |
44 | 65 | ||
45 | 66 | ||
46 | def set_timezone(values): | ||
47 | # Takes a list of weather data values | ||
48 | # and converts all times to proper timezone | ||
49 | |||
50 | ret = [] | ||
51 | tz = pytz.timezone("America/New_York") #temp | ||
52 | for val in values: | ||
53 | val["time"] = val["time"].astimezone(tz) | ||
54 | ret.append(val) | ||
55 | return ret | ||
56 | |||
57 | |||
58 | def make_current(values): | 67 | def make_current(values): |
59 | # Takes a list of weather data values | 68 | # Takes a list of weather data values |
60 | # and removes items from before the current time | 69 | # and removes items from before the current time |
@@ -67,349 +76,6 @@ def make_current(values): | |||
67 | return ret | 76 | return ret |
68 | 77 | ||
69 | 78 | ||
70 | def fill_gaps(values): | 79 | def translate_weather_code(weather_code:int): |
71 | # Takes a list of weather data values | 80 | return weather_codes[weather_code] |
72 | # and fills gaps left by duration periods of longer | ||
73 | # than 1 hour | ||
74 | ret = [] | ||
75 | for val in values: | ||
76 | ret.append(val) | ||
77 | duration_hours = int((val["duration"].seconds / 3600) + (val["duration"].days * 24)) | ||
78 | if duration_hours > 1: | ||
79 | for i in range(1, duration_hours): | ||
80 | copy = val.copy() | ||
81 | copy["time"] = val["time"] + datetime.timedelta(hours=i) | ||
82 | copy["duration"] = datetime.timedelta(hours=1) | ||
83 | ret.append(copy) | ||
84 | return ret | ||
85 | |||
86 | |||
87 | def normalize(values): | ||
88 | values = set_timezone(values) | ||
89 | values = make_current(values) | ||
90 | values = fill_gaps(values) | ||
91 | return values | ||
92 | |||
93 | |||
94 | def celcius_to_fahrenheit(celcius): | ||
95 | fahrenheit = int(celcius * 9/5 + 32) | ||
96 | return fahrenheit | ||
97 | |||
98 | |||
99 | def parse_duration(duration_str): | ||
100 | #Parses time duration string and returns timedelta | ||
101 | |||
102 | duration_str = duration_str[1:] # strip off leading P | ||
103 | period_str, time_str = duration_str.split('T') | ||
104 | if len(period_str) > 0: | ||
105 | days = int(period_str[0]) | ||
106 | else: | ||
107 | days = 0 | ||
108 | hours = int(time_str[0:len(time_str)-1]) | ||
109 | delta = datetime.timedelta(hours=hours, days=days) | ||
110 | return delta | ||
111 | |||
112 | |||
113 | def get_daily_highs(raw_data): | ||
114 | daily_highs_raw = raw_data["properties"]["maxTemperature"]["values"] | ||
115 | |||
116 | daily_highs = [] | ||
117 | |||
118 | for high in daily_highs_raw: | ||
119 | high_celc = high["value"] | ||
120 | high_fahr = celcius_to_fahrenheit(high_celc) | ||
121 | |||
122 | time_str, duration_str = high["validTime"].split('/') | ||
123 | time = datetime.datetime.strptime(time_str, "%Y-%m-%dT%H:%M:%S%z") | ||
124 | duration = parse_duration(duration_str) | ||
125 | daily_highs.append({"time":time,"duration":duration,"high_celc":high_celc,"high_fahr":high_fahr}) | ||
126 | |||
127 | return daily_highs | ||
128 | |||
129 | |||
130 | def get_daily_lows(raw_data): | ||
131 | daily_lows_raw = raw_data["properties"]["minTemperature"]["values"] | ||
132 | |||
133 | daily_lows = [] | ||
134 | |||
135 | for low in daily_lows_raw: | ||
136 | low_celc = low["value"] | ||
137 | low_fahr = celcius_to_fahrenheit(low_celc) | ||
138 | time_str, duration_str = low["validTime"].split('/') | ||
139 | time = datetime.datetime.strptime(time_str, "%Y-%m-%dT%H:%M:%S%z") | ||
140 | duration = parse_duration(duration_str) | ||
141 | daily_lows.append({"time":time,"duration":duration,"low_celc":low_celc,"low_fahr":low_fahr}) | ||
142 | |||
143 | return daily_lows | ||
144 | |||
145 | |||
146 | def get_daily_forecast(raw_data): | ||
147 | daily_forecast_raw = raw_data["properties"]["periods"] | ||
148 | |||
149 | daily_forecast = [] | ||
150 | for point in daily_forecast_raw: | ||
151 | time_str = point["startTime"] | ||
152 | time = datetime.datetime.strptime(time_str, "%Y-%m-%dT%H:%M:%S%z") | ||
153 | daily_forecast.append({"time":time, "short_forecast":point["shortForecast"], "detailed_forecast":point["detailedForecast"]}) | ||
154 | return make_current(set_timezone(daily_forecast)) | ||
155 | |||
156 | |||
157 | def get_temperature(raw_data): | ||
158 | raw_values = raw_data["properties"]["temperature"]["values"] | ||
159 | ret = [] | ||
160 | |||
161 | for val in raw_values: | ||
162 | val_celc = round(val["value"]) | ||
163 | val_fahr = round(celcius_to_fahrenheit(val_celc)) | ||
164 | time_str, duration_str = val["validTime"].split('/') | ||
165 | time = datetime.datetime.strptime(time_str, "%Y-%m-%dT%H:%M:%S%z") | ||
166 | duration = parse_duration(duration_str) | ||
167 | ret.append({"time":time,"duration":duration,"value_celc":val_celc,"value_fahr":val_fahr}) | ||
168 | |||
169 | return normalize(ret) | ||
170 | |||
171 | |||
172 | def get_apparent_temperature(raw_data): | ||
173 | raw_values = raw_data["properties"]["apparentTemperature"]["values"] | ||
174 | ret = [] | ||
175 | |||
176 | |||
177 | for val in raw_values: | ||
178 | val_celc = round(val["value"]) | ||
179 | val_fahr = round(celcius_to_fahrenheit(val_celc)) | ||
180 | time_str, duration_str = val["validTime"].split('/') | ||
181 | time = datetime.datetime.strptime(time_str, "%Y-%m-%dT%H:%M:%S%z") | ||
182 | duration = parse_duration(duration_str) | ||
183 | ret.append({"time":time,"duration":duration,"value_celc":val_celc,"value_fahr":val_far}) | ||
184 | |||
185 | return normalize(ret) | ||
186 | |||
187 | |||
188 | def get_humidity(raw_data): | ||
189 | raw_values = raw_data["properties"]["relativeHumidity"]["values"] | ||
190 | ret = [] | ||
191 | |||
192 | for val in raw_values: | ||
193 | time_str, duration_str = val["validTime"].split('/') | ||
194 | time = datetime.datetime.strptime(time_str, "%Y-%m-%dT%H:%M:%S%z") | ||
195 | duration = parse_duration(duration_str) | ||
196 | ret.append({"time":time,"duration":duration,"value":round(val["value"])}) | ||
197 | |||
198 | return normalize(ret) | ||
199 | |||
200 | |||
201 | def get_wind_chill(raw_data): | ||
202 | raw_values = raw_data["properties"]["windChill"]["values"] | ||
203 | ret = [] | ||
204 | |||
205 | for val in raw_values: | ||
206 | val_celc = round(val["value"]) | ||
207 | val_fahr = round(celcius_to_fahrenheit(val_celc)) | ||
208 | time_str, duration_str = val["validTime"].split('/') | ||
209 | time = datetime.datetime.strptime(time_str, "%Y-%m-%dT%H:%M:%S%z") | ||
210 | duration = parse_duration(duration_str) | ||
211 | ret.append({"time":time,"duration":duration,"value_celc":val_celc,"value_fahr":val_fahr}) | ||
212 | |||
213 | return normalize(ret) | ||
214 | |||
215 | |||
216 | def get_wind_speed(raw_data): | ||
217 | raw_values = raw_data["properties"]["windSpeed"]["values"] | ||
218 | ret = [] | ||
219 | |||
220 | for val in raw_values: | ||
221 | time_str, duration_str = val["validTime"].split('/') | ||
222 | time = datetime.datetime.strptime(time_str, "%Y-%m-%dT%H:%M:%S%z") | ||
223 | duration = parse_duration(duration_str) | ||
224 | ret.append({"time":time,"duration":duration,"value":round(val["value"])}) | ||
225 | |||
226 | return normalize(ret) | ||
227 | |||
228 | |||
229 | def get_wind_gust(raw_data): | ||
230 | raw_values = raw_data["properties"]["windGust"]["values"] | ||
231 | ret = [] | ||
232 | |||
233 | for val in raw_values: | ||
234 | time_str, duration_str = val["validTime"].split('/') | ||
235 | time = datetime.datetime.strptime(time_str, "%Y-%m-%dT%H:%M:%S%z") | ||
236 | duration = parse_duration(duration_str) | ||
237 | ret.append({"time":time,"duration":duration,"value":round(val["value"])}) | ||
238 | |||
239 | return normalize(ret) | ||
240 | |||
241 | |||
242 | def get_precip_chance(raw_data): | ||
243 | raw_values = raw_data["properties"]["probabilityOfPrecipitation"]["values"] | ||
244 | ret = [] | ||
245 | |||
246 | for val in raw_values: | ||
247 | time_str, duration_str = val["validTime"].split('/') | ||
248 | time = datetime.datetime.strptime(time_str, "%Y-%m-%dT%H:%M:%S%z") | ||
249 | duration = parse_duration(duration_str) | ||
250 | ret.append({"time":time,"duration":duration,"value":round(val["value"])}) | ||
251 | |||
252 | return normalize(ret) | ||
253 | |||
254 | |||
255 | def get_precip_amount(raw_data): | ||
256 | raw_values = raw_data["properties"]["quantitativePrecipitation"]["values"] | ||
257 | ret = [] | ||
258 | |||
259 | for val in raw_values: | ||
260 | time_str, duration_str = val["validTime"].split('/') | ||
261 | time = datetime.datetime.strptime(time_str, "%Y-%m-%dT%H:%M:%S%z") | ||
262 | duration = parse_duration(duration_str) | ||
263 | ret.append({"time":time,"duration":duration,"value":round(val["value"])}) | ||
264 | |||
265 | return normalize(ret) | ||
266 | |||
267 | |||
268 | def get_snowfall_amount(raw_data): | ||
269 | raw_values = raw_data["properties"]["snowfallAmount"]["values"] | ||
270 | ret = [] | ||
271 | |||
272 | for val in raw_values: | ||
273 | time_str, duration_str = val["validTime"].split('/') | ||
274 | time = datetime.datetime.strptime(time_str, "%Y-%m-%dT%H:%M:%S%z") | ||
275 | duration = parse_duration(duration_str) | ||
276 | ret.append({"time":time,"duration":duration,"value":round(val["value"])}) | ||
277 | |||
278 | return normalize(ret) | ||
279 | |||
280 | |||
281 | def get_snow_level(raw_data): | ||
282 | raw_values = raw_data["properties"]["snowLevel"]["values"] | ||
283 | ret = [] | ||
284 | |||
285 | for val in raw_values: | ||
286 | time_str, duration_str = val["validTime"].split('/') | ||
287 | time = datetime.datetime.strptime(time_str, "%Y-%m-%dT%H:%M:%S%z") | ||
288 | duration = parse_duration(duration_str) | ||
289 | ret.append({"time":time,"duration":duration,"value":round(val["value"])}) | ||
290 | |||
291 | return normalize(ret) | ||
292 | |||
293 | |||
294 | def get_visibility(raw_data): | ||
295 | raw_values = raw_data["properties"]["visibility"]["values"] | ||
296 | ret = [] | ||
297 | |||
298 | for val in raw_values: | ||
299 | time_str, duration_str = val["validTime"].split('/') | ||
300 | time = datetime.datetime.strptime(time_str, "%Y-%m-%dT%H:%M:%S%z") | ||
301 | duration = parse_duration(duration_str) | ||
302 | ret.append({"time":time,"duration":duration,"value":round(val["value"])}) | ||
303 | |||
304 | return normalize(ret) | ||
305 | |||
306 | |||
307 | def get_wind_direction(raw_data): | ||
308 | raw_values = raw_data["properties"]["windDirection"]["values"] | ||
309 | ret = [] | ||
310 | |||
311 | for val in raw_values: | ||
312 | time_str, duration_str = val["validTime"].split('/') | ||
313 | time = datetime.datetime.strptime(time_str, "%Y-%m-%dT%H:%M:%S%z") | ||
314 | duration = parse_duration(duration_str) | ||
315 | |||
316 | def degrees_to_cardinal(d): | ||
317 | dirs = ['N', 'NNE', 'NE', 'ENE', 'E', 'ESE', 'SE', 'SSE', 'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW'] | ||
318 | ix = round(d / (360. / len(dirs))) | ||
319 | return dirs[ix % len(dirs)] | ||
320 | |||
321 | direction_str = degrees_to_cardinal(val["value"]) | ||
322 | |||
323 | ret.append({"time":time,"duration":duration,"value":direction_str}) | ||
324 | |||
325 | return normalize(ret) | ||
326 | |||
327 | |||
328 | def get_dewpoint(raw_data): | ||
329 | raw_values = raw_data["properties"]["dewpoint"]["values"] | ||
330 | ret = [] | ||
331 | |||
332 | for val in raw_values: | ||
333 | val_celc = round(val["value"]) | ||
334 | val_fahr = round(celcius_to_fahrenheit(val_celc)) | ||
335 | time_str, duration_str = val["validTime"].split('/') | ||
336 | time = datetime.datetime.strptime(time_str, "%Y-%m-%dT%H:%M:%S%z") | ||
337 | duration = parse_duration(duration_str) | ||
338 | ret.append({"time":time,"duration":duration,"value_celc":val_celc,"value_fahr":val_fahr}) | ||
339 | |||
340 | return normalize(ret) | ||
341 | |||
342 | |||
343 | def get_hourly_data(raw_data, end_time): | ||
344 | temps = get_temperature(raw_data) | ||
345 | humidity = get_humidity(raw_data) | ||
346 | precip_chance = get_precip_chance(raw_data) | ||
347 | precip_amount = get_precip_amount(raw_data) | ||
348 | wind_speed = get_wind_speed(raw_data) | ||
349 | wind_direction = get_wind_direction(raw_data) | ||
350 | ret_list = [] | ||
351 | i = 0 | ||
352 | while i < len(temps) and temps[i]["time"] < end_time: | ||
353 | if i >= len(temps): | ||
354 | temps.append({"value":"N/A"}) | ||
355 | if i >= len(humidity): | ||
356 | humidity.append({"value":"N/A"}) | ||
357 | if i >= len(precip_chance): | ||
358 | precip_chance.append({"value":"N/A"}) | ||
359 | if i >= len(precip_amount): | ||
360 | precip_amount.append({"value":"N/A"}) | ||
361 | if i >= len(wind_speed): | ||
362 | wind_speed.append({"value":"N/A"}) | ||
363 | if i >= len(wind_direction): | ||
364 | wind_direction.append({"value":"N/A"}) | ||
365 | |||
366 | val_dict = { "time": temps[i]["time"], | ||
367 | "temp": temps[i]["value_fahr"], | ||
368 | "humidity": humidity[i]["value"], | ||
369 | "precip_chance": precip_chance[i]["value"], | ||
370 | "precip_amount": precip_amount[i]["value"], | ||
371 | "wind_speed": wind_speed[i]["value"], | ||
372 | "wind_direction": wind_direction[i]["value"] } | ||
373 | ret_list.append(val_dict) | ||
374 | i+=1 | ||
375 | |||
376 | return ret_list | ||
377 | |||
378 | |||
379 | def get_daily_data(raw_data, raw_forecast, end_time): | ||
380 | daily_highs = get_daily_highs(raw_data) | ||
381 | daily_lows = get_daily_lows(raw_data) | ||
382 | daily_forecasts = get_daily_forecast(raw_forecast) | ||
383 | ret_list = [] | ||
384 | i = 0 | ||
385 | while i < len(daily_highs) and daily_highs[i]["time"] < end_time: | ||
386 | val_dict = { "time": daily_highs[i]["time"], | ||
387 | "high": daily_highs[i]["high_fahr"], | ||
388 | "low": daily_lows[i]["low_fahr"], | ||
389 | "short_forecast_am": daily_forecasts[i]["short_forecast"], | ||
390 | "detailed_forecast_am": daily_forecasts[i]["detailed_forecast"], | ||
391 | "short_forecast_pm": daily_forecasts[i+1]["short_forecast"], | ||
392 | "detailed_forecast_pm": daily_forecasts[i+1]["detailed_forecast"] } | ||
393 | ret_list.append(val_dict) | ||
394 | i+=1 | ||
395 | return ret_list | ||
396 | |||
397 | |||
398 | def hourly_forecast(raw_data, days): | ||
399 | init_time = get_current_rounded_time() | ||
400 | if days > 0: | ||
401 | delta = datetime.timedelta(days=days) | ||
402 | else: | ||
403 | delta = datetime.timedelta(hours=(24-init_time.hour)) | ||
404 | end_time = init_time + delta | ||
405 | return get_hourly_data(raw_data, end_time) | ||
406 | |||
407 | 81 | ||
408 | def daily_forecast(raw_data, raw_forecast, days): | ||
409 | init_time = get_current_rounded_time() | ||
410 | if days > 0: | ||
411 | delta = datetime.timedelta(days=days) | ||
412 | else: | ||
413 | delta = datetime.timedelta(days=5) | ||
414 | end_time = init_time + delta | ||
415 | return get_daily_data(raw_data, raw_forecast, end_time) | ||