From eb80c2b3b44b2fc146ac835bb6fbcda137057411 Mon Sep 17 00:00:00 2001 From: agessaman Date: Thu, 1 Oct 2026 15:48:56 -0700 Subject: [PATCH] test(characterization): pin wx's NOAA forecast formatting on real responses Replays api.weather.gov points, forecast, station and observation responses captured on 2026-10-01 for Seattle, Denver, Miami and Anchorage (geometry stripped), plus hourly forecasts for two of them, with wx_command's clock frozen at capture time. Each location runs get_noaa_weather with 0-3 leading periods dropped (other times of day), with and without a station observation, at 130 and 200 characters, and pins format_tomorrow_forecast, format_multiday_forecast for 3/5/7 days, _add_period_details and format_hourly_forecast. Coverage of those functions is 72-85%, the rest mostly error paths. This guards the planned breakup of get_noaa_weather and friends. --- .../golden/noaa_wx_anchorage.json | 90 + .../golden/noaa_wx_denver.json | 90 + .../golden/noaa_wx_hourly_miami.json | 4 + .../golden/noaa_wx_hourly_seattle.json | 4 + .../golden/noaa_wx_miami.json | 90 + .../golden/noaa_wx_seattle.json | 90 + .../test_noaa_weather_format.py | 110 ++ tests/fixtures/noaa/anchorage.json | 589 +++++++ tests/fixtures/noaa/denver.json | 539 ++++++ tests/fixtures/noaa/miami.json | 1500 ++++++++++++++++ tests/fixtures/noaa/seattle.json | 1546 +++++++++++++++++ 11 files changed, 4652 insertions(+) create mode 100644 tests/characterization/golden/noaa_wx_anchorage.json create mode 100644 tests/characterization/golden/noaa_wx_denver.json create mode 100644 tests/characterization/golden/noaa_wx_hourly_miami.json create mode 100644 tests/characterization/golden/noaa_wx_hourly_seattle.json create mode 100644 tests/characterization/golden/noaa_wx_miami.json create mode 100644 tests/characterization/golden/noaa_wx_seattle.json create mode 100644 tests/characterization/test_noaa_weather_format.py create mode 100644 tests/fixtures/noaa/anchorage.json create mode 100644 tests/fixtures/noaa/denver.json create mode 100644 tests/fixtures/noaa/miami.json create mode 100644 tests/fixtures/noaa/seattle.json diff --git a/tests/characterization/golden/noaa_wx_anchorage.json b/tests/characterization/golden/noaa_wx_anchorage.json new file mode 100644 index 0000000..da0f687 --- /dev/null +++ b/tests/characterization/golden/noaa_wx_anchorage.json @@ -0,0 +1,90 @@ +{ + "details-drop0": [ + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:" + ], + "details-drop1": [ + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:" + ], + "details-drop2": [ + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:" + ], + "details-drop3": [ + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:" + ], + "drop0-obs0-len130": "This Afternoon: 🌦️Chance Rain And Snow Showers 39°F 💨N0", + "drop0-obs0-len200": "This Afternoon: 🌦️Chance Rain And Snow Showers 39°F 💨N0 | Tonight: 🌦️Chance Rain Showers then Patchy Freezing Fog :26°F 💨NE0", + "drop0-obs1-len130": "This Afternoon: 🌦️Chance Rain And Snow Showers 39°F 💨N0 86%RH 💧33° 👁️9mi 📊1009hPa", + "drop0-obs1-len200": "This Afternoon: 🌦️Chance Rain And Snow Showers 39°F 💨N0 86%RH 💧33° 👁️9mi 📊1009hPa | Tonight: 🌦️Chance Rain Showers then Patchy Freezing Fog :26°F", + "drop1-obs0-len130": "Tonight: 🌦️Chance Rain Showers then Patchy Freezing Fog 26°F 💨NE0", + "drop1-obs0-len200": "Tonight: 🌦️Chance Rain Showers then Patchy Freezing Fog 26°F 💨NE0 | Fri: ☀️Patchy Freezing Fog then Sunny :42°F 💨NE5", + "drop1-obs1-len130": "Tonight: 🌦️Chance Rain Showers then Patchy Freezing Fog 26°F 💨NE0 86%RH 💧33° 👁️9mi 📊1009hPa", + "drop1-obs1-len200": "Tonight: 🌦️Chance Rain Showers then Patchy Freezing Fog 26°F 💨NE0 86%RH 💧33° 👁️9mi 📊1009hPa | Fri: ☀️Patchy Freezing Fog then Sunny :42°F 💨NE5", + "drop2-obs0-len130": "Fri: ☀️Patchy Freezing Fog then Sunny 42°F 💨NE5", + "drop2-obs0-len200": "Fri: ☀️Patchy Freezing Fog then Sunny 42°F 💨NE5", + "drop2-obs1-len130": "Fri: ☀️Patchy Freezing Fog then Sunny 42°F 💨NE5 86%RH 💧33° 👁️9mi 📊1009hPa", + "drop2-obs1-len200": "Fri: ☀️Patchy Freezing Fog then Sunny 42°F 💨NE5 86%RH 💧33° 👁️9mi 📊1009hPa", + "drop3-obs0-len130": "Fri Night: ☀️Mostly Clear 29°F 💨NE5 | Sat: 🌦️Chance Rain And Snow :44°F 💨N5", + "drop3-obs0-len200": "Fri Night: ☀️Mostly Clear 29°F 💨NE5 | Sat: 🌦️Chance Rain And Snow :44°F 💨N5", + "drop3-obs1-len130": "Fri Night: ☀️Mostly Clear 29°F 💨NE5 86%RH 💧33° 👁️9mi 📊1009hPa", + "drop3-obs1-len200": "Fri Night: ☀️Mostly Clear 29°F 💨NE5 86%RH 💧33° 👁️9mi 📊1009hPa | Sat: 🌦️Chance Rain And Snow :44°F 💨N5", + "multiday3-drop0": "F: ☀️Patchy Freezing Fog th... :42°F\nSa: 🌦️Chance Rain And Snow :44°F\nSu: 🌦️Light Rain Likely :45°F", + "multiday3-drop1": "F: ☀️Patchy Freezing Fog th... :42°F\nSa: 🌦️Chance Rain And Snow :44°F\nSu: 🌦️Light Rain Likely :45°F", + "multiday3-drop2": "F: ☀️Patchy Freezing Fog th... :42°F\nSa: 🌦️Chance Rain And Snow :44°F\nSu: 🌦️Light Rain Likely :45°F", + "multiday3-drop3": "F: ☀️Mostly Clear :29°F\nSa: 🌦️Chance Rain And Snow :44°F\nSu: 🌦️Light Rain Likely :45°F", + "multiday5-drop0": "F: ☀️Patchy Freezing Fog th... :42°F\nSa: 🌦️Chance Rain And Snow :44°F\nSu: 🌦️Light Rain Likely :45°F\nM: 🌦️Light Rain Likely :49°F\nT: 🌦️Chance Light Rain :49°F", + "multiday5-drop1": "F: ☀️Patchy Freezing Fog th... :42°F\nSa: 🌦️Chance Rain And Snow :44°F\nSu: 🌦️Light Rain Likely :45°F\nM: 🌦️Light Rain Likely :49°F\nT: 🌦️Chance Light Rain :49°F", + "multiday5-drop2": "F: ☀️Patchy Freezing Fog th... :42°F\nSa: 🌦️Chance Rain And Snow :44°F\nSu: 🌦️Light Rain Likely :45°F\nM: 🌦️Light Rain Likely :49°F\nT: 🌦️Chance Light Rain :49°F", + "multiday5-drop3": "F: ☀️Mostly Clear :29°F\nSa: 🌦️Chance Rain And Snow :44°F\nSu: 🌦️Light Rain Likely :45°F\nM: 🌦️Light Rain Likely :49°F\nT: 🌦️Chance Light Rain :49°F", + "multiday7-drop0": "F: ☀️Patchy Freezing Fog th... :42°F\nSa: 🌦️Chance Rain And Snow :44°F\nSu: 🌦️Light Rain Likely :45°F\nM: 🌦️Light Rain Likely :49°F\nT: 🌦️Chance Light Rain :49°F\nW: 🌦️Chance Light Rain :47°F", + "multiday7-drop1": "F: ☀️Patchy Freezing Fog th... :42°F\nSa: 🌦️Chance Rain And Snow :44°F\nSu: 🌦️Light Rain Likely :45°F\nM: 🌦️Light Rain Likely :49°F\nT: 🌦️Chance Light Rain :49°F\nW: 🌦️Chance Light Rain :47°F", + "multiday7-drop2": "F: ☀️Patchy Freezing Fog th... :42°F\nSa: 🌦️Chance Rain And Snow :44°F\nSu: 🌦️Light Rain Likely :45°F\nM: 🌦️Light Rain Likely :49°F\nT: 🌦️Chance Light Rain :49°F\nW: 🌦️Chance Light Rain :47°F", + "multiday7-drop3": "F: ☀️Mostly Clear :29°F\nSa: 🌦️Chance Rain And Snow :44°F\nSu: 🌦️Light Rain Likely :45°F\nM: 🌦️Light Rain Likely :49°F\nT: 🌦️Chance Light Rain :49°F\nW: 🌦️Chance Light Rain :47°F", + "tomorrow-drop0": "Fri: ☀️Patchy Freezing Fog then Sunny :42°F 💨NE5 | Fri Night: ☀️Mostly Clear :29°F 💨NE5", + "tomorrow-drop1": "Fri: ☀️Patchy Freezing Fog then Sunny :42°F 💨NE5 | Fri Night: ☀️Mostly Clear :29°F 💨NE5", + "tomorrow-drop2": "Fri: ☀️Patchy Freezing Fog then Sunny :42°F 💨NE5 | Fri Night: ☀️Mostly Clear :29°F 💨NE5", + "tomorrow-drop3": "Fri Night: ☀️Mostly Clear :29°F 💨NE5" +} diff --git a/tests/characterization/golden/noaa_wx_denver.json b/tests/characterization/golden/noaa_wx_denver.json new file mode 100644 index 0000000..ad229c2 --- /dev/null +++ b/tests/characterization/golden/noaa_wx_denver.json @@ -0,0 +1,90 @@ +{ + "details-drop0": [ + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:" + ], + "details-drop1": [ + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:" + ], + "details-drop2": [ + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:" + ], + "details-drop3": [ + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:" + ], + "drop0-obs0-len130": "This Afternoon: ☀️Sunny 72°F 💨E8 | Tonight: ☀️Mostly Clear :50°F 💨S3", + "drop0-obs0-len200": "This Afternoon: ☀️Sunny 72°F 💨E8 | Tonight: ☀️Mostly Clear :50°F 💨S3", + "drop0-obs1-len130": "This Afternoon: ☀️Sunny 72°F 💨E8 28%RH 💧37° 👁️9mi 📊1024hPa", + "drop0-obs1-len200": "This Afternoon: ☀️Sunny 72°F 💨E8 28%RH 💧37° 👁️9mi 📊1024hPa | Tonight: ☀️Mostly Clear :50°F 💨S3", + "drop1-obs0-len130": "Tonight: ☀️Mostly Clear 50°F 💨S3 | Fri: ☀️Sunny :81°F 💨S2", + "drop1-obs0-len200": "Tonight: ☀️Mostly Clear 50°F 💨S3 | Fri: ☀️Sunny :81°F 💨S2 | Fri Night: ☀️Mostly Clear :53°F", + "drop1-obs1-len130": "Tonight: ☀️Mostly Clear 50°F 💨S3 28%RH 💧37° 👁️9mi 📊1024hPa | Fri: ☀️Sunny :81°F", + "drop1-obs1-len200": "Tonight: ☀️Mostly Clear 50°F 💨S3 28%RH 💧37° 👁️9mi 📊1024hPa | Fri: ☀️Sunny :81°F 💨S2 | Fri Night: ☀️Mostly Clear :53°F", + "drop2-obs0-len130": "Fri: ☀️Sunny 81°F 💨S2", + "drop2-obs0-len200": "Fri: ☀️Sunny 81°F 💨S2", + "drop2-obs1-len130": "Fri: ☀️Sunny 81°F 💨S2 28%RH 💧37° 👁️9mi 📊1024hPa", + "drop2-obs1-len200": "Fri: ☀️Sunny 81°F 💨S2 28%RH 💧37° 👁️9mi 📊1024hPa", + "drop3-obs0-len130": "Fri Night: ☀️Mostly Clear 53°F 💨S5 | Sat: ☀️Sunny :85°F 💨NN2", + "drop3-obs0-len200": "Fri Night: ☀️Mostly Clear 53°F 💨S5 | Sat: ☀️Sunny :85°F 💨NN2", + "drop3-obs1-len130": "Fri Night: ☀️Mostly Clear 53°F 💨S5 28%RH 💧37° 👁️9mi 📊1024hPa | Sat: ☀️Sunny :85°F", + "drop3-obs1-len200": "Fri Night: ☀️Mostly Clear 53°F 💨S5 28%RH 💧37° 👁️9mi 📊1024hPa | Sat: ☀️Sunny :85°F 💨NN2", + "multiday3-drop0": "F: ☀️Sunny :81°F\nSa: ☀️Sunny :85°F\nSu: ☀️Sunny :82°F", + "multiday3-drop1": "F: ☀️Sunny :81°F\nSa: ☀️Sunny :85°F\nSu: ☀️Sunny :82°F", + "multiday3-drop2": "F: ☀️Sunny :81°F\nSa: ☀️Sunny :85°F\nSu: ☀️Sunny :82°F", + "multiday3-drop3": "F: ☀️Mostly Clear :53°F\nSa: ☀️Sunny :85°F\nSu: ☀️Sunny :82°F", + "multiday5-drop0": "F: ☀️Sunny :81°F\nSa: ☀️Sunny :85°F\nSu: ☀️Sunny :82°F\nM: ☀️Sunny :87°F\nT: ☀️Mostly Sunny :84°F", + "multiday5-drop1": "F: ☀️Sunny :81°F\nSa: ☀️Sunny :85°F\nSu: ☀️Sunny :82°F\nM: ☀️Sunny :87°F\nT: ☀️Mostly Sunny :84°F", + "multiday5-drop2": "F: ☀️Sunny :81°F\nSa: ☀️Sunny :85°F\nSu: ☀️Sunny :82°F\nM: ☀️Sunny :87°F\nT: ☀️Mostly Sunny :84°F", + "multiday5-drop3": "F: ☀️Mostly Clear :53°F\nSa: ☀️Sunny :85°F\nSu: ☀️Sunny :82°F\nM: ☀️Sunny :87°F\nT: ☀️Mostly Sunny :84°F", + "multiday7-drop0": "F: ☀️Sunny :81°F\nSa: ☀️Sunny :85°F\nSu: ☀️Sunny :82°F\nM: ☀️Sunny :87°F\nT: ☀️Mostly Sunny :84°F\nW: ☀️Sunny :82°F", + "multiday7-drop1": "F: ☀️Sunny :81°F\nSa: ☀️Sunny :85°F\nSu: ☀️Sunny :82°F\nM: ☀️Sunny :87°F\nT: ☀️Mostly Sunny :84°F\nW: ☀️Sunny :82°F", + "multiday7-drop2": "F: ☀️Sunny :81°F\nSa: ☀️Sunny :85°F\nSu: ☀️Sunny :82°F\nM: ☀️Sunny :87°F\nT: ☀️Mostly Sunny :84°F\nW: ☀️Sunny :82°F", + "multiday7-drop3": "F: ☀️Mostly Clear :53°F\nSa: ☀️Sunny :85°F\nSu: ☀️Sunny :82°F\nM: ☀️Sunny :87°F\nT: ☀️Mostly Sunny :84°F\nW: ☀️Sunny :82°F", + "tomorrow-drop0": "Fri: ☀️Sunny :81°F 💨S2 | Fri Night: ☀️Mostly Clear :53°F 💨S5", + "tomorrow-drop1": "Fri: ☀️Sunny :81°F 💨S2 | Fri Night: ☀️Mostly Clear :53°F 💨S5", + "tomorrow-drop2": "Fri: ☀️Sunny :81°F 💨S2 | Fri Night: ☀️Mostly Clear :53°F 💨S5", + "tomorrow-drop3": "Fri Night: ☀️Mostly Clear :53°F 💨S5" +} diff --git a/tests/characterization/golden/noaa_wx_hourly_miami.json b/tests/characterization/golden/noaa_wx_hourly_miami.json new file mode 100644 index 0000000..391b465 --- /dev/null +++ b/tests/characterization/golden/noaa_wx_hourly_miami.json @@ -0,0 +1,4 @@ +{ + "len130": "6PM: 🌦️ 38% Chance Showers And 83° E15\n7PM: 🌦️ 34% Chance Showers And 83° E15", + "len200": "6PM: 🌦️ 38% Chance Showers And 83° E15\n7PM: 🌦️ 34% Chance Showers And 83° E15\n8PM: 🌦️ 43% Chance Showers And 82° E15\n9PM: 🌦️ 39% Chance Showers And 83° E16" +} diff --git a/tests/characterization/golden/noaa_wx_hourly_seattle.json b/tests/characterization/golden/noaa_wx_hourly_seattle.json new file mode 100644 index 0000000..4cc8e61 --- /dev/null +++ b/tests/characterization/golden/noaa_wx_hourly_seattle.json @@ -0,0 +1,4 @@ +{ + "len130": "4PM: ☁️ 3% Mostly Cloudy 65° WN2\n5PM: ☁️ 3% Mostly Cloudy 66° NW2\n6PM: ☁️ 3% Mostly Cloudy 64° NN2", + "len200": "4PM: ☁️ 3% Mostly Cloudy 65° WN2\n5PM: ☁️ 3% Mostly Cloudy 66° NW2\n6PM: ☁️ 3% Mostly Cloudy 64° NN2\n7PM: ☁️ 3% Mostly Cloudy 63° NW2\n8PM: ☁️ 3% Mostly Cloudy 61° NN2" +} diff --git a/tests/characterization/golden/noaa_wx_miami.json b/tests/characterization/golden/noaa_wx_miami.json new file mode 100644 index 0000000..97b0c2c --- /dev/null +++ b/tests/characterization/golden/noaa_wx_miami.json @@ -0,0 +1,90 @@ +{ + "details-drop0": [ + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:" + ], + "details-drop1": [ + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:" + ], + "details-drop2": [ + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:" + ], + "details-drop3": [ + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:" + ], + "drop0-obs0-len130": "Tonight: 🌦️Chance Showers And Thunderstorms 81°F 💨E17", + "drop0-obs0-len200": "Tonight: 🌦️Chance Showers And Thunderstorms 81°F 💨E17 | Fri: 🌦️Chance Showers And Thunderstorms :88°F 💨SE14", + "drop0-obs1-len130": "Tonight: 🌦️Chance Showers And Thunderstorms 81°F 💨E17 88%RH 💧73° 👁️6mi 📊1015hPa", + "drop0-obs1-len200": "Tonight: 🌦️Chance Showers And Thunderstorms 81°F 💨E17 88%RH 💧73° 👁️6mi 📊1015hPa | Fri: 🌦️Chance Showers And Thunderstorms :88°F 💨SE14", + "drop1-obs0-len130": "Fri: 🌦️Chance Showers And Thunderstorms 88°F 💨SE14", + "drop1-obs0-len200": "Fri: 🌦️Chance Showers And Thunderstorms 88°F 💨SE14", + "drop1-obs1-len130": "Fri: 🌦️Chance Showers And Thunderstorms 88°F 💨SE14 88%RH 💧73° 👁️6mi 📊1015hPa", + "drop1-obs1-len200": "Fri: 🌦️Chance Showers And Thunderstorms 88°F 💨SE14 88%RH 💧73° 👁️6mi 📊1015hPa", + "drop2-obs0-len130": "Fri Night: 🌦️Chance Showers And Thunderstorms 81°F 💨E15", + "drop2-obs0-len200": "Fri Night: 🌦️Chance Showers And Thunderstorms 81°F 💨E15 | Sat: 🌦️Chance Showers And Thunderstorms :88°F 💨E15", + "drop2-obs1-len130": "Fri Night: 🌦️Chance Showers And Thunderstorms 81°F 💨E15 88%RH 💧73° 👁️6mi 📊1015hPa", + "drop2-obs1-len200": "Fri Night: 🌦️Chance Showers And Thunderstorms 81°F 💨E15 88%RH 💧73° 👁️6mi 📊1015hPa | Sat: 🌦️Chance Showers And Thunderstorms :88°F 💨E15", + "drop3-obs0-len130": "Sat: 🌦️Chance Showers And Thunderstorms 88°F 💨E15", + "drop3-obs0-len200": "Sat: 🌦️Chance Showers And Thunderstorms 88°F 💨E15", + "drop3-obs1-len130": "Sat: 🌦️Chance Showers And Thunderstorms 88°F 💨E15 88%RH 💧73° 👁️6mi 📊1015hPa", + "drop3-obs1-len200": "Sat: 🌦️Chance Showers And Thunderstorms 88°F 💨E15 88%RH 💧73° 👁️6mi 📊1015hPa", + "multiday3-drop0": "F: 🌦️Chance shwrs And t-storms :88°F\nSa: 🌦️Chance shwrs And t-storms :88°F\nSu: ☀️Sunny then Slight Chan... :88°F", + "multiday3-drop1": "F: 🌦️Chance shwrs And t-storms :88°F\nSa: 🌦️Chance shwrs And t-storms :88°F\nSu: ☀️Sunny then Slight Chan... :88°F", + "multiday3-drop2": "F: 🌦️Chance shwrs And t-storms :81°F\nSa: 🌦️Chance shwrs And t-storms :88°F\nSu: ☀️Sunny then Slight Chan... :88°F", + "multiday3-drop3": "Sa: 🌦️Chance shwrs And t-storms :88°F\nSu: ☀️Sunny then Slight Chan... :88°F\nM: ☀️Mostly Sunny then Chan... :89°F", + "multiday5-drop0": "F: 🌦️Chance shwrs And t-storms :88°F\nSa: 🌦️Chance shwrs And t-storms :88°F\nSu: ☀️Sunny then Slight Chan... :88°F\nM: ☀️Mostly Sunny then Chan... :89°F\nT: 🌦️Slight Chance shwrs An... :88°F", + "multiday5-drop1": "F: 🌦️Chance shwrs And t-storms :88°F\nSa: 🌦️Chance shwrs And t-storms :88°F\nSu: ☀️Sunny then Slight Chan... :88°F\nM: ☀️Mostly Sunny then Chan... :89°F\nT: 🌦️Slight Chance shwrs An... :88°F", + "multiday5-drop2": "F: 🌦️Chance shwrs And t-storms :81°F\nSa: 🌦️Chance shwrs And t-storms :88°F\nSu: ☀️Sunny then Slight Chan... :88°F\nM: ☀️Mostly Sunny then Chan... :89°F\nT: 🌦️Slight Chance shwrs An... :88°F", + "multiday5-drop3": "Sa: 🌦️Chance shwrs And t-storms :88°F\nSu: ☀️Sunny then Slight Chan... :88°F\nM: ☀️Mostly Sunny then Chan... :89°F\nT: 🌦️Slight Chance shwrs An... :88°F\nW: 🌦️Chance shwrs And t-storms :88°F", + "multiday7-drop0": "F: 🌦️Chance shwrs And t-storms :88°F\nSa: 🌦️Chance shwrs And t-storms :88°F\nSu: ☀️Sunny then Slight Chan... :88°F\nM: ☀️Mostly Sunny then Chan... :89°F\nT: 🌦️Slight Chance shwrs An... :88°F\nW: 🌦️Chance shwrs And t-storms :88°F", + "multiday7-drop1": "F: 🌦️Chance shwrs And t-storms :88°F\nSa: 🌦️Chance shwrs And t-storms :88°F\nSu: ☀️Sunny then Slight Chan... :88°F\nM: ☀️Mostly Sunny then Chan... :89°F\nT: 🌦️Slight Chance shwrs An... :88°F\nW: 🌦️Chance shwrs And t-storms :88°F", + "multiday7-drop2": "F: 🌦️Chance shwrs And t-storms :81°F\nSa: 🌦️Chance shwrs And t-storms :88°F\nSu: ☀️Sunny then Slight Chan... :88°F\nM: ☀️Mostly Sunny then Chan... :89°F\nT: 🌦️Slight Chance shwrs An... :88°F\nW: 🌦️Chance shwrs And t-storms :88°F", + "multiday7-drop3": "Sa: 🌦️Chance shwrs And t-storms :88°F\nSu: ☀️Sunny then Slight Chan... :88°F\nM: ☀️Mostly Sunny then Chan... :89°F\nT: 🌦️Slight Chance shwrs An... :88°F\nW: 🌦️Chance shwrs And t-storms :88°F", + "tomorrow-drop0": "Fri: 🌦️Chance Showers And Thunderstorms :88°F 💨SE14 | Fri Night: 🌦️Chance Showers And Thunderstorms :81°F 💨E15", + "tomorrow-drop1": "Fri: 🌦️Chance Showers And Thunderstorms :88°F 💨SE14 | Fri Night: 🌦️Chance Showers And Thunderstorms :81°F 💨E15", + "tomorrow-drop2": "Fri Night: 🌦️Chance Showers And Thunderstorms :81°F 💨E15", + "tomorrow-drop3": "" +} diff --git a/tests/characterization/golden/noaa_wx_seattle.json b/tests/characterization/golden/noaa_wx_seattle.json new file mode 100644 index 0000000..7ec7a7c --- /dev/null +++ b/tests/characterization/golden/noaa_wx_seattle.json @@ -0,0 +1,90 @@ +{ + "details-drop0": [ + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:" + ], + "details-drop1": [ + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:" + ], + "details-drop2": [ + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:" + ], + "details-drop3": [ + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:", + "Now:" + ], + "drop0-obs0-len130": "This Afternoon: ☁️Mostly Cloudy 66°F 💨WN2 | Tonight: ☁️Partly Cloudy :53°F 💨WN2", + "drop0-obs0-len200": "This Afternoon: ☁️Mostly Cloudy 66°F 💨WN2 | Tonight: ☁️Partly Cloudy :53°F 💨WN2", + "drop0-obs1-len130": "This Afternoon: ☁️Mostly Cloudy 66°F 💨WN2 52%RH 💧48° 👁️9mi 📊1016hPa", + "drop0-obs1-len200": "This Afternoon: ☁️Mostly Cloudy 66°F 💨WN2 52%RH 💧48° 👁️9mi 📊1016hPa | Tonight: ☁️Partly Cloudy :53°F 💨WN2", + "drop1-obs0-len130": "Tonight: ☁️Partly Cloudy 53°F 💨WN2 | Fri: ☀️Partly Sunny :70°F 💨SS1", + "drop1-obs0-len200": "Tonight: ☁️Partly Cloudy 53°F 💨WN2 | Fri: ☀️Partly Sunny :70°F 💨SS1 | Fri Night: ☁️Mostly Cloudy :54°F", + "drop1-obs1-len130": "Tonight: ☁️Partly Cloudy 53°F 💨WN2 52%RH 💧48° 👁️9mi 📊1016hPa", + "drop1-obs1-len200": "Tonight: ☁️Partly Cloudy 53°F 💨WN2 52%RH 💧48° 👁️9mi 📊1016hPa | Fri: ☀️Partly Sunny :70°F 💨SS1", + "drop2-obs0-len130": "Fri: ☀️Partly Sunny 70°F 💨SS1", + "drop2-obs0-len200": "Fri: ☀️Partly Sunny 70°F 💨SS1", + "drop2-obs1-len130": "Fri: ☀️Partly Sunny 70°F 💨SS1 52%RH 💧48° 👁️9mi 📊1016hPa", + "drop2-obs1-len200": "Fri: ☀️Partly Sunny 70°F 💨SS1 52%RH 💧48° 👁️9mi 📊1016hPa", + "drop3-obs0-len130": "Fri Night: ☁️Mostly Cloudy 54°F 💨NN5 | Sat: ☀️Mostly Sunny :67°F 💨N5", + "drop3-obs0-len200": "Fri Night: ☁️Mostly Cloudy 54°F 💨NN5 | Sat: ☀️Mostly Sunny :67°F 💨N5", + "drop3-obs1-len130": "Fri Night: ☁️Mostly Cloudy 54°F 💨NN5 52%RH 💧48° 👁️9mi 📊1016hPa", + "drop3-obs1-len200": "Fri Night: ☁️Mostly Cloudy 54°F 💨NN5 52%RH 💧48° 👁️9mi 📊1016hPa | Sat: ☀️Mostly Sunny :67°F 💨N5", + "multiday3-drop0": "F: ☀️Partly Sunny :70°F\nSa: ☀️Mostly Sunny :67°F\nSu: ☀️Mostly Sunny :70°F", + "multiday3-drop1": "F: ☀️Partly Sunny :70°F\nSa: ☀️Mostly Sunny :67°F\nSu: ☀️Mostly Sunny :70°F", + "multiday3-drop2": "F: ☀️Partly Sunny :70°F\nSa: ☀️Mostly Sunny :67°F\nSu: ☀️Mostly Sunny :70°F", + "multiday3-drop3": "F: ☁️Mostly Cloudy :54°F\nSa: ☀️Mostly Sunny :67°F\nSu: ☀️Mostly Sunny :70°F", + "multiday5-drop0": "F: ☀️Partly Sunny :70°F\nSa: ☀️Mostly Sunny :67°F\nSu: ☀️Mostly Sunny :70°F\nM: ☀️Mostly Sunny :68°F\nT: ☀️Partly Sunny :64°F", + "multiday5-drop1": "F: ☀️Partly Sunny :70°F\nSa: ☀️Mostly Sunny :67°F\nSu: ☀️Mostly Sunny :70°F\nM: ☀️Mostly Sunny :68°F\nT: ☀️Partly Sunny :64°F", + "multiday5-drop2": "F: ☀️Partly Sunny :70°F\nSa: ☀️Mostly Sunny :67°F\nSu: ☀️Mostly Sunny :70°F\nM: ☀️Mostly Sunny :68°F\nT: ☀️Partly Sunny :64°F", + "multiday5-drop3": "F: ☁️Mostly Cloudy :54°F\nSa: ☀️Mostly Sunny :67°F\nSu: ☀️Mostly Sunny :70°F\nM: ☀️Mostly Sunny :68°F\nT: ☀️Partly Sunny :64°F", + "multiday7-drop0": "F: ☀️Partly Sunny :70°F\nSa: ☀️Mostly Sunny :67°F\nSu: ☀️Mostly Sunny :70°F\nM: ☀️Mostly Sunny :68°F\nT: ☀️Partly Sunny :64°F\nW: ☀️Mostly Sunny :65°F", + "multiday7-drop1": "F: ☀️Partly Sunny :70°F\nSa: ☀️Mostly Sunny :67°F\nSu: ☀️Mostly Sunny :70°F\nM: ☀️Mostly Sunny :68°F\nT: ☀️Partly Sunny :64°F\nW: ☀️Mostly Sunny :65°F", + "multiday7-drop2": "F: ☀️Partly Sunny :70°F\nSa: ☀️Mostly Sunny :67°F\nSu: ☀️Mostly Sunny :70°F\nM: ☀️Mostly Sunny :68°F\nT: ☀️Partly Sunny :64°F\nW: ☀️Mostly Sunny :65°F", + "multiday7-drop3": "F: ☁️Mostly Cloudy :54°F\nSa: ☀️Mostly Sunny :67°F\nSu: ☀️Mostly Sunny :70°F\nM: ☀️Mostly Sunny :68°F\nT: ☀️Partly Sunny :64°F\nW: ☀️Mostly Sunny :65°F", + "tomorrow-drop0": "Fri: ☀️Partly Sunny :70°F 💨SS1 | Fri Night: ☁️Mostly Cloudy :54°F 💨NN5", + "tomorrow-drop1": "Fri: ☀️Partly Sunny :70°F 💨SS1 | Fri Night: ☁️Mostly Cloudy :54°F 💨NN5", + "tomorrow-drop2": "Fri: ☀️Partly Sunny :70°F 💨SS1 | Fri Night: ☁️Mostly Cloudy :54°F 💨NN5", + "tomorrow-drop3": "Fri Night: ☁️Mostly Cloudy :54°F 💨NN5" +} diff --git a/tests/characterization/test_noaa_weather_format.py b/tests/characterization/test_noaa_weather_format.py new file mode 100644 index 0000000..d62a951 --- /dev/null +++ b/tests/characterization/test_noaa_weather_format.py @@ -0,0 +1,110 @@ +"""Characterization: wx's NOAA forecast formatting. + +Replays real api.weather.gov responses captured on 2026-10-01 (Seattle, Denver, +Miami, Anchorage; tests/fixtures/noaa) with the clock frozen at capture time. +Variants drop leading forecast periods (other times of day), remove the +station observation, and change the length budget. +""" + +import configparser +import copy +import json +from datetime import datetime +from pathlib import Path +from unittest.mock import AsyncMock, Mock, patch + +import pytest + +from tests.characterization.golden_util import assert_golden + +FIXTURES = Path(__file__).resolve().parents[1] / "fixtures" / "noaa" +LOCATIONS = ["seattle", "denver", "miami", "anchorage"] +FROZEN_NOW = datetime(2026, 10, 1, 15, 30, 0) + + +class _FrozenDateTime(datetime): + @classmethod + def now(cls, tz=None): + return FROZEN_NOW if tz is None else FROZEN_NOW.astimezone(tz) + + +def _wx(): + from modules.commands.wx_command import WxCommand + + config = configparser.ConfigParser() + config.read_dict({"Weather": {"weather_provider": "noaa"}, "Wx_Command": {}, "Bot": {}}) + bot = Mock() + bot.config = config + bot.logger = Mock() + bot.db_manager.get_cached_geocoding = Mock(return_value=(None, None)) + bot.command_manager.send_channel_message = AsyncMock() + bot.translator.translate.side_effect = lambda key, **kwargs: f"<{key}{sorted(kwargs.items()) or ''}>" + return WxCommand(bot) + + +def _response(payload, ok=True): + response = Mock() + response.ok = ok + response.status_code = 200 if ok else 503 + response.json.return_value = payload + return response + + +def _load(name): + return json.loads((FIXTURES / f"{name}.json").read_text(encoding="utf-8")) + + +def _session(data, *, drop_periods=0, with_observation=True): + forecast = copy.deepcopy(data["forecast"]) + forecast["properties"]["periods"] = forecast["properties"]["periods"][drop_periods:] + routes = { + data["points_url"]: _response(data["points"]), + data["forecast_url"]: _response(forecast), + data["stations_url"]: _response(data["stations"]), + data["observation_url"]: _response(data["observation"], ok=with_observation), + } + session = Mock() + session.get = Mock(side_effect=lambda url, timeout=None, **kw: routes.get(url, _response({}, ok=False))) + return session, forecast["properties"]["periods"] + + +def _latlon(data): + url = data["points_url"].rsplit("/", 1)[1] + lat, lon = url.split(",") + return float(lat), float(lon) + + +@pytest.mark.parametrize("name", LOCATIONS) +def test_noaa_forecast_text(name): + data = _load(name) + lat, lon = _latlon(data) + results = {} + with patch("modules.commands.wx_command.datetime", _FrozenDateTime): + for drop in (0, 1, 2, 3): + for with_obs in (True, False): + for max_length in (130, 200): + cmd = _wx() + cmd.noaa_session, periods = _session(data, drop_periods=drop, with_observation=with_obs) + weather, _points = cmd.get_noaa_weather(lat, lon, max_length=max_length) + key = f"drop{drop}-obs{int(with_obs)}-len{max_length}" + results[key] = weather + if with_obs and max_length == 130: + results[f"tomorrow-drop{drop}"] = cmd.format_tomorrow_forecast(periods) + for days in (3, 5, 7): + results[f"multiday{days}-drop{drop}"] = cmd.format_multiday_forecast(periods, num_days=days) + results[f"details-drop{drop}"] = [ + cmd._add_period_details("Now:", p.get("detailedForecast", ""), length, max_length=130) + for p in periods[:4] + for length in (0, 60, 110) + ] + assert_golden(f"noaa_wx_{name}", results) + + +@pytest.mark.parametrize("name", ["seattle", "miami"]) +def test_noaa_hourly_text(name): + data = _load(name) + periods = data["hourly"]["properties"]["periods"] + with patch("modules.commands.wx_command.datetime", _FrozenDateTime): + cmd = _wx() + results = {f"len{n}": cmd.format_hourly_forecast(periods, max_length=n) for n in (130, 200)} + assert_golden(f"noaa_wx_hourly_{name}", results) diff --git a/tests/fixtures/noaa/anchorage.json b/tests/fixtures/noaa/anchorage.json new file mode 100644 index 0000000..38b6331 --- /dev/null +++ b/tests/fixtures/noaa/anchorage.json @@ -0,0 +1,589 @@ +{ + "points_url": "https://api.weather.gov/points/61.2181,-149.9003", + "points": { + "id": "https://api.weather.gov/points/61.2181,-149.9003", + "type": "Feature", + "properties": { + "@id": "https://api.weather.gov/points/61.2181,-149.9003", + "@type": "wx:Point", + "cwa": "AFC", + "type": "land", + "forecastOffice": "https://api.weather.gov/offices/AFC", + "gridId": "AER", + "gridX": 143, + "gridY": 236, + "forecast": "https://api.weather.gov/gridpoints/AER/143,236/forecast", + "forecastHourly": "https://api.weather.gov/gridpoints/AER/143,236/forecast/hourly", + "forecastGridData": "https://api.weather.gov/gridpoints/AER/143,236", + "observationStations": "https://api.weather.gov/gridpoints/AER/143,236/stations", + "timeZone": "America/Anchorage", + "radarStation": "PAHG", + "astronomicalData": { + "sunrise": "2026-10-01T08:07:19-08:00", + "sunset": "2026-10-01T19:30:54-08:00", + "transit": "2026-10-01T13:49:07-08:00", + "civilTwilightBegin": "2026-10-01T07:24:29-08:00", + "civilTwilightEnd": "2026-10-01T20:13:44-08:00", + "nauticalTwilightBegin": "2026-10-01T06:33:53-08:00", + "nauticalTwilightEnd": "2026-10-01T21:04:20-08:00", + "astronomicalTwilightBegin": "2026-10-01T05:40:21-08:00", + "astronomicalTwilightEnd": "2026-10-01T21:57:53-08:00" + }, + "nwr": { + "transmitter": "KEC43", + "sameCode": "002020", + "areaBroadcast": "https://api.weather.gov/radio/KEC43/broadcast", + "pointBroadcast": "https://api.weather.gov/points/61.2181,-149.9003/radio" + } + } + }, + "forecast_url": "https://api.weather.gov/gridpoints/AER/143,236/forecast", + "forecast": { + "type": "Feature", + "properties": { + "units": "us", + "forecastGenerator": "BaselineForecastGenerator", + "generatedAt": "2026-10-01T21:49:17+00:00", + "updateTime": "2026-10-01T16:23:02+00:00", + "validTimes": "2026-10-01T10:00:00+00:00/P7DT15H", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 29.8704 + }, + "periods": [ + { + "number": 1, + "name": "This Afternoon", + "startTime": "2026-10-01T13:00:00-08:00", + "endTime": "2026-10-01T18:00:00-08:00", + "isDaytime": true, + "temperature": 39, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 48 + }, + "windSpeed": "0 to 5 mph", + "windDirection": "N", + "icon": "https://api.weather.gov/icons/land/day/snow,50?size=medium", + "shortForecast": "Chance Rain And Snow Showers", + "detailedForecast": "A chance of rain and snow showers. Mostly cloudy, with a high near 39. North wind 0 to 5 mph. Chance of precipitation is 50%." + }, + { + "number": 2, + "name": "Tonight", + "startTime": "2026-10-01T18:00:00-08:00", + "endTime": "2026-10-02T06:00:00-08:00", + "isDaytime": false, + "temperature": 26, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 42 + }, + "windSpeed": "0 to 5 mph", + "windDirection": "NE", + "icon": "https://api.weather.gov/icons/land/night/rain_showers,40/fog?size=medium", + "shortForecast": "Chance Rain Showers then Patchy Freezing Fog", + "detailedForecast": "A chance of rain showers before 10pm, then patchy freezing fog. Partly cloudy, with a low around 26. Northeast wind 0 to 5 mph. Chance of precipitation is 40%." + }, + { + "number": 3, + "name": "Friday", + "startTime": "2026-10-02T06:00:00-08:00", + "endTime": "2026-10-02T18:00:00-08:00", + "isDaytime": true, + "temperature": 42, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "windSpeed": "5 mph", + "windDirection": "NE", + "icon": "https://api.weather.gov/icons/land/day/fog/few?size=medium", + "shortForecast": "Patchy Freezing Fog then Sunny", + "detailedForecast": "Patchy freezing fog before 10am. Sunny, with a high near 42. Northeast wind around 5 mph." + }, + { + "number": 4, + "name": "Friday Night", + "startTime": "2026-10-02T18:00:00-08:00", + "endTime": "2026-10-03T06:00:00-08:00", + "isDaytime": false, + "temperature": 29, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 3 + }, + "windSpeed": "5 to 10 mph", + "windDirection": "NE", + "icon": "https://api.weather.gov/icons/land/night/few?size=medium", + "shortForecast": "Mostly Clear", + "detailedForecast": "Mostly clear, with a low around 29. Northeast wind 5 to 10 mph." + }, + { + "number": 5, + "name": "Saturday", + "startTime": "2026-10-03T06:00:00-08:00", + "endTime": "2026-10-03T18:00:00-08:00", + "isDaytime": true, + "temperature": 44, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 28 + }, + "windSpeed": "5 to 10 mph", + "windDirection": "N", + "icon": "https://api.weather.gov/icons/land/day/snow,30?size=medium", + "shortForecast": "Chance Rain And Snow", + "detailedForecast": "A chance of rain and snow between 10am and 1pm. Mostly cloudy, with a high near 44. North wind 5 to 10 mph. Chance of precipitation is 30%." + }, + { + "number": 6, + "name": "Saturday Night", + "startTime": "2026-10-03T18:00:00-08:00", + "endTime": "2026-10-04T06:00:00-08:00", + "isDaytime": false, + "temperature": 33, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 36 + }, + "windSpeed": "5 to 10 mph", + "windDirection": "N", + "icon": "https://api.weather.gov/icons/land/night/rain,40?size=medium", + "shortForecast": "Chance Light Rain", + "detailedForecast": "A chance of rain after 7pm. Cloudy, with a low around 33. North wind 5 to 10 mph. Chance of precipitation is 40%." + }, + { + "number": 7, + "name": "Sunday", + "startTime": "2026-10-04T06:00:00-08:00", + "endTime": "2026-10-04T18:00:00-08:00", + "isDaytime": true, + "temperature": 45, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 60 + }, + "windSpeed": "5 mph", + "windDirection": "N", + "icon": "https://api.weather.gov/icons/land/day/rain,40/rain,60?size=medium", + "shortForecast": "Light Rain Likely", + "detailedForecast": "Rain likely. Cloudy, with a high near 45." + }, + { + "number": 8, + "name": "Sunday Night", + "startTime": "2026-10-04T18:00:00-08:00", + "endTime": "2026-10-05T06:00:00-08:00", + "isDaytime": false, + "temperature": 36, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 69 + }, + "windSpeed": "0 to 5 mph", + "windDirection": "NE", + "icon": "https://api.weather.gov/icons/land/night/rain,70?size=medium", + "shortForecast": "Light Rain Likely", + "detailedForecast": "Rain likely. Cloudy, with a low around 36." + }, + { + "number": 9, + "name": "Monday", + "startTime": "2026-10-05T06:00:00-08:00", + "endTime": "2026-10-05T18:00:00-08:00", + "isDaytime": true, + "temperature": 49, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 62 + }, + "windSpeed": "0 to 5 mph", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/day/rain,60/rain,40?size=medium", + "shortForecast": "Light Rain Likely", + "detailedForecast": "Rain likely. Cloudy, with a high near 49." + }, + { + "number": 10, + "name": "Monday Night", + "startTime": "2026-10-05T18:00:00-08:00", + "endTime": "2026-10-06T06:00:00-08:00", + "isDaytime": false, + "temperature": 36, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 44 + }, + "windSpeed": "0 to 5 mph", + "windDirection": "NE", + "icon": "https://api.weather.gov/icons/land/night/rain,40/rain,30?size=medium", + "shortForecast": "Chance Light Rain", + "detailedForecast": "A chance of rain. Cloudy, with a low around 36." + }, + { + "number": 11, + "name": "Tuesday", + "startTime": "2026-10-06T06:00:00-08:00", + "endTime": "2026-10-06T18:00:00-08:00", + "isDaytime": true, + "temperature": 49, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 46 + }, + "windSpeed": "0 to 5 mph", + "windDirection": "NE", + "icon": "https://api.weather.gov/icons/land/day/rain,50?size=medium", + "shortForecast": "Chance Light Rain", + "detailedForecast": "A chance of rain. Cloudy, with a high near 49." + }, + { + "number": 12, + "name": "Tuesday Night", + "startTime": "2026-10-06T18:00:00-08:00", + "endTime": "2026-10-07T06:00:00-08:00", + "isDaytime": false, + "temperature": 35, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 41 + }, + "windSpeed": "0 to 5 mph", + "windDirection": "NE", + "icon": "https://api.weather.gov/icons/land/night/rain,40?size=medium", + "shortForecast": "Chance Light Rain", + "detailedForecast": "A chance of rain. Cloudy, with a low around 35." + }, + { + "number": 13, + "name": "Wednesday", + "startTime": "2026-10-07T06:00:00-08:00", + "endTime": "2026-10-07T18:00:00-08:00", + "isDaytime": true, + "temperature": 47, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 39 + }, + "windSpeed": "0 to 5 mph", + "windDirection": "NE", + "icon": "https://api.weather.gov/icons/land/day/rain,40?size=medium", + "shortForecast": "Chance Light Rain", + "detailedForecast": "A chance of rain. Cloudy, with a high near 47." + }, + { + "number": 14, + "name": "Wednesday Night", + "startTime": "2026-10-07T18:00:00-08:00", + "endTime": "2026-10-08T06:00:00-08:00", + "isDaytime": false, + "temperature": 34, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 36 + }, + "windSpeed": "0 mph", + "windDirection": "", + "icon": "https://api.weather.gov/icons/land/night/rain,40/rain,30?size=medium", + "shortForecast": "Chance Light Rain", + "detailedForecast": "A chance of rain. Mostly cloudy, with a low around 34." + } + ] + } + }, + "stations_url": "https://api.weather.gov/gridpoints/AER/143,236/stations", + "stations": { + "type": "FeatureCollection", + "features": [ + { + "id": "https://api.weather.gov/stations/PAMR", + "type": "Feature", + "properties": { + "@id": "https://api.weather.gov/stations/PAMR", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 42.0624 + }, + "stationIdentifier": "PAMR", + "name": "Anchorage, Merrill Field Airport", + "timeZone": "America/Anchorage", + "provider": "ASOS-HFM", + "subProvider": "", + "distance": { + "unitCode": "wmoUnit:m", + "value": 2025.0290855549 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 82 + }, + "forecast": "https://api.weather.gov/zones/forecast/AKZ701" + } + }, + { + "id": "https://api.weather.gov/stations/PALH", + "type": "Feature", + "properties": { + "@id": "https://api.weather.gov/stations/PALH", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 21.9456 + }, + "stationIdentifier": "PALH", + "name": "Anchorage, Lake Hood Seaplane Base", + "timeZone": "America/Anchorage", + "provider": "ASOS-HFM", + "subProvider": "", + "distance": { + "unitCode": "wmoUnit:m", + "value": 5462.695498311 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 230 + }, + "forecast": "https://api.weather.gov/zones/forecast/AKZ701" + } + } + ], + "observationStations": [ + "https://api.weather.gov/stations/PAMR", + "https://api.weather.gov/stations/PALH", + "https://api.weather.gov/stations/PANC", + "https://api.weather.gov/stations/PABV", + "https://api.weather.gov/stations/PAWS", + "https://api.weather.gov/stations/PAAQ", + "https://api.weather.gov/stations/PATO", + "https://api.weather.gov/stations/PASX", + "https://api.weather.gov/stations/PAEN", + "https://api.weather.gov/stations/PATK", + "https://api.weather.gov/stations/PAWD", + "https://api.weather.gov/stations/PAPT", + "https://api.weather.gov/stations/PAVD", + "https://api.weather.gov/stations/PAHO", + "https://api.weather.gov/stations/PASO", + "https://api.weather.gov/stations/PACV", + "https://api.weather.gov/stations/PAGK", + "https://api.weather.gov/stations/PAMD", + "https://api.weather.gov/stations/PAIN", + "https://api.weather.gov/stations/PASV", + "https://api.weather.gov/stations/PAIL", + "https://api.weather.gov/stations/PAMH", + "https://api.weather.gov/stations/PAMC", + "https://api.weather.gov/stations/PATL", + "https://api.weather.gov/stations/PANN", + "https://api.weather.gov/stations/PABI", + "https://api.weather.gov/stations/PASL", + "https://api.weather.gov/stations/PAFA", + "https://api.weather.gov/stations/PADQ", + "https://api.weather.gov/stations/PATA", + "https://api.weather.gov/stations/PAOR", + "https://api.weather.gov/stations/PAKN", + "https://api.weather.gov/stations/PANI", + "https://api.weather.gov/stations/PAGA", + "https://api.weather.gov/stations/PADL", + "https://api.weather.gov/stations/PAII", + "https://api.weather.gov/stations/PANV", + "https://api.weather.gov/stations/PAIM", + "https://api.weather.gov/stations/PAKV", + "https://api.weather.gov/stations/PAEG", + "https://api.weather.gov/stations/PAYA", + "https://api.weather.gov/stations/PAHL", + "https://api.weather.gov/stations/PATG", + "https://api.weather.gov/stations/PAUN", + "https://api.weather.gov/stations/PFYU", + "https://api.weather.gov/stations/PABT", + "https://api.weather.gov/stations/PABE", + "https://api.weather.gov/stations/PAPH", + "https://api.weather.gov/stations/PAKK", + "https://api.weather.gov/stations/PASM", + "https://api.weather.gov/stations/PAJC", + "https://api.weather.gov/stations/PAEH", + "https://api.weather.gov/stations/PAFM", + "https://api.weather.gov/stations/PAGL", + "https://api.weather.gov/stations/PAKP", + "https://api.weather.gov/stations/PASK", + "https://api.weather.gov/stations/PAEM", + "https://api.weather.gov/stations/PARC", + "https://api.weather.gov/stations/PAGB", + "https://api.weather.gov/stations/PAHN", + "https://api.weather.gov/stations/PAGY", + "https://api.weather.gov/stations/PAEL", + "https://api.weather.gov/stations/PADE", + "https://api.weather.gov/stations/PAGS", + "https://api.weather.gov/stations/PACZ", + "https://api.weather.gov/stations/PAHP", + "https://api.weather.gov/stations/PAOM", + "https://api.weather.gov/stations/PAOT", + "https://api.weather.gov/stations/PAOH", + "https://api.weather.gov/stations/PAMY", + "https://api.weather.gov/stations/PASD", + "https://api.weather.gov/stations/PAJN", + "https://api.weather.gov/stations/PAWN", + "https://api.weather.gov/stations/PASI", + "https://api.weather.gov/stations/PASH", + "https://api.weather.gov/stations/PASC", + "https://api.weather.gov/stations/PAQT", + "https://api.weather.gov/stations/PACD", + "https://api.weather.gov/stations/PAVL", + "https://api.weather.gov/stations/PAFE", + "https://api.weather.gov/stations/PABA", + "https://api.weather.gov/stations/PAPG", + "https://api.weather.gov/stations/PASA", + "https://api.weather.gov/stations/PPIZ", + "https://api.weather.gov/stations/PAPO", + "https://api.weather.gov/stations/PAWG", + "https://api.weather.gov/stations/PALU", + "https://api.weather.gov/stations/PAWI", + "https://api.weather.gov/stations/PAGM", + "https://api.weather.gov/stations/PAKW", + "https://api.weather.gov/stations/PABR", + "https://api.weather.gov/stations/PAHY", + "https://api.weather.gov/stations/PASN", + "https://api.weather.gov/stations/PAKT", + "https://api.weather.gov/stations/PAMM", + "https://api.weather.gov/stations/PADU", + "https://api.weather.gov/stations/PAAK", + "https://api.weather.gov/stations/PADK" + ], + "pagination": { + "next": "https://api.weather.gov/stations?id%5B0%5D=PAAK&id%5B1%5D=PAAP&id%5B2%5D=PAAQ&id%5B3%5D=PABA&id%5B4%5D=PABE&id%5B5%5D=PABI&id%5B6%5D=PABL&id%5B7%5D=PABN&id%5B8%5D=PABR&id%5B9%5D=PABT&id%5B10%5D=PABV&id%5B11%5D=PACD&id%5B12%5D=PACV&id%5B13%5D=PACZ&id%5B14%5D=PADE&id%5B15%5D=PADK&id%5B16%5D=PADL&id%5B17%5D=PADQ&id%5B18%5D=PADT&id%5B19%5D=PADU&id%5B20%5D=PAEC&id%5B21%5D=PAEG&id%5B22%5D=PAEH&id%5B23%5D=PAEL&id%5B24%5D=PAEM&id%5B25%5D=PAEN&id%5B26%5D=PAFA&id%5B27%5D=PAFE&id%5B28%5D=PAFK&id%5B29%5D=PAFM&id%5B30%5D=PAGA&id%5B31%5D=PAGB&id%5B32%5D=PAGK&id%5B33%5D=PAGL&id%5B34%5D=PAGM&id%5B35%5D=PAGS&id%5B36%5D=PAGY&id%5B37%5D=PAHL&id%5B38%5D=PAHN&id%5B39%5D=PAHO&id%5B40%5D=PAHP&id%5B41%5D=PAHS&id%5B42%5D=PAHV&id%5B43%5D=PAHY&id%5B44%5D=PAHZ&id%5B45%5D=PAII&id%5B46%5D=PAIL&id%5B47%5D=PAIM&id%5B48%5D=PAIN&id%5B49%5D=PAJC&id%5B50%5D=PAJN&id%5B51%5D=PAJV&id%5B52%5D=PAKK&id%5B53%5D=PAKN&id%5B54%5D=PAKP&id%5B55%5D=PAKT&id%5B56%5D=PAKV&id%5B57%5D=PAKW&id%5B58%5D=PALH&id%5B59%5D=PALJ&id%5B60%5D=PALK&id%5B61%5D=PALR&id%5B62%5D=PALU&id%5B63%5D=PALV&id%5B64%5D=PAMC&id%5B65%5D=PAMD&id%5B66%5D=PAMH&id%5B67%5D=PAML&id%5B68%5D=PAMM&id%5B69%5D=PAMR&id%5B70%5D=PAMX&id%5B71%5D=PAMY&id%5B72%5D=PANC&id%5B73%5D=PANI&id%5B74%5D=PANN&id%5B75%5D=PANT&id%5B76%5D=PANV&id%5B77%5D=PAOH&id%5B78%5D=PAOM&id%5B79%5D=PAOR&id%5B80%5D=PAOT&id%5B81%5D=PAPG&id%5B82%5D=PAPH&id%5B83%5D=PAPO&id%5B84%5D=PAPT&id%5B85%5D=PAQT&id%5B86%5D=PARC&id%5B87%5D=PARD&id%5B88%5D=PARL&id%5B89%5D=PASA&id%5B90%5D=PASC&id%5B91%5D=PASD&id%5B92%5D=PASH&id%5B93%5D=PASI&id%5B94%5D=PASK&id%5B95%5D=PASL&id%5B96%5D=PASM&id%5B97%5D=PASN&id%5B98%5D=PASO&id%5B99%5D=PASP&id%5B100%5D=PASV&id%5B101%5D=PASW&id%5B102%5D=PASX&id%5B103%5D=PATA&id%5B104%5D=PATC&id%5B105%5D=PATG&id%5B106%5D=PATK&id%5B107%5D=PATL&id%5B108%5D=PATO&id%5B109%5D=PATW&id%5B110%5D=PAUN&id%5B111%5D=PAVD&id%5B112%5D=PAVL&id%5B113%5D=PAVW&id%5B114%5D=PAWD&id%5B115%5D=PAWG&id%5B116%5D=PAWI&id%5B117%5D=PAWN&id%5B118%5D=PAWS&id%5B119%5D=PAYA&id%5B120%5D=PFYU&id%5B121%5D=PPIZ&cursor=eyJzIjo1MDB9" + } + }, + "observation_url": "https://api.weather.gov/stations/PAMR/observations/latest", + "observation": { + "id": "https://api.weather.gov/stations/PAMR/observations/2026-10-01T22:30:00+00:00", + "type": "Feature", + "properties": { + "@id": "https://api.weather.gov/stations/PAMR/observations/2026-10-01T22:30:00+00:00", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 42 + }, + "station": "https://api.weather.gov/stations/PAMR", + "stationId": "PAMR", + "stationName": "Anchorage, Merrill Field Airport", + "timestamp": "2026-10-01T22:30:00+00:00", + "rawMessage": "", + "textDescription": "Cloudy", + "icon": "https://api.weather.gov/icons/land/day/ovc?size=medium", + "presentWeather": [], + "temperature": { + "unitCode": "wmoUnit:degC", + "value": 3, + "qualityControl": "V" + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 1, + "qualityControl": "V" + }, + "windDirection": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 80, + "qualityControl": "V" + }, + "windSpeed": { + "unitCode": "wmoUnit:km_h-1", + "value": 9.252, + "qualityControl": "V" + }, + "windGust": { + "unitCode": "wmoUnit:km_h-1", + "value": null, + "qualityControl": "Z" + }, + "barometricPressure": { + "unitCode": "wmoUnit:Pa", + "value": 100948.24, + "qualityControl": "V" + }, + "seaLevelPressure": { + "unitCode": "wmoUnit:Pa", + "value": null, + "qualityControl": "Z" + }, + "visibility": { + "unitCode": "wmoUnit:m", + "value": 16093.44, + "qualityControl": "C" + }, + "maxTemperatureLast24Hours": { + "unitCode": "wmoUnit:degC", + "value": null + }, + "minTemperatureLast24Hours": { + "unitCode": "wmoUnit:degC", + "value": null + }, + "precipitationLast3Hours": { + "unitCode": "wmoUnit:mm", + "value": null, + "qualityControl": "Z" + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 86.702946851968, + "qualityControl": "V" + }, + "windChill": { + "unitCode": "wmoUnit:degC", + "value": 0.4673325558422222, + "qualityControl": "V" + }, + "heatIndex": { + "unitCode": "wmoUnit:degC", + "value": null, + "qualityControl": "V" + }, + "cloudLayers": [ + { + "base": { + "unitCode": "wmoUnit:m", + "value": 1402.08 + }, + "amount": "BKN" + }, + { + "base": { + "unitCode": "wmoUnit:m", + "value": 1828.8 + }, + "amount": "OVC" + } + ] + } + } +} \ No newline at end of file diff --git a/tests/fixtures/noaa/denver.json b/tests/fixtures/noaa/denver.json new file mode 100644 index 0000000..7f3aaf9 --- /dev/null +++ b/tests/fixtures/noaa/denver.json @@ -0,0 +1,539 @@ +{ + "points_url": "https://api.weather.gov/points/39.7392,-104.9903", + "points": { + "id": "https://api.weather.gov/points/39.7392,-104.9903", + "type": "Feature", + "properties": { + "@id": "https://api.weather.gov/points/39.7392,-104.9903", + "@type": "wx:Point", + "cwa": "BOU", + "type": "land", + "forecastOffice": "https://api.weather.gov/offices/BOU", + "gridId": "BOU", + "gridX": 63, + "gridY": 62, + "forecast": "https://api.weather.gov/gridpoints/BOU/63,62/forecast", + "forecastHourly": "https://api.weather.gov/gridpoints/BOU/63,62/forecast/hourly", + "forecastGridData": "https://api.weather.gov/gridpoints/BOU/63,62", + "observationStations": "https://api.weather.gov/gridpoints/BOU/63,62/stations", + "timeZone": "America/Denver", + "radarStation": "KFTG", + "astronomicalData": { + "sunrise": "2026-10-01T06:56:28-06:00", + "sunset": "2026-10-01T18:42:34-06:00", + "transit": "2026-10-01T12:49:31-06:00", + "civilTwilightBegin": "2026-10-01T06:29:39-06:00", + "civilTwilightEnd": "2026-10-01T19:09:22-06:00", + "nauticalTwilightBegin": "2026-10-01T05:58:23-06:00", + "nauticalTwilightEnd": "2026-10-01T19:40:38-06:00", + "astronomicalTwilightBegin": "2026-10-01T05:26:51-06:00", + "astronomicalTwilightEnd": "2026-10-01T20:12:11-06:00" + }, + "nwr": { + "transmitter": "KEC76", + "sameCode": "008031", + "areaBroadcast": "https://api.weather.gov/radio/KEC76/broadcast", + "pointBroadcast": "https://api.weather.gov/points/39.7392,-104.9903/radio" + } + } + }, + "forecast_url": "https://api.weather.gov/gridpoints/BOU/63,62/forecast", + "forecast": { + "type": "Feature", + "properties": { + "units": "us", + "forecastGenerator": "BaselineForecastGenerator", + "generatedAt": "2026-10-01T20:00:34+00:00", + "updateTime": "2026-10-01T19:43:21+00:00", + "validTimes": "2026-10-01T13:00:00+00:00/P7DT12H", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 1587.0936 + }, + "periods": [ + { + "number": 1, + "name": "This Afternoon", + "startTime": "2026-10-01T14:00:00-06:00", + "endTime": "2026-10-01T18:00:00-06:00", + "isDaytime": true, + "temperature": 72, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 3 + }, + "windSpeed": "8 mph", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/day/few?size=medium", + "shortForecast": "Sunny", + "detailedForecast": "Sunny. High near 72, with temperatures falling to around 70 in the afternoon. East wind around 8 mph." + }, + { + "number": 2, + "name": "Tonight", + "startTime": "2026-10-01T18:00:00-06:00", + "endTime": "2026-10-02T06:00:00-06:00", + "isDaytime": false, + "temperature": 50, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "windSpeed": "3 to 8 mph", + "windDirection": "S", + "icon": "https://api.weather.gov/icons/land/night/few?size=medium", + "shortForecast": "Mostly Clear", + "detailedForecast": "Mostly clear, with a low around 50. South wind 3 to 8 mph." + }, + { + "number": 3, + "name": "Friday", + "startTime": "2026-10-02T06:00:00-06:00", + "endTime": "2026-10-02T18:00:00-06:00", + "isDaytime": true, + "temperature": 81, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "windSpeed": "2 to 7 mph", + "windDirection": "S", + "icon": "https://api.weather.gov/icons/land/day/few?size=medium", + "shortForecast": "Sunny", + "detailedForecast": "Sunny, with a high near 81. South wind 2 to 7 mph." + }, + { + "number": 4, + "name": "Friday Night", + "startTime": "2026-10-02T18:00:00-06:00", + "endTime": "2026-10-03T06:00:00-06:00", + "isDaytime": false, + "temperature": 53, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "windSpeed": "5 to 8 mph", + "windDirection": "S", + "icon": "https://api.weather.gov/icons/land/night/few?size=medium", + "shortForecast": "Mostly Clear", + "detailedForecast": "Mostly clear, with a low around 53. South wind 5 to 8 mph, with gusts as high as 16 mph." + }, + { + "number": 5, + "name": "Saturday", + "startTime": "2026-10-03T06:00:00-06:00", + "endTime": "2026-10-03T18:00:00-06:00", + "isDaytime": true, + "temperature": 85, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "windSpeed": "2 to 9 mph", + "windDirection": "NNW", + "icon": "https://api.weather.gov/icons/land/day/few?size=medium", + "shortForecast": "Sunny", + "detailedForecast": "Sunny, with a high near 85. North northwest wind 2 to 9 mph, with gusts as high as 16 mph." + }, + { + "number": 6, + "name": "Saturday Night", + "startTime": "2026-10-03T18:00:00-06:00", + "endTime": "2026-10-04T06:00:00-06:00", + "isDaytime": false, + "temperature": 54, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "windSpeed": "3 to 9 mph", + "windDirection": "ENE", + "icon": "https://api.weather.gov/icons/land/night/few?size=medium", + "shortForecast": "Mostly Clear", + "detailedForecast": "Mostly clear, with a low around 54." + }, + { + "number": 7, + "name": "Sunday", + "startTime": "2026-10-04T06:00:00-06:00", + "endTime": "2026-10-04T18:00:00-06:00", + "isDaytime": true, + "temperature": 82, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 1 + }, + "windSpeed": "6 mph", + "windDirection": "SE", + "icon": "https://api.weather.gov/icons/land/day/few?size=medium", + "shortForecast": "Sunny", + "detailedForecast": "Sunny, with a high near 82." + }, + { + "number": 8, + "name": "Sunday Night", + "startTime": "2026-10-04T18:00:00-06:00", + "endTime": "2026-10-05T06:00:00-06:00", + "isDaytime": false, + "temperature": 55, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 1 + }, + "windSpeed": "6 mph", + "windDirection": "S", + "icon": "https://api.weather.gov/icons/land/night/skc?size=medium", + "shortForecast": "Clear", + "detailedForecast": "Clear, with a low around 55." + }, + { + "number": 9, + "name": "Monday", + "startTime": "2026-10-05T06:00:00-06:00", + "endTime": "2026-10-05T18:00:00-06:00", + "isDaytime": true, + "temperature": 87, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "windSpeed": "2 to 7 mph", + "windDirection": "SSE", + "icon": "https://api.weather.gov/icons/land/day/skc?size=medium", + "shortForecast": "Sunny", + "detailedForecast": "Sunny, with a high near 87." + }, + { + "number": 10, + "name": "Monday Night", + "startTime": "2026-10-05T18:00:00-06:00", + "endTime": "2026-10-06T06:00:00-06:00", + "isDaytime": false, + "temperature": 59, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 1 + }, + "windSpeed": "7 mph", + "windDirection": "SSW", + "icon": "https://api.weather.gov/icons/land/night/sct?size=medium", + "shortForecast": "Partly Cloudy", + "detailedForecast": "Partly cloudy, with a low around 59." + }, + { + "number": 11, + "name": "Tuesday", + "startTime": "2026-10-06T06:00:00-06:00", + "endTime": "2026-10-06T18:00:00-06:00", + "isDaytime": true, + "temperature": 84, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 6 + }, + "windSpeed": "5 to 8 mph", + "windDirection": "NNW", + "icon": "https://api.weather.gov/icons/land/day/sct?size=medium", + "shortForecast": "Mostly Sunny", + "detailedForecast": "Mostly sunny, with a high near 84." + }, + { + "number": 12, + "name": "Tuesday Night", + "startTime": "2026-10-06T18:00:00-06:00", + "endTime": "2026-10-07T06:00:00-06:00", + "isDaytime": false, + "temperature": 57, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 7 + }, + "windSpeed": "3 to 8 mph", + "windDirection": "WSW", + "icon": "https://api.weather.gov/icons/land/night/sct?size=medium", + "shortForecast": "Partly Cloudy", + "detailedForecast": "Partly cloudy, with a low around 57." + }, + { + "number": 13, + "name": "Wednesday", + "startTime": "2026-10-07T06:00:00-06:00", + "endTime": "2026-10-07T18:00:00-06:00", + "isDaytime": true, + "temperature": 82, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "windSpeed": "3 to 7 mph", + "windDirection": "NE", + "icon": "https://api.weather.gov/icons/land/day/skc?size=medium", + "shortForecast": "Sunny", + "detailedForecast": "Sunny, with a high near 82." + }, + { + "number": 14, + "name": "Wednesday Night", + "startTime": "2026-10-07T18:00:00-06:00", + "endTime": "2026-10-08T06:00:00-06:00", + "isDaytime": false, + "temperature": 56, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "windSpeed": "7 mph", + "windDirection": "S", + "icon": "https://api.weather.gov/icons/land/night/few?size=medium", + "shortForecast": "Mostly Clear", + "detailedForecast": "Mostly clear, with a low around 56." + } + ] + } + }, + "stations_url": "https://api.weather.gov/gridpoints/BOU/63,62/stations", + "stations": { + "type": "FeatureCollection", + "features": [ + { + "id": "https://api.weather.gov/stations/KBJC", + "type": "Feature", + "properties": { + "@id": "https://api.weather.gov/stations/KBJC", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 1691.9448 + }, + "stationIdentifier": "KBJC", + "name": "Broomfield / Jeffco", + "timeZone": "America/Denver", + "provider": "OTHER-MTR", + "subProvider": "", + "distance": { + "unitCode": "wmoUnit:m", + "value": 19333.36205419 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 330 + }, + "forecast": "https://api.weather.gov/zones/forecast/COZ039" + } + }, + { + "id": "https://api.weather.gov/stations/KBKF", + "type": "Feature", + "properties": { + "@id": "https://api.weather.gov/stations/KBKF", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 1699.8696 + }, + "stationIdentifier": "KBKF", + "name": "Buckley Space Force Base", + "timeZone": "America/Denver", + "provider": "OTHER-MTR", + "subProvider": "", + "distance": { + "unitCode": "wmoUnit:m", + "value": 20361.38362392 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 101 + }, + "forecast": "https://api.weather.gov/zones/forecast/COZ040" + } + } + ], + "observationStations": [ + "https://api.weather.gov/stations/KBJC", + "https://api.weather.gov/stations/KBKF", + "https://api.weather.gov/stations/KAPA", + "https://api.weather.gov/stations/KEIK", + "https://api.weather.gov/stations/KDEN", + "https://api.weather.gov/stations/KBDU", + "https://api.weather.gov/stations/KCFO", + "https://api.weather.gov/stations/KLMO", + "https://api.weather.gov/stations/KMNH", + "https://api.weather.gov/stations/KFNL", + "https://api.weather.gov/stations/KGXY", + "https://api.weather.gov/stations/KGNB", + "https://api.weather.gov/stations/KAFF", + "https://api.weather.gov/stations/K4BM", + "https://api.weather.gov/stations/KCCU", + "https://api.weather.gov/stations/KCOS", + "https://api.weather.gov/stations/KFMM", + "https://api.weather.gov/stations/KFCS", + "https://api.weather.gov/stations/K20V", + "https://api.weather.gov/stations/KLIC", + "https://api.weather.gov/stations/KLXV", + "https://api.weather.gov/stations/KAEJ", + "https://api.weather.gov/stations/K33V", + "https://api.weather.gov/stations/KCYS", + "https://api.weather.gov/stations/KAKO", + "https://api.weather.gov/stations/KANK", + "https://api.weather.gov/stations/KEGE", + "https://api.weather.gov/stations/KPUB", + "https://api.weather.gov/stations/KASE", + "https://api.weather.gov/stations/KSTK", + "https://api.weather.gov/stations/KMYP", + "https://api.weather.gov/stations/KLAR", + "https://api.weather.gov/stations/KIBM", + "https://api.weather.gov/stations/KHDN", + "https://api.weather.gov/stations/K04V", + "https://api.weather.gov/stations/KGUC", + "https://api.weather.gov/stations/KSNY", + "https://api.weather.gov/stations/KLHX", + "https://api.weather.gov/stations/KCAG", + "https://api.weather.gov/stations/KITR", + "https://api.weather.gov/stations/KHEQ", + "https://api.weather.gov/stations/KLAA", + "https://api.weather.gov/stations/KGLD", + "https://api.weather.gov/stations/KIML", + "https://api.weather.gov/stations/KOGA" + ], + "pagination": { + "next": "https://api.weather.gov/stations?id%5B0%5D=K04V&id%5B1%5D=K20V&id%5B2%5D=K33V&id%5B3%5D=K4BM&id%5B4%5D=KABH&id%5B5%5D=KAEJ&id%5B6%5D=KAFF&id%5B7%5D=KAKO&id%5B8%5D=KANK&id%5B9%5D=KAPA&id%5B10%5D=KASE&id%5B11%5D=KBDU&id%5B12%5D=KBJC&id%5B13%5D=KBKF&id%5B14%5D=KCAG&id%5B15%5D=KCCU&id%5B16%5D=KCFO&id%5B17%5D=KCOS&id%5B18%5D=KCYS&id%5B19%5D=KDCP&id%5B20%5D=KDEN&id%5B21%5D=KEGE&id%5B22%5D=KEIK&id%5B23%5D=KFCS&id%5B24%5D=KFMM&id%5B25%5D=KFNL&id%5B26%5D=KFTG&id%5B27%5D=KGLD&id%5B28%5D=KGNB&id%5B29%5D=KGUC&id%5B30%5D=KGXY&id%5B31%5D=KHDN&id%5B32%5D=KHEQ&id%5B33%5D=KIBM&id%5B34%5D=KIML&id%5B35%5D=KITR&id%5B36%5D=KLAA&id%5B37%5D=KLAR&id%5B38%5D=KLHX&id%5B39%5D=KLIC&id%5B40%5D=KLMO&id%5B41%5D=KLXV&id%5B42%5D=KMNH&id%5B43%5D=KMYP&id%5B44%5D=KOGA&id%5B45%5D=KPUB&id%5B46%5D=KSNY&id%5B47%5D=KSTK&cursor=eyJzIjo1MDB9" + } + }, + "observation_url": "https://api.weather.gov/stations/KBJC/observations/latest", + "observation": { + "id": "https://api.weather.gov/stations/KBJC/observations/2026-10-01T21:45:00+00:00", + "type": "Feature", + "properties": { + "@id": "https://api.weather.gov/stations/KBJC/observations/2026-10-01T21:45:00+00:00", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 1724 + }, + "station": "https://api.weather.gov/stations/KBJC", + "stationId": "KBJC", + "stationName": "Broomfield / Jeffco", + "timestamp": "2026-10-01T21:45:00+00:00", + "rawMessage": "KBJC 012145Z 17007KT 10SM CLR 22/03 A3024", + "textDescription": "Clear", + "icon": "https://api.weather.gov/icons/land/day/skc?size=medium", + "presentWeather": [], + "temperature": { + "unitCode": "wmoUnit:degC", + "value": 22, + "qualityControl": "V" + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 3, + "qualityControl": "V" + }, + "windDirection": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 170, + "qualityControl": "V" + }, + "windSpeed": { + "unitCode": "wmoUnit:km_h-1", + "value": 12.96, + "qualityControl": "V" + }, + "windGust": { + "unitCode": "wmoUnit:km_h-1", + "value": null, + "qualityControl": "Z" + }, + "barometricPressure": { + "unitCode": "wmoUnit:Pa", + "value": 102410, + "qualityControl": "V" + }, + "seaLevelPressure": { + "unitCode": "wmoUnit:Pa", + "value": null, + "qualityControl": "Z" + }, + "visibility": { + "unitCode": "wmoUnit:m", + "value": 16090, + "qualityControl": "C" + }, + "maxTemperatureLast24Hours": { + "unitCode": "wmoUnit:degC", + "value": null + }, + "minTemperatureLast24Hours": { + "unitCode": "wmoUnit:degC", + "value": null + }, + "precipitationLastHour": { + "unitCode": "wmoUnit:mm", + "value": null, + "qualityControl": "Z" + }, + "precipitationLast3Hours": { + "unitCode": "wmoUnit:mm", + "value": null, + "qualityControl": "Z" + }, + "precipitationLast6Hours": { + "unitCode": "wmoUnit:mm", + "value": null, + "qualityControl": "Z" + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 28.705465714271, + "qualityControl": "V" + }, + "windChill": { + "unitCode": "wmoUnit:degC", + "value": null, + "qualityControl": "V" + }, + "heatIndex": { + "unitCode": "wmoUnit:degC", + "value": 21.00508716031722, + "qualityControl": "V" + }, + "cloudLayers": [ + { + "base": { + "unitCode": "wmoUnit:m", + "value": null + }, + "amount": "CLR" + } + ] + } + } +} \ No newline at end of file diff --git a/tests/fixtures/noaa/miami.json b/tests/fixtures/noaa/miami.json new file mode 100644 index 0000000..963931f --- /dev/null +++ b/tests/fixtures/noaa/miami.json @@ -0,0 +1,1500 @@ +{ + "points_url": "https://api.weather.gov/points/25.7617,-80.1918", + "points": { + "id": "https://api.weather.gov/points/25.7617,-80.1918", + "type": "Feature", + "properties": { + "@id": "https://api.weather.gov/points/25.7617,-80.1918", + "@type": "wx:Point", + "cwa": "MFL", + "type": "land", + "forecastOffice": "https://api.weather.gov/offices/MFL", + "gridId": "MFL", + "gridX": 110, + "gridY": 50, + "forecast": "https://api.weather.gov/gridpoints/MFL/110,50/forecast", + "forecastHourly": "https://api.weather.gov/gridpoints/MFL/110,50/forecast/hourly", + "forecastGridData": "https://api.weather.gov/gridpoints/MFL/110,50", + "observationStations": "https://api.weather.gov/gridpoints/MFL/110,50/stations", + "timeZone": "America/New_York", + "radarStation": "KAMX", + "astronomicalData": { + "sunrise": "2026-10-01T07:13:07-04:00", + "sunset": "2026-10-01T19:07:34-04:00", + "transit": "2026-10-01T13:10:20-04:00", + "civilTwilightBegin": "2026-10-01T06:50:13-04:00", + "civilTwilightEnd": "2026-10-01T19:30:28-04:00", + "nauticalTwilightBegin": "2026-10-01T06:23:34-04:00", + "nauticalTwilightEnd": "2026-10-01T19:57:07-04:00", + "astronomicalTwilightBegin": "2026-10-01T05:56:52-04:00", + "astronomicalTwilightEnd": "2026-10-01T20:23:49-04:00" + }, + "nwr": { + "transmitter": "WZ2531", + "sameCode": "012086", + "areaBroadcast": "https://api.weather.gov/radio/WZ2531/broadcast", + "pointBroadcast": "https://api.weather.gov/points/25.7617,-80.1918/radio" + } + } + }, + "forecast_url": "https://api.weather.gov/gridpoints/MFL/110,50/forecast", + "forecast": { + "type": "Feature", + "properties": { + "units": "us", + "forecastGenerator": "BaselineForecastGenerator", + "generatedAt": "2026-10-01T22:33:03+00:00", + "updateTime": "2026-10-01T20:17:07+00:00", + "validTimes": "2026-10-01T14:00:00+00:00/P7DT11H", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 0.9144 + }, + "periods": [ + { + "number": 1, + "name": "Tonight", + "startTime": "2026-10-01T18:00:00-04:00", + "endTime": "2026-10-02T06:00:00-04:00", + "isDaytime": false, + "temperature": 81, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 43 + }, + "windSpeed": "17 mph", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/night/tsra_sct,40?size=medium", + "shortForecast": "Chance Showers And Thunderstorms", + "detailedForecast": "A chance of showers and thunderstorms. Mostly cloudy, with a low around 81. East wind around 17 mph, with gusts as high as 21 mph. Chance of precipitation is 40%. New rainfall amounts less than a tenth of an inch possible." + }, + { + "number": 2, + "name": "Friday", + "startTime": "2026-10-02T06:00:00-04:00", + "endTime": "2026-10-02T18:00:00-04:00", + "isDaytime": true, + "temperature": 88, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 35 + }, + "windSpeed": "14 to 18 mph", + "windDirection": "SE", + "icon": "https://api.weather.gov/icons/land/day/tsra_sct,40/tsra_sct,30?size=medium", + "shortForecast": "Chance Showers And Thunderstorms", + "detailedForecast": "A chance of showers and thunderstorms before 8am, then a chance of showers and thunderstorms between 8am and 9am, then a chance of showers and thunderstorms. Partly sunny, with a high near 88. Heat index values as high as 104. Southeast wind 14 to 18 mph, with gusts as high as 22 mph. Chance of precipitation is 40%. New rainfall amounts less than a tenth of an inch possible." + }, + { + "number": 3, + "name": "Friday Night", + "startTime": "2026-10-02T18:00:00-04:00", + "endTime": "2026-10-03T06:00:00-04:00", + "isDaytime": false, + "temperature": 81, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 45 + }, + "windSpeed": "15 mph", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/night/tsra_hi,50/tsra_hi,40?size=medium", + "shortForecast": "Chance Showers And Thunderstorms", + "detailedForecast": "A chance of showers and thunderstorms before 3am, then a chance of showers and thunderstorms. Partly cloudy, with a low around 81. East wind around 15 mph, with gusts as high as 18 mph. Chance of precipitation is 50%. New rainfall amounts less than a tenth of an inch possible." + }, + { + "number": 4, + "name": "Saturday", + "startTime": "2026-10-03T06:00:00-04:00", + "endTime": "2026-10-03T18:00:00-04:00", + "isDaytime": true, + "temperature": 88, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 37 + }, + "windSpeed": "15 mph", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/day/tsra_hi,40?size=medium", + "shortForecast": "Chance Showers And Thunderstorms", + "detailedForecast": "A chance of showers and thunderstorms before 8am, then a chance of showers and thunderstorms. Mostly sunny, with a high near 88. Heat index values as high as 103. East wind around 15 mph, with gusts as high as 20 mph. Chance of precipitation is 40%." + }, + { + "number": 5, + "name": "Saturday Night", + "startTime": "2026-10-03T18:00:00-04:00", + "endTime": "2026-10-04T06:00:00-04:00", + "isDaytime": false, + "temperature": 81, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 36 + }, + "windSpeed": "14 mph", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/night/tsra_hi,40/tsra_hi,20?size=medium", + "shortForecast": "Chance Showers And Thunderstorms", + "detailedForecast": "A chance of showers and thunderstorms before 2am. Partly cloudy, with a low around 81. East wind around 14 mph. Chance of precipitation is 40%." + }, + { + "number": 6, + "name": "Sunday", + "startTime": "2026-10-04T06:00:00-04:00", + "endTime": "2026-10-04T18:00:00-04:00", + "isDaytime": true, + "temperature": 88, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 20 + }, + "windSpeed": "13 mph", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/day/few/tsra_hi,20?size=medium", + "shortForecast": "Sunny then Slight Chance Showers And Thunderstorms", + "detailedForecast": "A slight chance of showers and thunderstorms after 2pm. Sunny, with a high near 88. East wind around 13 mph. Chance of precipitation is 20%." + }, + { + "number": 7, + "name": "Sunday Night", + "startTime": "2026-10-04T18:00:00-04:00", + "endTime": "2026-10-05T06:00:00-04:00", + "isDaytime": false, + "temperature": 79, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 20 + }, + "windSpeed": "6 to 9 mph", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/night/tsra_hi,20/sct?size=medium", + "shortForecast": "Slight Chance Showers And Thunderstorms then Partly Cloudy", + "detailedForecast": "A slight chance of showers and thunderstorms before 8pm. Partly cloudy, with a low around 79. East wind 6 to 9 mph. Chance of precipitation is 20%." + }, + { + "number": 8, + "name": "Monday", + "startTime": "2026-10-05T06:00:00-04:00", + "endTime": "2026-10-05T18:00:00-04:00", + "isDaytime": true, + "temperature": 89, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 37 + }, + "windSpeed": "8 mph", + "windDirection": "SE", + "icon": "https://api.weather.gov/icons/land/day/sct/tsra_hi,40?size=medium", + "shortForecast": "Mostly Sunny then Chance Showers And Thunderstorms", + "detailedForecast": "A chance of showers and thunderstorms after 2pm. Mostly sunny, with a high near 89. Southeast wind around 8 mph. Chance of precipitation is 40%." + }, + { + "number": 9, + "name": "Monday Night", + "startTime": "2026-10-05T18:00:00-04:00", + "endTime": "2026-10-06T06:00:00-04:00", + "isDaytime": false, + "temperature": 77, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 37 + }, + "windSpeed": "2 to 6 mph", + "windDirection": "SE", + "icon": "https://api.weather.gov/icons/land/night/tsra_hi,40/tsra_hi,20?size=medium", + "shortForecast": "Chance Showers And Thunderstorms", + "detailedForecast": "A chance of showers and thunderstorms. Partly cloudy, with a low around 77. Southeast wind 2 to 6 mph. Chance of precipitation is 40%." + }, + { + "number": 10, + "name": "Tuesday", + "startTime": "2026-10-06T06:00:00-04:00", + "endTime": "2026-10-06T18:00:00-04:00", + "isDaytime": true, + "temperature": 88, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 62 + }, + "windSpeed": "3 to 7 mph", + "windDirection": "SE", + "icon": "https://api.weather.gov/icons/land/day/tsra_hi,20/tsra_hi,60?size=medium", + "shortForecast": "Slight Chance Showers And Thunderstorms", + "detailedForecast": "A slight chance of showers and thunderstorms before 2pm, then showers and thunderstorms likely. Mostly sunny, with a high near 88. Chance of precipitation is 60%." + }, + { + "number": 11, + "name": "Tuesday Night", + "startTime": "2026-10-06T18:00:00-04:00", + "endTime": "2026-10-07T06:00:00-04:00", + "isDaytime": false, + "temperature": 77, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 62 + }, + "windSpeed": "5 mph", + "windDirection": "S", + "icon": "https://api.weather.gov/icons/land/night/tsra_hi,60/tsra_hi,30?size=medium", + "shortForecast": "Showers And Thunderstorms Likely then Chance Showers And Thunderstorms", + "detailedForecast": "Showers and thunderstorms likely before 8pm, then a chance of showers and thunderstorms. Mostly cloudy, with a low around 77. Chance of precipitation is 60%." + }, + { + "number": 12, + "name": "Wednesday", + "startTime": "2026-10-07T06:00:00-04:00", + "endTime": "2026-10-07T18:00:00-04:00", + "isDaytime": true, + "temperature": 88, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 69 + }, + "windSpeed": "3 to 8 mph", + "windDirection": "S", + "icon": "https://api.weather.gov/icons/land/day/tsra_hi,30/tsra_hi,70?size=medium", + "shortForecast": "Chance Showers And Thunderstorms", + "detailedForecast": "A chance of showers and thunderstorms before 2pm, then showers and thunderstorms likely. Partly sunny, with a high near 88. Chance of precipitation is 70%." + }, + { + "number": 13, + "name": "Wednesday Night", + "startTime": "2026-10-07T18:00:00-04:00", + "endTime": "2026-10-08T06:00:00-04:00", + "isDaytime": false, + "temperature": 77, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 69 + }, + "windSpeed": "5 mph", + "windDirection": "S", + "icon": "https://api.weather.gov/icons/land/night/tsra_hi,70/tsra_hi,40?size=medium", + "shortForecast": "Showers And Thunderstorms Likely then Chance Showers And Thunderstorms", + "detailedForecast": "Showers and thunderstorms likely before 8pm, then a chance of showers and thunderstorms. Mostly cloudy, with a low around 77. Chance of precipitation is 70%." + }, + { + "number": 14, + "name": "Thursday", + "startTime": "2026-10-08T06:00:00-04:00", + "endTime": "2026-10-08T18:00:00-04:00", + "isDaytime": true, + "temperature": 88, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 61 + }, + "windSpeed": "5 to 8 mph", + "windDirection": "S", + "icon": "https://api.weather.gov/icons/land/day/tsra_hi,30/tsra_hi,60?size=medium", + "shortForecast": "Showers And Thunderstorms Likely", + "detailedForecast": "A slight chance of rain showers before 8am, then showers and thunderstorms likely. Mostly sunny, with a high near 88." + } + ] + } + }, + "stations_url": "https://api.weather.gov/gridpoints/MFL/110,50/stations", + "stations": { + "type": "FeatureCollection", + "features": [ + { + "id": "https://api.weather.gov/stations/KMIA", + "type": "Feature", + "properties": { + "@id": "https://api.weather.gov/stations/KMIA", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 3.048 + }, + "stationIdentifier": "KMIA", + "name": "Miami, Miami International Airport", + "timeZone": "America/New_York", + "provider": "ASOS-HFM", + "subProvider": "", + "distance": { + "unitCode": "wmoUnit:m", + "value": 13352.943132011 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 285 + }, + "forecast": "https://api.weather.gov/zones/forecast/FLZ074" + } + }, + { + "id": "https://api.weather.gov/stations/KOPF", + "type": "Feature", + "properties": { + "@id": "https://api.weather.gov/stations/KOPF", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 3.048 + }, + "stationIdentifier": "KOPF", + "name": "Miami, Opa Locka Airport", + "timeZone": "America/New_York", + "provider": "ASOS-HFM", + "subProvider": "", + "distance": { + "unitCode": "wmoUnit:m", + "value": 19269.596429138 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 330 + }, + "forecast": "https://api.weather.gov/zones/forecast/FLZ074" + } + } + ], + "observationStations": [ + "https://api.weather.gov/stations/KMIA", + "https://api.weather.gov/stations/KOPF", + "https://api.weather.gov/stations/KHWO", + "https://api.weather.gov/stations/KTMB", + "https://api.weather.gov/stations/KHST", + "https://api.weather.gov/stations/KFLL", + "https://api.weather.gov/stations/KFXE", + "https://api.weather.gov/stations/KPMP", + "https://api.weather.gov/stations/KDJT", + "https://api.weather.gov/stations/KMTH", + "https://api.weather.gov/stations/KSUA", + "https://api.weather.gov/stations/KAPF", + "https://api.weather.gov/stations/KRSW", + "https://api.weather.gov/stations/KOBE", + "https://api.weather.gov/stations/KFMY", + "https://api.weather.gov/stations/KFPR", + "https://api.weather.gov/stations/KNQX", + "https://api.weather.gov/stations/KEYW", + "https://api.weather.gov/stations/KPGD", + "https://api.weather.gov/stations/KSRQ" + ], + "pagination": { + "next": "https://api.weather.gov/stations?id%5B0%5D=K2IS&id%5B1%5D=KAPF&id%5B2%5D=KDJT&id%5B3%5D=KEYW&id%5B4%5D=KFLL&id%5B5%5D=KFMY&id%5B6%5D=KFPR&id%5B7%5D=KFXE&id%5B8%5D=KHST&id%5B9%5D=KHWO&id%5B10%5D=KMIA&id%5B11%5D=KMTH&id%5B12%5D=KNQX&id%5B13%5D=KOBE&id%5B14%5D=KOPF&id%5B15%5D=KPGD&id%5B16%5D=KPMP&id%5B17%5D=KRSW&id%5B18%5D=KSRQ&id%5B19%5D=KSUA&id%5B20%5D=KTMB&cursor=eyJzIjo1MDB9" + } + }, + "observation_url": "https://api.weather.gov/stations/KMIA/observations/latest", + "observation": { + "id": "https://api.weather.gov/stations/KMIA/observations/2026-10-01T22:20:00+00:00", + "type": "Feature", + "properties": { + "@id": "https://api.weather.gov/stations/KMIA/observations/2026-10-01T22:20:00+00:00", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 4 + }, + "station": "https://api.weather.gov/stations/KMIA", + "stationId": "KMIA", + "stationName": "Miami, Miami International Airport", + "timestamp": "2026-10-01T22:20:00+00:00", + "rawMessage": "", + "textDescription": "Rain", + "icon": "https://api.weather.gov/icons/land/day/rain?size=medium", + "presentWeather": [ + { + "intensity": null, + "modifier": null, + "weather": "rain", + "rawString": "RA" + } + ], + "temperature": { + "unitCode": "wmoUnit:degC", + "value": 25, + "qualityControl": "V" + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 23, + "qualityControl": "V" + }, + "windDirection": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 80, + "qualityControl": "V" + }, + "windSpeed": { + "unitCode": "wmoUnit:km_h-1", + "value": 12.96, + "qualityControl": "V" + }, + "windGust": { + "unitCode": "wmoUnit:km_h-1", + "value": null, + "qualityControl": "Z" + }, + "barometricPressure": { + "unitCode": "wmoUnit:Pa", + "value": 101557.8, + "qualityControl": "V" + }, + "seaLevelPressure": { + "unitCode": "wmoUnit:Pa", + "value": null, + "qualityControl": "Z" + }, + "visibility": { + "unitCode": "wmoUnit:m", + "value": 11265.41, + "qualityControl": "C" + }, + "maxTemperatureLast24Hours": { + "unitCode": "wmoUnit:degC", + "value": null + }, + "minTemperatureLast24Hours": { + "unitCode": "wmoUnit:degC", + "value": null + }, + "precipitationLast3Hours": { + "unitCode": "wmoUnit:mm", + "value": null, + "qualityControl": "Z" + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 88.67956137467, + "qualityControl": "V" + }, + "windChill": { + "unitCode": "wmoUnit:degC", + "value": null, + "qualityControl": "V" + }, + "heatIndex": { + "unitCode": "wmoUnit:degC", + "value": 25.871077435894446, + "qualityControl": "V" + }, + "cloudLayers": [ + { + "base": { + "unitCode": "wmoUnit:m", + "value": 3352.8 + }, + "amount": "BKN" + } + ] + } + }, + "hourly_url": "https://api.weather.gov/gridpoints/MFL/110,50/forecast/hourly", + "hourly": { + "type": "Feature", + "properties": { + "units": "us", + "forecastGenerator": "HourlyForecastGenerator", + "generatedAt": "2026-10-01T22:09:27+00:00", + "updateTime": "2026-10-01T20:17:07+00:00", + "validTimes": "2026-10-01T14:00:00+00:00/P7DT11H", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 0.9144 + }, + "periods": [ + { + "number": 1, + "name": "", + "startTime": "2026-10-01T18:00:00-04:00", + "endTime": "2026-10-01T19:00:00-04:00", + "isDaytime": false, + "temperature": 83, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 38 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 26.11111111111111 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 88 + }, + "windSpeed": "15 mph", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/night/tsra,40?size=small", + "shortForecast": "Chance Showers And Thunderstorms", + "detailedForecast": "" + }, + { + "number": 2, + "name": "", + "startTime": "2026-10-01T19:00:00-04:00", + "endTime": "2026-10-01T20:00:00-04:00", + "isDaytime": false, + "temperature": 83, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 34 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 25.555555555555557 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 85 + }, + "windSpeed": "15 mph", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/night/tsra_sct,30?size=small", + "shortForecast": "Chance Showers And Thunderstorms", + "detailedForecast": "" + }, + { + "number": 3, + "name": "", + "startTime": "2026-10-01T20:00:00-04:00", + "endTime": "2026-10-01T21:00:00-04:00", + "isDaytime": false, + "temperature": 82, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 43 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 25.555555555555557 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 88 + }, + "windSpeed": "15 mph", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/night/tsra_sct,40?size=small", + "shortForecast": "Chance Showers And Thunderstorms", + "detailedForecast": "" + }, + { + "number": 4, + "name": "", + "startTime": "2026-10-01T21:00:00-04:00", + "endTime": "2026-10-01T22:00:00-04:00", + "isDaytime": false, + "temperature": 83, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 39 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 26.11111111111111 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 88 + }, + "windSpeed": "16 mph", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/night/tsra_sct,40?size=small", + "shortForecast": "Chance Showers And Thunderstorms", + "detailedForecast": "" + }, + { + "number": 5, + "name": "", + "startTime": "2026-10-01T22:00:00-04:00", + "endTime": "2026-10-01T23:00:00-04:00", + "isDaytime": false, + "temperature": 83, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 34 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 25.555555555555557 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 85 + }, + "windSpeed": "17 mph", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/night/tsra_sct,30?size=small", + "shortForecast": "Chance Showers And Thunderstorms", + "detailedForecast": "" + }, + { + "number": 6, + "name": "", + "startTime": "2026-10-01T23:00:00-04:00", + "endTime": "2026-10-02T00:00:00-04:00", + "isDaytime": false, + "temperature": 83, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 35 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 25.555555555555557 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 85 + }, + "windSpeed": "17 mph", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/night/tsra_hi,40?size=small", + "shortForecast": "Chance Showers And Thunderstorms", + "detailedForecast": "" + }, + { + "number": 7, + "name": "", + "startTime": "2026-10-02T00:00:00-04:00", + "endTime": "2026-10-02T01:00:00-04:00", + "isDaytime": false, + "temperature": 83, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 33 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 25.555555555555557 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 85 + }, + "windSpeed": "17 mph", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/night/tsra_hi,30?size=small", + "shortForecast": "Chance Showers And Thunderstorms", + "detailedForecast": "" + }, + { + "number": 8, + "name": "", + "startTime": "2026-10-02T01:00:00-04:00", + "endTime": "2026-10-02T02:00:00-04:00", + "isDaytime": false, + "temperature": 83, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 34 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 25.555555555555557 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 85 + }, + "windSpeed": "17 mph", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/night/tsra_hi,30?size=small", + "shortForecast": "Chance Showers And Thunderstorms", + "detailedForecast": "" + }, + { + "number": 9, + "name": "", + "startTime": "2026-10-02T02:00:00-04:00", + "endTime": "2026-10-02T03:00:00-04:00", + "isDaytime": false, + "temperature": 83, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 31 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 25.555555555555557 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 85 + }, + "windSpeed": "16 mph", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/night/tsra_hi,30?size=small", + "shortForecast": "Chance Showers And Thunderstorms", + "detailedForecast": "" + }, + { + "number": 10, + "name": "", + "startTime": "2026-10-02T03:00:00-04:00", + "endTime": "2026-10-02T04:00:00-04:00", + "isDaytime": false, + "temperature": 83, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 36 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 25.555555555555557 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 85 + }, + "windSpeed": "17 mph", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/night/tsra_sct,40?size=small", + "shortForecast": "Chance Showers And Thunderstorms", + "detailedForecast": "" + }, + { + "number": 11, + "name": "", + "startTime": "2026-10-02T04:00:00-04:00", + "endTime": "2026-10-02T05:00:00-04:00", + "isDaytime": false, + "temperature": 83, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 36 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 25.555555555555557 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 85 + }, + "windSpeed": "17 mph", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/night/tsra_sct,40?size=small", + "shortForecast": "Chance Showers And Thunderstorms", + "detailedForecast": "" + }, + { + "number": 12, + "name": "", + "startTime": "2026-10-02T05:00:00-04:00", + "endTime": "2026-10-02T06:00:00-04:00", + "isDaytime": false, + "temperature": 82, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 34 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 25.555555555555557 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 88 + }, + "windSpeed": "17 mph", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/night/tsra_sct,30?size=small", + "shortForecast": "Chance Showers And Thunderstorms", + "detailedForecast": "" + }, + { + "number": 13, + "name": "", + "startTime": "2026-10-02T06:00:00-04:00", + "endTime": "2026-10-02T07:00:00-04:00", + "isDaytime": true, + "temperature": 83, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 35 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 25.555555555555557 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 85 + }, + "windSpeed": "17 mph", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/day/tsra_sct,40?size=small", + "shortForecast": "Chance Showers And Thunderstorms", + "detailedForecast": "" + }, + { + "number": 14, + "name": "", + "startTime": "2026-10-02T07:00:00-04:00", + "endTime": "2026-10-02T08:00:00-04:00", + "isDaytime": true, + "temperature": 82, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 27 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 25.555555555555557 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 88 + }, + "windSpeed": "18 mph", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/day/tsra_sct,30?size=small", + "shortForecast": "Chance Showers And Thunderstorms", + "detailedForecast": "" + }, + { + "number": 15, + "name": "", + "startTime": "2026-10-02T08:00:00-04:00", + "endTime": "2026-10-02T09:00:00-04:00", + "isDaytime": true, + "temperature": 83, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 27 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 25.555555555555557 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 85 + }, + "windSpeed": "17 mph", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/day/tsra_sct,30?size=small", + "shortForecast": "Chance Showers And Thunderstorms", + "detailedForecast": "" + }, + { + "number": 16, + "name": "", + "startTime": "2026-10-02T09:00:00-04:00", + "endTime": "2026-10-02T10:00:00-04:00", + "isDaytime": true, + "temperature": 84, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 22 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 26.11111111111111 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 85 + }, + "windSpeed": "17 mph", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/day/tsra_hi,20?size=small", + "shortForecast": "Slight Chance Showers And Thunderstorms", + "detailedForecast": "" + }, + { + "number": 17, + "name": "", + "startTime": "2026-10-02T10:00:00-04:00", + "endTime": "2026-10-02T11:00:00-04:00", + "isDaytime": true, + "temperature": 84, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 21 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 26.666666666666668 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 88 + }, + "windSpeed": "17 mph", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/day/tsra_sct,20?size=small", + "shortForecast": "Slight Chance Showers And Thunderstorms", + "detailedForecast": "" + }, + { + "number": 18, + "name": "", + "startTime": "2026-10-02T11:00:00-04:00", + "endTime": "2026-10-02T12:00:00-04:00", + "isDaytime": true, + "temperature": 84, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 22 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 26.666666666666668 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 88 + }, + "windSpeed": "16 mph", + "windDirection": "SE", + "icon": "https://api.weather.gov/icons/land/day/tsra_sct,20?size=small", + "shortForecast": "Slight Chance Showers And Thunderstorms", + "detailedForecast": "" + }, + { + "number": 19, + "name": "", + "startTime": "2026-10-02T12:00:00-04:00", + "endTime": "2026-10-02T13:00:00-04:00", + "isDaytime": true, + "temperature": 85, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 20 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 27.22222222222222 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 88 + }, + "windSpeed": "15 mph", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/day/tsra_hi,20?size=small", + "shortForecast": "Slight Chance Showers And Thunderstorms", + "detailedForecast": "" + }, + { + "number": 20, + "name": "", + "startTime": "2026-10-02T13:00:00-04:00", + "endTime": "2026-10-02T14:00:00-04:00", + "isDaytime": true, + "temperature": 86, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 25 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 27.22222222222222 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 85 + }, + "windSpeed": "16 mph", + "windDirection": "SE", + "icon": "https://api.weather.gov/icons/land/day/tsra_sct,30?size=small", + "shortForecast": "Chance Showers And Thunderstorms", + "detailedForecast": "" + }, + { + "number": 21, + "name": "", + "startTime": "2026-10-02T14:00:00-04:00", + "endTime": "2026-10-02T15:00:00-04:00", + "isDaytime": true, + "temperature": 86, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 28 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 27.22222222222222 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 85 + }, + "windSpeed": "15 mph", + "windDirection": "SE", + "icon": "https://api.weather.gov/icons/land/day/tsra_sct,30?size=small", + "shortForecast": "Chance Showers And Thunderstorms", + "detailedForecast": "" + }, + { + "number": 22, + "name": "", + "startTime": "2026-10-02T15:00:00-04:00", + "endTime": "2026-10-02T16:00:00-04:00", + "isDaytime": true, + "temperature": 87, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 30 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 27.22222222222222 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 82 + }, + "windSpeed": "15 mph", + "windDirection": "SE", + "icon": "https://api.weather.gov/icons/land/day/tsra_sct,30?size=small", + "shortForecast": "Chance Showers And Thunderstorms", + "detailedForecast": "" + }, + { + "number": 23, + "name": "", + "startTime": "2026-10-02T16:00:00-04:00", + "endTime": "2026-10-02T17:00:00-04:00", + "isDaytime": true, + "temperature": 86, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 33 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 27.22222222222222 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 85 + }, + "windSpeed": "14 mph", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/day/tsra_sct,30?size=small", + "shortForecast": "Chance Showers And Thunderstorms", + "detailedForecast": "" + }, + { + "number": 24, + "name": "", + "startTime": "2026-10-02T17:00:00-04:00", + "endTime": "2026-10-02T18:00:00-04:00", + "isDaytime": true, + "temperature": 85, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 33 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 26.666666666666668 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 85 + }, + "windSpeed": "14 mph", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/day/tsra_sct,30?size=small", + "shortForecast": "Chance Showers And Thunderstorms", + "detailedForecast": "" + }, + { + "number": 25, + "name": "", + "startTime": "2026-10-02T18:00:00-04:00", + "endTime": "2026-10-02T19:00:00-04:00", + "isDaytime": false, + "temperature": 85, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 30 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 26.666666666666668 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 85 + }, + "windSpeed": "13 mph", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/night/tsra_sct,30?size=small", + "shortForecast": "Chance Showers And Thunderstorms", + "detailedForecast": "" + }, + { + "number": 26, + "name": "", + "startTime": "2026-10-02T19:00:00-04:00", + "endTime": "2026-10-02T20:00:00-04:00", + "isDaytime": false, + "temperature": 83, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 33 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 26.11111111111111 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 88 + }, + "windSpeed": "13 mph", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/night/tsra_sct,30?size=small", + "shortForecast": "Chance Showers And Thunderstorms", + "detailedForecast": "" + }, + { + "number": 27, + "name": "", + "startTime": "2026-10-02T20:00:00-04:00", + "endTime": "2026-10-02T21:00:00-04:00", + "isDaytime": false, + "temperature": 84, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 36 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 26.11111111111111 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 85 + }, + "windSpeed": "13 mph", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/night/tsra_sct,40?size=small", + "shortForecast": "Chance Showers And Thunderstorms", + "detailedForecast": "" + }, + { + "number": 28, + "name": "", + "startTime": "2026-10-02T21:00:00-04:00", + "endTime": "2026-10-02T22:00:00-04:00", + "isDaytime": false, + "temperature": 83, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 40 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 26.11111111111111 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 88 + }, + "windSpeed": "14 mph", + "windDirection": "SE", + "icon": "https://api.weather.gov/icons/land/night/tsra_hi,40?size=small", + "shortForecast": "Chance Showers And Thunderstorms", + "detailedForecast": "" + }, + { + "number": 29, + "name": "", + "startTime": "2026-10-02T22:00:00-04:00", + "endTime": "2026-10-02T23:00:00-04:00", + "isDaytime": false, + "temperature": 83, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 45 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 26.11111111111111 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 88 + }, + "windSpeed": "14 mph", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/night/tsra_hi,50?size=small", + "shortForecast": "Chance Showers And Thunderstorms", + "detailedForecast": "" + }, + { + "number": 30, + "name": "", + "startTime": "2026-10-02T23:00:00-04:00", + "endTime": "2026-10-03T00:00:00-04:00", + "isDaytime": false, + "temperature": 83, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 34 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 26.11111111111111 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 88 + }, + "windSpeed": "15 mph", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/night/tsra_hi,30?size=small", + "shortForecast": "Chance Showers And Thunderstorms", + "detailedForecast": "" + }, + { + "number": 31, + "name": "", + "startTime": "2026-10-03T00:00:00-04:00", + "endTime": "2026-10-03T01:00:00-04:00", + "isDaytime": false, + "temperature": 83, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 31 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 26.11111111111111 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 88 + }, + "windSpeed": "15 mph", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/night/tsra_hi,30?size=small", + "shortForecast": "Chance Showers And Thunderstorms", + "detailedForecast": "" + }, + { + "number": 32, + "name": "", + "startTime": "2026-10-03T01:00:00-04:00", + "endTime": "2026-10-03T02:00:00-04:00", + "isDaytime": false, + "temperature": 83, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 25 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 26.11111111111111 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 88 + }, + "windSpeed": "15 mph", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/night/tsra_hi,30?size=small", + "shortForecast": "Chance Showers And Thunderstorms", + "detailedForecast": "" + }, + { + "number": 33, + "name": "", + "startTime": "2026-10-03T02:00:00-04:00", + "endTime": "2026-10-03T03:00:00-04:00", + "isDaytime": false, + "temperature": 83, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 23 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 26.11111111111111 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 88 + }, + "windSpeed": "14 mph", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/night/tsra_hi,20?size=small", + "shortForecast": "Slight Chance Showers And Thunderstorms", + "detailedForecast": "" + }, + { + "number": 34, + "name": "", + "startTime": "2026-10-03T03:00:00-04:00", + "endTime": "2026-10-03T04:00:00-04:00", + "isDaytime": false, + "temperature": 83, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 30 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 26.11111111111111 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 88 + }, + "windSpeed": "15 mph", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/night/tsra_hi,30?size=small", + "shortForecast": "Chance Showers And Thunderstorms", + "detailedForecast": "" + }, + { + "number": 35, + "name": "", + "startTime": "2026-10-03T04:00:00-04:00", + "endTime": "2026-10-03T05:00:00-04:00", + "isDaytime": false, + "temperature": 83, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 37 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 25.555555555555557 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 85 + }, + "windSpeed": "15 mph", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/night/tsra_hi,40?size=small", + "shortForecast": "Chance Showers And Thunderstorms", + "detailedForecast": "" + }, + { + "number": 36, + "name": "", + "startTime": "2026-10-03T05:00:00-04:00", + "endTime": "2026-10-03T06:00:00-04:00", + "isDaytime": false, + "temperature": 83, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 40 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 25.555555555555557 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 85 + }, + "windSpeed": "15 mph", + "windDirection": "E", + "icon": "https://api.weather.gov/icons/land/night/tsra_hi,40?size=small", + "shortForecast": "Chance Showers And Thunderstorms", + "detailedForecast": "" + } + ] + } + } +} \ No newline at end of file diff --git a/tests/fixtures/noaa/seattle.json b/tests/fixtures/noaa/seattle.json new file mode 100644 index 0000000..3ae3487 --- /dev/null +++ b/tests/fixtures/noaa/seattle.json @@ -0,0 +1,1546 @@ +{ + "points_url": "https://api.weather.gov/points/47.6062,-122.3321", + "points": { + "id": "https://api.weather.gov/points/47.6062,-122.3321", + "type": "Feature", + "properties": { + "@id": "https://api.weather.gov/points/47.6062,-122.3321", + "@type": "wx:Point", + "cwa": "SEW", + "type": "land", + "forecastOffice": "https://api.weather.gov/offices/SEW", + "gridId": "SEW", + "gridX": 125, + "gridY": 68, + "forecast": "https://api.weather.gov/gridpoints/SEW/125,68/forecast", + "forecastHourly": "https://api.weather.gov/gridpoints/SEW/125,68/forecast/hourly", + "forecastGridData": "https://api.weather.gov/gridpoints/SEW/125,68", + "observationStations": "https://api.weather.gov/gridpoints/SEW/125,68/stations", + "timeZone": "America/Los_Angeles", + "radarStation": "KATX", + "astronomicalData": { + "sunrise": "2026-10-01T07:08:53-07:00", + "sunset": "2026-10-01T18:48:50-07:00", + "transit": "2026-10-01T12:58:52-07:00", + "civilTwilightBegin": "2026-10-01T06:38:19-07:00", + "civilTwilightEnd": "2026-10-01T19:19:25-07:00", + "nauticalTwilightBegin": "2026-10-01T06:02:34-07:00", + "nauticalTwilightEnd": "2026-10-01T19:55:09-07:00", + "astronomicalTwilightBegin": "2026-10-01T05:26:12-07:00", + "astronomicalTwilightEnd": "2026-10-01T20:31:32-07:00" + }, + "nwr": { + "transmitter": "KHB60", + "sameCode": "053033", + "areaBroadcast": "https://api.weather.gov/radio/KHB60/broadcast", + "pointBroadcast": "https://api.weather.gov/points/47.6062,-122.3321/radio" + } + } + }, + "forecast_url": "https://api.weather.gov/gridpoints/SEW/125,68/forecast", + "forecast": { + "type": "Feature", + "properties": { + "units": "us", + "forecastGenerator": "BaselineForecastGenerator", + "generatedAt": "2026-10-01T20:32:30+00:00", + "updateTime": "2026-10-01T20:20:49+00:00", + "validTimes": "2026-10-01T14:00:00+00:00/P7DT11H", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 73.152 + }, + "periods": [ + { + "number": 1, + "name": "This Afternoon", + "startTime": "2026-10-01T13:00:00-07:00", + "endTime": "2026-10-01T18:00:00-07:00", + "isDaytime": true, + "temperature": 66, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 3 + }, + "windSpeed": "2 mph", + "windDirection": "WNW", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=medium", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "Mostly cloudy, with a high near 66. West northwest wind around 2 mph." + }, + { + "number": 2, + "name": "Tonight", + "startTime": "2026-10-01T18:00:00-07:00", + "endTime": "2026-10-02T06:00:00-07:00", + "isDaytime": false, + "temperature": 53, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 4 + }, + "windSpeed": "2 mph", + "windDirection": "WNW", + "icon": "https://api.weather.gov/icons/land/night/sct?size=medium", + "shortForecast": "Partly Cloudy", + "detailedForecast": "Partly cloudy, with a low around 53. West northwest wind around 2 mph." + }, + { + "number": 3, + "name": "Friday", + "startTime": "2026-10-02T06:00:00-07:00", + "endTime": "2026-10-02T18:00:00-07:00", + "isDaytime": true, + "temperature": 70, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 5 + }, + "windSpeed": "1 to 5 mph", + "windDirection": "SSW", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=medium", + "shortForecast": "Partly Sunny", + "detailedForecast": "Partly sunny, with a high near 70. South southwest wind 1 to 5 mph." + }, + { + "number": 4, + "name": "Friday Night", + "startTime": "2026-10-02T18:00:00-07:00", + "endTime": "2026-10-03T06:00:00-07:00", + "isDaytime": false, + "temperature": 54, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "windSpeed": "5 mph", + "windDirection": "NNW", + "icon": "https://api.weather.gov/icons/land/night/bkn?size=medium", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "Mostly cloudy, with a low around 54. North northwest wind around 5 mph." + }, + { + "number": 5, + "name": "Saturday", + "startTime": "2026-10-03T06:00:00-07:00", + "endTime": "2026-10-03T18:00:00-07:00", + "isDaytime": true, + "temperature": 67, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "windSpeed": "5 to 8 mph", + "windDirection": "N", + "icon": "https://api.weather.gov/icons/land/day/sct?size=medium", + "shortForecast": "Mostly Sunny", + "detailedForecast": "Mostly sunny, with a high near 67. North wind 5 to 8 mph." + }, + { + "number": 6, + "name": "Saturday Night", + "startTime": "2026-10-03T18:00:00-07:00", + "endTime": "2026-10-04T06:00:00-07:00", + "isDaytime": false, + "temperature": 53, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "windSpeed": "3 to 7 mph", + "windDirection": "N", + "icon": "https://api.weather.gov/icons/land/night/few?size=medium", + "shortForecast": "Mostly Clear", + "detailedForecast": "Mostly clear, with a low around 53." + }, + { + "number": 7, + "name": "Sunday", + "startTime": "2026-10-04T06:00:00-07:00", + "endTime": "2026-10-04T18:00:00-07:00", + "isDaytime": true, + "temperature": 70, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "windSpeed": "5 mph", + "windDirection": "N", + "icon": "https://api.weather.gov/icons/land/day/sct?size=medium", + "shortForecast": "Mostly Sunny", + "detailedForecast": "Mostly sunny, with a high near 70." + }, + { + "number": 8, + "name": "Sunday Night", + "startTime": "2026-10-04T18:00:00-07:00", + "endTime": "2026-10-05T06:00:00-07:00", + "isDaytime": false, + "temperature": 54, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "windSpeed": "3 mph", + "windDirection": "NNE", + "icon": "https://api.weather.gov/icons/land/night/sct?size=medium", + "shortForecast": "Partly Cloudy", + "detailedForecast": "Partly cloudy, with a low around 54." + }, + { + "number": 9, + "name": "Monday", + "startTime": "2026-10-05T06:00:00-07:00", + "endTime": "2026-10-05T18:00:00-07:00", + "isDaytime": true, + "temperature": 68, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 2 + }, + "windSpeed": "2 mph", + "windDirection": "WSW", + "icon": "https://api.weather.gov/icons/land/day/sct?size=medium", + "shortForecast": "Mostly Sunny", + "detailedForecast": "Mostly sunny, with a high near 68." + }, + { + "number": 10, + "name": "Monday Night", + "startTime": "2026-10-05T18:00:00-07:00", + "endTime": "2026-10-06T06:00:00-07:00", + "isDaytime": false, + "temperature": 55, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 5 + }, + "windSpeed": "2 mph", + "windDirection": "NNE", + "icon": "https://api.weather.gov/icons/land/night/sct?size=medium", + "shortForecast": "Partly Cloudy", + "detailedForecast": "Partly cloudy, with a low around 55." + }, + { + "number": 11, + "name": "Tuesday", + "startTime": "2026-10-06T06:00:00-07:00", + "endTime": "2026-10-06T18:00:00-07:00", + "isDaytime": true, + "temperature": 64, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 2 + }, + "windSpeed": "5 mph", + "windDirection": "NNE", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=medium", + "shortForecast": "Partly Sunny", + "detailedForecast": "Partly sunny, with a high near 64." + }, + { + "number": 12, + "name": "Tuesday Night", + "startTime": "2026-10-06T18:00:00-07:00", + "endTime": "2026-10-07T06:00:00-07:00", + "isDaytime": false, + "temperature": 52, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 1 + }, + "windSpeed": "5 mph", + "windDirection": "N", + "icon": "https://api.weather.gov/icons/land/night/bkn?size=medium", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "Mostly cloudy, with a low around 52." + }, + { + "number": 13, + "name": "Wednesday", + "startTime": "2026-10-07T06:00:00-07:00", + "endTime": "2026-10-07T18:00:00-07:00", + "isDaytime": true, + "temperature": 65, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 1 + }, + "windSpeed": "2 to 6 mph", + "windDirection": "N", + "icon": "https://api.weather.gov/icons/land/day/sct?size=medium", + "shortForecast": "Mostly Sunny", + "detailedForecast": "Mostly sunny, with a high near 65." + }, + { + "number": 14, + "name": "Wednesday Night", + "startTime": "2026-10-07T18:00:00-07:00", + "endTime": "2026-10-08T06:00:00-07:00", + "isDaytime": false, + "temperature": 52, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 1 + }, + "windSpeed": "5 mph", + "windDirection": "NNE", + "icon": "https://api.weather.gov/icons/land/night/sct?size=medium", + "shortForecast": "Partly Cloudy", + "detailedForecast": "Partly cloudy, with a low around 52." + } + ] + } + }, + "stations_url": "https://api.weather.gov/gridpoints/SEW/125,68/stations", + "stations": { + "type": "FeatureCollection", + "features": [ + { + "id": "https://api.weather.gov/stations/KBFI", + "type": "Feature", + "properties": { + "@id": "https://api.weather.gov/stations/KBFI", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 6.096 + }, + "stationIdentifier": "KBFI", + "name": "Boeing Field - King County International Airport", + "timeZone": "America/Los_Angeles", + "provider": "ASOS-HFM", + "subProvider": "", + "distance": { + "unitCode": "wmoUnit:m", + "value": 6941.0159666151 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 176 + }, + "forecast": "https://api.weather.gov/zones/forecast/WAZ315" + } + }, + { + "id": "https://api.weather.gov/stations/SEAW1", + "type": "Feature", + "properties": { + "@id": "https://api.weather.gov/stations/SEAW1", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 8.8392 + }, + "stationIdentifier": "SEAW1", + "name": "SEATTLE WEATHER FORECAST OFFICE", + "timeZone": "America/Los_Angeles", + "provider": "HADS", + "subProvider": "", + "distance": { + "unitCode": "wmoUnit:m", + "value": 10042.843783477 + }, + "bearing": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 30 + }, + "forecast": "https://api.weather.gov/zones/forecast/WAZ315" + } + } + ], + "observationStations": [ + "https://api.weather.gov/stations/KBFI", + "https://api.weather.gov/stations/SEAW1", + "https://api.weather.gov/stations/KRNT", + "https://api.weather.gov/stations/T144T", + "https://api.weather.gov/stations/E0123", + "https://api.weather.gov/stations/KSEA", + "https://api.weather.gov/stations/D2607", + "https://api.weather.gov/stations/E6690", + "https://api.weather.gov/stations/KPWT", + "https://api.weather.gov/stations/KPAE", + "https://api.weather.gov/stations/C8405", + "https://api.weather.gov/stations/C5456", + "https://api.weather.gov/stations/D2629", + "https://api.weather.gov/stations/D4827", + "https://api.weather.gov/stations/KTIW", + "https://api.weather.gov/stations/ENCW1", + "https://api.weather.gov/stations/FTAW1", + "https://api.weather.gov/stations/KTCM", + "https://api.weather.gov/stations/KPLU", + "https://api.weather.gov/stations/K0S9", + "https://api.weather.gov/stations/KAWO", + "https://api.weather.gov/stations/C1035", + "https://api.weather.gov/stations/SWYW1", + "https://api.weather.gov/stations/JEFW1", + "https://api.weather.gov/stations/TDIAM", + "https://api.weather.gov/stations/C5398", + "https://api.weather.gov/stations/BUSW1", + "https://api.weather.gov/stations/TALPE", + "https://api.weather.gov/stations/KSHN", + "https://api.weather.gov/stations/SKKW1", + "https://api.weather.gov/stations/KOLM", + "https://api.weather.gov/stations/TCAND", + "https://api.weather.gov/stations/KNUW", + "https://api.weather.gov/stations/BKKW1", + "https://api.weather.gov/stations/TSEIB", + "https://api.weather.gov/stations/WHSW1", + "https://api.weather.gov/stations/D0126", + "https://api.weather.gov/stations/FIFW1", + "https://api.weather.gov/stations/ASHW1", + "https://api.weather.gov/stations/KBVS", + "https://api.weather.gov/stations/HUR53", + "https://api.weather.gov/stations/C2882", + "https://api.weather.gov/stations/KCLM", + "https://api.weather.gov/stations/HUFW1", + "https://api.weather.gov/stations/D8787", + "https://api.weather.gov/stations/KFHR", + "https://api.weather.gov/stations/MIPW1", + "https://api.weather.gov/stations/KCLS", + "https://api.weather.gov/stations/CLSW1", + "https://api.weather.gov/stations/ELSW1", + "https://api.weather.gov/stations/OLFW1", + "https://api.weather.gov/stations/TWHIT", + "https://api.weather.gov/stations/KORS", + "https://api.weather.gov/stations/TOFW1", + "https://api.weather.gov/stations/D3348", + "https://api.weather.gov/stations/KBLI", + "https://api.weather.gov/stations/BKBW1", + "https://api.weather.gov/stations/MRTW1", + "https://api.weather.gov/stations/MNOW1", + "https://api.weather.gov/stations/THECK", + "https://api.weather.gov/stations/KHQM", + "https://api.weather.gov/stations/C3375", + "https://api.weather.gov/stations/E1976", + "https://api.weather.gov/stations/CTKW1", + "https://api.weather.gov/stations/KCFW1", + "https://api.weather.gov/stations/TGREN", + "https://api.weather.gov/stations/TQUEE", + "https://api.weather.gov/stations/D0707", + "https://api.weather.gov/stations/TBURN", + "https://api.weather.gov/stations/EMTW1", + "https://api.weather.gov/stations/FRKW1", + "https://api.weather.gov/stations/KUIL", + "https://api.weather.gov/stations/HZCW1" + ], + "pagination": { + "next": "https://api.weather.gov/stations?id%5B0%5D=ASHW1&id%5B1%5D=BAK42&id%5B2%5D=BKBW1&id%5B3%5D=BKKW1&id%5B4%5D=BUSW1&id%5B5%5D=C1035&id%5B6%5D=C2882&id%5B7%5D=C3375&id%5B8%5D=C5398&id%5B9%5D=C5456&id%5B10%5D=C8405&id%5B11%5D=CLSW1&id%5B12%5D=CTKW1&id%5B13%5D=CYVR&id%5B14%5D=CYXX&id%5B15%5D=D0126&id%5B16%5D=D0707&id%5B17%5D=D2607&id%5B18%5D=D2629&id%5B19%5D=D3348&id%5B20%5D=D3625&id%5B21%5D=D4249&id%5B22%5D=D4827&id%5B23%5D=D8787&id%5B24%5D=D9771&id%5B25%5D=DGSWA&id%5B26%5D=E0123&id%5B27%5D=E1976&id%5B28%5D=E2824&id%5B29%5D=E4160&id%5B30%5D=E4667&id%5B31%5D=E5131&id%5B32%5D=E6690&id%5B33%5D=ELSW1&id%5B34%5D=EMTW1&id%5B35%5D=ENCW1&id%5B36%5D=F0240&id%5B37%5D=F4694&id%5B38%5D=FIFW1&id%5B39%5D=FRKW1&id%5B40%5D=FTAW1&id%5B41%5D=HUFW1&id%5B42%5D=HUR53&id%5B43%5D=HZCW1&id%5B44%5D=JEFW1&id%5B45%5D=K0S9&id%5B46%5D=KAWO&id%5B47%5D=KBFI&id%5B48%5D=KBLI&id%5B49%5D=KBVS&id%5B50%5D=KCFW1&id%5B51%5D=KCLM&id%5B52%5D=KCLS&id%5B53%5D=KFHR&id%5B54%5D=KHQM&id%5B55%5D=KNUW&id%5B56%5D=KOLM&id%5B57%5D=KORS&id%5B58%5D=KPAE&id%5B59%5D=KPLU&id%5B60%5D=KPWT&id%5B61%5D=KRNT&id%5B62%5D=KSEA&id%5B63%5D=KSHN&id%5B64%5D=KTCM&id%5B65%5D=KTIW&id%5B66%5D=KUIL&id%5B67%5D=MIPW1&id%5B68%5D=MNOW1&id%5B69%5D=MRTW1&id%5B70%5D=OLFW1&id%5B71%5D=PVC55&id%5B72%5D=SEAW1&id%5B73%5D=SKKW1&id%5B74%5D=SWYW1&id%5B75%5D=T144T&id%5B76%5D=TALPE&id%5B77%5D=TBURN&id%5B78%5D=TCAND&id%5B79%5D=TDIAM&id%5B80%5D=TGREN&id%5B81%5D=THECK&id%5B82%5D=TOFW1&id%5B83%5D=TQUEE&id%5B84%5D=TSEIB&id%5B85%5D=TWHIT&id%5B86%5D=W7YED&id%5B87%5D=WHSW1&cursor=eyJzIjo1MDB9" + } + }, + "observation_url": "https://api.weather.gov/stations/KBFI/observations/latest", + "observation": { + "id": "https://api.weather.gov/stations/KBFI/observations/2026-10-01T22:30:00+00:00", + "type": "Feature", + "properties": { + "@id": "https://api.weather.gov/stations/KBFI/observations/2026-10-01T22:30:00+00:00", + "@type": "wx:ObservationStation", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 5 + }, + "station": "https://api.weather.gov/stations/KBFI", + "stationId": "KBFI", + "stationName": "Boeing Field - King County International Airport", + "timestamp": "2026-10-01T22:30:00+00:00", + "rawMessage": "", + "textDescription": "Clear", + "icon": "https://api.weather.gov/icons/land/day/skc?size=medium", + "presentWeather": [], + "temperature": { + "unitCode": "wmoUnit:degC", + "value": 19, + "qualityControl": "V" + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 9, + "qualityControl": "V" + }, + "windDirection": { + "unitCode": "wmoUnit:degree_(angle)", + "value": 300, + "qualityControl": "V" + }, + "windSpeed": { + "unitCode": "wmoUnit:km_h-1", + "value": 7.416, + "qualityControl": "V" + }, + "windGust": { + "unitCode": "wmoUnit:km_h-1", + "value": null, + "qualityControl": "Z" + }, + "barometricPressure": { + "unitCode": "wmoUnit:Pa", + "value": 101659.39, + "qualityControl": "V" + }, + "seaLevelPressure": { + "unitCode": "wmoUnit:Pa", + "value": null, + "qualityControl": "Z" + }, + "visibility": { + "unitCode": "wmoUnit:m", + "value": 16093.44, + "qualityControl": "C" + }, + "maxTemperatureLast24Hours": { + "unitCode": "wmoUnit:degC", + "value": null + }, + "minTemperatureLast24Hours": { + "unitCode": "wmoUnit:degC", + "value": null + }, + "precipitationLast3Hours": { + "unitCode": "wmoUnit:mm", + "value": null, + "qualityControl": "Z" + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 52.278271459276, + "qualityControl": "V" + }, + "windChill": { + "unitCode": "wmoUnit:degC", + "value": null, + "qualityControl": "V" + }, + "heatIndex": { + "unitCode": "wmoUnit:degC", + "value": null, + "qualityControl": "V" + }, + "cloudLayers": [ + { + "base": { + "unitCode": "wmoUnit:m", + "value": 3810 + }, + "amount": "CLR" + } + ] + } + }, + "hourly_url": "https://api.weather.gov/gridpoints/SEW/125,68/forecast/hourly", + "hourly": { + "type": "Feature", + "properties": { + "units": "us", + "forecastGenerator": "HourlyForecastGenerator", + "generatedAt": "2026-10-01T22:07:01+00:00", + "updateTime": "2026-10-01T20:20:49+00:00", + "validTimes": "2026-10-01T14:00:00+00:00/P7DT11H", + "elevation": { + "unitCode": "wmoUnit:m", + "value": 73.152 + }, + "periods": [ + { + "number": 1, + "name": "", + "startTime": "2026-10-01T15:00:00-07:00", + "endTime": "2026-10-01T16:00:00-07:00", + "isDaytime": true, + "temperature": 65, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 3 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 12.222222222222221 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 67 + }, + "windSpeed": "2 mph", + "windDirection": "WNW", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + }, + { + "number": 2, + "name": "", + "startTime": "2026-10-01T16:00:00-07:00", + "endTime": "2026-10-01T17:00:00-07:00", + "isDaytime": true, + "temperature": 65, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 3 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 12.222222222222221 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 67 + }, + "windSpeed": "2 mph", + "windDirection": "WNW", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + }, + { + "number": 3, + "name": "", + "startTime": "2026-10-01T17:00:00-07:00", + "endTime": "2026-10-01T18:00:00-07:00", + "isDaytime": true, + "temperature": 66, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 3 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 12.777777777777779 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 67 + }, + "windSpeed": "2 mph", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + }, + { + "number": 4, + "name": "", + "startTime": "2026-10-01T18:00:00-07:00", + "endTime": "2026-10-01T19:00:00-07:00", + "isDaytime": false, + "temperature": 64, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 3 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 12.222222222222221 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 69 + }, + "windSpeed": "2 mph", + "windDirection": "NNW", + "icon": "https://api.weather.gov/icons/land/night/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + }, + { + "number": 5, + "name": "", + "startTime": "2026-10-01T19:00:00-07:00", + "endTime": "2026-10-01T20:00:00-07:00", + "isDaytime": false, + "temperature": 63, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 3 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 12.777777777777779 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 74 + }, + "windSpeed": "2 mph", + "windDirection": "NW", + "icon": "https://api.weather.gov/icons/land/night/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + }, + { + "number": 6, + "name": "", + "startTime": "2026-10-01T20:00:00-07:00", + "endTime": "2026-10-01T21:00:00-07:00", + "isDaytime": false, + "temperature": 61, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 3 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 11.666666666666666 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 75 + }, + "windSpeed": "2 mph", + "windDirection": "NNW", + "icon": "https://api.weather.gov/icons/land/night/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + }, + { + "number": 7, + "name": "", + "startTime": "2026-10-01T21:00:00-07:00", + "endTime": "2026-10-01T22:00:00-07:00", + "isDaytime": false, + "temperature": 59, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 4 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 11.11111111111111 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 77 + }, + "windSpeed": "2 mph", + "windDirection": "N", + "icon": "https://api.weather.gov/icons/land/night/sct?size=small", + "shortForecast": "Partly Cloudy", + "detailedForecast": "" + }, + { + "number": 8, + "name": "", + "startTime": "2026-10-01T22:00:00-07:00", + "endTime": "2026-10-01T23:00:00-07:00", + "isDaytime": false, + "temperature": 58, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 4 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 11.11111111111111 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 80 + }, + "windSpeed": "2 mph", + "windDirection": "NNE", + "icon": "https://api.weather.gov/icons/land/night/sct?size=small", + "shortForecast": "Partly Cloudy", + "detailedForecast": "" + }, + { + "number": 9, + "name": "", + "startTime": "2026-10-01T23:00:00-07:00", + "endTime": "2026-10-02T00:00:00-07:00", + "isDaytime": false, + "temperature": 58, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 3 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 11.666666666666666 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 82 + }, + "windSpeed": "2 mph", + "windDirection": "N", + "icon": "https://api.weather.gov/icons/land/night/sct?size=small", + "shortForecast": "Partly Cloudy", + "detailedForecast": "" + }, + { + "number": 10, + "name": "", + "startTime": "2026-10-02T00:00:00-07:00", + "endTime": "2026-10-02T01:00:00-07:00", + "isDaytime": false, + "temperature": 57, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 3 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 11.11111111111111 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 84 + }, + "windSpeed": "1 mph", + "windDirection": "WSW", + "icon": "https://api.weather.gov/icons/land/night/few?size=small", + "shortForecast": "Mostly Clear", + "detailedForecast": "" + }, + { + "number": 11, + "name": "", + "startTime": "2026-10-02T01:00:00-07:00", + "endTime": "2026-10-02T02:00:00-07:00", + "isDaytime": false, + "temperature": 56, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 2 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 11.11111111111111 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 86 + }, + "windSpeed": "1 mph", + "windDirection": "SSW", + "icon": "https://api.weather.gov/icons/land/night/few?size=small", + "shortForecast": "Mostly Clear", + "detailedForecast": "" + }, + { + "number": 12, + "name": "", + "startTime": "2026-10-02T02:00:00-07:00", + "endTime": "2026-10-02T03:00:00-07:00", + "isDaytime": false, + "temperature": 56, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 2 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 11.11111111111111 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 87 + }, + "windSpeed": "1 mph", + "windDirection": "SSW", + "icon": "https://api.weather.gov/icons/land/night/few?size=small", + "shortForecast": "Mostly Clear", + "detailedForecast": "" + }, + { + "number": 13, + "name": "", + "startTime": "2026-10-02T03:00:00-07:00", + "endTime": "2026-10-02T04:00:00-07:00", + "isDaytime": false, + "temperature": 55, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 3 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 10.555555555555555 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 87 + }, + "windSpeed": "1 mph", + "windDirection": "S", + "icon": "https://api.weather.gov/icons/land/night/few?size=small", + "shortForecast": "Mostly Clear", + "detailedForecast": "" + }, + { + "number": 14, + "name": "", + "startTime": "2026-10-02T04:00:00-07:00", + "endTime": "2026-10-02T05:00:00-07:00", + "isDaytime": false, + "temperature": 55, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 3 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 11.11111111111111 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 88 + }, + "windSpeed": "1 mph", + "windDirection": "S", + "icon": "https://api.weather.gov/icons/land/night/few?size=small", + "shortForecast": "Mostly Clear", + "detailedForecast": "" + }, + { + "number": 15, + "name": "", + "startTime": "2026-10-02T05:00:00-07:00", + "endTime": "2026-10-02T06:00:00-07:00", + "isDaytime": false, + "temperature": 54, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 4 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 10.555555555555555 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 89 + }, + "windSpeed": "1 mph", + "windDirection": "S", + "icon": "https://api.weather.gov/icons/land/night/sct?size=small", + "shortForecast": "Partly Cloudy", + "detailedForecast": "" + }, + { + "number": 16, + "name": "", + "startTime": "2026-10-02T06:00:00-07:00", + "endTime": "2026-10-02T07:00:00-07:00", + "isDaytime": true, + "temperature": 54, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 4 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 10.555555555555555 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 89 + }, + "windSpeed": "1 mph", + "windDirection": "S", + "icon": "https://api.weather.gov/icons/land/day/sct?size=small", + "shortForecast": "Mostly Sunny", + "detailedForecast": "" + }, + { + "number": 17, + "name": "", + "startTime": "2026-10-02T07:00:00-07:00", + "endTime": "2026-10-02T08:00:00-07:00", + "isDaytime": true, + "temperature": 53, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 4 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 10 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 90 + }, + "windSpeed": "2 mph", + "windDirection": "S", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + }, + { + "number": 18, + "name": "", + "startTime": "2026-10-02T08:00:00-07:00", + "endTime": "2026-10-02T09:00:00-07:00", + "isDaytime": true, + "temperature": 55, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 4 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 11.11111111111111 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 90 + }, + "windSpeed": "2 mph", + "windDirection": "S", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + }, + { + "number": 19, + "name": "", + "startTime": "2026-10-02T09:00:00-07:00", + "endTime": "2026-10-02T10:00:00-07:00", + "isDaytime": true, + "temperature": 56, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 4 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 11.11111111111111 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 88 + }, + "windSpeed": "2 mph", + "windDirection": "S", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=small", + "shortForecast": "Partly Sunny", + "detailedForecast": "" + }, + { + "number": 20, + "name": "", + "startTime": "2026-10-02T10:00:00-07:00", + "endTime": "2026-10-02T11:00:00-07:00", + "isDaytime": true, + "temperature": 59, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 5 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 12.222222222222221 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 84 + }, + "windSpeed": "3 mph", + "windDirection": "S", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=small", + "shortForecast": "Partly Sunny", + "detailedForecast": "" + }, + { + "number": 21, + "name": "", + "startTime": "2026-10-02T11:00:00-07:00", + "endTime": "2026-10-02T12:00:00-07:00", + "isDaytime": true, + "temperature": 61, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 4 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 12.777777777777779 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 81 + }, + "windSpeed": "5 mph", + "windDirection": "S", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=small", + "shortForecast": "Partly Sunny", + "detailedForecast": "" + }, + { + "number": 22, + "name": "", + "startTime": "2026-10-02T12:00:00-07:00", + "endTime": "2026-10-02T13:00:00-07:00", + "isDaytime": true, + "temperature": 63, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 3 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 13.333333333333334 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 79 + }, + "windSpeed": "5 mph", + "windDirection": "SSW", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=small", + "shortForecast": "Partly Sunny", + "detailedForecast": "" + }, + { + "number": 23, + "name": "", + "startTime": "2026-10-02T13:00:00-07:00", + "endTime": "2026-10-02T14:00:00-07:00", + "isDaytime": true, + "temperature": 66, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 3 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 14.444444444444445 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 75 + }, + "windSpeed": "5 mph", + "windDirection": "SSW", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=small", + "shortForecast": "Partly Sunny", + "detailedForecast": "" + }, + { + "number": 24, + "name": "", + "startTime": "2026-10-02T14:00:00-07:00", + "endTime": "2026-10-02T15:00:00-07:00", + "isDaytime": true, + "temperature": 68, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 3 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 15 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 72 + }, + "windSpeed": "5 mph", + "windDirection": "SSW", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=small", + "shortForecast": "Partly Sunny", + "detailedForecast": "" + }, + { + "number": 25, + "name": "", + "startTime": "2026-10-02T15:00:00-07:00", + "endTime": "2026-10-02T16:00:00-07:00", + "isDaytime": true, + "temperature": 68, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 14.444444444444445 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 70 + }, + "windSpeed": "3 mph", + "windDirection": "SW", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=small", + "shortForecast": "Partly Sunny", + "detailedForecast": "" + }, + { + "number": 26, + "name": "", + "startTime": "2026-10-02T16:00:00-07:00", + "endTime": "2026-10-02T17:00:00-07:00", + "isDaytime": true, + "temperature": 69, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 1 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 14.444444444444445 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 69 + }, + "windSpeed": "3 mph", + "windDirection": "SW", + "icon": "https://api.weather.gov/icons/land/day/sct?size=small", + "shortForecast": "Mostly Sunny", + "detailedForecast": "" + }, + { + "number": 27, + "name": "", + "startTime": "2026-10-02T17:00:00-07:00", + "endTime": "2026-10-02T18:00:00-07:00", + "isDaytime": true, + "temperature": 69, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 15 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 70 + }, + "windSpeed": "2 mph", + "windDirection": "WNW", + "icon": "https://api.weather.gov/icons/land/day/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + }, + { + "number": 28, + "name": "", + "startTime": "2026-10-02T18:00:00-07:00", + "endTime": "2026-10-02T19:00:00-07:00", + "isDaytime": false, + "temperature": 68, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 14.444444444444445 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 71 + }, + "windSpeed": "2 mph", + "windDirection": "WNW", + "icon": "https://api.weather.gov/icons/land/night/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + }, + { + "number": 29, + "name": "", + "startTime": "2026-10-02T19:00:00-07:00", + "endTime": "2026-10-02T20:00:00-07:00", + "isDaytime": false, + "temperature": 66, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 14.444444444444445 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 76 + }, + "windSpeed": "2 mph", + "windDirection": "WNW", + "icon": "https://api.weather.gov/icons/land/night/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + }, + { + "number": 30, + "name": "", + "startTime": "2026-10-02T20:00:00-07:00", + "endTime": "2026-10-02T21:00:00-07:00", + "isDaytime": false, + "temperature": 63, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 13.88888888888889 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 80 + }, + "windSpeed": "3 mph", + "windDirection": "N", + "icon": "https://api.weather.gov/icons/land/night/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + }, + { + "number": 31, + "name": "", + "startTime": "2026-10-02T21:00:00-07:00", + "endTime": "2026-10-02T22:00:00-07:00", + "isDaytime": false, + "temperature": 61, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 12.777777777777779 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 82 + }, + "windSpeed": "3 mph", + "windDirection": "N", + "icon": "https://api.weather.gov/icons/land/night/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + }, + { + "number": 32, + "name": "", + "startTime": "2026-10-02T22:00:00-07:00", + "endTime": "2026-10-02T23:00:00-07:00", + "isDaytime": false, + "temperature": 60, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 12.777777777777779 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 84 + }, + "windSpeed": "3 mph", + "windDirection": "N", + "icon": "https://api.weather.gov/icons/land/night/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + }, + { + "number": 33, + "name": "", + "startTime": "2026-10-02T23:00:00-07:00", + "endTime": "2026-10-03T00:00:00-07:00", + "isDaytime": false, + "temperature": 59, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 12.777777777777779 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 85 + }, + "windSpeed": "3 mph", + "windDirection": "N", + "icon": "https://api.weather.gov/icons/land/night/sct?size=small", + "shortForecast": "Partly Cloudy", + "detailedForecast": "" + }, + { + "number": 34, + "name": "", + "startTime": "2026-10-03T00:00:00-07:00", + "endTime": "2026-10-03T01:00:00-07:00", + "isDaytime": false, + "temperature": 58, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 12.222222222222221 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 87 + }, + "windSpeed": "3 mph", + "windDirection": "N", + "icon": "https://api.weather.gov/icons/land/night/sct?size=small", + "shortForecast": "Partly Cloudy", + "detailedForecast": "" + }, + { + "number": 35, + "name": "", + "startTime": "2026-10-03T01:00:00-07:00", + "endTime": "2026-10-03T02:00:00-07:00", + "isDaytime": false, + "temperature": 57, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 12.222222222222221 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 89 + }, + "windSpeed": "3 mph", + "windDirection": "N", + "icon": "https://api.weather.gov/icons/land/night/sct?size=small", + "shortForecast": "Partly Cloudy", + "detailedForecast": "" + }, + { + "number": 36, + "name": "", + "startTime": "2026-10-03T02:00:00-07:00", + "endTime": "2026-10-03T03:00:00-07:00", + "isDaytime": false, + "temperature": 57, + "temperatureUnit": "F", + "temperatureTrend": null, + "probabilityOfPrecipitation": { + "unitCode": "wmoUnit:percent", + "value": 0 + }, + "dewpoint": { + "unitCode": "wmoUnit:degC", + "value": 12.222222222222221 + }, + "relativeHumidity": { + "unitCode": "wmoUnit:percent", + "value": 90 + }, + "windSpeed": "5 mph", + "windDirection": "N", + "icon": "https://api.weather.gov/icons/land/night/bkn?size=small", + "shortForecast": "Mostly Cloudy", + "detailedForecast": "" + } + ] + } + } +} \ No newline at end of file