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.
This commit is contained in:
agessaman committed 2026-10-01 15:48:56 -07:00
1 parent 03ba510b53
commit eb80c2b3b4
11 files changed
+4652

No files matched your search

@@ -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 <common.temp_low_label>: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 <common.temp_low_label>: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 <common.temp_high_label>: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 <common.temp_high_label>: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 <common.temp_high_label>:44°F 💨N5",
"drop3-obs0-len200": "Fri Night: ☀️Mostly Clear 29°F 💨NE5 | Sat: 🌦️Chance Rain And Snow <common.temp_high_label>: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 <common.temp_high_label>:44°F 💨N5",
"multiday3-drop0": "F: ☀️Patchy Freezing Fog th... <common.temp_high_label>:42°F\nSa: 🌦️Chance Rain And Snow <common.temp_high_label>:44°F\nSu: 🌦️Light Rain Likely <common.temp_high_label>:45°F",
"multiday3-drop1": "F: ☀️Patchy Freezing Fog th... <common.temp_high_label>:42°F\nSa: 🌦️Chance Rain And Snow <common.temp_high_label>:44°F\nSu: 🌦️Light Rain Likely <common.temp_high_label>:45°F",
"multiday3-drop2": "F: ☀️Patchy Freezing Fog th... <common.temp_high_label>:42°F\nSa: 🌦️Chance Rain And Snow <common.temp_high_label>:44°F\nSu: 🌦️Light Rain Likely <common.temp_high_label>:45°F",
"multiday3-drop3": "F: ☀️Mostly Clear <common.temp_low_label>:29°F\nSa: 🌦️Chance Rain And Snow <common.temp_high_label>:44°F\nSu: 🌦️Light Rain Likely <common.temp_high_label>:45°F",
"multiday5-drop0": "F: ☀️Patchy Freezing Fog th... <common.temp_high_label>:42°F\nSa: 🌦️Chance Rain And Snow <common.temp_high_label>:44°F\nSu: 🌦️Light Rain Likely <common.temp_high_label>:45°F\nM: 🌦️Light Rain Likely <common.temp_high_label>:49°F\nT: 🌦️Chance Light Rain <common.temp_high_label>:49°F",
"multiday5-drop1": "F: ☀️Patchy Freezing Fog th... <common.temp_high_label>:42°F\nSa: 🌦️Chance Rain And Snow <common.temp_high_label>:44°F\nSu: 🌦️Light Rain Likely <common.temp_high_label>:45°F\nM: 🌦️Light Rain Likely <common.temp_high_label>:49°F\nT: 🌦️Chance Light Rain <common.temp_high_label>:49°F",
"multiday5-drop2": "F: ☀️Patchy Freezing Fog th... <common.temp_high_label>:42°F\nSa: 🌦️Chance Rain And Snow <common.temp_high_label>:44°F\nSu: 🌦️Light Rain Likely <common.temp_high_label>:45°F\nM: 🌦️Light Rain Likely <common.temp_high_label>:49°F\nT: 🌦️Chance Light Rain <common.temp_high_label>:49°F",
"multiday5-drop3": "F: ☀️Mostly Clear <common.temp_low_label>:29°F\nSa: 🌦️Chance Rain And Snow <common.temp_high_label>:44°F\nSu: 🌦️Light Rain Likely <common.temp_high_label>:45°F\nM: 🌦️Light Rain Likely <common.temp_high_label>:49°F\nT: 🌦️Chance Light Rain <common.temp_high_label>:49°F",
"multiday7-drop0": "F: ☀️Patchy Freezing Fog th... <common.temp_high_label>:42°F\nSa: 🌦️Chance Rain And Snow <common.temp_high_label>:44°F\nSu: 🌦️Light Rain Likely <common.temp_high_label>:45°F\nM: 🌦️Light Rain Likely <common.temp_high_label>:49°F\nT: 🌦️Chance Light Rain <common.temp_high_label>:49°F\nW: 🌦️Chance Light Rain <common.temp_high_label>:47°F",
"multiday7-drop1": "F: ☀️Patchy Freezing Fog th... <common.temp_high_label>:42°F\nSa: 🌦️Chance Rain And Snow <common.temp_high_label>:44°F\nSu: 🌦️Light Rain Likely <common.temp_high_label>:45°F\nM: 🌦️Light Rain Likely <common.temp_high_label>:49°F\nT: 🌦️Chance Light Rain <common.temp_high_label>:49°F\nW: 🌦️Chance Light Rain <common.temp_high_label>:47°F",
"multiday7-drop2": "F: ☀️Patchy Freezing Fog th... <common.temp_high_label>:42°F\nSa: 🌦️Chance Rain And Snow <common.temp_high_label>:44°F\nSu: 🌦️Light Rain Likely <common.temp_high_label>:45°F\nM: 🌦️Light Rain Likely <common.temp_high_label>:49°F\nT: 🌦️Chance Light Rain <common.temp_high_label>:49°F\nW: 🌦️Chance Light Rain <common.temp_high_label>:47°F",
"multiday7-drop3": "F: ☀️Mostly Clear <common.temp_low_label>:29°F\nSa: 🌦️Chance Rain And Snow <common.temp_high_label>:44°F\nSu: 🌦️Light Rain Likely <common.temp_high_label>:45°F\nM: 🌦️Light Rain Likely <common.temp_high_label>:49°F\nT: 🌦️Chance Light Rain <common.temp_high_label>:49°F\nW: 🌦️Chance Light Rain <common.temp_high_label>:47°F",
"tomorrow-drop0": "Fri: ☀️Patchy Freezing Fog then Sunny <common.temp_high_label>:42°F 💨NE5 | Fri Night: ☀️Mostly Clear <common.temp_low_label>:29°F 💨NE5",
"tomorrow-drop1": "Fri: ☀️Patchy Freezing Fog then Sunny <common.temp_high_label>:42°F 💨NE5 | Fri Night: ☀️Mostly Clear <common.temp_low_label>:29°F 💨NE5",
"tomorrow-drop2": "Fri: ☀️Patchy Freezing Fog then Sunny <common.temp_high_label>:42°F 💨NE5 | Fri Night: ☀️Mostly Clear <common.temp_low_label>:29°F 💨NE5",
"tomorrow-drop3": "Fri Night: ☀️Mostly Clear <common.temp_low_label>:29°F 💨NE5"
}
@@ -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 <common.temp_low_label>:50°F 💨S3",
"drop0-obs0-len200": "This Afternoon: ☀️Sunny 72°F 💨E8 | Tonight: ☀️Mostly Clear <common.temp_low_label>: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 <common.temp_low_label>:50°F 💨S3",
"drop1-obs0-len130": "Tonight: ☀️Mostly Clear 50°F 💨S3 | Fri: ☀️Sunny <common.temp_high_label>:81°F 💨S2",
"drop1-obs0-len200": "Tonight: ☀️Mostly Clear 50°F 💨S3 | Fri: ☀️Sunny <common.temp_high_label>:81°F 💨S2 | Fri Night: ☀️Mostly Clear <common.temp_low_label>:53°F",
"drop1-obs1-len130": "Tonight: ☀️Mostly Clear 50°F 💨S3 28%RH 💧37° 👁️9mi 📊1024hPa | Fri: ☀️Sunny <common.temp_high_label>:81°F",
"drop1-obs1-len200": "Tonight: ☀️Mostly Clear 50°F 💨S3 28%RH 💧37° 👁️9mi 📊1024hPa | Fri: ☀️Sunny <common.temp_high_label>:81°F 💨S2 | Fri Night: ☀️Mostly Clear <common.temp_low_label>: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 <common.temp_high_label>:85°F 💨NN2",
"drop3-obs0-len200": "Fri Night: ☀️Mostly Clear 53°F 💨S5 | Sat: ☀️Sunny <common.temp_high_label>:85°F 💨NN2",
"drop3-obs1-len130": "Fri Night: ☀️Mostly Clear 53°F 💨S5 28%RH 💧37° 👁️9mi 📊1024hPa | Sat: ☀️Sunny <common.temp_high_label>:85°F",
"drop3-obs1-len200": "Fri Night: ☀️Mostly Clear 53°F 💨S5 28%RH 💧37° 👁️9mi 📊1024hPa | Sat: ☀️Sunny <common.temp_high_label>:85°F 💨NN2",
"multiday3-drop0": "F: ☀️Sunny <common.temp_high_label>:81°F\nSa: ☀️Sunny <common.temp_high_label>:85°F\nSu: ☀️Sunny <common.temp_high_label>:82°F",
"multiday3-drop1": "F: ☀️Sunny <common.temp_high_label>:81°F\nSa: ☀️Sunny <common.temp_high_label>:85°F\nSu: ☀️Sunny <common.temp_high_label>:82°F",
"multiday3-drop2": "F: ☀️Sunny <common.temp_high_label>:81°F\nSa: ☀️Sunny <common.temp_high_label>:85°F\nSu: ☀️Sunny <common.temp_high_label>:82°F",
"multiday3-drop3": "F: ☀️Mostly Clear <common.temp_low_label>:53°F\nSa: ☀️Sunny <common.temp_high_label>:85°F\nSu: ☀️Sunny <common.temp_high_label>:82°F",
"multiday5-drop0": "F: ☀️Sunny <common.temp_high_label>:81°F\nSa: ☀️Sunny <common.temp_high_label>:85°F\nSu: ☀️Sunny <common.temp_high_label>:82°F\nM: ☀️Sunny <common.temp_high_label>:87°F\nT: ☀️Mostly Sunny <common.temp_high_label>:84°F",
"multiday5-drop1": "F: ☀️Sunny <common.temp_high_label>:81°F\nSa: ☀️Sunny <common.temp_high_label>:85°F\nSu: ☀️Sunny <common.temp_high_label>:82°F\nM: ☀️Sunny <common.temp_high_label>:87°F\nT: ☀️Mostly Sunny <common.temp_high_label>:84°F",
"multiday5-drop2": "F: ☀️Sunny <common.temp_high_label>:81°F\nSa: ☀️Sunny <common.temp_high_label>:85°F\nSu: ☀️Sunny <common.temp_high_label>:82°F\nM: ☀️Sunny <common.temp_high_label>:87°F\nT: ☀️Mostly Sunny <common.temp_high_label>:84°F",
"multiday5-drop3": "F: ☀️Mostly Clear <common.temp_low_label>:53°F\nSa: ☀️Sunny <common.temp_high_label>:85°F\nSu: ☀️Sunny <common.temp_high_label>:82°F\nM: ☀️Sunny <common.temp_high_label>:87°F\nT: ☀️Mostly Sunny <common.temp_high_label>:84°F",
"multiday7-drop0": "F: ☀️Sunny <common.temp_high_label>:81°F\nSa: ☀️Sunny <common.temp_high_label>:85°F\nSu: ☀️Sunny <common.temp_high_label>:82°F\nM: ☀️Sunny <common.temp_high_label>:87°F\nT: ☀️Mostly Sunny <common.temp_high_label>:84°F\nW: ☀️Sunny <common.temp_high_label>:82°F",
"multiday7-drop1": "F: ☀️Sunny <common.temp_high_label>:81°F\nSa: ☀️Sunny <common.temp_high_label>:85°F\nSu: ☀️Sunny <common.temp_high_label>:82°F\nM: ☀️Sunny <common.temp_high_label>:87°F\nT: ☀️Mostly Sunny <common.temp_high_label>:84°F\nW: ☀️Sunny <common.temp_high_label>:82°F",
"multiday7-drop2": "F: ☀️Sunny <common.temp_high_label>:81°F\nSa: ☀️Sunny <common.temp_high_label>:85°F\nSu: ☀️Sunny <common.temp_high_label>:82°F\nM: ☀️Sunny <common.temp_high_label>:87°F\nT: ☀️Mostly Sunny <common.temp_high_label>:84°F\nW: ☀️Sunny <common.temp_high_label>:82°F",
"multiday7-drop3": "F: ☀️Mostly Clear <common.temp_low_label>:53°F\nSa: ☀️Sunny <common.temp_high_label>:85°F\nSu: ☀️Sunny <common.temp_high_label>:82°F\nM: ☀️Sunny <common.temp_high_label>:87°F\nT: ☀️Mostly Sunny <common.temp_high_label>:84°F\nW: ☀️Sunny <common.temp_high_label>:82°F",
"tomorrow-drop0": "Fri: ☀️Sunny <common.temp_high_label>:81°F 💨S2 | Fri Night: ☀️Mostly Clear <common.temp_low_label>:53°F 💨S5",
"tomorrow-drop1": "Fri: ☀️Sunny <common.temp_high_label>:81°F 💨S2 | Fri Night: ☀️Mostly Clear <common.temp_low_label>:53°F 💨S5",
"tomorrow-drop2": "Fri: ☀️Sunny <common.temp_high_label>:81°F 💨S2 | Fri Night: ☀️Mostly Clear <common.temp_low_label>:53°F 💨S5",
"tomorrow-drop3": "Fri Night: ☀️Mostly Clear <common.temp_low_label>:53°F 💨S5"
}
@@ -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"
}
@@ -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"
}
@@ -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 <common.temp_high_label>: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 <common.temp_high_label>: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 <common.temp_high_label>: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 <common.temp_high_label>: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 <common.temp_high_label>:88°F\nSa: 🌦️Chance shwrs And t-storms <common.temp_high_label>:88°F\nSu: ☀️Sunny then Slight Chan... <common.temp_high_label>:88°F",
"multiday3-drop1": "F: 🌦️Chance shwrs And t-storms <common.temp_high_label>:88°F\nSa: 🌦️Chance shwrs And t-storms <common.temp_high_label>:88°F\nSu: ☀️Sunny then Slight Chan... <common.temp_high_label>:88°F",
"multiday3-drop2": "F: 🌦️Chance shwrs And t-storms <common.temp_low_label>:81°F\nSa: 🌦️Chance shwrs And t-storms <common.temp_high_label>:88°F\nSu: ☀️Sunny then Slight Chan... <common.temp_high_label>:88°F",
"multiday3-drop3": "Sa: 🌦️Chance shwrs And t-storms <common.temp_high_label>:88°F\nSu: ☀️Sunny then Slight Chan... <common.temp_high_label>:88°F\nM: ☀️Mostly Sunny then Chan... <common.temp_high_label>:89°F",
"multiday5-drop0": "F: 🌦️Chance shwrs And t-storms <common.temp_high_label>:88°F\nSa: 🌦️Chance shwrs And t-storms <common.temp_high_label>:88°F\nSu: ☀️Sunny then Slight Chan... <common.temp_high_label>:88°F\nM: ☀️Mostly Sunny then Chan... <common.temp_high_label>:89°F\nT: 🌦️Slight Chance shwrs An... <common.temp_high_label>:88°F",
"multiday5-drop1": "F: 🌦️Chance shwrs And t-storms <common.temp_high_label>:88°F\nSa: 🌦️Chance shwrs And t-storms <common.temp_high_label>:88°F\nSu: ☀️Sunny then Slight Chan... <common.temp_high_label>:88°F\nM: ☀️Mostly Sunny then Chan... <common.temp_high_label>:89°F\nT: 🌦️Slight Chance shwrs An... <common.temp_high_label>:88°F",
"multiday5-drop2": "F: 🌦️Chance shwrs And t-storms <common.temp_low_label>:81°F\nSa: 🌦️Chance shwrs And t-storms <common.temp_high_label>:88°F\nSu: ☀️Sunny then Slight Chan... <common.temp_high_label>:88°F\nM: ☀️Mostly Sunny then Chan... <common.temp_high_label>:89°F\nT: 🌦️Slight Chance shwrs An... <common.temp_high_label>:88°F",
"multiday5-drop3": "Sa: 🌦️Chance shwrs And t-storms <common.temp_high_label>:88°F\nSu: ☀️Sunny then Slight Chan... <common.temp_high_label>:88°F\nM: ☀️Mostly Sunny then Chan... <common.temp_high_label>:89°F\nT: 🌦️Slight Chance shwrs An... <common.temp_high_label>:88°F\nW: 🌦️Chance shwrs And t-storms <common.temp_high_label>:88°F",
"multiday7-drop0": "F: 🌦️Chance shwrs And t-storms <common.temp_high_label>:88°F\nSa: 🌦️Chance shwrs And t-storms <common.temp_high_label>:88°F\nSu: ☀️Sunny then Slight Chan... <common.temp_high_label>:88°F\nM: ☀️Mostly Sunny then Chan... <common.temp_high_label>:89°F\nT: 🌦️Slight Chance shwrs An... <common.temp_high_label>:88°F\nW: 🌦️Chance shwrs And t-storms <common.temp_high_label>:88°F",
"multiday7-drop1": "F: 🌦️Chance shwrs And t-storms <common.temp_high_label>:88°F\nSa: 🌦️Chance shwrs And t-storms <common.temp_high_label>:88°F\nSu: ☀️Sunny then Slight Chan... <common.temp_high_label>:88°F\nM: ☀️Mostly Sunny then Chan... <common.temp_high_label>:89°F\nT: 🌦️Slight Chance shwrs An... <common.temp_high_label>:88°F\nW: 🌦️Chance shwrs And t-storms <common.temp_high_label>:88°F",
"multiday7-drop2": "F: 🌦️Chance shwrs And t-storms <common.temp_low_label>:81°F\nSa: 🌦️Chance shwrs And t-storms <common.temp_high_label>:88°F\nSu: ☀️Sunny then Slight Chan... <common.temp_high_label>:88°F\nM: ☀️Mostly Sunny then Chan... <common.temp_high_label>:89°F\nT: 🌦️Slight Chance shwrs An... <common.temp_high_label>:88°F\nW: 🌦️Chance shwrs And t-storms <common.temp_high_label>:88°F",
"multiday7-drop3": "Sa: 🌦️Chance shwrs And t-storms <common.temp_high_label>:88°F\nSu: ☀️Sunny then Slight Chan... <common.temp_high_label>:88°F\nM: ☀️Mostly Sunny then Chan... <common.temp_high_label>:89°F\nT: 🌦️Slight Chance shwrs An... <common.temp_high_label>:88°F\nW: 🌦️Chance shwrs And t-storms <common.temp_high_label>:88°F",
"tomorrow-drop0": "Fri: 🌦️Chance Showers And Thunderstorms <common.temp_high_label>:88°F 💨SE14 | Fri Night: 🌦️Chance Showers And Thunderstorms <common.temp_low_label>:81°F 💨E15",
"tomorrow-drop1": "Fri: 🌦️Chance Showers And Thunderstorms <common.temp_high_label>:88°F 💨SE14 | Fri Night: 🌦️Chance Showers And Thunderstorms <common.temp_low_label>:81°F 💨E15",
"tomorrow-drop2": "Fri Night: 🌦️Chance Showers And Thunderstorms <common.temp_low_label>:81°F 💨E15",
"tomorrow-drop3": "<commands.wx.tomorrow_not_available>"
}
@@ -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 <common.temp_low_label>:53°F 💨WN2",
"drop0-obs0-len200": "This Afternoon: ☁️Mostly Cloudy 66°F 💨WN2 | Tonight: ☁️Partly Cloudy <common.temp_low_label>: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 <common.temp_low_label>:53°F 💨WN2",
"drop1-obs0-len130": "Tonight: ☁️Partly Cloudy 53°F 💨WN2 | Fri: ☀️Partly Sunny <common.temp_high_label>:70°F 💨SS1",
"drop1-obs0-len200": "Tonight: ☁️Partly Cloudy 53°F 💨WN2 | Fri: ☀️Partly Sunny <common.temp_high_label>:70°F 💨SS1 | Fri Night: ☁️Mostly Cloudy <common.temp_low_label>: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 <common.temp_high_label>: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 <common.temp_high_label>:67°F 💨N5",
"drop3-obs0-len200": "Fri Night: ☁️Mostly Cloudy 54°F 💨NN5 | Sat: ☀️Mostly Sunny <common.temp_high_label>: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 <common.temp_high_label>:67°F 💨N5",
"multiday3-drop0": "F: ☀️Partly Sunny <common.temp_high_label>:70°F\nSa: ☀️Mostly Sunny <common.temp_high_label>:67°F\nSu: ☀️Mostly Sunny <common.temp_high_label>:70°F",
"multiday3-drop1": "F: ☀️Partly Sunny <common.temp_high_label>:70°F\nSa: ☀️Mostly Sunny <common.temp_high_label>:67°F\nSu: ☀️Mostly Sunny <common.temp_high_label>:70°F",
"multiday3-drop2": "F: ☀️Partly Sunny <common.temp_high_label>:70°F\nSa: ☀️Mostly Sunny <common.temp_high_label>:67°F\nSu: ☀️Mostly Sunny <common.temp_high_label>:70°F",
"multiday3-drop3": "F: ☁️Mostly Cloudy <common.temp_low_label>:54°F\nSa: ☀️Mostly Sunny <common.temp_high_label>:67°F\nSu: ☀️Mostly Sunny <common.temp_high_label>:70°F",
"multiday5-drop0": "F: ☀️Partly Sunny <common.temp_high_label>:70°F\nSa: ☀️Mostly Sunny <common.temp_high_label>:67°F\nSu: ☀️Mostly Sunny <common.temp_high_label>:70°F\nM: ☀️Mostly Sunny <common.temp_high_label>:68°F\nT: ☀️Partly Sunny <common.temp_high_label>:64°F",
"multiday5-drop1": "F: ☀️Partly Sunny <common.temp_high_label>:70°F\nSa: ☀️Mostly Sunny <common.temp_high_label>:67°F\nSu: ☀️Mostly Sunny <common.temp_high_label>:70°F\nM: ☀️Mostly Sunny <common.temp_high_label>:68°F\nT: ☀️Partly Sunny <common.temp_high_label>:64°F",
"multiday5-drop2": "F: ☀️Partly Sunny <common.temp_high_label>:70°F\nSa: ☀️Mostly Sunny <common.temp_high_label>:67°F\nSu: ☀️Mostly Sunny <common.temp_high_label>:70°F\nM: ☀️Mostly Sunny <common.temp_high_label>:68°F\nT: ☀️Partly Sunny <common.temp_high_label>:64°F",
"multiday5-drop3": "F: ☁️Mostly Cloudy <common.temp_low_label>:54°F\nSa: ☀️Mostly Sunny <common.temp_high_label>:67°F\nSu: ☀️Mostly Sunny <common.temp_high_label>:70°F\nM: ☀️Mostly Sunny <common.temp_high_label>:68°F\nT: ☀️Partly Sunny <common.temp_high_label>:64°F",
"multiday7-drop0": "F: ☀️Partly Sunny <common.temp_high_label>:70°F\nSa: ☀️Mostly Sunny <common.temp_high_label>:67°F\nSu: ☀️Mostly Sunny <common.temp_high_label>:70°F\nM: ☀️Mostly Sunny <common.temp_high_label>:68°F\nT: ☀️Partly Sunny <common.temp_high_label>:64°F\nW: ☀️Mostly Sunny <common.temp_high_label>:65°F",
"multiday7-drop1": "F: ☀️Partly Sunny <common.temp_high_label>:70°F\nSa: ☀️Mostly Sunny <common.temp_high_label>:67°F\nSu: ☀️Mostly Sunny <common.temp_high_label>:70°F\nM: ☀️Mostly Sunny <common.temp_high_label>:68°F\nT: ☀️Partly Sunny <common.temp_high_label>:64°F\nW: ☀️Mostly Sunny <common.temp_high_label>:65°F",
"multiday7-drop2": "F: ☀️Partly Sunny <common.temp_high_label>:70°F\nSa: ☀️Mostly Sunny <common.temp_high_label>:67°F\nSu: ☀️Mostly Sunny <common.temp_high_label>:70°F\nM: ☀️Mostly Sunny <common.temp_high_label>:68°F\nT: ☀️Partly Sunny <common.temp_high_label>:64°F\nW: ☀️Mostly Sunny <common.temp_high_label>:65°F",
"multiday7-drop3": "F: ☁️Mostly Cloudy <common.temp_low_label>:54°F\nSa: ☀️Mostly Sunny <common.temp_high_label>:67°F\nSu: ☀️Mostly Sunny <common.temp_high_label>:70°F\nM: ☀️Mostly Sunny <common.temp_high_label>:68°F\nT: ☀️Partly Sunny <common.temp_high_label>:64°F\nW: ☀️Mostly Sunny <common.temp_high_label>:65°F",
"tomorrow-drop0": "Fri: ☀️Partly Sunny <common.temp_high_label>:70°F 💨SS1 | Fri Night: ☁️Mostly Cloudy <common.temp_low_label>:54°F 💨NN5",
"tomorrow-drop1": "Fri: ☀️Partly Sunny <common.temp_high_label>:70°F 💨SS1 | Fri Night: ☁️Mostly Cloudy <common.temp_low_label>:54°F 💨NN5",
"tomorrow-drop2": "Fri: ☀️Partly Sunny <common.temp_high_label>:70°F 💨SS1 | Fri Night: ☁️Mostly Cloudy <common.temp_low_label>:54°F 💨NN5",
"tomorrow-drop3": "Fri Night: ☁️Mostly Cloudy <common.temp_low_label>:54°F 💨NN5"
}
@@ -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)
+589
View File
@@ -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"
}
]
}
}
}
+539
View File
@@ -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"
}
]
}
}
}
+1500
View File
File diff suppressed because it is too large. Load diff
+1546
View File
File diff suppressed because it is too large. Load diff