} expectedResponseHeaders the expected HTTP headers to receive
- * @returns {Promise} resolved when the fetch is done
- */
- async fetchData (url, type = "json", requestHeaders = undefined, expectedResponseHeaders = undefined) {
- const mockData = this.config.mockData;
- if (mockData) {
- const data = mockData.substring(1, mockData.length - 1);
- return JSON.parse(data);
- }
- const useCorsProxy = typeof this.config.useCorsProxy !== "undefined" && this.config.useCorsProxy;
- return performWebRequest(url, type, useCorsProxy, requestHeaders, expectedResponseHeaders, config.basePath);
- }
-});
-
-/**
- * Collection of registered weather providers.
- */
-WeatherProvider.providers = [];
-
-/**
- * Static method to register a new weather provider.
- * @param {string} providerIdentifier The name of the weather provider
- * @param {object} providerDetails The details of the weather provider
- */
-WeatherProvider.register = function (providerIdentifier, providerDetails) {
- WeatherProvider.providers[providerIdentifier.toLowerCase()] = WeatherProvider.extend(providerDetails);
-};
-
-/**
- * Static method to initialize a new weather provider.
- * @param {string} providerIdentifier The name of the weather provider
- * @param {object} delegate The weather module
- * @returns {object} The new weather provider
- */
-WeatherProvider.initialize = function (providerIdentifier, delegate) {
- const pi = providerIdentifier.toLowerCase();
-
- const provider = new WeatherProvider.providers[pi]();
- const config = Object.assign({}, provider.defaults, delegate.config);
-
- provider.delegate = delegate;
- provider.setConfig(config);
-
- provider.providerIdentifier = pi;
- if (!provider.providerName) {
- provider.providerName = pi;
- }
-
- if (config.allowOverrideNotification) {
- return new OverrideWrapper(provider);
- }
-
- return provider;
-};
diff --git a/defaultmodules/weather/weatherutils.js b/defaultmodules/weather/weatherutils.js
index 43a273b5..365441f0 100644
--- a/defaultmodules/weather/weatherutils.js
+++ b/defaultmodules/weather/weatherutils.js
@@ -25,6 +25,9 @@ const WeatherUtils = {
* @returns {string} - A string with tha value and a unit postfix.
*/
convertPrecipitationUnit (value, valueUnit, outputUnit) {
+ if (value === null || value === undefined || isNaN(value)) {
+ return "";
+ }
if (valueUnit === "%") return `${value.toFixed(0)} ${valueUnit}`;
let convertedValue = value;
diff --git a/eslint.config.mjs b/eslint.config.mjs
index 238efa96..ee3af12c 100644
--- a/eslint.config.mjs
+++ b/eslint.config.mjs
@@ -51,7 +51,7 @@ export default defineConfig([
"@stylistic/space-before-function-paren": ["error", "always"],
"@stylistic/spaced-comment": "off",
"dot-notation": "error",
- eqeqeq: "error",
+ eqeqeq: ["error", "always", { null: "ignore" }],
"id-length": "off",
"import-x/extensions": "error",
"import-x/newline-after-import": "error",
@@ -146,6 +146,15 @@ export default defineConfig([
"vitest/prefer-to-have-length": "error"
}
},
+ {
+ files: ["tests/unit/modules/default/weather/providers/*.js"],
+ rules: {
+ "import-x/namespace": "off",
+ "import-x/named": "off",
+ "import-x/default": "off",
+ "import-x/extensions": "off"
+ }
+ },
{
files: ["tests/configs/modules/weather/*.js"],
rules: {
diff --git a/js/http_fetcher.js b/js/http_fetcher.js
index f5a56fc4..95a13ba5 100644
--- a/js/http_fetcher.js
+++ b/js/http_fetcher.js
@@ -42,6 +42,23 @@ const ERROR_TYPE_TO_TRANSLATION = {
*/
class HTTPFetcher extends EventEmitter {
+ /**
+ * Calculates exponential backoff delay for retries
+ * @param {number} attempt - Attempt number (1-based)
+ * @param {object} options - Configuration options
+ * @param {number} [options.baseDelay] - Initial delay in ms (default: 15s)
+ * @param {number} [options.maxDelay] - Maximum delay in ms (default: 5min)
+ * @returns {number} Delay in milliseconds
+ * @example
+ * HTTPFetcher.calculateBackoffDelay(1) // 15000 (15s)
+ * HTTPFetcher.calculateBackoffDelay(2) // 30000 (30s)
+ * HTTPFetcher.calculateBackoffDelay(3) // 60000 (60s)
+ * HTTPFetcher.calculateBackoffDelay(6) // 300000 (5min, capped)
+ */
+ static calculateBackoffDelay (attempt, { baseDelay = 15000, maxDelay = 300000 } = {}) {
+ return Math.min(baseDelay * Math.pow(2, attempt - 1), maxDelay);
+ }
+
/**
* Creates a new HTTPFetcher instance
* @param {string} url - The URL to fetch
@@ -55,6 +72,7 @@ class HTTPFetcher extends EventEmitter {
* @param {object} [options.headers] - Additional headers to send
* @param {number} [options.maxRetries] - Max retries for 5xx errors (default: 3)
* @param {number} [options.timeout] - Request timeout in ms (default: 30000)
+ * @param {string} [options.logContext] - Optional context for log messages (e.g., provider name)
*/
constructor (url, options = {}) {
super();
@@ -66,9 +84,11 @@ class HTTPFetcher extends EventEmitter {
this.customHeaders = options.headers || {};
this.maxRetries = options.maxRetries || MAX_SERVER_BACKOFF;
this.timeout = options.timeout || DEFAULT_TIMEOUT;
+ this.logContext = options.logContext ? `[${options.logContext}] ` : "";
this.reloadTimer = null;
this.serverErrorCount = 0;
+ this.networkErrorCount = 0;
}
/**
@@ -177,29 +197,29 @@ class HTTPFetcher extends EventEmitter {
if (status === 401 || status === 403) {
errorType = "AUTH_FAILURE";
delay = Math.max(this.reloadInterval * 5, THIRTY_MINUTES);
- message = `Authentication failed (${status}). Waiting ${Math.round(delay / 60000)} minutes before retry.`;
- Log.error(`${this.url} - ${message}`);
+ message = `Authentication failed (${status}). Check your API key. Waiting ${Math.round(delay / 60000)} minutes before retry.`;
+ Log.error(`${this.logContext}${this.url} - ${message}`);
} else if (status === 429) {
errorType = "RATE_LIMITED";
const retryAfter = response.headers.get("retry-after");
const parsed = retryAfter ? this.#parseRetryAfter(retryAfter) : null;
delay = parsed !== null ? Math.max(parsed, this.reloadInterval) : Math.max(this.reloadInterval * 2, FIFTEEN_MINUTES);
message = `Rate limited (429). Retrying in ${Math.round(delay / 60000)} minutes.`;
- Log.warn(`${this.url} - ${message}`);
+ Log.warn(`${this.logContext}${this.url} - ${message}`);
} else if (status >= 500) {
errorType = "SERVER_ERROR";
this.serverErrorCount = Math.min(this.serverErrorCount + 1, this.maxRetries);
delay = this.reloadInterval * Math.pow(2, this.serverErrorCount);
message = `Server error (${status}). Retry #${this.serverErrorCount} in ${Math.round(delay / 60000)} minutes.`;
- Log.error(`${this.url} - ${message}`);
+ Log.error(`${this.logContext}${this.url} - ${message}`);
} else if (status >= 400) {
errorType = "CLIENT_ERROR";
delay = Math.max(this.reloadInterval * 2, FIFTEEN_MINUTES);
message = `Client error (${status}). Retrying in ${Math.round(delay / 60000)} minutes.`;
- Log.error(`${this.url} - ${message}`);
+ Log.error(`${this.logContext}${this.url} - ${message}`);
} else {
message = `Unexpected HTTP status ${status}.`;
- Log.error(`${this.url} - ${message}`);
+ Log.error(`${this.logContext}${this.url} - ${message}`);
}
return {
@@ -224,7 +244,7 @@ class HTTPFetcher extends EventEmitter {
errorType,
translationKey: ERROR_TYPE_TO_TRANSLATION[errorType] || "MODULE_ERROR_UNSPECIFIED",
retryAfter,
- retryCount: this.serverErrorCount,
+ retryCount: errorType === "NETWORK_ERROR" ? this.networkErrorCount : this.serverErrorCount,
url: this.url,
originalError
};
@@ -253,8 +273,9 @@ class HTTPFetcher extends EventEmitter {
nextDelay = delay;
this.emit("error", errorInfo);
} else {
- // Reset server error count on success
+ // Reset error counts on success
this.serverErrorCount = 0;
+ this.networkErrorCount = 0;
/**
* Response event - fired when fetch succeeds
@@ -267,13 +288,35 @@ class HTTPFetcher extends EventEmitter {
const isTimeout = error.name === "AbortError";
const message = isTimeout ? `Request timeout after ${this.timeout}ms` : `Network error: ${error.message}`;
- Log.error(`${this.url} - ${message}`);
+ // Apply exponential backoff for network errors
+ this.networkErrorCount = Math.min(this.networkErrorCount + 1, this.maxRetries);
+ const backoffDelay = HTTPFetcher.calculateBackoffDelay(this.networkErrorCount, {
+ maxDelay: this.reloadInterval
+ });
+ nextDelay = backoffDelay;
+
+ // Truncate URL for cleaner logs
+ let shortUrl = this.url;
+ try {
+ const urlObj = new URL(this.url);
+ shortUrl = `${urlObj.origin}${urlObj.pathname}${urlObj.search.length > 50 ? "?..." : urlObj.search}`;
+ } catch (urlError) {
+ // If URL parsing fails, use original URL
+ }
+
+ // Gradual log-level escalation: WARN for first 2 attempts, ERROR after
+ const retryMessage = `Retry #${this.networkErrorCount} in ${Math.round(nextDelay / 1000)}s.`;
+ if (this.networkErrorCount <= 2) {
+ Log.warn(`${this.logContext}${shortUrl} - ${message} ${retryMessage}`);
+ } else {
+ Log.error(`${this.logContext}${shortUrl} - ${message} ${retryMessage}`);
+ }
const errorInfo = this.#createErrorInfo(
message,
null,
"NETWORK_ERROR",
- this.reloadInterval,
+ nextDelay,
error
);
diff --git a/js/server.js b/js/server.js
index 3bf89209..9eba4f97 100644
--- a/js/server.js
+++ b/js/server.js
@@ -6,7 +6,7 @@ const express = require("express");
const helmet = require("helmet");
const socketio = require("socket.io");
const Log = require("logger");
-const { cors, getHtml, getVersion, getStartup, getEnvVars } = require("#server_functions");
+const { getHtml, getVersion, getEnvVars, cors } = require("#server_functions");
const { ipAccessControl } = require(`${__dirname}/ip_access_control`);
@@ -106,6 +106,9 @@ function Server (configObj) {
app.use(directory, express.static(path.resolve(global.root_path + directory)));
}
+ const startUp = new Date();
+ const getStartup = (req, res) => res.send(startUp);
+
const getConfig = (req, res) => {
if (config.hideConfigSecrets) {
res.send(configObj.redactedConf);
@@ -113,13 +116,12 @@ function Server (configObj) {
res.send(configObj.fullConf);
}
};
+ app.get("/config", (req, res) => getConfig(req, res));
app.get("/cors", async (req, res) => await cors(req, res));
app.get("/version", (req, res) => getVersion(req, res));
- app.get("/config", (req, res) => getConfig(req, res));
-
app.get("/startup", (req, res) => getStartup(req, res));
app.get("/env", (req, res) => getEnvVars(req, res));
diff --git a/tests/configs/modules/weather/currentweather_compliments.js b/tests/configs/modules/weather/currentweather_compliments.js
index 603fafa1..70bb1b8f 100644
--- a/tests/configs/modules/weather/currentweather_compliments.js
+++ b/tests/configs/modules/weather/currentweather_compliments.js
@@ -16,10 +16,10 @@ let config = {
module: "weather",
position: "bottom_bar",
config: {
- location: "Munich",
+ lat: 48.14,
+ lon: 11.58,
weatherProvider: "openweathermap",
- weatherEndpoint: "/weather",
- mockData: '"#####WEATHERDATA#####"'
+ apiKey: "test-api-key"
}
}
]
diff --git a/tests/configs/modules/weather/currentweather_default.js b/tests/configs/modules/weather/currentweather_default.js
index e5a9fdce..0e6e9f17 100644
--- a/tests/configs/modules/weather/currentweather_default.js
+++ b/tests/configs/modules/weather/currentweather_default.js
@@ -8,11 +8,11 @@ let config = {
module: "weather",
position: "bottom_bar",
config: {
- location: "Munich",
+ lat: 48.14,
+ lon: 11.58,
showHumidity: "feelslike",
weatherProvider: "openweathermap",
- weatherEndpoint: "/weather",
- mockData: '"#####WEATHERDATA#####"'
+ apiKey: "test-api-key"
}
}
]
diff --git a/tests/configs/modules/weather/currentweather_options.js b/tests/configs/modules/weather/currentweather_options.js
index 0ddb8b7c..814fca55 100644
--- a/tests/configs/modules/weather/currentweather_options.js
+++ b/tests/configs/modules/weather/currentweather_options.js
@@ -6,10 +6,10 @@ let config = {
module: "weather",
position: "bottom_bar",
config: {
- location: "Munich",
+ lat: 48.14,
+ lon: 11.58,
weatherProvider: "openweathermap",
- weatherEndpoint: "/weather",
- mockData: '"#####WEATHERDATA#####"',
+ apiKey: "test-api-key",
windUnits: "beaufort",
showWindDirectionAsArrow: true,
showSun: false,
diff --git a/tests/configs/modules/weather/currentweather_units.js b/tests/configs/modules/weather/currentweather_units.js
index 462b67f6..33baecd6 100644
--- a/tests/configs/modules/weather/currentweather_units.js
+++ b/tests/configs/modules/weather/currentweather_units.js
@@ -8,10 +8,10 @@ let config = {
module: "weather",
position: "bottom_bar",
config: {
- location: "Munich",
+ lat: 48.14,
+ lon: 11.58,
weatherProvider: "openweathermap",
- weatherEndpoint: "/weather",
- mockData: '"#####WEATHERDATA#####"',
+ apiKey: "test-api-key",
decimalSymbol: ",",
showHumidity: "wind"
}
diff --git a/tests/configs/modules/weather/forecastweather_absolute.js b/tests/configs/modules/weather/forecastweather_absolute.js
index ff18bdf9..01fc4f43 100644
--- a/tests/configs/modules/weather/forecastweather_absolute.js
+++ b/tests/configs/modules/weather/forecastweather_absolute.js
@@ -9,10 +9,10 @@ let config = {
position: "bottom_bar",
config: {
type: "forecast",
- location: "Munich",
+ lat: 48.14,
+ lon: 11.58,
weatherProvider: "openweathermap",
- weatherEndpoint: "/forecast/daily",
- mockData: '"#####WEATHERDATA#####"',
+ apiKey: "test-api-key",
absoluteDates: true
}
}
diff --git a/tests/configs/modules/weather/forecastweather_default.js b/tests/configs/modules/weather/forecastweather_default.js
index a53ba127..4cb23763 100644
--- a/tests/configs/modules/weather/forecastweather_default.js
+++ b/tests/configs/modules/weather/forecastweather_default.js
@@ -9,10 +9,10 @@ let config = {
position: "bottom_bar",
config: {
type: "forecast",
- location: "Munich",
+ lat: 48.14,
+ lon: 11.58,
weatherProvider: "openweathermap",
- weatherEndpoint: "/forecast/daily",
- mockData: '"#####WEATHERDATA#####"'
+ apiKey: "test-api-key"
}
}
]
diff --git a/tests/configs/modules/weather/forecastweather_options.js b/tests/configs/modules/weather/forecastweather_options.js
index 0e801988..25ff5bcd 100644
--- a/tests/configs/modules/weather/forecastweather_options.js
+++ b/tests/configs/modules/weather/forecastweather_options.js
@@ -9,10 +9,10 @@ let config = {
position: "bottom_bar",
config: {
type: "forecast",
- location: "Munich",
+ lat: 48.14,
+ lon: 11.58,
weatherProvider: "openweathermap",
- weatherEndpoint: "/forecast/daily",
- mockData: '"#####WEATHERDATA#####"',
+ apiKey: "test-api-key",
showPrecipitationAmount: true,
colored: true,
tableClass: "myTableClass"
diff --git a/tests/configs/modules/weather/forecastweather_units.js b/tests/configs/modules/weather/forecastweather_units.js
index 73bcde97..a71afaad 100644
--- a/tests/configs/modules/weather/forecastweather_units.js
+++ b/tests/configs/modules/weather/forecastweather_units.js
@@ -9,10 +9,10 @@ let config = {
position: "bottom_bar",
config: {
type: "forecast",
- location: "Munich",
+ lat: 48.14,
+ lon: 11.58,
weatherProvider: "openweathermap",
- weatherEndpoint: "/forecast/daily",
- mockData: '"#####WEATHERDATA#####"',
+ apiKey: "test-api-key",
decimalSymbol: "_",
showPrecipitationAmount: true
}
diff --git a/tests/configs/modules/weather/hourlyweather_default.js b/tests/configs/modules/weather/hourlyweather_default.js
index 191ceab1..e7437b09 100644
--- a/tests/configs/modules/weather/hourlyweather_default.js
+++ b/tests/configs/modules/weather/hourlyweather_default.js
@@ -8,11 +8,11 @@ let config = {
module: "weather",
position: "bottom_bar",
config: {
+ lat: 48.14,
+ lon: 11.58,
type: "hourly",
- location: "Berlin",
weatherProvider: "openweathermap",
- weatherEndpoint: "/onecall",
- mockData: '"#####WEATHERDATA#####"'
+ apiKey: "test-api-key"
}
}
]
diff --git a/tests/configs/modules/weather/hourlyweather_options.js b/tests/configs/modules/weather/hourlyweather_options.js
index c11d23db..0e323a9f 100644
--- a/tests/configs/modules/weather/hourlyweather_options.js
+++ b/tests/configs/modules/weather/hourlyweather_options.js
@@ -8,11 +8,11 @@ let config = {
module: "weather",
position: "bottom_bar",
config: {
+ lat: 48.14,
+ lon: 11.58,
type: "hourly",
- location: "Berlin",
weatherProvider: "openweathermap",
- weatherEndpoint: "/onecall",
- mockData: '"#####WEATHERDATA#####"',
+ apiKey: "test-api-key",
hourlyForecastIncrements: 2
}
}
diff --git a/tests/configs/modules/weather/hourlyweather_showPrecipitation.js b/tests/configs/modules/weather/hourlyweather_showPrecipitation.js
index 3dbbc418..bc04a991 100644
--- a/tests/configs/modules/weather/hourlyweather_showPrecipitation.js
+++ b/tests/configs/modules/weather/hourlyweather_showPrecipitation.js
@@ -8,11 +8,11 @@ let config = {
module: "weather",
position: "bottom_bar",
config: {
+ lat: 48.14,
+ lon: 11.58,
type: "hourly",
- location: "Berlin",
weatherProvider: "openweathermap",
- weatherEndpoint: "/onecall",
- mockData: '"#####WEATHERDATA#####"',
+ apiKey: "test-api-key",
showPrecipitationAmount: true,
showPrecipitationProbability: true
}
diff --git a/tests/e2e/helpers/weather-functions.js b/tests/e2e/helpers/weather-functions.js
index 6780ea42..8eb0c069 100644
--- a/tests/e2e/helpers/weather-functions.js
+++ b/tests/e2e/helpers/weather-functions.js
@@ -1,12 +1,108 @@
-const { injectMockData, cleanupMockData } = require("../../utils/weather_mocker");
+const fs = require("node:fs");
+const path = require("node:path");
+const weatherUtils = require("../../../defaultmodules/weather/provider-utils");
const helpers = require("./global-setup");
-exports.startApplication = async (configFileName, additionalMockData) => {
- await helpers.startApplication(injectMockData(configFileName, additionalMockData));
+/**
+ * Inject mock weather data directly via socket communication
+ * This bypasses the weather provider and tests only client-side rendering
+ * @param {object} page - Playwright page
+ * @param {string} mockDataFile - Filename of mock data
+ */
+async function injectMockWeatherData (page, mockDataFile) {
+ const rawData = JSON.parse(fs.readFileSync(path.resolve(__dirname, "../../mocks", mockDataFile)).toString());
+
+ // Validate that the fixture has at least one expected weather data type
+ if (!rawData.current && !rawData.daily && !rawData.hourly) {
+ throw new Error(
+ "Invalid weather fixture: missing current, daily, and hourly data. "
+ + `Available keys: ${Object.keys(rawData).join(", ")}`
+ );
+ }
+
+ // Determine weather type from the mock data structure
+ let type = "current";
+ let data = null;
+
+ const timezoneOffset = rawData.timezone_offset ? rawData.timezone_offset / 60 : 0;
+
+ if (rawData.current) {
+ type = "current";
+ // Mock what the provider would send for current weather
+ data = {
+ date: weatherUtils.applyTimezoneOffset(new Date(rawData.current.dt * 1000), timezoneOffset),
+ windSpeed: rawData.current.wind_speed,
+ windFromDirection: rawData.current.wind_deg,
+ sunrise: weatherUtils.applyTimezoneOffset(new Date(rawData.current.sunrise * 1000), timezoneOffset),
+ sunset: weatherUtils.applyTimezoneOffset(new Date(rawData.current.sunset * 1000), timezoneOffset),
+ temperature: rawData.current.temp,
+ weatherType: weatherUtils.convertWeatherType(rawData.current.weather[0].icon),
+ humidity: rawData.current.humidity,
+ feelsLikeTemp: rawData.current.feels_like
+ };
+ } else if (rawData.daily) {
+ type = "forecast";
+ data = rawData.daily.map((day) => ({
+ date: weatherUtils.applyTimezoneOffset(new Date(day.dt * 1000), timezoneOffset),
+ minTemperature: day.temp.min,
+ maxTemperature: day.temp.max,
+ weatherType: weatherUtils.convertWeatherType(day.weather[0].icon),
+ rain: day.rain || 0,
+ snow: day.snow || 0,
+ precipitationAmount: (day.rain || 0) + (day.snow || 0)
+ }));
+ } else if (rawData.hourly) {
+ type = "hourly";
+ data = rawData.hourly.map((hour) => ({
+ date: weatherUtils.applyTimezoneOffset(new Date(hour.dt * 1000), timezoneOffset),
+ temperature: hour.temp,
+ feelsLikeTemp: hour.feels_like,
+ humidity: hour.humidity,
+ windSpeed: hour.wind_speed,
+ windFromDirection: hour.wind_deg,
+ weatherType: weatherUtils.convertWeatherType(hour.weather[0].icon),
+ precipitationProbability: hour.pop != null ? hour.pop * 100 : undefined,
+ precipitationAmount: (hour.rain?.["1h"] || 0) + (hour.snow?.["1h"] || 0)
+ }));
+ }
+
+ // Inject weather data by evaluating code in the browser context
+ await page.evaluate(({ type, data }) => {
+ // Find the weather module instance
+ const weatherModule = MM.getModules().find((m) => m.name === "weather");
+ if (weatherModule) {
+ // Send INITIALIZED first
+ weatherModule.socketNotificationReceived("WEATHER_INITIALIZED", {
+ instanceId: weatherModule.instanceId,
+ locationName: "Munich"
+ });
+ // Then send the actual data
+ weatherModule.socketNotificationReceived("WEATHER_DATA", {
+ instanceId: weatherModule.instanceId,
+ type: type,
+ data: data
+ });
+ }
+ }, { type, data });
+}
+
+exports.startApplication = async (configFileName, mockDataFile) => {
+ await helpers.startApplication(configFileName);
await helpers.getDocument();
+
+ // If mock data file is provided, inject it
+ if (mockDataFile) {
+ const page = helpers.getPage();
+ // Wait for weather module to initialize
+ // eslint-disable-next-line playwright/no-wait-for-selector
+ await page.waitForSelector(".weather", { timeout: 5000 });
+ await injectMockWeatherData(page, mockDataFile);
+ // Wait for data to be rendered
+ // eslint-disable-next-line playwright/no-wait-for-selector
+ await page.waitForSelector(".weather .weathericon", { timeout: 2000 });
+ }
};
exports.stopApplication = async () => {
await helpers.stopApplication();
- cleanupMockData();
};
diff --git a/tests/e2e/modules/weather_current_spec.js b/tests/e2e/modules/weather_current_spec.js
index 9b292879..bb8b63e2 100644
--- a/tests/e2e/modules/weather_current_spec.js
+++ b/tests/e2e/modules/weather_current_spec.js
@@ -12,7 +12,7 @@ describe("Weather module", () => {
describe("Current weather", () => {
describe("Default configuration", () => {
beforeAll(async () => {
- await weatherFunc.startApplication("tests/configs/modules/weather/currentweather_default.js", {});
+ await weatherFunc.startApplication("tests/configs/modules/weather/currentweather_default.js", "weather_onecall_current.json");
page = helpers.getPage();
});
@@ -38,7 +38,7 @@ describe("Weather module", () => {
describe("Compliments Integration", () => {
beforeAll(async () => {
- await weatherFunc.startApplication("tests/configs/modules/weather/currentweather_compliments.js", {});
+ await weatherFunc.startApplication("tests/configs/modules/weather/currentweather_compliments.js", "weather_onecall_current.json");
page = helpers.getPage();
});
@@ -51,7 +51,7 @@ describe("Weather module", () => {
describe("Configuration Options", () => {
beforeAll(async () => {
- await weatherFunc.startApplication("tests/configs/modules/weather/currentweather_options.js", {});
+ await weatherFunc.startApplication("tests/configs/modules/weather/currentweather_options.js", "weather_onecall_current.json");
page = helpers.getPage();
});
@@ -79,7 +79,7 @@ describe("Weather module", () => {
describe("Current weather with imperial units", () => {
beforeAll(async () => {
- await weatherFunc.startApplication("tests/configs/modules/weather/currentweather_units.js", {});
+ await weatherFunc.startApplication("tests/configs/modules/weather/currentweather_units.js", "weather_onecall_current.json");
page = helpers.getPage();
});
diff --git a/tests/e2e/modules/weather_forecast_spec.js b/tests/e2e/modules/weather_forecast_spec.js
index 011ed35f..435cc98c 100644
--- a/tests/e2e/modules/weather_forecast_spec.js
+++ b/tests/e2e/modules/weather_forecast_spec.js
@@ -11,7 +11,7 @@ describe("Weather module: Weather Forecast", () => {
describe("Default configuration", () => {
beforeAll(async () => {
- await weatherFunc.startApplication("tests/configs/modules/weather/forecastweather_default.js", {});
+ await weatherFunc.startApplication("tests/configs/modules/weather/forecastweather_default.js", "weather_onecall_forecast.json");
page = helpers.getPage();
});
@@ -58,7 +58,7 @@ describe("Weather module: Weather Forecast", () => {
describe("Absolute configuration", () => {
beforeAll(async () => {
- await weatherFunc.startApplication("tests/configs/modules/weather/forecastweather_absolute.js", {});
+ await weatherFunc.startApplication("tests/configs/modules/weather/forecastweather_absolute.js", "weather_onecall_forecast.json");
page = helpers.getPage();
});
@@ -73,7 +73,7 @@ describe("Weather module: Weather Forecast", () => {
describe("Configuration Options", () => {
beforeAll(async () => {
- await weatherFunc.startApplication("tests/configs/modules/weather/forecastweather_options.js", {});
+ await weatherFunc.startApplication("tests/configs/modules/weather/forecastweather_options.js", "weather_onecall_forecast.json");
page = helpers.getPage();
});
@@ -99,7 +99,7 @@ describe("Weather module: Weather Forecast", () => {
describe("Forecast weather with imperial units", () => {
beforeAll(async () => {
- await weatherFunc.startApplication("tests/configs/modules/weather/forecastweather_units.js", {});
+ await weatherFunc.startApplication("tests/configs/modules/weather/forecastweather_units.js", "weather_onecall_forecast.json");
page = helpers.getPage();
});
diff --git a/tests/e2e/modules/weather_hourly_spec.js b/tests/e2e/modules/weather_hourly_spec.js
index a33503f3..d84bd69e 100644
--- a/tests/e2e/modules/weather_hourly_spec.js
+++ b/tests/e2e/modules/weather_hourly_spec.js
@@ -11,7 +11,7 @@ describe("Weather module: Weather Hourly Forecast", () => {
describe("Default configuration", () => {
beforeAll(async () => {
- await weatherFunc.startApplication("tests/configs/modules/weather/hourlyweather_default.js", {});
+ await weatherFunc.startApplication("tests/configs/modules/weather/hourlyweather_default.js", "weather_onecall_hourly.json");
page = helpers.getPage();
});
@@ -26,7 +26,7 @@ describe("Weather module: Weather Hourly Forecast", () => {
describe("Hourly weather options", () => {
beforeAll(async () => {
- await weatherFunc.startApplication("tests/configs/modules/weather/hourlyweather_options.js", {});
+ await weatherFunc.startApplication("tests/configs/modules/weather/hourlyweather_options.js", "weather_onecall_hourly.json");
page = helpers.getPage();
});
@@ -43,7 +43,7 @@ describe("Weather module: Weather Hourly Forecast", () => {
describe("Show precipitations", () => {
beforeAll(async () => {
- await weatherFunc.startApplication("tests/configs/modules/weather/hourlyweather_showPrecipitation.js", {});
+ await weatherFunc.startApplication("tests/configs/modules/weather/hourlyweather_showPrecipitation.js", "weather_onecall_hourly.json");
page = helpers.getPage();
});
diff --git a/tests/electron/helpers/weather-setup.js b/tests/electron/helpers/weather-setup.js
index cb430548..3bddaef1 100644
--- a/tests/electron/helpers/weather-setup.js
+++ b/tests/electron/helpers/weather-setup.js
@@ -1,6 +1,77 @@
-const { injectMockData } = require("../../utils/weather_mocker");
+const fs = require("node:fs");
+const path = require("node:path");
+const weatherUtils = require("../../../defaultmodules/weather/provider-utils");
const helpers = require("./global-setup");
+/**
+ * Inject mock weather data directly via socket communication
+ * This bypasses the weather provider and tests only client-side rendering
+ * @param {string} mockDataFile - Filename of mock data in tests/mocks
+ */
+async function injectMockWeatherData (mockDataFile) {
+ const rawData = JSON.parse(fs.readFileSync(path.resolve(__dirname, "../../mocks", mockDataFile)).toString());
+
+ const timezoneOffset = rawData.timezone_offset ? rawData.timezone_offset / 60 : 0;
+
+ let type = "current";
+ let data = null;
+
+ if (rawData.current) {
+ type = "current";
+ data = {
+ date: weatherUtils.applyTimezoneOffset(new Date(rawData.current.dt * 1000), timezoneOffset),
+ windSpeed: rawData.current.wind_speed,
+ windFromDirection: rawData.current.wind_deg,
+ sunrise: weatherUtils.applyTimezoneOffset(new Date(rawData.current.sunrise * 1000), timezoneOffset),
+ sunset: weatherUtils.applyTimezoneOffset(new Date(rawData.current.sunset * 1000), timezoneOffset),
+ temperature: rawData.current.temp,
+ weatherType: weatherUtils.convertWeatherType(rawData.current.weather[0].icon),
+ humidity: rawData.current.humidity,
+ feelsLikeTemp: rawData.current.feels_like
+ };
+ } else if (rawData.daily) {
+ type = "forecast";
+ data = rawData.daily.map((day) => ({
+ date: weatherUtils.applyTimezoneOffset(new Date(day.dt * 1000), timezoneOffset),
+ minTemperature: day.temp.min,
+ maxTemperature: day.temp.max,
+ weatherType: weatherUtils.convertWeatherType(day.weather[0].icon),
+ rain: day.rain || 0,
+ snow: day.snow || 0,
+ precipitationAmount: (day.rain || 0) + (day.snow || 0)
+ }));
+ } else if (rawData.hourly) {
+ type = "hourly";
+ data = rawData.hourly.map((hour) => ({
+ date: weatherUtils.applyTimezoneOffset(new Date(hour.dt * 1000), timezoneOffset),
+ temperature: hour.temp,
+ feelsLikeTemp: hour.feels_like,
+ humidity: hour.humidity,
+ windSpeed: hour.wind_speed,
+ windFromDirection: hour.wind_deg,
+ weatherType: weatherUtils.convertWeatherType(hour.weather[0].icon),
+ precipitationProbability: hour.pop != null ? hour.pop * 100 : undefined,
+ precipitationAmount: (hour.rain?.["1h"] || 0) + (hour.snow?.["1h"] || 0)
+ }));
+ }
+
+ // Inject weather data by evaluating code in the browser context
+ await global.page.evaluate(({ type, data }) => {
+ const weatherModule = MM.getModules().find((m) => m.name === "weather");
+ if (weatherModule) {
+ weatherModule.socketNotificationReceived("WEATHER_INITIALIZED", {
+ instanceId: weatherModule.instanceId,
+ locationName: "Munich"
+ });
+ weatherModule.socketNotificationReceived("WEATHER_DATA", {
+ instanceId: weatherModule.instanceId,
+ type: type,
+ data: data
+ });
+ }
+ }, { type, data });
+}
+
exports.getText = async (element, result) => {
const elem = await helpers.getElement(element);
await expect(elem).not.toBeNull();
@@ -14,6 +85,18 @@ exports.getText = async (element, result) => {
return true;
};
-exports.startApp = async (configFileName, systemDate) => {
- await helpers.startApplication(injectMockData(configFileName), systemDate);
+exports.startApp = async (configFileName, systemDate, mockDataFile = "weather_onecall_current.json") => {
+ await helpers.startApplication(configFileName, systemDate);
+
+ // Wait for weather module to be present in DOM
+ await global.page.waitForSelector(".weather", { timeout: 5000 });
+
+ // Inject mock weather data
+ await injectMockWeatherData(mockDataFile);
+
+ // Wait for weather content to be rendered
+ await global.page.waitForFunction(() => {
+ const weatherRoot = document.querySelector(".weather");
+ return !!(weatherRoot && weatherRoot.textContent && weatherRoot.textContent.trim().length > 0);
+ }, { timeout: 5000 });
};
diff --git a/tests/electron/modules/weather_spec.js b/tests/electron/modules/weather_spec.js
index fb362f80..e300da90 100644
--- a/tests/electron/modules/weather_spec.js
+++ b/tests/electron/modules/weather_spec.js
@@ -1,6 +1,5 @@
const helpers = require("../helpers/global-setup");
const weatherHelper = require("../helpers/weather-setup");
-const { cleanupMockData } = require("../../utils/weather_mocker");
const CURRENT_WEATHER_CONFIG = "tests/configs/modules/weather/currentweather_default.js";
const SUNRISE_DATE = "13 Jan 2019 00:30:00 GMT";
@@ -12,7 +11,6 @@ const EXPECTED_SUNSET_TEXT = "3:45 pm";
describe("Weather module", () => {
afterEach(async () => {
await helpers.stopApplication();
- cleanupMockData();
});
describe("Current weather with sunrise", () => {
diff --git a/tests/mocks/weather_envcanada.xml b/tests/mocks/weather_envcanada.xml
new file mode 100644
index 00000000..ac8d6fcf
--- /dev/null
+++ b/tests/mocks/weather_envcanada.xml
@@ -0,0 +1,871 @@
+
+
+ https://dd.weather.gc.ca/doc/LICENCE_GENERAL.txt
+
+ 2026
+ 02
+ 07
+ 12
+ 04
+ 20260207120421
+ Saturday February 07, 2026 at 12:04 UTC
+
+
+ 2026
+ 02
+ 07
+ 07
+ 04
+ 20260207070421
+ Saturday February 07, 2026 at 07:04 EST
+
+
+ North America
+ Canada
+ Ontario
+ Toronto
+ City of Toronto
+
+
+
+
+ 2026
+ 02
+ 07
+ 09
+ 06
+ 20260207090653
+ Saturday February 07, 2026 at 09:06 UTC
+
+
+ 2026
+ 02
+ 07
+ 04
+ 06
+ 20260207040653
+ Saturday February 07, 2026 at 04:06 EST
+
+
+
+
+ Toronto Pearson Int'l Airport
+
+ 2026
+ 02
+ 07
+ 12
+ 00
+ 20260207120000
+ Saturday February 07, 2026 at 12:00 UTC
+
+
+ 2026
+ 02
+ 07
+ 07
+ 00
+ 20260207070000
+ Saturday February 07, 2026 at 07:00 EST
+
+ Blowing Snow
+ 40
+ -20.3
+ -24.9
+ -31
+ 102.1
+ 9.7
+ 67
+
+ 19
+ 33
+ NNW
+ 346.0
+
+
+
+
+ 2026
+ 02
+ 07
+ 10
+ 00
+ 20260207100000
+ Saturday February 07, 2026 at 10:00 UTC
+
+
+ 2026
+ 02
+ 07
+ 05
+ 00
+ 20260207050000
+ Saturday February 07, 2026 at 05:00 EST
+
+
+ Low minus 9. High minus 2.
+ -2
+ -9
+
+
+ Saturday
+ A mix of sun and cloud. 40 percent chance of flurries early this morning. Wind northwest 30 km/h gusting to 50. High minus 13. Wind chill minus 33 this morning and minus 22 this afternoon. Risk of frostbite. UV index 1 or low.
+
+ A mix of sun and cloud. 40 percent chance of flurries early this morning.
+
+
+ 08
+ 40
+ Chance of flurries
+
+
+ High minus 13.
+ -13
+
+
+ Wind northwest 30 km/h gusting to 50.
+
+ 30
+ 50
+ NW
+ 32
+
+
+
+
+ snow
+
+
+ Wind chill minus 33 this morning and minus 22 this afternoon. Risk of frostbite.
+ -33
+ -22
+ Risk of frostbite
+
+
+ 1
+ UV index 1 or low.
+
+ 40
+
+
+
+ Saturday night
+ Partly cloudy. Clearing late this evening. Wind northwest 20 km/h becoming light late this evening. Low minus 21. Wind chill minus 22 this evening and minus 28 overnight. Risk of frostbite.
+
+ Partly cloudy. Clearing late this evening.
+
+
+ 35
+
+ Clearing
+
+
+ Low minus 21.
+ -21
+
+
+ Wind northwest 20 km/h becoming light late this evening.
+
+ 20
+ 00
+ NW
+ 32
+
+
+ 10
+ 00
+ NW
+ 32
+
+
+
+
+
+
+
+ Wind chill minus 22 this evening and minus 28 overnight. Risk of frostbite.
+ -22
+ -28
+ Risk of frostbite
+
+ 65
+
+
+
+ Sunday
+ Sunny. Wind up to 15 km/h. High minus 12. Wind chill minus 28 in the morning and minus 19 in the afternoon. Risk of frostbite. UV index 2 or low.
+
+ Sunny.
+
+
+ 00
+
+ Sunny
+
+
+ High minus 12.
+ -12
+
+
+ Wind up to 15 km/h.
+
+ 10
+ 00
+ N
+ 36
+
+
+ 15
+ 00
+ NW
+ 32
+
+
+
+
+
+
+
+ Wind chill minus 28 in the morning and minus 19 in the afternoon. Risk of frostbite.
+ -28
+ -19
+ Risk of frostbite
+
+
+ 2
+ UV index 2 or low.
+
+ 55
+
+
+
+ Sunday night
+ Cloudy periods. Low minus 14.
+
+ Cloudy periods.
+
+
+ 32
+
+ Cloudy periods
+
+
+ Low minus 14.
+ -14
+
+
+
+
+
+
+
+ 60
+
+
+
+ Monday
+ Cloudy with 40 percent chance of flurries. High minus 6.
+
+ Cloudy with 40 percent chance of flurries.
+
+
+ 16
+ 40
+ Chance of flurries
+
+
+ High minus 6.
+ -6
+
+
+
+
+ snow
+
+
+ 65
+
+
+
+ Monday night
+ Cloudy with 30 percent chance of flurries. Low minus 8.
+
+ Cloudy with 30 percent chance of flurries.
+
+
+ 16
+ 30
+ Chance of flurries
+
+
+ Low minus 8.
+ -8
+
+
+
+
+ snow
+
+
+ 65
+
+
+
+ Tuesday
+ Cloudy with 30 percent chance of flurries. High minus 2.
+
+ Cloudy with 30 percent chance of flurries.
+
+
+ 16
+ 30
+ Chance of flurries
+
+
+ High minus 2.
+ -2
+
+
+
+
+ snow
+
+
+ 75
+
+
+
+ Tuesday night
+ Cloudy with 40 percent chance of flurries. Low minus 3.
+
+ Cloudy with 40 percent chance of flurries.
+
+
+ 16
+ 40
+ Chance of flurries
+
+
+ Low minus 3.
+ -3
+
+
+
+
+ snow
+
+
+ 80
+
+
+
+ Wednesday
+ Cloudy with 30 percent chance of flurries. High zero.
+
+ Cloudy with 30 percent chance of flurries.
+
+
+ 16
+ 30
+ Chance of flurries
+
+
+ High zero.
+ 0
+
+
+
+
+ snow
+
+
+ 80
+
+
+
+ Wednesday night
+ Cloudy periods. Low minus 6.
+
+ Cloudy periods.
+
+
+ 32
+
+ Cloudy periods
+
+
+ Low minus 6.
+ -6
+
+
+
+
+
+
+
+ 90
+
+
+
+ Thursday
+ A mix of sun and cloud. High minus 2.
+
+ A mix of sun and cloud.
+
+
+ 02
+
+ A mix of sun and cloud
+
+
+ High minus 2.
+ -2
+
+
+
+
+
+
+
+ 75
+
+
+
+ Thursday night
+ Cloudy periods. Low minus 7.
+
+ Cloudy periods.
+
+
+ 32
+
+ Cloudy periods
+
+
+ Low minus 7.
+ -7
+
+
+
+
+
+
+
+ 75
+
+
+
+ Friday
+ A mix of sun and cloud. High minus 1.
+
+ A mix of sun and cloud.
+
+
+ 02
+
+ A mix of sun and cloud
+
+
+ High minus 1.
+ -1
+
+
+
+
+
+
+
+ 75
+
+
+
+
+
+ 2026
+ 02
+ 07
+ 10
+ 00
+ 20260207100000
+ Saturday February 07, 2026 at 10:00 UTC
+
+
+ 2026
+ 02
+ 07
+ 05
+ 00
+ 20260207050000
+ Saturday February 07, 2026 at 05:00 EST
+
+
+ A mix of sun and cloud
+ 02
+ -20
+ 10
+ -32
+
+
+ 30
+ NW
+ 50
+
+
+
+ A mix of sun and cloud
+ 02
+ -19
+ 10
+ -32
+
+
+ 30
+ NW
+ 50
+
+
+ 1
+
+
+
+ A mix of sun and cloud
+ 02
+ -19
+ 10
+ -31
+
+
+ 30
+ NW
+ 50
+
+
+ 1
+
+
+
+ A mix of sun and cloud
+ 02
+ -18
+ 10
+ -30
+
+
+ 30
+ NW
+ 50
+
+
+ 1
+
+
+
+ Mainly sunny
+ 01
+ -16
+ 10
+ -28
+
+
+ 30
+ NW
+ 50
+
+
+ 1
+
+
+
+ A mix of sun and cloud
+ 02
+ -15
+ 10
+ -26
+
+
+ 30
+ NW
+ 50
+
+
+ 1
+
+
+
+ A mix of sun and cloud
+ 02
+ -14
+ 10
+ -25
+
+
+ 30
+ NW
+ 50
+
+
+ 1
+
+
+
+ A mix of sun and cloud
+ 02
+ -14
+ 10
+ -24
+
+
+ 30
+ NW
+ 50
+
+
+
+ A mix of sun and cloud
+ 02
+ -13
+ 10
+ -23
+
+
+ 30
+ NW
+ 50
+
+
+
+ A mix of sun and cloud
+ 02
+ -13
+ 10
+ -24
+
+
+ 30
+ NW
+ 50
+
+
+
+ Partly cloudy
+ 32
+ -14
+ 10
+ -22
+
+
+ 20
+ NW
+
+
+
+
+ Partly cloudy
+ 32
+ -14
+ 10
+ -23
+
+
+ 20
+ NW
+
+
+
+
+ Partly cloudy
+ 32
+ -15
+ 10
+ -24
+
+
+ 20
+ NW
+
+
+
+
+ Partly cloudy
+ 32
+ -16
+ 0
+ -25
+
+
+ 20
+ NW
+
+
+
+
+ Partly cloudy
+ 32
+ -17
+ 0
+ -24
+
+
+ 10
+ NW
+
+
+
+
+ A few clouds
+ 31
+ -18
+ 0
+ -24
+
+
+ 10
+ NW
+
+
+
+
+ A few clouds
+ 31
+ -18
+ 0
+ -25
+
+
+ 10
+ NW
+
+
+
+
+ A few clouds
+ 31
+ -19
+ 0
+ -26
+
+
+ 10
+ NW
+
+
+
+
+ Clear
+ 30
+ -20
+ 0
+ -27
+
+
+ 10
+ NW
+
+
+
+
+ Clear
+ 30
+ -20
+ 0
+ -28
+
+
+ 10
+ NW
+
+
+
+
+ Clear
+ 30
+ -21
+ 0
+ -28
+
+
+ 10
+ NW
+
+
+
+
+ Clear
+ 30
+ -21
+ 0
+ -28
+
+
+ 10
+ NW
+
+
+
+
+ Clear
+ 30
+ -21
+ 0
+ -28
+
+
+ 10
+ N
+
+
+
+
+ Sunny
+ 00
+ -21
+ 0
+ -28
+
+
+ 10
+ N
+
+
+
+
+
+ The information provided here, for the times of the rise and set of the sun, is an estimate included as a convenience to our clients. Values shown here may differ from the official sunrise/sunset data available from (http://hia-iha.nrc-cnrc.gc.ca/sunrise_e.html)
+
+ 2026
+ 02
+ 07
+ 12
+ 27
+ 20260207122700
+ Saturday February 07, 2026 at 12:27 UTC
+
+
+ 2026
+ 02
+ 07
+ 07
+ 27
+ 20260207072700
+ Saturday February 07, 2026 at 07:27 EST
+
+
+ 2026
+ 02
+ 07
+ 22
+ 37
+ 20260207223700
+ Saturday February 07, 2026 at 22:37 UTC
+
+
+ 2026
+ 02
+ 07
+ 17
+ 37
+ 20260207173700
+ Saturday February 07, 2026 at 17:37 EST
+
+
+
\ No newline at end of file
diff --git a/tests/mocks/weather_envcanada_index.html b/tests/mocks/weather_envcanada_index.html
new file mode 100644
index 00000000..93d5a5d4
--- /dev/null
+++ b/tests/mocks/weather_envcanada_index.html
@@ -0,0 +1,427 @@
+
+
+
+ Index of /today/citypage_weather/ON/12
+
+
+ Index of /today/citypage_weather/ON/12
+
Name Last modified Size Description
Parent Directory -
+
20260207T120044.778Z_MSC_CitypageWeather_s0000024_en.xml 2026-02-07 12:00 36K
+
20260207T120044.827Z_MSC_CitypageWeather_s0000024_fr.xml 2026-02-07 12:00 36K
+
20260207T120044.875Z_MSC_CitypageWeather_s0000022_en.xml 2026-02-07 12:00 36K
+
20260207T120044.919Z_MSC_CitypageWeather_s0000022_fr.xml 2026-02-07 12:00 37K
+
20260207T120045.458Z_MSC_CitypageWeather_s0000588_en.xml 2026-02-07 12:00 36K
+
20260207T120045.502Z_MSC_CitypageWeather_s0000588_fr.xml 2026-02-07 12:00 36K
+
20260207T120047.636Z_MSC_CitypageWeather_s0000546_en.xml 2026-02-07 12:01 36K
+
20260207T120047.636Z_MSC_CitypageWeather_s0000819_en.xml 2026-02-07 12:00 36K
+
20260207T120047.715Z_MSC_CitypageWeather_s0000546_fr.xml 2026-02-07 12:00 37K
+
20260207T120047.715Z_MSC_CitypageWeather_s0000819_fr.xml 2026-02-07 12:00 37K
+
20260207T120047.911Z_MSC_CitypageWeather_s0000646_en.xml 2026-02-07 12:00 36K
+
20260207T120047.960Z_MSC_CitypageWeather_s0000646_fr.xml 2026-02-07 12:00 37K
+
20260207T120048.388Z_MSC_CitypageWeather_s0000512_en.xml 2026-02-07 12:00 36K
+
20260207T120048.388Z_MSC_CitypageWeather_s0000513_en.xml 2026-02-07 12:00 36K
+
20260207T120048.388Z_MSC_CitypageWeather_s0000790_en.xml 2026-02-07 12:00 36K
+
20260207T120048.526Z_MSC_CitypageWeather_s0000512_fr.xml 2026-02-07 12:00 36K
+
20260207T120048.526Z_MSC_CitypageWeather_s0000513_fr.xml 2026-02-07 12:00 37K
+
20260207T120048.526Z_MSC_CitypageWeather_s0000790_fr.xml 2026-02-07 12:01 37K
+
20260207T120048.664Z_MSC_CitypageWeather_s0000765_en.xml 2026-02-07 12:01 36K
+
20260207T120048.664Z_MSC_CitypageWeather_s0000766_en.xml 2026-02-07 12:00 36K
+
20260207T120048.752Z_MSC_CitypageWeather_s0000765_fr.xml 2026-02-07 12:01 37K
+
20260207T120048.752Z_MSC_CitypageWeather_s0000766_fr.xml 2026-02-07 12:01 37K
+
20260207T120048.945Z_MSC_CitypageWeather_s0000782_en.xml 2026-02-07 12:00 36K
+
20260207T120048.994Z_MSC_CitypageWeather_s0000782_fr.xml 2026-02-07 12:00 37K
+
20260207T120049.038Z_MSC_CitypageWeather_s0000585_en.xml 2026-02-07 12:01 37K
+
20260207T120049.038Z_MSC_CitypageWeather_s0000785_en.xml 2026-02-07 12:01 37K
+
20260207T120049.127Z_MSC_CitypageWeather_s0000585_fr.xml 2026-02-07 12:00 37K
+
20260207T120049.127Z_MSC_CitypageWeather_s0000785_fr.xml 2026-02-07 12:01 37K
+
20260207T120049.536Z_MSC_CitypageWeather_s0000411_en.xml 2026-02-07 12:01 36K
+
20260207T120049.536Z_MSC_CitypageWeather_s0000659_en.xml 2026-02-07 12:00 36K
+
20260207T120049.536Z_MSC_CitypageWeather_s0000660_en.xml 2026-02-07 12:01 37K
+
20260207T120049.653Z_MSC_CitypageWeather_s0000411_fr.xml 2026-02-07 12:01 37K
+
20260207T120049.653Z_MSC_CitypageWeather_s0000659_fr.xml 2026-02-07 12:00 37K
+
20260207T120049.653Z_MSC_CitypageWeather_s0000660_fr.xml 2026-02-07 12:00 38K
+
20260207T120052.583Z_MSC_CitypageWeather_s0000080_en.xml 2026-02-07 12:01 37K
+
20260207T120052.583Z_MSC_CitypageWeather_s0000454_en.xml 2026-02-07 12:01 37K
+
20260207T120052.665Z_MSC_CitypageWeather_s0000080_fr.xml 2026-02-07 12:01 37K
+
20260207T120052.665Z_MSC_CitypageWeather_s0000454_fr.xml 2026-02-07 12:01 37K
+
20260207T120055.400Z_MSC_CitypageWeather_s0000596_en.xml 2026-02-07 12:01 35K
+
20260207T120055.400Z_MSC_CitypageWeather_s0000597_en.xml 2026-02-07 12:01 36K
+
20260207T120055.471Z_MSC_CitypageWeather_s0000596_fr.xml 2026-02-07 12:01 36K
+
20260207T120055.471Z_MSC_CitypageWeather_s0000597_fr.xml 2026-02-07 12:01 37K
+
20260207T120117.907Z_MSC_CitypageWeather_s0000744_en.xml 2026-02-07 12:01 38K
+
20260207T120117.907Z_MSC_CitypageWeather_s0000796_en.xml 2026-02-07 12:01 38K
+
20260207T120118.045Z_MSC_CitypageWeather_s0000744_fr.xml 2026-02-07 12:01 39K
+
20260207T120118.045Z_MSC_CitypageWeather_s0000796_fr.xml 2026-02-07 12:01 39K
+
20260207T120118.904Z_MSC_CitypageWeather_s0000572_en.xml 2026-02-07 12:01 38K
+
20260207T120118.904Z_MSC_CitypageWeather_s0000573_en.xml 2026-02-07 12:01 38K
+
20260207T120119.006Z_MSC_CitypageWeather_s0000572_fr.xml 2026-02-07 12:01 39K
+
20260207T120119.006Z_MSC_CitypageWeather_s0000573_fr.xml 2026-02-07 12:01 39K
+
20260207T120119.181Z_MSC_CitypageWeather_s0000765_en.xml 2026-02-07 12:01 36K
+
20260207T120119.181Z_MSC_CitypageWeather_s0000766_en.xml 2026-02-07 12:01 36K
+
20260207T120119.228Z_MSC_CitypageWeather_s0000765_fr.xml 2026-02-07 12:01 37K
+
20260207T120119.228Z_MSC_CitypageWeather_s0000766_fr.xml 2026-02-07 12:01 37K
+
20260207T120119.276Z_MSC_CitypageWeather_s0000395_en.xml 2026-02-07 12:01 36K
+
20260207T120119.276Z_MSC_CitypageWeather_s0000520_en.xml 2026-02-07 12:01 36K
+
20260207T120119.351Z_MSC_CitypageWeather_s0000395_fr.xml 2026-02-07 12:01 37K
+
20260207T120119.351Z_MSC_CitypageWeather_s0000520_fr.xml 2026-02-07 12:01 37K
+
20260207T120119.429Z_MSC_CitypageWeather_s0000724_en.xml 2026-02-07 12:01 38K
+
20260207T120119.429Z_MSC_CitypageWeather_s0000725_en.xml 2026-02-07 12:01 38K
+
20260207T120119.429Z_MSC_CitypageWeather_s0000726_en.xml 2026-02-07 12:01 38K
+
20260207T120119.429Z_MSC_CitypageWeather_s0000727_en.xml 2026-02-07 12:01 38K
+
20260207T120119.429Z_MSC_CitypageWeather_s0000728_en.xml 2026-02-07 12:01 38K
+
20260207T120119.665Z_MSC_CitypageWeather_s0000724_fr.xml 2026-02-07 12:01 39K
+
20260207T120119.665Z_MSC_CitypageWeather_s0000725_fr.xml 2026-02-07 12:01 39K
+
20260207T120119.665Z_MSC_CitypageWeather_s0000726_fr.xml 2026-02-07 12:01 39K
+
20260207T120119.665Z_MSC_CitypageWeather_s0000727_fr.xml 2026-02-07 12:01 39K
+
20260207T120119.665Z_MSC_CitypageWeather_s0000728_fr.xml 2026-02-07 12:01 39K
+
20260207T120120.713Z_MSC_CitypageWeather_s0000752_en.xml 2026-02-07 12:01 36K
+
20260207T120120.713Z_MSC_CitypageWeather_s0000753_en.xml 2026-02-07 12:01 36K
+
20260207T120120.815Z_MSC_CitypageWeather_s0000752_fr.xml 2026-02-07 12:01 37K
+
20260207T120120.815Z_MSC_CitypageWeather_s0000753_fr.xml 2026-02-07 12:01 37K
+
20260207T120121.465Z_MSC_CitypageWeather_s0000538_en.xml 2026-02-07 12:01 36K
+
20260207T120121.465Z_MSC_CitypageWeather_s0000539_en.xml 2026-02-07 12:01 36K
+
20260207T120121.544Z_MSC_CitypageWeather_s0000538_fr.xml 2026-02-07 12:01 36K
+
20260207T120121.544Z_MSC_CitypageWeather_s0000539_fr.xml 2026-02-07 12:01 37K
+
20260207T120121.909Z_MSC_CitypageWeather_s0000637_en.xml 2026-02-07 12:01 36K
+
20260207T120121.909Z_MSC_CitypageWeather_s0000638_en.xml 2026-02-07 12:01 37K
+
20260207T120121.909Z_MSC_CitypageWeather_s0000639_en.xml 2026-02-07 12:01 37K
+
20260207T120121.909Z_MSC_CitypageWeather_s0000640_en.xml 2026-02-07 12:01 36K
+
20260207T120121.909Z_MSC_CitypageWeather_s0000641_en.xml 2026-02-07 12:01 37K
+
20260207T120121.909Z_MSC_CitypageWeather_s0000642_en.xml 2026-02-07 12:01 37K
+
20260207T120122.236Z_MSC_CitypageWeather_s0000637_fr.xml 2026-02-07 12:01 37K
+
20260207T120122.236Z_MSC_CitypageWeather_s0000638_fr.xml 2026-02-07 12:01 38K
+
20260207T120122.236Z_MSC_CitypageWeather_s0000639_fr.xml 2026-02-07 12:01 38K
+
20260207T120122.236Z_MSC_CitypageWeather_s0000640_fr.xml 2026-02-07 12:01 37K
+
20260207T120122.236Z_MSC_CitypageWeather_s0000641_fr.xml 2026-02-07 12:01 38K
+
20260207T120122.236Z_MSC_CitypageWeather_s0000642_fr.xml 2026-02-07 12:01 38K
+
20260207T120123.442Z_MSC_CitypageWeather_s0000707_en.xml 2026-02-07 12:01 37K
+
20260207T120123.442Z_MSC_CitypageWeather_s0000708_en.xml 2026-02-07 12:01 37K
+
20260207T120123.442Z_MSC_CitypageWeather_s0000710_en.xml 2026-02-07 12:01 37K
+
20260207T120123.575Z_MSC_CitypageWeather_s0000707_fr.xml 2026-02-07 12:01 37K
+
20260207T120123.575Z_MSC_CitypageWeather_s0000708_fr.xml 2026-02-07 12:01 37K
+
20260207T120123.575Z_MSC_CitypageWeather_s0000710_fr.xml 2026-02-07 12:01 37K
+
20260207T120124.159Z_MSC_CitypageWeather_s0000628_en.xml 2026-02-07 12:01 35K
+
20260207T120124.217Z_MSC_CitypageWeather_s0000628_fr.xml 2026-02-07 12:01 36K
+
20260207T120125.748Z_MSC_CitypageWeather_s0000629_en.xml 2026-02-07 12:01 37K
+
20260207T120125.748Z_MSC_CitypageWeather_s0000631_en.xml 2026-02-07 12:01 37K
+
20260207T120125.748Z_MSC_CitypageWeather_s0000632_en.xml 2026-02-07 12:01 37K
+
20260207T120125.902Z_MSC_CitypageWeather_s0000629_fr.xml 2026-02-07 12:01 37K
+
20260207T120125.902Z_MSC_CitypageWeather_s0000631_fr.xml 2026-02-07 12:01 37K
+
20260207T120125.902Z_MSC_CitypageWeather_s0000632_fr.xml 2026-02-07 12:01 37K
+
20260207T120126.136Z_MSC_CitypageWeather_s0000650_en.xml 2026-02-07 12:01 36K
+
20260207T120126.136Z_MSC_CitypageWeather_s0000651_en.xml 2026-02-07 12:01 36K
+
20260207T120126.234Z_MSC_CitypageWeather_s0000650_fr.xml 2026-02-07 12:01 37K
+
20260207T120126.234Z_MSC_CitypageWeather_s0000651_fr.xml 2026-02-07 12:01 37K
+
20260207T120126.402Z_MSC_CitypageWeather_s0000691_en.xml 2026-02-07 12:01 38K
+
20260207T120126.402Z_MSC_CitypageWeather_s0000692_en.xml 2026-02-07 12:01 38K
+
20260207T120126.591Z_MSC_CitypageWeather_s0000691_fr.xml 2026-02-07 12:01 39K
+
20260207T120126.591Z_MSC_CitypageWeather_s0000692_fr.xml 2026-02-07 12:01 39K
+
20260207T120127.205Z_MSC_CitypageWeather_s0000696_en.xml 2026-02-07 12:01 36K
+
20260207T120127.205Z_MSC_CitypageWeather_s0000697_en.xml 2026-02-07 12:01 36K
+
20260207T120127.205Z_MSC_CitypageWeather_s0000698_en.xml 2026-02-07 12:01 35K
+
20260207T120127.458Z_MSC_CitypageWeather_s0000696_fr.xml 2026-02-07 12:01 37K
+
20260207T120127.458Z_MSC_CitypageWeather_s0000697_fr.xml 2026-02-07 12:01 36K
+
20260207T120127.458Z_MSC_CitypageWeather_s0000698_fr.xml 2026-02-07 12:01 36K
+
20260207T120127.975Z_MSC_CitypageWeather_s0000374_en.xml 2026-02-07 12:01 36K
+
20260207T120128.092Z_MSC_CitypageWeather_s0000374_fr.xml 2026-02-07 12:01 36K
+
20260207T120128.201Z_MSC_CitypageWeather_s0000761_en.xml 2026-02-07 12:01 36K
+
20260207T120128.201Z_MSC_CitypageWeather_s0000762_en.xml 2026-02-07 12:01 35K
+
20260207T120128.201Z_MSC_CitypageWeather_s0000764_en.xml 2026-02-07 12:01 36K
+
20260207T120128.320Z_MSC_CitypageWeather_s0000761_fr.xml 2026-02-07 12:01 37K
+
20260207T120128.320Z_MSC_CitypageWeather_s0000762_fr.xml 2026-02-07 12:01 36K
+
20260207T120128.320Z_MSC_CitypageWeather_s0000764_fr.xml 2026-02-07 12:01 37K
+
20260207T120129.744Z_MSC_CitypageWeather_s0000676_en.xml 2026-02-07 12:01 36K
+
20260207T120129.744Z_MSC_CitypageWeather_s0000677_en.xml 2026-02-07 12:01 35K
+
20260207T120129.871Z_MSC_CitypageWeather_s0000676_fr.xml 2026-02-07 12:01 37K
+
20260207T120129.871Z_MSC_CitypageWeather_s0000677_fr.xml 2026-02-07 12:01 36K
+
20260207T120130.576Z_MSC_CitypageWeather_s0000069_en.xml 2026-02-07 12:01 36K
+
20260207T120131.204Z_MSC_CitypageWeather_s0000069_fr.xml 2026-02-07 12:01 37K
+
20260207T120131.735Z_MSC_CitypageWeather_s0000691_en.xml 2026-02-07 12:01 38K
+
20260207T120131.735Z_MSC_CitypageWeather_s0000692_en.xml 2026-02-07 12:01 38K
+
20260207T120131.790Z_MSC_CitypageWeather_s0000691_fr.xml 2026-02-07 12:01 39K
+
20260207T120131.790Z_MSC_CitypageWeather_s0000692_fr.xml 2026-02-07 12:01 39K
+
20260207T120132.173Z_MSC_CitypageWeather_s0000232_en.xml 2026-02-07 12:01 36K
+
20260207T120132.173Z_MSC_CitypageWeather_s0000233_en.xml 2026-02-07 12:01 36K
+
20260207T120132.291Z_MSC_CitypageWeather_s0000232_fr.xml 2026-02-07 12:01 37K
+
20260207T120132.291Z_MSC_CitypageWeather_s0000233_fr.xml 2026-02-07 12:01 36K
+
20260207T120132.667Z_MSC_CitypageWeather_s0000325_en.xml 2026-02-07 12:01 39K
+
20260207T120132.667Z_MSC_CitypageWeather_s0000326_en.xml 2026-02-07 12:01 38K
+
20260207T120132.667Z_MSC_CitypageWeather_s0000327_en.xml 2026-02-07 12:01 38K
+
20260207T120132.667Z_MSC_CitypageWeather_s0000328_en.xml 2026-02-07 12:01 38K
+
20260207T120132.667Z_MSC_CitypageWeather_s0000329_en.xml 2026-02-07 12:01 38K
+
20260207T120132.904Z_MSC_CitypageWeather_s0000325_fr.xml 2026-02-07 12:01 39K
+
20260207T120132.904Z_MSC_CitypageWeather_s0000326_fr.xml 2026-02-07 12:01 39K
+
20260207T120132.904Z_MSC_CitypageWeather_s0000327_fr.xml 2026-02-07 12:01 39K
+
20260207T120132.904Z_MSC_CitypageWeather_s0000328_fr.xml 2026-02-07 12:01 39K
+
20260207T120132.904Z_MSC_CitypageWeather_s0000329_fr.xml 2026-02-07 12:01 39K
+
20260207T120133.465Z_MSC_CitypageWeather_s0000676_en.xml 2026-02-07 12:01 36K
+
20260207T120133.465Z_MSC_CitypageWeather_s0000677_en.xml 2026-02-07 12:01 35K
+
20260207T120133.514Z_MSC_CitypageWeather_s0000676_fr.xml 2026-02-07 12:01 37K
+
20260207T120133.514Z_MSC_CitypageWeather_s0000677_fr.xml 2026-02-07 12:01 36K
+
20260207T120133.562Z_MSC_CitypageWeather_s0000761_en.xml 2026-02-07 12:01 37K
+
20260207T120133.562Z_MSC_CitypageWeather_s0000762_en.xml 2026-02-07 12:01 35K
+
20260207T120133.562Z_MSC_CitypageWeather_s0000764_en.xml 2026-02-07 12:01 36K
+
20260207T120133.639Z_MSC_CitypageWeather_s0000761_fr.xml 2026-02-07 12:01 37K
+
20260207T120133.639Z_MSC_CitypageWeather_s0000762_fr.xml 2026-02-07 12:01 36K
+
20260207T120133.639Z_MSC_CitypageWeather_s0000764_fr.xml 2026-02-07 12:01 37K
+
20260207T120136.411Z_MSC_CitypageWeather_s0000424_en.xml 2026-02-07 12:01 37K
+
20260207T120136.411Z_MSC_CitypageWeather_s0000425_en.xml 2026-02-07 12:01 38K
+
20260207T120136.411Z_MSC_CitypageWeather_s0000426_en.xml 2026-02-07 12:01 37K
+
20260207T120136.517Z_MSC_CitypageWeather_s0000424_fr.xml 2026-02-07 12:01 38K
+
20260207T120136.517Z_MSC_CitypageWeather_s0000425_fr.xml 2026-02-07 12:01 39K
+
20260207T120136.517Z_MSC_CitypageWeather_s0000426_fr.xml 2026-02-07 12:01 38K
+
20260207T120139.492Z_MSC_CitypageWeather_s0000724_en.xml 2026-02-07 12:01 38K
+
20260207T120139.492Z_MSC_CitypageWeather_s0000725_en.xml 2026-02-07 12:01 38K
+
20260207T120139.492Z_MSC_CitypageWeather_s0000726_en.xml 2026-02-07 12:01 38K
+
20260207T120139.492Z_MSC_CitypageWeather_s0000727_en.xml 2026-02-07 12:01 38K
+
20260207T120139.492Z_MSC_CitypageWeather_s0000728_en.xml 2026-02-07 12:01 38K
+
20260207T120139.618Z_MSC_CitypageWeather_s0000724_fr.xml 2026-02-07 12:01 39K
+
20260207T120139.618Z_MSC_CitypageWeather_s0000725_fr.xml 2026-02-07 12:01 39K
+
20260207T120139.618Z_MSC_CitypageWeather_s0000726_fr.xml 2026-02-07 12:01 39K
+
20260207T120139.618Z_MSC_CitypageWeather_s0000727_fr.xml 2026-02-07 12:01 39K
+
20260207T120139.618Z_MSC_CitypageWeather_s0000728_fr.xml 2026-02-07 12:01 39K
+
20260207T120139.808Z_MSC_CitypageWeather_s0000826_en.xml 2026-02-07 12:01 36K
+
20260207T120139.851Z_MSC_CitypageWeather_s0000826_fr.xml 2026-02-07 12:01 36K
+
20260207T120147.835Z_MSC_CitypageWeather_s0000548_en.xml 2026-02-07 12:01 37K
+
20260207T120147.835Z_MSC_CitypageWeather_s0000549_en.xml 2026-02-07 12:01 37K
+
20260207T120147.928Z_MSC_CitypageWeather_s0000548_fr.xml 2026-02-07 12:01 38K
+
20260207T120147.928Z_MSC_CitypageWeather_s0000549_fr.xml 2026-02-07 12:01 38K
+
20260207T120148.018Z_MSC_CitypageWeather_s0000747_en.xml 2026-02-07 12:01 36K
+
20260207T120148.018Z_MSC_CitypageWeather_s0000748_en.xml 2026-02-07 12:01 37K
+
20260207T120148.089Z_MSC_CitypageWeather_s0000747_fr.xml 2026-02-07 12:01 37K
+
20260207T120148.089Z_MSC_CitypageWeather_s0000748_fr.xml 2026-02-07 12:01 38K
+
20260207T120148.161Z_MSC_CitypageWeather_s0000231_en.xml 2026-02-07 12:01 36K
+
20260207T120148.194Z_MSC_CitypageWeather_s0000231_fr.xml 2026-02-07 12:01 36K
+
20260207T120150.484Z_MSC_CitypageWeather_s0000071_en.xml 2026-02-07 12:01 36K
+
20260207T120150.649Z_MSC_CitypageWeather_s0000071_fr.xml 2026-02-07 12:01 37K
+
20260207T120153.235Z_MSC_CitypageWeather_s0000023_en.xml 2026-02-07 12:02 36K
+
20260207T120153.276Z_MSC_CitypageWeather_s0000023_fr.xml 2026-02-07 12:02 37K
+
20260207T120153.480Z_MSC_CitypageWeather_s0000072_en.xml 2026-02-07 12:02 36K
+
20260207T120153.480Z_MSC_CitypageWeather_s0000077_en.xml 2026-02-07 12:02 36K
+
20260207T120153.480Z_MSC_CitypageWeather_s0000434_en.xml 2026-02-07 12:02 37K
+
20260207T120153.480Z_MSC_CitypageWeather_s0000435_en.xml 2026-02-07 12:02 37K
+
20260207T120153.480Z_MSC_CitypageWeather_s0000436_en.xml 2026-02-07 12:02 37K
+
20260207T120153.708Z_MSC_CitypageWeather_s0000072_fr.xml 2026-02-07 12:02 37K
+
20260207T120153.708Z_MSC_CitypageWeather_s0000077_fr.xml 2026-02-07 12:02 37K
+
20260207T120153.708Z_MSC_CitypageWeather_s0000434_fr.xml 2026-02-07 12:02 37K
+
20260207T120153.708Z_MSC_CitypageWeather_s0000435_fr.xml 2026-02-07 12:02 37K
+
20260207T120153.708Z_MSC_CitypageWeather_s0000436_fr.xml 2026-02-07 12:02 38K
+
20260207T120153.926Z_MSC_CitypageWeather_s0000437_en.xml 2026-02-07 12:02 36K
+
20260207T120153.960Z_MSC_CitypageWeather_s0000437_fr.xml 2026-02-07 12:02 37K
+
20260207T120154.081Z_MSC_CitypageWeather_s0000073_en.xml 2026-02-07 12:02 36K
+
20260207T120154.081Z_MSC_CitypageWeather_s0000074_en.xml 2026-02-07 12:02 36K
+
20260207T120154.081Z_MSC_CitypageWeather_s0000075_en.xml 2026-02-07 12:02 36K
+
20260207T120154.216Z_MSC_CitypageWeather_s0000073_fr.xml 2026-02-07 12:02 37K
+
20260207T120154.216Z_MSC_CitypageWeather_s0000074_fr.xml 2026-02-07 12:02 37K
+
20260207T120154.216Z_MSC_CitypageWeather_s0000075_fr.xml 2026-02-07 12:02 37K
+
20260207T120205.167Z_MSC_CitypageWeather_s0000428_en.xml 2026-02-07 12:02 36K
+
20260207T120205.205Z_MSC_CitypageWeather_s0000428_fr.xml 2026-02-07 12:02 36K
+
20260207T120207.885Z_MSC_CitypageWeather_s0000680_en.xml 2026-02-07 12:02 37K
+
20260207T120207.885Z_MSC_CitypageWeather_s0000843_en.xml 2026-02-07 12:02 37K
+
20260207T120207.961Z_MSC_CitypageWeather_s0000680_fr.xml 2026-02-07 12:02 38K
+
20260207T120207.961Z_MSC_CitypageWeather_s0000843_fr.xml 2026-02-07 12:02 38K
+
20260207T120210.405Z_MSC_CitypageWeather_s0000455_en.xml 2026-02-07 12:02 38K
+
20260207T120210.451Z_MSC_CitypageWeather_s0000455_fr.xml 2026-02-07 12:02 39K
+
20260207T120210.675Z_MSC_CitypageWeather_s0000367_en.xml 2026-02-07 12:02 36K
+
20260207T120210.675Z_MSC_CitypageWeather_s0000368_en.xml 2026-02-07 12:02 36K
+
20260207T120210.758Z_MSC_CitypageWeather_s0000367_fr.xml 2026-02-07 12:02 37K
+
20260207T120210.758Z_MSC_CitypageWeather_s0000368_fr.xml 2026-02-07 12:02 37K
+
20260207T120211.358Z_MSC_CitypageWeather_s0000251_en.xml 2026-02-07 12:02 37K
+
20260207T120211.408Z_MSC_CitypageWeather_s0000251_fr.xml 2026-02-07 12:02 37K
+
20260207T120221.954Z_MSC_CitypageWeather_s0000418_en.xml 2026-02-07 12:02 35K
+
20260207T120221.954Z_MSC_CitypageWeather_s0000419_en.xml 2026-02-07 12:02 37K
+
20260207T120222.043Z_MSC_CitypageWeather_s0000418_fr.xml 2026-02-07 12:02 36K
+
20260207T120222.043Z_MSC_CitypageWeather_s0000419_fr.xml 2026-02-07 12:02 37K
+
20260207T120222.347Z_MSC_CitypageWeather_s0000451_en.xml 2026-02-07 12:02 37K
+
20260207T120222.347Z_MSC_CitypageWeather_s0000452_en.xml 2026-02-07 12:02 37K
+
20260207T120222.448Z_MSC_CitypageWeather_s0000451_fr.xml 2026-02-07 12:02 38K
+
20260207T120222.448Z_MSC_CitypageWeather_s0000452_fr.xml 2026-02-07 12:02 37K
+
20260207T120223.004Z_MSC_CitypageWeather_s0000550_en.xml 2026-02-07 12:02 37K
+
20260207T120223.050Z_MSC_CitypageWeather_s0000550_fr.xml 2026-02-07 12:02 38K
+
20260207T120223.502Z_MSC_CitypageWeather_s0000763_en.xml 2026-02-07 12:02 36K
+
20260207T120223.539Z_MSC_CitypageWeather_s0000763_fr.xml 2026-02-07 12:02 36K
+
20260207T120223.577Z_MSC_CitypageWeather_s0000469_en.xml 2026-02-07 12:02 38K
+
20260207T120223.577Z_MSC_CitypageWeather_s0000470_en.xml 2026-02-07 12:02 38K
+
20260207T120223.660Z_MSC_CitypageWeather_s0000469_fr.xml 2026-02-07 12:02 39K
+
20260207T120223.660Z_MSC_CitypageWeather_s0000470_fr.xml 2026-02-07 12:02 39K
+
20260207T120223.753Z_MSC_CitypageWeather_s0000103_en.xml 2026-02-07 12:02 36K
+
20260207T120223.753Z_MSC_CitypageWeather_s0000105_en.xml 2026-02-07 12:02 36K
+
20260207T120223.839Z_MSC_CitypageWeather_s0000103_fr.xml 2026-02-07 12:02 37K
+
20260207T120223.839Z_MSC_CitypageWeather_s0000105_fr.xml 2026-02-07 12:02 37K
+
20260207T120225.159Z_MSC_CitypageWeather_s0000528_en.xml 2026-02-07 12:02 37K
+
20260207T120225.159Z_MSC_CitypageWeather_s0000529_en.xml 2026-02-07 12:02 37K
+
20260207T120225.159Z_MSC_CitypageWeather_s0000530_en.xml 2026-02-07 12:02 37K
+
20260207T120225.159Z_MSC_CitypageWeather_s0000531_en.xml 2026-02-07 12:02 37K
+
20260207T120225.356Z_MSC_CitypageWeather_s0000528_fr.xml 2026-02-07 12:02 37K
+
20260207T120225.356Z_MSC_CitypageWeather_s0000529_fr.xml 2026-02-07 12:02 37K
+
20260207T120225.356Z_MSC_CitypageWeather_s0000530_fr.xml 2026-02-07 12:02 38K
+
20260207T120225.356Z_MSC_CitypageWeather_s0000531_fr.xml 2026-02-07 12:02 37K
+
20260207T120226.518Z_MSC_CitypageWeather_s0000582_en.xml 2026-02-07 12:02 37K
+
20260207T120226.518Z_MSC_CitypageWeather_s0000584_en.xml 2026-02-07 12:02 37K
+
20260207T120226.518Z_MSC_CitypageWeather_s0000773_en.xml 2026-02-07 12:02 37K
+
20260207T120226.630Z_MSC_CitypageWeather_s0000582_fr.xml 2026-02-07 12:02 37K
+
20260207T120226.630Z_MSC_CitypageWeather_s0000584_fr.xml 2026-02-07 12:02 37K
+
20260207T120226.630Z_MSC_CitypageWeather_s0000773_fr.xml 2026-02-07 12:02 37K
+
20260207T120228.362Z_MSC_CitypageWeather_s0000235_en.xml 2026-02-07 12:02 38K
+
20260207T120228.362Z_MSC_CitypageWeather_s0000236_en.xml 2026-02-07 12:02 38K
+
20260207T120228.362Z_MSC_CitypageWeather_s0000237_en.xml 2026-02-07 12:02 38K
+
20260207T120228.362Z_MSC_CitypageWeather_s0000238_en.xml 2026-02-07 12:02 38K
+
20260207T120228.362Z_MSC_CitypageWeather_s0000240_en.xml 2026-02-07 12:02 38K
+
20260207T120228.597Z_MSC_CitypageWeather_s0000235_fr.xml 2026-02-07 12:02 39K
+
20260207T120228.597Z_MSC_CitypageWeather_s0000236_fr.xml 2026-02-07 12:02 39K
+
20260207T120228.597Z_MSC_CitypageWeather_s0000237_fr.xml 2026-02-07 12:02 39K
+
20260207T120228.597Z_MSC_CitypageWeather_s0000238_fr.xml 2026-02-07 12:02 39K
+
20260207T120228.597Z_MSC_CitypageWeather_s0000240_fr.xml 2026-02-07 12:02 39K
+
20260207T120228.829Z_MSC_CitypageWeather_s0000127_en.xml 2026-02-07 12:02 36K
+
20260207T120228.874Z_MSC_CitypageWeather_s0000127_fr.xml 2026-02-07 12:02 37K
+
20260207T120238.436Z_MSC_CitypageWeather_s0000700_en.xml 2026-02-07 12:02 37K
+
20260207T120238.436Z_MSC_CitypageWeather_s0000701_en.xml 2026-02-07 12:02 37K
+
20260207T120238.436Z_MSC_CitypageWeather_s0000702_en.xml 2026-02-07 12:03 37K
+
20260207T120238.436Z_MSC_CitypageWeather_s0000703_en.xml 2026-02-07 12:02 37K
+
20260207T120238.436Z_MSC_CitypageWeather_s0000704_en.xml 2026-02-07 12:03 37K
+
20260207T120238.621Z_MSC_CitypageWeather_s0000700_fr.xml 2026-02-07 12:02 37K
+
20260207T120238.621Z_MSC_CitypageWeather_s0000701_fr.xml 2026-02-07 12:03 37K
+
20260207T120238.621Z_MSC_CitypageWeather_s0000702_fr.xml 2026-02-07 12:02 38K
+
20260207T120238.621Z_MSC_CitypageWeather_s0000703_fr.xml 2026-02-07 12:03 37K
+
20260207T120238.621Z_MSC_CitypageWeather_s0000704_fr.xml 2026-02-07 12:03 37K
+
20260207T120240.742Z_MSC_CitypageWeather_s0000104_en.xml 2026-02-07 12:02 36K
+
20260207T120240.780Z_MSC_CitypageWeather_s0000104_fr.xml 2026-02-07 12:02 37K
+
20260207T120252.049Z_MSC_CitypageWeather_s0000431_en.xml 2026-02-07 12:03 36K
+
20260207T120252.088Z_MSC_CitypageWeather_s0000431_fr.xml 2026-02-07 12:03 37K
+
20260207T120253.001Z_MSC_CitypageWeather_s0000169_en.xml 2026-02-07 12:03 36K
+
20260207T120253.050Z_MSC_CitypageWeather_s0000169_fr.xml 2026-02-07 12:03 37K
+
20260207T120255.032Z_MSC_CitypageWeather_s0000108_en.xml 2026-02-07 12:03 38K
+
20260207T120255.032Z_MSC_CitypageWeather_s0000429_en.xml 2026-02-07 12:03 38K
+
20260207T120255.032Z_MSC_CitypageWeather_s0000489_en.xml 2026-02-07 12:03 38K
+
20260207T120255.158Z_MSC_CitypageWeather_s0000108_fr.xml 2026-02-07 12:03 39K
+
20260207T120255.158Z_MSC_CitypageWeather_s0000429_fr.xml 2026-02-07 12:03 39K
+
20260207T120255.158Z_MSC_CitypageWeather_s0000489_fr.xml 2026-02-07 12:03 39K
+
20260207T120305.479Z_MSC_CitypageWeather_s0000705_en.xml 2026-02-07 12:03 36K
+
20260207T120305.479Z_MSC_CitypageWeather_s0000706_en.xml 2026-02-07 12:03 36K
+
20260207T120305.555Z_MSC_CitypageWeather_s0000705_fr.xml 2026-02-07 12:03 37K
+
20260207T120305.555Z_MSC_CitypageWeather_s0000706_fr.xml 2026-02-07 12:03 37K
+
20260207T120307.995Z_MSC_CitypageWeather_s0000517_en.xml 2026-02-07 12:03 35K
+
20260207T120308.045Z_MSC_CitypageWeather_s0000517_fr.xml 2026-02-07 12:03 36K
+
20260207T120312.670Z_MSC_CitypageWeather_s0000076_en.xml 2026-02-07 12:03 38K
+
20260207T120312.703Z_MSC_CitypageWeather_s0000076_fr.xml 2026-02-07 12:03 39K
+
20260207T120312.743Z_MSC_CitypageWeather_s0000281_en.xml 2026-02-07 12:03 37K
+
20260207T120312.743Z_MSC_CitypageWeather_s0000414_en.xml 2026-02-07 12:03 37K
+
20260207T120312.743Z_MSC_CitypageWeather_s0000415_en.xml 2026-02-07 12:03 38K
+
20260207T120312.872Z_MSC_CitypageWeather_s0000281_fr.xml 2026-02-07 12:03 37K
+
20260207T120312.872Z_MSC_CitypageWeather_s0000414_fr.xml 2026-02-07 12:03 37K
+
20260207T120312.872Z_MSC_CitypageWeather_s0000415_fr.xml 2026-02-07 12:03 39K
+
20260207T120323.523Z_MSC_CitypageWeather_s0000301_en.xml 2026-02-07 12:03 36K
+
20260207T120323.523Z_MSC_CitypageWeather_s0000302_en.xml 2026-02-07 12:03 36K
+
20260207T120323.523Z_MSC_CitypageWeather_s0000303_en.xml 2026-02-07 12:03 36K
+
20260207T120323.523Z_MSC_CitypageWeather_s0000304_en.xml 2026-02-07 12:03 36K
+
20260207T120323.523Z_MSC_CitypageWeather_s0000305_en.xml 2026-02-07 12:03 37K
+
20260207T120323.760Z_MSC_CitypageWeather_s0000301_fr.xml 2026-02-07 12:03 37K
+
20260207T120323.760Z_MSC_CitypageWeather_s0000302_fr.xml 2026-02-07 12:03 37K
+
20260207T120323.760Z_MSC_CitypageWeather_s0000303_fr.xml 2026-02-07 12:03 37K
+
20260207T120323.760Z_MSC_CitypageWeather_s0000304_fr.xml 2026-02-07 12:03 37K
+
20260207T120323.760Z_MSC_CitypageWeather_s0000305_fr.xml 2026-02-07 12:03 37K
+
20260207T120324.150Z_MSC_CitypageWeather_s0000168_en.xml 2026-02-07 12:03 36K
+
20260207T120324.203Z_MSC_CitypageWeather_s0000168_fr.xml 2026-02-07 12:03 37K
+
20260207T120324.794Z_MSC_CitypageWeather_s0000165_en.xml 2026-02-07 12:03 38K
+
20260207T120324.794Z_MSC_CitypageWeather_s0000166_en.xml 2026-02-07 12:03 38K
+
20260207T120324.879Z_MSC_CitypageWeather_s0000165_fr.xml 2026-02-07 12:03 39K
+
20260207T120324.879Z_MSC_CitypageWeather_s0000166_fr.xml 2026-02-07 12:03 39K
+
20260207T120326.004Z_MSC_CitypageWeather_s0000266_en.xml 2026-02-07 12:03 36K
+
20260207T120326.004Z_MSC_CitypageWeather_s0000267_en.xml 2026-02-07 12:03 36K
+
20260207T120326.077Z_MSC_CitypageWeather_s0000266_fr.xml 2026-02-07 12:03 37K
+
20260207T120326.077Z_MSC_CitypageWeather_s0000267_fr.xml 2026-02-07 12:03 36K
+
20260207T120334.963Z_MSC_CitypageWeather_s0000571_en.xml 2026-02-07 12:04 38K
+
20260207T120335.008Z_MSC_CitypageWeather_s0000571_fr.xml 2026-02-07 12:04 39K
+
20260207T120407.043Z_MSC_CitypageWeather_s0000422_en.xml 2026-02-07 12:04 38K
+
20260207T120407.081Z_MSC_CitypageWeather_s0000422_fr.xml 2026-02-07 12:04 39K
+
20260207T120410.902Z_MSC_CitypageWeather_s0000070_en.xml 2026-02-07 12:04 36K
+
20260207T120410.951Z_MSC_CitypageWeather_s0000070_fr.xml 2026-02-07 12:04 37K
+
20260207T120421.782Z_MSC_CitypageWeather_s0000458_en.xml 2026-02-07 12:04 37K
+
20260207T120421.782Z_MSC_CitypageWeather_s0000658_en.xml 2026-02-07 12:05 37K
+
20260207T120421.782Z_MSC_CitypageWeather_s0000786_en.xml 2026-02-07 12:04 37K
+
20260207T120421.782Z_MSC_CitypageWeather_s0000787_en.xml 2026-02-07 12:05 38K
+
20260207T120421.782Z_MSC_CitypageWeather_s0000789_en.xml 2026-02-07 12:04 37K
+
20260207T120421.980Z_MSC_CitypageWeather_s0000458_fr.xml 2026-02-07 12:05 37K
+
20260207T120421.980Z_MSC_CitypageWeather_s0000658_fr.xml 2026-02-07 12:04 37K
+
20260207T120421.980Z_MSC_CitypageWeather_s0000786_fr.xml 2026-02-07 12:05 37K
+
20260207T120421.980Z_MSC_CitypageWeather_s0000787_fr.xml 2026-02-07 12:04 39K
+
20260207T120421.980Z_MSC_CitypageWeather_s0000789_fr.xml 2026-02-07 12:04 37K
+
20260207T120503.727Z_MSC_CitypageWeather_s0000729_en.xml 2026-02-07 12:05 36K
+
20260207T120503.727Z_MSC_CitypageWeather_s0000730_en.xml 2026-02-07 12:05 36K
+
20260207T120503.727Z_MSC_CitypageWeather_s0000731_en.xml 2026-02-07 12:05 37K
+
20260207T120503.727Z_MSC_CitypageWeather_s0000732_en.xml 2026-02-07 12:05 36K
+
20260207T120503.926Z_MSC_CitypageWeather_s0000729_fr.xml 2026-02-07 12:05 37K
+
20260207T120503.926Z_MSC_CitypageWeather_s0000730_fr.xml 2026-02-07 12:05 37K
+
20260207T120503.926Z_MSC_CitypageWeather_s0000731_fr.xml 2026-02-07 12:05 37K
+
20260207T120503.926Z_MSC_CitypageWeather_s0000732_fr.xml 2026-02-07 12:05 37K
+
20260207T120504.127Z_MSC_CitypageWeather_s0000430_en.xml 2026-02-07 12:05 37K
+
20260207T120504.127Z_MSC_CitypageWeather_s0000623_en.xml 2026-02-07 12:05 37K
+
20260207T120504.217Z_MSC_CitypageWeather_s0000430_fr.xml 2026-02-07 12:05 38K
+
20260207T120504.217Z_MSC_CitypageWeather_s0000623_fr.xml 2026-02-07 12:05 38K
+
20260207T120504.532Z_MSC_CitypageWeather_s0000025_en.xml 2026-02-07 12:05 34K
+
20260207T120504.532Z_MSC_CitypageWeather_s0000025_fr.xml 2026-02-07 12:05 35K
+
20260207T120504.532Z_MSC_CitypageWeather_s0000088_en.xml 2026-02-07 12:05 34K
+
20260207T120504.532Z_MSC_CitypageWeather_s0000088_fr.xml 2026-02-07 12:05 35K
+
20260207T120504.532Z_MSC_CitypageWeather_s0000239_en.xml 2026-02-07 12:05 36K
+
20260207T120504.532Z_MSC_CitypageWeather_s0000239_fr.xml 2026-02-07 12:05 37K
+
20260207T120504.532Z_MSC_CitypageWeather_s0000282_en.xml 2026-02-07 12:05 36K
+
20260207T120504.532Z_MSC_CitypageWeather_s0000282_fr.xml 2026-02-07 12:05 37K
+
20260207T120504.532Z_MSC_CitypageWeather_s0000283_en.xml 2026-02-07 12:05 36K
+
20260207T120504.532Z_MSC_CitypageWeather_s0000283_fr.xml 2026-02-07 12:05 37K
+
20260207T120504.532Z_MSC_CitypageWeather_s0000479_en.xml 2026-02-07 12:05 37K
+
20260207T120504.532Z_MSC_CitypageWeather_s0000479_fr.xml 2026-02-07 12:05 38K
+
20260207T120504.532Z_MSC_CitypageWeather_s0000630_en.xml 2026-02-07 12:05 37K
+
20260207T120504.532Z_MSC_CitypageWeather_s0000630_fr.xml 2026-02-07 12:05 37K
+
20260207T120504.532Z_MSC_CitypageWeather_s0000815_en.xml 2026-02-07 12:05 36K
+
20260207T120504.532Z_MSC_CitypageWeather_s0000815_fr.xml 2026-02-07 12:05 37K
+
20260207T120611.878Z_MSC_CitypageWeather_s0000528_en.xml 2026-02-07 12:07 37K
+
20260207T120611.878Z_MSC_CitypageWeather_s0000529_en.xml 2026-02-07 12:07 37K
+
20260207T120611.878Z_MSC_CitypageWeather_s0000530_en.xml 2026-02-07 12:07 37K
+
20260207T120611.878Z_MSC_CitypageWeather_s0000531_en.xml 2026-02-07 12:07 37K
+
20260207T120611.965Z_MSC_CitypageWeather_s0000528_fr.xml 2026-02-07 12:06 38K
+
20260207T120611.965Z_MSC_CitypageWeather_s0000529_fr.xml 2026-02-07 12:07 37K
+
20260207T120611.965Z_MSC_CitypageWeather_s0000530_fr.xml 2026-02-07 12:07 38K
+
20260207T120611.965Z_MSC_CitypageWeather_s0000531_fr.xml 2026-02-07 12:07 38K
+
20260207T120612.072Z_MSC_CitypageWeather_s0000479_en.xml 2026-02-07 12:07 37K
+
20260207T120612.109Z_MSC_CitypageWeather_s0000479_fr.xml 2026-02-07 12:07 38K
+
20260207T120622.544Z_MSC_CitypageWeather_s0000630_en.xml 2026-02-07 12:07 37K
+
20260207T120622.567Z_MSC_CitypageWeather_s0000630_fr.xml 2026-02-07 12:07 37K
+
20260207T120622.795Z_MSC_CitypageWeather_s0000782_en.xml 2026-02-07 12:07 36K
+
20260207T120622.821Z_MSC_CitypageWeather_s0000782_fr.xml 2026-02-07 12:07 37K
+
20260207T120723.672Z_MSC_CitypageWeather_s0000588_en.xml 2026-02-07 12:08 36K
+
20260207T120723.699Z_MSC_CitypageWeather_s0000588_fr.xml 2026-02-07 12:08 36K
+
20260207T120740.860Z_MSC_CitypageWeather_s0000691_en.xml 2026-02-07 12:08 38K
+
20260207T120740.860Z_MSC_CitypageWeather_s0000692_en.xml 2026-02-07 12:08 38K
+
20260207T120740.911Z_MSC_CitypageWeather_s0000691_fr.xml 2026-02-07 12:08 39K
+
20260207T120740.911Z_MSC_CitypageWeather_s0000692_fr.xml 2026-02-07 12:08 39K
+
20260207T121451.572Z_MSC_CitypageWeather_s0000458_en.xml 2026-02-07 12:15 37K
+
20260207T121451.572Z_MSC_CitypageWeather_s0000658_en.xml 2026-02-07 12:15 37K
+
20260207T121451.572Z_MSC_CitypageWeather_s0000786_en.xml 2026-02-07 12:15 37K
+
20260207T121451.572Z_MSC_CitypageWeather_s0000787_en.xml 2026-02-07 12:15 38K
+
20260207T121451.572Z_MSC_CitypageWeather_s0000789_en.xml 2026-02-07 12:15 37K
+
20260207T121451.691Z_MSC_CitypageWeather_s0000458_fr.xml 2026-02-07 12:15 37K
+
20260207T121451.691Z_MSC_CitypageWeather_s0000658_fr.xml 2026-02-07 12:15 37K
+
20260207T121451.691Z_MSC_CitypageWeather_s0000786_fr.xml 2026-02-07 12:15 37K
+
20260207T121451.691Z_MSC_CitypageWeather_s0000787_fr.xml 2026-02-07 12:15 39K
+
20260207T121451.691Z_MSC_CitypageWeather_s0000789_fr.xml 2026-02-07 12:15 37K
+
20260207T122801.995Z_MSC_CitypageWeather_s0000430_en.xml 2026-02-07 12:28 37K
+
20260207T122801.995Z_MSC_CitypageWeather_s0000623_en.xml 2026-02-07 12:28 37K
+
20260207T122802.053Z_MSC_CitypageWeather_s0000430_fr.xml 2026-02-07 12:28 38K
+
20260207T122802.053Z_MSC_CitypageWeather_s0000623_fr.xml 2026-02-07 12:28 38K
+
20260207T124745.464Z_MSC_CitypageWeather_s0000752_en.xml 2026-02-07 12:47 36K
+
20260207T124745.464Z_MSC_CitypageWeather_s0000753_en.xml 2026-02-07 12:47 36K
+
20260207T124745.526Z_MSC_CitypageWeather_s0000752_fr.xml 2026-02-07 12:47 37K
+
20260207T124745.526Z_MSC_CitypageWeather_s0000753_fr.xml 2026-02-07 12:47 37K
+
20260207T124815.922Z_MSC_CitypageWeather_s0000458_en.xml 2026-02-07 12:48 37K
+
20260207T124815.922Z_MSC_CitypageWeather_s0000658_en.xml 2026-02-07 12:48 37K
+
20260207T124815.922Z_MSC_CitypageWeather_s0000786_en.xml 2026-02-07 12:48 37K
+
20260207T124815.922Z_MSC_CitypageWeather_s0000787_en.xml 2026-02-07 12:48 38K
+
20260207T124815.922Z_MSC_CitypageWeather_s0000789_en.xml 2026-02-07 12:48 37K
+
20260207T124816.077Z_MSC_CitypageWeather_s0000458_fr.xml 2026-02-07 12:48 37K
+
20260207T124816.077Z_MSC_CitypageWeather_s0000658_fr.xml 2026-02-07 12:48 37K
+
20260207T124816.077Z_MSC_CitypageWeather_s0000786_fr.xml 2026-02-07 12:48 37K
+
20260207T124816.077Z_MSC_CitypageWeather_s0000787_fr.xml 2026-02-07 12:48 39K
+
20260207T124816.077Z_MSC_CitypageWeather_s0000789_fr.xml 2026-02-07 12:48 37K
+
+
+
diff --git a/tests/mocks/weather_onecall_current.json b/tests/mocks/weather_onecall_current.json
new file mode 100644
index 00000000..73b88d7a
--- /dev/null
+++ b/tests/mocks/weather_onecall_current.json
@@ -0,0 +1,28 @@
+{
+ "lat": 48.14,
+ "lon": 11.58,
+ "timezone": "Europe/Berlin",
+ "timezone_offset": 0,
+ "current": {
+ "dt": 1547387400,
+ "sunrise": 1547362817,
+ "sunset": 1547394301,
+ "temp": 1.49,
+ "feels_like": -5.6,
+ "pressure": 1005,
+ "humidity": 93.7,
+ "uvi": 0,
+ "clouds": 75,
+ "visibility": 7000,
+ "wind_speed": 11.8,
+ "wind_deg": 250,
+ "weather": [
+ {
+ "id": 615,
+ "main": "Snow",
+ "description": "light rain and snow",
+ "icon": "13d"
+ }
+ ]
+ }
+}
diff --git a/tests/mocks/weather_onecall_forecast.json b/tests/mocks/weather_onecall_forecast.json
new file mode 100644
index 00000000..aa70f6e5
--- /dev/null
+++ b/tests/mocks/weather_onecall_forecast.json
@@ -0,0 +1,149 @@
+{
+ "lat": 48.14,
+ "lon": 11.58,
+ "timezone": "Europe/Berlin",
+ "timezone_offset": 3600,
+ "daily": [
+ {
+ "dt": 1568372400,
+ "sunrise": 1568350044,
+ "sunset": 1568395948,
+ "temp": {
+ "day": 24.44,
+ "min": 15.35,
+ "max": 24.44,
+ "night": 15.35,
+ "eve": 18,
+ "morn": 23.03
+ },
+ "pressure": 1031,
+ "humidity": 70,
+ "wind_speed": 3.35,
+ "wind_deg": 314,
+ "weather": [
+ {
+ "id": 801,
+ "main": "Clouds",
+ "description": "few clouds",
+ "icon": "02d"
+ }
+ ],
+ "clouds": 21,
+ "pop": 0,
+ "uvi": 5
+ },
+ {
+ "dt": 1568458800,
+ "sunrise": 1568436525,
+ "sunset": 1568482223,
+ "temp": {
+ "day": 20.81,
+ "min": 13.56,
+ "max": 21.02,
+ "night": 13.56,
+ "eve": 16.6,
+ "morn": 15.88
+ },
+ "pressure": 1028,
+ "humidity": 72,
+ "wind_speed": 2.78,
+ "wind_deg": 266,
+ "weather": [
+ {
+ "id": 500,
+ "main": "Rain",
+ "description": "light rain",
+ "icon": "10d"
+ }
+ ],
+ "clouds": 21,
+ "pop": 0.56,
+ "rain": 2.51,
+ "uvi": 4.5
+ },
+ {
+ "dt": 1568545200,
+ "sunrise": 1568523006,
+ "sunset": 1568568498,
+ "temp": {
+ "day": 22.93,
+ "min": 13.78,
+ "max": 22.93,
+ "night": 13.78,
+ "eve": 17.21,
+ "morn": 14.56
+ },
+ "pressure": 1024,
+ "humidity": 59,
+ "wind_speed": 2.17,
+ "wind_deg": 255,
+ "weather": [
+ {
+ "id": 800,
+ "main": "Clear",
+ "description": "clear sky",
+ "icon": "01d"
+ }
+ ],
+ "clouds": 0,
+ "pop": 0,
+ "uvi": 5.2
+ },
+ {
+ "dt": 1568631600,
+ "sunrise": 1568609487,
+ "sunset": 1568654774,
+ "temp": {
+ "day": 23.39,
+ "min": 13.93,
+ "max": 23.39,
+ "night": 13.93,
+ "eve": 17.98,
+ "morn": 15.05
+ },
+ "pressure": 1023,
+ "humidity": 57,
+ "wind_speed": 1.93,
+ "wind_deg": 236,
+ "weather": [
+ {
+ "id": 800,
+ "main": "Clear",
+ "description": "clear sky",
+ "icon": "01d"
+ }
+ ],
+ "clouds": 0,
+ "pop": 0,
+ "uvi": 5.1
+ },
+ {
+ "dt": 1568718000,
+ "sunrise": 1568695968,
+ "sunset": 1568741049,
+ "temp": {
+ "day": 20.64,
+ "min": 10.87,
+ "max": 20.64,
+ "night": 10.87,
+ "eve": 15.21,
+ "morn": 13.67
+ },
+ "pressure": 1021,
+ "humidity": 64,
+ "wind_speed": 2.44,
+ "wind_deg": 284,
+ "weather": [
+ {
+ "id": 800,
+ "main": "Clear",
+ "description": "clear sky",
+ "icon": "01d"
+ }
+ ],
+ "clouds": 3,
+ "pop": 0,
+ "uvi": 4.9
+ }
+ ]
+}
diff --git a/tests/mocks/weather_hourly.json b/tests/mocks/weather_onecall_hourly.json
similarity index 99%
rename from tests/mocks/weather_hourly.json
rename to tests/mocks/weather_onecall_hourly.json
index b0b2e662..bcf2b806 100644
--- a/tests/mocks/weather_hourly.json
+++ b/tests/mocks/weather_onecall_hourly.json
@@ -1,7 +1,11 @@
{
+ "lat": 48.14,
+ "lon": 11.58,
+ "timezone": "Europe/Berlin",
+ "timezone_offset": 3600,
"hourly": [
{
- "dt": 1673204400,
+ "dt": 1673200800,
"temp": 27.31,
"feels_like": 29.59,
"pressure": 1013,
@@ -24,7 +28,7 @@
"pop": 0
},
{
- "dt": 1673208000,
+ "dt": 1673204400,
"temp": 27.31,
"feels_like": 29.69,
"pressure": 1013,
@@ -47,7 +51,7 @@
"pop": 0
},
{
- "dt": 1673211600,
+ "dt": 1673208000,
"temp": 27.29,
"feels_like": 29.65,
"pressure": 1013,
@@ -70,7 +74,7 @@
"pop": 0.12
},
{
- "dt": 1673215200,
+ "dt": 1673211600,
"temp": 27.21,
"feels_like": 29.6,
"pressure": 1013,
@@ -96,7 +100,7 @@
}
},
{
- "dt": 1673218800,
+ "dt": 1673215200,
"temp": 27.1,
"feels_like": 29.39,
"pressure": 1014,
@@ -122,7 +126,7 @@
}
},
{
- "dt": 1673222400,
+ "dt": 1673218800,
"temp": 26.95,
"feels_like": 29.19,
"pressure": 1013,
@@ -145,7 +149,7 @@
"pop": 0.52
},
{
- "dt": 1673226000,
+ "dt": 1673222400,
"temp": 26.72,
"feels_like": 28.83,
"pressure": 1012,
@@ -168,7 +172,7 @@
"pop": 0.08
},
{
- "dt": 1673229600,
+ "dt": 1673226000,
"temp": 26.57,
"feels_like": 26.57,
"pressure": 1012,
@@ -191,7 +195,7 @@
"pop": 0.08
},
{
- "dt": 1673233200,
+ "dt": 1673229600,
"temp": 26.46,
"feels_like": 26.46,
"pressure": 1011,
@@ -214,7 +218,7 @@
"pop": 0.04
},
{
- "dt": 1673236800,
+ "dt": 1673233200,
"temp": 26.38,
"feels_like": 26.38,
"pressure": 1011,
@@ -237,7 +241,7 @@
"pop": 0
},
{
- "dt": 1673240400,
+ "dt": 1673236800,
"temp": 26.32,
"feels_like": 26.32,
"pressure": 1012,
@@ -260,7 +264,7 @@
"pop": 0
},
{
- "dt": 1673244000,
+ "dt": 1673240400,
"temp": 26.32,
"feels_like": 26.32,
"pressure": 1012,
@@ -283,7 +287,7 @@
"pop": 0
},
{
- "dt": 1673247600,
+ "dt": 1673244000,
"temp": 26.44,
"feels_like": 26.44,
"pressure": 1013,
@@ -306,7 +310,7 @@
"pop": 0
},
{
- "dt": 1673251200,
+ "dt": 1673247600,
"temp": 26.45,
"feels_like": 26.45,
"pressure": 1013,
@@ -329,7 +333,7 @@
"pop": 0
},
{
- "dt": 1673254800,
+ "dt": 1673251200,
"temp": 26.54,
"feels_like": 26.54,
"pressure": 1014,
@@ -352,7 +356,7 @@
"pop": 0
},
{
- "dt": 1673258400,
+ "dt": 1673254800,
"temp": 26.61,
"feels_like": 26.61,
"pressure": 1013,
@@ -375,7 +379,7 @@
"pop": 0
},
{
- "dt": 1673262000,
+ "dt": 1673258400,
"temp": 26.76,
"feels_like": 28.9,
"pressure": 1013,
@@ -398,7 +402,7 @@
"pop": 0
},
{
- "dt": 1673265600,
+ "dt": 1673262000,
"temp": 26.91,
"feels_like": 29.11,
"pressure": 1012,
@@ -421,7 +425,7 @@
"pop": 0
},
{
- "dt": 1673269200,
+ "dt": 1673265600,
"temp": 27.04,
"feels_like": 29.27,
"pressure": 1011,
@@ -444,7 +448,7 @@
"pop": 0
},
{
- "dt": 1673272800,
+ "dt": 1673269200,
"temp": 27.12,
"feels_like": 29.33,
"pressure": 1011,
@@ -467,7 +471,7 @@
"pop": 0
},
{
- "dt": 1673276400,
+ "dt": 1673272800,
"temp": 27.17,
"feels_like": 29.33,
"pressure": 1010,
@@ -490,7 +494,7 @@
"pop": 0
},
{
- "dt": 1673280000,
+ "dt": 1673276400,
"temp": 27.28,
"feels_like": 29.43,
"pressure": 1011,
@@ -513,7 +517,7 @@
"pop": 0
},
{
- "dt": 1673283600,
+ "dt": 1673280000,
"temp": 27.28,
"feels_like": 29.43,
"pressure": 1011,
@@ -536,7 +540,7 @@
"pop": 0
},
{
- "dt": 1673287200,
+ "dt": 1673283600,
"temp": 27.34,
"feels_like": 29.54,
"pressure": 1012,
@@ -559,7 +563,7 @@
"pop": 0
},
{
- "dt": 1673290800,
+ "dt": 1673287200,
"temp": 27.25,
"feels_like": 29.38,
"pressure": 1013,
@@ -582,7 +586,7 @@
"pop": 0
},
{
- "dt": 1673294400,
+ "dt": 1673290800,
"temp": 27.25,
"feels_like": 29.38,
"pressure": 1014,
@@ -605,7 +609,7 @@
"pop": 0
},
{
- "dt": 1673298000,
+ "dt": 1673294400,
"temp": 27.17,
"feels_like": 29.24,
"pressure": 1015,
@@ -628,7 +632,7 @@
"pop": 0
},
{
- "dt": 1673301600,
+ "dt": 1673298000,
"temp": 27.07,
"feels_like": 29.06,
"pressure": 1015,
@@ -651,7 +655,7 @@
"pop": 0
},
{
- "dt": 1673305200,
+ "dt": 1673301600,
"temp": 26.99,
"feels_like": 29.09,
"pressure": 1014,
@@ -674,7 +678,7 @@
"pop": 0
},
{
- "dt": 1673308800,
+ "dt": 1673305200,
"temp": 26.83,
"feels_like": 28.8,
"pressure": 1014,
@@ -697,7 +701,7 @@
"pop": 0
},
{
- "dt": 1673312400,
+ "dt": 1673308800,
"temp": 26.68,
"feels_like": 28.54,
"pressure": 1013,
@@ -720,7 +724,7 @@
"pop": 0
},
{
- "dt": 1673316000,
+ "dt": 1673312400,
"temp": 26.54,
"feels_like": 26.54,
"pressure": 1013,
@@ -743,7 +747,7 @@
"pop": 0
},
{
- "dt": 1673319600,
+ "dt": 1673316000,
"temp": 26.54,
"feels_like": 26.54,
"pressure": 1012,
@@ -766,7 +770,7 @@
"pop": 0
},
{
- "dt": 1673323200,
+ "dt": 1673319600,
"temp": 26.43,
"feels_like": 26.43,
"pressure": 1012,
@@ -789,7 +793,7 @@
"pop": 0
},
{
- "dt": 1673326800,
+ "dt": 1673323200,
"temp": 26.38,
"feels_like": 26.38,
"pressure": 1013,
@@ -812,7 +816,7 @@
"pop": 0
},
{
- "dt": 1673330400,
+ "dt": 1673326800,
"temp": 26.36,
"feels_like": 26.36,
"pressure": 1013,
@@ -835,7 +839,7 @@
"pop": 0
},
{
- "dt": 1673334000,
+ "dt": 1673330400,
"temp": 26.45,
"feels_like": 26.45,
"pressure": 1014,
@@ -858,7 +862,7 @@
"pop": 0
},
{
- "dt": 1673337600,
+ "dt": 1673334000,
"temp": 26.54,
"feels_like": 26.54,
"pressure": 1014,
@@ -881,7 +885,7 @@
"pop": 0
},
{
- "dt": 1673341200,
+ "dt": 1673337600,
"temp": 26.63,
"feels_like": 26.63,
"pressure": 1014,
@@ -904,7 +908,7 @@
"pop": 0
},
{
- "dt": 1673344800,
+ "dt": 1673341200,
"temp": 26.62,
"feels_like": 26.62,
"pressure": 1014,
@@ -927,7 +931,7 @@
"pop": 0
},
{
- "dt": 1673348400,
+ "dt": 1673344800,
"temp": 26.71,
"feels_like": 28.81,
"pressure": 1014,
@@ -950,7 +954,7 @@
"pop": 0
},
{
- "dt": 1673352000,
+ "dt": 1673348400,
"temp": 26.81,
"feels_like": 29,
"pressure": 1013,
@@ -973,7 +977,7 @@
"pop": 0
},
{
- "dt": 1673355600,
+ "dt": 1673352000,
"temp": 26.91,
"feels_like": 29.19,
"pressure": 1012,
@@ -996,7 +1000,7 @@
"pop": 0
},
{
- "dt": 1673359200,
+ "dt": 1673355600,
"temp": 27.02,
"feels_like": 29.32,
"pressure": 1012,
@@ -1019,7 +1023,7 @@
"pop": 0
},
{
- "dt": 1673362800,
+ "dt": 1673359200,
"temp": 27.03,
"feels_like": 29.25,
"pressure": 1011,
@@ -1042,7 +1046,7 @@
"pop": 0
},
{
- "dt": 1673366400,
+ "dt": 1673362800,
"temp": 27.12,
"feels_like": 29.42,
"pressure": 1011,
@@ -1065,7 +1069,7 @@
"pop": 0
},
{
- "dt": 1673370000,
+ "dt": 1673366400,
"temp": 27.1,
"feels_like": 29.29,
"pressure": 1012,
@@ -1088,7 +1092,7 @@
"pop": 0
},
{
- "dt": 1673373600,
+ "dt": 1673370000,
"temp": 27.18,
"feels_like": 29.54,
"pressure": 1012,
diff --git a/tests/mocks/weather_openmeteo_current.json b/tests/mocks/weather_openmeteo_current.json
new file mode 100644
index 00000000..478ee1d1
--- /dev/null
+++ b/tests/mocks/weather_openmeteo_current.json
@@ -0,0 +1,218 @@
+{
+ "latitude": 40.78858,
+ "longitude": -73.9661,
+ "generationtime_ms": 0.7585287094116211,
+ "utc_offset_seconds": -18000,
+ "timezone": "America/New_York",
+ "timezone_abbreviation": "GMT-5",
+ "elevation": 20.0,
+ "current_units": { "time": "iso8601", "interval": "seconds", "temperature_2m": "°C", "relative_humidity_2m": "%", "weather_code": "wmo code", "wind_speed_10m": "km/h", "wind_direction_10m": "°" },
+ "current": { "time": "2026-02-06T16:30", "interval": 900, "temperature_2m": -1.4, "relative_humidity_2m": 60, "weather_code": 3, "wind_speed_10m": 4.8, "wind_direction_10m": 138 },
+ "hourly_units": { "time": "iso8601", "temperature_2m": "°C", "precipitation": "mm", "weather_code": "wmo code", "wind_speed_10m": "km/h" },
+ "hourly": {
+ "time": [
+ "2026-02-06T00:00",
+ "2026-02-06T01:00",
+ "2026-02-06T02:00",
+ "2026-02-06T03:00",
+ "2026-02-06T04:00",
+ "2026-02-06T05:00",
+ "2026-02-06T06:00",
+ "2026-02-06T07:00",
+ "2026-02-06T08:00",
+ "2026-02-06T09:00",
+ "2026-02-06T10:00",
+ "2026-02-06T11:00",
+ "2026-02-06T12:00",
+ "2026-02-06T13:00",
+ "2026-02-06T14:00",
+ "2026-02-06T15:00",
+ "2026-02-06T16:00",
+ "2026-02-06T17:00",
+ "2026-02-06T18:00",
+ "2026-02-06T19:00",
+ "2026-02-06T20:00",
+ "2026-02-06T21:00",
+ "2026-02-06T22:00",
+ "2026-02-06T23:00",
+ "2026-02-07T00:00",
+ "2026-02-07T01:00",
+ "2026-02-07T02:00",
+ "2026-02-07T03:00",
+ "2026-02-07T04:00",
+ "2026-02-07T05:00",
+ "2026-02-07T06:00",
+ "2026-02-07T07:00",
+ "2026-02-07T08:00",
+ "2026-02-07T09:00",
+ "2026-02-07T10:00",
+ "2026-02-07T11:00",
+ "2026-02-07T12:00",
+ "2026-02-07T13:00",
+ "2026-02-07T14:00",
+ "2026-02-07T15:00",
+ "2026-02-07T16:00",
+ "2026-02-07T17:00",
+ "2026-02-07T18:00",
+ "2026-02-07T19:00",
+ "2026-02-07T20:00",
+ "2026-02-07T21:00",
+ "2026-02-07T22:00",
+ "2026-02-07T23:00",
+ "2026-02-08T00:00",
+ "2026-02-08T01:00",
+ "2026-02-08T02:00",
+ "2026-02-08T03:00",
+ "2026-02-08T04:00",
+ "2026-02-08T05:00",
+ "2026-02-08T06:00",
+ "2026-02-08T07:00",
+ "2026-02-08T08:00",
+ "2026-02-08T09:00",
+ "2026-02-08T10:00",
+ "2026-02-08T11:00",
+ "2026-02-08T12:00",
+ "2026-02-08T13:00",
+ "2026-02-08T14:00",
+ "2026-02-08T15:00",
+ "2026-02-08T16:00",
+ "2026-02-08T17:00",
+ "2026-02-08T18:00",
+ "2026-02-08T19:00",
+ "2026-02-08T20:00",
+ "2026-02-08T21:00",
+ "2026-02-08T22:00",
+ "2026-02-08T23:00",
+ "2026-02-09T00:00",
+ "2026-02-09T01:00",
+ "2026-02-09T02:00",
+ "2026-02-09T03:00",
+ "2026-02-09T04:00",
+ "2026-02-09T05:00",
+ "2026-02-09T06:00",
+ "2026-02-09T07:00",
+ "2026-02-09T08:00",
+ "2026-02-09T09:00",
+ "2026-02-09T10:00",
+ "2026-02-09T11:00",
+ "2026-02-09T12:00",
+ "2026-02-09T13:00",
+ "2026-02-09T14:00",
+ "2026-02-09T15:00",
+ "2026-02-09T16:00",
+ "2026-02-09T17:00",
+ "2026-02-09T18:00",
+ "2026-02-09T19:00",
+ "2026-02-09T20:00",
+ "2026-02-09T21:00",
+ "2026-02-09T22:00",
+ "2026-02-09T23:00",
+ "2026-02-10T00:00",
+ "2026-02-10T01:00",
+ "2026-02-10T02:00",
+ "2026-02-10T03:00",
+ "2026-02-10T04:00",
+ "2026-02-10T05:00",
+ "2026-02-10T06:00",
+ "2026-02-10T07:00",
+ "2026-02-10T08:00",
+ "2026-02-10T09:00",
+ "2026-02-10T10:00",
+ "2026-02-10T11:00",
+ "2026-02-10T12:00",
+ "2026-02-10T13:00",
+ "2026-02-10T14:00",
+ "2026-02-10T15:00",
+ "2026-02-10T16:00",
+ "2026-02-10T17:00",
+ "2026-02-10T18:00",
+ "2026-02-10T19:00",
+ "2026-02-10T20:00",
+ "2026-02-10T21:00",
+ "2026-02-10T22:00",
+ "2026-02-10T23:00",
+ "2026-02-11T00:00",
+ "2026-02-11T01:00",
+ "2026-02-11T02:00",
+ "2026-02-11T03:00",
+ "2026-02-11T04:00",
+ "2026-02-11T05:00",
+ "2026-02-11T06:00",
+ "2026-02-11T07:00",
+ "2026-02-11T08:00",
+ "2026-02-11T09:00",
+ "2026-02-11T10:00",
+ "2026-02-11T11:00",
+ "2026-02-11T12:00",
+ "2026-02-11T13:00",
+ "2026-02-11T14:00",
+ "2026-02-11T15:00",
+ "2026-02-11T16:00",
+ "2026-02-11T17:00",
+ "2026-02-11T18:00",
+ "2026-02-11T19:00",
+ "2026-02-11T20:00",
+ "2026-02-11T21:00",
+ "2026-02-11T22:00",
+ "2026-02-11T23:00",
+ "2026-02-12T00:00",
+ "2026-02-12T01:00",
+ "2026-02-12T02:00",
+ "2026-02-12T03:00",
+ "2026-02-12T04:00",
+ "2026-02-12T05:00",
+ "2026-02-12T06:00",
+ "2026-02-12T07:00",
+ "2026-02-12T08:00",
+ "2026-02-12T09:00",
+ "2026-02-12T10:00",
+ "2026-02-12T11:00",
+ "2026-02-12T12:00",
+ "2026-02-12T13:00",
+ "2026-02-12T14:00",
+ "2026-02-12T15:00",
+ "2026-02-12T16:00",
+ "2026-02-12T17:00",
+ "2026-02-12T18:00",
+ "2026-02-12T19:00",
+ "2026-02-12T20:00",
+ "2026-02-12T21:00",
+ "2026-02-12T22:00",
+ "2026-02-12T23:00"
+ ],
+ "temperature_2m": [
+ -7.1, -7.1, -8.5, -8.8, -9.0, -7.7, -9.2, -8.8, -8.9, -5.9, -3.4, -2.4, -1.3, -0.8, -0.5, -0.2, -0.7, -2.1, -3.2, -3.7, -4.4, -5.3, -6.2, -6.8, -6.5, -6.3, -6.5, -6.3, -5.8, -5.3, -8.5, -11.2, -12.7, -13.6, -13.9, -13.8, -13.5, -13.2,
+ -12.9, -13.0, -13.2, -14.0, -15.2, -16.1, -16.9, -17.4, -17.5, -17.7, -18.1, -18.5, -18.9, -19.4, -20.0, -20.5, -21.0, -21.5, -20.2, -18.3, -16.4, -14.2, -12.5, -10.8, -9.3, -8.9, -10.0, -10.6, -11.2, -11.8, -12.5, -12.9, -13.4, -13.9,
+ -14.9, -15.7, -16.6, -17.0, -17.3, -17.5, -17.7, -18.1, -15.5, -12.6, -10.5, -8.6, -7.1, -5.8, -4.9, -4.4, -4.1, -4.9, -7.1, -9.1, -9.7, -6.9, -6.5, -6.4, -6.1, -7.2, -9.6, -10.1, -10.5, -10.8, -10.8, -11.0, -9.1, -6.7, -4.8, -3.1, -2.3,
+ -1.7, -1.2, -0.8, -0.7, -1.1, -1.8, -1.7, -1.7, -1.9, -4.7, -5.3, -5.3, -5.1, -5.1, -4.8, -5.0, -1.9, -1.2, -0.3, 0.4, 0.6, 0.8, 0.8, 0.6, 0.5, 0.5, 0.6, 0.8, 1.3, 1.9, 2.0, 1.3, 0.1, -0.9, -1.3, -1.6, -1.8, -2.0, -2.3, -2.6, -3.2, -3.8,
+ -3.9, -3.1, -1.8, -0.8, -0.3, -0.1, 0.0, 0.0, -0.1, -0.5, -1.3, -2.4, -3.3, -4.0, -4.5, -5.0, -5.3
+ ],
+ "precipitation": [
+ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.4, 1.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.3, 0.3, 0.3, 0.0, 0.0, 0.0, 0.0,
+ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
+ ],
+ "weather_code": [
+ 0, 0, 0, 0, 2, 0, 3, 3, 3, 0, 3, 3, 3, 1, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 71, 71, 3, 3, 3, 3, 3, 51, 3, 3, 3, 3, 3, 3, 3, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3, 3, 3, 1, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 1, 3, 3, 3, 3, 3, 3, 3, 56, 71, 3, 3, 45, 45, 45, 45, 51, 51, 51, 3, 3, 3, 3, 3, 3, 3, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 2, 3, 3, 3, 3, 3, 3, 2, 3, 3, 3, 2
+ ],
+ "wind_speed_10m": [
+ 4.3, 9.3, 8.1, 3.3, 11.3, 8.2, 8.8, 7.2, 3.6, 7.2, 5.4, 4.7, 5.0, 1.5, 1.1, 3.9, 4.9, 5.8, 6.5, 5.8, 7.1, 9.3, 8.5, 6.6, 6.6, 6.9, 6.9, 7.5, 8.9, 12.0, 25.8, 27.3, 27.3, 27.0, 28.5, 30.5, 30.8, 30.0, 29.3, 28.3, 27.8, 27.5, 26.3, 24.5,
+ 25.7, 22.9, 21.9, 19.4, 18.7, 18.4, 21.0, 19.0, 19.1, 18.5, 17.0, 13.8, 13.3, 18.1, 18.6, 19.7, 20.4, 20.5, 20.9, 21.7, 24.2, 22.2, 20.2, 18.8, 15.9, 13.8, 12.8, 11.2, 7.9, 5.9, 4.9, 4.6, 4.3, 3.2, 2.9, 3.0, 5.2, 6.9, 7.5, 6.6, 6.6, 5.2,
+ 4.1, 5.3, 2.2, 1.9, 2.6, 1.1, 2.2, 4.0, 3.9, 5.2, 4.0, 2.2, 5.0, 4.4, 4.5, 4.7, 4.2, 5.8, 5.8, 7.9, 6.8, 6.0, 5.4, 4.2, 3.4, 3.5, 1.1, 2.8, 5.3, 5.8, 6.1, 4.9, 4.8, 3.3, 3.7, 2.2, 1.0, 1.4, 4.0, 4.4, 3.7, 6.9, 7.6, 7.3, 6.6, 5.5, 4.1,
+ 3.9, 4.9, 6.0, 7.3, 9.7, 14.1, 17.1, 16.9, 15.1, 14.0, 14.7, 16.4, 17.4, 18.0, 18.1, 17.6, 15.5, 12.9, 11.9, 13.2, 15.8, 18.2, 19.0, 19.2, 19.2, 19.5, 19.7, 19.7, 19.0, 18.0, 17.4, 17.4, 17.6, 17.9, 18.1
+ ]
+ },
+ "daily_units": { "time": "iso8601", "weather_code": "wmo code", "temperature_2m_max": "°C", "temperature_2m_min": "°C", "sunrise": "iso8601", "sunset": "iso8601", "precipitation_sum": "mm" },
+ "daily": {
+ "time": ["2026-02-06", "2026-02-07", "2026-02-08", "2026-02-09", "2026-02-10", "2026-02-11", "2026-02-12"],
+ "weather_code": [3, 71, 3, 3, 3, 71, 3],
+ "temperature_2m_max": [-0.2, -5.3, -8.9, -4.1, -0.7, 2.0, 0.0],
+ "temperature_2m_min": [-9.2, -17.7, -21.5, -18.1, -11.0, -5.3, -5.3],
+ "sunrise": ["2026-02-06T07:00", "2026-02-07T06:59", "2026-02-08T06:58", "2026-02-09T06:56", "2026-02-10T06:55", "2026-02-11T06:54", "2026-02-12T06:53"],
+ "sunset": ["2026-02-06T17:19", "2026-02-07T17:20", "2026-02-08T17:21", "2026-02-09T17:23", "2026-02-10T17:24", "2026-02-11T17:25", "2026-02-12T17:26"],
+ "precipitation_sum": [0.0, 0.4, 0.0, 0.0, 0.0, 2.6, 0.0]
+ }
+}
diff --git a/tests/mocks/weather_openmeteo_current_weather.json b/tests/mocks/weather_openmeteo_current_weather.json
new file mode 100644
index 00000000..ba5f1831
--- /dev/null
+++ b/tests/mocks/weather_openmeteo_current_weather.json
@@ -0,0 +1,84 @@
+{
+ "latitude": 48.14,
+ "longitude": 11.58,
+ "generationtime_ms": 0.3949403762817383,
+ "utc_offset_seconds": 3600,
+ "timezone": "Europe/Berlin",
+ "timezone_abbreviation": "GMT+1",
+ "elevation": 524.0,
+ "current_weather_units": {
+ "time": "unixtime",
+ "interval": "seconds",
+ "temperature": "°C",
+ "windspeed": "km/h",
+ "winddirection": "°",
+ "is_day": "",
+ "weathercode": "wmo code"
+ },
+ "current_weather": {
+ "time": 1770477300,
+ "interval": 900,
+ "temperature": 8.5,
+ "windspeed": 4.7,
+ "winddirection": 9,
+ "is_day": 1,
+ "weathercode": 2
+ },
+ "hourly_units": {
+ "time": "unixtime",
+ "temperature_2m": "°C",
+ "windspeed_10m": "km/h",
+ "winddirection_10m": "°",
+ "relativehumidity_2m": "%"
+ },
+ "hourly": {
+ "time": [
+ 1770418800, 1770422400, 1770426000, 1770429600, 1770433200, 1770436800, 1770440400, 1770444000, 1770447600, 1770451200, 1770454800, 1770458400, 1770462000, 1770465600, 1770469200, 1770472800, 1770476400, 1770480000, 1770483600,
+ 1770487200, 1770490800, 1770494400, 1770498000, 1770501600, 1770505200, 1770508800, 1770512400, 1770516000, 1770519600, 1770523200, 1770526800, 1770530400, 1770534000, 1770537600, 1770541200, 1770544800, 1770548400, 1770552000,
+ 1770555600, 1770559200, 1770562800, 1770566400, 1770570000, 1770573600, 1770577200, 1770580800, 1770584400, 1770588000, 1770591600, 1770595200, 1770598800, 1770602400, 1770606000, 1770609600, 1770613200, 1770616800, 1770620400,
+ 1770624000, 1770627600, 1770631200, 1770634800, 1770638400, 1770642000, 1770645600, 1770649200, 1770652800, 1770656400, 1770660000, 1770663600, 1770667200, 1770670800, 1770674400, 1770678000, 1770681600, 1770685200, 1770688800,
+ 1770692400, 1770696000, 1770699600, 1770703200, 1770706800, 1770710400, 1770714000, 1770717600, 1770721200, 1770724800, 1770728400, 1770732000, 1770735600, 1770739200, 1770742800, 1770746400, 1770750000, 1770753600, 1770757200,
+ 1770760800, 1770764400, 1770768000, 1770771600, 1770775200, 1770778800, 1770782400, 1770786000, 1770789600, 1770793200, 1770796800, 1770800400, 1770804000, 1770807600, 1770811200, 1770814800, 1770818400, 1770822000, 1770825600,
+ 1770829200, 1770832800, 1770836400, 1770840000, 1770843600, 1770847200, 1770850800, 1770854400, 1770858000, 1770861600, 1770865200, 1770868800, 1770872400, 1770876000, 1770879600, 1770883200, 1770886800, 1770890400, 1770894000,
+ 1770897600, 1770901200, 1770904800, 1770908400, 1770912000, 1770915600, 1770919200, 1770922800, 1770926400, 1770930000, 1770933600, 1770937200, 1770940800, 1770944400, 1770948000, 1770951600, 1770955200, 1770958800, 1770962400,
+ 1770966000, 1770969600, 1770973200, 1770976800, 1770980400, 1770984000, 1770987600, 1770991200, 1770994800, 1770998400, 1771002000, 1771005600, 1771009200, 1771012800, 1771016400, 1771020000
+ ],
+ "temperature_2m": [
+ 6.4, 6.6, 6.3, 5.8, 5.7, 5.1, 5.0, 5.5, 5.2, 5.3, 6.2, 7.0, 7.9, 9.1, 9.5, 9.0, 8.6, 8.2, 7.2, 6.4, 5.5, 5.1, 4.7, 4.9, 4.5, 4.5, 4.5, 4.7, 3.8, 3.1, 3.2, 3.0, 3.6, 3.8, 3.5, 4.3, 5.2, 6.2, 6.6, 6.8, 6.4, 5.5, 4.7, 4.7, 4.3, 4.2, 4.1,
+ 3.9, 3.6, 3.4, 3.2, 3.0, 2.9, 2.8, 2.7, 2.6, 2.5, 2.8, 3.1, 3.7, 4.3, 4.6, 4.7, 4.7, 4.4, 4.0, 3.5, 3.0, 2.5, 1.9, 1.2, 0.7, 0.3, 0.0, -0.1, -0.4, -0.8, -1.1, -1.3, -1.2, -1.2, -1.0, 0.2, 1.9, 3.3, 5.0, 6.1, 6.8, 7.0, 6.4, 5.2, 4.2, 3.6,
+ 3.1, 2.8, 2.5, 2.2, 2.2, 2.3, 2.6, 2.9, 3.0, 3.0, 3.4, 4.7, 6.3, 7.7, 8.5, 9.0, 9.3, 9.2, 8.9, 8.6, 8.3, 8.1, 7.9, 7.6, 7.4, 7.2, 7.1, 7.0, 6.9, 6.7, 6.4, 6.2, 5.6, 5.2, 4.9, 6.1, 6.4, 6.6, 6.9, 7.1, 7.2, 7.2, 7.0, 6.8, 6.4, 5.9, 5.5,
+ 5.4, 5.3, 5.2, 5.0, 4.8, 4.6, 4.5, 4.5, 4.6, 4.6, 4.6, 4.8, 5.2, 5.8, 6.4, 7.2, 8.1, 8.6, 8.3, 7.6, 7.0, 6.5, 6.2, 5.8, 5.5, 5.2, 5.0, 4.9
+ ],
+ "windspeed_10m": [
+ 9.4, 9.5, 9.2, 9.1, 7.9, 6.6, 6.8, 7.6, 6.7, 6.0, 5.9, 5.9, 6.6, 4.5, 7.9, 7.7, 5.4, 4.2, 3.3, 1.4, 2.6, 1.6, 2.2, 1.5, 0.8, 2.3, 2.3, 1.3, 2.5, 1.8, 1.6, 1.1, 1.8, 2.9, 5.6, 9.1, 9.0, 7.8, 9.0, 9.8, 9.7, 9.8, 10.4, 9.1, 7.9, 8.2, 7.6,
+ 6.0, 6.2, 5.3, 5.0, 5.5, 6.2, 5.9, 6.2, 6.5, 5.9, 5.4, 6.2, 5.9, 6.7, 6.5, 6.2, 6.2, 5.8, 5.5, 4.7, 4.2, 3.2, 3.4, 3.2, 2.7, 2.9, 3.7, 2.9, 3.4, 3.2, 3.6, 3.1, 3.6, 3.8, 4.6, 4.8, 4.3, 5.5, 5.3, 5.2, 4.9, 4.4, 3.2, 2.2, 2.0, 2.2, 3.0,
+ 3.4, 3.6, 4.0, 4.9, 5.2, 5.2, 5.2, 5.5, 5.8, 6.5, 9.0, 13.2, 16.9, 19.3, 20.8, 21.7, 22.3, 22.1, 22.0, 21.5, 21.2, 20.9, 20.2, 20.0, 19.3, 18.9, 18.2, 17.4, 16.4, 15.3, 14.2, 12.8, 11.7, 11.2, 21.7, 21.5, 21.5, 22.1, 23.0, 23.7, 23.8,
+ 23.6, 23.0, 22.0, 20.5, 19.5, 19.2, 19.3, 19.3, 19.5, 19.5, 20.0, 20.9, 21.9, 23.2, 24.7, 26.1, 26.9, 26.3, 25.4, 24.6, 25.0, 25.6, 26.1, 25.5, 24.4, 22.9, 20.5, 17.9, 15.9, 14.8, 14.3, 14.2, 14.8
+ ],
+ "winddirection_10m": [
+ 247, 241, 244, 252, 240, 229, 245, 251, 234, 245, 256, 256, 261, 284, 300, 332, 356, 59, 84, 90, 164, 207, 189, 284, 243, 198, 321, 304, 172, 180, 207, 180, 79, 30, 45, 72, 74, 68, 74, 73, 75, 54, 56, 56, 66, 67, 82, 57, 69, 62, 60, 58,
+ 69, 79, 83, 87, 101, 98, 97, 95, 88, 89, 97, 97, 97, 113, 122, 121, 117, 108, 117, 113, 120, 119, 120, 122, 117, 127, 135, 135, 131, 129, 117, 95, 79, 62, 56, 54, 55, 63, 90, 135, 171, 194, 198, 180, 153, 144, 146, 155, 164, 169, 173,
+ 186, 209, 225, 232, 237, 242, 246, 247, 248, 249, 249, 249, 249, 248, 247, 246, 246, 245, 246, 244, 240, 240, 240, 242, 245, 249, 249, 249, 251, 253, 253, 252, 251, 250, 249, 246, 245, 244, 243, 243, 242, 242, 242, 243, 245, 246, 247,
+ 247, 247, 247, 245, 245, 247, 250, 252, 254, 254, 254, 252, 248, 245, 244, 245, 246, 247
+ ],
+ "relativehumidity_2m": [
+ 83, 81, 81, 84, 83, 85, 86, 88, 89, 89, 85, 82, 77, 65, 62, 68, 71, 73, 81, 87, 91, 91, 93, 93, 94, 94, 94, 94, 99, 97, 94, 93, 94, 95, 96, 91, 86, 79, 77, 77, 76, 81, 85, 82, 89, 88, 87, 87, 89, 90, 90, 91, 92, 93, 94, 94, 95, 93, 89,
+ 83, 80, 75, 75, 75, 76, 79, 82, 83, 86, 90, 93, 93, 93, 95, 95, 95, 95, 97, 98, 99, 99, 98, 92, 84, 79, 73, 69, 67, 67, 69, 73, 77, 80, 83, 85, 87, 88, 87, 83, 76, 73, 76, 81, 85, 84, 82, 79, 76, 74, 72, 72, 72, 73, 73, 73, 74, 75, 77,
+ 78, 77, 75, 74, 73, 73, 74, 78, 84, 87, 81, 80, 78, 77, 77, 77, 77, 77, 78, 80, 82, 84, 85, 86, 86, 86, 87, 87, 87, 88, 88, 88, 88, 86, 82, 78, 73, 69, 65, 63, 64, 68, 72, 76, 81, 84, 85, 85, 85, 85
+ ]
+ },
+ "daily_units": {
+ "time": "unixtime",
+ "temperature_2m_max": "°C",
+ "temperature_2m_min": "°C",
+ "sunrise": "unixtime",
+ "sunset": "unixtime"
+ },
+ "daily": {
+ "time": [1770418800, 1770505200, 1770591600, 1770678000, 1770764400, 1770850800, 1770937200],
+ "temperature_2m_max": [9.5, 6.8, 4.7, 7.0, 9.3, 7.2, 8.6],
+ "temperature_2m_min": [4.7, 3.0, 0.7, -1.3, 2.2, 4.9, 4.5],
+ "sunrise": [1770445978, 1770532288, 1770618596, 1770704904, 1770791211, 1770877515, 1770963818],
+ "sunset": [1770481348, 1770567844, 1770654340, 1770740836, 1770827331, 1770913826, 1771000321]
+ }
+}
diff --git a/tests/mocks/weather_owm_onecall.json b/tests/mocks/weather_owm_onecall.json
new file mode 100644
index 00000000..0696e347
--- /dev/null
+++ b/tests/mocks/weather_owm_onecall.json
@@ -0,0 +1,970 @@
+{
+ "lat": 40.7767,
+ "lon": -73.9713,
+ "timezone": "America/New_York",
+ "timezone_offset": -18000,
+ "current": {
+ "dt": 1770414297,
+ "sunrise": 1770379257,
+ "sunset": 1770416341,
+ "temp": -0.27,
+ "feels_like": -3.9,
+ "pressure": 1004,
+ "humidity": 54,
+ "dew_point": -7.54,
+ "uvi": 0,
+ "clouds": 75,
+ "visibility": 10000,
+ "wind_speed": 3.09,
+ "wind_deg": 220,
+ "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04d" }]
+ },
+ "hourly": [
+ {
+ "dt": 1770411600,
+ "temp": -0.66,
+ "feels_like": -3.52,
+ "pressure": 1004,
+ "humidity": 61,
+ "dew_point": -6.5,
+ "uvi": 0.18,
+ "clouds": 80,
+ "visibility": 10000,
+ "wind_speed": 2.24,
+ "wind_deg": 187,
+ "wind_gust": 3.73,
+ "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04d" }],
+ "pop": 0
+ },
+ {
+ "dt": 1770415200,
+ "temp": -0.27,
+ "feels_like": -2.6,
+ "pressure": 1004,
+ "humidity": 54,
+ "dew_point": -7.54,
+ "uvi": 0,
+ "clouds": 75,
+ "visibility": 10000,
+ "wind_speed": 1.87,
+ "wind_deg": 169,
+ "wind_gust": 3.26,
+ "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04d" }],
+ "pop": 0
+ },
+ {
+ "dt": 1770418800,
+ "temp": -1.03,
+ "feels_like": -3.4,
+ "pressure": 1004,
+ "humidity": 62,
+ "dew_point": -6.67,
+ "uvi": 0,
+ "clouds": 80,
+ "visibility": 10000,
+ "wind_speed": 1.81,
+ "wind_deg": 190,
+ "wind_gust": 3.93,
+ "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04n" }],
+ "pop": 0
+ },
+ {
+ "dt": 1770422400,
+ "temp": -1.54,
+ "feels_like": -5.39,
+ "pressure": 1004,
+ "humidity": 71,
+ "dew_point": -5.59,
+ "uvi": 0,
+ "clouds": 85,
+ "wind_speed": 3.04,
+ "wind_deg": 232,
+ "wind_gust": 6.25,
+ "weather": [{ "id": 600, "main": "Snow", "description": "light snow", "icon": "13n" }],
+ "pop": 0.2,
+ "snow": { "1h": 0.13 }
+ },
+ {
+ "dt": 1770426000,
+ "temp": -2.25,
+ "feels_like": -5.2,
+ "pressure": 1004,
+ "humidity": 80,
+ "dew_point": -4.89,
+ "uvi": 0,
+ "clouds": 90,
+ "visibility": 235,
+ "wind_speed": 2.09,
+ "wind_deg": 224,
+ "wind_gust": 6.04,
+ "weather": [{ "id": 600, "main": "Snow", "description": "light snow", "icon": "13n" }],
+ "pop": 1,
+ "snow": { "1h": 0.18 }
+ },
+ {
+ "dt": 1770429600,
+ "temp": -2.79,
+ "feels_like": -6.29,
+ "pressure": 1003,
+ "humidity": 89,
+ "dew_point": -4.17,
+ "uvi": 0,
+ "clouds": 95,
+ "visibility": 177,
+ "wind_speed": 2.47,
+ "wind_deg": 217,
+ "wind_gust": 6.99,
+ "weather": [{ "id": 600, "main": "Snow", "description": "light snow", "icon": "13n" }],
+ "pop": 1,
+ "snow": { "1h": 0.19 }
+ },
+ {
+ "dt": 1770433200,
+ "temp": -3.46,
+ "feels_like": -7.71,
+ "pressure": 1002,
+ "humidity": 96,
+ "dew_point": -4.21,
+ "uvi": 0,
+ "clouds": 100,
+ "visibility": 501,
+ "wind_speed": 3.05,
+ "wind_deg": 236,
+ "wind_gust": 7.82,
+ "weather": [{ "id": 600, "main": "Snow", "description": "light snow", "icon": "13n" }],
+ "pop": 1,
+ "snow": { "1h": 0.19 }
+ },
+ {
+ "dt": 1770436800,
+ "temp": -3.88,
+ "feels_like": -7.67,
+ "pressure": 1001,
+ "humidity": 97,
+ "dew_point": -4.47,
+ "uvi": 0,
+ "clouds": 100,
+ "visibility": 424,
+ "wind_speed": 2.54,
+ "wind_deg": 234,
+ "wind_gust": 7.49,
+ "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }],
+ "pop": 0.8
+ },
+ {
+ "dt": 1770440400,
+ "temp": -3.78,
+ "feels_like": -7.68,
+ "pressure": 1001,
+ "humidity": 96,
+ "dew_point": -4.57,
+ "uvi": 0,
+ "clouds": 100,
+ "visibility": 2576,
+ "wind_speed": 2.66,
+ "wind_deg": 231,
+ "wind_gust": 7.51,
+ "weather": [{ "id": 600, "main": "Snow", "description": "light snow", "icon": "13n" }],
+ "pop": 1,
+ "snow": { "1h": 0.14 }
+ },
+ {
+ "dt": 1770444000,
+ "temp": -4.1,
+ "feels_like": -8.05,
+ "pressure": 1000,
+ "humidity": 96,
+ "dew_point": -4.92,
+ "uvi": 0,
+ "clouds": 100,
+ "visibility": 305,
+ "wind_speed": 2.65,
+ "wind_deg": 237,
+ "wind_gust": 7.6,
+ "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }],
+ "pop": 0.8
+ },
+ {
+ "dt": 1770447600,
+ "temp": -4.12,
+ "feels_like": -8.44,
+ "pressure": 1000,
+ "humidity": 95,
+ "dew_point": -4.97,
+ "uvi": 0,
+ "clouds": 100,
+ "visibility": 10000,
+ "wind_speed": 2.99,
+ "wind_deg": 247,
+ "wind_gust": 7.23,
+ "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }],
+ "pop": 0
+ },
+ {
+ "dt": 1770451200,
+ "temp": -4.9,
+ "feels_like": -9.33,
+ "pressure": 999,
+ "humidity": 95,
+ "dew_point": -5.82,
+ "uvi": 0,
+ "clouds": 100,
+ "visibility": 10000,
+ "wind_speed": 2.95,
+ "wind_deg": 256,
+ "wind_gust": 7.85,
+ "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }],
+ "pop": 0
+ },
+ {
+ "dt": 1770454800,
+ "temp": -4.84,
+ "feels_like": -9.36,
+ "pressure": 999,
+ "humidity": 94,
+ "dew_point": -5.93,
+ "uvi": 0,
+ "clouds": 100,
+ "visibility": 4481,
+ "wind_speed": 3.04,
+ "wind_deg": 273,
+ "wind_gust": 10.32,
+ "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }],
+ "pop": 0
+ },
+ {
+ "dt": 1770458400,
+ "temp": -5.46,
+ "feels_like": -12.46,
+ "pressure": 1000,
+ "humidity": 85,
+ "dew_point": -7.96,
+ "uvi": 0,
+ "clouds": 100,
+ "visibility": 9905,
+ "wind_speed": 7.66,
+ "wind_deg": 316,
+ "wind_gust": 11.92,
+ "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }],
+ "pop": 0
+ },
+ {
+ "dt": 1770462000,
+ "temp": -9.55,
+ "feels_like": -16.55,
+ "pressure": 1001,
+ "humidity": 76,
+ "dew_point": -13.6,
+ "uvi": 0,
+ "clouds": 100,
+ "visibility": 10000,
+ "wind_speed": 8.25,
+ "wind_deg": 315,
+ "wind_gust": 15.03,
+ "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }],
+ "pop": 0
+ },
+ {
+ "dt": 1770465600,
+ "temp": -12.37,
+ "feels_like": -19.37,
+ "pressure": 1002,
+ "humidity": 76,
+ "dew_point": -16.71,
+ "uvi": 0,
+ "clouds": 100,
+ "visibility": 10000,
+ "wind_speed": 8.55,
+ "wind_deg": 309,
+ "wind_gust": 15.72,
+ "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04d" }],
+ "pop": 0
+ },
+ {
+ "dt": 1770469200,
+ "temp": -14.13,
+ "feels_like": -21.13,
+ "pressure": 1003,
+ "humidity": 76,
+ "dew_point": -18.65,
+ "uvi": 0.27,
+ "clouds": 100,
+ "visibility": 10000,
+ "wind_speed": 8.44,
+ "wind_deg": 308,
+ "wind_gust": 16.05,
+ "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04d" }],
+ "pop": 0
+ },
+ {
+ "dt": 1770472800,
+ "temp": -13.41,
+ "feels_like": -20.41,
+ "pressure": 1004,
+ "humidity": 76,
+ "dew_point": -17.82,
+ "uvi": 0.72,
+ "clouds": 56,
+ "visibility": 10000,
+ "wind_speed": 8.4,
+ "wind_deg": 311,
+ "wind_gust": 16,
+ "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04d" }],
+ "pop": 0
+ },
+ {
+ "dt": 1770476400,
+ "temp": -12.76,
+ "feels_like": -19.76,
+ "pressure": 1004,
+ "humidity": 78,
+ "dew_point": -16.79,
+ "uvi": 1.2,
+ "clouds": 52,
+ "visibility": 10000,
+ "wind_speed": 8.67,
+ "wind_deg": 317,
+ "wind_gust": 15.12,
+ "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04d" }],
+ "pop": 0
+ },
+ {
+ "dt": 1770480000,
+ "temp": -12.33,
+ "feels_like": -19.33,
+ "pressure": 1005,
+ "humidity": 83,
+ "dew_point": -15.61,
+ "uvi": 1.56,
+ "clouds": 64,
+ "visibility": 3083,
+ "wind_speed": 8.8,
+ "wind_deg": 321,
+ "wind_gust": 15.19,
+ "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04d" }],
+ "pop": 0
+ },
+ {
+ "dt": 1770483600,
+ "temp": -11.87,
+ "feels_like": -18.87,
+ "pressure": 1004,
+ "humidity": 82,
+ "dew_point": -15.28,
+ "uvi": 1.56,
+ "clouds": 71,
+ "visibility": 8917,
+ "wind_speed": 8.88,
+ "wind_deg": 322,
+ "wind_gust": 15.55,
+ "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04d" }],
+ "pop": 0
+ },
+ {
+ "dt": 1770487200,
+ "temp": -11.69,
+ "feels_like": -18.69,
+ "pressure": 1005,
+ "humidity": 79,
+ "dew_point": -15.5,
+ "uvi": 1.57,
+ "clouds": 76,
+ "visibility": 10000,
+ "wind_speed": 9.46,
+ "wind_deg": 324,
+ "wind_gust": 16.31,
+ "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04d" }],
+ "pop": 0
+ },
+ {
+ "dt": 1770490800,
+ "temp": -11.62,
+ "feels_like": -18.62,
+ "pressure": 1005,
+ "humidity": 77,
+ "dew_point": -15.73,
+ "uvi": 1.11,
+ "clouds": 100,
+ "visibility": 10000,
+ "wind_speed": 9.8,
+ "wind_deg": 327,
+ "wind_gust": 16.18,
+ "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04d" }],
+ "pop": 0
+ },
+ {
+ "dt": 1770494400,
+ "temp": -12,
+ "feels_like": -19,
+ "pressure": 1006,
+ "humidity": 75,
+ "dew_point": -16.48,
+ "uvi": 0.59,
+ "clouds": 100,
+ "visibility": 10000,
+ "wind_speed": 9.97,
+ "wind_deg": 328,
+ "wind_gust": 16.89,
+ "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04d" }],
+ "pop": 0
+ },
+ {
+ "dt": 1770498000,
+ "temp": -12.71,
+ "feels_like": -19.71,
+ "pressure": 1007,
+ "humidity": 74,
+ "dew_point": -17.39,
+ "uvi": 0.19,
+ "clouds": 100,
+ "visibility": 10000,
+ "wind_speed": 10.12,
+ "wind_deg": 328,
+ "wind_gust": 17.9,
+ "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04d" }],
+ "pop": 0
+ },
+ {
+ "dt": 1770501600,
+ "temp": -13.43,
+ "feels_like": -20.43,
+ "pressure": 1009,
+ "humidity": 72,
+ "dew_point": -18.44,
+ "uvi": 0,
+ "clouds": 100,
+ "visibility": 10000,
+ "wind_speed": 10.09,
+ "wind_deg": 329,
+ "wind_gust": 18.24,
+ "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04d" }],
+ "pop": 0
+ },
+ {
+ "dt": 1770505200,
+ "temp": -14.05,
+ "feels_like": -21.05,
+ "pressure": 1011,
+ "humidity": 72,
+ "dew_point": -19.28,
+ "uvi": 0,
+ "clouds": 99,
+ "visibility": 10000,
+ "wind_speed": 10.11,
+ "wind_deg": 329,
+ "wind_gust": 18.4,
+ "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }],
+ "pop": 0
+ },
+ {
+ "dt": 1770508800,
+ "temp": -14.31,
+ "feels_like": -21.31,
+ "pressure": 1013,
+ "humidity": 72,
+ "dew_point": -19.61,
+ "uvi": 0,
+ "clouds": 97,
+ "visibility": 10000,
+ "wind_speed": 10.18,
+ "wind_deg": 328,
+ "wind_gust": 18.77,
+ "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }],
+ "pop": 0
+ },
+ {
+ "dt": 1770512400,
+ "temp": -14.29,
+ "feels_like": -21.29,
+ "pressure": 1014,
+ "humidity": 72,
+ "dew_point": -19.51,
+ "uvi": 0,
+ "clouds": 97,
+ "visibility": 10000,
+ "wind_speed": 9.7,
+ "wind_deg": 330,
+ "wind_gust": 18.29,
+ "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }],
+ "pop": 0
+ },
+ {
+ "dt": 1770516000,
+ "temp": -14.14,
+ "feels_like": -21.14,
+ "pressure": 1015,
+ "humidity": 72,
+ "dew_point": -19.28,
+ "uvi": 0,
+ "clouds": 98,
+ "visibility": 10000,
+ "wind_speed": 9.38,
+ "wind_deg": 330,
+ "wind_gust": 17.25,
+ "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }],
+ "pop": 0
+ },
+ {
+ "dt": 1770519600,
+ "temp": -14.08,
+ "feels_like": -21.08,
+ "pressure": 1016,
+ "humidity": 73,
+ "dew_point": -19.05,
+ "uvi": 0,
+ "clouds": 99,
+ "visibility": 10000,
+ "wind_speed": 8.71,
+ "wind_deg": 329,
+ "wind_gust": 16.58,
+ "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }],
+ "pop": 0
+ },
+ {
+ "dt": 1770523200,
+ "temp": -14.19,
+ "feels_like": -21.19,
+ "pressure": 1016,
+ "humidity": 74,
+ "dew_point": -19.05,
+ "uvi": 0,
+ "clouds": 99,
+ "visibility": 10000,
+ "wind_speed": 8.24,
+ "wind_deg": 328,
+ "wind_gust": 15.71,
+ "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }],
+ "pop": 0
+ },
+ {
+ "dt": 1770526800,
+ "temp": -14.38,
+ "feels_like": -21.38,
+ "pressure": 1017,
+ "humidity": 74,
+ "dew_point": -19.34,
+ "uvi": 0,
+ "clouds": 99,
+ "visibility": 10000,
+ "wind_speed": 8.08,
+ "wind_deg": 326,
+ "wind_gust": 15.77,
+ "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }],
+ "pop": 0
+ },
+ {
+ "dt": 1770530400,
+ "temp": -14.74,
+ "feels_like": -21.74,
+ "pressure": 1018,
+ "humidity": 74,
+ "dew_point": -19.74,
+ "uvi": 0,
+ "clouds": 99,
+ "visibility": 10000,
+ "wind_speed": 7.81,
+ "wind_deg": 324,
+ "wind_gust": 15.4,
+ "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }],
+ "pop": 0
+ },
+ {
+ "dt": 1770534000,
+ "temp": -15.13,
+ "feels_like": -22.13,
+ "pressure": 1019,
+ "humidity": 73,
+ "dew_point": -20.25,
+ "uvi": 0,
+ "clouds": 93,
+ "visibility": 10000,
+ "wind_speed": 7.57,
+ "wind_deg": 325,
+ "wind_gust": 15.39,
+ "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }],
+ "pop": 0
+ },
+ {
+ "dt": 1770537600,
+ "temp": -15.57,
+ "feels_like": -22.57,
+ "pressure": 1019,
+ "humidity": 73,
+ "dew_point": -20.69,
+ "uvi": 0,
+ "clouds": 94,
+ "visibility": 10000,
+ "wind_speed": 7.36,
+ "wind_deg": 323,
+ "wind_gust": 15.29,
+ "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }],
+ "pop": 0
+ },
+ {
+ "dt": 1770541200,
+ "temp": -15.98,
+ "feels_like": -22.98,
+ "pressure": 1019,
+ "humidity": 73,
+ "dew_point": -21.2,
+ "uvi": 0,
+ "clouds": 88,
+ "visibility": 10000,
+ "wind_speed": 7.37,
+ "wind_deg": 321,
+ "wind_gust": 15.7,
+ "weather": [{ "id": 804, "main": "Clouds", "description": "overcast clouds", "icon": "04n" }],
+ "pop": 0
+ },
+ {
+ "dt": 1770544800,
+ "temp": -16.36,
+ "feels_like": -23.36,
+ "pressure": 1020,
+ "humidity": 73,
+ "dew_point": -21.64,
+ "uvi": 0,
+ "clouds": 69,
+ "visibility": 10000,
+ "wind_speed": 7.62,
+ "wind_deg": 322,
+ "wind_gust": 16.29,
+ "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04n" }],
+ "pop": 0
+ },
+ {
+ "dt": 1770548400,
+ "temp": -16.63,
+ "feels_like": -23.63,
+ "pressure": 1021,
+ "humidity": 74,
+ "dew_point": -21.86,
+ "uvi": 0,
+ "clouds": 57,
+ "visibility": 10000,
+ "wind_speed": 7.52,
+ "wind_deg": 323,
+ "wind_gust": 16.46,
+ "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04n" }],
+ "pop": 0
+ },
+ {
+ "dt": 1770552000,
+ "temp": -16.84,
+ "feels_like": -23.84,
+ "pressure": 1022,
+ "humidity": 74,
+ "dew_point": -22.06,
+ "uvi": 0,
+ "clouds": 48,
+ "visibility": 10000,
+ "wind_speed": 7.59,
+ "wind_deg": 324,
+ "wind_gust": 16.2,
+ "weather": [{ "id": 802, "main": "Clouds", "description": "scattered clouds", "icon": "03d" }],
+ "pop": 0
+ },
+ {
+ "dt": 1770555600,
+ "temp": -16.57,
+ "feels_like": -23.57,
+ "pressure": 1023,
+ "humidity": 74,
+ "dew_point": -21.63,
+ "uvi": 0.3,
+ "clouds": 2,
+ "visibility": 10000,
+ "wind_speed": 7.27,
+ "wind_deg": 325,
+ "wind_gust": 14.68,
+ "weather": [{ "id": 800, "main": "Clear", "description": "clear sky", "icon": "01d" }],
+ "pop": 0
+ },
+ {
+ "dt": 1770559200,
+ "temp": -15.7,
+ "feels_like": -22.7,
+ "pressure": 1023,
+ "humidity": 76,
+ "dew_point": -20.43,
+ "uvi": 0.77,
+ "clouds": 4,
+ "visibility": 10000,
+ "wind_speed": 7.26,
+ "wind_deg": 324,
+ "wind_gust": 13.65,
+ "weather": [{ "id": 800, "main": "Clear", "description": "clear sky", "icon": "01d" }],
+ "pop": 0
+ },
+ {
+ "dt": 1770562800,
+ "temp": -14.48,
+ "feels_like": -21.48,
+ "pressure": 1023,
+ "humidity": 77,
+ "dew_point": -18.94,
+ "uvi": 1.42,
+ "clouds": 5,
+ "visibility": 10000,
+ "wind_speed": 6.7,
+ "wind_deg": 324,
+ "wind_gust": 12.19,
+ "weather": [{ "id": 800, "main": "Clear", "description": "clear sky", "icon": "01d" }],
+ "pop": 0
+ },
+ {
+ "dt": 1770566400,
+ "temp": -13.34,
+ "feels_like": -20.34,
+ "pressure": 1023,
+ "humidity": 73,
+ "dew_point": -18.23,
+ "uvi": 1.98,
+ "clouds": 5,
+ "visibility": 10000,
+ "wind_speed": 6.59,
+ "wind_deg": 327,
+ "wind_gust": 10.06,
+ "weather": [{ "id": 800, "main": "Clear", "description": "clear sky", "icon": "01d" }],
+ "pop": 0
+ },
+ {
+ "dt": 1770570000,
+ "temp": -11.94,
+ "feels_like": -18.94,
+ "pressure": 1022,
+ "humidity": 74,
+ "dew_point": -16.63,
+ "uvi": 2.19,
+ "clouds": 6,
+ "visibility": 10000,
+ "wind_speed": 6.3,
+ "wind_deg": 325,
+ "wind_gust": 9.29,
+ "weather": [{ "id": 800, "main": "Clear", "description": "clear sky", "icon": "01d" }],
+ "pop": 0
+ },
+ {
+ "dt": 1770573600,
+ "temp": -10.51,
+ "feels_like": -17.51,
+ "pressure": 1022,
+ "humidity": 75,
+ "dew_point": -14.88,
+ "uvi": 1.95,
+ "clouds": 7,
+ "visibility": 10000,
+ "wind_speed": 5.98,
+ "wind_deg": 321,
+ "wind_gust": 8.89,
+ "weather": [{ "id": 800, "main": "Clear", "description": "clear sky", "icon": "01d" }],
+ "pop": 0
+ },
+ {
+ "dt": 1770577200,
+ "temp": -9.42,
+ "feels_like": -16.42,
+ "pressure": 1022,
+ "humidity": 75,
+ "dew_point": -13.63,
+ "uvi": 1.39,
+ "clouds": 72,
+ "visibility": 10000,
+ "wind_speed": 5.92,
+ "wind_deg": 317,
+ "wind_gust": 8.77,
+ "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04d" }],
+ "pop": 0
+ },
+ {
+ "dt": 1770580800,
+ "temp": -8.96,
+ "feels_like": -15.96,
+ "pressure": 1023,
+ "humidity": 79,
+ "dew_point": -12.4,
+ "uvi": 0.73,
+ "clouds": 80,
+ "visibility": 10000,
+ "wind_speed": 6.03,
+ "wind_deg": 312,
+ "wind_gust": 10.13,
+ "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04d" }],
+ "pop": 0
+ }
+ ],
+ "daily": [
+ {
+ "dt": 1770397200,
+ "sunrise": 1770379257,
+ "sunset": 1770416341,
+ "moonrise": 1770435960,
+ "moonset": 1770386880,
+ "moon_phase": 0.66,
+ "summary": "Expect a day of partly cloudy with snow",
+ "temp": { "day": -2.5, "min": -11.86, "max": -0.27, "night": -3.88, "eve": -1.03, "morn": -10.39 },
+ "feels_like": { "day": -2.5, "night": -7.67, "eve": -3.4, "morn": -14.33 },
+ "pressure": 1006,
+ "humidity": 88,
+ "dew_point": -4.3,
+ "wind_speed": 3.05,
+ "wind_deg": 236,
+ "wind_gust": 7.82,
+ "weather": [{ "id": 600, "main": "Snow", "description": "light snow", "icon": "13d" }],
+ "clouds": 95,
+ "pop": 1,
+ "snow": 0.69,
+ "uvi": 2.22
+ },
+ {
+ "dt": 1770483600,
+ "sunrise": 1770465590,
+ "sunset": 1770502816,
+ "moonrise": 1770526200,
+ "moonset": 1770474600,
+ "moon_phase": 0.69,
+ "summary": "There will be snow until morning, then partly cloudy",
+ "temp": { "day": -11.87, "min": -14.31, "max": -3.78, "night": -14.19, "eve": -14.05, "morn": -9.55 },
+ "feels_like": { "day": -18.87, "night": -21.19, "eve": -21.05, "morn": -16.55 },
+ "pressure": 1004,
+ "humidity": 82,
+ "dew_point": -15.28,
+ "wind_speed": 10.18,
+ "wind_deg": 328,
+ "wind_gust": 18.77,
+ "weather": [{ "id": 600, "main": "Snow", "description": "light snow", "icon": "13d" }],
+ "clouds": 71,
+ "pop": 1,
+ "snow": 0.14,
+ "uvi": 1.57
+ },
+ {
+ "dt": 1770570000,
+ "sunrise": 1770551923,
+ "sunset": 1770589291,
+ "moonrise": 0,
+ "moonset": 1770562440,
+ "moon_phase": 0.72,
+ "summary": "Expect a day of partly cloudy with clear spells",
+ "temp": { "day": -11.94, "min": -16.84, "max": -8.96, "night": -13.75, "eve": -11.11, "morn": -16.63 },
+ "feels_like": { "day": -18.94, "night": -20.33, "eve": -18.11, "morn": -23.63 },
+ "pressure": 1022,
+ "humidity": 74,
+ "dew_point": -16.63,
+ "wind_speed": 8.08,
+ "wind_deg": 326,
+ "wind_gust": 16.46,
+ "weather": [{ "id": 800, "main": "Clear", "description": "clear sky", "icon": "01d" }],
+ "clouds": 6,
+ "pop": 0,
+ "uvi": 2.19
+ },
+ {
+ "dt": 1770656400,
+ "sunrise": 1770638253,
+ "sunset": 1770675765,
+ "moonrise": 1770616380,
+ "moonset": 1770650520,
+ "moon_phase": 0.75,
+ "summary": "The day will start with clear sky through the late morning hours, transitioning to partly cloudy",
+ "temp": { "day": -6.9, "min": -17.11, "max": -3.39, "night": -5.77, "eve": -7.87, "morn": -16.94 },
+ "feels_like": { "day": -10.1, "night": -5.77, "eve": -7.87, "morn": -16.94 },
+ "pressure": 1024,
+ "humidity": 78,
+ "dew_point": -10.38,
+ "wind_speed": 2.5,
+ "wind_deg": 319,
+ "wind_gust": 7.03,
+ "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04d" }],
+ "clouds": 83,
+ "pop": 0,
+ "uvi": 2.7
+ },
+ {
+ "dt": 1770742800,
+ "sunrise": 1770724583,
+ "sunset": 1770762240,
+ "moonrise": 1770706560,
+ "moonset": 1770739020,
+ "moon_phase": 0.79,
+ "summary": "There will be partly cloudy today",
+ "temp": { "day": -1.46, "min": -10, "max": -0.51, "night": -3.8, "eve": -1.57, "morn": -10 },
+ "feels_like": { "day": -1.46, "night": -6.36, "eve": -3.98, "morn": -13.81 },
+ "pressure": 1020,
+ "humidity": 94,
+ "dew_point": -2.47,
+ "wind_speed": 1.83,
+ "wind_deg": 2,
+ "wind_gust": 2.92,
+ "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04d" }],
+ "clouds": 56,
+ "pop": 0,
+ "uvi": 3.1
+ },
+ {
+ "dt": 1770829200,
+ "sunrise": 1770810911,
+ "sunset": 1770848714,
+ "moonrise": 1770796620,
+ "moonset": 1770827880,
+ "moon_phase": 0.82,
+ "summary": "The day will start with partly cloudy with snow through the late morning hours, transitioning to partly cloudy with rain",
+ "temp": { "day": 0.7, "min": -4.02, "max": 2.06, "night": -0.6, "eve": 2.06, "morn": -0.03 },
+ "feels_like": { "day": 0.7, "night": -5, "eve": -2, "morn": -3.1 },
+ "pressure": 1009,
+ "humidity": 100,
+ "dew_point": 0.64,
+ "wind_speed": 4.4,
+ "wind_deg": 311,
+ "wind_gust": 11.56,
+ "weather": [{ "id": 616, "main": "Snow", "description": "rain and snow", "icon": "13d" }],
+ "clouds": 100,
+ "pop": 1,
+ "rain": 4.38,
+ "snow": 2.17,
+ "uvi": 4
+ },
+ {
+ "dt": 1770915600,
+ "sunrise": 1770897237,
+ "sunset": 1770935188,
+ "moonrise": 1770886440,
+ "moonset": 1770917220,
+ "moon_phase": 0.85,
+ "summary": "There will be partly cloudy today",
+ "temp": { "day": 0.2, "min": -4.63, "max": 0.2, "night": -4.63, "eve": -2.9, "morn": -3.67 },
+ "feels_like": { "day": -4.8, "night": -10.67, "eve": -8.49, "morn": -8.22 },
+ "pressure": 1012,
+ "humidity": 81,
+ "dew_point": -2.81,
+ "wind_speed": 5.52,
+ "wind_deg": 301,
+ "wind_gust": 12.97,
+ "weather": [{ "id": 802, "main": "Clouds", "description": "scattered clouds", "icon": "03d" }],
+ "clouds": 50,
+ "pop": 0,
+ "uvi": 4
+ },
+ {
+ "dt": 1771002000,
+ "sunrise": 1770983562,
+ "sunset": 1771021662,
+ "moonrise": 1770975780,
+ "moonset": 1771007160,
+ "moon_phase": 0.88,
+ "summary": "Expect a day of partly cloudy with clear spells",
+ "temp": { "day": 0.38, "min": -6.39, "max": 0.95, "night": -1.17, "eve": -0.91, "morn": -6.39 },
+ "feels_like": { "day": -3.92, "night": -6.3, "eve": -5.42, "morn": -12.89 },
+ "pressure": 1017,
+ "humidity": 80,
+ "dew_point": -2.71,
+ "wind_speed": 5.27,
+ "wind_deg": 298,
+ "wind_gust": 14.69,
+ "weather": [{ "id": 803, "main": "Clouds", "description": "broken clouds", "icon": "04d" }],
+ "clouds": 74,
+ "pop": 0,
+ "uvi": 4
+ }
+ ]
+}
diff --git a/tests/mocks/weather_pirateweather.json b/tests/mocks/weather_pirateweather.json
new file mode 100644
index 00000000..75a13969
--- /dev/null
+++ b/tests/mocks/weather_pirateweather.json
@@ -0,0 +1,1665 @@
+{
+ "latitude": 40.7128,
+ "longitude": -74.006,
+ "timezone": "America/New_York",
+ "offset": -5.0,
+ "elevation": 19,
+ "currently": {
+ "time": 1770414300,
+ "summary": "Overcast",
+ "icon": "cloudy",
+ "nearestStormDistance": 115.95,
+ "nearestStormBearing": 233,
+ "precipIntensity": 0.0,
+ "precipProbability": 0.0,
+ "precipIntensityError": 0.0,
+ "precipType": "none",
+ "temperature": -0.26,
+ "apparentTemperature": -4.77,
+ "dewPoint": -7.89,
+ "humidity": 0.56,
+ "pressure": 1004.92,
+ "windSpeed": 2.32,
+ "windGust": 3.2,
+ "windBearing": 166,
+ "cloudCover": 0.97,
+ "uvIndex": 0.54,
+ "visibility": 16.09,
+ "ozone": 401.41
+ },
+ "minutely": {
+ "summary": "Overcast for the hour.",
+ "icon": "cloudy",
+ "data": [
+ { "time": 1770414300, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770414360, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770414420, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770414480, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770414540, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770414600, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770414660, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770414720, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770414780, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770414840, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770414900, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770414960, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770415020, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770415080, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770415140, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770415200, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770415260, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770415320, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770415380, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770415440, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770415500, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770415560, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770415620, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770415680, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770415740, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770415800, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770415860, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770415920, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770415980, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770416040, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770416100, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770416160, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770416220, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770416280, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770416340, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770416400, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770416460, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770416520, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770416580, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770416640, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770416700, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770416760, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770416820, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770416880, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770416940, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770417000, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770417060, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770417120, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770417180, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770417240, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770417300, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770417360, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770417420, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770417480, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770417540, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770417600, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770417660, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770417720, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770417780, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770417840, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" },
+ { "time": 1770417900, "precipIntensity": 0.0, "precipProbability": 0.0, "precipIntensityError": 0.0, "precipType": "none" }
+ ]
+ },
+ "hourly": {
+ "summary": "Hazy tonight and windy starting tomorrow morning.",
+ "icon": "fog",
+ "data": [
+ {
+ "time": 1770411600,
+ "summary": "Mostly Cloudy",
+ "icon": "partly-cloudy-day",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.16,
+ "precipIntensityError": 0.0,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -2.19,
+ "apparentTemperature": -6.47,
+ "dewPoint": -6.77,
+ "humidity": 0.7,
+ "pressure": 1005.22,
+ "windSpeed": 3.6,
+ "windGust": 4.7,
+ "windBearing": 200,
+ "cloudCover": 0.77,
+ "uvIndex": 1.12,
+ "visibility": 16.09,
+ "ozone": 402.15,
+ "nearestStormDistance": 108.83,
+ "nearestStormBearing": 258
+ },
+ {
+ "time": 1770415200,
+ "summary": "Mostly Cloudy",
+ "icon": "partly-cloudy-day",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.16,
+ "precipIntensityError": 0.0,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -2.11,
+ "apparentTemperature": -6.3,
+ "dewPoint": -6.64,
+ "humidity": 0.71,
+ "pressure": 1004.82,
+ "windSpeed": 3.6,
+ "windGust": 4.77,
+ "windBearing": 207,
+ "cloudCover": 0.8,
+ "uvIndex": 0.35,
+ "visibility": 14.72,
+ "ozone": 401.17,
+ "nearestStormDistance": 118.33,
+ "nearestStormBearing": 233
+ },
+ {
+ "time": 1770418800,
+ "summary": "Mostly Cloudy",
+ "icon": "partly-cloudy-night",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.16,
+ "precipIntensityError": 0.0,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -2.02,
+ "apparentTemperature": -6.13,
+ "dewPoint": -6.5,
+ "humidity": 0.71,
+ "pressure": 1004.19,
+ "windSpeed": 3.6,
+ "windGust": 4.83,
+ "windBearing": 213,
+ "cloudCover": 0.83,
+ "uvIndex": 0.01,
+ "visibility": 13.18,
+ "ozone": 403.38,
+ "nearestStormDistance": 63.25,
+ "nearestStormBearing": 270
+ },
+ {
+ "time": 1770422400,
+ "summary": "Mostly Cloudy",
+ "icon": "partly-cloudy-night",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.16,
+ "precipIntensityError": 0.02,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -1.94,
+ "apparentTemperature": -5.96,
+ "dewPoint": -6.37,
+ "humidity": 0.72,
+ "pressure": 1004.33,
+ "windSpeed": 3.6,
+ "windGust": 4.9,
+ "windBearing": 220,
+ "cloudCover": 0.86,
+ "uvIndex": 0.0,
+ "visibility": 11.65,
+ "ozone": 406.37,
+ "nearestStormDistance": 34.89,
+ "nearestStormBearing": 225
+ },
+ {
+ "time": 1770426000,
+ "summary": "Mostly Cloudy",
+ "icon": "partly-cloudy-night",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.22,
+ "precipIntensityError": 0.02,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -1.87,
+ "apparentTemperature": -6.11,
+ "dewPoint": -6.26,
+ "humidity": 0.73,
+ "pressure": 1003.94,
+ "windSpeed": 3.6,
+ "windGust": 4.93,
+ "windBearing": 223,
+ "cloudCover": 0.87,
+ "uvIndex": 0.0,
+ "visibility": 8.58,
+ "ozone": 408.33,
+ "nearestStormDistance": 21.08,
+ "nearestStormBearing": 270
+ },
+ {
+ "time": 1770429600,
+ "summary": "Overcast",
+ "icon": "cloudy",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.27,
+ "precipIntensityError": 0.03,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -1.79,
+ "apparentTemperature": -6.25,
+ "dewPoint": -6.15,
+ "humidity": 0.73,
+ "pressure": 1003.89,
+ "windSpeed": 3.6,
+ "windGust": 4.97,
+ "windBearing": 227,
+ "cloudCover": 0.88,
+ "uvIndex": 0.0,
+ "visibility": 5.5,
+ "ozone": 405.87,
+ "nearestStormDistance": 34.89,
+ "nearestStormBearing": 135
+ },
+ {
+ "time": 1770433200,
+ "summary": "Hazy",
+ "icon": "fog",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.33,
+ "precipIntensityError": 0.03,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -1.72,
+ "apparentTemperature": -6.4,
+ "dewPoint": -6.04,
+ "humidity": 0.74,
+ "pressure": 1003.77,
+ "windSpeed": 3.6,
+ "windGust": 5.0,
+ "windBearing": 230,
+ "cloudCover": 0.89,
+ "uvIndex": 0.0,
+ "visibility": 2.43,
+ "ozone": 406.71,
+ "nearestStormDistance": 21.08,
+ "nearestStormBearing": 90
+ },
+ {
+ "time": 1770436800,
+ "summary": "Hazy",
+ "icon": "fog",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.33,
+ "precipIntensityError": 0.03,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -1.89,
+ "apparentTemperature": -6.74,
+ "dewPoint": -6.17,
+ "humidity": 0.74,
+ "pressure": 1003.03,
+ "windSpeed": 3.87,
+ "windGust": 5.4,
+ "windBearing": 237,
+ "cloudCover": 0.86,
+ "uvIndex": 0.0,
+ "visibility": 2.73,
+ "ozone": 403.27,
+ "nearestStormDistance": 84.33,
+ "nearestStormBearing": 90
+ },
+ {
+ "time": 1770440400,
+ "summary": "Hazy",
+ "icon": "fog",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.33,
+ "precipIntensityError": 0.03,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -2.05,
+ "apparentTemperature": -7.07,
+ "dewPoint": -6.3,
+ "humidity": 0.73,
+ "pressure": 1002.42,
+ "windSpeed": 4.13,
+ "windGust": 5.8,
+ "windBearing": 243,
+ "cloudCover": 0.84,
+ "uvIndex": 0.0,
+ "visibility": 3.03,
+ "ozone": 408.05,
+ "nearestStormDistance": 105.41,
+ "nearestStormBearing": 90
+ },
+ {
+ "time": 1770444000,
+ "summary": "Hazy",
+ "icon": "fog",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.33,
+ "precipIntensityError": 0.03,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -2.22,
+ "apparentTemperature": -7.41,
+ "dewPoint": -6.43,
+ "humidity": 0.73,
+ "pressure": 1001.45,
+ "windSpeed": 4.4,
+ "windGust": 6.2,
+ "windBearing": 250,
+ "cloudCover": 0.81,
+ "uvIndex": 0.0,
+ "visibility": 3.33,
+ "ozone": 412.89,
+ "nearestStormDistance": 118.85,
+ "nearestStormBearing": 111
+ },
+ {
+ "time": 1770447600,
+ "summary": "Mostly Cloudy",
+ "icon": "partly-cloudy-night",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.29,
+ "precipIntensityError": 0.03,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -2.58,
+ "apparentTemperature": -8.29,
+ "dewPoint": -6.62,
+ "humidity": 0.74,
+ "pressure": 1000.84,
+ "windSpeed": 5.33,
+ "windGust": 7.5,
+ "windBearing": 260,
+ "cloudCover": 0.8,
+ "uvIndex": 0.0,
+ "visibility": 5.6,
+ "ozone": 417.97,
+ "nearestStormDistance": 118.85,
+ "nearestStormBearing": 111
+ },
+ {
+ "time": 1770451200,
+ "summary": "Mostly Cloudy",
+ "icon": "partly-cloudy-night",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.24,
+ "precipIntensityError": 0.03,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -2.95,
+ "apparentTemperature": -9.17,
+ "dewPoint": -6.82,
+ "humidity": 0.75,
+ "pressure": 1000.63,
+ "windSpeed": 6.27,
+ "windGust": 8.8,
+ "windBearing": 270,
+ "cloudCover": 0.78,
+ "uvIndex": 0.0,
+ "visibility": 8.4,
+ "ozone": 417.69,
+ "nearestStormDistance": 118.85,
+ "nearestStormBearing": 111
+ },
+ {
+ "time": 1770454800,
+ "summary": "Breezy and Mostly Cloudy",
+ "icon": "wind",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.2,
+ "precipIntensityError": 0.04,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -3.31,
+ "apparentTemperature": -10.05,
+ "dewPoint": -7.01,
+ "humidity": 0.76,
+ "pressure": 1000.26,
+ "windSpeed": 7.2,
+ "windGust": 10.1,
+ "windBearing": 280,
+ "cloudCover": 0.77,
+ "uvIndex": 0.0,
+ "visibility": 2.3,
+ "ozone": 416.64,
+ "nearestStormDistance": 55.66,
+ "nearestStormBearing": 180
+ },
+ {
+ "time": 1770458400,
+ "summary": "Breezy and Mostly Cloudy",
+ "icon": "wind",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.2,
+ "precipIntensityError": 0.04,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -4.07,
+ "apparentTemperature": -11.46,
+ "dewPoint": -8.19,
+ "humidity": 0.73,
+ "pressure": 1000.86,
+ "windSpeed": 8.13,
+ "windGust": 11.13,
+ "windBearing": 287,
+ "cloudCover": 0.73,
+ "uvIndex": 0.0,
+ "visibility": 2.5,
+ "ozone": 430.55,
+ "nearestStormDistance": 59.55,
+ "nearestStormBearing": 333
+ },
+ {
+ "time": 1770462000,
+ "summary": "Breezy and Mostly Cloudy",
+ "icon": "wind",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.2,
+ "precipIntensityError": 0.04,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -4.82,
+ "apparentTemperature": -12.87,
+ "dewPoint": -9.36,
+ "humidity": 0.71,
+ "pressure": 1001.53,
+ "windSpeed": 9.07,
+ "windGust": 12.17,
+ "windBearing": 293,
+ "cloudCover": 0.69,
+ "uvIndex": 0.0,
+ "visibility": 16.09,
+ "ozone": 444.39,
+ "nearestStormDistance": 63.25,
+ "nearestStormBearing": 90
+ },
+ {
+ "time": 1770465600,
+ "summary": "Windy and Mostly Cloudy",
+ "icon": "wind",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.2,
+ "precipIntensityError": 0.04,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -5.58,
+ "apparentTemperature": -14.28,
+ "dewPoint": -10.54,
+ "humidity": 0.68,
+ "pressure": 1002.21,
+ "windSpeed": 10.0,
+ "windGust": 13.2,
+ "windBearing": 300,
+ "cloudCover": 0.65,
+ "uvIndex": 0.0,
+ "visibility": 16.09,
+ "ozone": 445.07,
+ "nearestStormDistance": 101.31,
+ "nearestStormBearing": 63
+ },
+ {
+ "time": 1770469200,
+ "summary": "Windy and Partly Cloudy",
+ "icon": "wind",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.16,
+ "precipIntensityError": 0.04,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -6.72,
+ "apparentTemperature": -15.95,
+ "dewPoint": -11.67,
+ "humidity": 0.68,
+ "pressure": 1003.26,
+ "windSpeed": 10.4,
+ "windGust": 14.17,
+ "windBearing": 303,
+ "cloudCover": 0.57,
+ "uvIndex": 0.21,
+ "visibility": 16.09,
+ "ozone": 446.52,
+ "nearestStormDistance": 118.85,
+ "nearestStormBearing": 111
+ },
+ {
+ "time": 1770472800,
+ "summary": "Windy and Partly Cloudy",
+ "icon": "wind",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.11,
+ "precipIntensityError": 0.04,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -7.85,
+ "apparentTemperature": -17.63,
+ "dewPoint": -12.79,
+ "humidity": 0.68,
+ "pressure": 1003.8,
+ "windSpeed": 10.8,
+ "windGust": 15.13,
+ "windBearing": 307,
+ "cloudCover": 0.49,
+ "uvIndex": 1.08,
+ "visibility": 16.09,
+ "ozone": 451.89,
+ "nearestStormDistance": 68.99,
+ "nearestStormBearing": 108
+ },
+ {
+ "time": 1770476400,
+ "summary": "Windy and Partly Cloudy",
+ "icon": "wind",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.07,
+ "precipIntensityError": 0.04,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -8.99,
+ "apparentTemperature": -19.3,
+ "dewPoint": -13.92,
+ "humidity": 0.68,
+ "pressure": 1004.89,
+ "windSpeed": 11.2,
+ "windGust": 16.1,
+ "windBearing": 310,
+ "cloudCover": 0.41,
+ "uvIndex": 2.15,
+ "visibility": 6.5,
+ "ozone": 449.97,
+ "nearestStormDistance": 63.25,
+ "nearestStormBearing": 90
+ },
+ {
+ "time": 1770480000,
+ "summary": "Windy and Partly Cloudy",
+ "icon": "wind",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.07,
+ "precipIntensityError": 0.04,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -9.07,
+ "apparentTemperature": -19.26,
+ "dewPoint": -14.3,
+ "humidity": 0.66,
+ "pressure": 1005.63,
+ "windSpeed": 11.07,
+ "windGust": 16.07,
+ "windBearing": 313,
+ "cloudCover": 0.39,
+ "uvIndex": 2.87,
+ "visibility": 4.3,
+ "ozone": 447.68,
+ "nearestStormDistance": 129.75,
+ "nearestStormBearing": 80
+ },
+ {
+ "time": 1770483600,
+ "summary": "Windy and Mostly Clear",
+ "icon": "wind",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.07,
+ "precipIntensityError": 0.03,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -9.14,
+ "apparentTemperature": -19.23,
+ "dewPoint": -14.68,
+ "humidity": 0.64,
+ "pressure": 1006.14,
+ "windSpeed": 10.93,
+ "windGust": 16.03,
+ "windBearing": 317,
+ "cloudCover": 0.36,
+ "uvIndex": 3.23,
+ "visibility": 9.5,
+ "ozone": 460.33,
+ "nearestStormDistance": 63.25,
+ "nearestStormBearing": 90
+ },
+ {
+ "time": 1770487200,
+ "summary": "Windy and Mostly Clear",
+ "icon": "wind",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.07,
+ "precipIntensityError": 0.03,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -9.22,
+ "apparentTemperature": -19.19,
+ "dewPoint": -15.06,
+ "humidity": 0.62,
+ "pressure": 1006.64,
+ "windSpeed": 10.8,
+ "windGust": 16.0,
+ "windBearing": 320,
+ "cloudCover": 0.34,
+ "uvIndex": 3.23,
+ "visibility": 16.09,
+ "ozone": 466.32,
+ "nearestStormDistance": 84.43,
+ "nearestStormBearing": 56
+ },
+ {
+ "time": 1770490800,
+ "summary": "Windy and Mostly Clear",
+ "icon": "wind",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.06,
+ "precipIntensityError": 0.03,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -9.12,
+ "apparentTemperature": -19.17,
+ "dewPoint": -15.37,
+ "humidity": 0.6,
+ "pressure": 1007.56,
+ "windSpeed": 10.93,
+ "windGust": 16.2,
+ "windBearing": 320,
+ "cloudCover": 0.31,
+ "uvIndex": 2.88,
+ "visibility": 16.09,
+ "ozone": 461.77,
+ "nearestStormDistance": 63.25,
+ "nearestStormBearing": 90
+ },
+ {
+ "time": 1770494400,
+ "summary": "Windy and Mostly Clear",
+ "icon": "wind",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.05,
+ "precipIntensityError": 0.02,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -9.02,
+ "apparentTemperature": -19.16,
+ "dewPoint": -15.67,
+ "humidity": 0.57,
+ "pressure": 1008.89,
+ "windSpeed": 11.07,
+ "windGust": 16.4,
+ "windBearing": 320,
+ "cloudCover": 0.28,
+ "uvIndex": 2.08,
+ "visibility": 16.09,
+ "ozone": 460.11,
+ "nearestStormDistance": 63.25,
+ "nearestStormBearing": 90
+ },
+ {
+ "time": 1770498000,
+ "summary": "Windy and Mostly Clear",
+ "icon": "wind",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.0,
+ "precipIntensityError": 0.02,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -8.92,
+ "apparentTemperature": -19.14,
+ "dewPoint": -15.98,
+ "humidity": 0.55,
+ "pressure": 1009.92,
+ "windSpeed": 11.2,
+ "windGust": 16.6,
+ "windBearing": 320,
+ "cloudCover": 0.25,
+ "uvIndex": 1.23,
+ "visibility": 16.09,
+ "ozone": 464.16,
+ "nearestStormDistance": 163.12,
+ "nearestStormBearing": 38
+ },
+ {
+ "time": 1770501600,
+ "summary": "Windy and Mostly Clear",
+ "icon": "wind",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.0,
+ "precipIntensityError": 0.0,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -9.09,
+ "apparentTemperature": -19.43,
+ "dewPoint": -16.42,
+ "humidity": 0.54,
+ "pressure": 1011.26,
+ "windSpeed": 11.33,
+ "windGust": 16.13,
+ "windBearing": 320,
+ "cloudCover": 0.23,
+ "uvIndex": 0.43,
+ "visibility": 16.09,
+ "ozone": 482.48,
+ "nearestStormDistance": 129.29,
+ "nearestStormBearing": 99
+ },
+ {
+ "time": 1770505200,
+ "summary": "Windy and Mostly Clear",
+ "icon": "wind",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.0,
+ "precipIntensityError": 0.0,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -9.25,
+ "apparentTemperature": -19.71,
+ "dewPoint": -16.86,
+ "humidity": 0.53,
+ "pressure": 1013.04,
+ "windSpeed": 11.47,
+ "windGust": 15.67,
+ "windBearing": 320,
+ "cloudCover": 0.22,
+ "uvIndex": 0.01,
+ "visibility": 16.09,
+ "ozone": 484.32,
+ "nearestStormDistance": 105.41,
+ "nearestStormBearing": 90
+ },
+ {
+ "time": 1770508800,
+ "summary": "Windy and Mostly Clear",
+ "icon": "wind",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.0,
+ "precipIntensityError": 0.0,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -9.42,
+ "apparentTemperature": -20.0,
+ "dewPoint": -17.3,
+ "humidity": 0.52,
+ "pressure": 1014.7,
+ "windSpeed": 11.6,
+ "windGust": 15.2,
+ "windBearing": 320,
+ "cloudCover": 0.2,
+ "uvIndex": 0.0,
+ "visibility": 16.09,
+ "ozone": 476.4,
+ "nearestStormDistance": 63.25,
+ "nearestStormBearing": 90
+ },
+ {
+ "time": 1770512400,
+ "summary": "Windy and Mostly Clear",
+ "icon": "wind",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.0,
+ "precipIntensityError": 0.0,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -9.84,
+ "apparentTemperature": -20.51,
+ "dewPoint": -17.58,
+ "humidity": 0.53,
+ "pressure": 1015.83,
+ "windSpeed": 11.2,
+ "windGust": 14.73,
+ "windBearing": 320,
+ "cloudCover": 0.2,
+ "uvIndex": 0.0,
+ "visibility": 16.09,
+ "ozone": 488.47,
+ "nearestStormDistance": 63.25,
+ "nearestStormBearing": 90
+ },
+ {
+ "time": 1770516000,
+ "summary": "Windy and Mostly Clear",
+ "icon": "wind",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.0,
+ "precipIntensityError": 0.0,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -10.26,
+ "apparentTemperature": -21.02,
+ "dewPoint": -17.87,
+ "humidity": 0.53,
+ "pressure": 1016.42,
+ "windSpeed": 10.8,
+ "windGust": 14.27,
+ "windBearing": 320,
+ "cloudCover": 0.19,
+ "uvIndex": 0.0,
+ "visibility": 16.09,
+ "ozone": 488.94,
+ "nearestStormDistance": 42.17,
+ "nearestStormBearing": 90
+ },
+ {
+ "time": 1770519600,
+ "summary": "Windy and Mostly Clear",
+ "icon": "wind",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.0,
+ "precipIntensityError": 0.02,
+ "precipAccumulation": 0.0,
+ "precipType": "none",
+ "temperature": -10.68,
+ "apparentTemperature": -21.53,
+ "dewPoint": -18.15,
+ "humidity": 0.54,
+ "pressure": 1017.26,
+ "windSpeed": 10.4,
+ "windGust": 13.8,
+ "windBearing": 320,
+ "cloudCover": 0.19,
+ "uvIndex": 0.0,
+ "visibility": 16.09,
+ "ozone": 476.31,
+ "nearestStormDistance": 63.25,
+ "nearestStormBearing": 90
+ },
+ {
+ "time": 1770523200,
+ "summary": "Breezy and Mostly Clear",
+ "icon": "wind",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.0,
+ "precipIntensityError": 0.0,
+ "precipAccumulation": 0.0,
+ "precipType": "none",
+ "temperature": -11.0,
+ "apparentTemperature": -21.6,
+ "dewPoint": -18.21,
+ "humidity": 0.55,
+ "pressure": 1017.96,
+ "windSpeed": 9.87,
+ "windGust": 13.07,
+ "windBearing": 320,
+ "cloudCover": 0.19,
+ "uvIndex": 0.0,
+ "visibility": 16.09,
+ "ozone": 472.62,
+ "nearestStormDistance": 84.43,
+ "nearestStormBearing": 56
+ },
+ {
+ "time": 1770526800,
+ "summary": "Breezy and Mostly Clear",
+ "icon": "wind",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.0,
+ "precipIntensityError": 0.0,
+ "precipAccumulation": 0.0,
+ "precipType": "none",
+ "temperature": -11.31,
+ "apparentTemperature": -21.67,
+ "dewPoint": -18.28,
+ "humidity": 0.55,
+ "pressure": 1018.54,
+ "windSpeed": 9.33,
+ "windGust": 12.33,
+ "windBearing": 320,
+ "cloudCover": 0.18,
+ "uvIndex": 0.0,
+ "visibility": 16.09,
+ "ozone": 473.0,
+ "nearestStormDistance": 104.96,
+ "nearestStormBearing": 45
+ },
+ {
+ "time": 1770530400,
+ "summary": "Breezy and Mostly Clear",
+ "icon": "wind",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.0,
+ "precipIntensityError": 0.0,
+ "precipAccumulation": 0.0,
+ "precipType": "none",
+ "temperature": -11.63,
+ "apparentTemperature": -21.74,
+ "dewPoint": -18.34,
+ "humidity": 0.56,
+ "pressure": 1018.94,
+ "windSpeed": 8.8,
+ "windGust": 11.6,
+ "windBearing": 320,
+ "cloudCover": 0.18,
+ "uvIndex": 0.0,
+ "visibility": 16.09,
+ "ozone": 471.38,
+ "nearestStormDistance": 128.27,
+ "nearestStormBearing": 36
+ },
+ {
+ "time": 1770534000,
+ "summary": "Breezy and Mostly Clear",
+ "icon": "wind",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.0,
+ "precipIntensityError": 0.0,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -11.85,
+ "apparentTemperature": -21.99,
+ "dewPoint": -18.42,
+ "humidity": 0.57,
+ "pressure": 1019.57,
+ "windSpeed": 8.53,
+ "windGust": 11.43,
+ "windBearing": 320,
+ "cloudCover": 0.2,
+ "uvIndex": 0.0,
+ "visibility": 16.09,
+ "ozone": 469.74,
+ "nearestStormDistance": 163.12,
+ "nearestStormBearing": 38
+ },
+ {
+ "time": 1770537600,
+ "summary": "Breezy and Mostly Clear",
+ "icon": "wind",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.0,
+ "precipIntensityError": 0.0,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -12.08,
+ "apparentTemperature": -22.23,
+ "dewPoint": -18.51,
+ "humidity": 0.58,
+ "pressure": 1020.57,
+ "windSpeed": 8.27,
+ "windGust": 11.27,
+ "windBearing": 320,
+ "cloudCover": 0.22,
+ "uvIndex": 0.0,
+ "visibility": 16.09,
+ "ozone": 469.32,
+ "nearestStormDistance": 198.1,
+ "nearestStormBearing": 39
+ },
+ {
+ "time": 1770541200,
+ "summary": "Breezy and Mostly Clear",
+ "icon": "wind",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.0,
+ "precipIntensityError": 0.0,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -12.3,
+ "apparentTemperature": -22.48,
+ "dewPoint": -18.59,
+ "humidity": 0.59,
+ "pressure": 1020.96,
+ "windSpeed": 8.0,
+ "windGust": 11.1,
+ "windBearing": 320,
+ "cloudCover": 0.24,
+ "uvIndex": 0.0,
+ "visibility": 16.09,
+ "ozone": 470.4,
+ "nearestStormDistance": 210.33,
+ "nearestStormBearing": 45
+ },
+ {
+ "time": 1770544800,
+ "summary": "Breezy and Mostly Clear",
+ "icon": "wind",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.0,
+ "precipIntensityError": 0.0,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -12.29,
+ "apparentTemperature": -22.26,
+ "dewPoint": -18.48,
+ "humidity": 0.6,
+ "pressure": 1021.44,
+ "windSpeed": 7.73,
+ "windGust": 10.67,
+ "windBearing": 317,
+ "cloudCover": 0.26,
+ "uvIndex": 0.0,
+ "visibility": 16.09,
+ "ozone": 467.82,
+ "nearestStormDistance": 223.94,
+ "nearestStormBearing": 49
+ },
+ {
+ "time": 1770548400,
+ "summary": "Breezy and Mostly Clear",
+ "icon": "wind",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.0,
+ "precipIntensityError": 0.0,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -12.29,
+ "apparentTemperature": -22.05,
+ "dewPoint": -18.38,
+ "humidity": 0.61,
+ "pressure": 1021.88,
+ "windSpeed": 7.47,
+ "windGust": 10.23,
+ "windBearing": 313,
+ "cloudCover": 0.27,
+ "uvIndex": 0.0,
+ "visibility": 16.09,
+ "ozone": 467.33,
+ "nearestStormDistance": 222.15,
+ "nearestStormBearing": 35
+ },
+ {
+ "time": 1770552000,
+ "summary": "Breezy and Mostly Clear",
+ "icon": "wind",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.0,
+ "precipIntensityError": 0.0,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -12.28,
+ "apparentTemperature": -21.83,
+ "dewPoint": -18.27,
+ "humidity": 0.62,
+ "pressure": 1022.51,
+ "windSpeed": 7.2,
+ "windGust": 9.8,
+ "windBearing": 310,
+ "cloudCover": 0.29,
+ "uvIndex": 0.0,
+ "visibility": 16.09,
+ "ozone": 470.61,
+ "nearestStormDistance": 222.15,
+ "nearestStormBearing": 35
+ },
+ {
+ "time": 1770555600,
+ "summary": "Breezy and Mostly Clear",
+ "icon": "wind",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.0,
+ "precipIntensityError": 0.0,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -12.06,
+ "apparentTemperature": -21.37,
+ "dewPoint": -17.87,
+ "humidity": 0.63,
+ "pressure": 1023.17,
+ "windSpeed": 7.07,
+ "windGust": 9.83,
+ "windBearing": 313,
+ "cloudCover": 0.32,
+ "uvIndex": 0.23,
+ "visibility": 16.09,
+ "ozone": 475.74,
+ "nearestStormDistance": 198.1,
+ "nearestStormBearing": 39
+ },
+ {
+ "time": 1770559200,
+ "summary": "Breezy and Mostly Clear",
+ "icon": "wind",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.0,
+ "precipIntensityError": 0.0,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -11.85,
+ "apparentTemperature": -20.92,
+ "dewPoint": -17.48,
+ "humidity": 0.63,
+ "pressure": 1023.18,
+ "windSpeed": 6.93,
+ "windGust": 9.87,
+ "windBearing": 317,
+ "cloudCover": 0.35,
+ "uvIndex": 1.09,
+ "visibility": 16.09,
+ "ozone": 473.89,
+ "nearestStormDistance": 210.33,
+ "nearestStormBearing": 45
+ },
+ {
+ "time": 1770562800,
+ "summary": "Breezy and Partly Cloudy",
+ "icon": "wind",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.05,
+ "precipIntensityError": 0.0,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -11.63,
+ "apparentTemperature": -20.46,
+ "dewPoint": -17.08,
+ "humidity": 0.64,
+ "pressure": 1023.83,
+ "windSpeed": 6.8,
+ "windGust": 9.9,
+ "windBearing": 320,
+ "cloudCover": 0.38,
+ "uvIndex": 2.2,
+ "visibility": 16.09,
+ "ozone": 467.51,
+ "nearestStormDistance": 233.17,
+ "nearestStormBearing": 40
+ },
+ {
+ "time": 1770566400,
+ "summary": "Partly Cloudy",
+ "icon": "partly-cloudy-day",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.05,
+ "precipIntensityError": 0.0,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -10.88,
+ "apparentTemperature": -19.39,
+ "dewPoint": -16.45,
+ "humidity": 0.64,
+ "pressure": 1024.02,
+ "windSpeed": 6.53,
+ "windGust": 9.77,
+ "windBearing": 317,
+ "cloudCover": 0.41,
+ "uvIndex": 3.21,
+ "visibility": 16.09,
+ "ozone": 453.24,
+ "nearestStormDistance": 233.17,
+ "nearestStormBearing": 40
+ },
+ {
+ "time": 1770570000,
+ "summary": "Partly Cloudy",
+ "icon": "partly-cloudy-day",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.05,
+ "precipIntensityError": 0.0,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -10.12,
+ "apparentTemperature": -18.31,
+ "dewPoint": -15.82,
+ "humidity": 0.63,
+ "pressure": 1023.84,
+ "windSpeed": 6.27,
+ "windGust": 9.63,
+ "windBearing": 313,
+ "cloudCover": 0.45,
+ "uvIndex": 3.87,
+ "visibility": 16.09,
+ "ozone": 444.43,
+ "nearestStormDistance": 247.0,
+ "nearestStormBearing": 32
+ },
+ {
+ "time": 1770573600,
+ "summary": "Partly Cloudy",
+ "icon": "partly-cloudy-day",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.05,
+ "precipIntensityError": 0.0,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -9.37,
+ "apparentTemperature": -17.24,
+ "dewPoint": -15.19,
+ "humidity": 0.63,
+ "pressure": 1023.45,
+ "windSpeed": 6.0,
+ "windGust": 9.5,
+ "windBearing": 310,
+ "cloudCover": 0.48,
+ "uvIndex": 3.98,
+ "visibility": 16.09,
+ "ozone": 441.37,
+ "nearestStormDistance": 280.82,
+ "nearestStormBearing": 45
+ },
+ {
+ "time": 1770577200,
+ "summary": "Partly Cloudy",
+ "icon": "partly-cloudy-day",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.06,
+ "precipIntensityError": 0.0,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -8.97,
+ "apparentTemperature": -16.72,
+ "dewPoint": -14.92,
+ "humidity": 0.62,
+ "pressure": 1021.09,
+ "windSpeed": 6.07,
+ "windGust": 9.37,
+ "windBearing": 310,
+ "cloudCover": 0.49,
+ "uvIndex": 3.5,
+ "visibility": 16.09,
+ "ozone": 440.69,
+ "nearestStormDistance": 291.96,
+ "nearestStormBearing": 37
+ },
+ {
+ "time": 1770580800,
+ "summary": "Partly Cloudy",
+ "icon": "partly-cloudy-day",
+ "precipIntensity": 0.0,
+ "precipProbability": 0.06,
+ "precipIntensityError": 0.0,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperature": -8.58,
+ "apparentTemperature": -16.2,
+ "dewPoint": -14.64,
+ "humidity": 0.62,
+ "pressure": 1021.18,
+ "windSpeed": 6.13,
+ "windGust": 9.23,
+ "windBearing": 310,
+ "cloudCover": 0.51,
+ "uvIndex": 2.58,
+ "visibility": 16.09,
+ "ozone": 433.53,
+ "nearestStormDistance": 303.53,
+ "nearestStormBearing": 41
+ }
+ ]
+ },
+ "daily": {
+ "summary": "Snow next Friday, with high temperatures peaking at 2°C on Wednesday.",
+ "icon": "snow",
+ "data": [
+ {
+ "time": 1770354000,
+ "summary": "Hazy overnight.",
+ "icon": "fog",
+ "sunriseTime": 1770379258,
+ "sunsetTime": 1770416384,
+ "moonPhase": 0.66,
+ "precipIntensity": 0.0,
+ "precipIntensityMax": 0.0,
+ "precipIntensityMaxTime": 1770354000,
+ "precipProbability": 0.33,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperatureHigh": -2.02,
+ "temperatureHighTime": 1770418800,
+ "temperatureLow": -4.82,
+ "temperatureLowTime": 1770462000,
+ "apparentTemperatureHigh": -5.66,
+ "apparentTemperatureHighTime": 1770411600,
+ "apparentTemperatureLow": -14.37,
+ "apparentTemperatureLowTime": 1770462000,
+ "dewPoint": -9.17,
+ "humidity": 0.71,
+ "pressure": 1007.52,
+ "windSpeed": 3.01,
+ "windGust": 4.09,
+ "windGustTime": 1770436800,
+ "windBearing": 281,
+ "cloudCover": 0.63,
+ "uvIndex": 3.7,
+ "uvIndexTime": 1770400800,
+ "visibility": 13.85,
+ "temperatureMin": -8.2,
+ "temperatureMinTime": 1770379200,
+ "temperatureMax": -1.72,
+ "temperatureMaxTime": 1770433200,
+ "apparentTemperatureMin": -13.29,
+ "apparentTemperatureMinTime": 1770379200,
+ "apparentTemperatureMax": -5.66,
+ "apparentTemperatureMaxTime": 1770411600
+ },
+ {
+ "time": 1770440400,
+ "summary": "Windy throughout the day.",
+ "icon": "wind",
+ "sunriseTime": 1770465591,
+ "sunsetTime": 1770502858,
+ "moonPhase": 0.69,
+ "precipIntensity": 0.0,
+ "precipIntensityMax": 0.0,
+ "precipIntensityMaxTime": 1770440400,
+ "precipProbability": 0.33,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperatureHigh": -5.58,
+ "temperatureHighTime": 1770465600,
+ "temperatureLow": -12.3,
+ "temperatureLowTime": 1770541200,
+ "apparentTemperatureHigh": -15.88,
+ "apparentTemperatureHighTime": 1770465600,
+ "apparentTemperatureLow": -21.7,
+ "apparentTemperatureLowTime": 1770519600,
+ "dewPoint": -13.05,
+ "humidity": 0.64,
+ "pressure": 1007.22,
+ "windSpeed": 9.57,
+ "windGust": 13.35,
+ "windGustTime": 1770498000,
+ "windBearing": 302,
+ "cloudCover": 0.45,
+ "uvIndex": 3.23,
+ "uvIndexTime": 1770483600,
+ "visibility": 11.95,
+ "temperatureMin": -11.0,
+ "temperatureMinTime": 1770523200,
+ "temperatureMax": -2.05,
+ "temperatureMaxTime": 1770440400,
+ "apparentTemperatureMin": -21.7,
+ "apparentTemperatureMinTime": 1770519600,
+ "apparentTemperatureMax": -7.86,
+ "apparentTemperatureMaxTime": 1770440400
+ },
+ {
+ "time": 1770526800,
+ "summary": "Breezy in the morning.",
+ "icon": "wind",
+ "sunriseTime": 1770551923,
+ "sunsetTime": 1770589332,
+ "moonPhase": 0.72,
+ "precipIntensity": 0.0,
+ "precipIntensityMax": 0.0,
+ "precipIntensityMaxTime": 1770526800,
+ "precipProbability": 0.07,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperatureHigh": -7.97,
+ "temperatureHighTime": 1770591600,
+ "temperatureLow": -10.64,
+ "temperatureLowTime": 1770634800,
+ "apparentTemperatureHigh": -14.7,
+ "apparentTemperatureHighTime": 1770584400,
+ "apparentTemperatureLow": -17.9,
+ "apparentTemperatureLowTime": 1770634800,
+ "dewPoint": -16.36,
+ "humidity": 0.61,
+ "pressure": 1022.11,
+ "windSpeed": 6.89,
+ "windGust": 9.71,
+ "windGustTime": 1770526800,
+ "windBearing": 313,
+ "cloudCover": 0.37,
+ "uvIndex": 3.98,
+ "uvIndexTime": 1770573600,
+ "visibility": 16.09,
+ "temperatureMin": -12.3,
+ "temperatureMinTime": 1770541200,
+ "temperatureMax": -7.86,
+ "temperatureMaxTime": 1770595200,
+ "apparentTemperatureMin": -21.66,
+ "apparentTemperatureMinTime": 1770541200,
+ "apparentTemperatureMax": -14.7,
+ "apparentTemperatureMaxTime": 1770584400
+ },
+ {
+ "time": 1770613200,
+ "summary": "Mostly clear until night.",
+ "icon": "clear-day",
+ "sunriseTime": 1770638253,
+ "sunsetTime": 1770675806,
+ "moonPhase": 0.75,
+ "precipIntensity": 0.0,
+ "precipIntensityMax": 0.0,
+ "precipIntensityMaxTime": 1770613200,
+ "precipProbability": 0.07,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperatureHigh": -4.77,
+ "temperatureHighTime": 1770670800,
+ "temperatureLow": -7.39,
+ "temperatureLowTime": 1770721200,
+ "apparentTemperatureHigh": -10.59,
+ "apparentTemperatureHighTime": 1770670800,
+ "apparentTemperatureLow": -14.19,
+ "apparentTemperatureLowTime": 1770714000,
+ "dewPoint": -13.37,
+ "humidity": 0.64,
+ "pressure": 1023.19,
+ "windSpeed": 5.64,
+ "windGust": 8.0,
+ "windGustTime": 1770670800,
+ "windBearing": 306,
+ "cloudCover": 0.35,
+ "uvIndex": 3.54,
+ "uvIndexTime": 1770660000,
+ "visibility": 16.09,
+ "temperatureMin": -10.96,
+ "temperatureMinTime": 1770638400,
+ "temperatureMax": -4.77,
+ "temperatureMaxTime": 1770670800,
+ "apparentTemperatureMin": -18.23,
+ "apparentTemperatureMinTime": 1770638400,
+ "apparentTemperatureMax": -10.59,
+ "apparentTemperatureMaxTime": 1770670800
+ },
+ {
+ "time": 1770699600,
+ "summary": "Mostly clear until evening.",
+ "icon": "clear-day",
+ "sunriseTime": 1770724581,
+ "sunsetTime": 1770762279,
+ "moonPhase": 0.78,
+ "precipIntensity": 0.0,
+ "precipIntensityMax": 0.0,
+ "precipIntensityMaxTime": 1770699600,
+ "precipProbability": 0.0,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperatureHigh": -1.3,
+ "temperatureHighTime": 1770757200,
+ "temperatureLow": -4.83,
+ "temperatureLowTime": 1770807600,
+ "apparentTemperatureHigh": -6.5,
+ "apparentTemperatureHighTime": 1770757200,
+ "apparentTemperatureLow": -10.85,
+ "apparentTemperatureLowTime": 1770807600,
+ "dewPoint": -10.03,
+ "humidity": 0.65,
+ "pressure": 1021.43,
+ "windSpeed": 4.8,
+ "windGust": 6.78,
+ "windGustTime": 1770699600,
+ "windBearing": 303,
+ "cloudCover": 0.37,
+ "uvIndex": 4.35,
+ "uvIndexTime": 1770746400,
+ "visibility": 15.2,
+ "temperatureMin": -7.39,
+ "temperatureMinTime": 1770721200,
+ "temperatureMax": -1.3,
+ "temperatureMaxTime": 1770757200,
+ "apparentTemperatureMin": -14.19,
+ "apparentTemperatureMinTime": 1770714000,
+ "apparentTemperatureMax": -6.5,
+ "apparentTemperatureMaxTime": 1770757200
+ },
+ {
+ "time": 1770786000,
+ "summary": "Hazy in the afternoon.",
+ "icon": "fog",
+ "sunriseTime": 1770810908,
+ "sunsetTime": 1770848753,
+ "moonPhase": 0.81,
+ "precipIntensity": 0.0,
+ "precipIntensityMax": 0.0,
+ "precipIntensityMaxTime": 1770786000,
+ "precipProbability": 0.08,
+ "precipAccumulation": 0.0,
+ "precipType": "snow",
+ "temperatureHigh": 2.11,
+ "temperatureHighTime": 1770836400,
+ "temperatureLow": -5.5,
+ "temperatureLowTime": 1770865200,
+ "apparentTemperatureHigh": -2.01,
+ "apparentTemperatureHighTime": 1770836400,
+ "apparentTemperatureLow": -8.93,
+ "apparentTemperatureLowTime": 1770876000,
+ "dewPoint": -6.87,
+ "humidity": 0.78,
+ "pressure": 1018.44,
+ "windSpeed": 3.33,
+ "windGust": 7.15,
+ "windGustTime": 1770854400,
+ "windBearing": 303,
+ "cloudCover": 0.5,
+ "uvIndex": 0.47,
+ "uvIndexTime": 1770832800,
+ "visibility": 10.62,
+ "temperatureMin": -5.5,
+ "temperatureMinTime": 1770865200,
+ "temperatureMax": 2.11,
+ "temperatureMaxTime": 1770836400,
+ "apparentTemperatureMin": -10.85,
+ "apparentTemperatureMinTime": 1770811200,
+ "apparentTemperatureMax": -2.01,
+ "apparentTemperatureMaxTime": 1770836400
+ },
+ {
+ "time": 1770872400,
+ "summary": "Possible snow (< 4 cm.) starting in the evening.",
+ "icon": "partly-cloudy-day",
+ "sunriseTime": 1770897234,
+ "sunsetTime": 1770935226,
+ "moonPhase": 0.84,
+ "precipIntensity": 0.15,
+ "precipIntensityMax": 1.008,
+ "precipIntensityMaxTime": 1770955200,
+ "precipProbability": 0.12,
+ "precipAccumulation": 0.9236,
+ "precipType": "snow",
+ "temperatureHigh": -0.19,
+ "temperatureHighTime": 1770919200,
+ "temperatureLow": -2.21,
+ "temperatureLowTime": 1770962400,
+ "apparentTemperatureHigh": 1.12,
+ "apparentTemperatureHighTime": 1770919200,
+ "apparentTemperatureLow": -7.73,
+ "apparentTemperatureLowTime": 1770980400,
+ "dewPoint": -4.45,
+ "humidity": 0.78,
+ "pressure": 1023.22,
+ "windSpeed": 0.95,
+ "windGust": 11.32,
+ "windGustTime": 1770886800,
+ "windBearing": 248,
+ "cloudCover": 0.47,
+ "uvIndex": 3.94,
+ "uvIndexTime": 1770919200,
+ "visibility": 16.09,
+ "temperatureMin": -5.35,
+ "temperatureMinTime": 1770872400,
+ "temperatureMax": -0.19,
+ "temperatureMaxTime": 1770919200,
+ "apparentTemperatureMin": -8.93,
+ "apparentTemperatureMinTime": 1770876000,
+ "apparentTemperatureMax": 1.12,
+ "apparentTemperatureMaxTime": 1770919200
+ },
+ {
+ "time": 1770958800,
+ "summary": "Light snow (< 10 cm.) throughout the day.",
+ "icon": "snow",
+ "sunriseTime": 1770983559,
+ "sunsetTime": 1771021699,
+ "moonPhase": 0.87,
+ "precipIntensity": 0.381,
+ "precipIntensityMax": 1.368,
+ "precipIntensityMaxTime": 1770962400,
+ "precipProbability": 0.34,
+ "precipAccumulation": 4.0291,
+ "precipType": "snow",
+ "temperatureHigh": -0.77,
+ "temperatureHighTime": 1771023600,
+ "temperatureLow": -0.81,
+ "temperatureLowTime": 1771048800,
+ "apparentTemperatureHigh": -3.43,
+ "apparentTemperatureHighTime": 1771005600,
+ "apparentTemperatureLow": -5.95,
+ "apparentTemperatureLowTime": 1771059600,
+ "dewPoint": -2.67,
+ "humidity": 0.8,
+ "pressure": 1015.78,
+ "windSpeed": 3.24,
+ "windGust": 12.21,
+ "windGustTime": 1771038000,
+ "windBearing": 30,
+ "cloudCover": 0.36,
+ "uvIndex": 3.8,
+ "uvIndexTime": 1771005600,
+ "visibility": 16.09,
+ "temperatureMin": -2.21,
+ "temperatureMinTime": 1770962400,
+ "temperatureMax": -0.64,
+ "temperatureMaxTime": 1771027200,
+ "apparentTemperatureMin": -7.91,
+ "apparentTemperatureMinTime": 1770984000,
+ "apparentTemperatureMax": -3.43,
+ "apparentTemperatureMaxTime": 1771005600
+ }
+ ]
+ },
+ "alerts": [
+ {
+ "title": "Extreme Cold Warning",
+ "regions": [
+ "Eastern Passaic",
+ "Hudson",
+ "Western Bergen",
+ "Eastern Bergen",
+ "Western Essex",
+ "Eastern Essex",
+ "Western Union",
+ "Eastern Union",
+ "Putnam",
+ "Rockland",
+ "Northern Westchester",
+ "Southern Westchester",
+ "New York (Manhattan)",
+ "Bronx",
+ "Richmond (Staten Is.)",
+ "Kings (Brooklyn)",
+ "Northern Queens",
+ "Southern Queens"
+ ],
+ "severity": "Severe",
+ "time": 1770402120,
+ "expires": 1770458400,
+ "description": "* WHAT...For the Wind Advisory, northwest winds 20 to 30 mph with gusts up to 50 mph expected. For the Extreme Cold Warning, dangerously cold wind chills as low as 20 below expected.\n* WHERE...Portions of northeast New Jersey and southeast New York.\n* WHEN...For the Wind Advisory, from 9 AM Saturday to midnight EST Saturday Night. For the Extreme Cold Warning, from 10 AM Saturday to 1 PM EST Sunday.\n* IMPACTS...Gusty winds will blow around unsecured objects. Tree limbs could be blown down and a few power outages may result. The cold wind chills could cause frostbite on exposed skin in as little as 30 minutes.",
+ "uri": "https://api.weather.gov/alerts/urn:oid:2.49.0.1.840.0.5df73ec191a300e305a2e7beb31cdbaded01fd49.004.1"
+ },
+ {
+ "title": "Wind Advisory",
+ "regions": [
+ "Eastern Passaic",
+ "Hudson",
+ "Western Bergen",
+ "Eastern Bergen",
+ "Western Essex",
+ "Eastern Essex",
+ "Western Union",
+ "Eastern Union",
+ "Putnam",
+ "Rockland",
+ "Northern Westchester",
+ "Southern Westchester",
+ "New York (Manhattan)",
+ "Bronx",
+ "Richmond (Staten Is.)",
+ "Kings (Brooklyn)",
+ "Northern Queens",
+ "Southern Queens"
+ ],
+ "severity": "Moderate",
+ "time": 1770402120,
+ "expires": 1770458400,
+ "description": "* WHAT...For the Wind Advisory, northwest winds 20 to 30 mph with gusts up to 50 mph expected. For the Extreme Cold Warning, dangerously cold wind chills as low as 20 below expected.\n* WHERE...Portions of northeast New Jersey and southeast New York.\n* WHEN...For the Wind Advisory, from 9 AM Saturday to midnight EST Saturday Night. For the Extreme Cold Warning, from 10 AM Saturday to 1 PM EST Sunday.\n* IMPACTS...Gusty winds will blow around unsecured objects. Tree limbs could be blown down and a few power outages may result. The cold wind chills could cause frostbite on exposed skin in as little as 30 minutes.",
+ "uri": "https://api.weather.gov/alerts/urn:oid:2.49.0.1.840.0.5df73ec191a300e305a2e7beb31cdbaded01fd49.004.2"
+ }
+ ],
+ "flags": {
+ "sources": ["ETOPO1", "hrrrsubh", "rtma_ru", "hrrr_0-18", "nbm", "nbm_fire", "dwd_mosmix", "ecmwf_ifs", "hrrr_18-48", "gfs", "gefs"],
+ "sourceTimes": {
+ "hrrr_subh": "2026-02-06 19Z",
+ "rtma_ru": "2026-02-06 21:15Z",
+ "hrrr_0-18": "2026-02-06 19Z",
+ "nbm": "2026-02-03 23Z",
+ "nbm_fire": "2026-02-06 12Z",
+ "dwd_mosmix": "2026-02-06 20Z",
+ "ecmwf_ifs": "2026-02-06 12Z",
+ "hrrr_18-48": "2026-02-06 18Z",
+ "gfs": "2026-02-06 12Z",
+ "gefs": "2026-02-06 12Z"
+ },
+ "nearest-station": 10.96,
+ "units": "si",
+ "version": "V2.9.1"
+ }
+}
diff --git a/tests/mocks/weather_smhi.json b/tests/mocks/weather_smhi.json
new file mode 100644
index 00000000..c08a6e85
--- /dev/null
+++ b/tests/mocks/weather_smhi.json
@@ -0,0 +1,1907 @@
+{
+ "approvedTime": "2026-02-06T21:31:33Z",
+ "referenceTime": "2026-02-06T21:00:00Z",
+ "geometry": { "type": "Point", "coordinates": [[18.089437, 59.339222]] },
+ "timeSeries": [
+ {
+ "validTime": "2026-02-06T22:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.5] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [40] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.3] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [7.8] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [88] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1013.6] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [12.3] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [100] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-06T23:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.4] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [38] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.2] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [7.7] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [88] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1013.9] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [12.8] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [100] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-07T00:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.3] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [38] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.9] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [7.7] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [87] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1014.2] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [75.0] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [7] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [100] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-07T01:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.2] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [37] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.7] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [7.2] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [87] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1014.2] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [12.9] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [6] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [100] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-07T02:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.2] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [31] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.5] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [6.8] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [88] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1014.2] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [12.6] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [5] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-07T03:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.2] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [33] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.6] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [6.5] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [88] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1014.1] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [75.0] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [6] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-07T04:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.2] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [35] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.6] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [6.8] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [89] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1014.4] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [12.0] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [7] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-07T05:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.4] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [35] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.8] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [6.9] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [89] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1014.7] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [11.8] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [5] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-07T06:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.6] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [37] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.4] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [8.0] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [88] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1015.3] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [12.5] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-07T07:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.7] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [36] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.6] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [8.5] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [88] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1015.9] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [12.8] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [3] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-07T08:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.5] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [42] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.8] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [8.9] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [86] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1016.5] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [14.1] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [3] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [7] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [3] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-07T09:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.2] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [41] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.3] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [8.7] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [82] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1017.3] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [17.1] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [7] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [6] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-07T10:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-4.7] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [44] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.2] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [7.9] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [77] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1017.8] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [20.1] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [7] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [5] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-07T11:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-4.1] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [48] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.3] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [7.9] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [64] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1018.1] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [28.8] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [7] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [6] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [3] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-07T12:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-3.9] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [47] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.3] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [7.9] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [50] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1018.1] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [38.9] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [7] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [2] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-07T13:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-3.6] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [42] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.2] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [7.9] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [52] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1018.1] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [75.0] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [1] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-07T14:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-3.5] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [38] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.0] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [7.7] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [71] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1018.4] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [23.8] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-07T15:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-3.9] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [32] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.7] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [7.3] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [76] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1018.9] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [75.0] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-07T16:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-4.2] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [31] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.1] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [6.6] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [80] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1019.2] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [75.0] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [6] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [6] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-07T17:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-4.6] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [38] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.4] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [5.6] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [84] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1019.6] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [75.0] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [3] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-07T18:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.4] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [36] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.6] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [7.0] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [87] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1020.1] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [13.3] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [1] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [1] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-07T19:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-6.1] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [33] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.6] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [6.0] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [86] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1020.5] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [13.7] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-07T20:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-6.5] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [32] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.0] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [7.0] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [84] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1021.0] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [15.3] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [1] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [1] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [2] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-07T21:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-6.8] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [32] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.2] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [7.3] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [90] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1021.4] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [75.0] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [3] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [3] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [2] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-07T22:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-6.3] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [38] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.2] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [7.3] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [90] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1021.9] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [10.9] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [3] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [3] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [2] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-07T23:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.9] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [44] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.5] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [8.1] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [89] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1022.3] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [75.0] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [3] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-08T00:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.9] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [46] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.8] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [8.6] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [86] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1022.5] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [13.9] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [6] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [6] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-08T01:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.8] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [53] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.9] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [8.9] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [84] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1022.9] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [75.0] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-08T02:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.8] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [49] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.6] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [8.9] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [84] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1023.2] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [75.0] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-08T03:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.9] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [39] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.1] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [8.4] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [85] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1023.6] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [75.0] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-08T04:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-6.0] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [40] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.7] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [7.6] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [86] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1023.9] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [5.3] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-08T05:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.8] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [46] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.3] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [6.8] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [87] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1024.0] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [5.6] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-08T06:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.4] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [63] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.4] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [6.2] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [83] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1024.2] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [75.0] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-08T07:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.3] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [55] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.7] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [6.9] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [83] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1024.5] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [16.1] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-08T08:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.2] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [54] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.4] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [6.7] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [83] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1024.8] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [15.9] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-08T09:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-4.8] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [53] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.7] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [6.8] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [85] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1025.1] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [14.7] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-08T10:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-3.8] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [66] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.5] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [6.8] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [82] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1025.2] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [75.0] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-08T11:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-2.6] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [103] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.1] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [6.4] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [64] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1025.1] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [29.0] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-08T12:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-2.2] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [116] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.7] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [7.2] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [55] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1025.0] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [75.0] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-08T13:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-2.0] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [118] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.5] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [6.9] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [54] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1024.9] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [75.0] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [-0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [-0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-08T14:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-2.1] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [123] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.1] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [6.4] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [55] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1025.0] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [35.2] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [-0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [-0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-08T15:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-2.9] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [120] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [2.5] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [5.4] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [60] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1025.0] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [31.5] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [7] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [7] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [-0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [-0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-08T16:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-4.2] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [116] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [2.1] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.1] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [65] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1024.8] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [75.0] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [5] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [5] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [-0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [3] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-08T17:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.2] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [115] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [1.8] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.1] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [71] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1024.6] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [24.3] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [5] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [5] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [3] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-08T18:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-6.7] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [107] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [1.4] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [2.4] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [78] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1024.5] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [19.3] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [5] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [5] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [-0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [3] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-08T19:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-7.5] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [117] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [1.3] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [1.9] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [80] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1024.4] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [17.9] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [6] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [6] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [-0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-08T20:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-8.1] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [124] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [1.2] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [1.7] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [80] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1024.3] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [75.0] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [7] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [7] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-08T21:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-8.2] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [138] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [1.2] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [1.7] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [80] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1024.2] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [18.0] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [7] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [7] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [-0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-08T22:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-8.3] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [157] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [1.4] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [1.8] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [80] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1024.0] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [18.2] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [-0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [-0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-08T23:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-8.3] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [174] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [1.4] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [1.9] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [80] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1023.6] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [18.2] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [-0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-09T00:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-8.3] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [182] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [1.7] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [2.2] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [79] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1023.2] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [18.8] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [-0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-09T03:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-7.5] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [223] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [2.6] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.9] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [78] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1021.3] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [19.5] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [-0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [-0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [-0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-09T06:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-7.0] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [251] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [2.4] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.8] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [77] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1020.4] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [20.4] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [7] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [7] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [-0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [-0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-09T09:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-7.0] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [264] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [2.8] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.7] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [76] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1019.9] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [21.1] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-09T12:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-7.0] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [254] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.5] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [7.8] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [84] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1017.7] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [19.1] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-09T18:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-9.4] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [250] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [2.3] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.5] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [86] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1015.3] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [22.9] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-10T00:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-9.9] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [271] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [0.8] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [2.0] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [87] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1012.9] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [7.3] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-10T06:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-10.3] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [253] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [1.3] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.3] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [86] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1009.6] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [8.2] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [7] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-10T12:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-9.1] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [249] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [2.3] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [5.3] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [80] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1006.5] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [10.3] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [-9] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [0] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-10T18:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-10.3] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [318] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [1.0] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.0] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [85] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1003.7] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [13.4] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [100] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-11T00:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-13.1] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [314] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [0.5] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [1.5] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [91] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1001.5] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [13.1] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [3] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [1] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [100] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [3] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-11T06:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-11.2] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [348] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [1.0] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [2.3] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [88] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [999.3] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [43.7] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.2] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [100] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-11T12:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.1] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [344] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [2.0] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.5] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [82] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [998.2] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [49.2] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [7] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [0] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.2] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [100] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-11T18:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.8] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [52] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [3.7] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [6.5] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [86] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [996.1] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [40.7] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [3] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.3] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [100] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-12T00:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-6.1] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [49] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.1] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [7.3] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [87] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [994.7] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [39.1] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [3] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [3] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.2] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.4] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [100] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-12T06:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-6.6] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [56] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.9] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [8.6] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [87] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [993.3] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [29.9] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [3] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.3] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [100] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-12T12:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-5.7] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [55] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [5.5] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [10.3] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [81] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [993.6] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [31.5] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [3] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.5] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [100] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-12T18:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-7.1] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [45] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [5.2] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [10.3] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [86] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [994.2] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [31.7] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.2] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.4] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [100] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-13T00:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-7.9] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [38] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [5.0] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [9.5] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [86] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [994.7] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [31.1] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [5] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.6] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [88] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [6] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-13T12:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-7.7] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [19] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [5.4] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [10.5] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [80] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [996.6] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [33.8] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [8] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [7] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [2] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.5] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [100] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-14T00:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-10.0] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [3] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.7] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [9.4] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [85] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [999.6] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [37.5] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [7] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [6] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [2] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.3] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [100] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-14T12:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-8.0] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [350] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.9] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [9.6] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [75] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1002.7] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [38.9] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [6] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [5] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [3] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [1] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.3] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [100] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-15T00:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-11.4] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [321] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.2] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [8.1] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [83] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1007.3] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [40.6] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [5] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [3] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [3] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [1] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.3] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [100] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [3] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-15T12:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-7.9] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [304] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.1] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [8.3] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [72] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1011.2] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [43.3] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [3] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [2] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [1] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.4] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [100] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [3] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-16T00:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-9.4] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [292] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.2] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [7.7] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [85] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1013.8] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [43.3] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [5] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [2] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [1] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [100] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [3] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ },
+ {
+ "validTime": "2026-02-16T12:00:00Z",
+ "parameters": [
+ { "name": "t", "levelType": "hl", "level": 2, "unit": "Cel", "values": [-4.8] },
+ { "name": "wd", "levelType": "hl", "level": 10, "unit": "degree", "values": [295] },
+ { "name": "ws", "levelType": "hl", "level": 10, "unit": "m/s", "values": [4.1] },
+ { "name": "gust", "levelType": "hl", "level": 10, "unit": "m/s", "values": [8.3] },
+ { "name": "r", "levelType": "hl", "level": 2, "unit": "percent", "values": [78] },
+ { "name": "msl", "levelType": "hmsl", "level": 0, "unit": "hPa", "values": [1014.7] },
+ { "name": "vis", "levelType": "hl", "level": 2, "unit": "km", "values": [45.8] },
+ { "name": "tstm", "levelType": "hl", "level": 0, "unit": "percent", "values": [0] },
+ { "name": "tcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [6] },
+ { "name": "lcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [4] },
+ { "name": "mcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [3] },
+ { "name": "hcc_mean", "levelType": "hl", "level": 0, "unit": "octas", "values": [2] },
+ { "name": "pmean", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "pmin", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.1] },
+ { "name": "pmax", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.2] },
+ { "name": "pmedian", "levelType": "hl", "level": 0, "unit": "kg/m2/h", "values": [0.0] },
+ { "name": "spp", "levelType": "hl", "level": 0, "unit": "percent", "values": [100] },
+ { "name": "pcat", "levelType": "hl", "level": 0, "unit": "category", "values": [1] },
+ { "name": "Wsymb2", "levelType": "hl", "level": 0, "unit": "category", "values": [4] },
+ { "name": "tp", "levelType": "hl", "level": 0, "unit": "kg/m2", "values": [0.0] }
+ ]
+ }
+ ]
+}
diff --git a/tests/mocks/weather_ukmetoffice.json b/tests/mocks/weather_ukmetoffice.json
new file mode 100644
index 00000000..1a5663e8
--- /dev/null
+++ b/tests/mocks/weather_ukmetoffice.json
@@ -0,0 +1,1062 @@
+{
+ "type": "FeatureCollection",
+ "features": [
+ {
+ "type": "Feature",
+ "geometry": { "type": "Point", "coordinates": [-0.12480000000000001, 51.5081, 11.0] },
+ "properties": {
+ "location": { "name": "London" },
+ "requestPointDistance": 221.7807,
+ "modelRunDate": "2026-02-07T12:00Z",
+ "timeSeries": [
+ {
+ "time": "2026-02-07T12:00Z",
+ "screenTemperature": 9.56,
+ "maxScreenAirTemp": 9.56,
+ "minScreenAirTemp": 9.11,
+ "screenDewPointTemperature": 8.51,
+ "feelsLikeTemperature": 8.74,
+ "windSpeed10m": 1.9,
+ "windDirectionFrom10m": 165,
+ "windGustSpeed10m": 7.72,
+ "max10mWindGust": 9.32,
+ "visibility": 8550,
+ "screenRelativeHumidity": 93.08,
+ "mslp": 99440,
+ "uvIndex": 1,
+ "significantWeatherCode": 8,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 15
+ },
+ {
+ "time": "2026-02-07T13:00Z",
+ "screenTemperature": 9.67,
+ "maxScreenAirTemp": 9.69,
+ "minScreenAirTemp": 9.56,
+ "screenDewPointTemperature": 8.39,
+ "feelsLikeTemperature": 8.76,
+ "windSpeed10m": 2.13,
+ "windDirectionFrom10m": 188,
+ "windGustSpeed10m": 7.31,
+ "max10mWindGust": 8.26,
+ "visibility": 7592,
+ "screenRelativeHumidity": 91.56,
+ "mslp": 99435,
+ "uvIndex": 1,
+ "significantWeatherCode": 11,
+ "precipitationRate": 0.06,
+ "totalPrecipAmount": 0.04,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 33
+ },
+ {
+ "time": "2026-02-07T14:00Z",
+ "screenTemperature": 9.91,
+ "maxScreenAirTemp": 10.01,
+ "minScreenAirTemp": 9.67,
+ "screenDewPointTemperature": 8.62,
+ "feelsLikeTemperature": 8.29,
+ "windSpeed10m": 3.22,
+ "windDirectionFrom10m": 189,
+ "windGustSpeed10m": 8.15,
+ "max10mWindGust": 8.64,
+ "visibility": 9509,
+ "screenRelativeHumidity": 91.56,
+ "mslp": 99496,
+ "uvIndex": 1,
+ "significantWeatherCode": 14,
+ "precipitationRate": 1.5,
+ "totalPrecipAmount": 0.23,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 62
+ },
+ {
+ "time": "2026-02-07T15:00Z",
+ "screenTemperature": 10.21,
+ "maxScreenAirTemp": 10.4,
+ "minScreenAirTemp": 9.91,
+ "screenDewPointTemperature": 8.5,
+ "feelsLikeTemperature": 8.19,
+ "windSpeed10m": 4.1,
+ "windDirectionFrom10m": 184,
+ "windGustSpeed10m": 9.49,
+ "max10mWindGust": 9.56,
+ "visibility": 9666,
+ "screenRelativeHumidity": 89.1,
+ "mslp": 99550,
+ "uvIndex": 1,
+ "significantWeatherCode": 12,
+ "precipitationRate": 0.24,
+ "totalPrecipAmount": 0.09,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 55
+ },
+ {
+ "time": "2026-02-07T16:00Z",
+ "screenTemperature": 10.22,
+ "maxScreenAirTemp": 10.24,
+ "minScreenAirTemp": 10.18,
+ "screenDewPointTemperature": 8.24,
+ "feelsLikeTemperature": 8.28,
+ "windSpeed10m": 3.92,
+ "windDirectionFrom10m": 187,
+ "windGustSpeed10m": 8.95,
+ "max10mWindGust": 9.64,
+ "visibility": 7525,
+ "screenRelativeHumidity": 87.43,
+ "mslp": 99620,
+ "uvIndex": 1,
+ "significantWeatherCode": 12,
+ "precipitationRate": 0.53,
+ "totalPrecipAmount": 0.08,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 59
+ },
+ {
+ "time": "2026-02-07T17:00Z",
+ "screenTemperature": 9.99,
+ "maxScreenAirTemp": 10.22,
+ "minScreenAirTemp": 9.98,
+ "screenDewPointTemperature": 8.13,
+ "feelsLikeTemperature": 8.22,
+ "windSpeed10m": 3.51,
+ "windDirectionFrom10m": 180,
+ "windGustSpeed10m": 8.31,
+ "max10mWindGust": 9.11,
+ "visibility": 11604,
+ "screenRelativeHumidity": 88.07,
+ "mslp": 99680,
+ "uvIndex": 0,
+ "significantWeatherCode": 7,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 5
+ },
+ {
+ "time": "2026-02-07T18:00Z",
+ "screenTemperature": 9.89,
+ "maxScreenAirTemp": 9.99,
+ "minScreenAirTemp": 9.84,
+ "screenDewPointTemperature": 8.13,
+ "feelsLikeTemperature": 8.07,
+ "windSpeed10m": 3.54,
+ "windDirectionFrom10m": 181,
+ "windGustSpeed10m": 8.86,
+ "max10mWindGust": 9.03,
+ "visibility": 11879,
+ "screenRelativeHumidity": 88.72,
+ "mslp": 99760,
+ "uvIndex": 0,
+ "significantWeatherCode": 7,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 6
+ },
+ {
+ "time": "2026-02-07T19:00Z",
+ "screenTemperature": 9.68,
+ "maxScreenAirTemp": 9.89,
+ "minScreenAirTemp": 9.67,
+ "screenDewPointTemperature": 8.06,
+ "feelsLikeTemperature": 7.86,
+ "windSpeed10m": 3.45,
+ "windDirectionFrom10m": 183,
+ "windGustSpeed10m": 8.57,
+ "max10mWindGust": 8.86,
+ "visibility": 12104,
+ "screenRelativeHumidity": 89.57,
+ "mslp": 99816,
+ "uvIndex": 0,
+ "significantWeatherCode": 7,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 6
+ },
+ {
+ "time": "2026-02-07T20:00Z",
+ "screenTemperature": 9.59,
+ "maxScreenAirTemp": 9.68,
+ "minScreenAirTemp": 9.57,
+ "screenDewPointTemperature": 8.02,
+ "feelsLikeTemperature": 7.96,
+ "windSpeed10m": 3.08,
+ "windDirectionFrom10m": 179,
+ "windGustSpeed10m": 8.15,
+ "max10mWindGust": 8.88,
+ "visibility": 12574,
+ "screenRelativeHumidity": 89.91,
+ "mslp": 99876,
+ "uvIndex": 0,
+ "significantWeatherCode": 7,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 4
+ },
+ {
+ "time": "2026-02-07T21:00Z",
+ "screenTemperature": 9.34,
+ "maxScreenAirTemp": 9.59,
+ "minScreenAirTemp": 9.34,
+ "screenDewPointTemperature": 8.01,
+ "feelsLikeTemperature": 7.65,
+ "windSpeed10m": 3.12,
+ "windDirectionFrom10m": 180,
+ "windGustSpeed10m": 7.95,
+ "max10mWindGust": 8.46,
+ "visibility": 12829,
+ "screenRelativeHumidity": 91.36,
+ "mslp": 99932,
+ "uvIndex": 0,
+ "significantWeatherCode": 2,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 3
+ },
+ {
+ "time": "2026-02-07T22:00Z",
+ "screenTemperature": 9.0,
+ "maxScreenAirTemp": 9.34,
+ "minScreenAirTemp": 8.98,
+ "screenDewPointTemperature": 7.71,
+ "feelsLikeTemperature": 7.27,
+ "windSpeed10m": 3.08,
+ "windDirectionFrom10m": 177,
+ "windGustSpeed10m": 8.34,
+ "max10mWindGust": 8.76,
+ "visibility": 12923,
+ "screenRelativeHumidity": 91.6,
+ "mslp": 99986,
+ "uvIndex": 0,
+ "significantWeatherCode": 0,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 2
+ },
+ {
+ "time": "2026-02-07T23:00Z",
+ "screenTemperature": 8.74,
+ "maxScreenAirTemp": 8.98,
+ "minScreenAirTemp": 8.71,
+ "screenDewPointTemperature": 7.57,
+ "feelsLikeTemperature": 7.09,
+ "windSpeed10m": 2.86,
+ "windDirectionFrom10m": 177,
+ "windGustSpeed10m": 7.68,
+ "max10mWindGust": 8.78,
+ "visibility": 14190,
+ "screenRelativeHumidity": 92.32,
+ "mslp": 100056,
+ "uvIndex": 0,
+ "significantWeatherCode": 0,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 2
+ },
+ {
+ "time": "2026-02-08T00:00Z",
+ "screenTemperature": 8.56,
+ "maxScreenAirTemp": 8.74,
+ "minScreenAirTemp": 8.56,
+ "screenDewPointTemperature": 7.59,
+ "feelsLikeTemperature": 7.12,
+ "windSpeed10m": 2.52,
+ "windDirectionFrom10m": 184,
+ "windGustSpeed10m": 7.13,
+ "max10mWindGust": 8.49,
+ "visibility": 13732,
+ "screenRelativeHumidity": 93.62,
+ "mslp": 100096,
+ "uvIndex": 0,
+ "significantWeatherCode": 2,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 2
+ },
+ {
+ "time": "2026-02-08T01:00Z",
+ "screenTemperature": 8.4,
+ "maxScreenAirTemp": 8.56,
+ "minScreenAirTemp": 8.38,
+ "screenDewPointTemperature": 7.27,
+ "feelsLikeTemperature": 7.08,
+ "windSpeed10m": 2.32,
+ "windDirectionFrom10m": 180,
+ "windGustSpeed10m": 6.73,
+ "max10mWindGust": 7.62,
+ "visibility": 14599,
+ "screenRelativeHumidity": 92.57,
+ "mslp": 100150,
+ "uvIndex": 0,
+ "significantWeatherCode": 2,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 2
+ },
+ {
+ "time": "2026-02-08T02:00Z",
+ "screenTemperature": 8.14,
+ "maxScreenAirTemp": 8.4,
+ "minScreenAirTemp": 8.13,
+ "screenDewPointTemperature": 7.17,
+ "feelsLikeTemperature": 7.11,
+ "windSpeed10m": 1.93,
+ "windDirectionFrom10m": 191,
+ "windGustSpeed10m": 5.96,
+ "max10mWindGust": 7.23,
+ "visibility": 12665,
+ "screenRelativeHumidity": 93.62,
+ "mslp": 100190,
+ "uvIndex": 0,
+ "significantWeatherCode": 7,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 5
+ },
+ {
+ "time": "2026-02-08T03:00Z",
+ "screenTemperature": 7.9,
+ "maxScreenAirTemp": 8.14,
+ "minScreenAirTemp": 7.89,
+ "screenDewPointTemperature": 7.12,
+ "feelsLikeTemperature": 7.1,
+ "windSpeed10m": 1.63,
+ "windDirectionFrom10m": 195,
+ "windGustSpeed10m": 5.28,
+ "max10mWindGust": 6.22,
+ "visibility": 10018,
+ "screenRelativeHumidity": 94.84,
+ "mslp": 100224,
+ "uvIndex": 0,
+ "significantWeatherCode": 7,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 5
+ },
+ {
+ "time": "2026-02-08T04:00Z",
+ "screenTemperature": 7.78,
+ "maxScreenAirTemp": 7.9,
+ "minScreenAirTemp": 7.76,
+ "screenDewPointTemperature": 7.07,
+ "feelsLikeTemperature": 6.86,
+ "windSpeed10m": 1.74,
+ "windDirectionFrom10m": 188,
+ "windGustSpeed10m": 5.13,
+ "max10mWindGust": 5.76,
+ "visibility": 8777,
+ "screenRelativeHumidity": 95.25,
+ "mslp": 100253,
+ "uvIndex": 0,
+ "significantWeatherCode": 7,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 5
+ },
+ {
+ "time": "2026-02-08T05:00Z",
+ "screenTemperature": 7.67,
+ "maxScreenAirTemp": 7.78,
+ "minScreenAirTemp": 7.62,
+ "screenDewPointTemperature": 7.02,
+ "feelsLikeTemperature": 6.77,
+ "windSpeed10m": 1.64,
+ "windDirectionFrom10m": 177,
+ "windGustSpeed10m": 5.17,
+ "max10mWindGust": 5.88,
+ "visibility": 7296,
+ "screenRelativeHumidity": 95.73,
+ "mslp": 100280,
+ "uvIndex": 0,
+ "significantWeatherCode": 7,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 5
+ },
+ {
+ "time": "2026-02-08T06:00Z",
+ "screenTemperature": 7.52,
+ "maxScreenAirTemp": 7.67,
+ "minScreenAirTemp": 7.47,
+ "screenDewPointTemperature": 6.7,
+ "feelsLikeTemperature": 6.68,
+ "windSpeed10m": 1.6,
+ "windDirectionFrom10m": 183,
+ "windGustSpeed10m": 4.97,
+ "max10mWindGust": 5.64,
+ "visibility": 7420,
+ "screenRelativeHumidity": 94.66,
+ "mslp": 100327,
+ "uvIndex": 0,
+ "significantWeatherCode": 7,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 5
+ },
+ {
+ "time": "2026-02-08T07:00Z",
+ "screenTemperature": 7.63,
+ "maxScreenAirTemp": 7.64,
+ "minScreenAirTemp": 7.52,
+ "screenDewPointTemperature": 6.82,
+ "feelsLikeTemperature": 6.29,
+ "windSpeed10m": 2.18,
+ "windDirectionFrom10m": 182,
+ "windGustSpeed10m": 5.54,
+ "max10mWindGust": 6.01,
+ "visibility": 7504,
+ "screenRelativeHumidity": 94.7,
+ "mslp": 100390,
+ "uvIndex": 0,
+ "significantWeatherCode": 8,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 10
+ },
+ {
+ "time": "2026-02-08T08:00Z",
+ "screenTemperature": 7.81,
+ "maxScreenAirTemp": 7.81,
+ "minScreenAirTemp": 7.63,
+ "screenDewPointTemperature": 7.06,
+ "feelsLikeTemperature": 6.72,
+ "windSpeed10m": 1.93,
+ "windDirectionFrom10m": 190,
+ "windGustSpeed10m": 4.93,
+ "max10mWindGust": 5.86,
+ "visibility": 6197,
+ "screenRelativeHumidity": 95.08,
+ "mslp": 100450,
+ "uvIndex": 1,
+ "significantWeatherCode": 8,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 9
+ },
+ {
+ "time": "2026-02-08T09:00Z",
+ "screenTemperature": 8.12,
+ "maxScreenAirTemp": 8.13,
+ "minScreenAirTemp": 7.81,
+ "screenDewPointTemperature": 7.2,
+ "feelsLikeTemperature": 7.05,
+ "windSpeed10m": 1.95,
+ "windDirectionFrom10m": 180,
+ "windGustSpeed10m": 4.53,
+ "max10mWindGust": 4.92,
+ "visibility": 6327,
+ "screenRelativeHumidity": 94.03,
+ "mslp": 100503,
+ "uvIndex": 1,
+ "significantWeatherCode": 8,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 10
+ },
+ {
+ "time": "2026-02-08T10:00Z",
+ "screenTemperature": 8.86,
+ "maxScreenAirTemp": 8.86,
+ "minScreenAirTemp": 8.12,
+ "screenDewPointTemperature": 7.54,
+ "feelsLikeTemperature": 7.73,
+ "windSpeed10m": 2.17,
+ "windDirectionFrom10m": 176,
+ "windGustSpeed10m": 4.42,
+ "max10mWindGust": 4.54,
+ "visibility": 7222,
+ "screenRelativeHumidity": 91.55,
+ "mslp": 100533,
+ "uvIndex": 1,
+ "significantWeatherCode": 8,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 10
+ },
+ {
+ "time": "2026-02-08T11:00Z",
+ "screenTemperature": 9.57,
+ "maxScreenAirTemp": 9.57,
+ "minScreenAirTemp": 8.86,
+ "screenDewPointTemperature": 7.57,
+ "feelsLikeTemperature": 8.41,
+ "windSpeed10m": 2.37,
+ "windDirectionFrom10m": 181,
+ "windGustSpeed10m": 4.88,
+ "max10mWindGust": 4.88,
+ "visibility": 10651,
+ "screenRelativeHumidity": 87.5,
+ "mslp": 100560,
+ "uvIndex": 1,
+ "significantWeatherCode": 7,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 6
+ },
+ {
+ "time": "2026-02-08T12:00Z",
+ "screenTemperature": 10.27,
+ "maxScreenAirTemp": 10.28,
+ "minScreenAirTemp": 9.57,
+ "screenDewPointTemperature": 7.41,
+ "feelsLikeTemperature": 9.29,
+ "windSpeed10m": 2.28,
+ "windDirectionFrom10m": 185,
+ "windGustSpeed10m": 4.71,
+ "max10mWindGust": 4.71,
+ "visibility": 12395,
+ "screenRelativeHumidity": 82.51,
+ "mslp": 100560,
+ "uvIndex": 1,
+ "significantWeatherCode": 7,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 6
+ },
+ {
+ "time": "2026-02-08T13:00Z",
+ "screenTemperature": 10.75,
+ "maxScreenAirTemp": 10.76,
+ "minScreenAirTemp": 10.27,
+ "screenDewPointTemperature": 6.87,
+ "feelsLikeTemperature": 9.48,
+ "windSpeed10m": 2.77,
+ "windDirectionFrom10m": 184,
+ "windGustSpeed10m": 5.56,
+ "max10mWindGust": 5.56,
+ "visibility": 14708,
+ "screenRelativeHumidity": 76.97,
+ "mslp": 100530,
+ "uvIndex": 1,
+ "significantWeatherCode": 7,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 6
+ },
+ {
+ "time": "2026-02-08T14:00Z",
+ "screenTemperature": 10.84,
+ "maxScreenAirTemp": 10.88,
+ "minScreenAirTemp": 10.75,
+ "screenDewPointTemperature": 6.71,
+ "feelsLikeTemperature": 9.4,
+ "windSpeed10m": 3.1,
+ "windDirectionFrom10m": 186,
+ "windGustSpeed10m": 6.12,
+ "max10mWindGust": 6.29,
+ "visibility": 16685,
+ "screenRelativeHumidity": 75.74,
+ "mslp": 100530,
+ "uvIndex": 1,
+ "significantWeatherCode": 7,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 7
+ },
+ {
+ "time": "2026-02-08T15:00Z",
+ "screenTemperature": 10.76,
+ "maxScreenAirTemp": 10.84,
+ "minScreenAirTemp": 10.73,
+ "screenDewPointTemperature": 6.67,
+ "feelsLikeTemperature": 9.29,
+ "windSpeed10m": 3.11,
+ "windDirectionFrom10m": 182,
+ "windGustSpeed10m": 6.07,
+ "max10mWindGust": 6.26,
+ "visibility": 16963,
+ "screenRelativeHumidity": 75.87,
+ "mslp": 100527,
+ "uvIndex": 1,
+ "significantWeatherCode": 7,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 7
+ },
+ {
+ "time": "2026-02-08T16:00Z",
+ "screenTemperature": 10.36,
+ "maxScreenAirTemp": 10.76,
+ "minScreenAirTemp": 10.33,
+ "screenDewPointTemperature": 6.66,
+ "feelsLikeTemperature": 8.88,
+ "windSpeed10m": 3.07,
+ "windDirectionFrom10m": 180,
+ "windGustSpeed10m": 5.99,
+ "max10mWindGust": 6.33,
+ "visibility": 17519,
+ "screenRelativeHumidity": 77.89,
+ "mslp": 100530,
+ "uvIndex": 1,
+ "significantWeatherCode": 7,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 7
+ },
+ {
+ "time": "2026-02-08T17:00Z",
+ "screenTemperature": 9.94,
+ "maxScreenAirTemp": 10.36,
+ "minScreenAirTemp": 9.93,
+ "screenDewPointTemperature": 6.86,
+ "feelsLikeTemperature": 8.52,
+ "windSpeed10m": 2.84,
+ "windDirectionFrom10m": 179,
+ "windGustSpeed10m": 5.58,
+ "max10mWindGust": 6.05,
+ "visibility": 16071,
+ "screenRelativeHumidity": 81.23,
+ "mslp": 100550,
+ "uvIndex": 0,
+ "significantWeatherCode": 8,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 10
+ },
+ {
+ "time": "2026-02-08T18:00Z",
+ "screenTemperature": 9.55,
+ "maxScreenAirTemp": 9.94,
+ "minScreenAirTemp": 9.54,
+ "screenDewPointTemperature": 6.97,
+ "feelsLikeTemperature": 8.1,
+ "windSpeed10m": 2.81,
+ "windDirectionFrom10m": 176,
+ "windGustSpeed10m": 5.68,
+ "max10mWindGust": 6.14,
+ "visibility": 15755,
+ "screenRelativeHumidity": 83.93,
+ "mslp": 100560,
+ "uvIndex": 0,
+ "significantWeatherCode": 8,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 12
+ },
+ {
+ "time": "2026-02-08T19:00Z",
+ "screenTemperature": 9.23,
+ "maxScreenAirTemp": 9.55,
+ "minScreenAirTemp": 9.22,
+ "screenDewPointTemperature": 7.05,
+ "feelsLikeTemperature": 7.71,
+ "windSpeed10m": 2.83,
+ "windDirectionFrom10m": 168,
+ "windGustSpeed10m": 5.67,
+ "max10mWindGust": 6.27,
+ "visibility": 14548,
+ "screenRelativeHumidity": 86.32,
+ "mslp": 100547,
+ "uvIndex": 0,
+ "significantWeatherCode": 8,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 18
+ },
+ {
+ "time": "2026-02-08T20:00Z",
+ "screenTemperature": 9.05,
+ "maxScreenAirTemp": 9.23,
+ "minScreenAirTemp": 9.04,
+ "screenDewPointTemperature": 7.13,
+ "feelsLikeTemperature": 7.66,
+ "windSpeed10m": 2.57,
+ "windDirectionFrom10m": 173,
+ "windGustSpeed10m": 5.24,
+ "max10mWindGust": 6.08,
+ "visibility": 13961,
+ "screenRelativeHumidity": 87.79,
+ "mslp": 100547,
+ "uvIndex": 0,
+ "significantWeatherCode": 7,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 17
+ },
+ {
+ "time": "2026-02-08T21:00Z",
+ "screenTemperature": 8.81,
+ "maxScreenAirTemp": 9.05,
+ "minScreenAirTemp": 8.81,
+ "screenDewPointTemperature": 7.2,
+ "feelsLikeTemperature": 7.4,
+ "windSpeed10m": 2.56,
+ "windDirectionFrom10m": 163,
+ "windGustSpeed10m": 5.38,
+ "max10mWindGust": 5.73,
+ "visibility": 13739,
+ "screenRelativeHumidity": 89.7,
+ "mslp": 100540,
+ "uvIndex": 0,
+ "significantWeatherCode": 12,
+ "precipitationRate": 0.07,
+ "totalPrecipAmount": 0.2,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 45
+ },
+ {
+ "time": "2026-02-08T22:00Z",
+ "screenTemperature": 8.74,
+ "maxScreenAirTemp": 8.81,
+ "minScreenAirTemp": 8.72,
+ "screenDewPointTemperature": 7.12,
+ "feelsLikeTemperature": 7.36,
+ "windSpeed10m": 2.47,
+ "windDirectionFrom10m": 164,
+ "windGustSpeed10m": 5.43,
+ "max10mWindGust": 5.67,
+ "visibility": 11395,
+ "screenRelativeHumidity": 89.66,
+ "mslp": 100530,
+ "uvIndex": 0,
+ "significantWeatherCode": 9,
+ "precipitationRate": 0.23,
+ "totalPrecipAmount": 0.18,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 44
+ },
+ {
+ "time": "2026-02-08T23:00Z",
+ "screenTemperature": 8.57,
+ "maxScreenAirTemp": 8.74,
+ "minScreenAirTemp": 8.53,
+ "screenDewPointTemperature": 7.23,
+ "feelsLikeTemperature": 7.31,
+ "windSpeed10m": 2.28,
+ "windDirectionFrom10m": 149,
+ "windGustSpeed10m": 5.28,
+ "max10mWindGust": 5.87,
+ "visibility": 10051,
+ "screenRelativeHumidity": 91.35,
+ "mslp": 100497,
+ "uvIndex": 0,
+ "significantWeatherCode": 12,
+ "precipitationRate": 0.22,
+ "totalPrecipAmount": 0.26,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 54
+ },
+ {
+ "time": "2026-02-09T00:00Z",
+ "screenTemperature": 8.52,
+ "maxScreenAirTemp": 8.57,
+ "minScreenAirTemp": 8.49,
+ "screenDewPointTemperature": 7.17,
+ "feelsLikeTemperature": 7.21,
+ "windSpeed10m": 2.32,
+ "windDirectionFrom10m": 151,
+ "windGustSpeed10m": 5.44,
+ "max10mWindGust": 5.96,
+ "visibility": 13108,
+ "screenRelativeHumidity": 91.42,
+ "mslp": 100475,
+ "uvIndex": 0,
+ "significantWeatherCode": 8,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 13
+ },
+ {
+ "time": "2026-02-09T01:00Z",
+ "screenTemperature": 8.39,
+ "maxScreenAirTemp": 8.52,
+ "minScreenAirTemp": 8.36,
+ "screenDewPointTemperature": 7.08,
+ "feelsLikeTemperature": 6.94,
+ "windSpeed10m": 2.49,
+ "windDirectionFrom10m": 157,
+ "windGustSpeed10m": 5.83,
+ "max10mWindGust": 6.54,
+ "visibility": 14678,
+ "screenRelativeHumidity": 91.55,
+ "mslp": 100430,
+ "uvIndex": 0,
+ "significantWeatherCode": 7,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 12
+ },
+ {
+ "time": "2026-02-09T02:00Z",
+ "screenTemperature": 8.23,
+ "maxScreenAirTemp": 8.39,
+ "minScreenAirTemp": 8.18,
+ "screenDewPointTemperature": 6.88,
+ "feelsLikeTemperature": 6.86,
+ "windSpeed10m": 2.34,
+ "windDirectionFrom10m": 155,
+ "windGustSpeed10m": 5.35,
+ "max10mWindGust": 6.7,
+ "visibility": 13081,
+ "screenRelativeHumidity": 91.35,
+ "mslp": 100385,
+ "uvIndex": 0,
+ "significantWeatherCode": 7,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 16
+ },
+ {
+ "time": "2026-02-09T03:00Z",
+ "screenTemperature": 8.1,
+ "maxScreenAirTemp": 8.23,
+ "minScreenAirTemp": 8.05,
+ "screenDewPointTemperature": 6.78,
+ "feelsLikeTemperature": 6.67,
+ "windSpeed10m": 2.37,
+ "windDirectionFrom10m": 150,
+ "windGustSpeed10m": 5.35,
+ "max10mWindGust": 6.67,
+ "visibility": 15140,
+ "screenRelativeHumidity": 91.56,
+ "mslp": 100335,
+ "uvIndex": 0,
+ "significantWeatherCode": 7,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 7
+ },
+ {
+ "time": "2026-02-09T04:00Z",
+ "screenTemperature": 7.9,
+ "maxScreenAirTemp": 8.1,
+ "minScreenAirTemp": 7.86,
+ "screenDewPointTemperature": 6.58,
+ "feelsLikeTemperature": 6.41,
+ "windSpeed10m": 2.39,
+ "windDirectionFrom10m": 149,
+ "windGustSpeed10m": 5.43,
+ "max10mWindGust": 6.53,
+ "visibility": 15366,
+ "screenRelativeHumidity": 91.65,
+ "mslp": 100305,
+ "uvIndex": 0,
+ "significantWeatherCode": 8,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 10
+ },
+ {
+ "time": "2026-02-09T05:00Z",
+ "screenTemperature": 7.71,
+ "maxScreenAirTemp": 7.9,
+ "minScreenAirTemp": 7.65,
+ "screenDewPointTemperature": 6.51,
+ "feelsLikeTemperature": 6.28,
+ "windSpeed10m": 2.3,
+ "windDirectionFrom10m": 146,
+ "windGustSpeed10m": 5.3,
+ "max10mWindGust": 6.91,
+ "visibility": 14570,
+ "screenRelativeHumidity": 92.33,
+ "mslp": 100283,
+ "uvIndex": 0,
+ "significantWeatherCode": 7,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 6
+ },
+ {
+ "time": "2026-02-09T06:00Z",
+ "screenTemperature": 7.56,
+ "maxScreenAirTemp": 7.71,
+ "minScreenAirTemp": 7.54,
+ "screenDewPointTemperature": 6.38,
+ "feelsLikeTemperature": 6.11,
+ "windSpeed10m": 2.29,
+ "windDirectionFrom10m": 148,
+ "windGustSpeed10m": 5.34,
+ "max10mWindGust": 6.56,
+ "visibility": 13685,
+ "screenRelativeHumidity": 92.49,
+ "mslp": 100280,
+ "uvIndex": 0,
+ "significantWeatherCode": 7,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 6
+ },
+ {
+ "time": "2026-02-09T07:00Z",
+ "screenTemperature": 7.61,
+ "maxScreenAirTemp": 7.62,
+ "minScreenAirTemp": 7.56,
+ "screenDewPointTemperature": 6.43,
+ "feelsLikeTemperature": 6.17,
+ "windSpeed10m": 2.28,
+ "windDirectionFrom10m": 146,
+ "windGustSpeed10m": 5.26,
+ "max10mWindGust": 6.34,
+ "visibility": 13185,
+ "screenRelativeHumidity": 92.48,
+ "mslp": 100282,
+ "uvIndex": 0,
+ "significantWeatherCode": 7,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 7
+ },
+ {
+ "time": "2026-02-09T08:00Z",
+ "screenTemperature": 7.7,
+ "maxScreenAirTemp": 7.75,
+ "minScreenAirTemp": 7.61,
+ "screenDewPointTemperature": 6.48,
+ "feelsLikeTemperature": 6.25,
+ "windSpeed10m": 2.34,
+ "windDirectionFrom10m": 146,
+ "windGustSpeed10m": 5.57,
+ "max10mWindGust": 5.76,
+ "visibility": 13541,
+ "screenRelativeHumidity": 92.21,
+ "mslp": 100275,
+ "uvIndex": 1,
+ "significantWeatherCode": 7,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 6
+ },
+ {
+ "time": "2026-02-09T09:00Z",
+ "screenTemperature": 7.92,
+ "maxScreenAirTemp": 7.92,
+ "minScreenAirTemp": 7.7,
+ "screenDewPointTemperature": 6.53,
+ "feelsLikeTemperature": 6.42,
+ "windSpeed10m": 2.43,
+ "windDirectionFrom10m": 142,
+ "windGustSpeed10m": 5.54,
+ "max10mWindGust": 6.4,
+ "visibility": 13747,
+ "screenRelativeHumidity": 91.19,
+ "mslp": 100275,
+ "uvIndex": 1,
+ "significantWeatherCode": 7,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 6
+ },
+ {
+ "time": "2026-02-09T10:00Z",
+ "screenTemperature": 8.6,
+ "maxScreenAirTemp": 8.65,
+ "minScreenAirTemp": 7.92,
+ "screenDewPointTemperature": 6.57,
+ "feelsLikeTemperature": 7.09,
+ "windSpeed10m": 2.66,
+ "windDirectionFrom10m": 146,
+ "windGustSpeed10m": 5.71,
+ "max10mWindGust": 5.71,
+ "visibility": 14552,
+ "screenRelativeHumidity": 87.48,
+ "mslp": 100241,
+ "uvIndex": 1,
+ "significantWeatherCode": 7,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 6
+ },
+ {
+ "time": "2026-02-09T11:00Z",
+ "screenTemperature": 9.43,
+ "maxScreenAirTemp": 9.43,
+ "minScreenAirTemp": 8.6,
+ "screenDewPointTemperature": 6.49,
+ "feelsLikeTemperature": 7.83,
+ "windSpeed10m": 3.0,
+ "windDirectionFrom10m": 151,
+ "windGustSpeed10m": 6.25,
+ "max10mWindGust": 6.25,
+ "visibility": 19055,
+ "screenRelativeHumidity": 82.28,
+ "mslp": 100209,
+ "uvIndex": 1,
+ "significantWeatherCode": 7,
+ "precipitationRate": 0.0,
+ "totalPrecipAmount": 0.0,
+ "totalSnowAmount": 0,
+ "probOfPrecipitation": 6
+ },
+ {
+ "time": "2026-02-09T12:00Z",
+ "screenTemperature": 10.25,
+ "screenDewPointTemperature": 6.37,
+ "feelsLikeTemperature": 8.61,
+ "windSpeed10m": 3.28,
+ "windDirectionFrom10m": 155,
+ "windGustSpeed10m": 6.87,
+ "visibility": 20517,
+ "screenRelativeHumidity": 77.18,
+ "mslp": 100150,
+ "uvIndex": 1,
+ "significantWeatherCode": 7,
+ "precipitationRate": 0.0,
+ "probOfPrecipitation": 6
+ }
+ ]
+ }
+ }
+ ],
+ "parameters": [
+ {
+ "totalSnowAmount": { "type": "Parameter", "description": "Total Snow Amount Over Previous Hour", "unit": { "label": "millimetres", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "mm" } } },
+ "screenTemperature": { "type": "Parameter", "description": "Screen Air Temperature", "unit": { "label": "degrees Celsius", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "Cel" } } },
+ "visibility": { "type": "Parameter", "description": "Visibility", "unit": { "label": "metres", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "m" } } },
+ "windDirectionFrom10m": { "type": "Parameter", "description": "10m Wind From Direction", "unit": { "label": "degrees", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "deg" } } },
+ "precipitationRate": { "type": "Parameter", "description": "Precipitation Rate", "unit": { "label": "millimetres per hour", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "mm/h" } } },
+ "maxScreenAirTemp": { "type": "Parameter", "description": "Maximum Screen Air Temperature Over Previous Hour", "unit": { "label": "degrees Celsius", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "Cel" } } },
+ "feelsLikeTemperature": { "type": "Parameter", "description": "Feels Like Temperature", "unit": { "label": "degrees Celsius", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "Cel" } } },
+ "screenDewPointTemperature": { "type": "Parameter", "description": "Screen Dew Point Temperature", "unit": { "label": "degrees Celsius", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "Cel" } } },
+ "screenRelativeHumidity": { "type": "Parameter", "description": "Screen Relative Humidity", "unit": { "label": "percentage", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "%" } } },
+ "windSpeed10m": { "type": "Parameter", "description": "10m Wind Speed", "unit": { "label": "metres per second", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "m/s" } } },
+ "probOfPrecipitation": { "type": "Parameter", "description": "Probability of Precipitation", "unit": { "label": "percentage", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "%" } } },
+ "max10mWindGust": { "type": "Parameter", "description": "Maximum 10m Wind Gust Speed Over Previous Hour", "unit": { "label": "metres per second", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "m/s" } } },
+ "significantWeatherCode": { "type": "Parameter", "description": "Significant Weather Code", "unit": { "label": "dimensionless", "symbol": { "value": "https://datahub.metoffice.gov.uk/", "type": "1" } } },
+ "minScreenAirTemp": { "type": "Parameter", "description": "Minimum Screen Air Temperature Over Previous Hour", "unit": { "label": "degrees Celsius", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "Cel" } } },
+ "totalPrecipAmount": { "type": "Parameter", "description": "Total Precipitation Amount Over Previous Hour", "unit": { "label": "millimetres", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "mm" } } },
+ "mslp": { "type": "Parameter", "description": "Mean Sea Level Pressure", "unit": { "label": "pascals", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "Pa" } } },
+ "windGustSpeed10m": { "type": "Parameter", "description": "10m Wind Gust Speed", "unit": { "label": "metres per second", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "m/s" } } },
+ "uvIndex": { "type": "Parameter", "description": "UV Index", "unit": { "label": "dimensionless", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "1" } } }
+ }
+ ]
+}
diff --git a/tests/mocks/weather_ukmetoffice_daily.json b/tests/mocks/weather_ukmetoffice_daily.json
new file mode 100644
index 00000000..e774a0f5
--- /dev/null
+++ b/tests/mocks/weather_ukmetoffice_daily.json
@@ -0,0 +1,419 @@
+{
+ "type": "FeatureCollection",
+ "features": [
+ {
+ "type": "Feature",
+ "geometry": { "type": "Point", "coordinates": [-0.12480000000000001, 51.5081, 11.0] },
+ "properties": {
+ "location": { "name": "London" },
+ "requestPointDistance": 221.7807,
+ "modelRunDate": "2026-02-07T12:00Z",
+ "timeSeries": [
+ {
+ "time": "2026-02-06T00:00Z",
+ "midday10MWindSpeed": 0.82,
+ "midnight10MWindSpeed": 1.59,
+ "midday10MWindDirection": 121,
+ "midnight10MWindDirection": 175,
+ "midday10MWindGust": 3.09,
+ "midnight10MWindGust": 7.72,
+ "middayVisibility": 4000,
+ "midnightVisibility": 12560,
+ "middayRelativeHumidity": 92.93,
+ "midnightRelativeHumidity": 89.85,
+ "middayMslp": 98480,
+ "midnightMslp": 99260,
+ "nightSignificantWeatherCode": 2,
+ "dayMaxScreenTemperature": 11.37,
+ "nightMinScreenTemperature": 7.26,
+ "dayUpperBoundMaxTemp": 12.53,
+ "nightUpperBoundMinTemp": 8.77,
+ "dayLowerBoundMaxTemp": 9.86,
+ "nightLowerBoundMinTemp": 6.62,
+ "nightMinFeelsLikeTemp": 5.98,
+ "dayUpperBoundMaxFeelsLikeTemp": 11.58,
+ "nightUpperBoundMinFeelsLikeTemp": 6.83,
+ "dayLowerBoundMaxFeelsLikeTemp": 8.89,
+ "nightLowerBoundMinFeelsLikeTemp": 5.23,
+ "nightProbabilityOfPrecipitation": 85,
+ "nightProbabilityOfSnow": 0,
+ "nightProbabilityOfHeavySnow": 0,
+ "nightProbabilityOfRain": 85,
+ "nightProbabilityOfHeavyRain": 80,
+ "nightProbabilityOfHail": 16,
+ "nightProbabilityOfSferics": 8
+ },
+ {
+ "time": "2026-02-07T00:00Z",
+ "midday10MWindSpeed": 1.9,
+ "midnight10MWindSpeed": 2.52,
+ "midday10MWindDirection": 165,
+ "midnight10MWindDirection": 184,
+ "midday10MWindGust": 7.72,
+ "midnight10MWindGust": 7.13,
+ "middayVisibility": 8550,
+ "midnightVisibility": 13732,
+ "middayRelativeHumidity": 93.08,
+ "midnightRelativeHumidity": 93.62,
+ "middayMslp": 99440,
+ "midnightMslp": 100100,
+ "maxUvIndex": 1,
+ "daySignificantWeatherCode": 12,
+ "nightSignificantWeatherCode": 7,
+ "dayMaxScreenTemperature": 10.5,
+ "nightMinScreenTemperature": 7.52,
+ "dayUpperBoundMaxTemp": 11.72,
+ "nightUpperBoundMinTemp": 9.39,
+ "dayLowerBoundMaxTemp": 9.78,
+ "nightLowerBoundMinTemp": 5.83,
+ "dayMaxFeelsLikeTemp": 8.76,
+ "nightMinFeelsLikeTemp": 6.29,
+ "dayUpperBoundMaxFeelsLikeTemp": 9.47,
+ "nightUpperBoundMinFeelsLikeTemp": 8.28,
+ "dayLowerBoundMaxFeelsLikeTemp": 8.06,
+ "nightLowerBoundMinFeelsLikeTemp": 5.22,
+ "dayProbabilityOfPrecipitation": 91,
+ "nightProbabilityOfPrecipitation": 10,
+ "dayProbabilityOfSnow": 0,
+ "nightProbabilityOfSnow": 0,
+ "dayProbabilityOfHeavySnow": 0,
+ "nightProbabilityOfHeavySnow": 0,
+ "dayProbabilityOfRain": 91,
+ "nightProbabilityOfRain": 10,
+ "dayProbabilityOfHeavyRain": 86,
+ "nightProbabilityOfHeavyRain": 2,
+ "dayProbabilityOfHail": 17,
+ "nightProbabilityOfHail": 0,
+ "dayProbabilityOfSferics": 11,
+ "nightProbabilityOfSferics": 0
+ },
+ {
+ "time": "2026-02-08T00:00Z",
+ "midday10MWindSpeed": 2.28,
+ "midnight10MWindSpeed": 2.32,
+ "midday10MWindDirection": 185,
+ "midnight10MWindDirection": 151,
+ "midday10MWindGust": 4.71,
+ "midnight10MWindGust": 5.44,
+ "middayVisibility": 12395,
+ "midnightVisibility": 13108,
+ "middayRelativeHumidity": 82.51,
+ "midnightRelativeHumidity": 91.42,
+ "middayMslp": 100559,
+ "midnightMslp": 100474,
+ "maxUvIndex": 1,
+ "daySignificantWeatherCode": 7,
+ "nightSignificantWeatherCode": 7,
+ "dayMaxScreenTemperature": 11.07,
+ "nightMinScreenTemperature": 7.56,
+ "dayUpperBoundMaxTemp": 11.84,
+ "nightUpperBoundMinTemp": 8.59,
+ "dayLowerBoundMaxTemp": 9.76,
+ "nightLowerBoundMinTemp": 5.18,
+ "dayMaxFeelsLikeTemp": 9.48,
+ "nightMinFeelsLikeTemp": 6.11,
+ "dayUpperBoundMaxFeelsLikeTemp": 10.97,
+ "nightUpperBoundMinFeelsLikeTemp": 7.32,
+ "dayLowerBoundMaxFeelsLikeTemp": 8.13,
+ "nightLowerBoundMinFeelsLikeTemp": 5.38,
+ "dayProbabilityOfPrecipitation": 10,
+ "nightProbabilityOfPrecipitation": 54,
+ "dayProbabilityOfSnow": 0,
+ "nightProbabilityOfSnow": 0,
+ "dayProbabilityOfHeavySnow": 0,
+ "nightProbabilityOfHeavySnow": 0,
+ "dayProbabilityOfRain": 10,
+ "nightProbabilityOfRain": 54,
+ "dayProbabilityOfHeavyRain": 2,
+ "nightProbabilityOfHeavyRain": 32,
+ "dayProbabilityOfHail": 0,
+ "nightProbabilityOfHail": 4,
+ "dayProbabilityOfSferics": 0,
+ "nightProbabilityOfSferics": 6
+ },
+ {
+ "time": "2026-02-09T00:00Z",
+ "midday10MWindSpeed": 3.28,
+ "midnight10MWindSpeed": 3.42,
+ "midday10MWindDirection": 155,
+ "midnight10MWindDirection": 121,
+ "midday10MWindGust": 6.87,
+ "midnight10MWindGust": 7.02,
+ "middayVisibility": 20517,
+ "midnightVisibility": 18708,
+ "middayRelativeHumidity": 77.18,
+ "midnightRelativeHumidity": 86.28,
+ "middayMslp": 100150,
+ "midnightMslp": 99580,
+ "maxUvIndex": 1,
+ "daySignificantWeatherCode": 7,
+ "nightSignificantWeatherCode": 7,
+ "dayMaxScreenTemperature": 10.89,
+ "nightMinScreenTemperature": 6.93,
+ "dayUpperBoundMaxTemp": 11.87,
+ "nightUpperBoundMinTemp": 8.61,
+ "dayLowerBoundMaxTemp": 8.55,
+ "nightLowerBoundMinTemp": 4.78,
+ "dayMaxFeelsLikeTemp": 9.06,
+ "nightMinFeelsLikeTemp": 5.13,
+ "dayUpperBoundMaxFeelsLikeTemp": 9.87,
+ "nightUpperBoundMinFeelsLikeTemp": 6.29,
+ "dayLowerBoundMaxFeelsLikeTemp": 6.57,
+ "nightLowerBoundMinFeelsLikeTemp": 3.3,
+ "dayProbabilityOfPrecipitation": 6,
+ "nightProbabilityOfPrecipitation": 18,
+ "dayProbabilityOfSnow": 0,
+ "nightProbabilityOfSnow": 0,
+ "dayProbabilityOfHeavySnow": 0,
+ "nightProbabilityOfHeavySnow": 0,
+ "dayProbabilityOfRain": 6,
+ "nightProbabilityOfRain": 18,
+ "dayProbabilityOfHeavyRain": 1,
+ "nightProbabilityOfHeavyRain": 7,
+ "dayProbabilityOfHail": 0,
+ "nightProbabilityOfHail": 1,
+ "dayProbabilityOfSferics": 0,
+ "nightProbabilityOfSferics": 0
+ },
+ {
+ "time": "2026-02-10T00:00Z",
+ "midday10MWindSpeed": 3.09,
+ "midnight10MWindSpeed": 3.12,
+ "midday10MWindDirection": 150,
+ "midnight10MWindDirection": 191,
+ "midday10MWindGust": 6.52,
+ "midnight10MWindGust": 6.18,
+ "middayVisibility": 17148,
+ "midnightVisibility": 12750,
+ "middayRelativeHumidity": 86.68,
+ "midnightRelativeHumidity": 93.78,
+ "middayMslp": 98991,
+ "midnightMslp": 98238,
+ "maxUvIndex": 1,
+ "daySignificantWeatherCode": 8,
+ "nightSignificantWeatherCode": 12,
+ "dayMaxScreenTemperature": 10.47,
+ "nightMinScreenTemperature": 8.75,
+ "dayUpperBoundMaxTemp": 13.15,
+ "nightUpperBoundMinTemp": 10.63,
+ "dayLowerBoundMaxTemp": 7.91,
+ "nightLowerBoundMinTemp": 6.14,
+ "dayMaxFeelsLikeTemp": 8.44,
+ "nightMinFeelsLikeTemp": 7.65,
+ "dayUpperBoundMaxFeelsLikeTemp": 11.11,
+ "nightUpperBoundMinFeelsLikeTemp": 8.73,
+ "dayLowerBoundMaxFeelsLikeTemp": 6.87,
+ "nightLowerBoundMinFeelsLikeTemp": 5.59,
+ "dayProbabilityOfPrecipitation": 49,
+ "nightProbabilityOfPrecipitation": 54,
+ "dayProbabilityOfSnow": 0,
+ "nightProbabilityOfSnow": 0,
+ "dayProbabilityOfHeavySnow": 0,
+ "nightProbabilityOfHeavySnow": 0,
+ "dayProbabilityOfRain": 49,
+ "nightProbabilityOfRain": 54,
+ "dayProbabilityOfHeavyRain": 26,
+ "nightProbabilityOfHeavyRain": 32,
+ "dayProbabilityOfHail": 1,
+ "nightProbabilityOfHail": 2,
+ "dayProbabilityOfSferics": 1,
+ "nightProbabilityOfSferics": 2
+ },
+ {
+ "time": "2026-02-11T00:00Z",
+ "midday10MWindSpeed": 4.2,
+ "midnight10MWindSpeed": 3.4,
+ "midday10MWindDirection": 228,
+ "midnight10MWindDirection": 241,
+ "midday10MWindGust": 9.23,
+ "midnight10MWindGust": 6.88,
+ "middayVisibility": 20709,
+ "midnightVisibility": 18608,
+ "middayRelativeHumidity": 82.88,
+ "midnightRelativeHumidity": 89.7,
+ "middayMslp": 98098,
+ "midnightMslp": 97870,
+ "maxUvIndex": 1,
+ "daySignificantWeatherCode": 12,
+ "nightSignificantWeatherCode": 12,
+ "dayMaxScreenTemperature": 11.71,
+ "nightMinScreenTemperature": 7.6,
+ "dayUpperBoundMaxTemp": 13.23,
+ "nightUpperBoundMinTemp": 9.77,
+ "dayLowerBoundMaxTemp": 7.85,
+ "nightLowerBoundMinTemp": 4.71,
+ "dayMaxFeelsLikeTemp": 9.43,
+ "nightMinFeelsLikeTemp": 5.5,
+ "dayUpperBoundMaxFeelsLikeTemp": 11.39,
+ "nightUpperBoundMinFeelsLikeTemp": 7.6,
+ "dayLowerBoundMaxFeelsLikeTemp": 8.0,
+ "nightLowerBoundMinFeelsLikeTemp": 4.33,
+ "dayProbabilityOfPrecipitation": 50,
+ "nightProbabilityOfPrecipitation": 46,
+ "dayProbabilityOfSnow": 0,
+ "nightProbabilityOfSnow": 0,
+ "dayProbabilityOfHeavySnow": 0,
+ "nightProbabilityOfHeavySnow": 0,
+ "dayProbabilityOfRain": 50,
+ "nightProbabilityOfRain": 46,
+ "dayProbabilityOfHeavyRain": 28,
+ "nightProbabilityOfHeavyRain": 25,
+ "dayProbabilityOfHail": 2,
+ "nightProbabilityOfHail": 1,
+ "dayProbabilityOfSferics": 5,
+ "nightProbabilityOfSferics": 4
+ },
+ {
+ "time": "2026-02-12T00:00Z",
+ "midday10MWindSpeed": 3.99,
+ "midnight10MWindSpeed": 3.62,
+ "midday10MWindDirection": 297,
+ "midnight10MWindDirection": 321,
+ "midday10MWindGust": 8.71,
+ "midnight10MWindGust": 7.52,
+ "middayVisibility": 21894,
+ "midnightVisibility": 24612,
+ "middayRelativeHumidity": 80.41,
+ "midnightRelativeHumidity": 83.6,
+ "middayMslp": 98255,
+ "midnightMslp": 98981,
+ "maxUvIndex": 1,
+ "daySignificantWeatherCode": 8,
+ "nightSignificantWeatherCode": 7,
+ "dayMaxScreenTemperature": 9.92,
+ "nightMinScreenTemperature": 3.15,
+ "dayUpperBoundMaxTemp": 12.14,
+ "nightUpperBoundMinTemp": 9.05,
+ "dayLowerBoundMaxTemp": 5.26,
+ "nightLowerBoundMinTemp": 0.41,
+ "dayMaxFeelsLikeTemp": 6.69,
+ "nightMinFeelsLikeTemp": -0.03,
+ "dayUpperBoundMaxFeelsLikeTemp": 10.16,
+ "nightUpperBoundMinFeelsLikeTemp": 7.3,
+ "dayLowerBoundMaxFeelsLikeTemp": 4.45,
+ "nightLowerBoundMinFeelsLikeTemp": -3.64,
+ "dayProbabilityOfPrecipitation": 21,
+ "nightProbabilityOfPrecipitation": 22,
+ "dayProbabilityOfSnow": 0,
+ "nightProbabilityOfSnow": 2,
+ "dayProbabilityOfHeavySnow": 0,
+ "nightProbabilityOfHeavySnow": 1,
+ "dayProbabilityOfRain": 21,
+ "nightProbabilityOfRain": 22,
+ "dayProbabilityOfHeavyRain": 9,
+ "nightProbabilityOfHeavyRain": 10,
+ "dayProbabilityOfHail": 1,
+ "nightProbabilityOfHail": 1,
+ "dayProbabilityOfSferics": 2,
+ "nightProbabilityOfSferics": 2
+ },
+ {
+ "time": "2026-02-13T00:00Z",
+ "midday10MWindSpeed": 4.14,
+ "midnight10MWindSpeed": 2.83,
+ "midday10MWindDirection": 322,
+ "midnight10MWindDirection": 307,
+ "midday10MWindGust": 9.4,
+ "midnight10MWindGust": 5.92,
+ "middayVisibility": 34312,
+ "midnightVisibility": 34597,
+ "middayRelativeHumidity": 66.26,
+ "midnightRelativeHumidity": 77.93,
+ "middayMslp": 99718,
+ "midnightMslp": 100243,
+ "maxUvIndex": 1,
+ "daySignificantWeatherCode": 1,
+ "nightSignificantWeatherCode": 0,
+ "dayMaxScreenTemperature": 6.79,
+ "nightMinScreenTemperature": 0.85,
+ "dayUpperBoundMaxTemp": 11.07,
+ "nightUpperBoundMinTemp": 7.3,
+ "dayLowerBoundMaxTemp": 2.84,
+ "nightLowerBoundMinTemp": -1.75,
+ "dayMaxFeelsLikeTemp": 2.21,
+ "nightMinFeelsLikeTemp": -2.05,
+ "dayUpperBoundMaxFeelsLikeTemp": 9.57,
+ "nightUpperBoundMinFeelsLikeTemp": 6.72,
+ "dayLowerBoundMaxFeelsLikeTemp": -0.29,
+ "nightLowerBoundMinFeelsLikeTemp": -3.77,
+ "dayProbabilityOfPrecipitation": 11,
+ "nightProbabilityOfPrecipitation": 6,
+ "dayProbabilityOfSnow": 2,
+ "nightProbabilityOfSnow": 1,
+ "dayProbabilityOfHeavySnow": 1,
+ "nightProbabilityOfHeavySnow": 0,
+ "dayProbabilityOfRain": 9,
+ "nightProbabilityOfRain": 6,
+ "dayProbabilityOfHeavyRain": 4,
+ "nightProbabilityOfHeavyRain": 3,
+ "dayProbabilityOfHail": 1,
+ "nightProbabilityOfHail": 0,
+ "dayProbabilityOfSferics": 1,
+ "nightProbabilityOfSferics": 0
+ }
+ ]
+ }
+ }
+ ],
+ "parameters": [
+ {
+ "daySignificantWeatherCode": { "type": "Parameter", "description": "Day Significant Weather Code", "unit": { "label": "dimensionless", "symbol": { "value": "https://datahub.metoffice.gov.uk/", "type": "1" } } },
+ "midnightRelativeHumidity": { "type": "Parameter", "description": "Relative Humidity at Local Midnight", "unit": { "label": "percentage", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "%" } } },
+ "nightProbabilityOfHeavyRain": { "type": "Parameter", "description": "Probability of Heavy Rain During The Night", "unit": { "label": "percentage", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "%" } } },
+ "midnight10MWindSpeed": { "type": "Parameter", "description": "10m Wind Speed at Local Midnight", "unit": { "label": "metres per second", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "m/s" } } },
+ "nightUpperBoundMinFeelsLikeTemp": {
+ "type": "Parameter",
+ "description": "Upper Bound on Night Minimum Feels Like Air Temperature",
+ "unit": { "label": "degrees Celsius", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "Cel" } }
+ },
+ "nightUpperBoundMinTemp": { "type": "Parameter", "description": "Upper Bound on Night Minimum Screen Air Temperature", "unit": { "label": "degrees Celsius", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "Cel" } } },
+ "midnightVisibility": { "type": "Parameter", "description": "Visibility at Local Midnight", "unit": { "label": "metres", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "m" } } },
+ "dayUpperBoundMaxFeelsLikeTemp": {
+ "type": "Parameter",
+ "description": "Upper Bound on Day Maximum Feels Like Air Temperature",
+ "unit": { "label": "degrees Celsius", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "Cel" } }
+ },
+ "nightProbabilityOfRain": { "type": "Parameter", "description": "Probability of Rain During The Night", "unit": { "label": "percentage", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "%" } } },
+ "midday10MWindDirection": { "type": "Parameter", "description": "10m Wind Direction at Local Midday", "unit": { "label": "degrees", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "deg" } } },
+ "nightLowerBoundMinFeelsLikeTemp": {
+ "type": "Parameter",
+ "description": "Lower Bound on Night Minimum Feels Like Air Temperature",
+ "unit": { "label": "degrees Celsius", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "Cel" } }
+ },
+ "nightProbabilityOfHail": { "type": "Parameter", "description": "Probability of Hail During The Night", "unit": { "label": "percentage", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "%" } } },
+ "middayMslp": { "type": "Parameter", "description": "Mean Sea Level Pressure at Local Midday", "unit": { "label": "pascals", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "Pa" } } },
+ "dayProbabilityOfHeavySnow": { "type": "Parameter", "description": "Probability of Heavy Snow During The Day", "unit": { "label": "percentage", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "%" } } },
+ "nightProbabilityOfPrecipitation": { "type": "Parameter", "description": "Probability of Precipitation During The Night", "unit": { "label": "percentage", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "%" } } },
+ "dayProbabilityOfHail": { "type": "Parameter", "description": "Probability of Hail During The Day", "unit": { "label": "percentage", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "%" } } },
+ "dayProbabilityOfRain": { "type": "Parameter", "description": "Probability of Rain During The Day", "unit": { "label": "percentage", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "%" } } },
+ "midday10MWindSpeed": { "type": "Parameter", "description": "10m Wind Speed at Local Midday", "unit": { "label": "metres per second", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "m/s" } } },
+ "midday10MWindGust": { "type": "Parameter", "description": "10m Wind Gust Speed at Local Midday", "unit": { "label": "metres per second", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "m/s" } } },
+ "middayVisibility": { "type": "Parameter", "description": "Visibility at Local Midday", "unit": { "label": "metres", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "m" } } },
+ "midnight10MWindGust": { "type": "Parameter", "description": "10m Wind Gust Speed at Local Midnight", "unit": { "label": "metres per second", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "m/s" } } },
+ "midnightMslp": { "type": "Parameter", "description": "Mean Sea Level Pressure at Local Midnight", "unit": { "label": "pascals", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "Pa" } } },
+ "dayProbabilityOfSferics": { "type": "Parameter", "description": "Probability of Sferics During The Day", "unit": { "label": "percentage", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "%" } } },
+ "nightSignificantWeatherCode": { "type": "Parameter", "description": "Night Significant Weather Code", "unit": { "label": "dimensionless", "symbol": { "value": "https://datahub.metoffice.gov.uk/", "type": "1" } } },
+ "dayProbabilityOfPrecipitation": { "type": "Parameter", "description": "Probability of Precipitation During The Day", "unit": { "label": "percentage", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "%" } } },
+ "dayProbabilityOfHeavyRain": { "type": "Parameter", "description": "Probability of Heavy Rain During The Day", "unit": { "label": "percentage", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "%" } } },
+ "dayMaxScreenTemperature": { "type": "Parameter", "description": "Day Maximum Screen Air Temperature", "unit": { "label": "degrees Celsius", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "Cel" } } },
+ "nightMinScreenTemperature": { "type": "Parameter", "description": "Night Minimum Screen Air Temperature", "unit": { "label": "degrees Celsius", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "Cel" } } },
+ "midnight10MWindDirection": { "type": "Parameter", "description": "10m Wind Direction at Local Midnight", "unit": { "label": "degrees", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "deg" } } },
+ "maxUvIndex": { "type": "Parameter", "description": "Day Maximum UV Index", "unit": { "label": "dimensionless", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "1" } } },
+ "dayProbabilityOfSnow": { "type": "Parameter", "description": "Probability of Snow During The Day", "unit": { "label": "percentage", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "%" } } },
+ "nightProbabilityOfSnow": { "type": "Parameter", "description": "Probability of Snow During The Night", "unit": { "label": "percentage", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "%" } } },
+ "dayLowerBoundMaxTemp": { "type": "Parameter", "description": "Lower Bound on Day Maximum Screen Air Temperature", "unit": { "label": "degrees Celsius", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "Cel" } } },
+ "nightProbabilityOfHeavySnow": { "type": "Parameter", "description": "Probability of Heavy Snow During The Night", "unit": { "label": "percentage", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "%" } } },
+ "dayLowerBoundMaxFeelsLikeTemp": {
+ "type": "Parameter",
+ "description": "Lower Bound on Day Maximum Feels Like Air Temperature",
+ "unit": { "label": "degrees Celsius", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "Cel" } }
+ },
+ "dayUpperBoundMaxTemp": { "type": "Parameter", "description": "Upper Bound on Day Maximum Screen Air Temperature", "unit": { "label": "degrees Celsius", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "Cel" } } },
+ "dayMaxFeelsLikeTemp": { "type": "Parameter", "description": "Day Maximum Feels Like Air Temperature", "unit": { "label": "degrees Celsius", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "Cel" } } },
+ "middayRelativeHumidity": { "type": "Parameter", "description": "Relative Humidity at Local Midday", "unit": { "label": "percentage", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "%" } } },
+ "nightLowerBoundMinTemp": { "type": "Parameter", "description": "Lower Bound on Night Minimum Screen Air Temperature", "unit": { "label": "degrees Celsius", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "Cel" } } },
+ "nightMinFeelsLikeTemp": { "type": "Parameter", "description": "Night Minimum Feels Like Air Temperature", "unit": { "label": "degrees Celsius", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "Cel" } } },
+ "nightProbabilityOfSferics": { "type": "Parameter", "description": "Probability of Sferics During The Night", "unit": { "label": "percentage", "symbol": { "value": "http://www.opengis.net/def/uom/UCUM/", "type": "%" } } }
+ }
+ ]
+}
diff --git a/tests/mocks/weather_weatherbit.json b/tests/mocks/weather_weatherbit.json
new file mode 100644
index 00000000..bc8dfb53
--- /dev/null
+++ b/tests/mocks/weather_weatherbit.json
@@ -0,0 +1,45 @@
+{
+ "count": 1,
+ "data": [
+ {
+ "app_temp": -0.6,
+ "aqi": 44,
+ "city_name": "New York City",
+ "clouds": 100,
+ "country_code": "US",
+ "datetime": "2026-02-06:21",
+ "dewpt": -9,
+ "dhi": 62,
+ "dni": 555,
+ "elev_angle": 12.55,
+ "ghi": 175,
+ "gust": 3.1,
+ "h_angle": 60,
+ "lat": 40.7128,
+ "lon": -74.006,
+ "ob_time": "2026-02-06 21:25",
+ "pod": "d",
+ "precip": 0,
+ "pres": 1004,
+ "rh": 47,
+ "slp": 1004,
+ "snow": 0,
+ "solar_rad": 35,
+ "sources": ["KJRB", "radar", "satellite"],
+ "state_code": "NY",
+ "station": "KJRB",
+ "sunrise": "11:59",
+ "sunset": "22:21",
+ "temp": 1,
+ "timezone": "America/New_York",
+ "ts": 1770413100,
+ "uv": 0,
+ "vis": 16,
+ "weather": { "code": 804, "description": "Overcast clouds", "icon": "c04d" },
+ "wind_cdir": "SSW",
+ "wind_cdir_full": "south-southwest",
+ "wind_dir": 210,
+ "wind_spd": 1.5
+ }
+ ]
+}
diff --git a/tests/mocks/weather_weatherbit_forecast.json b/tests/mocks/weather_weatherbit_forecast.json
new file mode 100644
index 00000000..b5239b84
--- /dev/null
+++ b/tests/mocks/weather_weatherbit_forecast.json
@@ -0,0 +1,290 @@
+{
+ "city_name": "New York City",
+ "country_code": "US",
+ "data": [
+ {
+ "app_max_temp": -2.7,
+ "app_min_temp": -9.8,
+ "clouds": 76,
+ "clouds_hi": 8,
+ "clouds_low": 40,
+ "clouds_mid": 90,
+ "datetime": "2026-02-06",
+ "dewpt": -7.6,
+ "high_temp": 0.8,
+ "low_temp": -6.5,
+ "max_dhi": null,
+ "max_temp": 0.5,
+ "min_temp": -6.3,
+ "moon_phase": 0.68,
+ "moon_phase_lunation": 0.65,
+ "moonrise_ts": 1770432076,
+ "moonset_ts": 1770388275,
+ "ozone": 405,
+ "pop": 50,
+ "precip": 0.25,
+ "pres": 1005,
+ "rh": 66,
+ "slp": 1008,
+ "snow": 3.75,
+ "snow_depth": 216.91895,
+ "sunrise_ts": 1770379197,
+ "sunset_ts": 1770416511,
+ "temp": -2,
+ "ts": 1770372060,
+ "uv": 1,
+ "valid_date": "2026-02-06",
+ "vis": 21.7,
+ "weather": { "code": 600, "description": "Light snow", "icon": "s01d" },
+ "wind_cdir": "SSW",
+ "wind_cdir_full": "south-southwest",
+ "wind_dir": 192,
+ "wind_gust_spd": 3.4,
+ "wind_spd": 2.4
+ },
+ {
+ "app_max_temp": -4.9,
+ "app_min_temp": -22.5,
+ "clouds": 76,
+ "clouds_hi": 0,
+ "clouds_low": 87,
+ "clouds_mid": 57,
+ "datetime": "2026-02-07",
+ "dewpt": -13.7,
+ "high_temp": -5.9,
+ "low_temp": -13.9,
+ "max_dhi": null,
+ "max_temp": -0.2,
+ "min_temp": -12.2,
+ "moon_phase": 0.59,
+ "moon_phase_lunation": 0.68,
+ "moonrise_ts": 1770522306,
+ "moonset_ts": 1770476147,
+ "ozone": 452,
+ "pop": 0,
+ "precip": 0,
+ "pres": 1006,
+ "rh": 61,
+ "slp": 1009,
+ "snow": 0,
+ "snow_depth": 201.76189,
+ "sunrise_ts": 1770465530,
+ "sunset_ts": 1770502984,
+ "temp": -7.5,
+ "ts": 1770440460,
+ "uv": 1,
+ "valid_date": "2026-02-07",
+ "vis": 17.8,
+ "weather": { "code": 804, "description": "Overcast clouds", "icon": "c04d" },
+ "wind_cdir": "NW",
+ "wind_cdir_full": "northwest",
+ "wind_dir": 307,
+ "wind_gust_spd": 13.2,
+ "wind_spd": 9.6
+ },
+ {
+ "app_max_temp": -16.5,
+ "app_min_temp": -23.8,
+ "clouds": 9,
+ "clouds_hi": 0,
+ "clouds_low": 17,
+ "clouds_mid": 0,
+ "datetime": "2026-02-08",
+ "dewpt": -18.1,
+ "high_temp": -7.5,
+ "low_temp": -12.4,
+ "max_dhi": null,
+ "max_temp": -7.5,
+ "min_temp": -13.9,
+ "moon_phase": 0.49,
+ "moon_phase_lunation": 0.71,
+ "moonrise_ts": 1770612516,
+ "moonset_ts": 1770564257,
+ "ozone": 453,
+ "pop": 0,
+ "precip": 0,
+ "pres": 1021,
+ "rh": 54,
+ "slp": 1024,
+ "snow": 0,
+ "snow_depth": 190.89763,
+ "sunrise_ts": 1770551862,
+ "sunset_ts": 1770589457,
+ "temp": -10.7,
+ "ts": 1770526860,
+ "uv": 3,
+ "valid_date": "2026-02-08",
+ "vis": 24,
+ "weather": { "code": 801, "description": "Few clouds", "icon": "c02d" },
+ "wind_cdir": "NW",
+ "wind_cdir_full": "northwest",
+ "wind_dir": 321,
+ "wind_gust_spd": 11.3,
+ "wind_spd": 8.2
+ },
+ {
+ "app_max_temp": -7.5,
+ "app_min_temp": -18.4,
+ "clouds": 38,
+ "clouds_hi": 23,
+ "clouds_low": 36,
+ "clouds_mid": 53,
+ "datetime": "2026-02-09",
+ "dewpt": -13.7,
+ "high_temp": -1.6,
+ "low_temp": -7.4,
+ "max_dhi": null,
+ "max_temp": -1.6,
+ "min_temp": -12.4,
+ "moon_phase": 0.4,
+ "moon_phase_lunation": 0.75,
+ "moonrise_ts": 1770616323,
+ "moonset_ts": 1770652706,
+ "ozone": 379,
+ "pop": 0,
+ "precip": 0,
+ "pres": 1021,
+ "rh": 59,
+ "slp": 1024,
+ "snow": 0,
+ "snow_depth": 174.14348,
+ "sunrise_ts": 1770638193,
+ "sunset_ts": 1770675930,
+ "temp": -7,
+ "ts": 1770613260,
+ "uv": 2,
+ "valid_date": "2026-02-09",
+ "vis": 23.5,
+ "weather": { "code": 802, "description": "Scattered clouds", "icon": "c02d" },
+ "wind_cdir": "WNW",
+ "wind_cdir_full": "west-northwest",
+ "wind_dir": 301,
+ "wind_gust_spd": 5.9,
+ "wind_spd": 4.3
+ },
+ {
+ "app_max_temp": -3.1,
+ "app_min_temp": -11.5,
+ "clouds": 36,
+ "clouds_hi": 45,
+ "clouds_low": 39,
+ "clouds_mid": 25,
+ "datetime": "2026-02-10",
+ "dewpt": -8.5,
+ "high_temp": 1.5,
+ "low_temp": -3,
+ "max_dhi": null,
+ "max_temp": 1.5,
+ "min_temp": -7.4,
+ "moon_phase": 0.3,
+ "moon_phase_lunation": 0.78,
+ "moonrise_ts": 1770706492,
+ "moonset_ts": 1770741592,
+ "ozone": 348,
+ "pop": 0,
+ "precip": 0,
+ "pres": 1018,
+ "rh": 65,
+ "slp": 1021,
+ "snow": 0,
+ "snow_depth": 150.55084,
+ "sunrise_ts": 1770724522,
+ "sunset_ts": 1770762403,
+ "temp": -2.9,
+ "ts": 1770699660,
+ "uv": 3,
+ "valid_date": "2026-02-10",
+ "vis": 23,
+ "weather": { "code": 802, "description": "Scattered clouds", "icon": "c02d" },
+ "wind_cdir": "WNW",
+ "wind_cdir_full": "west-northwest",
+ "wind_dir": 290,
+ "wind_gust_spd": 3.6,
+ "wind_spd": 3.5
+ },
+ {
+ "app_max_temp": -1.4,
+ "app_min_temp": -5.8,
+ "clouds": 73,
+ "clouds_hi": 97,
+ "clouds_low": 55,
+ "clouds_mid": 81,
+ "datetime": "2026-02-11",
+ "dewpt": -4.2,
+ "high_temp": 3.8,
+ "low_temp": -3.4,
+ "max_dhi": null,
+ "max_temp": 3.8,
+ "min_temp": -3,
+ "moon_phase": 0.22,
+ "moon_phase_lunation": 0.81,
+ "moonrise_ts": 1770796533,
+ "moonset_ts": 1770830974,
+ "ozone": 327,
+ "pop": 80,
+ "precip": 6.33,
+ "pres": 1012,
+ "rh": 72,
+ "slp": 1014,
+ "snow": 8.82,
+ "snow_depth": 103.88888,
+ "sunrise_ts": 1770810850,
+ "sunset_ts": 1770848875,
+ "temp": 0.3,
+ "ts": 1770786060,
+ "uv": 2,
+ "valid_date": "2026-02-11",
+ "vis": 16.7,
+ "weather": { "code": 500, "description": "Light rain", "icon": "r01d" },
+ "wind_cdir": "WNW",
+ "wind_cdir_full": "west-northwest",
+ "wind_dir": 302,
+ "wind_gust_spd": 4.2,
+ "wind_spd": 4.2
+ },
+ {
+ "app_max_temp": -5.3,
+ "app_min_temp": -10.9,
+ "clouds": 40,
+ "clouds_hi": 0,
+ "clouds_low": 40,
+ "clouds_mid": 0,
+ "datetime": "2026-02-12",
+ "dewpt": -5.2,
+ "high_temp": 0,
+ "low_temp": -6.3,
+ "max_dhi": null,
+ "max_temp": 0,
+ "min_temp": -4.6,
+ "moon_phase": 0.14,
+ "moon_phase_lunation": 0.85,
+ "moonrise_ts": 1770886312,
+ "moonset_ts": 1770920833,
+ "ozone": 378,
+ "pop": 20,
+ "precip": 0.125,
+ "pres": 1010,
+ "rh": 79,
+ "slp": 1013,
+ "snow": 0.625,
+ "snow_depth": 49.526215,
+ "sunrise_ts": 1770897177,
+ "sunset_ts": 1770935347,
+ "temp": -2,
+ "ts": 1770872460,
+ "uv": 4,
+ "valid_date": "2026-02-12",
+ "vis": 24,
+ "weather": { "code": 610, "description": "Mix snow/rain", "icon": "s04d" },
+ "wind_cdir": "WNW",
+ "wind_cdir_full": "west-northwest",
+ "wind_dir": 299,
+ "wind_gust_spd": 12,
+ "wind_spd": 5.3
+ }
+ ],
+ "lat": 40.7128,
+ "lon": -74.006,
+ "state_code": "NY",
+ "timezone": "America/New_York"
+}
diff --git a/tests/mocks/weather_weatherbit_hourly.json b/tests/mocks/weather_weatherbit_hourly.json
new file mode 100644
index 00000000..d2777500
--- /dev/null
+++ b/tests/mocks/weather_weatherbit_hourly.json
@@ -0,0 +1 @@
+{ "error": "Your API key does not allow access to this endpoint." }
diff --git a/tests/mocks/weather_weatherflow.json b/tests/mocks/weather_weatherflow.json
new file mode 100644
index 00000000..38e4fbdb
--- /dev/null
+++ b/tests/mocks/weather_weatherflow.json
@@ -0,0 +1,4875 @@
+{
+ "current_conditions": {
+ "air_density": 1.22,
+ "air_temperature": 16.0,
+ "brightness": 22546,
+ "conditions": "Clear",
+ "delta_t": 8.0,
+ "dew_point": -2.0,
+ "feels_like": 16.0,
+ "icon": "clear-day",
+ "is_precip_local_day_rain_check": true,
+ "is_precip_local_yesterday_rain_check": true,
+ "lightning_strike_count_last_1hr": 0,
+ "lightning_strike_count_last_3hr": 0,
+ "lightning_strike_last_distance": 25,
+ "lightning_strike_last_distance_msg": "23 - 27 km",
+ "lightning_strike_last_epoch": 1765159221,
+ "precip_accum_local_day": 0,
+ "precip_accum_local_yesterday": 1.75,
+ "precip_minutes_local_day": 0,
+ "precip_minutes_local_yesterday": 141,
+ "precip_probability": 0,
+ "pressure_trend": "falling",
+ "relative_humidity": 28,
+ "sea_level_pressure": 1013.6,
+ "solar_radiation": 188,
+ "station_pressure": 1013.0,
+ "time": 1770414299,
+ "uv": 1,
+ "wet_bulb_globe_temperature": 10.0,
+ "wet_bulb_temperature": 8.0,
+ "wind_avg": 15.0,
+ "wind_direction": 269,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 20.0
+ },
+ "forecast": {
+ "daily": [
+ {
+ "air_temp_high": 15.0,
+ "air_temp_low": 4.0,
+ "conditions": "Clear",
+ "day_num": 6,
+ "day_start_local": 1770354000,
+ "icon": "clear-day",
+ "month_num": 2,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "sunrise": 1770379765,
+ "sunset": 1770419180
+ },
+ {
+ "air_temp_high": 14.0,
+ "air_temp_low": 10.0,
+ "conditions": "Clear",
+ "day_num": 7,
+ "day_start_local": 1770440400,
+ "icon": "clear-day",
+ "month_num": 2,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "sunrise": 1770466123,
+ "sunset": 1770505628
+ },
+ {
+ "air_temp_high": 16.0,
+ "air_temp_low": 10.0,
+ "conditions": "Clear",
+ "day_num": 8,
+ "day_start_local": 1770526800,
+ "icon": "clear-day",
+ "month_num": 2,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "sunrise": 1770552481,
+ "sunset": 1770592076
+ },
+ {
+ "air_temp_high": 18.0,
+ "air_temp_low": 9.0,
+ "conditions": "Clear",
+ "day_num": 9,
+ "day_start_local": 1770613200,
+ "icon": "clear-day",
+ "month_num": 2,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "sunrise": 1770638837,
+ "sunset": 1770678523
+ },
+ {
+ "air_temp_high": 20.0,
+ "air_temp_low": 10.0,
+ "conditions": "Partly Cloudy",
+ "day_num": 10,
+ "day_start_local": 1770699600,
+ "icon": "partly-cloudy-day",
+ "month_num": 2,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "sunrise": 1770725192,
+ "sunset": 1770764970
+ },
+ {
+ "air_temp_high": 21.0,
+ "air_temp_low": 13.0,
+ "conditions": "Partly Cloudy",
+ "day_num": 11,
+ "day_start_local": 1770786000,
+ "icon": "partly-cloudy-day",
+ "month_num": 2,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "sunrise": 1770811546,
+ "sunset": 1770851417
+ },
+ {
+ "air_temp_high": 20.0,
+ "air_temp_low": 14.0,
+ "conditions": "Partly Cloudy",
+ "day_num": 12,
+ "day_start_local": 1770872400,
+ "icon": "partly-cloudy-day",
+ "month_num": 2,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "sunrise": 1770897898,
+ "sunset": 1770937863
+ },
+ {
+ "air_temp_high": 20.0,
+ "air_temp_low": 14.0,
+ "conditions": "Partly Cloudy",
+ "day_num": 13,
+ "day_start_local": 1770958800,
+ "icon": "partly-cloudy-day",
+ "month_num": 2,
+ "precip_icon": "chance-rain",
+ "precip_probability": 10,
+ "precip_type": "rain",
+ "sunrise": 1770984250,
+ "sunset": 1771024309
+ },
+ {
+ "air_temp_high": 19.0,
+ "air_temp_low": 14.0,
+ "conditions": "Rain Possible",
+ "day_num": 14,
+ "day_start_local": 1771045200,
+ "icon": "possibly-rainy-day",
+ "month_num": 2,
+ "precip_icon": "chance-rain",
+ "precip_probability": 20,
+ "precip_type": "rain",
+ "sunrise": 1771070600,
+ "sunset": 1771110755
+ },
+ {
+ "air_temp_high": 19.0,
+ "air_temp_low": 14.0,
+ "conditions": "Partly Cloudy",
+ "day_num": 15,
+ "day_start_local": 1771131600,
+ "icon": "partly-cloudy-day",
+ "month_num": 2,
+ "precip_icon": "chance-rain",
+ "precip_probability": 10,
+ "precip_type": "rain",
+ "sunrise": 1771156949,
+ "sunset": 1771197200
+ }
+ ],
+ "hourly": [
+ {
+ "air_temperature": 15.0,
+ "conditions": "Clear",
+ "feels_like": 15.0,
+ "icon": "clear-day",
+ "local_day": 6,
+ "local_hour": 17,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 42,
+ "sea_level_pressure": 1013.6,
+ "station_pressure": 1013.2,
+ "time": 1770415200,
+ "uv": 2.0,
+ "wind_avg": 27.0,
+ "wind_direction": 260,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 40.0
+ },
+ {
+ "air_temperature": 15.0,
+ "conditions": "Clear",
+ "feels_like": 15.0,
+ "icon": "clear-day",
+ "local_day": 6,
+ "local_hour": 18,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 45,
+ "sea_level_pressure": 1014.4,
+ "station_pressure": 1014.0,
+ "time": 1770418800,
+ "uv": 0.0,
+ "wind_avg": 32.0,
+ "wind_direction": 250,
+ "wind_direction_cardinal": "WSW",
+ "wind_gust": 44.0
+ },
+ {
+ "air_temperature": 14.0,
+ "conditions": "Clear",
+ "feels_like": 14.0,
+ "icon": "clear-night",
+ "local_day": 6,
+ "local_hour": 19,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 52,
+ "sea_level_pressure": 1015.0,
+ "station_pressure": 1014.6,
+ "time": 1770422400,
+ "uv": 0.0,
+ "wind_avg": 33.0,
+ "wind_direction": 250,
+ "wind_direction_cardinal": "WSW",
+ "wind_gust": 48.0
+ },
+ {
+ "air_temperature": 13.0,
+ "conditions": "Clear",
+ "feels_like": 13.0,
+ "icon": "clear-night",
+ "local_day": 6,
+ "local_hour": 20,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 61,
+ "sea_level_pressure": 1015.3,
+ "station_pressure": 1014.9,
+ "time": 1770426000,
+ "uv": 0.0,
+ "wind_avg": 35.0,
+ "wind_direction": 250,
+ "wind_direction_cardinal": "WSW",
+ "wind_gust": 48.0
+ },
+ {
+ "air_temperature": 12.0,
+ "conditions": "Clear",
+ "feels_like": 12.0,
+ "icon": "clear-night",
+ "local_day": 6,
+ "local_hour": 21,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 68,
+ "sea_level_pressure": 1015.2,
+ "station_pressure": 1014.8,
+ "time": 1770429600,
+ "uv": 0.0,
+ "wind_avg": 33.0,
+ "wind_direction": 250,
+ "wind_direction_cardinal": "WSW",
+ "wind_gust": 50.0
+ },
+ {
+ "air_temperature": 12.0,
+ "conditions": "Clear",
+ "feels_like": 12.0,
+ "icon": "clear-night",
+ "local_day": 6,
+ "local_hour": 22,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 76,
+ "sea_level_pressure": 1015.2,
+ "station_pressure": 1014.8,
+ "time": 1770433200,
+ "uv": 0.0,
+ "wind_avg": 32.0,
+ "wind_direction": 250,
+ "wind_direction_cardinal": "WSW",
+ "wind_gust": 48.0
+ },
+ {
+ "air_temperature": 12.0,
+ "conditions": "Clear",
+ "feels_like": 12.0,
+ "icon": "clear-night",
+ "local_day": 6,
+ "local_hour": 23,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 83,
+ "sea_level_pressure": 1015.0,
+ "station_pressure": 1014.6,
+ "time": 1770436800,
+ "uv": 0.0,
+ "wind_avg": 30.0,
+ "wind_direction": 250,
+ "wind_direction_cardinal": "WSW",
+ "wind_gust": 47.0
+ },
+ {
+ "air_temperature": 12.0,
+ "conditions": "Clear",
+ "feels_like": 12.0,
+ "icon": "clear-night",
+ "local_day": 7,
+ "local_hour": 0,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 88,
+ "sea_level_pressure": 1015.0,
+ "station_pressure": 1014.6,
+ "time": 1770440400,
+ "uv": 0.0,
+ "wind_avg": 29.0,
+ "wind_direction": 260,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 45.0
+ },
+ {
+ "air_temperature": 12.0,
+ "conditions": "Clear",
+ "feels_like": 12.0,
+ "icon": "clear-night",
+ "local_day": 7,
+ "local_hour": 1,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 88,
+ "sea_level_pressure": 1015.1,
+ "station_pressure": 1014.7,
+ "time": 1770444000,
+ "uv": 0.0,
+ "wind_avg": 27.0,
+ "wind_direction": 270,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 44.0
+ },
+ {
+ "air_temperature": 12.0,
+ "conditions": "Clear",
+ "feels_like": 12.0,
+ "icon": "clear-night",
+ "local_day": 7,
+ "local_hour": 2,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 86,
+ "sea_level_pressure": 1014.9,
+ "station_pressure": 1014.5,
+ "time": 1770447600,
+ "uv": 0.0,
+ "wind_avg": 27.0,
+ "wind_direction": 270,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 44.0
+ },
+ {
+ "air_temperature": 12.0,
+ "conditions": "Clear",
+ "feels_like": 12.0,
+ "icon": "clear-night",
+ "local_day": 7,
+ "local_hour": 3,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 86,
+ "sea_level_pressure": 1015.0,
+ "station_pressure": 1014.6,
+ "time": 1770451200,
+ "uv": 0.0,
+ "wind_avg": 26.0,
+ "wind_direction": 280,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 44.0
+ },
+ {
+ "air_temperature": 12.0,
+ "conditions": "Clear",
+ "feels_like": 12.0,
+ "icon": "clear-night",
+ "local_day": 7,
+ "local_hour": 4,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 85,
+ "sea_level_pressure": 1015.1,
+ "station_pressure": 1014.7,
+ "time": 1770454800,
+ "uv": 0.0,
+ "wind_avg": 26.0,
+ "wind_direction": 290,
+ "wind_direction_cardinal": "WNW",
+ "wind_gust": 42.0
+ },
+ {
+ "air_temperature": 11.0,
+ "conditions": "Clear",
+ "feels_like": 11.0,
+ "icon": "clear-night",
+ "local_day": 7,
+ "local_hour": 5,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 83,
+ "sea_level_pressure": 1015.6,
+ "station_pressure": 1015.2,
+ "time": 1770458400,
+ "uv": 0.0,
+ "wind_avg": 24.0,
+ "wind_direction": 290,
+ "wind_direction_cardinal": "WNW",
+ "wind_gust": 41.0
+ },
+ {
+ "air_temperature": 11.0,
+ "conditions": "Clear",
+ "feels_like": 11.0,
+ "icon": "clear-night",
+ "local_day": 7,
+ "local_hour": 6,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 83,
+ "sea_level_pressure": 1016.4,
+ "station_pressure": 1016.0,
+ "time": 1770462000,
+ "uv": 0.0,
+ "wind_avg": 24.0,
+ "wind_direction": 300,
+ "wind_direction_cardinal": "WNW",
+ "wind_gust": 39.0
+ },
+ {
+ "air_temperature": 10.0,
+ "conditions": "Clear",
+ "feels_like": 10.0,
+ "icon": "clear-night",
+ "local_day": 7,
+ "local_hour": 7,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 83,
+ "sea_level_pressure": 1017.2,
+ "station_pressure": 1016.8,
+ "time": 1770465600,
+ "uv": 0.0,
+ "wind_avg": 24.0,
+ "wind_direction": 310,
+ "wind_direction_cardinal": "NW",
+ "wind_gust": 39.0
+ },
+ {
+ "air_temperature": 11.0,
+ "conditions": "Clear",
+ "feels_like": 11.0,
+ "icon": "clear-day",
+ "local_day": 7,
+ "local_hour": 8,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 82,
+ "sea_level_pressure": 1018.5,
+ "station_pressure": 1018.1,
+ "time": 1770469200,
+ "uv": 1.0,
+ "wind_avg": 26.0,
+ "wind_direction": 320,
+ "wind_direction_cardinal": "NW",
+ "wind_gust": 39.0
+ },
+ {
+ "air_temperature": 12.0,
+ "conditions": "Clear",
+ "feels_like": 12.0,
+ "icon": "clear-day",
+ "local_day": 7,
+ "local_hour": 9,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 73,
+ "sea_level_pressure": 1019.8,
+ "station_pressure": 1019.4,
+ "time": 1770472800,
+ "uv": 2.0,
+ "wind_avg": 27.0,
+ "wind_direction": 330,
+ "wind_direction_cardinal": "NNW",
+ "wind_gust": 39.0
+ },
+ {
+ "air_temperature": 13.0,
+ "conditions": "Clear",
+ "feels_like": 13.0,
+ "icon": "clear-day",
+ "local_day": 7,
+ "local_hour": 10,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 67,
+ "sea_level_pressure": 1020.4,
+ "station_pressure": 1020.0,
+ "time": 1770476400,
+ "uv": 4.0,
+ "wind_avg": 29.0,
+ "wind_direction": 340,
+ "wind_direction_cardinal": "NNW",
+ "wind_gust": 39.0
+ },
+ {
+ "air_temperature": 13.0,
+ "conditions": "Clear",
+ "feels_like": 13.0,
+ "icon": "clear-day",
+ "local_day": 7,
+ "local_hour": 11,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 64,
+ "sea_level_pressure": 1020.8,
+ "station_pressure": 1020.4,
+ "time": 1770480000,
+ "uv": 5.0,
+ "wind_avg": 29.0,
+ "wind_direction": 340,
+ "wind_direction_cardinal": "NNW",
+ "wind_gust": 39.0
+ },
+ {
+ "air_temperature": 13.0,
+ "conditions": "Clear",
+ "feels_like": 13.0,
+ "icon": "clear-day",
+ "local_day": 7,
+ "local_hour": 12,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 61,
+ "sea_level_pressure": 1020.7,
+ "station_pressure": 1020.3,
+ "time": 1770483600,
+ "uv": 6.0,
+ "wind_avg": 29.0,
+ "wind_direction": 350,
+ "wind_direction_cardinal": "N",
+ "wind_gust": 38.0
+ },
+ {
+ "air_temperature": 14.0,
+ "conditions": "Clear",
+ "feels_like": 14.0,
+ "icon": "clear-day",
+ "local_day": 7,
+ "local_hour": 13,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 59,
+ "sea_level_pressure": 1020.0,
+ "station_pressure": 1019.6,
+ "time": 1770487200,
+ "uv": 7.0,
+ "wind_avg": 27.0,
+ "wind_direction": 350,
+ "wind_direction_cardinal": "N",
+ "wind_gust": 39.0
+ },
+ {
+ "air_temperature": 13.0,
+ "conditions": "Clear",
+ "feels_like": 13.0,
+ "icon": "clear-day",
+ "local_day": 7,
+ "local_hour": 14,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 63,
+ "sea_level_pressure": 1019.8,
+ "station_pressure": 1019.4,
+ "time": 1770490800,
+ "uv": 7.0,
+ "wind_avg": 27.0,
+ "wind_direction": 360,
+ "wind_direction_cardinal": "N",
+ "wind_gust": 38.0
+ },
+ {
+ "air_temperature": 13.0,
+ "conditions": "Clear",
+ "feels_like": 13.0,
+ "icon": "clear-day",
+ "local_day": 7,
+ "local_hour": 15,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 61,
+ "sea_level_pressure": 1019.9,
+ "station_pressure": 1019.5,
+ "time": 1770494400,
+ "uv": 6.0,
+ "wind_avg": 27.0,
+ "wind_direction": 0,
+ "wind_direction_cardinal": "N",
+ "wind_gust": 38.0
+ },
+ {
+ "air_temperature": 13.0,
+ "conditions": "Clear",
+ "feels_like": 13.0,
+ "icon": "clear-day",
+ "local_day": 7,
+ "local_hour": 16,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 61,
+ "sea_level_pressure": 1020.4,
+ "station_pressure": 1020.0,
+ "time": 1770498000,
+ "uv": 4.0,
+ "wind_avg": 27.0,
+ "wind_direction": 10,
+ "wind_direction_cardinal": "N",
+ "wind_gust": 36.0
+ },
+ {
+ "air_temperature": 13.0,
+ "conditions": "Clear",
+ "feels_like": 13.0,
+ "icon": "clear-day",
+ "local_day": 7,
+ "local_hour": 17,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 63,
+ "sea_level_pressure": 1021.1,
+ "station_pressure": 1020.7,
+ "time": 1770501600,
+ "uv": 2.0,
+ "wind_avg": 27.0,
+ "wind_direction": 10,
+ "wind_direction_cardinal": "N",
+ "wind_gust": 36.0
+ },
+ {
+ "air_temperature": 12.0,
+ "conditions": "Clear",
+ "feels_like": 12.0,
+ "icon": "clear-day",
+ "local_day": 7,
+ "local_hour": 18,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 65,
+ "sea_level_pressure": 1021.6,
+ "station_pressure": 1021.2,
+ "time": 1770505200,
+ "uv": 1.0,
+ "wind_avg": 26.0,
+ "wind_direction": 10,
+ "wind_direction_cardinal": "N",
+ "wind_gust": 36.0
+ },
+ {
+ "air_temperature": 12.0,
+ "conditions": "Clear",
+ "feels_like": 12.0,
+ "icon": "clear-night",
+ "local_day": 7,
+ "local_hour": 19,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 66,
+ "sea_level_pressure": 1022.3,
+ "station_pressure": 1021.9,
+ "time": 1770508800,
+ "uv": 0.0,
+ "wind_avg": 23.0,
+ "wind_direction": 20,
+ "wind_direction_cardinal": "NNE",
+ "wind_gust": 34.0
+ },
+ {
+ "air_temperature": 12.0,
+ "conditions": "Clear",
+ "feels_like": 12.0,
+ "icon": "clear-night",
+ "local_day": 7,
+ "local_hour": 20,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 68,
+ "sea_level_pressure": 1022.9,
+ "station_pressure": 1022.5,
+ "time": 1770512400,
+ "uv": 0.0,
+ "wind_avg": 23.0,
+ "wind_direction": 20,
+ "wind_direction_cardinal": "NNE",
+ "wind_gust": 32.0
+ },
+ {
+ "air_temperature": 12.0,
+ "conditions": "Clear",
+ "feels_like": 12.0,
+ "icon": "clear-night",
+ "local_day": 7,
+ "local_hour": 21,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 65,
+ "sea_level_pressure": 1023.4,
+ "station_pressure": 1023.0,
+ "time": 1770516000,
+ "uv": 0.0,
+ "wind_avg": 22.0,
+ "wind_direction": 20,
+ "wind_direction_cardinal": "NNE",
+ "wind_gust": 32.0
+ },
+ {
+ "air_temperature": 12.0,
+ "conditions": "Clear",
+ "feels_like": 12.0,
+ "icon": "clear-night",
+ "local_day": 7,
+ "local_hour": 22,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 68,
+ "sea_level_pressure": 1023.7,
+ "station_pressure": 1023.3,
+ "time": 1770519600,
+ "uv": 0.0,
+ "wind_avg": 19.0,
+ "wind_direction": 20,
+ "wind_direction_cardinal": "NNE",
+ "wind_gust": 31.0
+ },
+ {
+ "air_temperature": 12.0,
+ "conditions": "Clear",
+ "feels_like": 12.0,
+ "icon": "clear-night",
+ "local_day": 7,
+ "local_hour": 23,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 67,
+ "sea_level_pressure": 1024.0,
+ "station_pressure": 1023.6,
+ "time": 1770523200,
+ "uv": 0.0,
+ "wind_avg": 19.0,
+ "wind_direction": 30,
+ "wind_direction_cardinal": "NNE",
+ "wind_gust": 28.0
+ },
+ {
+ "air_temperature": 12.0,
+ "conditions": "Clear",
+ "feels_like": 12.0,
+ "icon": "clear-night",
+ "local_day": 8,
+ "local_hour": 0,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 66,
+ "sea_level_pressure": 1024.1,
+ "station_pressure": 1023.7,
+ "time": 1770526800,
+ "uv": 0.0,
+ "wind_avg": 17.0,
+ "wind_direction": 20,
+ "wind_direction_cardinal": "NNE",
+ "wind_gust": 28.0
+ },
+ {
+ "air_temperature": 11.0,
+ "conditions": "Clear",
+ "feels_like": 11.0,
+ "icon": "clear-night",
+ "local_day": 8,
+ "local_hour": 1,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 67,
+ "sea_level_pressure": 1024.1,
+ "station_pressure": 1023.7,
+ "time": 1770530400,
+ "uv": 0.0,
+ "wind_avg": 16.0,
+ "wind_direction": 20,
+ "wind_direction_cardinal": "NNE",
+ "wind_gust": 26.0
+ },
+ {
+ "air_temperature": 11.0,
+ "conditions": "Clear",
+ "feels_like": 11.0,
+ "icon": "clear-night",
+ "local_day": 8,
+ "local_hour": 2,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 66,
+ "sea_level_pressure": 1024.2,
+ "station_pressure": 1023.8,
+ "time": 1770534000,
+ "uv": 0.0,
+ "wind_avg": 15.0,
+ "wind_direction": 20,
+ "wind_direction_cardinal": "NNE",
+ "wind_gust": 26.0
+ },
+ {
+ "air_temperature": 11.0,
+ "conditions": "Clear",
+ "feels_like": 11.0,
+ "icon": "clear-night",
+ "local_day": 8,
+ "local_hour": 3,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 67,
+ "sea_level_pressure": 1024.2,
+ "station_pressure": 1023.8,
+ "time": 1770537600,
+ "uv": 0.0,
+ "wind_avg": 15.0,
+ "wind_direction": 20,
+ "wind_direction_cardinal": "NNE",
+ "wind_gust": 25.0
+ },
+ {
+ "air_temperature": 10.0,
+ "conditions": "Clear",
+ "feels_like": 10.0,
+ "icon": "clear-night",
+ "local_day": 8,
+ "local_hour": 4,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 68,
+ "sea_level_pressure": 1024.3,
+ "station_pressure": 1023.9,
+ "time": 1770541200,
+ "uv": 0.0,
+ "wind_avg": 14.0,
+ "wind_direction": 20,
+ "wind_direction_cardinal": "NNE",
+ "wind_gust": 25.0
+ },
+ {
+ "air_temperature": 10.0,
+ "conditions": "Clear",
+ "feels_like": 10.0,
+ "icon": "clear-night",
+ "local_day": 8,
+ "local_hour": 5,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 70,
+ "sea_level_pressure": 1024.7,
+ "station_pressure": 1024.3,
+ "time": 1770544800,
+ "uv": 0.0,
+ "wind_avg": 14.0,
+ "wind_direction": 20,
+ "wind_direction_cardinal": "NNE",
+ "wind_gust": 24.0
+ },
+ {
+ "air_temperature": 10.0,
+ "conditions": "Clear",
+ "feels_like": 8.0,
+ "icon": "clear-night",
+ "local_day": 8,
+ "local_hour": 6,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 72,
+ "sea_level_pressure": 1025.1,
+ "station_pressure": 1024.7,
+ "time": 1770548400,
+ "uv": 0.0,
+ "wind_avg": 13.0,
+ "wind_direction": 20,
+ "wind_direction_cardinal": "NNE",
+ "wind_gust": 23.0
+ },
+ {
+ "air_temperature": 10.0,
+ "conditions": "Clear",
+ "feels_like": 8.0,
+ "icon": "clear-night",
+ "local_day": 8,
+ "local_hour": 7,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 71,
+ "sea_level_pressure": 1025.4,
+ "station_pressure": 1025.0,
+ "time": 1770552000,
+ "uv": 0.0,
+ "wind_avg": 13.0,
+ "wind_direction": 20,
+ "wind_direction_cardinal": "NNE",
+ "wind_gust": 22.0
+ },
+ {
+ "air_temperature": 11.0,
+ "conditions": "Clear",
+ "feels_like": 11.0,
+ "icon": "clear-day",
+ "local_day": 8,
+ "local_hour": 8,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 74,
+ "sea_level_pressure": 1025.9,
+ "station_pressure": 1025.5,
+ "time": 1770555600,
+ "uv": 4.0,
+ "wind_avg": 13.0,
+ "wind_direction": 30,
+ "wind_direction_cardinal": "NNE",
+ "wind_gust": 22.0
+ },
+ {
+ "air_temperature": 13.0,
+ "conditions": "Clear",
+ "feels_like": 13.0,
+ "icon": "clear-day",
+ "local_day": 8,
+ "local_hour": 9,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 67,
+ "sea_level_pressure": 1026.4,
+ "station_pressure": 1026.0,
+ "time": 1770559200,
+ "uv": 4.0,
+ "wind_avg": 14.0,
+ "wind_direction": 30,
+ "wind_direction_cardinal": "NNE",
+ "wind_gust": 23.0
+ },
+ {
+ "air_temperature": 14.0,
+ "conditions": "Clear",
+ "feels_like": 14.0,
+ "icon": "clear-day",
+ "local_day": 8,
+ "local_hour": 10,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 61,
+ "sea_level_pressure": 1026.9,
+ "station_pressure": 1026.5,
+ "time": 1770562800,
+ "uv": 4.0,
+ "wind_avg": 14.0,
+ "wind_direction": 30,
+ "wind_direction_cardinal": "NNE",
+ "wind_gust": 23.0
+ },
+ {
+ "air_temperature": 15.0,
+ "conditions": "Clear",
+ "feels_like": 15.0,
+ "icon": "clear-day",
+ "local_day": 8,
+ "local_hour": 11,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 62,
+ "sea_level_pressure": 1026.4,
+ "station_pressure": 1026.0,
+ "time": 1770566400,
+ "uv": 6.0,
+ "wind_avg": 15.0,
+ "wind_direction": 30,
+ "wind_direction_cardinal": "NNE",
+ "wind_gust": 22.0
+ },
+ {
+ "air_temperature": 15.0,
+ "conditions": "Clear",
+ "feels_like": 15.0,
+ "icon": "clear-day",
+ "local_day": 8,
+ "local_hour": 12,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 61,
+ "sea_level_pressure": 1026.0,
+ "station_pressure": 1025.6,
+ "time": 1770570000,
+ "uv": 6.0,
+ "wind_avg": 15.0,
+ "wind_direction": 30,
+ "wind_direction_cardinal": "NNE",
+ "wind_gust": 22.0
+ },
+ {
+ "air_temperature": 16.0,
+ "conditions": "Clear",
+ "feels_like": 16.0,
+ "icon": "clear-day",
+ "local_day": 8,
+ "local_hour": 13,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 60,
+ "sea_level_pressure": 1025.5,
+ "station_pressure": 1025.1,
+ "time": 1770573600,
+ "uv": 6.0,
+ "wind_avg": 16.0,
+ "wind_direction": 30,
+ "wind_direction_cardinal": "NNE",
+ "wind_gust": 21.0
+ },
+ {
+ "air_temperature": 16.0,
+ "conditions": "Clear",
+ "feels_like": 16.0,
+ "icon": "clear-day",
+ "local_day": 8,
+ "local_hour": 14,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 63,
+ "sea_level_pressure": 1025.3,
+ "station_pressure": 1024.9,
+ "time": 1770577200,
+ "uv": 5.0,
+ "wind_avg": 15.0,
+ "wind_direction": 30,
+ "wind_direction_cardinal": "NNE",
+ "wind_gust": 21.0
+ },
+ {
+ "air_temperature": 16.0,
+ "conditions": "Clear",
+ "feels_like": 16.0,
+ "icon": "clear-day",
+ "local_day": 8,
+ "local_hour": 15,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 62,
+ "sea_level_pressure": 1025.1,
+ "station_pressure": 1024.7,
+ "time": 1770580800,
+ "uv": 5.0,
+ "wind_avg": 15.0,
+ "wind_direction": 30,
+ "wind_direction_cardinal": "NNE",
+ "wind_gust": 20.0
+ },
+ {
+ "air_temperature": 16.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 16.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 8,
+ "local_hour": 16,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 63,
+ "sea_level_pressure": 1025.0,
+ "station_pressure": 1024.6,
+ "time": 1770584400,
+ "uv": 5.0,
+ "wind_avg": 14.0,
+ "wind_direction": 30,
+ "wind_direction_cardinal": "NNE",
+ "wind_gust": 19.0
+ },
+ {
+ "air_temperature": 15.0,
+ "conditions": "Clear",
+ "feels_like": 15.0,
+ "icon": "clear-day",
+ "local_day": 8,
+ "local_hour": 17,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 68,
+ "sea_level_pressure": 1025.3,
+ "station_pressure": 1024.9,
+ "time": 1770588000,
+ "uv": 1.0,
+ "wind_avg": 12.0,
+ "wind_direction": 40,
+ "wind_direction_cardinal": "NE",
+ "wind_gust": 18.0
+ },
+ {
+ "air_temperature": 14.0,
+ "conditions": "Clear",
+ "feels_like": 14.0,
+ "icon": "clear-day",
+ "local_day": 8,
+ "local_hour": 18,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 71,
+ "sea_level_pressure": 1025.7,
+ "station_pressure": 1025.3,
+ "time": 1770591600,
+ "uv": 1.0,
+ "wind_avg": 10.0,
+ "wind_direction": 40,
+ "wind_direction_cardinal": "NE",
+ "wind_gust": 16.0
+ },
+ {
+ "air_temperature": 14.0,
+ "conditions": "Clear",
+ "feels_like": 14.0,
+ "icon": "clear-night",
+ "local_day": 8,
+ "local_hour": 19,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 74,
+ "sea_level_pressure": 1026.1,
+ "station_pressure": 1025.7,
+ "time": 1770595200,
+ "uv": 1.0,
+ "wind_avg": 7.0,
+ "wind_direction": 40,
+ "wind_direction_cardinal": "NE",
+ "wind_gust": 14.0
+ },
+ {
+ "air_temperature": 13.0,
+ "conditions": "Clear",
+ "feels_like": 13.0,
+ "icon": "clear-night",
+ "local_day": 8,
+ "local_hour": 20,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 78,
+ "sea_level_pressure": 1026.1,
+ "station_pressure": 1025.7,
+ "time": 1770598800,
+ "uv": 0.0,
+ "wind_avg": 7.0,
+ "wind_direction": 60,
+ "wind_direction_cardinal": "ENE",
+ "wind_gust": 13.0
+ },
+ {
+ "air_temperature": 13.0,
+ "conditions": "Clear",
+ "feels_like": 13.0,
+ "icon": "clear-night",
+ "local_day": 8,
+ "local_hour": 21,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 80,
+ "sea_level_pressure": 1026.1,
+ "station_pressure": 1025.7,
+ "time": 1770602400,
+ "uv": 0.0,
+ "wind_avg": 6.0,
+ "wind_direction": 60,
+ "wind_direction_cardinal": "ENE",
+ "wind_gust": 12.0
+ },
+ {
+ "air_temperature": 13.0,
+ "conditions": "Clear",
+ "feels_like": 13.0,
+ "icon": "clear-night",
+ "local_day": 8,
+ "local_hour": 22,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 83,
+ "sea_level_pressure": 1026.2,
+ "station_pressure": 1025.8,
+ "time": 1770606000,
+ "uv": 0.0,
+ "wind_avg": 6.0,
+ "wind_direction": 60,
+ "wind_direction_cardinal": "ENE",
+ "wind_gust": 11.0
+ },
+ {
+ "air_temperature": 12.0,
+ "conditions": "Clear",
+ "feels_like": 12.0,
+ "icon": "clear-night",
+ "local_day": 8,
+ "local_hour": 23,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 79,
+ "sea_level_pressure": 1026.0,
+ "station_pressure": 1025.6,
+ "time": 1770609600,
+ "uv": 0.0,
+ "wind_avg": 5.0,
+ "wind_direction": 270,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 11.0
+ },
+ {
+ "air_temperature": 12.0,
+ "conditions": "Clear",
+ "feels_like": 12.0,
+ "icon": "clear-night",
+ "local_day": 9,
+ "local_hour": 0,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 80,
+ "sea_level_pressure": 1025.9,
+ "station_pressure": 1025.5,
+ "time": 1770613200,
+ "uv": 0.0,
+ "wind_avg": 5.0,
+ "wind_direction": 270,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 11.0
+ },
+ {
+ "air_temperature": 12.0,
+ "conditions": "Clear",
+ "feels_like": 12.0,
+ "icon": "clear-night",
+ "local_day": 9,
+ "local_hour": 1,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 82,
+ "sea_level_pressure": 1025.8,
+ "station_pressure": 1025.4,
+ "time": 1770616800,
+ "uv": 0.0,
+ "wind_avg": 4.0,
+ "wind_direction": 270,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 11.0
+ },
+ {
+ "air_temperature": 11.0,
+ "conditions": "Clear",
+ "feels_like": 11.0,
+ "icon": "clear-night",
+ "local_day": 9,
+ "local_hour": 2,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 80,
+ "sea_level_pressure": 1025.3,
+ "station_pressure": 1024.9,
+ "time": 1770620400,
+ "uv": 0.0,
+ "wind_avg": 5.0,
+ "wind_direction": 280,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 12.0
+ },
+ {
+ "air_temperature": 10.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 10.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 9,
+ "local_hour": 3,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 84,
+ "sea_level_pressure": 1024.8,
+ "station_pressure": 1024.4,
+ "time": 1770624000,
+ "uv": 0.0,
+ "wind_avg": 5.0,
+ "wind_direction": 280,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 12.0
+ },
+ {
+ "air_temperature": 10.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 9.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 9,
+ "local_hour": 4,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 87,
+ "sea_level_pressure": 1024.3,
+ "station_pressure": 1023.9,
+ "time": 1770627600,
+ "uv": 0.0,
+ "wind_avg": 6.0,
+ "wind_direction": 280,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 13.0
+ },
+ {
+ "air_temperature": 9.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 9.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 9,
+ "local_hour": 5,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 90,
+ "sea_level_pressure": 1024.7,
+ "station_pressure": 1024.3,
+ "time": 1770631200,
+ "uv": 0.0,
+ "wind_avg": 6.0,
+ "wind_direction": 290,
+ "wind_direction_cardinal": "WNW",
+ "wind_gust": 14.0
+ },
+ {
+ "air_temperature": 9.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 8.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 9,
+ "local_hour": 6,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 92,
+ "sea_level_pressure": 1025.0,
+ "station_pressure": 1024.6,
+ "time": 1770634800,
+ "uv": 0.0,
+ "wind_avg": 7.0,
+ "wind_direction": 290,
+ "wind_direction_cardinal": "WNW",
+ "wind_gust": 14.0
+ },
+ {
+ "air_temperature": 10.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 9.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 9,
+ "local_hour": 7,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 89,
+ "sea_level_pressure": 1025.3,
+ "station_pressure": 1024.9,
+ "time": 1770638400,
+ "uv": 0.0,
+ "wind_avg": 7.0,
+ "wind_direction": 290,
+ "wind_direction_cardinal": "WNW",
+ "wind_gust": 15.0
+ },
+ {
+ "air_temperature": 11.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 11.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 9,
+ "local_hour": 8,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 90,
+ "sea_level_pressure": 1025.8,
+ "station_pressure": 1025.4,
+ "time": 1770642000,
+ "uv": 2.0,
+ "wind_avg": 8.0,
+ "wind_direction": 300,
+ "wind_direction_cardinal": "WNW",
+ "wind_gust": 15.0
+ },
+ {
+ "air_temperature": 13.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 13.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 9,
+ "local_hour": 9,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 79,
+ "sea_level_pressure": 1026.3,
+ "station_pressure": 1025.9,
+ "time": 1770645600,
+ "uv": 2.0,
+ "wind_avg": 8.0,
+ "wind_direction": 300,
+ "wind_direction_cardinal": "WNW",
+ "wind_gust": 16.0
+ },
+ {
+ "air_temperature": 15.0,
+ "conditions": "Clear",
+ "feels_like": 15.0,
+ "icon": "clear-day",
+ "local_day": 9,
+ "local_hour": 10,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 71,
+ "sea_level_pressure": 1026.8,
+ "station_pressure": 1026.4,
+ "time": 1770649200,
+ "uv": 2.0,
+ "wind_avg": 9.0,
+ "wind_direction": 300,
+ "wind_direction_cardinal": "WNW",
+ "wind_gust": 16.0
+ },
+ {
+ "air_temperature": 16.0,
+ "conditions": "Clear",
+ "feels_like": 16.0,
+ "icon": "clear-day",
+ "local_day": 9,
+ "local_hour": 11,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 61,
+ "sea_level_pressure": 1026.2,
+ "station_pressure": 1025.8,
+ "time": 1770652800,
+ "uv": 4.0,
+ "wind_avg": 10.0,
+ "wind_direction": 330,
+ "wind_direction_cardinal": "NNW",
+ "wind_gust": 16.0
+ },
+ {
+ "air_temperature": 17.0,
+ "conditions": "Clear",
+ "feels_like": 17.0,
+ "icon": "clear-day",
+ "local_day": 9,
+ "local_hour": 12,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 59,
+ "sea_level_pressure": 1025.5,
+ "station_pressure": 1025.1,
+ "time": 1770656400,
+ "uv": 4.0,
+ "wind_avg": 10.0,
+ "wind_direction": 330,
+ "wind_direction_cardinal": "NNW",
+ "wind_gust": 17.0
+ },
+ {
+ "air_temperature": 17.0,
+ "conditions": "Clear",
+ "feels_like": 17.0,
+ "icon": "clear-day",
+ "local_day": 9,
+ "local_hour": 13,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 57,
+ "sea_level_pressure": 1024.8,
+ "station_pressure": 1024.4,
+ "time": 1770660000,
+ "uv": 4.0,
+ "wind_avg": 12.0,
+ "wind_direction": 330,
+ "wind_direction_cardinal": "NNW",
+ "wind_gust": 17.0
+ },
+ {
+ "air_temperature": 18.0,
+ "conditions": "Clear",
+ "feels_like": 18.0,
+ "icon": "clear-day",
+ "local_day": 9,
+ "local_hour": 14,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 57,
+ "sea_level_pressure": 1024.1,
+ "station_pressure": 1023.7,
+ "time": 1770663600,
+ "uv": 5.0,
+ "wind_avg": 12.0,
+ "wind_direction": 110,
+ "wind_direction_cardinal": "ESE",
+ "wind_gust": 18.0
+ },
+ {
+ "air_temperature": 18.0,
+ "conditions": "Clear",
+ "feels_like": 18.0,
+ "icon": "clear-day",
+ "local_day": 9,
+ "local_hour": 15,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 56,
+ "sea_level_pressure": 1023.4,
+ "station_pressure": 1023.0,
+ "time": 1770667200,
+ "uv": 5.0,
+ "wind_avg": 12.0,
+ "wind_direction": 110,
+ "wind_direction_cardinal": "ESE",
+ "wind_gust": 18.0
+ },
+ {
+ "air_temperature": 18.0,
+ "conditions": "Clear",
+ "feels_like": 18.0,
+ "icon": "clear-day",
+ "local_day": 9,
+ "local_hour": 16,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 56,
+ "sea_level_pressure": 1022.7,
+ "station_pressure": 1022.3,
+ "time": 1770670800,
+ "uv": 5.0,
+ "wind_avg": 12.0,
+ "wind_direction": 110,
+ "wind_direction_cardinal": "ESE",
+ "wind_gust": 19.0
+ },
+ {
+ "air_temperature": 17.0,
+ "conditions": "Clear",
+ "feels_like": 17.0,
+ "icon": "clear-day",
+ "local_day": 9,
+ "local_hour": 17,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 66,
+ "sea_level_pressure": 1022.9,
+ "station_pressure": 1022.5,
+ "time": 1770674400,
+ "uv": 3.0,
+ "wind_avg": 11.0,
+ "wind_direction": 160,
+ "wind_direction_cardinal": "SSE",
+ "wind_gust": 18.0
+ },
+ {
+ "air_temperature": 16.0,
+ "conditions": "Clear",
+ "feels_like": 16.0,
+ "icon": "clear-day",
+ "local_day": 9,
+ "local_hour": 18,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 69,
+ "sea_level_pressure": 1023.1,
+ "station_pressure": 1022.7,
+ "time": 1770678000,
+ "uv": 3.0,
+ "wind_avg": 10.0,
+ "wind_direction": 160,
+ "wind_direction_cardinal": "SSE",
+ "wind_gust": 16.0
+ },
+ {
+ "air_temperature": 16.0,
+ "conditions": "Clear",
+ "feels_like": 16.0,
+ "icon": "clear-night",
+ "local_day": 9,
+ "local_hour": 19,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 73,
+ "sea_level_pressure": 1023.3,
+ "station_pressure": 1022.9,
+ "time": 1770681600,
+ "uv": 3.0,
+ "wind_avg": 9.0,
+ "wind_direction": 160,
+ "wind_direction_cardinal": "SSE",
+ "wind_gust": 15.0
+ },
+ {
+ "air_temperature": 15.0,
+ "conditions": "Clear",
+ "feels_like": 15.0,
+ "icon": "clear-night",
+ "local_day": 9,
+ "local_hour": 20,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 74,
+ "sea_level_pressure": 1023.4,
+ "station_pressure": 1023.0,
+ "time": 1770685200,
+ "uv": 0.0,
+ "wind_avg": 9.0,
+ "wind_direction": 240,
+ "wind_direction_cardinal": "WSW",
+ "wind_gust": 16.0
+ },
+ {
+ "air_temperature": 15.0,
+ "conditions": "Clear",
+ "feels_like": 15.0,
+ "icon": "clear-night",
+ "local_day": 9,
+ "local_hour": 21,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 76,
+ "sea_level_pressure": 1023.5,
+ "station_pressure": 1023.1,
+ "time": 1770688800,
+ "uv": 0.0,
+ "wind_avg": 9.0,
+ "wind_direction": 240,
+ "wind_direction_cardinal": "WSW",
+ "wind_gust": 17.0
+ },
+ {
+ "air_temperature": 14.0,
+ "conditions": "Clear",
+ "feels_like": 14.0,
+ "icon": "clear-night",
+ "local_day": 9,
+ "local_hour": 22,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 79,
+ "sea_level_pressure": 1023.6,
+ "station_pressure": 1023.2,
+ "time": 1770692400,
+ "uv": 0.0,
+ "wind_avg": 9.0,
+ "wind_direction": 240,
+ "wind_direction_cardinal": "WSW",
+ "wind_gust": 17.0
+ },
+ {
+ "air_temperature": 14.0,
+ "conditions": "Clear",
+ "feels_like": 14.0,
+ "icon": "clear-night",
+ "local_day": 9,
+ "local_hour": 23,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 71,
+ "sea_level_pressure": 1023.4,
+ "station_pressure": 1023.0,
+ "time": 1770696000,
+ "uv": 0.0,
+ "wind_avg": 9.0,
+ "wind_direction": 270,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 18.0
+ },
+ {
+ "air_temperature": 13.0,
+ "conditions": "Clear",
+ "feels_like": 13.0,
+ "icon": "clear-night",
+ "local_day": 10,
+ "local_hour": 0,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 73,
+ "sea_level_pressure": 1023.2,
+ "station_pressure": 1022.8,
+ "time": 1770699600,
+ "uv": 0.0,
+ "wind_avg": 9.0,
+ "wind_direction": 270,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 18.0
+ },
+ {
+ "air_temperature": 13.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 13.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 10,
+ "local_hour": 1,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 76,
+ "sea_level_pressure": 1023.0,
+ "station_pressure": 1022.6,
+ "time": 1770703200,
+ "uv": 0.0,
+ "wind_avg": 9.0,
+ "wind_direction": 270,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 19.0
+ },
+ {
+ "air_temperature": 12.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 12.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 10,
+ "local_hour": 2,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 74,
+ "sea_level_pressure": 1022.9,
+ "station_pressure": 1022.5,
+ "time": 1770706800,
+ "uv": 0.0,
+ "wind_avg": 9.0,
+ "wind_direction": 280,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 18.0
+ },
+ {
+ "air_temperature": 12.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 12.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 10,
+ "local_hour": 3,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 76,
+ "sea_level_pressure": 1022.9,
+ "station_pressure": 1022.5,
+ "time": 1770710400,
+ "uv": 0.0,
+ "wind_avg": 9.0,
+ "wind_direction": 280,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 17.0
+ },
+ {
+ "air_temperature": 11.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 11.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 10,
+ "local_hour": 4,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 79,
+ "sea_level_pressure": 1022.8,
+ "station_pressure": 1022.4,
+ "time": 1770714000,
+ "uv": 0.0,
+ "wind_avg": 9.0,
+ "wind_direction": 280,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 16.0
+ },
+ {
+ "air_temperature": 11.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 11.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 10,
+ "local_hour": 5,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 82,
+ "sea_level_pressure": 1023.2,
+ "station_pressure": 1022.8,
+ "time": 1770717600,
+ "uv": 0.0,
+ "wind_avg": 8.0,
+ "wind_direction": 280,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 15.0
+ },
+ {
+ "air_temperature": 10.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 10.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 10,
+ "local_hour": 6,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 85,
+ "sea_level_pressure": 1023.5,
+ "station_pressure": 1023.1,
+ "time": 1770721200,
+ "uv": 0.0,
+ "wind_avg": 8.0,
+ "wind_direction": 280,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 15.0
+ },
+ {
+ "air_temperature": 11.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 11.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 10,
+ "local_hour": 7,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 83,
+ "sea_level_pressure": 1023.9,
+ "station_pressure": 1023.5,
+ "time": 1770724800,
+ "uv": 0.0,
+ "wind_avg": 7.0,
+ "wind_direction": 280,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 15.0
+ },
+ {
+ "air_temperature": 12.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 12.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 10,
+ "local_hour": 8,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 89,
+ "sea_level_pressure": 1024.2,
+ "station_pressure": 1023.8,
+ "time": 1770728400,
+ "uv": 2.0,
+ "wind_avg": 7.0,
+ "wind_direction": 280,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 15.0
+ },
+ {
+ "air_temperature": 14.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 14.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 10,
+ "local_hour": 9,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 79,
+ "sea_level_pressure": 1024.5,
+ "station_pressure": 1024.1,
+ "time": 1770732000,
+ "uv": 2.0,
+ "wind_avg": 7.0,
+ "wind_direction": 280,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 15.0
+ },
+ {
+ "air_temperature": 15.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 15.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 10,
+ "local_hour": 10,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 71,
+ "sea_level_pressure": 1024.8,
+ "station_pressure": 1024.4,
+ "time": 1770735600,
+ "uv": 2.0,
+ "wind_avg": 7.0,
+ "wind_direction": 280,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 15.0
+ },
+ {
+ "air_temperature": 17.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 17.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 10,
+ "local_hour": 11,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 67,
+ "sea_level_pressure": 1024.1,
+ "station_pressure": 1023.7,
+ "time": 1770739200,
+ "uv": 4.0,
+ "wind_avg": 8.0,
+ "wind_direction": 270,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 14.0
+ },
+ {
+ "air_temperature": 18.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 18.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 10,
+ "local_hour": 12,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 63,
+ "sea_level_pressure": 1023.3,
+ "station_pressure": 1022.9,
+ "time": 1770742800,
+ "uv": 4.0,
+ "wind_avg": 8.0,
+ "wind_direction": 270,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 14.0
+ },
+ {
+ "air_temperature": 19.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 19.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 10,
+ "local_hour": 13,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 60,
+ "sea_level_pressure": 1022.5,
+ "station_pressure": 1022.1,
+ "time": 1770746400,
+ "uv": 4.0,
+ "wind_avg": 9.0,
+ "wind_direction": 270,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 14.0
+ },
+ {
+ "air_temperature": 19.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 19.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 10,
+ "local_hour": 14,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 61,
+ "sea_level_pressure": 1021.9,
+ "station_pressure": 1021.5,
+ "time": 1770750000,
+ "uv": 5.0,
+ "wind_avg": 9.0,
+ "wind_direction": 110,
+ "wind_direction_cardinal": "ESE",
+ "wind_gust": 14.0
+ },
+ {
+ "air_temperature": 20.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 20.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 10,
+ "local_hour": 15,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 59,
+ "sea_level_pressure": 1021.3,
+ "station_pressure": 1020.9,
+ "time": 1770753600,
+ "uv": 5.0,
+ "wind_avg": 10.0,
+ "wind_direction": 110,
+ "wind_direction_cardinal": "ESE",
+ "wind_gust": 15.0
+ },
+ {
+ "air_temperature": 20.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 20.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 10,
+ "local_hour": 16,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 59,
+ "sea_level_pressure": 1020.6,
+ "station_pressure": 1020.2,
+ "time": 1770757200,
+ "uv": 5.0,
+ "wind_avg": 10.0,
+ "wind_direction": 110,
+ "wind_direction_cardinal": "ESE",
+ "wind_gust": 15.0
+ },
+ {
+ "air_temperature": 19.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 19.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 10,
+ "local_hour": 17,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 68,
+ "sea_level_pressure": 1021.1,
+ "station_pressure": 1020.7,
+ "time": 1770760800,
+ "uv": 3.0,
+ "wind_avg": 9.0,
+ "wind_direction": 140,
+ "wind_direction_cardinal": "SE",
+ "wind_gust": 15.0
+ },
+ {
+ "air_temperature": 18.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 18.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 10,
+ "local_hour": 18,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 73,
+ "sea_level_pressure": 1021.5,
+ "station_pressure": 1021.1,
+ "time": 1770764400,
+ "uv": 3.0,
+ "wind_avg": 8.0,
+ "wind_direction": 140,
+ "wind_direction_cardinal": "SE",
+ "wind_gust": 14.0
+ },
+ {
+ "air_temperature": 17.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 17.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 10,
+ "local_hour": 19,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 77,
+ "sea_level_pressure": 1022.0,
+ "station_pressure": 1021.6,
+ "time": 1770768000,
+ "uv": 3.0,
+ "wind_avg": 7.0,
+ "wind_direction": 140,
+ "wind_direction_cardinal": "SE",
+ "wind_gust": 14.0
+ },
+ {
+ "air_temperature": 16.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 16.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 10,
+ "local_hour": 20,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 78,
+ "sea_level_pressure": 1022.2,
+ "station_pressure": 1021.8,
+ "time": 1770771600,
+ "uv": 0.0,
+ "wind_avg": 7.0,
+ "wind_direction": 200,
+ "wind_direction_cardinal": "SSW",
+ "wind_gust": 14.0
+ },
+ {
+ "air_temperature": 16.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 16.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 10,
+ "local_hour": 21,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 79,
+ "sea_level_pressure": 1022.4,
+ "station_pressure": 1022.0,
+ "time": 1770775200,
+ "uv": 0.0,
+ "wind_avg": 7.0,
+ "wind_direction": 200,
+ "wind_direction_cardinal": "SSW",
+ "wind_gust": 14.0
+ },
+ {
+ "air_temperature": 16.0,
+ "conditions": "Cloudy",
+ "feels_like": 16.0,
+ "icon": "cloudy",
+ "local_day": 10,
+ "local_hour": 22,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 80,
+ "sea_level_pressure": 1022.6,
+ "station_pressure": 1022.2,
+ "time": 1770778800,
+ "uv": 0.0,
+ "wind_avg": 7.0,
+ "wind_direction": 200,
+ "wind_direction_cardinal": "SSW",
+ "wind_gust": 15.0
+ },
+ {
+ "air_temperature": 16.0,
+ "conditions": "Cloudy",
+ "feels_like": 16.0,
+ "icon": "cloudy",
+ "local_day": 10,
+ "local_hour": 23,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 78,
+ "sea_level_pressure": 1022.4,
+ "station_pressure": 1022.0,
+ "time": 1770782400,
+ "uv": 0.0,
+ "wind_avg": 7.0,
+ "wind_direction": 250,
+ "wind_direction_cardinal": "WSW",
+ "wind_gust": 15.0
+ },
+ {
+ "air_temperature": 15.0,
+ "conditions": "Cloudy",
+ "feels_like": 15.0,
+ "icon": "cloudy",
+ "local_day": 11,
+ "local_hour": 0,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 81,
+ "sea_level_pressure": 1022.3,
+ "station_pressure": 1021.9,
+ "time": 1770786000,
+ "uv": 0.0,
+ "wind_avg": 7.0,
+ "wind_direction": 250,
+ "wind_direction_cardinal": "WSW",
+ "wind_gust": 15.0
+ },
+ {
+ "air_temperature": 15.0,
+ "conditions": "Cloudy",
+ "feels_like": 15.0,
+ "icon": "cloudy",
+ "local_day": 11,
+ "local_hour": 1,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 83,
+ "sea_level_pressure": 1022.1,
+ "station_pressure": 1021.7,
+ "time": 1770789600,
+ "uv": 0.0,
+ "wind_avg": 7.0,
+ "wind_direction": 250,
+ "wind_direction_cardinal": "WSW",
+ "wind_gust": 16.0
+ },
+ {
+ "air_temperature": 14.0,
+ "conditions": "Cloudy",
+ "feels_like": 14.0,
+ "icon": "cloudy",
+ "local_day": 11,
+ "local_hour": 2,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 85,
+ "sea_level_pressure": 1021.8,
+ "station_pressure": 1021.4,
+ "time": 1770793200,
+ "uv": 0.0,
+ "wind_avg": 7.0,
+ "wind_direction": 270,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 16.0
+ },
+ {
+ "air_temperature": 14.0,
+ "conditions": "Cloudy",
+ "feels_like": 14.0,
+ "icon": "cloudy",
+ "local_day": 11,
+ "local_hour": 3,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 87,
+ "sea_level_pressure": 1021.6,
+ "station_pressure": 1021.2,
+ "time": 1770796800,
+ "uv": 0.0,
+ "wind_avg": 7.0,
+ "wind_direction": 270,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 15.0
+ },
+ {
+ "air_temperature": 14.0,
+ "conditions": "Cloudy",
+ "feels_like": 14.0,
+ "icon": "cloudy",
+ "local_day": 11,
+ "local_hour": 4,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 89,
+ "sea_level_pressure": 1021.4,
+ "station_pressure": 1021.0,
+ "time": 1770800400,
+ "uv": 0.0,
+ "wind_avg": 7.0,
+ "wind_direction": 270,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 15.0
+ },
+ {
+ "air_temperature": 13.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 13.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 11,
+ "local_hour": 5,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 91,
+ "sea_level_pressure": 1021.4,
+ "station_pressure": 1021.0,
+ "time": 1770804000,
+ "uv": 0.0,
+ "wind_avg": 7.0,
+ "wind_direction": 250,
+ "wind_direction_cardinal": "WSW",
+ "wind_gust": 16.0
+ },
+ {
+ "air_temperature": 13.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 13.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 11,
+ "local_hour": 6,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 92,
+ "sea_level_pressure": 1021.5,
+ "station_pressure": 1021.1,
+ "time": 1770807600,
+ "uv": 0.0,
+ "wind_avg": 7.0,
+ "wind_direction": 250,
+ "wind_direction_cardinal": "WSW",
+ "wind_gust": 16.0
+ },
+ {
+ "air_temperature": 13.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 13.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 11,
+ "local_hour": 7,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 91,
+ "sea_level_pressure": 1021.5,
+ "station_pressure": 1021.1,
+ "time": 1770811200,
+ "uv": 0.0,
+ "wind_avg": 7.0,
+ "wind_direction": 250,
+ "wind_direction_cardinal": "WSW",
+ "wind_gust": 17.0
+ },
+ {
+ "air_temperature": 14.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 14.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 11,
+ "local_hour": 8,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 91,
+ "sea_level_pressure": 1021.7,
+ "station_pressure": 1021.3,
+ "time": 1770814800,
+ "uv": 2.0,
+ "wind_avg": 8.0,
+ "wind_direction": 260,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 17.0
+ },
+ {
+ "air_temperature": 16.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 16.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 11,
+ "local_hour": 9,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 83,
+ "sea_level_pressure": 1022.0,
+ "station_pressure": 1021.6,
+ "time": 1770818400,
+ "uv": 2.0,
+ "wind_avg": 8.0,
+ "wind_direction": 260,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 17.0
+ },
+ {
+ "air_temperature": 17.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 17.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 11,
+ "local_hour": 10,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 76,
+ "sea_level_pressure": 1022.2,
+ "station_pressure": 1021.8,
+ "time": 1770822000,
+ "uv": 2.0,
+ "wind_avg": 9.0,
+ "wind_direction": 260,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 17.0
+ },
+ {
+ "air_temperature": 18.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 18.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 11,
+ "local_hour": 11,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 73,
+ "sea_level_pressure": 1021.3,
+ "station_pressure": 1020.9,
+ "time": 1770825600,
+ "uv": 4.0,
+ "wind_avg": 10.0,
+ "wind_direction": 240,
+ "wind_direction_cardinal": "WSW",
+ "wind_gust": 18.0
+ },
+ {
+ "air_temperature": 20.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 20.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 11,
+ "local_hour": 12,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 68,
+ "sea_level_pressure": 1020.4,
+ "station_pressure": 1020.0,
+ "time": 1770829200,
+ "uv": 4.0,
+ "wind_avg": 10.0,
+ "wind_direction": 240,
+ "wind_direction_cardinal": "WSW",
+ "wind_gust": 18.0
+ },
+ {
+ "air_temperature": 20.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 20.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 11,
+ "local_hour": 13,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 65,
+ "sea_level_pressure": 1019.5,
+ "station_pressure": 1019.1,
+ "time": 1770832800,
+ "uv": 4.0,
+ "wind_avg": 12.0,
+ "wind_direction": 240,
+ "wind_direction_cardinal": "WSW",
+ "wind_gust": 19.0
+ },
+ {
+ "air_temperature": 21.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 21.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 11,
+ "local_hour": 14,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 66,
+ "sea_level_pressure": 1019.1,
+ "station_pressure": 1018.7,
+ "time": 1770836400,
+ "uv": 5.0,
+ "wind_avg": 12.0,
+ "wind_direction": 170,
+ "wind_direction_cardinal": "S",
+ "wind_gust": 19.0
+ },
+ {
+ "air_temperature": 21.0,
+ "conditions": "Clear",
+ "feels_like": 21.0,
+ "icon": "clear-day",
+ "local_day": 11,
+ "local_hour": 15,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 65,
+ "sea_level_pressure": 1018.6,
+ "station_pressure": 1018.2,
+ "time": 1770840000,
+ "uv": 5.0,
+ "wind_avg": 13.0,
+ "wind_direction": 170,
+ "wind_direction_cardinal": "S",
+ "wind_gust": 19.0
+ },
+ {
+ "air_temperature": 21.0,
+ "conditions": "Clear",
+ "feels_like": 21.0,
+ "icon": "clear-day",
+ "local_day": 11,
+ "local_hour": 16,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 66,
+ "sea_level_pressure": 1018.1,
+ "station_pressure": 1017.7,
+ "time": 1770843600,
+ "uv": 5.0,
+ "wind_avg": 13.0,
+ "wind_direction": 170,
+ "wind_direction_cardinal": "S",
+ "wind_gust": 19.0
+ },
+ {
+ "air_temperature": 20.0,
+ "conditions": "Clear",
+ "feels_like": 20.0,
+ "icon": "clear-day",
+ "local_day": 11,
+ "local_hour": 17,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 69,
+ "sea_level_pressure": 1018.4,
+ "station_pressure": 1018.0,
+ "time": 1770847200,
+ "uv": 3.0,
+ "wind_avg": 13.0,
+ "wind_direction": 170,
+ "wind_direction_cardinal": "S",
+ "wind_gust": 20.0
+ },
+ {
+ "air_temperature": 20.0,
+ "conditions": "Clear",
+ "feels_like": 20.0,
+ "icon": "clear-day",
+ "local_day": 11,
+ "local_hour": 18,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 72,
+ "sea_level_pressure": 1018.7,
+ "station_pressure": 1018.3,
+ "time": 1770850800,
+ "uv": 3.0,
+ "wind_avg": 12.0,
+ "wind_direction": 170,
+ "wind_direction_cardinal": "S",
+ "wind_gust": 20.0
+ },
+ {
+ "air_temperature": 19.0,
+ "conditions": "Clear",
+ "feels_like": 19.0,
+ "icon": "clear-night",
+ "local_day": 11,
+ "local_hour": 19,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 76,
+ "sea_level_pressure": 1019.0,
+ "station_pressure": 1018.6,
+ "time": 1770854400,
+ "uv": 3.0,
+ "wind_avg": 12.0,
+ "wind_direction": 170,
+ "wind_direction_cardinal": "S",
+ "wind_gust": 20.0
+ },
+ {
+ "air_temperature": 18.0,
+ "conditions": "Clear",
+ "feels_like": 18.0,
+ "icon": "clear-night",
+ "local_day": 11,
+ "local_hour": 20,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 77,
+ "sea_level_pressure": 1019.1,
+ "station_pressure": 1018.7,
+ "time": 1770858000,
+ "uv": 0.0,
+ "wind_avg": 12.0,
+ "wind_direction": 230,
+ "wind_direction_cardinal": "SW",
+ "wind_gust": 20.0
+ },
+ {
+ "air_temperature": 18.0,
+ "conditions": "Clear",
+ "feels_like": 18.0,
+ "icon": "clear-night",
+ "local_day": 11,
+ "local_hour": 21,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 80,
+ "sea_level_pressure": 1019.3,
+ "station_pressure": 1018.9,
+ "time": 1770861600,
+ "uv": 0.0,
+ "wind_avg": 12.0,
+ "wind_direction": 230,
+ "wind_direction_cardinal": "SW",
+ "wind_gust": 21.0
+ },
+ {
+ "air_temperature": 17.0,
+ "conditions": "Clear",
+ "feels_like": 17.0,
+ "icon": "clear-night",
+ "local_day": 11,
+ "local_hour": 22,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 83,
+ "sea_level_pressure": 1019.4,
+ "station_pressure": 1019.0,
+ "time": 1770865200,
+ "uv": 0.0,
+ "wind_avg": 12.0,
+ "wind_direction": 230,
+ "wind_direction_cardinal": "SW",
+ "wind_gust": 21.0
+ },
+ {
+ "air_temperature": 17.0,
+ "conditions": "Clear",
+ "feels_like": 17.0,
+ "icon": "clear-night",
+ "local_day": 11,
+ "local_hour": 23,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 83,
+ "sea_level_pressure": 1019.0,
+ "station_pressure": 1018.6,
+ "time": 1770868800,
+ "uv": 0.0,
+ "wind_avg": 12.0,
+ "wind_direction": 260,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 21.0
+ },
+ {
+ "air_temperature": 16.0,
+ "conditions": "Clear",
+ "feels_like": 16.0,
+ "icon": "clear-night",
+ "local_day": 12,
+ "local_hour": 0,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 85,
+ "sea_level_pressure": 1018.5,
+ "station_pressure": 1018.1,
+ "time": 1770872400,
+ "uv": 0.0,
+ "wind_avg": 12.0,
+ "wind_direction": 260,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 22.0
+ },
+ {
+ "air_temperature": 16.0,
+ "conditions": "Clear",
+ "feels_like": 16.0,
+ "icon": "clear-night",
+ "local_day": 12,
+ "local_hour": 1,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 87,
+ "sea_level_pressure": 1018.1,
+ "station_pressure": 1017.7,
+ "time": 1770876000,
+ "uv": 0.0,
+ "wind_avg": 12.0,
+ "wind_direction": 260,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 22.0
+ },
+ {
+ "air_temperature": 16.0,
+ "conditions": "Clear",
+ "feels_like": 16.0,
+ "icon": "clear-night",
+ "local_day": 12,
+ "local_hour": 2,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 88,
+ "sea_level_pressure": 1017.9,
+ "station_pressure": 1017.5,
+ "time": 1770879600,
+ "uv": 0.0,
+ "wind_avg": 12.0,
+ "wind_direction": 270,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 22.0
+ },
+ {
+ "air_temperature": 15.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 15.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 12,
+ "local_hour": 3,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 90,
+ "sea_level_pressure": 1017.7,
+ "station_pressure": 1017.3,
+ "time": 1770883200,
+ "uv": 0.0,
+ "wind_avg": 13.0,
+ "wind_direction": 270,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 22.0
+ },
+ {
+ "air_temperature": 15.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 15.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 12,
+ "local_hour": 4,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 92,
+ "sea_level_pressure": 1017.5,
+ "station_pressure": 1017.1,
+ "time": 1770886800,
+ "uv": 0.0,
+ "wind_avg": 13.0,
+ "wind_direction": 270,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 23.0
+ },
+ {
+ "air_temperature": 14.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 14.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 12,
+ "local_hour": 5,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 97,
+ "sea_level_pressure": 1017.9,
+ "station_pressure": 1017.5,
+ "time": 1770890400,
+ "uv": 0.0,
+ "wind_avg": 13.0,
+ "wind_direction": 280,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 23.0
+ },
+ {
+ "air_temperature": 14.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 14.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 12,
+ "local_hour": 6,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 99,
+ "sea_level_pressure": 1018.2,
+ "station_pressure": 1017.8,
+ "time": 1770894000,
+ "uv": 0.0,
+ "wind_avg": 13.0,
+ "wind_direction": 280,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 22.0
+ },
+ {
+ "air_temperature": 14.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 14.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 12,
+ "local_hour": 7,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 98,
+ "sea_level_pressure": 1018.5,
+ "station_pressure": 1018.1,
+ "time": 1770897600,
+ "uv": 0.0,
+ "wind_avg": 13.0,
+ "wind_direction": 280,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 22.0
+ },
+ {
+ "air_temperature": 15.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 15.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 12,
+ "local_hour": 8,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 100,
+ "sea_level_pressure": 1018.6,
+ "station_pressure": 1018.2,
+ "time": 1770901200,
+ "uv": 2.0,
+ "wind_avg": 13.0,
+ "wind_direction": 290,
+ "wind_direction_cardinal": "WNW",
+ "wind_gust": 22.0
+ },
+ {
+ "air_temperature": 16.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 16.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 12,
+ "local_hour": 9,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 93,
+ "sea_level_pressure": 1018.7,
+ "station_pressure": 1018.3,
+ "time": 1770904800,
+ "uv": 2.0,
+ "wind_avg": 14.0,
+ "wind_direction": 290,
+ "wind_direction_cardinal": "WNW",
+ "wind_gust": 22.0
+ },
+ {
+ "air_temperature": 18.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 18.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 12,
+ "local_hour": 10,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 85,
+ "sea_level_pressure": 1018.8,
+ "station_pressure": 1018.4,
+ "time": 1770908400,
+ "uv": 2.0,
+ "wind_avg": 14.0,
+ "wind_direction": 290,
+ "wind_direction_cardinal": "WNW",
+ "wind_gust": 22.0
+ },
+ {
+ "air_temperature": 19.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 19.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 12,
+ "local_hour": 11,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 81,
+ "sea_level_pressure": 1018.1,
+ "station_pressure": 1017.7,
+ "time": 1770912000,
+ "uv": 4.0,
+ "wind_avg": 15.0,
+ "wind_direction": 310,
+ "wind_direction_cardinal": "NW",
+ "wind_gust": 22.0
+ },
+ {
+ "air_temperature": 20.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 20.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 12,
+ "local_hour": 12,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 77,
+ "sea_level_pressure": 1017.5,
+ "station_pressure": 1017.1,
+ "time": 1770915600,
+ "uv": 4.0,
+ "wind_avg": 15.0,
+ "wind_direction": 310,
+ "wind_direction_cardinal": "NW",
+ "wind_gust": 22.0
+ },
+ {
+ "air_temperature": 20.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 20.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 12,
+ "local_hour": 13,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 75,
+ "sea_level_pressure": 1016.8,
+ "station_pressure": 1016.4,
+ "time": 1770919200,
+ "uv": 4.0,
+ "wind_avg": 16.0,
+ "wind_direction": 310,
+ "wind_direction_cardinal": "NW",
+ "wind_gust": 22.0
+ },
+ {
+ "air_temperature": 20.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 20.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 12,
+ "local_hour": 14,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 73,
+ "sea_level_pressure": 1016.4,
+ "station_pressure": 1016.0,
+ "time": 1770922800,
+ "uv": 1.0,
+ "wind_avg": 16.0,
+ "wind_direction": 350,
+ "wind_direction_cardinal": "N",
+ "wind_gust": 22.0
+ },
+ {
+ "air_temperature": 20.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 20.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 12,
+ "local_hour": 15,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 73,
+ "sea_level_pressure": 1016.1,
+ "station_pressure": 1015.7,
+ "time": 1770926400,
+ "uv": 1.0,
+ "wind_avg": 15.0,
+ "wind_direction": 350,
+ "wind_direction_cardinal": "N",
+ "wind_gust": 22.0
+ },
+ {
+ "air_temperature": 20.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 20.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 12,
+ "local_hour": 16,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 75,
+ "sea_level_pressure": 1015.7,
+ "station_pressure": 1015.3,
+ "time": 1770930000,
+ "uv": 1.0,
+ "wind_avg": 15.0,
+ "wind_direction": 350,
+ "wind_direction_cardinal": "N",
+ "wind_gust": 22.0
+ },
+ {
+ "air_temperature": 19.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 19.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 12,
+ "local_hour": 17,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 77,
+ "sea_level_pressure": 1016.2,
+ "station_pressure": 1015.8,
+ "time": 1770933600,
+ "uv": 1.0,
+ "wind_avg": 14.0,
+ "wind_direction": 180,
+ "wind_direction_cardinal": "S",
+ "wind_gust": 21.0
+ },
+ {
+ "air_temperature": 19.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 19.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 12,
+ "local_hour": 18,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 79,
+ "sea_level_pressure": 1016.7,
+ "station_pressure": 1016.3,
+ "time": 1770937200,
+ "uv": 1.0,
+ "wind_avg": 13.0,
+ "wind_direction": 180,
+ "wind_direction_cardinal": "S",
+ "wind_gust": 21.0
+ },
+ {
+ "air_temperature": 18.0,
+ "conditions": "Clear",
+ "feels_like": 18.0,
+ "icon": "clear-night",
+ "local_day": 12,
+ "local_hour": 19,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 82,
+ "sea_level_pressure": 1017.2,
+ "station_pressure": 1016.8,
+ "time": 1770940800,
+ "uv": 1.0,
+ "wind_avg": 12.0,
+ "wind_direction": 180,
+ "wind_direction_cardinal": "S",
+ "wind_gust": 20.0
+ },
+ {
+ "air_temperature": 18.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 18.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 12,
+ "local_hour": 20,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 81,
+ "sea_level_pressure": 1017.4,
+ "station_pressure": 1017.0,
+ "time": 1770944400,
+ "uv": 0.0,
+ "wind_avg": 12.0,
+ "wind_direction": 260,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 21.0
+ },
+ {
+ "air_temperature": 17.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 17.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 12,
+ "local_hour": 21,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 84,
+ "sea_level_pressure": 1017.6,
+ "station_pressure": 1017.2,
+ "time": 1770948000,
+ "uv": 0.0,
+ "wind_avg": 12.0,
+ "wind_direction": 260,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 21.0
+ },
+ {
+ "air_temperature": 17.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 17.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 12,
+ "local_hour": 22,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 86,
+ "sea_level_pressure": 1017.8,
+ "station_pressure": 1017.4,
+ "time": 1770951600,
+ "uv": 0.0,
+ "wind_avg": 12.0,
+ "wind_direction": 260,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 21.0
+ },
+ {
+ "air_temperature": 16.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 16.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 12,
+ "local_hour": 23,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 86,
+ "sea_level_pressure": 1017.6,
+ "station_pressure": 1017.2,
+ "time": 1770955200,
+ "uv": 0.0,
+ "wind_avg": 12.0,
+ "wind_direction": 280,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 21.0
+ },
+ {
+ "air_temperature": 16.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 16.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 13,
+ "local_hour": 0,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 88,
+ "sea_level_pressure": 1017.5,
+ "station_pressure": 1017.1,
+ "time": 1770958800,
+ "uv": 0.0,
+ "wind_avg": 12.0,
+ "wind_direction": 280,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 22.0
+ },
+ {
+ "air_temperature": 16.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 16.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 13,
+ "local_hour": 1,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 90,
+ "sea_level_pressure": 1017.3,
+ "station_pressure": 1016.9,
+ "time": 1770962400,
+ "uv": 0.0,
+ "wind_avg": 12.0,
+ "wind_direction": 280,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 22.0
+ },
+ {
+ "air_temperature": 15.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 15.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 13,
+ "local_hour": 2,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 89,
+ "sea_level_pressure": 1017.2,
+ "station_pressure": 1016.8,
+ "time": 1770966000,
+ "uv": 0.0,
+ "wind_avg": 12.0,
+ "wind_direction": 300,
+ "wind_direction_cardinal": "WNW",
+ "wind_gust": 23.0
+ },
+ {
+ "air_temperature": 15.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 15.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 13,
+ "local_hour": 3,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 90,
+ "sea_level_pressure": 1017.1,
+ "station_pressure": 1016.7,
+ "time": 1770969600,
+ "uv": 0.0,
+ "wind_avg": 13.0,
+ "wind_direction": 300,
+ "wind_direction_cardinal": "WNW",
+ "wind_gust": 23.0
+ },
+ {
+ "air_temperature": 15.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 15.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 13,
+ "local_hour": 4,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 91,
+ "sea_level_pressure": 1017.0,
+ "station_pressure": 1016.6,
+ "time": 1770973200,
+ "uv": 0.0,
+ "wind_avg": 13.0,
+ "wind_direction": 300,
+ "wind_direction_cardinal": "WNW",
+ "wind_gust": 23.0
+ },
+ {
+ "air_temperature": 15.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 15.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 13,
+ "local_hour": 5,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 91,
+ "sea_level_pressure": 1017.5,
+ "station_pressure": 1017.1,
+ "time": 1770976800,
+ "uv": 0.0,
+ "wind_avg": 13.0,
+ "wind_direction": 310,
+ "wind_direction_cardinal": "NW",
+ "wind_gust": 23.0
+ },
+ {
+ "air_temperature": 14.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 14.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 13,
+ "local_hour": 6,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 94,
+ "sea_level_pressure": 1017.9,
+ "station_pressure": 1017.5,
+ "time": 1770980400,
+ "uv": 0.0,
+ "wind_avg": 13.0,
+ "wind_direction": 310,
+ "wind_direction_cardinal": "NW",
+ "wind_gust": 24.0
+ },
+ {
+ "air_temperature": 14.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 14.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 13,
+ "local_hour": 7,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 93,
+ "sea_level_pressure": 1018.3,
+ "station_pressure": 1017.9,
+ "time": 1770984000,
+ "uv": 0.0,
+ "wind_avg": 13.0,
+ "wind_direction": 310,
+ "wind_direction_cardinal": "NW",
+ "wind_gust": 24.0
+ },
+ {
+ "air_temperature": 15.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 15.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 13,
+ "local_hour": 8,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 94,
+ "sea_level_pressure": 1018.6,
+ "station_pressure": 1018.2,
+ "time": 1770987600,
+ "uv": 2.0,
+ "wind_avg": 14.0,
+ "wind_direction": 340,
+ "wind_direction_cardinal": "NNW",
+ "wind_gust": 24.0
+ },
+ {
+ "air_temperature": 17.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 17.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 13,
+ "local_hour": 9,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 86,
+ "sea_level_pressure": 1019.0,
+ "station_pressure": 1018.6,
+ "time": 1770991200,
+ "uv": 2.0,
+ "wind_avg": 15.0,
+ "wind_direction": 340,
+ "wind_direction_cardinal": "NNW",
+ "wind_gust": 24.0
+ },
+ {
+ "air_temperature": 18.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 18.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 13,
+ "local_hour": 10,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 79,
+ "sea_level_pressure": 1019.4,
+ "station_pressure": 1019.0,
+ "time": 1770994800,
+ "uv": 2.0,
+ "wind_avg": 16.0,
+ "wind_direction": 340,
+ "wind_direction_cardinal": "NNW",
+ "wind_gust": 24.0
+ },
+ {
+ "air_temperature": 19.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 19.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 13,
+ "local_hour": 11,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 75,
+ "sea_level_pressure": 1018.9,
+ "station_pressure": 1018.5,
+ "time": 1770998400,
+ "uv": 4.0,
+ "wind_avg": 17.0,
+ "wind_direction": 50,
+ "wind_direction_cardinal": "NE",
+ "wind_gust": 25.0
+ },
+ {
+ "air_temperature": 19.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 19.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 13,
+ "local_hour": 12,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 72,
+ "sea_level_pressure": 1018.5,
+ "station_pressure": 1018.1,
+ "time": 1771002000,
+ "uv": 4.0,
+ "wind_avg": 17.0,
+ "wind_direction": 50,
+ "wind_direction_cardinal": "NE",
+ "wind_gust": 26.0
+ },
+ {
+ "air_temperature": 20.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 20.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 13,
+ "local_hour": 13,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 71,
+ "sea_level_pressure": 1018.1,
+ "station_pressure": 1017.7,
+ "time": 1771005600,
+ "uv": 4.0,
+ "wind_avg": 18.0,
+ "wind_direction": 50,
+ "wind_direction_cardinal": "NE",
+ "wind_gust": 26.0
+ },
+ {
+ "air_temperature": 20.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 20.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 13,
+ "local_hour": 14,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 71,
+ "sea_level_pressure": 1017.6,
+ "station_pressure": 1017.2,
+ "time": 1771009200,
+ "uv": 5.0,
+ "wind_avg": 18.0,
+ "wind_direction": 90,
+ "wind_direction_cardinal": "E",
+ "wind_gust": 26.0
+ },
+ {
+ "air_temperature": 20.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 20.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 13,
+ "local_hour": 15,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 71,
+ "sea_level_pressure": 1017.1,
+ "station_pressure": 1016.7,
+ "time": 1771012800,
+ "uv": 5.0,
+ "wind_avg": 18.0,
+ "wind_direction": 90,
+ "wind_direction_cardinal": "E",
+ "wind_gust": 27.0
+ },
+ {
+ "air_temperature": 19.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 19.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 13,
+ "local_hour": 16,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 5,
+ "precip_type": "rain",
+ "relative_humidity": 73,
+ "sea_level_pressure": 1016.6,
+ "station_pressure": 1016.2,
+ "time": 1771016400,
+ "uv": 5.0,
+ "wind_avg": 19.0,
+ "wind_direction": 90,
+ "wind_direction_cardinal": "E",
+ "wind_gust": 27.0
+ },
+ {
+ "air_temperature": 19.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 19.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 13,
+ "local_hour": 17,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 5,
+ "precip_type": "rain",
+ "relative_humidity": 75,
+ "sea_level_pressure": 1016.9,
+ "station_pressure": 1016.5,
+ "time": 1771020000,
+ "uv": 3.0,
+ "wind_avg": 18.0,
+ "wind_direction": 110,
+ "wind_direction_cardinal": "ESE",
+ "wind_gust": 26.0
+ },
+ {
+ "air_temperature": 18.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 18.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 13,
+ "local_hour": 18,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 5,
+ "precip_type": "rain",
+ "relative_humidity": 78,
+ "sea_level_pressure": 1017.2,
+ "station_pressure": 1016.8,
+ "time": 1771023600,
+ "uv": 3.0,
+ "wind_avg": 17.0,
+ "wind_direction": 110,
+ "wind_direction_cardinal": "ESE",
+ "wind_gust": 26.0
+ },
+ {
+ "air_temperature": 18.0,
+ "conditions": "Clear",
+ "feels_like": 18.0,
+ "icon": "clear-night",
+ "local_day": 13,
+ "local_hour": 19,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 5,
+ "precip_type": "rain",
+ "relative_humidity": 80,
+ "sea_level_pressure": 1017.5,
+ "station_pressure": 1017.1,
+ "time": 1771027200,
+ "uv": 3.0,
+ "wind_avg": 16.0,
+ "wind_direction": 110,
+ "wind_direction_cardinal": "ESE",
+ "wind_gust": 25.0
+ },
+ {
+ "air_temperature": 17.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 17.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 13,
+ "local_hour": 20,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 5,
+ "precip_type": "rain",
+ "relative_humidity": 81,
+ "sea_level_pressure": 1017.6,
+ "station_pressure": 1017.2,
+ "time": 1771030800,
+ "uv": 0.0,
+ "wind_avg": 16.0,
+ "wind_direction": 100,
+ "wind_direction_cardinal": "E",
+ "wind_gust": 26.0
+ },
+ {
+ "air_temperature": 17.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 17.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 13,
+ "local_hour": 21,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 5,
+ "precip_type": "rain",
+ "relative_humidity": 83,
+ "sea_level_pressure": 1017.6,
+ "station_pressure": 1017.2,
+ "time": 1771034400,
+ "uv": 0.0,
+ "wind_avg": 16.0,
+ "wind_direction": 100,
+ "wind_direction_cardinal": "E",
+ "wind_gust": 26.0
+ },
+ {
+ "air_temperature": 17.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 17.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 13,
+ "local_hour": 22,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 5,
+ "precip_type": "rain",
+ "relative_humidity": 85,
+ "sea_level_pressure": 1017.7,
+ "station_pressure": 1017.3,
+ "time": 1771038000,
+ "uv": 0.0,
+ "wind_avg": 16.0,
+ "wind_direction": 100,
+ "wind_direction_cardinal": "E",
+ "wind_gust": 27.0
+ },
+ {
+ "air_temperature": 16.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 16.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 13,
+ "local_hour": 23,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 5,
+ "precip_type": "rain",
+ "relative_humidity": 84,
+ "sea_level_pressure": 1017.2,
+ "station_pressure": 1016.8,
+ "time": 1771041600,
+ "uv": 0.0,
+ "wind_avg": 17.0,
+ "wind_direction": 340,
+ "wind_direction_cardinal": "NNW",
+ "wind_gust": 27.0
+ },
+ {
+ "air_temperature": 16.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 16.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 14,
+ "local_hour": 0,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 5,
+ "precip_type": "rain",
+ "relative_humidity": 86,
+ "sea_level_pressure": 1016.8,
+ "station_pressure": 1016.4,
+ "time": 1771045200,
+ "uv": 0.0,
+ "wind_avg": 17.0,
+ "wind_direction": 340,
+ "wind_direction_cardinal": "NNW",
+ "wind_gust": 27.0
+ },
+ {
+ "air_temperature": 16.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 16.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 14,
+ "local_hour": 1,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 5,
+ "precip_type": "rain",
+ "relative_humidity": 88,
+ "sea_level_pressure": 1016.4,
+ "station_pressure": 1016.0,
+ "time": 1771048800,
+ "uv": 0.0,
+ "wind_avg": 18.0,
+ "wind_direction": 340,
+ "wind_direction_cardinal": "NNW",
+ "wind_gust": 28.0
+ },
+ {
+ "air_temperature": 15.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 15.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 14,
+ "local_hour": 2,
+ "precip": 0.09,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 87,
+ "sea_level_pressure": 1015.9,
+ "station_pressure": 1015.5,
+ "time": 1771052400,
+ "uv": 0.0,
+ "wind_avg": 18.0,
+ "wind_direction": 320,
+ "wind_direction_cardinal": "NW",
+ "wind_gust": 28.0
+ },
+ {
+ "air_temperature": 15.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 15.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 14,
+ "local_hour": 3,
+ "precip": 0.17,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 90,
+ "sea_level_pressure": 1015.5,
+ "station_pressure": 1015.1,
+ "time": 1771056000,
+ "uv": 0.0,
+ "wind_avg": 18.0,
+ "wind_direction": 320,
+ "wind_direction_cardinal": "NW",
+ "wind_gust": 28.0
+ },
+ {
+ "air_temperature": 15.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 15.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 14,
+ "local_hour": 4,
+ "precip": 0.25,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 91,
+ "sea_level_pressure": 1015.0,
+ "station_pressure": 1014.6,
+ "time": 1771059600,
+ "uv": 0.0,
+ "wind_avg": 18.0,
+ "wind_direction": 320,
+ "wind_direction_cardinal": "NW",
+ "wind_gust": 29.0
+ },
+ {
+ "air_temperature": 14.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 14.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 14,
+ "local_hour": 5,
+ "precip": 0.17,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 92,
+ "sea_level_pressure": 1015.4,
+ "station_pressure": 1015.0,
+ "time": 1771063200,
+ "uv": 0.0,
+ "wind_avg": 18.0,
+ "wind_direction": 310,
+ "wind_direction_cardinal": "NW",
+ "wind_gust": 29.0
+ },
+ {
+ "air_temperature": 14.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 14.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 14,
+ "local_hour": 6,
+ "precip": 0.09,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 95,
+ "sea_level_pressure": 1015.8,
+ "station_pressure": 1015.4,
+ "time": 1771066800,
+ "uv": 0.0,
+ "wind_avg": 18.0,
+ "wind_direction": 310,
+ "wind_direction_cardinal": "NW",
+ "wind_gust": 30.0
+ },
+ {
+ "air_temperature": 14.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 14.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 14,
+ "local_hour": 7,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 94,
+ "sea_level_pressure": 1016.2,
+ "station_pressure": 1015.8,
+ "time": 1771070400,
+ "uv": 0.0,
+ "wind_avg": 19.0,
+ "wind_direction": 310,
+ "wind_direction_cardinal": "NW",
+ "wind_gust": 30.0
+ },
+ {
+ "air_temperature": 15.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 15.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 14,
+ "local_hour": 8,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 0,
+ "precip_type": "rain",
+ "relative_humidity": 90,
+ "sea_level_pressure": 1016.4,
+ "station_pressure": 1016.0,
+ "time": 1771074000,
+ "uv": 2.0,
+ "wind_avg": 19.0,
+ "wind_direction": 320,
+ "wind_direction_cardinal": "NW",
+ "wind_gust": 30.0
+ },
+ {
+ "air_temperature": 16.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 16.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 14,
+ "local_hour": 9,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 5,
+ "precip_type": "rain",
+ "relative_humidity": 83,
+ "sea_level_pressure": 1016.6,
+ "station_pressure": 1016.2,
+ "time": 1771077600,
+ "uv": 2.0,
+ "wind_avg": 20.0,
+ "wind_direction": 320,
+ "wind_direction_cardinal": "NW",
+ "wind_gust": 31.0
+ },
+ {
+ "air_temperature": 17.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 17.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 14,
+ "local_hour": 10,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 5,
+ "precip_type": "rain",
+ "relative_humidity": 77,
+ "sea_level_pressure": 1016.8,
+ "station_pressure": 1016.4,
+ "time": 1771081200,
+ "uv": 2.0,
+ "wind_avg": 21.0,
+ "wind_direction": 320,
+ "wind_direction_cardinal": "NW",
+ "wind_gust": 31.0
+ },
+ {
+ "air_temperature": 18.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 18.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 14,
+ "local_hour": 11,
+ "precip": 0.09,
+ "precip_icon": "chance-rain",
+ "precip_probability": 5,
+ "precip_type": "rain",
+ "relative_humidity": 73,
+ "sea_level_pressure": 1016.1,
+ "station_pressure": 1015.7,
+ "time": 1771084800,
+ "uv": 4.0,
+ "wind_avg": 21.0,
+ "wind_direction": 210,
+ "wind_direction_cardinal": "SSW",
+ "wind_gust": 32.0
+ },
+ {
+ "air_temperature": 18.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 18.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 14,
+ "local_hour": 12,
+ "precip": 0.17,
+ "precip_icon": "chance-rain",
+ "precip_probability": 5,
+ "precip_type": "rain",
+ "relative_humidity": 71,
+ "sea_level_pressure": 1015.4,
+ "station_pressure": 1015.0,
+ "time": 1771088400,
+ "uv": 4.0,
+ "wind_avg": 22.0,
+ "wind_direction": 210,
+ "wind_direction_cardinal": "SSW",
+ "wind_gust": 32.0
+ },
+ {
+ "air_temperature": 19.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 19.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 14,
+ "local_hour": 13,
+ "precip": 0.25,
+ "precip_icon": "chance-rain",
+ "precip_probability": 10,
+ "precip_type": "rain",
+ "relative_humidity": 69,
+ "sea_level_pressure": 1014.7,
+ "station_pressure": 1014.3,
+ "time": 1771092000,
+ "uv": 4.0,
+ "wind_avg": 22.0,
+ "wind_direction": 210,
+ "wind_direction_cardinal": "SSW",
+ "wind_gust": 33.0
+ },
+ {
+ "air_temperature": 19.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 19.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 14,
+ "local_hour": 14,
+ "precip": 0.25,
+ "precip_icon": "chance-rain",
+ "precip_probability": 10,
+ "precip_type": "rain",
+ "relative_humidity": 67,
+ "sea_level_pressure": 1014.4,
+ "station_pressure": 1014.0,
+ "time": 1771095600,
+ "uv": 3.0,
+ "wind_avg": 22.0,
+ "wind_direction": 180,
+ "wind_direction_cardinal": "S",
+ "wind_gust": 33.0
+ },
+ {
+ "air_temperature": 19.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 19.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 14,
+ "local_hour": 15,
+ "precip": 0.25,
+ "precip_icon": "chance-rain",
+ "precip_probability": 10,
+ "precip_type": "rain",
+ "relative_humidity": 67,
+ "sea_level_pressure": 1014.2,
+ "station_pressure": 1013.8,
+ "time": 1771099200,
+ "uv": 3.0,
+ "wind_avg": 22.0,
+ "wind_direction": 180,
+ "wind_direction_cardinal": "S",
+ "wind_gust": 32.0
+ },
+ {
+ "air_temperature": 19.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 19.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 14,
+ "local_hour": 16,
+ "precip": 0.25,
+ "precip_icon": "chance-rain",
+ "precip_probability": 10,
+ "precip_type": "rain",
+ "relative_humidity": 68,
+ "sea_level_pressure": 1013.9,
+ "station_pressure": 1013.5,
+ "time": 1771102800,
+ "uv": 3.0,
+ "wind_avg": 21.0,
+ "wind_direction": 180,
+ "wind_direction_cardinal": "S",
+ "wind_gust": 32.0
+ },
+ {
+ "air_temperature": 18.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 18.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 14,
+ "local_hour": 17,
+ "precip": 0.25,
+ "precip_icon": "chance-rain",
+ "precip_probability": 10,
+ "precip_type": "rain",
+ "relative_humidity": 69,
+ "sea_level_pressure": 1013.7,
+ "station_pressure": 1013.3,
+ "time": 1771106400,
+ "uv": 3.0,
+ "wind_avg": 21.0,
+ "wind_direction": 180,
+ "wind_direction_cardinal": "S",
+ "wind_gust": 32.0
+ },
+ {
+ "air_temperature": 18.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 18.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 14,
+ "local_hour": 18,
+ "precip": 0.25,
+ "precip_icon": "chance-rain",
+ "precip_probability": 10,
+ "precip_type": "rain",
+ "relative_humidity": 71,
+ "sea_level_pressure": 1013.4,
+ "station_pressure": 1013.0,
+ "time": 1771110000,
+ "uv": 3.0,
+ "wind_avg": 21.0,
+ "wind_direction": 180,
+ "wind_direction_cardinal": "S",
+ "wind_gust": 32.0
+ },
+ {
+ "air_temperature": 18.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 18.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 14,
+ "local_hour": 19,
+ "precip": 0.25,
+ "precip_icon": "chance-rain",
+ "precip_probability": 15,
+ "precip_type": "rain",
+ "relative_humidity": 73,
+ "sea_level_pressure": 1013.2,
+ "station_pressure": 1012.8,
+ "time": 1771113600,
+ "uv": 3.0,
+ "wind_avg": 21.0,
+ "wind_direction": 180,
+ "wind_direction_cardinal": "S",
+ "wind_gust": 32.0
+ },
+ {
+ "air_temperature": 17.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 17.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 14,
+ "local_hour": 20,
+ "precip": 0.21,
+ "precip_icon": "chance-rain",
+ "precip_probability": 10,
+ "precip_type": "rain",
+ "relative_humidity": 72,
+ "sea_level_pressure": 1013.3,
+ "station_pressure": 1012.9,
+ "time": 1771117200,
+ "uv": 0.0,
+ "wind_avg": 21.0,
+ "wind_direction": 230,
+ "wind_direction_cardinal": "SW",
+ "wind_gust": 32.0
+ },
+ {
+ "air_temperature": 17.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 17.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 14,
+ "local_hour": 21,
+ "precip": 0.17,
+ "precip_icon": "chance-rain",
+ "precip_probability": 10,
+ "precip_type": "rain",
+ "relative_humidity": 73,
+ "sea_level_pressure": 1013.4,
+ "station_pressure": 1013.0,
+ "time": 1771120800,
+ "uv": 0.0,
+ "wind_avg": 20.0,
+ "wind_direction": 230,
+ "wind_direction_cardinal": "SW",
+ "wind_gust": 32.0
+ },
+ {
+ "air_temperature": 16.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 16.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 14,
+ "local_hour": 22,
+ "precip": 0.13,
+ "precip_icon": "chance-rain",
+ "precip_probability": 10,
+ "precip_type": "rain",
+ "relative_humidity": 75,
+ "sea_level_pressure": 1013.6,
+ "station_pressure": 1013.2,
+ "time": 1771124400,
+ "uv": 0.0,
+ "wind_avg": 20.0,
+ "wind_direction": 230,
+ "wind_direction_cardinal": "SW",
+ "wind_gust": 32.0
+ },
+ {
+ "air_temperature": 16.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 16.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 14,
+ "local_hour": 23,
+ "precip": 0.09,
+ "precip_icon": "chance-rain",
+ "precip_probability": 10,
+ "precip_type": "rain",
+ "relative_humidity": 78,
+ "sea_level_pressure": 1013.7,
+ "station_pressure": 1013.3,
+ "time": 1771128000,
+ "uv": 0.0,
+ "wind_avg": 20.0,
+ "wind_direction": 230,
+ "wind_direction_cardinal": "SW",
+ "wind_gust": 31.0
+ },
+ {
+ "air_temperature": 16.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 16.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 15,
+ "local_hour": 0,
+ "precip": 0.04,
+ "precip_icon": "chance-rain",
+ "precip_probability": 10,
+ "precip_type": "rain",
+ "relative_humidity": 80,
+ "sea_level_pressure": 1013.8,
+ "station_pressure": 1013.4,
+ "time": 1771131600,
+ "uv": 0.0,
+ "wind_avg": 19.0,
+ "wind_direction": 230,
+ "wind_direction_cardinal": "SW",
+ "wind_gust": 31.0
+ },
+ {
+ "air_temperature": 15.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 15.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 15,
+ "local_hour": 1,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 10,
+ "precip_type": "rain",
+ "relative_humidity": 82,
+ "sea_level_pressure": 1014.0,
+ "station_pressure": 1013.6,
+ "time": 1771135200,
+ "uv": 0.0,
+ "wind_avg": 19.0,
+ "wind_direction": 230,
+ "wind_direction_cardinal": "SW",
+ "wind_gust": 31.0
+ },
+ {
+ "air_temperature": 15.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 15.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 15,
+ "local_hour": 2,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 10,
+ "precip_type": "rain",
+ "relative_humidity": 86,
+ "sea_level_pressure": 1014.1,
+ "station_pressure": 1013.7,
+ "time": 1771138800,
+ "uv": 0.0,
+ "wind_avg": 19.0,
+ "wind_direction": 230,
+ "wind_direction_cardinal": "SW",
+ "wind_gust": 31.0
+ },
+ {
+ "air_temperature": 14.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 14.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 15,
+ "local_hour": 3,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 10,
+ "precip_type": "rain",
+ "relative_humidity": 88,
+ "sea_level_pressure": 1014.2,
+ "station_pressure": 1013.8,
+ "time": 1771142400,
+ "uv": 0.0,
+ "wind_avg": 19.0,
+ "wind_direction": 230,
+ "wind_direction_cardinal": "SW",
+ "wind_gust": 31.0
+ },
+ {
+ "air_temperature": 14.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 14.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 15,
+ "local_hour": 4,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 10,
+ "precip_type": "rain",
+ "relative_humidity": 91,
+ "sea_level_pressure": 1014.3,
+ "station_pressure": 1013.9,
+ "time": 1771146000,
+ "uv": 0.0,
+ "wind_avg": 19.0,
+ "wind_direction": 230,
+ "wind_direction_cardinal": "SW",
+ "wind_gust": 31.0
+ },
+ {
+ "air_temperature": 14.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 14.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 15,
+ "local_hour": 5,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 10,
+ "precip_type": "rain",
+ "relative_humidity": 92,
+ "sea_level_pressure": 1014.4,
+ "station_pressure": 1014.0,
+ "time": 1771149600,
+ "uv": 0.0,
+ "wind_avg": 19.0,
+ "wind_direction": 230,
+ "wind_direction_cardinal": "SW",
+ "wind_gust": 31.0
+ },
+ {
+ "air_temperature": 14.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 14.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 15,
+ "local_hour": 6,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 10,
+ "precip_type": "rain",
+ "relative_humidity": 92,
+ "sea_level_pressure": 1014.5,
+ "station_pressure": 1014.1,
+ "time": 1771153200,
+ "uv": 0.0,
+ "wind_avg": 19.0,
+ "wind_direction": 230,
+ "wind_direction_cardinal": "SW",
+ "wind_gust": 31.0
+ },
+ {
+ "air_temperature": 14.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 14.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 15,
+ "local_hour": 7,
+ "precip": 0,
+ "precip_icon": "chance-rain",
+ "precip_probability": 10,
+ "precip_type": "rain",
+ "relative_humidity": 90,
+ "sea_level_pressure": 1014.6,
+ "station_pressure": 1014.2,
+ "time": 1771156800,
+ "uv": 0.0,
+ "wind_avg": 19.0,
+ "wind_direction": 230,
+ "wind_direction_cardinal": "SW",
+ "wind_gust": 31.0
+ },
+ {
+ "air_temperature": 15.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 15.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 15,
+ "local_hour": 8,
+ "precip": 0.04,
+ "precip_icon": "chance-rain",
+ "precip_probability": 10,
+ "precip_type": "rain",
+ "relative_humidity": 93,
+ "sea_level_pressure": 1014.4,
+ "station_pressure": 1014.0,
+ "time": 1771160400,
+ "uv": 4.0,
+ "wind_avg": 19.0,
+ "wind_direction": 250,
+ "wind_direction_cardinal": "WSW",
+ "wind_gust": 31.0
+ },
+ {
+ "air_temperature": 15.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 15.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 15,
+ "local_hour": 9,
+ "precip": 0.09,
+ "precip_icon": "chance-rain",
+ "precip_probability": 10,
+ "precip_type": "rain",
+ "relative_humidity": 88,
+ "sea_level_pressure": 1014.2,
+ "station_pressure": 1013.8,
+ "time": 1771164000,
+ "uv": 4.0,
+ "wind_avg": 19.0,
+ "wind_direction": 250,
+ "wind_direction_cardinal": "WSW",
+ "wind_gust": 31.0
+ },
+ {
+ "air_temperature": 16.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 16.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 15,
+ "local_hour": 10,
+ "precip": 0.13,
+ "precip_icon": "chance-rain",
+ "precip_probability": 10,
+ "precip_type": "rain",
+ "relative_humidity": 82,
+ "sea_level_pressure": 1014.0,
+ "station_pressure": 1013.6,
+ "time": 1771167600,
+ "uv": 4.0,
+ "wind_avg": 20.0,
+ "wind_direction": 250,
+ "wind_direction_cardinal": "WSW",
+ "wind_gust": 31.0
+ },
+ {
+ "air_temperature": 18.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 18.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 15,
+ "local_hour": 11,
+ "precip": 0.17,
+ "precip_icon": "chance-rain",
+ "precip_probability": 10,
+ "precip_type": "rain",
+ "relative_humidity": 76,
+ "sea_level_pressure": 1013.8,
+ "station_pressure": 1013.4,
+ "time": 1771171200,
+ "uv": 4.0,
+ "wind_avg": 20.0,
+ "wind_direction": 250,
+ "wind_direction_cardinal": "WSW",
+ "wind_gust": 31.0
+ },
+ {
+ "air_temperature": 18.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 18.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 15,
+ "local_hour": 12,
+ "precip": 0.21,
+ "precip_icon": "chance-rain",
+ "precip_probability": 10,
+ "precip_type": "rain",
+ "relative_humidity": 73,
+ "sea_level_pressure": 1013.5,
+ "station_pressure": 1013.1,
+ "time": 1771174800,
+ "uv": 4.0,
+ "wind_avg": 21.0,
+ "wind_direction": 250,
+ "wind_direction_cardinal": "WSW",
+ "wind_gust": 31.0
+ },
+ {
+ "air_temperature": 19.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 19.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 15,
+ "local_hour": 13,
+ "precip": 0.25,
+ "precip_icon": "chance-rain",
+ "precip_probability": 10,
+ "precip_type": "rain",
+ "relative_humidity": 70,
+ "sea_level_pressure": 1013.3,
+ "station_pressure": 1012.9,
+ "time": 1771178400,
+ "uv": 4.0,
+ "wind_avg": 21.0,
+ "wind_direction": 250,
+ "wind_direction_cardinal": "WSW",
+ "wind_gust": 30.0
+ },
+ {
+ "air_temperature": 19.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 19.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 15,
+ "local_hour": 14,
+ "precip": 0.25,
+ "precip_icon": "chance-rain",
+ "precip_probability": 10,
+ "precip_type": "rain",
+ "relative_humidity": 68,
+ "sea_level_pressure": 1013.4,
+ "station_pressure": 1013.0,
+ "time": 1771182000,
+ "uv": 3.0,
+ "wind_avg": 21.0,
+ "wind_direction": 270,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 30.0
+ },
+ {
+ "air_temperature": 19.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 19.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 15,
+ "local_hour": 15,
+ "precip": 0.25,
+ "precip_icon": "chance-rain",
+ "precip_probability": 10,
+ "precip_type": "rain",
+ "relative_humidity": 68,
+ "sea_level_pressure": 1013.5,
+ "station_pressure": 1013.1,
+ "time": 1771185600,
+ "uv": 3.0,
+ "wind_avg": 21.0,
+ "wind_direction": 270,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 30.0
+ },
+ {
+ "air_temperature": 19.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 19.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 15,
+ "local_hour": 16,
+ "precip": 0.25,
+ "precip_icon": "chance-rain",
+ "precip_probability": 10,
+ "precip_type": "rain",
+ "relative_humidity": 69,
+ "sea_level_pressure": 1013.6,
+ "station_pressure": 1013.2,
+ "time": 1771189200,
+ "uv": 3.0,
+ "wind_avg": 20.0,
+ "wind_direction": 270,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 30.0
+ },
+ {
+ "air_temperature": 19.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 19.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 15,
+ "local_hour": 17,
+ "precip": 0.25,
+ "precip_icon": "chance-rain",
+ "precip_probability": 10,
+ "precip_type": "rain",
+ "relative_humidity": 71,
+ "sea_level_pressure": 1013.7,
+ "station_pressure": 1013.3,
+ "time": 1771192800,
+ "uv": 3.0,
+ "wind_avg": 20.0,
+ "wind_direction": 270,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 30.0
+ },
+ {
+ "air_temperature": 18.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 18.0,
+ "icon": "partly-cloudy-day",
+ "local_day": 15,
+ "local_hour": 18,
+ "precip": 0.25,
+ "precip_icon": "chance-rain",
+ "precip_probability": 10,
+ "precip_type": "rain",
+ "relative_humidity": 73,
+ "sea_level_pressure": 1013.8,
+ "station_pressure": 1013.4,
+ "time": 1771196400,
+ "uv": 3.0,
+ "wind_avg": 20.0,
+ "wind_direction": 270,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 30.0
+ },
+ {
+ "air_temperature": 18.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 18.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 15,
+ "local_hour": 19,
+ "precip": 0.25,
+ "precip_icon": "chance-rain",
+ "precip_probability": 10,
+ "precip_type": "rain",
+ "relative_humidity": 75,
+ "sea_level_pressure": 1013.8,
+ "station_pressure": 1013.4,
+ "time": 1771200000,
+ "uv": 3.0,
+ "wind_avg": 19.0,
+ "wind_direction": 270,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 30.0
+ },
+ {
+ "air_temperature": 17.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 17.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 15,
+ "local_hour": 20,
+ "precip": 0.21,
+ "precip_icon": "chance-rain",
+ "precip_probability": 10,
+ "precip_type": "rain",
+ "relative_humidity": 74,
+ "sea_level_pressure": 1014.0,
+ "station_pressure": 1013.6,
+ "time": 1771203600,
+ "uv": 0.0,
+ "wind_avg": 19.0,
+ "wind_direction": 270,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 29.0
+ },
+ {
+ "air_temperature": 17.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 17.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 15,
+ "local_hour": 21,
+ "precip": 0.17,
+ "precip_icon": "chance-rain",
+ "precip_probability": 10,
+ "precip_type": "rain",
+ "relative_humidity": 76,
+ "sea_level_pressure": 1014.2,
+ "station_pressure": 1013.8,
+ "time": 1771207200,
+ "uv": 0.0,
+ "wind_avg": 18.0,
+ "wind_direction": 270,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 29.0
+ },
+ {
+ "air_temperature": 16.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 16.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 15,
+ "local_hour": 22,
+ "precip": 0.13,
+ "precip_icon": "chance-rain",
+ "precip_probability": 10,
+ "precip_type": "rain",
+ "relative_humidity": 78,
+ "sea_level_pressure": 1014.4,
+ "station_pressure": 1014.0,
+ "time": 1771210800,
+ "uv": 0.0,
+ "wind_avg": 18.0,
+ "wind_direction": 270,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 29.0
+ },
+ {
+ "air_temperature": 16.0,
+ "conditions": "Partly Cloudy",
+ "feels_like": 16.0,
+ "icon": "partly-cloudy-night",
+ "local_day": 15,
+ "local_hour": 23,
+ "precip": 0.09,
+ "precip_icon": "chance-rain",
+ "precip_probability": 10,
+ "precip_type": "rain",
+ "relative_humidity": 81,
+ "sea_level_pressure": 1014.6,
+ "station_pressure": 1014.2,
+ "time": 1771214400,
+ "uv": 0.0,
+ "wind_avg": 17.0,
+ "wind_direction": 270,
+ "wind_direction_cardinal": "W",
+ "wind_gust": 29.0
+ }
+ ]
+ },
+ "latitude": 29.05592,
+ "location_name": "OG Pergola",
+ "longitude": -80.90748,
+ "source_id_conditions": 5,
+ "station": { "agl": 1.8288, "elevation": 3.0345869064331055, "is_station_online": true, "state": 1, "station_id": 151283 },
+ "status": { "status_code": 0, "status_message": "SUCCESS" },
+ "timezone": "America/New_York",
+ "timezone_offset_minutes": -300,
+ "units": { "units_air_density": "kg/m3", "units_brightness": "lux", "units_distance": "km", "units_other": "metric", "units_precip": "mm", "units_pressure": "mb", "units_solar_radiation": "w/m2", "units_temp": "c", "units_wind": "kph" }
+}
diff --git a/tests/mocks/weather_weathergov_current.json b/tests/mocks/weather_weathergov_current.json
new file mode 100644
index 00000000..770bba1f
--- /dev/null
+++ b/tests/mocks/weather_weathergov_current.json
@@ -0,0 +1,151 @@
+{
+ "@context": [
+ "https://geojson.org/geojson-ld/geojson-context.jsonld",
+ {
+ "@version": "1.1",
+ "wx": "https://api.weather.gov/ontology#",
+ "s": "https://schema.org/",
+ "geo": "http://www.opengis.net/ont/geosparql#",
+ "unit": "http://codes.wmo.int/common/unit/",
+ "@vocab": "https://api.weather.gov/ontology#",
+ "geometry": {
+ "@id": "s:GeoCoordinates",
+ "@type": "geo:wktLiteral"
+ },
+ "city": "s:addressLocality",
+ "state": "s:addressRegion",
+ "distance": {
+ "@id": "s:Distance",
+ "@type": "s:QuantitativeValue"
+ },
+ "bearing": {
+ "@type": "s:QuantitativeValue"
+ },
+ "value": {
+ "@id": "s:value"
+ },
+ "unitCode": {
+ "@id": "s:unitCode",
+ "@type": "@id"
+ },
+ "forecastOffice": {
+ "@type": "@id"
+ },
+ "forecastGridData": {
+ "@type": "@id"
+ },
+ "publicZone": {
+ "@type": "@id"
+ },
+ "county": {
+ "@type": "@id"
+ }
+ }
+ ],
+ "id": "https://api.weather.gov/stations/KDCA/observations/2026-02-06T21:30:00+00:00",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-77.03, 38.85]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KDCA/observations/2026-02-06T21:30:00+00:00",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 20
+ },
+ "station": "https://api.weather.gov/stations/KDCA",
+ "stationId": "KDCA",
+ "stationName": "Washington/Reagan National Airport, DC",
+ "timestamp": "2026-02-06T21:30:00+00:00",
+ "rawMessage": "",
+ "textDescription": "Light Snow",
+ "icon": "https://api.weather.gov/icons/land/day/snow?size=medium",
+ "presentWeather": [
+ {
+ "intensity": "light",
+ "modifier": null,
+ "weather": "snow",
+ "rawString": "-SN"
+ }
+ ],
+ "temperature": {
+ "unitCode": "wmoUnit:degC",
+ "value": -1,
+ "qualityControl": "V"
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -7,
+ "qualityControl": "V"
+ },
+ "windDirection": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 0,
+ "qualityControl": "V"
+ },
+ "windSpeed": {
+ "unitCode": "wmoUnit:km_h-1",
+ "value": 0,
+ "qualityControl": "V"
+ },
+ "windGust": {
+ "unitCode": "wmoUnit:km_h-1",
+ "value": null,
+ "qualityControl": "Z"
+ },
+ "barometricPressure": {
+ "unitCode": "wmoUnit:Pa",
+ "value": 100372.55,
+ "qualityControl": "V"
+ },
+ "seaLevelPressure": {
+ "unitCode": "wmoUnit:Pa",
+ "value": null,
+ "qualityControl": "Z"
+ },
+ "visibility": {
+ "unitCode": "wmoUnit:m",
+ "value": 9656.06,
+ "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": 63.771213893297,
+ "qualityControl": "V"
+ },
+ "windChill": {
+ "unitCode": "wmoUnit:degC",
+ "value": null,
+ "qualityControl": "V"
+ },
+ "heatIndex": {
+ "unitCode": "wmoUnit:degC",
+ "value": null,
+ "qualityControl": "V"
+ },
+ "cloudLayers": [
+ {
+ "base": {
+ "unitCode": "wmoUnit:m",
+ "value": 944.88
+ },
+ "amount": "OVC"
+ }
+ ]
+ }
+}
diff --git a/tests/mocks/weather_weathergov_forecast.json b/tests/mocks/weather_weathergov_forecast.json
new file mode 100644
index 00000000..258d8653
--- /dev/null
+++ b/tests/mocks/weather_weathergov_forecast.json
@@ -0,0 +1,304 @@
+{
+ "@context": [
+ "https://geojson.org/geojson-ld/geojson-context.jsonld",
+ {
+ "@version": "1.1",
+ "wx": "https://api.weather.gov/ontology#",
+ "geo": "http://www.opengis.net/ont/geosparql#",
+ "unit": "http://codes.wmo.int/common/unit/",
+ "@vocab": "https://api.weather.gov/ontology#"
+ }
+ ],
+ "type": "Feature",
+ "geometry": {
+ "type": "Polygon",
+ "coordinates": [
+ [
+ [-77.0445, 38.8569],
+ [-77.0408, 38.8788],
+ [-77.0689, 38.8818],
+ [-77.0727, 38.8598],
+ [-77.0445, 38.8569]
+ ]
+ ]
+ },
+ "properties": {
+ "units": "si",
+ "forecastGenerator": "BaselineForecastGenerator",
+ "generatedAt": "2026-02-06T21:45:05+00:00",
+ "updateTime": "2026-02-06T20:53:00+00:00",
+ "validTimes": "2026-02-06T14:00:00+00:00/P7DT14H",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 7.9248
+ },
+ "periods": [
+ {
+ "number": 1,
+ "name": "This Afternoon",
+ "startTime": "2026-02-06T16:00:00-05:00",
+ "endTime": "2026-02-06T18:00:00-05:00",
+ "isDaytime": true,
+ "temperature": 1,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 71
+ },
+ "windSpeed": "4 km/h",
+ "windDirection": "S",
+ "icon": "https://api.weather.gov/icons/land/day/snow,70?size=medium",
+ "shortForecast": "Light Snow Likely",
+ "detailedForecast": "Snow likely. Cloudy, with a high near 1. South wind around 4 km/h. Chance of precipitation is 70%. New snow accumulation of less than one cm possible."
+ },
+ {
+ "number": 2,
+ "name": "Tonight",
+ "startTime": "2026-02-06T18:00:00-05:00",
+ "endTime": "2026-02-07T06:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -11,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 45
+ },
+ "windSpeed": "2 to 35 km/h",
+ "windDirection": "W",
+ "icon": "https://api.weather.gov/icons/land/night/snow,50/wind_bkn?size=medium",
+ "shortForecast": "Chance Light Snow then Mostly Cloudy",
+ "detailedForecast": "A chance of snow before 10pm. Mostly cloudy. Low around -11, with temperatures rising to around -7 overnight. West wind 2 to 35 km/h, with gusts as high as 63 km/h. Chance of precipitation is 50%. New snow accumulation of less than two cm possible."
+ },
+ {
+ "number": 3,
+ "name": "Saturday",
+ "startTime": "2026-02-07T06:00:00-05:00",
+ "endTime": "2026-02-07T18:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -7,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "windSpeed": "37 to 48 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/wind_sct?size=medium",
+ "shortForecast": "Mostly Sunny",
+ "detailedForecast": "Mostly sunny, with a high near -7. Wind chill values as low as -21. Northwest wind 37 to 48 km/h, with gusts as high as 94 km/h."
+ },
+ {
+ "number": 4,
+ "name": "Saturday Night",
+ "startTime": "2026-02-07T18:00:00-05:00",
+ "endTime": "2026-02-08T06:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -12,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "windSpeed": "22 to 43 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/wind_few?size=medium",
+ "shortForecast": "Mostly Clear",
+ "detailedForecast": "Mostly clear, with a low around -12. Wind chill values as low as -21. Northwest wind 22 to 43 km/h, with gusts as high as 76 km/h."
+ },
+ {
+ "number": 5,
+ "name": "Sunday",
+ "startTime": "2026-02-08T06:00:00-05:00",
+ "endTime": "2026-02-08T18:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -4,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 3
+ },
+ "windSpeed": "13 to 22 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/sct?size=medium",
+ "shortForecast": "Mostly Sunny",
+ "detailedForecast": "Mostly sunny, with a high near -4. Northwest wind 13 to 22 km/h, with gusts as high as 43 km/h."
+ },
+ {
+ "number": 6,
+ "name": "Sunday Night",
+ "startTime": "2026-02-08T18:00:00-05:00",
+ "endTime": "2026-02-09T06:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -11,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 2
+ },
+ "windSpeed": "4 to 9 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/sct?size=medium",
+ "shortForecast": "Partly Cloudy",
+ "detailedForecast": "Partly cloudy, with a low around -11."
+ },
+ {
+ "number": 7,
+ "name": "Monday",
+ "startTime": "2026-02-09T06:00:00-05:00",
+ "endTime": "2026-02-09T18:00:00-05:00",
+ "isDaytime": true,
+ "temperature": 0,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "windSpeed": "7 km/h",
+ "windDirection": "W",
+ "icon": "https://api.weather.gov/icons/land/day/bkn?size=medium",
+ "shortForecast": "Partly Sunny",
+ "detailedForecast": "Partly sunny, with a high near 0."
+ },
+ {
+ "number": 8,
+ "name": "Monday Night",
+ "startTime": "2026-02-09T18:00:00-05:00",
+ "endTime": "2026-02-10T06:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -6,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "windSpeed": "2 km/h",
+ "windDirection": "SE",
+ "icon": "https://api.weather.gov/icons/land/night/bkn?size=medium",
+ "shortForecast": "Mostly Cloudy",
+ "detailedForecast": "Mostly cloudy, with a low around -6."
+ },
+ {
+ "number": 9,
+ "name": "Tuesday",
+ "startTime": "2026-02-10T06:00:00-05:00",
+ "endTime": "2026-02-10T18:00:00-05:00",
+ "isDaytime": true,
+ "temperature": 7,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 1
+ },
+ "windSpeed": "6 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/sct?size=medium",
+ "shortForecast": "Mostly Sunny",
+ "detailedForecast": "Mostly sunny, with a high near 7."
+ },
+ {
+ "number": 10,
+ "name": "Tuesday Night",
+ "startTime": "2026-02-10T18:00:00-05:00",
+ "endTime": "2026-02-11T06:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -1,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 18
+ },
+ "windSpeed": "4 km/h",
+ "windDirection": "E",
+ "icon": "https://api.weather.gov/icons/land/night/bkn/rain,20?size=medium",
+ "shortForecast": "Mostly Cloudy then Slight Chance Light Rain",
+ "detailedForecast": "A slight chance of rain after 1am. Mostly cloudy, with a low around -1."
+ },
+ {
+ "number": 11,
+ "name": "Wednesday",
+ "startTime": "2026-02-11T06:00:00-05:00",
+ "endTime": "2026-02-11T18:00:00-05:00",
+ "isDaytime": true,
+ "temperature": 8,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 50
+ },
+ "windSpeed": "4 to 11 km/h",
+ "windDirection": "W",
+ "icon": "https://api.weather.gov/icons/land/day/rain,50?size=medium",
+ "shortForecast": "Chance Light Rain",
+ "detailedForecast": "A chance of rain. Mostly cloudy, with a high near 8. Chance of precipitation is 50%."
+ },
+ {
+ "number": 12,
+ "name": "Wednesday Night",
+ "startTime": "2026-02-11T18:00:00-05:00",
+ "endTime": "2026-02-12T06:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -1,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 50
+ },
+ "windSpeed": "11 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/rain,50/rain,30?size=medium",
+ "shortForecast": "Chance Light Rain",
+ "detailedForecast": "A chance of rain. Mostly cloudy, with a low around -1. Chance of precipitation is 50%."
+ },
+ {
+ "number": 13,
+ "name": "Thursday",
+ "startTime": "2026-02-12T06:00:00-05:00",
+ "endTime": "2026-02-12T18:00:00-05:00",
+ "isDaytime": true,
+ "temperature": 4,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 27
+ },
+ "windSpeed": "11 to 17 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/rain,30/rain,20?size=medium",
+ "shortForecast": "Chance Light Rain",
+ "detailedForecast": "A chance of rain before 1pm. Mostly cloudy, with a high near 4. Chance of precipitation is 30%."
+ },
+ {
+ "number": 14,
+ "name": "Thursday Night",
+ "startTime": "2026-02-12T18:00:00-05:00",
+ "endTime": "2026-02-13T06:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -3,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 21
+ },
+ "windSpeed": "13 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/snow,20?size=medium",
+ "shortForecast": "Slight Chance Light Snow",
+ "detailedForecast": "A slight chance of snow after 7pm. Mostly cloudy, with a low around -3."
+ }
+ ]
+ }
+}
diff --git a/tests/mocks/weather_weathergov_hourly.json b/tests/mocks/weather_weathergov_hourly.json
new file mode 100644
index 00000000..e4fc3bb8
--- /dev/null
+++ b/tests/mocks/weather_weathergov_hourly.json
@@ -0,0 +1,4250 @@
+{
+ "@context": [
+ "https://geojson.org/geojson-ld/geojson-context.jsonld",
+ {
+ "@version": "1.1",
+ "wx": "https://api.weather.gov/ontology#",
+ "geo": "http://www.opengis.net/ont/geosparql#",
+ "unit": "http://codes.wmo.int/common/unit/",
+ "@vocab": "https://api.weather.gov/ontology#"
+ }
+ ],
+ "type": "Feature",
+ "geometry": {
+ "type": "Polygon",
+ "coordinates": [
+ [
+ [-77.0445, 38.8569],
+ [-77.0408, 38.8788],
+ [-77.0689, 38.8818],
+ [-77.0727, 38.8598],
+ [-77.0445, 38.8569]
+ ]
+ ]
+ },
+ "properties": {
+ "units": "si",
+ "forecastGenerator": "HourlyForecastGenerator",
+ "generatedAt": "2026-02-06T21:45:06+00:00",
+ "updateTime": "2026-02-06T20:53:00+00:00",
+ "validTimes": "2026-02-06T14:00:00+00:00/P7DT14H",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 7.9248
+ },
+ "periods": [
+ {
+ "number": 1,
+ "name": "",
+ "startTime": "2026-02-06T16:00:00-05:00",
+ "endTime": "2026-02-06T17:00:00-05:00",
+ "isDaytime": true,
+ "temperature": 1,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 71
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -3.888888888888889
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 72
+ },
+ "windSpeed": "4 km/h",
+ "windDirection": "S",
+ "icon": "https://api.weather.gov/icons/land/day/snow,70?size=small",
+ "shortForecast": "Light Snow Likely",
+ "detailedForecast": ""
+ },
+ {
+ "number": 2,
+ "name": "",
+ "startTime": "2026-02-06T17:00:00-05:00",
+ "endTime": "2026-02-06T18:00:00-05:00",
+ "isDaytime": true,
+ "temperature": 1,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 57
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -3.3333333333333335
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 75
+ },
+ "windSpeed": "4 km/h",
+ "windDirection": "S",
+ "icon": "https://api.weather.gov/icons/land/day/snow,60?size=small",
+ "shortForecast": "Light Snow Likely",
+ "detailedForecast": ""
+ },
+ {
+ "number": 3,
+ "name": "",
+ "startTime": "2026-02-06T18:00:00-05:00",
+ "endTime": "2026-02-06T19:00:00-05:00",
+ "isDaytime": false,
+ "temperature": 0,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 45
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -3.888888888888889
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 75
+ },
+ "windSpeed": "2 km/h",
+ "windDirection": "S",
+ "icon": "https://api.weather.gov/icons/land/night/snow,50?size=small",
+ "shortForecast": "Chance Light Snow",
+ "detailedForecast": ""
+ },
+ {
+ "number": 4,
+ "name": "",
+ "startTime": "2026-02-06T19:00:00-05:00",
+ "endTime": "2026-02-06T20:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -1,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 37
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -4.444444444444445
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 75
+ },
+ "windSpeed": "4 km/h",
+ "windDirection": "SE",
+ "icon": "https://api.weather.gov/icons/land/night/snow,40?size=small",
+ "shortForecast": "Chance Light Snow",
+ "detailedForecast": ""
+ },
+ {
+ "number": 5,
+ "name": "",
+ "startTime": "2026-02-06T20:00:00-05:00",
+ "endTime": "2026-02-06T21:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -1,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 30
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -3.888888888888889
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 81
+ },
+ "windSpeed": "4 km/h",
+ "windDirection": "SW",
+ "icon": "https://api.weather.gov/icons/land/night/snow,30?size=small",
+ "shortForecast": "Chance Light Snow",
+ "detailedForecast": ""
+ },
+ {
+ "number": 6,
+ "name": "",
+ "startTime": "2026-02-06T21:00:00-05:00",
+ "endTime": "2026-02-06T22:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -1,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 17
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -3.888888888888889
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 81
+ },
+ "windSpeed": "4 km/h",
+ "windDirection": "W",
+ "icon": "https://api.weather.gov/icons/land/night/snow,20?size=small",
+ "shortForecast": "Slight Chance Light Snow",
+ "detailedForecast": ""
+ },
+ {
+ "number": 7,
+ "name": "",
+ "startTime": "2026-02-06T22:00:00-05:00",
+ "endTime": "2026-02-06T23:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -1,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 13
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -3.888888888888889
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 81
+ },
+ "windSpeed": "6 km/h",
+ "windDirection": "W",
+ "icon": "https://api.weather.gov/icons/land/night/bkn?size=small",
+ "shortForecast": "Mostly Cloudy",
+ "detailedForecast": ""
+ },
+ {
+ "number": 8,
+ "name": "",
+ "startTime": "2026-02-06T23:00:00-05:00",
+ "endTime": "2026-02-07T00:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -1,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 5
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -4.444444444444445
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 78
+ },
+ "windSpeed": "7 km/h",
+ "windDirection": "W",
+ "icon": "https://api.weather.gov/icons/land/night/bkn?size=small",
+ "shortForecast": "Mostly Cloudy",
+ "detailedForecast": ""
+ },
+ {
+ "number": 9,
+ "name": "",
+ "startTime": "2026-02-07T00:00:00-05:00",
+ "endTime": "2026-02-07T01:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -2,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 7
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -5
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 78
+ },
+ "windSpeed": "9 km/h",
+ "windDirection": "W",
+ "icon": "https://api.weather.gov/icons/land/night/bkn?size=small",
+ "shortForecast": "Mostly Cloudy",
+ "detailedForecast": ""
+ },
+ {
+ "number": 10,
+ "name": "",
+ "startTime": "2026-02-07T01:00:00-05:00",
+ "endTime": "2026-02-07T02:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -2,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 6
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -5.555555555555555
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 75
+ },
+ "windSpeed": "11 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/bkn?size=small",
+ "shortForecast": "Mostly Cloudy",
+ "detailedForecast": ""
+ },
+ {
+ "number": 11,
+ "name": "",
+ "startTime": "2026-02-07T02:00:00-05:00",
+ "endTime": "2026-02-07T03:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -2,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 4
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -6.666666666666667
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 69
+ },
+ "windSpeed": "19 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/bkn?size=small",
+ "shortForecast": "Mostly Cloudy",
+ "detailedForecast": ""
+ },
+ {
+ "number": 12,
+ "name": "",
+ "startTime": "2026-02-07T03:00:00-05:00",
+ "endTime": "2026-02-07T04:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -3,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 4
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -7.777777777777778
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 68
+ },
+ "windSpeed": "24 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/sct?size=small",
+ "shortForecast": "Partly Cloudy",
+ "detailedForecast": ""
+ },
+ {
+ "number": 13,
+ "name": "",
+ "startTime": "2026-02-07T04:00:00-05:00",
+ "endTime": "2026-02-07T05:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -4,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 3
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -8.88888888888889
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 68
+ },
+ "windSpeed": "31 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/sct?size=small",
+ "shortForecast": "Partly Cloudy",
+ "detailedForecast": ""
+ },
+ {
+ "number": 14,
+ "name": "",
+ "startTime": "2026-02-07T05:00:00-05:00",
+ "endTime": "2026-02-07T06:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -7,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -11.11111111111111
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 71
+ },
+ "windSpeed": "35 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/wind_sct?size=small",
+ "shortForecast": "Partly Cloudy",
+ "detailedForecast": ""
+ },
+ {
+ "number": 15,
+ "name": "",
+ "startTime": "2026-02-07T06:00:00-05:00",
+ "endTime": "2026-02-07T07:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -8,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -13.333333333333334
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 64
+ },
+ "windSpeed": "37 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/wind_sct?size=small",
+ "shortForecast": "Mostly Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 16,
+ "name": "",
+ "startTime": "2026-02-07T07:00:00-05:00",
+ "endTime": "2026-02-07T08:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -9,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -15
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 61
+ },
+ "windSpeed": "39 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/wind_sct?size=small",
+ "shortForecast": "Mostly Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 17,
+ "name": "",
+ "startTime": "2026-02-07T08:00:00-05:00",
+ "endTime": "2026-02-07T09:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -10,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -16.11111111111111
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 61
+ },
+ "windSpeed": "43 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/wind_sct?size=small",
+ "shortForecast": "Mostly Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 18,
+ "name": "",
+ "startTime": "2026-02-07T09:00:00-05:00",
+ "endTime": "2026-02-07T10:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -9,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -17.22222222222222
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 53
+ },
+ "windSpeed": "44 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/wind_sct?size=small",
+ "shortForecast": "Mostly Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 19,
+ "name": "",
+ "startTime": "2026-02-07T10:00:00-05:00",
+ "endTime": "2026-02-07T11:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -9,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -18.333333333333332
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 48
+ },
+ "windSpeed": "48 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/wind_sct?size=small",
+ "shortForecast": "Mostly Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 20,
+ "name": "",
+ "startTime": "2026-02-07T11:00:00-05:00",
+ "endTime": "2026-02-07T12:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -9,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -18.333333333333332
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 48
+ },
+ "windSpeed": "48 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/wind_sct?size=small",
+ "shortForecast": "Mostly Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 21,
+ "name": "",
+ "startTime": "2026-02-07T12:00:00-05:00",
+ "endTime": "2026-02-07T13:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -8,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -18.333333333333332
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 44
+ },
+ "windSpeed": "48 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/wind_few?size=small",
+ "shortForecast": "Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 22,
+ "name": "",
+ "startTime": "2026-02-07T13:00:00-05:00",
+ "endTime": "2026-02-07T14:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -9,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -18.333333333333332
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 46
+ },
+ "windSpeed": "48 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/wind_few?size=small",
+ "shortForecast": "Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 23,
+ "name": "",
+ "startTime": "2026-02-07T14:00:00-05:00",
+ "endTime": "2026-02-07T15:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -8,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -18.333333333333332
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 42
+ },
+ "windSpeed": "46 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/wind_few?size=small",
+ "shortForecast": "Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 24,
+ "name": "",
+ "startTime": "2026-02-07T15:00:00-05:00",
+ "endTime": "2026-02-07T16:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -8,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -18.333333333333332
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 42
+ },
+ "windSpeed": "43 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/wind_few?size=small",
+ "shortForecast": "Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 25,
+ "name": "",
+ "startTime": "2026-02-07T16:00:00-05:00",
+ "endTime": "2026-02-07T17:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -8,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -17.77777777777778
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 44
+ },
+ "windSpeed": "41 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/wind_few?size=small",
+ "shortForecast": "Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 26,
+ "name": "",
+ "startTime": "2026-02-07T17:00:00-05:00",
+ "endTime": "2026-02-07T18:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -8,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -18.333333333333332
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 42
+ },
+ "windSpeed": "41 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/wind_few?size=small",
+ "shortForecast": "Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 27,
+ "name": "",
+ "startTime": "2026-02-07T18:00:00-05:00",
+ "endTime": "2026-02-07T19:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -9,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -18.333333333333332
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 46
+ },
+ "windSpeed": "43 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/wind_few?size=small",
+ "shortForecast": "Mostly Clear",
+ "detailedForecast": ""
+ },
+ {
+ "number": 28,
+ "name": "",
+ "startTime": "2026-02-07T19:00:00-05:00",
+ "endTime": "2026-02-07T20:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -8,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -18.333333333333332
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 44
+ },
+ "windSpeed": "43 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/wind_few?size=small",
+ "shortForecast": "Mostly Clear",
+ "detailedForecast": ""
+ },
+ {
+ "number": 29,
+ "name": "",
+ "startTime": "2026-02-07T20:00:00-05:00",
+ "endTime": "2026-02-07T21:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -9,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -17.22222222222222
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 51
+ },
+ "windSpeed": "39 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/wind_few?size=small",
+ "shortForecast": "Mostly Clear",
+ "detailedForecast": ""
+ },
+ {
+ "number": 30,
+ "name": "",
+ "startTime": "2026-02-07T21:00:00-05:00",
+ "endTime": "2026-02-07T22:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -9,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -17.77777777777778
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 50
+ },
+ "windSpeed": "37 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/wind_few?size=small",
+ "shortForecast": "Mostly Clear",
+ "detailedForecast": ""
+ },
+ {
+ "number": 31,
+ "name": "",
+ "startTime": "2026-02-07T22:00:00-05:00",
+ "endTime": "2026-02-07T23:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -10,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -17.77777777777778
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 53
+ },
+ "windSpeed": "33 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/wind_few?size=small",
+ "shortForecast": "Mostly Clear",
+ "detailedForecast": ""
+ },
+ {
+ "number": 32,
+ "name": "",
+ "startTime": "2026-02-07T23:00:00-05:00",
+ "endTime": "2026-02-08T00:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -11,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -17.77777777777778
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 55
+ },
+ "windSpeed": "31 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/few?size=small",
+ "shortForecast": "Mostly Clear",
+ "detailedForecast": ""
+ },
+ {
+ "number": 33,
+ "name": "",
+ "startTime": "2026-02-08T00:00:00-05:00",
+ "endTime": "2026-02-08T01:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -11,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -18.333333333333332
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 53
+ },
+ "windSpeed": "28 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/few?size=small",
+ "shortForecast": "Mostly Clear",
+ "detailedForecast": ""
+ },
+ {
+ "number": 34,
+ "name": "",
+ "startTime": "2026-02-08T01:00:00-05:00",
+ "endTime": "2026-02-08T02:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -11,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -18.333333333333332
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 55
+ },
+ "windSpeed": "28 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/few?size=small",
+ "shortForecast": "Mostly Clear",
+ "detailedForecast": ""
+ },
+ {
+ "number": 35,
+ "name": "",
+ "startTime": "2026-02-08T02:00:00-05:00",
+ "endTime": "2026-02-08T03:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -11,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -18.333333333333332
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 55
+ },
+ "windSpeed": "26 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/few?size=small",
+ "shortForecast": "Mostly Clear",
+ "detailedForecast": ""
+ },
+ {
+ "number": 36,
+ "name": "",
+ "startTime": "2026-02-08T03:00:00-05:00",
+ "endTime": "2026-02-08T04:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -11,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -17.77777777777778
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 58
+ },
+ "windSpeed": "24 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/few?size=small",
+ "shortForecast": "Mostly Clear",
+ "detailedForecast": ""
+ },
+ {
+ "number": 37,
+ "name": "",
+ "startTime": "2026-02-08T04:00:00-05:00",
+ "endTime": "2026-02-08T05:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -11,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -17.77777777777778
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 58
+ },
+ "windSpeed": "24 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/few?size=small",
+ "shortForecast": "Mostly Clear",
+ "detailedForecast": ""
+ },
+ {
+ "number": 38,
+ "name": "",
+ "startTime": "2026-02-08T05:00:00-05:00",
+ "endTime": "2026-02-08T06:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -12,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -17.77777777777778
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 60
+ },
+ "windSpeed": "22 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/few?size=small",
+ "shortForecast": "Mostly Clear",
+ "detailedForecast": ""
+ },
+ {
+ "number": 39,
+ "name": "",
+ "startTime": "2026-02-08T06:00:00-05:00",
+ "endTime": "2026-02-08T07:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -12,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -18.333333333333332
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 57
+ },
+ "windSpeed": "22 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/few?size=small",
+ "shortForecast": "Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 40,
+ "name": "",
+ "startTime": "2026-02-08T07:00:00-05:00",
+ "endTime": "2026-02-08T08:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -12,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 3
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -18.333333333333332
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 57
+ },
+ "windSpeed": "20 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/few?size=small",
+ "shortForecast": "Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 41,
+ "name": "",
+ "startTime": "2026-02-08T08:00:00-05:00",
+ "endTime": "2026-02-08T09:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -11,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 3
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -17.77777777777778
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 55
+ },
+ "windSpeed": "20 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/few?size=small",
+ "shortForecast": "Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 42,
+ "name": "",
+ "startTime": "2026-02-08T09:00:00-05:00",
+ "endTime": "2026-02-08T10:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -9,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 3
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -17.22222222222222
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 53
+ },
+ "windSpeed": "19 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/sct?size=small",
+ "shortForecast": "Mostly Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 43,
+ "name": "",
+ "startTime": "2026-02-08T10:00:00-05:00",
+ "endTime": "2026-02-08T11:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -8,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 3
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -16.666666666666668
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 51
+ },
+ "windSpeed": "19 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/sct?size=small",
+ "shortForecast": "Mostly Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 44,
+ "name": "",
+ "startTime": "2026-02-08T11:00:00-05:00",
+ "endTime": "2026-02-08T12:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -7,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 3
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -16.11111111111111
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 49
+ },
+ "windSpeed": "19 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/bkn?size=small",
+ "shortForecast": "Partly Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 45,
+ "name": "",
+ "startTime": "2026-02-08T12:00:00-05:00",
+ "endTime": "2026-02-08T13:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -7,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 3
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -15.555555555555555
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 49
+ },
+ "windSpeed": "19 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/bkn?size=small",
+ "shortForecast": "Partly Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 46,
+ "name": "",
+ "startTime": "2026-02-08T13:00:00-05:00",
+ "endTime": "2026-02-08T14:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -6,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 2
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -15
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 47
+ },
+ "windSpeed": "19 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/bkn?size=small",
+ "shortForecast": "Partly Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 47,
+ "name": "",
+ "startTime": "2026-02-08T14:00:00-05:00",
+ "endTime": "2026-02-08T15:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -5,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 2
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -14.444444444444445
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 47
+ },
+ "windSpeed": "19 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/bkn?size=small",
+ "shortForecast": "Partly Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 48,
+ "name": "",
+ "startTime": "2026-02-08T15:00:00-05:00",
+ "endTime": "2026-02-08T16:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -4,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 2
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -14.444444444444445
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 45
+ },
+ "windSpeed": "17 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/sct?size=small",
+ "shortForecast": "Mostly Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 49,
+ "name": "",
+ "startTime": "2026-02-08T16:00:00-05:00",
+ "endTime": "2026-02-08T17:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -4,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 2
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -13.88888888888889
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 47
+ },
+ "windSpeed": "15 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/sct?size=small",
+ "shortForecast": "Mostly Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 50,
+ "name": "",
+ "startTime": "2026-02-08T17:00:00-05:00",
+ "endTime": "2026-02-08T18:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -5,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 2
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -13.333333333333334
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 52
+ },
+ "windSpeed": "13 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/sct?size=small",
+ "shortForecast": "Mostly Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 51,
+ "name": "",
+ "startTime": "2026-02-08T18:00:00-05:00",
+ "endTime": "2026-02-08T19:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -5,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 2
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -13.333333333333334
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 52
+ },
+ "windSpeed": "9 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/sct?size=small",
+ "shortForecast": "Partly Cloudy",
+ "detailedForecast": ""
+ },
+ {
+ "number": 52,
+ "name": "",
+ "startTime": "2026-02-08T19:00:00-05:00",
+ "endTime": "2026-02-08T20:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -6,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -13.333333333333334
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 54
+ },
+ "windSpeed": "7 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/few?size=small",
+ "shortForecast": "Mostly Clear",
+ "detailedForecast": ""
+ },
+ {
+ "number": 53,
+ "name": "",
+ "startTime": "2026-02-08T20:00:00-05:00",
+ "endTime": "2026-02-08T21:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -6,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -13.333333333333334
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 56
+ },
+ "windSpeed": "7 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/few?size=small",
+ "shortForecast": "Mostly Clear",
+ "detailedForecast": ""
+ },
+ {
+ "number": 54,
+ "name": "",
+ "startTime": "2026-02-08T21:00:00-05:00",
+ "endTime": "2026-02-08T22:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -7,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -13.88888888888889
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 59
+ },
+ "windSpeed": "7 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/few?size=small",
+ "shortForecast": "Mostly Clear",
+ "detailedForecast": ""
+ },
+ {
+ "number": 55,
+ "name": "",
+ "startTime": "2026-02-08T22:00:00-05:00",
+ "endTime": "2026-02-08T23:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -8,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -13.88888888888889
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 61
+ },
+ "windSpeed": "7 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/few?size=small",
+ "shortForecast": "Mostly Clear",
+ "detailedForecast": ""
+ },
+ {
+ "number": 56,
+ "name": "",
+ "startTime": "2026-02-08T23:00:00-05:00",
+ "endTime": "2026-02-09T00:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -8,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -13.88888888888889
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 61
+ },
+ "windSpeed": "7 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/few?size=small",
+ "shortForecast": "Mostly Clear",
+ "detailedForecast": ""
+ },
+ {
+ "number": 57,
+ "name": "",
+ "startTime": "2026-02-09T00:00:00-05:00",
+ "endTime": "2026-02-09T01:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -8,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -14.444444444444445
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 61
+ },
+ "windSpeed": "6 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/few?size=small",
+ "shortForecast": "Mostly Clear",
+ "detailedForecast": ""
+ },
+ {
+ "number": 58,
+ "name": "",
+ "startTime": "2026-02-09T01:00:00-05:00",
+ "endTime": "2026-02-09T02:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -8,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -14.444444444444445
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 61
+ },
+ "windSpeed": "6 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/few?size=small",
+ "shortForecast": "Mostly Clear",
+ "detailedForecast": ""
+ },
+ {
+ "number": 59,
+ "name": "",
+ "startTime": "2026-02-09T02:00:00-05:00",
+ "endTime": "2026-02-09T03:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -9,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -14.444444444444445
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 64
+ },
+ "windSpeed": "6 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/sct?size=small",
+ "shortForecast": "Partly Cloudy",
+ "detailedForecast": ""
+ },
+ {
+ "number": 60,
+ "name": "",
+ "startTime": "2026-02-09T03:00:00-05:00",
+ "endTime": "2026-02-09T04:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -10,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -15
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 67
+ },
+ "windSpeed": "6 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/sct?size=small",
+ "shortForecast": "Partly Cloudy",
+ "detailedForecast": ""
+ },
+ {
+ "number": 61,
+ "name": "",
+ "startTime": "2026-02-09T04:00:00-05:00",
+ "endTime": "2026-02-09T05:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -11,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -15
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 70
+ },
+ "windSpeed": "4 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/sct?size=small",
+ "shortForecast": "Partly Cloudy",
+ "detailedForecast": ""
+ },
+ {
+ "number": 62,
+ "name": "",
+ "startTime": "2026-02-09T05:00:00-05:00",
+ "endTime": "2026-02-09T06:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -11,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -15.555555555555555
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 70
+ },
+ "windSpeed": "4 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/sct?size=small",
+ "shortForecast": "Partly Cloudy",
+ "detailedForecast": ""
+ },
+ {
+ "number": 63,
+ "name": "",
+ "startTime": "2026-02-09T06:00:00-05:00",
+ "endTime": "2026-02-09T07:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -11,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -15.555555555555555
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 70
+ },
+ "windSpeed": "4 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/bkn?size=small",
+ "shortForecast": "Partly Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 64,
+ "name": "",
+ "startTime": "2026-02-09T07:00:00-05:00",
+ "endTime": "2026-02-09T08:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -11,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -15.555555555555555
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 70
+ },
+ "windSpeed": "4 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/bkn?size=small",
+ "shortForecast": "Partly Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 65,
+ "name": "",
+ "startTime": "2026-02-09T08:00:00-05:00",
+ "endTime": "2026-02-09T09:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -10,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -15
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 67
+ },
+ "windSpeed": "4 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/bkn?size=small",
+ "shortForecast": "Partly Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 66,
+ "name": "",
+ "startTime": "2026-02-09T09:00:00-05:00",
+ "endTime": "2026-02-09T10:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -8,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -14.444444444444445
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 59
+ },
+ "windSpeed": "4 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/bkn?size=small",
+ "shortForecast": "Partly Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 67,
+ "name": "",
+ "startTime": "2026-02-09T10:00:00-05:00",
+ "endTime": "2026-02-09T11:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -6,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -13.333333333333334
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 56
+ },
+ "windSpeed": "4 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/bkn?size=small",
+ "shortForecast": "Partly Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 68,
+ "name": "",
+ "startTime": "2026-02-09T11:00:00-05:00",
+ "endTime": "2026-02-09T12:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -4,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -12.777777777777779
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 52
+ },
+ "windSpeed": "6 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/bkn?size=small",
+ "shortForecast": "Partly Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 69,
+ "name": "",
+ "startTime": "2026-02-09T12:00:00-05:00",
+ "endTime": "2026-02-09T13:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -3,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -11.666666666666666
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 50
+ },
+ "windSpeed": "7 km/h",
+ "windDirection": "W",
+ "icon": "https://api.weather.gov/icons/land/day/bkn?size=small",
+ "shortForecast": "Partly Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 70,
+ "name": "",
+ "startTime": "2026-02-09T13:00:00-05:00",
+ "endTime": "2026-02-09T14:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -2,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -11.11111111111111
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 48
+ },
+ "windSpeed": "7 km/h",
+ "windDirection": "W",
+ "icon": "https://api.weather.gov/icons/land/day/bkn?size=small",
+ "shortForecast": "Partly Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 71,
+ "name": "",
+ "startTime": "2026-02-09T14:00:00-05:00",
+ "endTime": "2026-02-09T15:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -1,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -10.555555555555555
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 49
+ },
+ "windSpeed": "7 km/h",
+ "windDirection": "W",
+ "icon": "https://api.weather.gov/icons/land/day/bkn?size=small",
+ "shortForecast": "Partly Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 72,
+ "name": "",
+ "startTime": "2026-02-09T15:00:00-05:00",
+ "endTime": "2026-02-09T16:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -1,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -10
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 49
+ },
+ "windSpeed": "6 km/h",
+ "windDirection": "SW",
+ "icon": "https://api.weather.gov/icons/land/day/bkn?size=small",
+ "shortForecast": "Partly Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 73,
+ "name": "",
+ "startTime": "2026-02-09T16:00:00-05:00",
+ "endTime": "2026-02-09T17:00:00-05:00",
+ "isDaytime": true,
+ "temperature": 0,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -10
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 47
+ },
+ "windSpeed": "6 km/h",
+ "windDirection": "SW",
+ "icon": "https://api.weather.gov/icons/land/day/bkn?size=small",
+ "shortForecast": "Mostly Cloudy",
+ "detailedForecast": ""
+ },
+ {
+ "number": 74,
+ "name": "",
+ "startTime": "2026-02-09T17:00:00-05:00",
+ "endTime": "2026-02-09T18:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -1,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -10
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 49
+ },
+ "windSpeed": "4 km/h",
+ "windDirection": "SW",
+ "icon": "https://api.weather.gov/icons/land/day/bkn?size=small",
+ "shortForecast": "Mostly Cloudy",
+ "detailedForecast": ""
+ },
+ {
+ "number": 75,
+ "name": "",
+ "startTime": "2026-02-09T18:00:00-05:00",
+ "endTime": "2026-02-09T19:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -1,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -9.444444444444445
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 53
+ },
+ "windSpeed": "2 km/h",
+ "windDirection": "S",
+ "icon": "https://api.weather.gov/icons/land/night/bkn?size=small",
+ "shortForecast": "Mostly Cloudy",
+ "detailedForecast": ""
+ },
+ {
+ "number": 76,
+ "name": "",
+ "startTime": "2026-02-09T19:00:00-05:00",
+ "endTime": "2026-02-09T20:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -2,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -9.444444444444445
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 58
+ },
+ "windSpeed": "2 km/h",
+ "windDirection": "SE",
+ "icon": "https://api.weather.gov/icons/land/night/bkn?size=small",
+ "shortForecast": "Mostly Cloudy",
+ "detailedForecast": ""
+ },
+ {
+ "number": 77,
+ "name": "",
+ "startTime": "2026-02-09T20:00:00-05:00",
+ "endTime": "2026-02-09T21:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -3,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -9.444444444444445
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 60
+ },
+ "windSpeed": "2 km/h",
+ "windDirection": "SE",
+ "icon": "https://api.weather.gov/icons/land/night/bkn?size=small",
+ "shortForecast": "Mostly Cloudy",
+ "detailedForecast": ""
+ },
+ {
+ "number": 78,
+ "name": "",
+ "startTime": "2026-02-09T21:00:00-05:00",
+ "endTime": "2026-02-09T22:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -3,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -8.88888888888889
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 65
+ },
+ "windSpeed": "2 km/h",
+ "windDirection": "S",
+ "icon": "https://api.weather.gov/icons/land/night/bkn?size=small",
+ "shortForecast": "Mostly Cloudy",
+ "detailedForecast": ""
+ },
+ {
+ "number": 79,
+ "name": "",
+ "startTime": "2026-02-09T22:00:00-05:00",
+ "endTime": "2026-02-09T23:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -4,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -8.88888888888889
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 68
+ },
+ "windSpeed": "2 km/h",
+ "windDirection": "S",
+ "icon": "https://api.weather.gov/icons/land/night/bkn?size=small",
+ "shortForecast": "Mostly Cloudy",
+ "detailedForecast": ""
+ },
+ {
+ "number": 80,
+ "name": "",
+ "startTime": "2026-02-09T23:00:00-05:00",
+ "endTime": "2026-02-10T00:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -4,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -8.88888888888889
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 71
+ },
+ "windSpeed": "2 km/h",
+ "windDirection": "SE",
+ "icon": "https://api.weather.gov/icons/land/night/bkn?size=small",
+ "shortForecast": "Mostly Cloudy",
+ "detailedForecast": ""
+ },
+ {
+ "number": 81,
+ "name": "",
+ "startTime": "2026-02-10T00:00:00-05:00",
+ "endTime": "2026-02-10T01:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -4,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -8.88888888888889
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 71
+ },
+ "windSpeed": "2 km/h",
+ "windDirection": "NE",
+ "icon": "https://api.weather.gov/icons/land/night/bkn?size=small",
+ "shortForecast": "Mostly Cloudy",
+ "detailedForecast": ""
+ },
+ {
+ "number": 82,
+ "name": "",
+ "startTime": "2026-02-10T01:00:00-05:00",
+ "endTime": "2026-02-10T02:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -5,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -8.88888888888889
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 74
+ },
+ "windSpeed": "2 km/h",
+ "windDirection": "N",
+ "icon": "https://api.weather.gov/icons/land/night/bkn?size=small",
+ "shortForecast": "Mostly Cloudy",
+ "detailedForecast": ""
+ },
+ {
+ "number": 83,
+ "name": "",
+ "startTime": "2026-02-10T02:00:00-05:00",
+ "endTime": "2026-02-10T03:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -5,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -8.88888888888889
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 74
+ },
+ "windSpeed": "2 km/h",
+ "windDirection": "N",
+ "icon": "https://api.weather.gov/icons/land/night/bkn?size=small",
+ "shortForecast": "Mostly Cloudy",
+ "detailedForecast": ""
+ },
+ {
+ "number": 84,
+ "name": "",
+ "startTime": "2026-02-10T03:00:00-05:00",
+ "endTime": "2026-02-10T04:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -6,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -8.88888888888889
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 77
+ },
+ "windSpeed": "2 km/h",
+ "windDirection": "N",
+ "icon": "https://api.weather.gov/icons/land/night/bkn?size=small",
+ "shortForecast": "Mostly Cloudy",
+ "detailedForecast": ""
+ },
+ {
+ "number": 85,
+ "name": "",
+ "startTime": "2026-02-10T04:00:00-05:00",
+ "endTime": "2026-02-10T05:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -6,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -8.88888888888889
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 77
+ },
+ "windSpeed": "2 km/h",
+ "windDirection": "N",
+ "icon": "https://api.weather.gov/icons/land/night/bkn?size=small",
+ "shortForecast": "Mostly Cloudy",
+ "detailedForecast": ""
+ },
+ {
+ "number": 86,
+ "name": "",
+ "startTime": "2026-02-10T05:00:00-05:00",
+ "endTime": "2026-02-10T06:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -6,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -8.88888888888889
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 77
+ },
+ "windSpeed": "2 km/h",
+ "windDirection": "N",
+ "icon": "https://api.weather.gov/icons/land/night/bkn?size=small",
+ "shortForecast": "Mostly Cloudy",
+ "detailedForecast": ""
+ },
+ {
+ "number": 87,
+ "name": "",
+ "startTime": "2026-02-10T06:00:00-05:00",
+ "endTime": "2026-02-10T07:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -6,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -8.88888888888889
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 77
+ },
+ "windSpeed": "2 km/h",
+ "windDirection": "N",
+ "icon": "https://api.weather.gov/icons/land/day/bkn?size=small",
+ "shortForecast": "Partly Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 88,
+ "name": "",
+ "startTime": "2026-02-10T07:00:00-05:00",
+ "endTime": "2026-02-10T08:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -5,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -8.333333333333334
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 77
+ },
+ "windSpeed": "2 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/bkn?size=small",
+ "shortForecast": "Partly Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 89,
+ "name": "",
+ "startTime": "2026-02-10T08:00:00-05:00",
+ "endTime": "2026-02-10T09:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -4,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -7.777777777777778
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 74
+ },
+ "windSpeed": "2 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/bkn?size=small",
+ "shortForecast": "Partly Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 90,
+ "name": "",
+ "startTime": "2026-02-10T09:00:00-05:00",
+ "endTime": "2026-02-10T10:00:00-05:00",
+ "isDaytime": true,
+ "temperature": -2,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -6.666666666666667
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 69
+ },
+ "windSpeed": "2 km/h",
+ "windDirection": "W",
+ "icon": "https://api.weather.gov/icons/land/day/bkn?size=small",
+ "shortForecast": "Partly Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 91,
+ "name": "",
+ "startTime": "2026-02-10T10:00:00-05:00",
+ "endTime": "2026-02-10T11:00:00-05:00",
+ "isDaytime": true,
+ "temperature": 1,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -5.555555555555555
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 63
+ },
+ "windSpeed": "4 km/h",
+ "windDirection": "W",
+ "icon": "https://api.weather.gov/icons/land/day/bkn?size=small",
+ "shortForecast": "Partly Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 92,
+ "name": "",
+ "startTime": "2026-02-10T11:00:00-05:00",
+ "endTime": "2026-02-10T12:00:00-05:00",
+ "isDaytime": true,
+ "temperature": 2,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -4.444444444444445
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 61
+ },
+ "windSpeed": "4 km/h",
+ "windDirection": "W",
+ "icon": "https://api.weather.gov/icons/land/day/sct?size=small",
+ "shortForecast": "Mostly Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 93,
+ "name": "",
+ "startTime": "2026-02-10T12:00:00-05:00",
+ "endTime": "2026-02-10T13:00:00-05:00",
+ "isDaytime": true,
+ "temperature": 4,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 0
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -3.888888888888889
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 57
+ },
+ "windSpeed": "6 km/h",
+ "windDirection": "W",
+ "icon": "https://api.weather.gov/icons/land/day/sct?size=small",
+ "shortForecast": "Mostly Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 94,
+ "name": "",
+ "startTime": "2026-02-10T13:00:00-05:00",
+ "endTime": "2026-02-10T14:00:00-05:00",
+ "isDaytime": true,
+ "temperature": 5,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 1
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -3.3333333333333335
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 55
+ },
+ "windSpeed": "6 km/h",
+ "windDirection": "W",
+ "icon": "https://api.weather.gov/icons/land/day/sct?size=small",
+ "shortForecast": "Mostly Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 95,
+ "name": "",
+ "startTime": "2026-02-10T14:00:00-05:00",
+ "endTime": "2026-02-10T15:00:00-05:00",
+ "isDaytime": true,
+ "temperature": 6,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 1
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -2.7777777777777777
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 55
+ },
+ "windSpeed": "6 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/few?size=small",
+ "shortForecast": "Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 96,
+ "name": "",
+ "startTime": "2026-02-10T15:00:00-05:00",
+ "endTime": "2026-02-10T16:00:00-05:00",
+ "isDaytime": true,
+ "temperature": 6,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 1
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -2.2222222222222223
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 55
+ },
+ "windSpeed": "6 km/h",
+ "windDirection": "NE",
+ "icon": "https://api.weather.gov/icons/land/day/few?size=small",
+ "shortForecast": "Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 97,
+ "name": "",
+ "startTime": "2026-02-10T16:00:00-05:00",
+ "endTime": "2026-02-10T17:00:00-05:00",
+ "isDaytime": true,
+ "temperature": 6,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 1
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -2.2222222222222223
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 55
+ },
+ "windSpeed": "4 km/h",
+ "windDirection": "NE",
+ "icon": "https://api.weather.gov/icons/land/day/few?size=small",
+ "shortForecast": "Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 98,
+ "name": "",
+ "startTime": "2026-02-10T17:00:00-05:00",
+ "endTime": "2026-02-10T18:00:00-05:00",
+ "isDaytime": true,
+ "temperature": 6,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 1
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -2.2222222222222223
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 57
+ },
+ "windSpeed": "4 km/h",
+ "windDirection": "E",
+ "icon": "https://api.weather.gov/icons/land/day/sct?size=small",
+ "shortForecast": "Mostly Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 99,
+ "name": "",
+ "startTime": "2026-02-10T18:00:00-05:00",
+ "endTime": "2026-02-10T19:00:00-05:00",
+ "isDaytime": false,
+ "temperature": 4,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 1
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -2.7777777777777777
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 59
+ },
+ "windSpeed": "4 km/h",
+ "windDirection": "E",
+ "icon": "https://api.weather.gov/icons/land/night/sct?size=small",
+ "shortForecast": "Partly Cloudy",
+ "detailedForecast": ""
+ },
+ {
+ "number": 100,
+ "name": "",
+ "startTime": "2026-02-10T19:00:00-05:00",
+ "endTime": "2026-02-10T20:00:00-05:00",
+ "isDaytime": false,
+ "temperature": 3,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 6
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -2.7777777777777777
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 67
+ },
+ "windSpeed": "4 km/h",
+ "windDirection": "E",
+ "icon": "https://api.weather.gov/icons/land/night/bkn?size=small",
+ "shortForecast": "Mostly Cloudy",
+ "detailedForecast": ""
+ },
+ {
+ "number": 101,
+ "name": "",
+ "startTime": "2026-02-10T20:00:00-05:00",
+ "endTime": "2026-02-10T21:00:00-05:00",
+ "isDaytime": false,
+ "temperature": 2,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 6
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -2.7777777777777777
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 69
+ },
+ "windSpeed": "2 km/h",
+ "windDirection": "E",
+ "icon": "https://api.weather.gov/icons/land/night/bkn?size=small",
+ "shortForecast": "Mostly Cloudy",
+ "detailedForecast": ""
+ },
+ {
+ "number": 102,
+ "name": "",
+ "startTime": "2026-02-10T21:00:00-05:00",
+ "endTime": "2026-02-10T22:00:00-05:00",
+ "isDaytime": false,
+ "temperature": 1,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 6
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -2.7777777777777777
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 75
+ },
+ "windSpeed": "4 km/h",
+ "windDirection": "E",
+ "icon": "https://api.weather.gov/icons/land/night/bkn?size=small",
+ "shortForecast": "Mostly Cloudy",
+ "detailedForecast": ""
+ },
+ {
+ "number": 103,
+ "name": "",
+ "startTime": "2026-02-10T22:00:00-05:00",
+ "endTime": "2026-02-10T23:00:00-05:00",
+ "isDaytime": false,
+ "temperature": 1,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 6
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -2.7777777777777777
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 78
+ },
+ "windSpeed": "4 km/h",
+ "windDirection": "E",
+ "icon": "https://api.weather.gov/icons/land/night/bkn?size=small",
+ "shortForecast": "Mostly Cloudy",
+ "detailedForecast": ""
+ },
+ {
+ "number": 104,
+ "name": "",
+ "startTime": "2026-02-10T23:00:00-05:00",
+ "endTime": "2026-02-11T00:00:00-05:00",
+ "isDaytime": false,
+ "temperature": 1,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 6
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -2.7777777777777777
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 78
+ },
+ "windSpeed": "4 km/h",
+ "windDirection": "E",
+ "icon": "https://api.weather.gov/icons/land/night/bkn?size=small",
+ "shortForecast": "Mostly Cloudy",
+ "detailedForecast": ""
+ },
+ {
+ "number": 105,
+ "name": "",
+ "startTime": "2026-02-11T00:00:00-05:00",
+ "endTime": "2026-02-11T01:00:00-05:00",
+ "isDaytime": false,
+ "temperature": 1,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 6
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -2.7777777777777777
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 78
+ },
+ "windSpeed": "2 km/h",
+ "windDirection": "E",
+ "icon": "https://api.weather.gov/icons/land/night/bkn?size=small",
+ "shortForecast": "Mostly Cloudy",
+ "detailedForecast": ""
+ },
+ {
+ "number": 106,
+ "name": "",
+ "startTime": "2026-02-11T01:00:00-05:00",
+ "endTime": "2026-02-11T02:00:00-05:00",
+ "isDaytime": false,
+ "temperature": 1,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 18
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -2.7777777777777777
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 78
+ },
+ "windSpeed": "4 km/h",
+ "windDirection": "E",
+ "icon": "https://api.weather.gov/icons/land/night/rain,20?size=small",
+ "shortForecast": "Slight Chance Light Rain",
+ "detailedForecast": ""
+ },
+ {
+ "number": 107,
+ "name": "",
+ "startTime": "2026-02-11T02:00:00-05:00",
+ "endTime": "2026-02-11T03:00:00-05:00",
+ "isDaytime": false,
+ "temperature": 0,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 18
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -2.7777777777777777
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 81
+ },
+ "windSpeed": "4 km/h",
+ "windDirection": "SE",
+ "icon": "https://api.weather.gov/icons/land/night/rain,20?size=small",
+ "shortForecast": "Slight Chance Light Rain",
+ "detailedForecast": ""
+ },
+ {
+ "number": 108,
+ "name": "",
+ "startTime": "2026-02-11T03:00:00-05:00",
+ "endTime": "2026-02-11T04:00:00-05:00",
+ "isDaytime": false,
+ "temperature": 0,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 18
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -2.2222222222222223
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 85
+ },
+ "windSpeed": "4 km/h",
+ "windDirection": "SE",
+ "icon": "https://api.weather.gov/icons/land/night/rain,20?size=small",
+ "shortForecast": "Slight Chance Light Rain",
+ "detailedForecast": ""
+ },
+ {
+ "number": 109,
+ "name": "",
+ "startTime": "2026-02-11T04:00:00-05:00",
+ "endTime": "2026-02-11T05:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -1,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 18
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -2.2222222222222223
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 88
+ },
+ "windSpeed": "4 km/h",
+ "windDirection": "SE",
+ "icon": "https://api.weather.gov/icons/land/night/rain,20?size=small",
+ "shortForecast": "Slight Chance Light Rain",
+ "detailedForecast": ""
+ },
+ {
+ "number": 110,
+ "name": "",
+ "startTime": "2026-02-11T05:00:00-05:00",
+ "endTime": "2026-02-11T06:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -1,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 18
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -2.2222222222222223
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 88
+ },
+ "windSpeed": "4 km/h",
+ "windDirection": "S",
+ "icon": "https://api.weather.gov/icons/land/night/rain,20?size=small",
+ "shortForecast": "Slight Chance Light Rain",
+ "detailedForecast": ""
+ },
+ {
+ "number": 111,
+ "name": "",
+ "startTime": "2026-02-11T06:00:00-05:00",
+ "endTime": "2026-02-11T07:00:00-05:00",
+ "isDaytime": true,
+ "temperature": 0,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 18
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -2.2222222222222223
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 85
+ },
+ "windSpeed": "4 km/h",
+ "windDirection": "S",
+ "icon": "https://api.weather.gov/icons/land/day/rain,20?size=small",
+ "shortForecast": "Slight Chance Light Rain",
+ "detailedForecast": ""
+ },
+ {
+ "number": 112,
+ "name": "",
+ "startTime": "2026-02-11T07:00:00-05:00",
+ "endTime": "2026-02-11T08:00:00-05:00",
+ "isDaytime": true,
+ "temperature": 1,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 49
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -1.6666666666666667
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 85
+ },
+ "windSpeed": "4 km/h",
+ "windDirection": "SW",
+ "icon": "https://api.weather.gov/icons/land/day/rain,50?size=small",
+ "shortForecast": "Chance Light Rain",
+ "detailedForecast": ""
+ },
+ {
+ "number": 113,
+ "name": "",
+ "startTime": "2026-02-11T08:00:00-05:00",
+ "endTime": "2026-02-11T09:00:00-05:00",
+ "isDaytime": true,
+ "temperature": 1,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 49
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -1.1111111111111112
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 85
+ },
+ "windSpeed": "6 km/h",
+ "windDirection": "SW",
+ "icon": "https://api.weather.gov/icons/land/day/rain,50?size=small",
+ "shortForecast": "Chance Light Rain",
+ "detailedForecast": ""
+ },
+ {
+ "number": 114,
+ "name": "",
+ "startTime": "2026-02-11T09:00:00-05:00",
+ "endTime": "2026-02-11T10:00:00-05:00",
+ "isDaytime": true,
+ "temperature": 2,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 49
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": 0
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 85
+ },
+ "windSpeed": "6 km/h",
+ "windDirection": "SW",
+ "icon": "https://api.weather.gov/icons/land/day/rain,50?size=small",
+ "shortForecast": "Chance Light Rain",
+ "detailedForecast": ""
+ },
+ {
+ "number": 115,
+ "name": "",
+ "startTime": "2026-02-11T10:00:00-05:00",
+ "endTime": "2026-02-11T11:00:00-05:00",
+ "isDaytime": true,
+ "temperature": 3,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 49
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": 0.5555555555555556
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 82
+ },
+ "windSpeed": "7 km/h",
+ "windDirection": "W",
+ "icon": "https://api.weather.gov/icons/land/day/rain,50?size=small",
+ "shortForecast": "Chance Light Rain",
+ "detailedForecast": ""
+ },
+ {
+ "number": 116,
+ "name": "",
+ "startTime": "2026-02-11T11:00:00-05:00",
+ "endTime": "2026-02-11T12:00:00-05:00",
+ "isDaytime": true,
+ "temperature": 4,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 49
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": 1.1111111111111112
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 79
+ },
+ "windSpeed": "7 km/h",
+ "windDirection": "W",
+ "icon": "https://api.weather.gov/icons/land/day/rain,50?size=small",
+ "shortForecast": "Chance Light Rain",
+ "detailedForecast": ""
+ },
+ {
+ "number": 117,
+ "name": "",
+ "startTime": "2026-02-11T12:00:00-05:00",
+ "endTime": "2026-02-11T13:00:00-05:00",
+ "isDaytime": true,
+ "temperature": 5,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 49
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": 1.1111111111111112
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 76
+ },
+ "windSpeed": "9 km/h",
+ "windDirection": "W",
+ "icon": "https://api.weather.gov/icons/land/day/rain,50?size=small",
+ "shortForecast": "Chance Light Rain",
+ "detailedForecast": ""
+ },
+ {
+ "number": 118,
+ "name": "",
+ "startTime": "2026-02-11T13:00:00-05:00",
+ "endTime": "2026-02-11T14:00:00-05:00",
+ "isDaytime": true,
+ "temperature": 6,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 50
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": 1.1111111111111112
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 70
+ },
+ "windSpeed": "9 km/h",
+ "windDirection": "W",
+ "icon": "https://api.weather.gov/icons/land/day/rain,50?size=small",
+ "shortForecast": "Chance Light Rain",
+ "detailedForecast": ""
+ },
+ {
+ "number": 119,
+ "name": "",
+ "startTime": "2026-02-11T14:00:00-05:00",
+ "endTime": "2026-02-11T15:00:00-05:00",
+ "isDaytime": true,
+ "temperature": 7,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 50
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": 1.1111111111111112
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 68
+ },
+ "windSpeed": "11 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/rain,50?size=small",
+ "shortForecast": "Chance Light Rain",
+ "detailedForecast": ""
+ },
+ {
+ "number": 120,
+ "name": "",
+ "startTime": "2026-02-11T15:00:00-05:00",
+ "endTime": "2026-02-11T16:00:00-05:00",
+ "isDaytime": true,
+ "temperature": 7,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 50
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": 1.6666666666666667
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 70
+ },
+ "windSpeed": "11 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/rain,50?size=small",
+ "shortForecast": "Chance Light Rain",
+ "detailedForecast": ""
+ },
+ {
+ "number": 121,
+ "name": "",
+ "startTime": "2026-02-11T16:00:00-05:00",
+ "endTime": "2026-02-11T17:00:00-05:00",
+ "isDaytime": true,
+ "temperature": 7,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 50
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": 1.6666666666666667
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 70
+ },
+ "windSpeed": "11 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/rain,50?size=small",
+ "shortForecast": "Chance Light Rain",
+ "detailedForecast": ""
+ },
+ {
+ "number": 122,
+ "name": "",
+ "startTime": "2026-02-11T17:00:00-05:00",
+ "endTime": "2026-02-11T18:00:00-05:00",
+ "isDaytime": true,
+ "temperature": 7,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 50
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": 1.6666666666666667
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 70
+ },
+ "windSpeed": "9 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/rain,50?size=small",
+ "shortForecast": "Chance Light Rain",
+ "detailedForecast": ""
+ },
+ {
+ "number": 123,
+ "name": "",
+ "startTime": "2026-02-11T18:00:00-05:00",
+ "endTime": "2026-02-11T19:00:00-05:00",
+ "isDaytime": false,
+ "temperature": 6,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 50
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": 1.1111111111111112
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 73
+ },
+ "windSpeed": "9 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/rain,50?size=small",
+ "shortForecast": "Chance Light Rain",
+ "detailedForecast": ""
+ },
+ {
+ "number": 124,
+ "name": "",
+ "startTime": "2026-02-11T19:00:00-05:00",
+ "endTime": "2026-02-11T20:00:00-05:00",
+ "isDaytime": false,
+ "temperature": 5,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 34
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": 0.5555555555555556
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 73
+ },
+ "windSpeed": "9 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/rain,30?size=small",
+ "shortForecast": "Chance Light Rain",
+ "detailedForecast": ""
+ },
+ {
+ "number": 125,
+ "name": "",
+ "startTime": "2026-02-11T20:00:00-05:00",
+ "endTime": "2026-02-11T21:00:00-05:00",
+ "isDaytime": false,
+ "temperature": 4,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 34
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": 0
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 73
+ },
+ "windSpeed": "9 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/rain,30?size=small",
+ "shortForecast": "Chance Light Rain",
+ "detailedForecast": ""
+ },
+ {
+ "number": 126,
+ "name": "",
+ "startTime": "2026-02-11T21:00:00-05:00",
+ "endTime": "2026-02-11T22:00:00-05:00",
+ "isDaytime": false,
+ "temperature": 3,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 34
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -0.5555555555555556
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 76
+ },
+ "windSpeed": "9 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/rain,30?size=small",
+ "shortForecast": "Chance Light Rain",
+ "detailedForecast": ""
+ },
+ {
+ "number": 127,
+ "name": "",
+ "startTime": "2026-02-11T22:00:00-05:00",
+ "endTime": "2026-02-11T23:00:00-05:00",
+ "isDaytime": false,
+ "temperature": 3,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 34
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -1.1111111111111112
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 75
+ },
+ "windSpeed": "9 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/rain,30?size=small",
+ "shortForecast": "Chance Light Rain",
+ "detailedForecast": ""
+ },
+ {
+ "number": 128,
+ "name": "",
+ "startTime": "2026-02-11T23:00:00-05:00",
+ "endTime": "2026-02-12T00:00:00-05:00",
+ "isDaytime": false,
+ "temperature": 2,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 34
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -1.6666666666666667
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 75
+ },
+ "windSpeed": "9 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/rain,30?size=small",
+ "shortForecast": "Chance Light Rain",
+ "detailedForecast": ""
+ },
+ {
+ "number": 129,
+ "name": "",
+ "startTime": "2026-02-12T00:00:00-05:00",
+ "endTime": "2026-02-12T01:00:00-05:00",
+ "isDaytime": false,
+ "temperature": 2,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 34
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -1.6666666666666667
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 75
+ },
+ "windSpeed": "9 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/rain,30?size=small",
+ "shortForecast": "Chance Light Rain",
+ "detailedForecast": ""
+ },
+ {
+ "number": 130,
+ "name": "",
+ "startTime": "2026-02-12T01:00:00-05:00",
+ "endTime": "2026-02-12T02:00:00-05:00",
+ "isDaytime": false,
+ "temperature": 2,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 27
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -2.2222222222222223
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 75
+ },
+ "windSpeed": "9 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/rain,30?size=small",
+ "shortForecast": "Chance Light Rain",
+ "detailedForecast": ""
+ },
+ {
+ "number": 131,
+ "name": "",
+ "startTime": "2026-02-12T02:00:00-05:00",
+ "endTime": "2026-02-12T03:00:00-05:00",
+ "isDaytime": false,
+ "temperature": 1,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 27
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -2.2222222222222223
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 78
+ },
+ "windSpeed": "11 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/rain,30?size=small",
+ "shortForecast": "Chance Light Rain",
+ "detailedForecast": ""
+ },
+ {
+ "number": 132,
+ "name": "",
+ "startTime": "2026-02-12T03:00:00-05:00",
+ "endTime": "2026-02-12T04:00:00-05:00",
+ "isDaytime": false,
+ "temperature": 1,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 27
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -2.7777777777777777
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 75
+ },
+ "windSpeed": "11 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/rain,30?size=small",
+ "shortForecast": "Chance Light Rain",
+ "detailedForecast": ""
+ },
+ {
+ "number": 133,
+ "name": "",
+ "startTime": "2026-02-12T04:00:00-05:00",
+ "endTime": "2026-02-12T05:00:00-05:00",
+ "isDaytime": false,
+ "temperature": 1,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 27
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -2.7777777777777777
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 78
+ },
+ "windSpeed": "11 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/rain,30?size=small",
+ "shortForecast": "Chance Light Rain",
+ "detailedForecast": ""
+ },
+ {
+ "number": 134,
+ "name": "",
+ "startTime": "2026-02-12T05:00:00-05:00",
+ "endTime": "2026-02-12T06:00:00-05:00",
+ "isDaytime": false,
+ "temperature": 1,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 27
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -2.7777777777777777
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 78
+ },
+ "windSpeed": "11 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/rain,30?size=small",
+ "shortForecast": "Chance Light Rain",
+ "detailedForecast": ""
+ },
+ {
+ "number": 135,
+ "name": "",
+ "startTime": "2026-02-12T06:00:00-05:00",
+ "endTime": "2026-02-12T07:00:00-05:00",
+ "isDaytime": true,
+ "temperature": 0,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 27
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -3.3333333333333335
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 78
+ },
+ "windSpeed": "11 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/rain,30?size=small",
+ "shortForecast": "Chance Light Rain",
+ "detailedForecast": ""
+ },
+ {
+ "number": 136,
+ "name": "",
+ "startTime": "2026-02-12T07:00:00-05:00",
+ "endTime": "2026-02-12T08:00:00-05:00",
+ "isDaytime": true,
+ "temperature": 0,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 21
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -3.3333333333333335
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 78
+ },
+ "windSpeed": "11 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/rain,20?size=small",
+ "shortForecast": "Slight Chance Light Rain",
+ "detailedForecast": ""
+ },
+ {
+ "number": 137,
+ "name": "",
+ "startTime": "2026-02-12T08:00:00-05:00",
+ "endTime": "2026-02-12T09:00:00-05:00",
+ "isDaytime": true,
+ "temperature": 1,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 21
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -3.3333333333333335
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 75
+ },
+ "windSpeed": "13 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/rain,20?size=small",
+ "shortForecast": "Slight Chance Light Rain",
+ "detailedForecast": ""
+ },
+ {
+ "number": 138,
+ "name": "",
+ "startTime": "2026-02-12T09:00:00-05:00",
+ "endTime": "2026-02-12T10:00:00-05:00",
+ "isDaytime": true,
+ "temperature": 1,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 21
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -3.3333333333333335
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 72
+ },
+ "windSpeed": "15 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/rain,20?size=small",
+ "shortForecast": "Slight Chance Light Rain",
+ "detailedForecast": ""
+ },
+ {
+ "number": 139,
+ "name": "",
+ "startTime": "2026-02-12T10:00:00-05:00",
+ "endTime": "2026-02-12T11:00:00-05:00",
+ "isDaytime": true,
+ "temperature": 2,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 21
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -3.3333333333333335
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 67
+ },
+ "windSpeed": "17 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/rain,20?size=small",
+ "shortForecast": "Slight Chance Light Rain",
+ "detailedForecast": ""
+ },
+ {
+ "number": 140,
+ "name": "",
+ "startTime": "2026-02-12T11:00:00-05:00",
+ "endTime": "2026-02-12T12:00:00-05:00",
+ "isDaytime": true,
+ "temperature": 3,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 21
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -3.3333333333333335
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 64
+ },
+ "windSpeed": "17 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/rain,20?size=small",
+ "shortForecast": "Slight Chance Light Rain",
+ "detailedForecast": ""
+ },
+ {
+ "number": 141,
+ "name": "",
+ "startTime": "2026-02-12T12:00:00-05:00",
+ "endTime": "2026-02-12T13:00:00-05:00",
+ "isDaytime": true,
+ "temperature": 3,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 21
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -3.888888888888889
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 59
+ },
+ "windSpeed": "17 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/rain,20?size=small",
+ "shortForecast": "Slight Chance Light Rain",
+ "detailedForecast": ""
+ },
+ {
+ "number": 142,
+ "name": "",
+ "startTime": "2026-02-12T13:00:00-05:00",
+ "endTime": "2026-02-12T14:00:00-05:00",
+ "isDaytime": true,
+ "temperature": 3,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 14
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -3.888888888888889
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 59
+ },
+ "windSpeed": "17 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/bkn?size=small",
+ "shortForecast": "Partly Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 143,
+ "name": "",
+ "startTime": "2026-02-12T14:00:00-05:00",
+ "endTime": "2026-02-12T15:00:00-05:00",
+ "isDaytime": true,
+ "temperature": 4,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 14
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -4.444444444444445
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 54
+ },
+ "windSpeed": "17 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/bkn?size=small",
+ "shortForecast": "Partly Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 144,
+ "name": "",
+ "startTime": "2026-02-12T15:00:00-05:00",
+ "endTime": "2026-02-12T16:00:00-05:00",
+ "isDaytime": true,
+ "temperature": 4,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 14
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -4.444444444444445
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 52
+ },
+ "windSpeed": "17 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/bkn?size=small",
+ "shortForecast": "Partly Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 145,
+ "name": "",
+ "startTime": "2026-02-12T16:00:00-05:00",
+ "endTime": "2026-02-12T17:00:00-05:00",
+ "isDaytime": true,
+ "temperature": 4,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 14
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -5
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 50
+ },
+ "windSpeed": "17 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/bkn?size=small",
+ "shortForecast": "Partly Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 146,
+ "name": "",
+ "startTime": "2026-02-12T17:00:00-05:00",
+ "endTime": "2026-02-12T18:00:00-05:00",
+ "isDaytime": true,
+ "temperature": 4,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 14
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -5
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 52
+ },
+ "windSpeed": "15 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/day/bkn?size=small",
+ "shortForecast": "Partly Sunny",
+ "detailedForecast": ""
+ },
+ {
+ "number": 147,
+ "name": "",
+ "startTime": "2026-02-12T18:00:00-05:00",
+ "endTime": "2026-02-12T19:00:00-05:00",
+ "isDaytime": false,
+ "temperature": 3,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 14
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -5.555555555555555
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 54
+ },
+ "windSpeed": "13 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/bkn?size=small",
+ "shortForecast": "Mostly Cloudy",
+ "detailedForecast": ""
+ },
+ {
+ "number": 148,
+ "name": "",
+ "startTime": "2026-02-12T19:00:00-05:00",
+ "endTime": "2026-02-12T20:00:00-05:00",
+ "isDaytime": false,
+ "temperature": 2,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 16
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -5.555555555555555
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 59
+ },
+ "windSpeed": "11 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/snow,20?size=small",
+ "shortForecast": "Slight Chance Light Snow",
+ "detailedForecast": ""
+ },
+ {
+ "number": 149,
+ "name": "",
+ "startTime": "2026-02-12T20:00:00-05:00",
+ "endTime": "2026-02-12T21:00:00-05:00",
+ "isDaytime": false,
+ "temperature": 1,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 16
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -5.555555555555555
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 61
+ },
+ "windSpeed": "11 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/snow,20?size=small",
+ "shortForecast": "Slight Chance Light Snow",
+ "detailedForecast": ""
+ },
+ {
+ "number": 150,
+ "name": "",
+ "startTime": "2026-02-12T21:00:00-05:00",
+ "endTime": "2026-02-12T22:00:00-05:00",
+ "isDaytime": false,
+ "temperature": 0,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 16
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -6.111111111111111
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 63
+ },
+ "windSpeed": "11 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/snow,20?size=small",
+ "shortForecast": "Slight Chance Light Snow",
+ "detailedForecast": ""
+ },
+ {
+ "number": 151,
+ "name": "",
+ "startTime": "2026-02-12T22:00:00-05:00",
+ "endTime": "2026-02-12T23:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -1,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 16
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -6.111111111111111
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 66
+ },
+ "windSpeed": "11 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/snow,20?size=small",
+ "shortForecast": "Slight Chance Light Snow",
+ "detailedForecast": ""
+ },
+ {
+ "number": 152,
+ "name": "",
+ "startTime": "2026-02-12T23:00:00-05:00",
+ "endTime": "2026-02-13T00:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -1,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 16
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -6.111111111111111
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 69
+ },
+ "windSpeed": "9 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/snow,20?size=small",
+ "shortForecast": "Slight Chance Light Snow",
+ "detailedForecast": ""
+ },
+ {
+ "number": 153,
+ "name": "",
+ "startTime": "2026-02-13T00:00:00-05:00",
+ "endTime": "2026-02-13T01:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -1,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 16
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -6.666666666666667
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 66
+ },
+ "windSpeed": "9 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/snow,20?size=small",
+ "shortForecast": "Slight Chance Light Snow",
+ "detailedForecast": ""
+ },
+ {
+ "number": 154,
+ "name": "",
+ "startTime": "2026-02-13T01:00:00-05:00",
+ "endTime": "2026-02-13T02:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -2,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 21
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -6.666666666666667
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 69
+ },
+ "windSpeed": "9 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/snow,20?size=small",
+ "shortForecast": "Slight Chance Light Snow",
+ "detailedForecast": ""
+ },
+ {
+ "number": 155,
+ "name": "",
+ "startTime": "2026-02-13T02:00:00-05:00",
+ "endTime": "2026-02-13T03:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -2,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 21
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -6.666666666666667
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 71
+ },
+ "windSpeed": "11 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/snow,20?size=small",
+ "shortForecast": "Slight Chance Light Snow",
+ "detailedForecast": ""
+ },
+ {
+ "number": 156,
+ "name": "",
+ "startTime": "2026-02-13T03:00:00-05:00",
+ "endTime": "2026-02-13T04:00:00-05:00",
+ "isDaytime": false,
+ "temperature": -2,
+ "temperatureUnit": "C",
+ "temperatureTrend": null,
+ "probabilityOfPrecipitation": {
+ "unitCode": "wmoUnit:percent",
+ "value": 21
+ },
+ "dewpoint": {
+ "unitCode": "wmoUnit:degC",
+ "value": -7.222222222222222
+ },
+ "relativeHumidity": {
+ "unitCode": "wmoUnit:percent",
+ "value": 68
+ },
+ "windSpeed": "11 km/h",
+ "windDirection": "NW",
+ "icon": "https://api.weather.gov/icons/land/night/snow,20?size=small",
+ "shortForecast": "Slight Chance Light Snow",
+ "detailedForecast": ""
+ }
+ ]
+ }
+}
diff --git a/tests/mocks/weather_weathergov_points.json b/tests/mocks/weather_weathergov_points.json
new file mode 100644
index 00000000..d1379489
--- /dev/null
+++ b/tests/mocks/weather_weathergov_points.json
@@ -0,0 +1,89 @@
+{
+ "@context": [
+ "https://geojson.org/geojson-ld/geojson-context.jsonld",
+ {
+ "@version": "1.1",
+ "wx": "https://api.weather.gov/ontology#",
+ "s": "https://schema.org/",
+ "geo": "http://www.opengis.net/ont/geosparql#",
+ "unit": "http://codes.wmo.int/common/unit/",
+ "@vocab": "https://api.weather.gov/ontology#",
+ "geometry": {
+ "@id": "s:GeoCoordinates",
+ "@type": "geo:wktLiteral"
+ },
+ "city": "s:addressLocality",
+ "state": "s:addressRegion",
+ "distance": {
+ "@id": "s:Distance",
+ "@type": "s:QuantitativeValue"
+ },
+ "bearing": {
+ "@type": "s:QuantitativeValue"
+ },
+ "value": {
+ "@id": "s:value"
+ },
+ "unitCode": {
+ "@id": "s:unitCode",
+ "@type": "@id"
+ },
+ "forecastOffice": {
+ "@type": "@id"
+ },
+ "forecastGridData": {
+ "@type": "@id"
+ },
+ "publicZone": {
+ "@type": "@id"
+ },
+ "county": {
+ "@type": "@id"
+ }
+ }
+ ],
+ "id": "https://api.weather.gov/points/38.8894,-77.0352",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-77.0352, 38.8894]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/points/38.8894,-77.0352",
+ "@type": "wx:Point",
+ "cwa": "LWX",
+ "type": "land",
+ "forecastOffice": "https://api.weather.gov/offices/LWX",
+ "gridId": "LWX",
+ "gridX": 97,
+ "gridY": 71,
+ "forecast": "https://api.weather.gov/gridpoints/LWX/97,71/forecast",
+ "forecastHourly": "https://api.weather.gov/gridpoints/LWX/97,71/forecast/hourly",
+ "forecastGridData": "https://api.weather.gov/gridpoints/LWX/97,71",
+ "observationStations": "https://api.weather.gov/gridpoints/LWX/97,71/stations",
+ "relativeLocation": {
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-77.017229, 38.904103]
+ },
+ "properties": {
+ "city": "Washington",
+ "state": "DC",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 2256.4628420106
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 223
+ }
+ }
+ },
+ "forecastZone": "https://api.weather.gov/zones/forecast/DCZ001",
+ "county": "https://api.weather.gov/zones/county/DCC001",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/DCZ001",
+ "timeZone": "America/New_York",
+ "radarStation": "KLWX"
+ }
+}
diff --git a/tests/mocks/weather_weathergov_stations.json b/tests/mocks/weather_weathergov_stations.json
new file mode 100644
index 00000000..742524a6
--- /dev/null
+++ b/tests/mocks/weather_weathergov_stations.json
@@ -0,0 +1,1793 @@
+{
+ "@context": [
+ "https://geojson.org/geojson-ld/geojson-context.jsonld",
+ {
+ "@version": "1.1",
+ "wx": "https://api.weather.gov/ontology#",
+ "s": "https://schema.org/",
+ "geo": "http://www.opengis.net/ont/geosparql#",
+ "unit": "http://codes.wmo.int/common/unit/",
+ "@vocab": "https://api.weather.gov/ontology#",
+ "geometry": {
+ "@id": "s:GeoCoordinates",
+ "@type": "geo:wktLiteral"
+ },
+ "city": "s:addressLocality",
+ "state": "s:addressRegion",
+ "distance": {
+ "@id": "s:Distance",
+ "@type": "s:QuantitativeValue"
+ },
+ "bearing": {
+ "@type": "s:QuantitativeValue"
+ },
+ "value": {
+ "@id": "s:value"
+ },
+ "unitCode": {
+ "@id": "s:unitCode",
+ "@type": "@id"
+ },
+ "forecastOffice": {
+ "@type": "@id"
+ },
+ "forecastGridData": {
+ "@type": "@id"
+ },
+ "publicZone": {
+ "@type": "@id"
+ },
+ "county": {
+ "@type": "@id"
+ },
+ "observationStations": {
+ "@container": "@list",
+ "@type": "@id"
+ }
+ }
+ ],
+ "type": "FeatureCollection",
+ "features": [
+ {
+ "id": "https://api.weather.gov/stations/KDCA",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-77.03417, 38.84833]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KDCA",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 3.9624
+ },
+ "stationIdentifier": "KDCA",
+ "name": "Washington/Reagan National Airport, DC",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 3043.6748842539
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 140
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/VAZ054",
+ "county": "https://api.weather.gov/zones/county/VAC013",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ054"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KCGS",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-76.9223, 38.9806]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KCGS",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 14.9352
+ },
+ "stationIdentifier": "KCGS",
+ "name": "College Park Airport",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 16980.874107362
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 43
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/MDZ013",
+ "county": "https://api.weather.gov/zones/county/MDC033",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/MDZ013"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KADW",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-76.85, 38.81667]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KADW",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 85.9536
+ },
+ "stationIdentifier": "KADW",
+ "name": "Camp Springs / Andrews Air Force Base",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 18837.139622535
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 108
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/MDZ013",
+ "county": "https://api.weather.gov/zones/county/MDC033",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/MDZ013"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KDAA",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-77.18333, 38.71667]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KDAA",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 21.0312
+ },
+ "stationIdentifier": "KDAA",
+ "name": "Fort Belvoir",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 20211.268967046
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 212
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/VAZ053",
+ "county": "https://api.weather.gov/zones/county/VAC059",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ053"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KFME",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-76.76667, 39.08333]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KFME",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 46.0248
+ },
+ "stationIdentifier": "KFME",
+ "name": "Fort Meade / Tipton",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 34568.722953871
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 46
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/MDZ014",
+ "county": "https://api.weather.gov/zones/county/MDC003",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/MDZ014"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KIAD",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-77.4475, 38.93472]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KIAD",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 95.0976
+ },
+ "stationIdentifier": "KIAD",
+ "name": "Washington/Dulles International Airport, DC",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 34587.939860418
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 282
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/VAZ053",
+ "county": "https://api.weather.gov/zones/county/VAC059",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ053"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KGAI",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-77.16551, 39.16957]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KGAI",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 150.876
+ },
+ "stationIdentifier": "KGAI",
+ "name": "Gaithersburg - Montgomery County Airport",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 34683.691088332
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 344
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/MDZ504",
+ "county": "https://api.weather.gov/zones/county/MDC031",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/MDZ504"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KHEF",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-77.51667, 38.71667]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KHEF",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 59.1312
+ },
+ "stationIdentifier": "KHEF",
+ "name": "Manassas, Manassas Regional Airport/Harry P. Davis Field",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 43324.86402354
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 247
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/VAZ527",
+ "county": "https://api.weather.gov/zones/county/VAC683",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ527"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KNYG",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-77.30129, 38.50326]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KNYG",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 2.1336
+ },
+ "stationIdentifier": "KNYG",
+ "name": "Quantico Marine Corps Airfield - Turner Field",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 45906.349012092
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 207
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/VAZ527",
+ "county": "https://api.weather.gov/zones/county/VAC153",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ527"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KBWI",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-76.68404, 39.17329]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KBWI",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 41.148
+ },
+ "stationIdentifier": "KBWI",
+ "name": "Baltimore, Baltimore-Washington International Airport",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 46680.187081868
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 43
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/MDZ014",
+ "county": "https://api.weather.gov/zones/county/MDC003",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/MDZ014"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KJYO",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-77.56667, 39.08333]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KJYO",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 118.872
+ },
+ "stationIdentifier": "KJYO",
+ "name": "Leesburg / Godfrey",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 50093.979211268
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 298
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/VAZ506",
+ "county": "https://api.weather.gov/zones/county/VAC107",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ506"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KNAK",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-76.48907, 38.99125]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KNAK",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 0.9144
+ },
+ "stationIdentifier": "KNAK",
+ "name": "Annapolis, United States Naval Academy",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 50940.029746488
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 74
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/MDZ014",
+ "county": "https://api.weather.gov/zones/county/MDC003",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/MDZ014"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KDMH",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-76.61667, 39.28333]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KDMH",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 6.096
+ },
+ "stationIdentifier": "KDMH",
+ "name": "Baltimore, Inner Harbor",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 59684.848549395
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 39
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/MDZ011",
+ "county": "https://api.weather.gov/zones/county/MDC510",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/MDZ011"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KRMN",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-77.45528, 38.39806]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KRMN",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 64.9224
+ },
+ "stationIdentifier": "KRMN",
+ "name": "Stafford, Stafford Regional Airport",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 62803.929543738
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 213
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/VAZ055",
+ "county": "https://api.weather.gov/zones/county/VAC179",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ055"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KW29",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-76.33, 38.9767]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KW29",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 14.9352
+ },
+ "stationIdentifier": "KW29",
+ "name": "Bay Bridge Field",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 63992.315724071
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 79
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/MDZ015",
+ "county": "https://api.weather.gov/zones/county/MDC035",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/MDZ015"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KHWY",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-77.71501, 38.58765]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KHWY",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 92.0496
+ },
+ "stationIdentifier": "KHWY",
+ "name": "Warrenton-Fauquier Airport",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 65127.84173743
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 241
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/VAZ502",
+ "county": "https://api.weather.gov/zones/county/VAC061",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ502"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KFDK",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-77.36982, 39.41775]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KFDK",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 81.9912
+ },
+ "stationIdentifier": "KFDK",
+ "name": "Frederick Municipal Airport",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 66692.582365459
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 336
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/MDZ004",
+ "county": "https://api.weather.gov/zones/county/MDC021",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/MDZ004"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KEZF",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-77.45, 38.26667]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KEZF",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 25.908
+ },
+ "stationIdentifier": "KEZF",
+ "name": "Fredericksburg, Shannon Airport",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 75229.907706335
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 207
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/VAZ056",
+ "county": "https://api.weather.gov/zones/county/VAC177",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ056"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KMTN",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-76.41667, 39.33333]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KMTN",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 7.0104
+ },
+ "stationIdentifier": "KMTN",
+ "name": "Baltimore / Martin",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 75581.565023524
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 46
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/MDZ011",
+ "county": "https://api.weather.gov/zones/county/MDC005",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/MDZ011"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/K2W6",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-76.5501, 38.3154]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/K2W6",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 43.8912
+ },
+ "stationIdentifier": "K2W6",
+ "name": "St Marys County Airport",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 75712.983389938
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 144
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/MDZ017",
+ "county": "https://api.weather.gov/zones/county/MDC037",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/MDZ017"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KCJR",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-77.85738, 38.52607]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KCJR",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 89.916
+ },
+ "stationIdentifier": "KCJR",
+ "name": "Culpeper Regional Airport",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 79274.931842245
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 241
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/VAZ051",
+ "county": "https://api.weather.gov/zones/county/VAC047",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ051"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KDMW",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-77.0077, 39.6083]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KDMW",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 240.4872
+ },
+ "stationIdentifier": "KDMW",
+ "name": "Carroll County Regional Jack B Poage Field",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 82279.382252508
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 2
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/MDZ005",
+ "county": "https://api.weather.gov/zones/county/MDC013",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/MDZ005"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KESN",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-76.06667, 38.8]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KESN",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 21.9456
+ },
+ "stationIdentifier": "KESN",
+ "name": "Easton Airport",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 86100.892604455
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 94
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/MDZ019",
+ "county": "https://api.weather.gov/zones/county/MDC041",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/MDZ019"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KNHK",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-76.41389, 38.27861]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KNHK",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 11.8872
+ },
+ "stationIdentifier": "KNHK",
+ "name": "Patuxent River, Naval Air Station",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 86239.928763087
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 139
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/MDZ017",
+ "county": "https://api.weather.gov/zones/county/MDC037",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/MDZ017"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KRSP",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-77.468, 39.645]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KRSP",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 561.1368
+ },
+ "stationIdentifier": "KRSP",
+ "name": "Camp David",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 93237.282967055
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 337
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/MDZ004",
+ "county": "https://api.weather.gov/zones/county/MDC021",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/MDZ004"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KNUI",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-76.42, 38.14889]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KNUI",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 6.096
+ },
+ "stationIdentifier": "KNUI",
+ "name": "St. Inigoes, Webster Field, Naval Electronic Systems Engineering Activity",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 97399.572233461
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 145
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/MDZ017",
+ "county": "https://api.weather.gov/zones/county/MDC037",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/MDZ017"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KMRB",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-77.975, 39.40372]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KMRB",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 163.9824
+ },
+ "stationIdentifier": "KMRB",
+ "name": "Eastern WV Regional Airport/Shepherd Field",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 99011.527250549
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 307
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/WVZ052",
+ "county": "https://api.weather.gov/zones/county/WVC003",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/WVZ052"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KOKV",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-78.15, 39.15]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KOKV",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 221.8944
+ },
+ "stationIdentifier": "KOKV",
+ "name": "Winchester Regional",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 99483.258804184
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 288
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/VAZ028",
+ "county": "https://api.weather.gov/zones/county/VAC069",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ028"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KAPG",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-76.16667, 39.46667]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KAPG",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 17.9832
+ },
+ "stationIdentifier": "KAPG",
+ "name": "Phillips Army Air Field / Aberdeen",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 101486.28902381
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 48
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/MDZ508",
+ "county": "https://api.weather.gov/zones/county/MDC025",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/MDZ508"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KFRR",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-78.2535, 38.9175]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KFRR",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 216.1032
+ },
+ "stationIdentifier": "KFRR",
+ "name": "Front Royal-warren County Airport",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 103711.79430435
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 273
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/VAZ030",
+ "county": "https://api.weather.gov/zones/county/VAC187",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ030"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/K0W3",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-76.20297, 39.5682]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/K0W3",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 125.5776
+ },
+ "stationIdentifier": "K0W3",
+ "name": "Harford County Airport",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 106997.11216766
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 43
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/MDZ508",
+ "county": "https://api.weather.gov/zones/county/MDC025",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/MDZ508"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KHGR",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-77.73, 39.70583]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KHGR",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 213.9696
+ },
+ "stationIdentifier": "KHGR",
+ "name": "Hagerstown, Washington County Regional Airport",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 109586.26730048
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 328
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/MDZ003",
+ "county": "https://api.weather.gov/zones/county/MDC043",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/MDZ003"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KOMH",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-78.04556, 38.24722]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KOMH",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 142.0368
+ },
+ "stationIdentifier": "KOMH",
+ "name": "Orange, Orange County Airport",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 110351.40846398
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 231
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/VAZ050",
+ "county": "https://api.weather.gov/zones/county/VAC137",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ050"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/K7W4",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-77.7459, 37.9658]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/K7W4",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 106.9848
+ },
+ "stationIdentifier": "K7W4",
+ "name": "Lake Anna Airport",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 117039.9799578
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 211
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/VAZ510",
+ "county": "https://api.weather.gov/zones/county/VAC109",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ510"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KTHV",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-76.87694, 39.91944]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KTHV",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 145.9992
+ },
+ "stationIdentifier": "KTHV",
+ "name": "York, York Airport",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 117785.75882145
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 7
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/PAZ065",
+ "county": "https://api.weather.gov/zones/county/PAC133",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/PAZ065"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KLKU",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-77.97028, 38.00972]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KLKU",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 149.9616
+ },
+ "stationIdentifier": "KLKU",
+ "name": "Louisa, Louisa County Airport/Freeman Field",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 124364.21495608
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 220
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/VAZ510",
+ "county": "https://api.weather.gov/zones/county/VAC109",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ510"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KGVE",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-78.1658, 38.156]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KGVE",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 138.0744
+ },
+ "stationIdentifier": "KGVE",
+ "name": "Gordonsville Municipal Airport",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 124909.61245374
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 230
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/VAZ050",
+ "county": "https://api.weather.gov/zones/county/VAC137",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ050"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KOFP",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-77.43444, 37.70806]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KOFP",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 61.8744
+ },
+ "stationIdentifier": "KOFP",
+ "name": "Ashland, Hanover County Municipal Airport",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 133267.46930022
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 194
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/VAZ511",
+ "county": "https://api.weather.gov/zones/county/VAC085",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ511"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/K8W2",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-78.7081, 38.6557]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/K8W2",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 297.18
+ },
+ "stationIdentifier": "K8W2",
+ "name": "New Market Airport",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 145135.20416818
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 261
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/VAZ027",
+ "county": "https://api.weather.gov/zones/county/VAC171",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ027"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KCHO",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-78.45516, 38.13738]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KCHO",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 195.072
+ },
+ "stationIdentifier": "KCHO",
+ "name": "Charlottesville-Albemarle Airport",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 146394.21605562
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 236
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/VAZ037",
+ "county": "https://api.weather.gov/zones/county/VAC003",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ037"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KRIC",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-77.32333, 37.51111]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KRIC",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 50.9016
+ },
+ "stationIdentifier": "KRIC",
+ "name": "Richmond, Richmond International Airport",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 152812.69388052
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 188
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/VAZ516",
+ "county": "https://api.weather.gov/zones/county/VAC087",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ516"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KILG",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-75.60567, 39.67442]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KILG",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 21.9456
+ },
+ "stationIdentifier": "KILG",
+ "name": "Wilmington Airport",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 153674.36438971
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 53
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/DEZ001",
+ "county": "https://api.weather.gov/zones/county/DEC003",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/DEZ001"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KLNS",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-76.29446, 40.12058]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KLNS",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 121.0056
+ },
+ "stationIdentifier": "KLNS",
+ "name": "Lancaster, Lancaster Airport",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 153739.95516367
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 24
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/PAZ066",
+ "county": "https://api.weather.gov/zones/county/PAC071",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/PAZ066"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KCBE",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-78.76083, 39.61528]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KCBE",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 235.9152
+ },
+ "stationIdentifier": "KCBE",
+ "name": "Cumberland, Greater Cumberland Regional Airport",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 168568.42779476
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 300
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/WVZ504",
+ "county": "https://api.weather.gov/zones/county/WVC057",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/WVZ504"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KSHD",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-78.9, 38.26667]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KSHD",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 366.0648
+ },
+ "stationIdentifier": "KSHD",
+ "name": "Staunton / Shenandoah",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 173695.8603158
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 247
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/VAZ025",
+ "county": "https://api.weather.gov/zones/county/VAC015",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ025"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KVBW",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-78.96033, 38.36674]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KVBW",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 355.092
+ },
+ "stationIdentifier": "KVBW",
+ "name": "Bridgewater Air Park",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 174565.90990218
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 251
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/VAZ026",
+ "county": "https://api.weather.gov/zones/county/VAC165",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ026"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KMFV",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-75.76667, 37.65]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KMFV",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 14.9352
+ },
+ "stationIdentifier": "KMFV",
+ "name": "Melfa / Accomack Airport",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 176261.84200174
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 139
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/VAZ099",
+ "county": "https://api.weather.gov/zones/county/VAC001",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ099"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KW13",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-78.9444, 38.0769]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KW13",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 437.9976
+ },
+ "stationIdentifier": "KW13",
+ "name": "Eagles Nest Airport",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 186456.91815645
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 242
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/VAZ025",
+ "county": "https://api.weather.gov/zones/county/VAC015",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ025"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KFVX",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-78.43333, 37.35]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KFVX",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 124.968
+ },
+ "stationIdentifier": "KFVX",
+ "name": "Farmville",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 207471.35283371
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 215
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/VAZ061",
+ "county": "https://api.weather.gov/zones/county/VAC049",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ061"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/K2G4",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-79.3394, 39.5803]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/K2G4",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 893.9784
+ },
+ "stationIdentifier": "K2G4",
+ "name": "Garrett County Airport",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 211917.76730527
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 292
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/MDZ509",
+ "county": "https://api.weather.gov/zones/county/MDC023",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/MDZ509"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/K2G9",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-79.015, 40.0389]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/K2G9",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 693.42
+ },
+ "stationIdentifier": "K2G9",
+ "name": "Somerset County Airport",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 212550.3935379
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 308
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/PAZ033",
+ "county": "https://api.weather.gov/zones/county/PAC111",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/PAZ033"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KEKN",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-79.85278, 38.88528]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KEKN",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 605.028
+ },
+ "stationIdentifier": "KEKN",
+ "name": "Elkins, Elkins-Randolph County-Jennings Randolph Field",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 242035.43677875
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 271
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/WVZ525",
+ "county": "https://api.weather.gov/zones/county/WVC083",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/WVZ525"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KLYH",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-79.20667, 37.32083]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KLYH",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 284.988
+ },
+ "stationIdentifier": "KLYH",
+ "name": "Lynchburg, Lynchburg Regional Airport",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 255021.94789795
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 228
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/VAZ045",
+ "county": "https://api.weather.gov/zones/county/VAC031",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ045"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KMGW",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-79.92065, 39.64985]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KMGW",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 373.9896
+ },
+ "stationIdentifier": "KMGW",
+ "name": "Morgantown Municipal-Hart Field",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 261388.09543822
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 290
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/WVZ509",
+ "county": "https://api.weather.gov/zones/county/WVC061",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/WVZ509"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KHSP",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-79.83333, 37.95]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KHSP",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 1156.1064
+ },
+ "stationIdentifier": "KHSP",
+ "name": "Hot Springs / Ingalls",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 262623.28570565
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 247
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/VAZ020",
+ "county": "https://api.weather.gov/zones/county/VAC017",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ020"
+ }
+ },
+ {
+ "id": "https://api.weather.gov/stations/KROA",
+ "type": "Feature",
+ "geometry": {
+ "type": "Point",
+ "coordinates": [-79.97417, 37.31694]
+ },
+ "properties": {
+ "@id": "https://api.weather.gov/stations/KROA",
+ "@type": "wx:ObservationStation",
+ "elevation": {
+ "unitCode": "wmoUnit:m",
+ "value": 358.14
+ },
+ "stationIdentifier": "KROA",
+ "name": "Roanoke, Roanoke Regional Airport",
+ "timeZone": "America/New_York",
+ "distance": {
+ "unitCode": "wmoUnit:m",
+ "value": 308160.42662802
+ },
+ "bearing": {
+ "unitCode": "wmoUnit:degree_(angle)",
+ "value": 236
+ },
+ "forecast": "https://api.weather.gov/zones/forecast/VAZ022",
+ "county": "https://api.weather.gov/zones/county/VAC770",
+ "fireWeatherZone": "https://api.weather.gov/zones/fire/VAZ022"
+ }
+ }
+ ],
+ "observationStations": [
+ "https://api.weather.gov/stations/KDCA",
+ "https://api.weather.gov/stations/KCGS",
+ "https://api.weather.gov/stations/KADW",
+ "https://api.weather.gov/stations/KDAA",
+ "https://api.weather.gov/stations/KFME",
+ "https://api.weather.gov/stations/KIAD",
+ "https://api.weather.gov/stations/KGAI",
+ "https://api.weather.gov/stations/KHEF",
+ "https://api.weather.gov/stations/KNYG",
+ "https://api.weather.gov/stations/KBWI",
+ "https://api.weather.gov/stations/KJYO",
+ "https://api.weather.gov/stations/KNAK",
+ "https://api.weather.gov/stations/KDMH",
+ "https://api.weather.gov/stations/KRMN",
+ "https://api.weather.gov/stations/KW29",
+ "https://api.weather.gov/stations/KHWY",
+ "https://api.weather.gov/stations/KFDK",
+ "https://api.weather.gov/stations/KEZF",
+ "https://api.weather.gov/stations/KMTN",
+ "https://api.weather.gov/stations/K2W6",
+ "https://api.weather.gov/stations/KCJR",
+ "https://api.weather.gov/stations/KDMW",
+ "https://api.weather.gov/stations/KESN",
+ "https://api.weather.gov/stations/KNHK",
+ "https://api.weather.gov/stations/KRSP",
+ "https://api.weather.gov/stations/KNUI",
+ "https://api.weather.gov/stations/KMRB",
+ "https://api.weather.gov/stations/KOKV",
+ "https://api.weather.gov/stations/KAPG",
+ "https://api.weather.gov/stations/KFRR",
+ "https://api.weather.gov/stations/K0W3",
+ "https://api.weather.gov/stations/KHGR",
+ "https://api.weather.gov/stations/KOMH",
+ "https://api.weather.gov/stations/K7W4",
+ "https://api.weather.gov/stations/KTHV",
+ "https://api.weather.gov/stations/KLKU",
+ "https://api.weather.gov/stations/KGVE",
+ "https://api.weather.gov/stations/KOFP",
+ "https://api.weather.gov/stations/K8W2",
+ "https://api.weather.gov/stations/KCHO",
+ "https://api.weather.gov/stations/KRIC",
+ "https://api.weather.gov/stations/KILG",
+ "https://api.weather.gov/stations/KLNS",
+ "https://api.weather.gov/stations/KCBE",
+ "https://api.weather.gov/stations/KSHD",
+ "https://api.weather.gov/stations/KVBW",
+ "https://api.weather.gov/stations/KMFV",
+ "https://api.weather.gov/stations/KW13",
+ "https://api.weather.gov/stations/KFVX",
+ "https://api.weather.gov/stations/K2G4",
+ "https://api.weather.gov/stations/K2G9",
+ "https://api.weather.gov/stations/KEKN",
+ "https://api.weather.gov/stations/KLYH",
+ "https://api.weather.gov/stations/KMGW",
+ "https://api.weather.gov/stations/KHSP",
+ "https://api.weather.gov/stations/KROA"
+ ],
+ "pagination": {
+ "next": "https://api.weather.gov/stations?id%5B0%5D=K0W3&id%5B1%5D=K2G4&id%5B2%5D=K2G9&id%5B3%5D=K2W6&id%5B4%5D=K7W4&id%5B5%5D=K8W2&id%5B6%5D=KADW&id%5B7%5D=KAPG&id%5B8%5D=KBWI&id%5B9%5D=KCBE&id%5B10%5D=KCGS&id%5B11%5D=KCHO&id%5B12%5D=KCJR&id%5B13%5D=KDAA&id%5B14%5D=KDCA&id%5B15%5D=KDMH&id%5B16%5D=KDMW&id%5B17%5D=KEKN&id%5B18%5D=KESN&id%5B19%5D=KEZF&id%5B20%5D=KFDK&id%5B21%5D=KFME&id%5B22%5D=KFRR&id%5B23%5D=KFVX&id%5B24%5D=KGAI&id%5B25%5D=KGVE&id%5B26%5D=KHEF&id%5B27%5D=KHGR&id%5B28%5D=KHSP&id%5B29%5D=KHWY&id%5B30%5D=KIAD&id%5B31%5D=KILG&id%5B32%5D=KJYO&id%5B33%5D=KLKU&id%5B34%5D=KLNS&id%5B35%5D=KLYH&id%5B36%5D=KMFV&id%5B37%5D=KMGW&id%5B38%5D=KMRB&id%5B39%5D=KMTN&id%5B40%5D=KNAK&id%5B41%5D=KNHK&id%5B42%5D=KNUI&id%5B43%5D=KNYG&id%5B44%5D=KOFP&id%5B45%5D=KOKV&id%5B46%5D=KOMH&id%5B47%5D=KRIC&id%5B48%5D=KRMN&id%5B49%5D=KROA&id%5B50%5D=KRSP&id%5B51%5D=KSHD&id%5B52%5D=KTHV&id%5B53%5D=KVBW&id%5B54%5D=KW13&id%5B55%5D=KW29&cursor=eyJzIjo1MDB9"
+ }
+}
diff --git a/tests/mocks/weather_yr.json b/tests/mocks/weather_yr.json
new file mode 100644
index 00000000..3d7dc66d
--- /dev/null
+++ b/tests/mocks/weather_yr.json
@@ -0,0 +1,707 @@
+{
+ "type": "Feature",
+ "geometry": { "type": "Point", "coordinates": [10.7522, 59.9139, 5] },
+ "properties": {
+ "meta": {
+ "updated_at": "2026-02-06T20:27:06Z",
+ "units": { "air_pressure_at_sea_level": "hPa", "air_temperature": "celsius", "cloud_area_fraction": "%", "precipitation_amount": "mm", "relative_humidity": "%", "wind_from_direction": "degrees", "wind_speed": "m/s" }
+ },
+ "timeseries": [
+ {
+ "time": "2026-02-06T21:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1014.6, "air_temperature": -5.8, "cloud_area_fraction": 100.0, "relative_humidity": 66.5, "wind_from_direction": 37.0, "wind_speed": 6.0 } },
+ "next_12_hours": { "summary": { "symbol_code": "lightsnow" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "snow" }, "details": { "precipitation_amount": 0.5 } },
+ "next_6_hours": { "summary": { "symbol_code": "snow" }, "details": { "precipitation_amount": 3.5 } }
+ }
+ },
+ {
+ "time": "2026-02-06T22:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1014.8, "air_temperature": -5.9, "cloud_area_fraction": 100.0, "relative_humidity": 70.5, "wind_from_direction": 39.0, "wind_speed": 6.4 } },
+ "next_12_hours": { "summary": { "symbol_code": "lightsnow" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "snow" }, "details": { "precipitation_amount": 0.7 } },
+ "next_6_hours": { "summary": { "symbol_code": "snow" }, "details": { "precipitation_amount": 3.3 } }
+ }
+ },
+ {
+ "time": "2026-02-06T23:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1015.1, "air_temperature": -5.9, "cloud_area_fraction": 100.0, "relative_humidity": 73.3, "wind_from_direction": 41.0, "wind_speed": 6.6 } },
+ "next_12_hours": { "summary": { "symbol_code": "lightsnow" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "snow" }, "details": { "precipitation_amount": 0.8 } },
+ "next_6_hours": { "summary": { "symbol_code": "snow" }, "details": { "precipitation_amount": 2.6 } }
+ }
+ },
+ {
+ "time": "2026-02-07T00:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1015.4, "air_temperature": -5.8, "cloud_area_fraction": 100.0, "relative_humidity": 74.6, "wind_from_direction": 40.0, "wind_speed": 6.9 } },
+ "next_12_hours": { "summary": { "symbol_code": "lightsnow" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "snow" }, "details": { "precipitation_amount": 0.6 } },
+ "next_6_hours": { "summary": { "symbol_code": "snow" }, "details": { "precipitation_amount": 1.9 } }
+ }
+ },
+ {
+ "time": "2026-02-07T01:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1015.5, "air_temperature": -5.7, "cloud_area_fraction": 100.0, "relative_humidity": 75.5, "wind_from_direction": 41.0, "wind_speed": 6.9 } },
+ "next_12_hours": { "summary": { "symbol_code": "lightsnow" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "snow" }, "details": { "precipitation_amount": 0.5 } },
+ "next_6_hours": { "summary": { "symbol_code": "snow" }, "details": { "precipitation_amount": 1.4 } }
+ }
+ },
+ {
+ "time": "2026-02-07T02:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1015.7, "air_temperature": -5.5, "cloud_area_fraction": 100.0, "relative_humidity": 76.2, "wind_from_direction": 38.0, "wind_speed": 5.6 } },
+ "next_12_hours": { "summary": { "symbol_code": "lightsnow" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "snow" }, "details": { "precipitation_amount": 0.3 } },
+ "next_6_hours": { "summary": { "symbol_code": "lightsnow" }, "details": { "precipitation_amount": 0.9 } }
+ }
+ },
+ {
+ "time": "2026-02-07T03:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1015.7, "air_temperature": -5.3, "cloud_area_fraction": 100.0, "relative_humidity": 76.6, "wind_from_direction": 37.0, "wind_speed": 5.2 } },
+ "next_12_hours": { "summary": { "symbol_code": "lightsnow" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "lightsnow" }, "details": { "precipitation_amount": 0.2 } },
+ "next_6_hours": { "summary": { "symbol_code": "lightsnow" }, "details": { "precipitation_amount": 0.6 } }
+ }
+ },
+ {
+ "time": "2026-02-07T04:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1015.7, "air_temperature": -5.2, "cloud_area_fraction": 100.0, "relative_humidity": 76.1, "wind_from_direction": 36.0, "wind_speed": 4.8 } },
+ "next_12_hours": { "summary": { "symbol_code": "cloudy" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "lightsnow" }, "details": { "precipitation_amount": 0.2 } },
+ "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-07T05:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1015.9, "air_temperature": -5.1, "cloud_area_fraction": 100.0, "relative_humidity": 75.6, "wind_from_direction": 35.0, "wind_speed": 4.4 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } },
+ "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-07T06:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1016.5, "air_temperature": -5.0, "cloud_area_fraction": 100.0, "relative_humidity": 74.7, "wind_from_direction": 33.0, "wind_speed": 4.0 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } },
+ "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-07T07:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1017.2, "air_temperature": -4.9, "cloud_area_fraction": 100.0, "relative_humidity": 73.7, "wind_from_direction": 35.0, "wind_speed": 4.3 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } },
+ "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-07T08:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1017.9, "air_temperature": -4.7, "cloud_area_fraction": 99.8, "relative_humidity": 71.7, "wind_from_direction": 38.0, "wind_speed": 4.6 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } },
+ "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-07T09:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1018.5, "air_temperature": -4.5, "cloud_area_fraction": 99.8, "relative_humidity": 70.2, "wind_from_direction": 43.0, "wind_speed": 5.5 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } },
+ "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-07T10:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1019.0, "air_temperature": -4.1, "cloud_area_fraction": 100.0, "relative_humidity": 69.5, "wind_from_direction": 45.0, "wind_speed": 5.7 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } },
+ "next_6_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-07T11:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1019.2, "air_temperature": -3.7, "cloud_area_fraction": 99.9, "relative_humidity": 68.7, "wind_from_direction": 45.0, "wind_speed": 5.7 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } },
+ "next_6_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-07T12:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1019.2, "air_temperature": -3.1, "cloud_area_fraction": 93.4, "relative_humidity": 63.4, "wind_from_direction": 43.0, "wind_speed": 5.8 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } },
+ "next_6_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-07T13:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1019.3, "air_temperature": -2.8, "cloud_area_fraction": 83.1, "relative_humidity": 59.5, "wind_from_direction": 46.0, "wind_speed": 6.1 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": { "precipitation_amount": 0.0 } },
+ "next_6_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-07T14:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1019.5, "air_temperature": -2.7, "cloud_area_fraction": 79.7, "relative_humidity": 57.7, "wind_from_direction": 43.0, "wind_speed": 5.9 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": { "precipitation_amount": 0.0 } },
+ "next_6_hours": { "summary": { "symbol_code": "fair_night" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-07T15:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1019.8, "air_temperature": -2.9, "cloud_area_fraction": 70.8, "relative_humidity": 56.6, "wind_from_direction": 40.0, "wind_speed": 5.6 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": { "precipitation_amount": 0.0 } },
+ "next_6_hours": { "summary": { "symbol_code": "fair_night" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-07T16:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1020.3, "air_temperature": -3.6, "cloud_area_fraction": 55.6, "relative_humidity": 55.7, "wind_from_direction": 42.0, "wind_speed": 5.5 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } },
+ "next_6_hours": { "summary": { "symbol_code": "fair_night" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-07T17:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1020.8, "air_temperature": -4.3, "cloud_area_fraction": 43.1, "relative_humidity": 54.0, "wind_from_direction": 43.0, "wind_speed": 5.4 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } },
+ "next_6_hours": { "summary": { "symbol_code": "fair_night" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-07T18:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1021.5, "air_temperature": -4.8, "cloud_area_fraction": 27.4, "relative_humidity": 52.3, "wind_from_direction": 42.0, "wind_speed": 5.2 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "fair_night" }, "details": { "precipitation_amount": 0.0 } },
+ "next_6_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-07T19:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1022.1, "air_temperature": -5.2, "cloud_area_fraction": 19.3, "relative_humidity": 53.2, "wind_from_direction": 43.0, "wind_speed": 5.4 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "fair_night" }, "details": { "precipitation_amount": 0.0 } },
+ "next_6_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-07T20:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1022.7, "air_temperature": -5.5, "cloud_area_fraction": 10.2, "relative_humidity": 55.0, "wind_from_direction": 43.0, "wind_speed": 5.7 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "clearsky_night" }, "details": { "precipitation_amount": 0.0 } },
+ "next_6_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-07T21:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1023.5, "air_temperature": -5.6, "cloud_area_fraction": 6.8, "relative_humidity": 61.3, "wind_from_direction": 43.0, "wind_speed": 5.6 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "clearsky_night" }, "details": { "precipitation_amount": 0.0 } },
+ "next_6_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-07T22:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1024.2, "air_temperature": -5.9, "cloud_area_fraction": 38.5, "relative_humidity": 71.4, "wind_from_direction": 38.0, "wind_speed": 4.7 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } },
+ "next_6_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-07T23:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1024.7, "air_temperature": -6.2, "cloud_area_fraction": 75.2, "relative_humidity": 77.8, "wind_from_direction": 36.0, "wind_speed": 4.0 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } },
+ "next_6_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-08T00:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1025.2, "air_temperature": -6.4, "cloud_area_fraction": 79.6, "relative_humidity": 79.8, "wind_from_direction": 36.0, "wind_speed": 3.2 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } },
+ "next_6_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-08T01:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1025.5, "air_temperature": -6.5, "cloud_area_fraction": 77.6, "relative_humidity": 80.0, "wind_from_direction": 34.0, "wind_speed": 3.1 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } },
+ "next_6_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-08T02:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1025.5, "air_temperature": -6.5, "cloud_area_fraction": 71.4, "relative_humidity": 79.7, "wind_from_direction": 32.0, "wind_speed": 3.4 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } },
+ "next_6_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-08T03:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1025.3, "air_temperature": -6.7, "cloud_area_fraction": 63.1, "relative_humidity": 79.9, "wind_from_direction": 32.0, "wind_speed": 3.3 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } },
+ "next_6_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-08T04:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1025.3, "air_temperature": -7.1, "cloud_area_fraction": 62.1, "relative_humidity": 80.4, "wind_from_direction": 33.0, "wind_speed": 3.1 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } },
+ "next_6_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-08T05:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1025.2, "air_temperature": -7.5, "cloud_area_fraction": 65.0, "relative_humidity": 82.2, "wind_from_direction": 45.0, "wind_speed": 2.4 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } },
+ "next_6_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-08T06:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1025.5, "air_temperature": -7.7, "cloud_area_fraction": 77.7, "relative_humidity": 82.7, "wind_from_direction": 48.0, "wind_speed": 2.2 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } },
+ "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-08T07:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1025.8, "air_temperature": -7.8, "cloud_area_fraction": 84.5, "relative_humidity": 82.2, "wind_from_direction": 48.0, "wind_speed": 2.6 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": { "precipitation_amount": 0.0 } },
+ "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-08T08:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1026.2, "air_temperature": -7.6, "cloud_area_fraction": 82.8, "relative_humidity": 80.9, "wind_from_direction": 48.0, "wind_speed": 3.0 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": { "precipitation_amount": 0.0 } },
+ "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-08T09:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1026.4, "air_temperature": -6.9, "cloud_area_fraction": 77.9, "relative_humidity": 78.9, "wind_from_direction": 46.0, "wind_speed": 3.3 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": { "precipitation_amount": 0.0 } },
+ "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-08T10:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1026.3, "air_temperature": -6.2, "cloud_area_fraction": 82.3, "relative_humidity": 77.0, "wind_from_direction": 43.0, "wind_speed": 3.5 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": { "precipitation_amount": 0.0 } },
+ "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-08T11:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1026.3, "air_temperature": -5.5, "cloud_area_fraction": 93.0, "relative_humidity": 76.6, "wind_from_direction": 49.0, "wind_speed": 3.2 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } },
+ "next_6_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-08T12:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1026.1, "air_temperature": -5.1, "cloud_area_fraction": 98.9, "relative_humidity": 76.2, "wind_from_direction": 47.0, "wind_speed": 2.6 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } },
+ "next_6_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-08T13:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1025.7, "air_temperature": -4.8, "cloud_area_fraction": 99.4, "relative_humidity": 76.2, "wind_from_direction": 50.0, "wind_speed": 2.3 } },
+ "next_1_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } },
+ "next_6_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-08T14:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1025.4, "air_temperature": -4.8, "cloud_area_fraction": 95.5, "relative_humidity": 76.3, "wind_from_direction": 56.0, "wind_speed": 2.5 } },
+ "next_1_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } },
+ "next_6_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-08T15:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1025.1, "air_temperature": -5.4, "cloud_area_fraction": 84.9, "relative_humidity": 77.2, "wind_from_direction": 56.0, "wind_speed": 2.6 } },
+ "next_1_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": { "precipitation_amount": 0.0 } },
+ "next_6_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-08T16:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1024.8, "air_temperature": -6.1, "cloud_area_fraction": 57.9, "relative_humidity": 78.9, "wind_from_direction": 48.0, "wind_speed": 2.7 } },
+ "next_1_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } },
+ "next_6_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-08T17:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1024.5, "air_temperature": -6.5, "cloud_area_fraction": 50.7, "relative_humidity": 81.3, "wind_from_direction": 38.0, "wind_speed": 2.5 } },
+ "next_1_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } },
+ "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-08T18:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1024.3, "air_temperature": -6.9, "cloud_area_fraction": 72.7, "relative_humidity": 82.2, "wind_from_direction": 38.0, "wind_speed": 2.5 } },
+ "next_12_hours": { "summary": { "symbol_code": "cloudy" }, "details": {} },
+ "next_1_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } },
+ "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-08T19:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1024.3, "air_temperature": -6.9, "cloud_area_fraction": 89.8, "relative_humidity": 81.9, "wind_from_direction": 44.0, "wind_speed": 1.9 } },
+ "next_1_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-08T20:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1024.2, "air_temperature": -7.0, "cloud_area_fraction": 96.6, "relative_humidity": 81.3, "wind_from_direction": 39.0, "wind_speed": 2.3 } },
+ "next_1_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-08T21:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1024.1, "air_temperature": -6.7, "cloud_area_fraction": 97.2, "relative_humidity": 79.9, "wind_from_direction": 40.0, "wind_speed": 2.8 } },
+ "next_1_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-08T22:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1023.8, "air_temperature": -6.7, "cloud_area_fraction": 97.6, "relative_humidity": 80.3, "wind_from_direction": 50.0, "wind_speed": 2.6 } },
+ "next_1_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-08T23:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1023.4, "air_temperature": -6.7, "cloud_area_fraction": 93.5, "relative_humidity": 80.7, "wind_from_direction": 53.0, "wind_speed": 2.3 } },
+ "next_1_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-09T00:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1023.1, "air_temperature": -7.1, "cloud_area_fraction": 80.0, "relative_humidity": 81.2, "wind_from_direction": 60.0, "wind_speed": 2.3 } },
+ "next_12_hours": { "summary": { "symbol_code": "cloudy" }, "details": {} },
+ "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-09T06:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1019.1, "air_temperature": -4.4, "cloud_area_fraction": 99.2, "relative_humidity": 85.9, "wind_from_direction": 339.8, "wind_speed": 1.1 } },
+ "next_12_hours": { "summary": { "symbol_code": "cloudy" }, "details": {} },
+ "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-09T12:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1017.8, "air_temperature": -4.3, "cloud_area_fraction": 100.0, "relative_humidity": 72.3, "wind_from_direction": 285.3, "wind_speed": 0.7 } },
+ "next_12_hours": { "summary": { "symbol_code": "cloudy" }, "details": {} },
+ "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-09T18:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1014.7, "air_temperature": -6.8, "cloud_area_fraction": 95.7, "relative_humidity": 82.1, "wind_from_direction": 346.8, "wind_speed": 0.6 } },
+ "next_12_hours": { "summary": { "symbol_code": "cloudy" }, "details": {} },
+ "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-10T00:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1012.9, "air_temperature": -8.8, "cloud_area_fraction": 97.7, "relative_humidity": 83.2, "wind_from_direction": 15.8, "wind_speed": 1.0 } },
+ "next_12_hours": { "summary": { "symbol_code": "cloudy" }, "details": {} },
+ "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-10T06:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1009.9, "air_temperature": -5.8, "cloud_area_fraction": 93.7, "relative_humidity": 82.2, "wind_from_direction": 22.4, "wind_speed": 1.0 } },
+ "next_12_hours": { "summary": { "symbol_code": "cloudy" }, "details": {} },
+ "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-10T12:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1007.5, "air_temperature": -3.5, "cloud_area_fraction": 100.0, "relative_humidity": 71.4, "wind_from_direction": 202.3, "wind_speed": 0.9 } },
+ "next_12_hours": { "summary": { "symbol_code": "cloudy" }, "details": {} },
+ "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-10T18:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1004.3, "air_temperature": -3.0, "cloud_area_fraction": 100.0, "relative_humidity": 81.9, "wind_from_direction": 22.3, "wind_speed": 1.0 } },
+ "next_12_hours": { "summary": { "symbol_code": "cloudy" }, "details": {} },
+ "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-11T00:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1002.5, "air_temperature": -2.3, "cloud_area_fraction": 100.0, "relative_humidity": 85.0, "wind_from_direction": 28.5, "wind_speed": 1.0 } },
+ "next_12_hours": { "summary": { "symbol_code": "cloudy" }, "details": {} },
+ "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-11T06:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1000.9, "air_temperature": -3.2, "cloud_area_fraction": 100.0, "relative_humidity": 85.5, "wind_from_direction": 28.1, "wind_speed": 1.6 } },
+ "next_12_hours": { "summary": { "symbol_code": "cloudy" }, "details": {} },
+ "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-11T12:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 999.8, "air_temperature": -2.0, "cloud_area_fraction": 100.0, "relative_humidity": 74.9, "wind_from_direction": 56.3, "wind_speed": 2.2 } },
+ "next_12_hours": { "summary": { "symbol_code": "cloudy" }, "details": {} },
+ "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-11T18:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 998.8, "air_temperature": -2.4, "cloud_area_fraction": 82.0, "relative_humidity": 77.8, "wind_from_direction": 29.5, "wind_speed": 2.2 } },
+ "next_12_hours": { "summary": { "symbol_code": "cloudy" }, "details": {} },
+ "next_6_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-12T00:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 998.3, "air_temperature": -2.9, "cloud_area_fraction": 100.0, "relative_humidity": 83.4, "wind_from_direction": 33.1, "wind_speed": 2.5 } },
+ "next_12_hours": { "summary": { "symbol_code": "cloudy" }, "details": {} },
+ "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-12T06:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 998.4, "air_temperature": -3.9, "cloud_area_fraction": 100.0, "relative_humidity": 83.0, "wind_from_direction": 24.1, "wind_speed": 2.5 } },
+ "next_12_hours": { "summary": { "symbol_code": "cloudy" }, "details": {} },
+ "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-12T12:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 998.9, "air_temperature": -3.3, "cloud_area_fraction": 99.6, "relative_humidity": 73.0, "wind_from_direction": 54.4, "wind_speed": 2.6 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} },
+ "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-12T18:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 999.9, "air_temperature": -4.3, "cloud_area_fraction": 98.0, "relative_humidity": 81.3, "wind_from_direction": 24.0, "wind_speed": 2.2 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": {} },
+ "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-13T00:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1001.9, "air_temperature": -4.6, "cloud_area_fraction": 39.8, "relative_humidity": 80.6, "wind_from_direction": 23.4, "wind_speed": 2.0 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} },
+ "next_6_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-13T06:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1004.1, "air_temperature": -7.4, "cloud_area_fraction": 36.3, "relative_humidity": 81.8, "wind_from_direction": 21.9, "wind_speed": 1.9 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} },
+ "next_6_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-13T12:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1005.7, "air_temperature": -5.8, "cloud_area_fraction": 100.0, "relative_humidity": 73.2, "wind_from_direction": 33.1, "wind_speed": 1.5 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} },
+ "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-13T18:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1004.7, "air_temperature": -5.0, "cloud_area_fraction": 0.0, "relative_humidity": 76.6, "wind_from_direction": 20.2, "wind_speed": 1.7 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": {} },
+ "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-14T00:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1007.8, "air_temperature": -7.8, "cloud_area_fraction": 6.2, "relative_humidity": 78.8, "wind_from_direction": 23.1, "wind_speed": 1.7 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} },
+ "next_6_hours": { "summary": { "symbol_code": "fair_night" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-14T06:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1007.4, "air_temperature": -11.8, "cloud_area_fraction": 21.9, "relative_humidity": 79.9, "wind_from_direction": 21.8, "wind_speed": 1.7 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} },
+ "next_6_hours": { "summary": { "symbol_code": "fair_day" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-14T12:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1007.5, "air_temperature": -6.3, "cloud_area_fraction": 100.0, "relative_humidity": 70.5, "wind_from_direction": 25.3, "wind_speed": 1.2 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} },
+ "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-14T18:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1008.0, "air_temperature": -5.5, "cloud_area_fraction": 100.0, "relative_humidity": 76.6, "wind_from_direction": 22.4, "wind_speed": 1.2 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_night" }, "details": {} },
+ "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-15T00:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1009.5, "air_temperature": -6.4, "cloud_area_fraction": 25.4, "relative_humidity": 76.8, "wind_from_direction": 18.6, "wind_speed": 1.5 } },
+ "next_12_hours": { "summary": { "symbol_code": "fair_day" }, "details": {} },
+ "next_6_hours": { "summary": { "symbol_code": "fair_night" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-15T06:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1012.1, "air_temperature": -11.2, "cloud_area_fraction": 16.8, "relative_humidity": 79.5, "wind_from_direction": 17.5, "wind_speed": 1.6 } },
+ "next_12_hours": { "summary": { "symbol_code": "clearsky_day" }, "details": {} },
+ "next_6_hours": { "summary": { "symbol_code": "fair_day" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-15T12:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1013.1, "air_temperature": -5.3, "cloud_area_fraction": 2.7, "relative_humidity": 59.4, "wind_from_direction": 197.5, "wind_speed": 1.2 } },
+ "next_12_hours": { "summary": { "symbol_code": "clearsky_day" }, "details": {} },
+ "next_6_hours": { "summary": { "symbol_code": "clearsky_day" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-15T18:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1015.2, "air_temperature": -7.4, "cloud_area_fraction": 2.3, "relative_humidity": 74.9, "wind_from_direction": 22.8, "wind_speed": 1.4 } },
+ "next_12_hours": { "summary": { "symbol_code": "fair_night" }, "details": {} },
+ "next_6_hours": { "summary": { "symbol_code": "clearsky_night" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-16T00:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1017.9, "air_temperature": -9.3, "cloud_area_fraction": 2.3, "relative_humidity": 78.8, "wind_from_direction": 22.1, "wind_speed": 1.5 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} },
+ "next_6_hours": { "summary": { "symbol_code": "clearsky_night" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-16T06:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1017.5, "air_temperature": -8.6, "cloud_area_fraction": 100.0, "relative_humidity": 82.1, "wind_from_direction": 17.7, "wind_speed": 1.4 } },
+ "next_12_hours": { "summary": { "symbol_code": "partlycloudy_day" }, "details": {} },
+ "next_6_hours": { "summary": { "symbol_code": "cloudy" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-16T12:00:00Z",
+ "data": {
+ "instant": { "details": { "air_pressure_at_sea_level": 1012.1, "air_temperature": -3.0, "cloud_area_fraction": 3.9, "relative_humidity": 62.3, "wind_from_direction": 30.4, "wind_speed": 1.4 } },
+ "next_6_hours": { "summary": { "symbol_code": "fair_day" }, "details": { "precipitation_amount": 0.0 } }
+ }
+ },
+ {
+ "time": "2026-02-16T18:00:00Z",
+ "data": { "instant": { "details": { "air_pressure_at_sea_level": 1017.1, "air_temperature": -5.9, "cloud_area_fraction": 100.0, "relative_humidity": 82.0, "wind_from_direction": 26.6, "wind_speed": 1.9 } } }
+ }
+ ]
+ }
+}
diff --git a/tests/unit/functions/server_functions_spec.js b/tests/unit/functions/server_functions_spec.js
index c0953d48..91ee3cac 100644
--- a/tests/unit/functions/server_functions_spec.js
+++ b/tests/unit/functions/server_functions_spec.js
@@ -164,6 +164,7 @@ describe("server_functions tests", () => {
});
it("Gets User-Agent from configuration", async () => {
+ const previousConfig = global.config;
global.config = {};
let userAgent;
@@ -177,6 +178,8 @@ describe("server_functions tests", () => {
global.config.userAgent = () => "Mozilla/5.0 (Bar)";
userAgent = getUserAgent();
expect(userAgent).toBe("Mozilla/5.0 (Bar)");
+
+ global.config = previousConfig;
});
});
});
diff --git a/tests/unit/modules/default/utils_spec.js b/tests/unit/modules/default/utils_spec.js
index 4af7db67..efea6e28 100644
--- a/tests/unit/modules/default/utils_spec.js
+++ b/tests/unit/modules/default/utils_spec.js
@@ -1,111 +1,9 @@
global.moment = require("moment-timezone");
const defaults = require("../../../../js/defaults");
-const { performWebRequest, formatTime } = require(`../../../../${defaults.defaultModulesDir}/utils`);
+const { formatTime } = require(`../../../../${defaults.defaultModulesDir}/utils`);
describe("Default modules utils tests", () => {
- describe("performWebRequest", () => {
- const locationHost = "localhost:8080";
- const locationProtocol = "http";
-
- let fetchResponse;
- let fetchMock;
- let urlToCall;
-
- beforeEach(() => {
- fetchResponse = new Response();
- global.fetch = vi.fn(() => Promise.resolve(fetchResponse));
- fetchMock = global.fetch;
- });
-
- describe("When using cors proxy", () => {
- Object.defineProperty(global, "location", {
- value: {
- host: locationHost,
- protocol: locationProtocol
- }
- });
-
- it("Calls correct URL once", async () => {
- urlToCall = "http://www.test.com/path?param1=value1";
-
- await performWebRequest(urlToCall, "json", true);
-
- expect(fetchMock.mock.calls).toHaveLength(1);
- expect(fetchMock.mock.calls[0][0]).toBe(`${locationProtocol}//${locationHost}/cors?url=${urlToCall}`);
- });
-
- it("Sends correct headers", async () => {
- urlToCall = "http://www.test.com/path?param1=value1";
-
- const headers = [
- { name: "header1", value: "value1" },
- { name: "header2", value: "value2" }
- ];
-
- await performWebRequest(urlToCall, "json", true, headers);
-
- expect(fetchMock.mock.calls).toHaveLength(1);
- expect(fetchMock.mock.calls[0][0]).toBe(`${locationProtocol}//${locationHost}/cors?sendheaders=header1:value1,header2:value2&url=${urlToCall}`);
- });
- });
-
- describe("When not using cors proxy", () => {
- it("Calls correct URL once", async () => {
- urlToCall = "http://www.test.com/path?param1=value1";
-
- await performWebRequest(urlToCall);
-
- expect(fetchMock.mock.calls).toHaveLength(1);
- expect(fetchMock.mock.calls[0][0]).toBe(urlToCall);
- });
-
- it("Sends correct headers", async () => {
- urlToCall = "http://www.test.com/path?param1=value1";
- const headers = [
- { name: "header1", value: "value1" },
- { name: "header2", value: "value2" }
- ];
-
- await performWebRequest(urlToCall, "json", false, headers);
-
- const expectedHeaders = { headers: { header1: "value1", header2: "value2" } };
- expect(fetchMock.mock.calls).toHaveLength(1);
- expect(fetchMock.mock.calls[0][1]).toStrictEqual(expectedHeaders);
- });
- });
-
- describe("When receiving json format", () => {
- it("Returns undefined when no data is received", async () => {
- urlToCall = "www.test.com";
-
- const response = await performWebRequest(urlToCall);
-
- expect(response).toBeUndefined();
- });
-
- it("Returns object when data is received", async () => {
- urlToCall = "www.test.com";
- fetchResponse = new Response("{\"body\": \"some content\"}");
-
- const response = await performWebRequest(urlToCall);
-
- expect(response.body).toBe("some content");
- });
-
- it("Returns expected headers when data is received", async () => {
- urlToCall = "www.test.com";
- fetchResponse = new Response("{\"body\": \"some content\"}", { headers: { header1: "value1", header2: "value2" } });
-
- const response = await performWebRequest(urlToCall, "json", false, undefined, ["header1"]);
-
- expect(response.headers).toHaveLength(1);
- expect(response.headers[0].name).toBe("header1");
- expect(response.headers[0].value).toBe("value1");
- });
- });
- });
-
describe("formatTime", () => {
const time = new Date();
diff --git a/tests/unit/modules/default/weather/provider_utils_spec.js b/tests/unit/modules/default/weather/provider_utils_spec.js
new file mode 100644
index 00000000..511a8434
--- /dev/null
+++ b/tests/unit/modules/default/weather/provider_utils_spec.js
@@ -0,0 +1,167 @@
+const defaults = require("../../../../../js/defaults");
+
+const providerUtils = require(`../../../../../${defaults.defaultModulesDir}/weather/provider-utils`);
+
+describe("Weather provider utils tests", () => {
+ describe("convertWeatherType", () => {
+ it("should convert OpenWeatherMap day icons correctly", () => {
+ expect(providerUtils.convertWeatherType("01d")).toBe("day-sunny");
+ expect(providerUtils.convertWeatherType("02d")).toBe("day-cloudy");
+ expect(providerUtils.convertWeatherType("10d")).toBe("rain");
+ expect(providerUtils.convertWeatherType("13d")).toBe("snow");
+ });
+
+ it("should convert OpenWeatherMap night icons correctly", () => {
+ expect(providerUtils.convertWeatherType("01n")).toBe("night-clear");
+ expect(providerUtils.convertWeatherType("02n")).toBe("night-cloudy");
+ expect(providerUtils.convertWeatherType("10n")).toBe("night-rain");
+ });
+
+ it("should return null for unknown weather types", () => {
+ expect(providerUtils.convertWeatherType("99x")).toBeNull();
+ expect(providerUtils.convertWeatherType("")).toBeNull();
+ });
+ });
+
+ describe("applyTimezoneOffset", () => {
+ it("should apply positive offset correctly", () => {
+ const date = new Date("2026-02-02T12:00:00Z");
+ const result = providerUtils.applyTimezoneOffset(date, 120); // +2 hours
+ // The function converts to UTC, then applies offset
+ const expected = new Date(date.getTime() + date.getTimezoneOffset() * 60000 + 120 * 60000);
+ expect(result.getTime()).toBe(expected.getTime());
+ });
+
+ it("should apply negative offset correctly", () => {
+ const date = new Date("2026-02-02T12:00:00Z");
+ const result = providerUtils.applyTimezoneOffset(date, -300); // -5 hours
+ const expected = new Date(date.getTime() + date.getTimezoneOffset() * 60000 - 300 * 60000);
+ expect(result.getTime()).toBe(expected.getTime());
+ });
+
+ it("should handle zero offset", () => {
+ const date = new Date("2026-02-02T12:00:00Z");
+ const result = providerUtils.applyTimezoneOffset(date, 0);
+ const expected = new Date(date.getTime() + date.getTimezoneOffset() * 60000);
+ expect(result.getTime()).toBe(expected.getTime());
+ });
+ });
+
+ describe("limitDecimals", () => {
+ it("should truncate decimals correctly", () => {
+ expect(providerUtils.limitDecimals(12.3456789, 4)).toBe(12.3456);
+ expect(providerUtils.limitDecimals(12.3456789, 2)).toBe(12.34);
+ });
+
+ it("should handle values with fewer decimals than limit", () => {
+ expect(providerUtils.limitDecimals(12.34, 6)).toBe(12.34);
+ expect(providerUtils.limitDecimals(12, 4)).toBe(12);
+ });
+
+ it("should handle negative values", () => {
+ expect(providerUtils.limitDecimals(-12.3456789, 2)).toBe(-12.34);
+ });
+
+ it("should truncate not round", () => {
+ expect(providerUtils.limitDecimals(12.9999, 2)).toBe(12.99);
+ expect(providerUtils.limitDecimals(12.9999, 0)).toBe(12);
+ });
+ });
+
+ describe("getSunTimes", () => {
+ it("should return sunrise and sunset times", () => {
+ const date = new Date("2026-06-21T12:00:00Z"); // Summer solstice
+ const lat = 52.52; // Berlin
+ const lon = 13.405;
+
+ const result = providerUtils.getSunTimes(date, lat, lon);
+
+ expect(result).toHaveProperty("sunrise");
+ expect(result).toHaveProperty("sunset");
+ expect(result.sunrise).toBeInstanceOf(Date);
+ expect(result.sunset).toBeInstanceOf(Date);
+ expect(result.sunrise.getTime()).toBeLessThan(result.sunset.getTime());
+ });
+
+ it("should handle different locations", () => {
+ const date = new Date("2026-06-21T12:00:00Z");
+
+ // London
+ const london = providerUtils.getSunTimes(date, 51.5074, -0.1278);
+ // Tokyo
+ const tokyo = providerUtils.getSunTimes(date, 35.6762, 139.6503);
+
+ expect(london.sunrise.getTime()).not.toBe(tokyo.sunrise.getTime());
+ });
+ });
+
+ describe("isDayTime", () => {
+ it("should return true when time is between sunrise and sunset", () => {
+ const sunrise = new Date("2026-02-02T07:00:00Z");
+ const sunset = new Date("2026-02-02T17:00:00Z");
+ const noon = new Date("2026-02-02T12:00:00Z");
+
+ expect(providerUtils.isDayTime(noon, sunrise, sunset)).toBe(true);
+ });
+
+ it("should return false when time is before sunrise", () => {
+ const sunrise = new Date("2026-02-02T07:00:00Z");
+ const sunset = new Date("2026-02-02T17:00:00Z");
+ const night = new Date("2026-02-02T03:00:00Z");
+
+ expect(providerUtils.isDayTime(night, sunrise, sunset)).toBe(false);
+ });
+
+ it("should return false when time is after sunset", () => {
+ const sunrise = new Date("2026-02-02T07:00:00Z");
+ const sunset = new Date("2026-02-02T17:00:00Z");
+ const night = new Date("2026-02-02T20:00:00Z");
+
+ expect(providerUtils.isDayTime(night, sunrise, sunset)).toBe(false);
+ });
+
+ it("should return true if sunrise/sunset are null", () => {
+ const noon = new Date("2026-02-02T12:00:00Z");
+ expect(providerUtils.isDayTime(noon, null, null)).toBe(true);
+ });
+ });
+
+ describe("formatTimezoneOffset", () => {
+ it("should format positive offsets correctly", () => {
+ expect(providerUtils.formatTimezoneOffset(60)).toBe("+01:00");
+ expect(providerUtils.formatTimezoneOffset(120)).toBe("+02:00");
+ expect(providerUtils.formatTimezoneOffset(330)).toBe("+05:30"); // India
+ });
+
+ it("should format negative offsets correctly", () => {
+ expect(providerUtils.formatTimezoneOffset(-300)).toBe("-05:00"); // EST
+ expect(providerUtils.formatTimezoneOffset(-480)).toBe("-08:00"); // PST
+ });
+
+ it("should format zero offset correctly", () => {
+ expect(providerUtils.formatTimezoneOffset(0)).toBe("+00:00");
+ });
+
+ it("should pad single digits with zero", () => {
+ expect(providerUtils.formatTimezoneOffset(5)).toBe("+00:05");
+ expect(providerUtils.formatTimezoneOffset(-5)).toBe("-00:05");
+ });
+ });
+
+ describe("getDateString", () => {
+ it("should format date as YYYY-MM-DD (local time)", () => {
+ const date = new Date(2026, 1, 2, 12, 34, 56); // Feb 2, 2026 (month is 0-indexed)
+ expect(providerUtils.getDateString(date)).toBe("2026-02-02");
+ });
+
+ it("should handle single-digit months and days correctly", () => {
+ const date = new Date(2026, 0, 5, 12, 0, 0); // Jan 5, 2026
+ expect(providerUtils.getDateString(date)).toBe("2026-01-05");
+ });
+
+ it("should handle end of year", () => {
+ const date = new Date(2025, 11, 31, 23, 59, 59); // Dec 31, 2025
+ expect(providerUtils.getDateString(date)).toBe("2025-12-31");
+ });
+ });
+});
diff --git a/tests/unit/modules/default/weather/providers/envcanada_spec.js b/tests/unit/modules/default/weather/providers/envcanada_spec.js
new file mode 100644
index 00000000..85533c51
--- /dev/null
+++ b/tests/unit/modules/default/weather/providers/envcanada_spec.js
@@ -0,0 +1,309 @@
+/**
+ * Environment Canada Weather Provider Tests
+ *
+ * Tests data parsing for current, forecast, and hourly weather types.
+ * Environment Canada is the Canadian weather service (XML-based).
+ */
+
+import fs from "fs";
+import path from "path";
+import { fileURLToPath } from "url";
+import { http, HttpResponse } from "msw";
+import { setupServer } from "msw/node";
+import { describe, it, expect, vi, beforeAll, afterAll, afterEach } from "vitest";
+
+const __dirname = path.dirname(fileURLToPath(import.meta.url));
+const indexHTML = fs.readFileSync(path.join(__dirname, "../../../../../mocks/weather_envcanada_index.html"), "utf-8");
+const cityPageXML = fs.readFileSync(path.join(__dirname, "../../../../../mocks/weather_envcanada.xml"), "utf-8");
+
+// Match directory listing (index) - must end with / and nothing after
+const ENVCANADA_INDEX_PATTERN = /https:\/\/dd\.weather\.gc\.ca\/today\/citypage_weather\/[A-Z]{2}\/\d{2}\/$/;
+// Match actual XML files
+const ENVCANADA_CITYPAGE_PATTERN = /https:\/\/dd\.weather\.gc\.ca\/today\/citypage_weather\/[A-Z]{2}\/\d{2}\/.*\.xml$/;
+
+let server;
+
+beforeAll(() => {
+ server = setupServer(
+ http.get(ENVCANADA_INDEX_PATTERN, () => {
+ return new HttpResponse(indexHTML, {
+ headers: { "Content-Type": "text/html" }
+ });
+ }),
+ http.get(ENVCANADA_CITYPAGE_PATTERN, () => {
+ return new HttpResponse(cityPageXML, {
+ headers: { "Content-Type": "application/xml" }
+ });
+ })
+ );
+ server.listen({ onUnhandledRequest: "bypass" });
+});
+
+afterAll(() => {
+ server.close();
+});
+
+afterEach(() => {
+ server.resetHandlers();
+});
+
+describe("EnvCanadaProvider", () => {
+ let EnvCanadaProvider;
+
+ beforeAll(async () => {
+ const module = await import("../../../../../../defaultmodules/weather/providers/envcanada");
+ EnvCanadaProvider = module.default || module;
+ });
+
+ describe("Constructor & Configuration", () => {
+ it("should set config values from params", () => {
+ const provider = new EnvCanadaProvider({
+ siteCode: "s0000458",
+ provCode: "ON",
+ type: "current"
+ });
+ expect(provider.config.siteCode).toBe("s0000458");
+ expect(provider.config.provCode).toBe("ON");
+ expect(provider.config.type).toBe("current");
+ });
+
+ it("should throw error if siteCode or provCode missing", async () => {
+ const provider = new EnvCanadaProvider({ siteCode: "", provCode: "" });
+ provider.setCallbacks(vi.fn(), vi.fn());
+ await expect(provider.initialize()).rejects.toThrow("siteCode and provCode are required");
+ });
+ });
+
+ describe("Two-Step Fetch Pattern", () => {
+ it("should first fetch index page then city page", async () => {
+ const provider = new EnvCanadaProvider({
+ siteCode: "s0000458",
+ provCode: "ON",
+ type: "current"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+ expect(result).toBeDefined();
+ });
+ });
+
+ describe("Current Weather Parsing", () => {
+ it("should parse current weather from XML", async () => {
+ const provider = new EnvCanadaProvider({
+ siteCode: "s0000458",
+ provCode: "ON",
+ type: "current"
+ });
+
+ const dataPromise = new Promise((resolve, reject) => {
+ provider.setCallbacks(
+ (data) => {
+ resolve(data);
+ },
+ (error) => {
+ reject(error);
+ }
+ );
+ });
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(result).toBeDefined();
+ expect(result.temperature).toBe(-20.3);
+ expect(result.windSpeed).toBeCloseTo(5.28, 1); // 19 km/h -> m/s
+ expect(result.windFromDirection).toBe(346); // NNW
+ expect(result.humidity).toBe(67);
+ });
+
+ it("should use wind chill for feels like temperature when available", async () => {
+ const provider = new EnvCanadaProvider({
+ siteCode: "s0000458",
+ provCode: "ON",
+ type: "current"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ // XML has windChill of -31
+ expect(result.feelsLikeTemp).toBe(-31);
+ });
+
+ it("should parse sunrise/sunset from XML", async () => {
+ const provider = new EnvCanadaProvider({
+ siteCode: "s0000458",
+ provCode: "ON",
+ type: "current"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(result.sunrise).toBeInstanceOf(Date);
+ expect(result.sunset).toBeInstanceOf(Date);
+ });
+
+ it("should convert icon code to weather type", async () => {
+ const provider = new EnvCanadaProvider({
+ siteCode: "s0000458",
+ provCode: "ON",
+ type: "current"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ // Icon code 40 = "Blowing Snow" → "snow-wind"
+ expect(result.weatherType).toBe("snow-wind");
+ });
+ });
+
+ describe("Forecast Parsing", () => {
+ it("should parse daily forecast from XML", async () => {
+ const provider = new EnvCanadaProvider({
+ siteCode: "s0000458",
+ provCode: "ON",
+ type: "forecast"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(Array.isArray(result)).toBe(true);
+ expect(result.length).toBeGreaterThan(0);
+
+ const day = result[0];
+ expect(day).toHaveProperty("date");
+ expect(day).toHaveProperty("minTemperature");
+ expect(day).toHaveProperty("maxTemperature");
+ expect(day).toHaveProperty("precipitationProbability");
+ expect(day).toHaveProperty("weatherType");
+ });
+
+ it("should extract max precipitation probability from day/night", async () => {
+ const provider = new EnvCanadaProvider({
+ siteCode: "s0000458",
+ provCode: "ON",
+ type: "forecast"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ // Real data has 40% for both day and night periods
+ expect(result[0].precipitationProbability).toBe(40);
+ });
+ });
+
+ describe("Hourly Parsing", () => {
+ it("should parse hourly forecast from XML", async () => {
+ const provider = new EnvCanadaProvider({
+ siteCode: "s0000458",
+ provCode: "ON",
+ type: "hourly"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(Array.isArray(result)).toBe(true);
+ expect(result).toHaveLength(24); // Real data has 24 hourly forecasts
+ const hour = result[0];
+ expect(hour).toHaveProperty("date");
+ expect(hour).toHaveProperty("temperature");
+ expect(hour).toHaveProperty("precipitationProbability");
+ expect(hour).toHaveProperty("weatherType");
+ });
+
+ it("should parse EC time format correctly", async () => {
+ const provider = new EnvCanadaProvider({
+ siteCode: "s0000458",
+ provCode: "ON",
+ type: "hourly"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ // First hourly forecast is for 202602071300 = 2026-02-07 13:00 UTC
+ const expectedDate = new Date(Date.UTC(2026, 1, 7, 13, 0, 0));
+ expect(result[0].date.getTime()).toBe(expectedDate.getTime());
+ });
+ });
+
+ describe("Error Handling", () => {
+ it("should handle missing city page URL", async () => {
+ const provider = new EnvCanadaProvider({
+ siteCode: "s9999999", // Invalid site code
+ provCode: "ON",
+ type: "current"
+ });
+
+ let errorCalled = false;
+ provider.setCallbacks(vi.fn(), () => {
+ errorCalled = true;
+ });
+
+ await provider.initialize();
+ provider.start();
+
+ // Should not call error callback if URL not found (it's expected during hour transitions)
+ // Wait a bit to see if callback is called
+ await new Promise((resolve) => setTimeout(resolve, 100));
+
+ expect(errorCalled).toBe(false);
+ });
+ });
+});
diff --git a/tests/unit/modules/default/weather/providers/openmeteo_spec.js b/tests/unit/modules/default/weather/providers/openmeteo_spec.js
new file mode 100644
index 00000000..7201c293
--- /dev/null
+++ b/tests/unit/modules/default/weather/providers/openmeteo_spec.js
@@ -0,0 +1,305 @@
+/**
+ * OpenMeteo Weather Provider Tests
+ *
+ * Tests data parsing for current, forecast, and hourly weather types.
+ * Uses MSW to mock HTTP responses from the Open-Meteo API.
+ */
+import { http, HttpResponse } from "msw";
+import { setupServer } from "msw/node";
+import { describe, it, expect, vi, beforeAll, afterAll, afterEach } from "vitest";
+
+import openMeteoData from "../../../../../mocks/weather_openmeteo_current.json" with { type: "json" };
+import openMeteoCurrentWeatherData from "../../../../../mocks/weather_openmeteo_current_weather.json" with { type: "json" };
+// Real API returns current + forecast in one response
+const currentData = openMeteoCurrentWeatherData;
+const forecastData = openMeteoData;
+
+const GEOCODE_URL = "https://api.bigdatacloud.net/data/reverse-geocode-client*";
+
+let server;
+
+beforeAll(() => {
+ // Mock global fetch for geocoding (used by provider's #fetchLocation)
+ server = setupServer(
+ http.get(GEOCODE_URL, () => {
+ return HttpResponse.json({
+ city: "Munich",
+ locality: "Munich",
+ principalSubdivisionCode: "BY"
+ });
+ })
+ );
+ server.listen({ onUnhandledRequest: "bypass" });
+});
+
+afterAll(() => {
+ server.close();
+});
+
+afterEach(() => {
+ server.resetHandlers();
+});
+
+describe("OpenMeteoProvider", () => {
+ let OpenMeteoProvider;
+
+ beforeAll(async () => {
+ const module = await import("../../../../../../defaultmodules/weather/providers/openmeteo");
+ OpenMeteoProvider = module.default;
+ });
+
+ describe("Constructor & Configuration", () => {
+ it("should set config values from params", () => {
+ const provider = new OpenMeteoProvider({
+ lat: 48.14,
+ lon: 11.58,
+ type: "current"
+ });
+ expect(provider.config.lat).toBe(48.14);
+ expect(provider.config.lon).toBe(11.58);
+ expect(provider.config.type).toBe("current");
+ });
+
+ it("should have default values", () => {
+ const provider = new OpenMeteoProvider({});
+ expect(provider.config.lat).toBe(0);
+ expect(provider.config.lon).toBe(0);
+ expect(provider.config.type).toBe("current");
+ expect(provider.config.maxNumberOfDays).toBe(5);
+ expect(provider.config.apiBase).toBe("https://api.open-meteo.com/v1");
+ });
+
+ it("should initialize without callbacks", async () => {
+ const provider = new OpenMeteoProvider({ lat: 48.14, lon: 11.58 });
+ await expect(provider.initialize()).resolves.not.toThrow();
+ });
+
+ it("should resolve location name via geocoding", async () => {
+ const provider = new OpenMeteoProvider({ lat: 48.14, lon: 11.58 });
+ await provider.initialize();
+ expect(provider.locationName).toBe("Munich, BY");
+ });
+ });
+
+ describe("Current Weather Parsing", () => {
+ it("should parse current weather data correctly", async () => {
+ const provider = new OpenMeteoProvider({
+ lat: 48.14,
+ lon: 11.58,
+ type: "current"
+ });
+
+ const dataPromise = new Promise((resolve, reject) => {
+ provider.setCallbacks(
+ (data) => {
+ resolve(data);
+ },
+ (error) => {
+ reject(error);
+ }
+ );
+ });
+
+ server.use(
+ http.get("https://api.open-meteo.com/v1/forecast*", () => {
+ return HttpResponse.json(currentData);
+ })
+ );
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(result).toBeDefined();
+ expect(result.temperature).toBe(8.5);
+ expect(result.windSpeed).toBeCloseTo(4.7, 1);
+ expect(result.windFromDirection).toBe(9);
+ expect(result.humidity).toBe(83);
+ });
+
+ it("should include sunrise and sunset from daily data", async () => {
+ const provider = new OpenMeteoProvider({
+ lat: 48.14,
+ lon: 11.58,
+ type: "current"
+ });
+
+ const dataPromise = new Promise((resolve, reject) => {
+ provider.setCallbacks(
+ (data) => {
+ resolve(data);
+ },
+ (error) => {
+ reject(error);
+ }
+ );
+ });
+
+ server.use(
+ http.get("https://api.open-meteo.com/v1/forecast*", () => {
+ return HttpResponse.json(currentData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(result.sunrise).toBeInstanceOf(Date);
+ expect(result.sunset).toBeInstanceOf(Date);
+ expect(result.minTemperature).toBe(4.7);
+ expect(result.maxTemperature).toBe(9.5);
+ });
+ });
+
+ describe("Forecast Parsing", () => {
+ it("should parse daily forecast data correctly", async () => {
+ const provider = new OpenMeteoProvider({
+ lat: 48.14,
+ lon: 11.58,
+ type: "forecast"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get("https://api.open-meteo.com/v1/forecast*", () => {
+ return HttpResponse.json(forecastData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(Array.isArray(result)).toBe(true);
+ expect(result).toHaveLength(7);
+ const firstDay = result[0];
+ expect(firstDay.minTemperature).toBe(-9.2);
+ expect(firstDay.maxTemperature).toBe(-0.2);
+ expect(firstDay.temperature).toBeCloseTo(-4.7, 0); // (-0.2+-9.2)/2
+
+ expect(firstDay.sunrise).toBeInstanceOf(Date);
+ expect(firstDay.sunset).toBeInstanceOf(Date);
+ });
+
+ it("should include precipitation data in forecast", async () => {
+ const provider = new OpenMeteoProvider({
+ lat: 48.14,
+ lon: 11.58,
+ type: "forecast"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get("https://api.open-meteo.com/v1/forecast*", () => {
+ return HttpResponse.json(forecastData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ // Mock data has no rain_sum field - provider returns null for missing data
+ expect(result[0].rain).toBeNull();
+ // precipitation_sum has value 0.0 in mock data
+ expect(result[0].precipitationAmount).toBe(0.0);
+ });
+ });
+
+ describe("Error Handling", () => {
+ it("should call error callback on invalid API response", async () => {
+ const provider = new OpenMeteoProvider({
+ lat: 48.14,
+ lon: 11.58,
+ type: "current"
+ });
+
+ const errorPromise = new Promise((resolve) => {
+ provider.setCallbacks(vi.fn(), resolve);
+ });
+
+ server.use(
+ http.get("https://api.open-meteo.com/v1/forecast*", () => {
+ return HttpResponse.json({});
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const error = await errorPromise;
+ expect(error).toHaveProperty("message");
+ expect(error).toHaveProperty("translationKey");
+ });
+
+ it("should call error callback on network failure", async () => {
+ const provider = new OpenMeteoProvider({
+ lat: 48.14,
+ lon: 11.58,
+ type: "current"
+ });
+
+ const errorPromise = new Promise((resolve) => {
+ provider.setCallbacks(vi.fn(), resolve);
+ });
+
+ server.use(
+ http.get("https://api.open-meteo.com/v1/forecast*", () => {
+ return HttpResponse.error();
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const error = await errorPromise;
+ expect(error).toHaveProperty("url");
+ });
+ });
+
+ describe("Callback Interface", () => {
+ it("should store callbacks via setCallbacks", () => {
+ const provider = new OpenMeteoProvider({});
+ const onData = vi.fn();
+ const onError = vi.fn();
+ provider.setCallbacks(onData, onError);
+ expect(provider.onDataCallback).toBe(onData);
+ expect(provider.onErrorCallback).toBe(onError);
+ });
+ });
+
+ describe("Lifecycle", () => {
+ it("should have start/stop methods", () => {
+ const provider = new OpenMeteoProvider({});
+ expect(typeof provider.start).toBe("function");
+ expect(typeof provider.stop).toBe("function");
+ });
+
+ it("should clear timer on stop", async () => {
+ const provider = new OpenMeteoProvider({ lat: 48.14, lon: 11.58 });
+ provider.setCallbacks(vi.fn(), vi.fn());
+
+ server.use(
+ http.get("https://api.open-meteo.com/v1/forecast*", () => {
+ return HttpResponse.json(currentData);
+ })
+ );
+
+ await provider.initialize();
+ provider.stop();
+
+ // Should not throw
+ expect(provider.fetcher).not.toBeNull();
+ });
+ });
+});
diff --git a/tests/unit/modules/default/weather/providers/openweathermap_spec.js b/tests/unit/modules/default/weather/providers/openweathermap_spec.js
new file mode 100644
index 00000000..63039784
--- /dev/null
+++ b/tests/unit/modules/default/weather/providers/openweathermap_spec.js
@@ -0,0 +1,235 @@
+/**
+ * OpenWeatherMap Provider Tests
+ *
+ * Tests data parsing for current, forecast, and hourly weather types.
+ */
+import { http, HttpResponse } from "msw";
+import { setupServer } from "msw/node";
+import { describe, it, expect, vi, beforeAll, afterAll, afterEach } from "vitest";
+
+import onecallData from "../../../../../mocks/weather_owm_onecall.json" with { type: "json" };
+
+let server;
+
+beforeAll(() => {
+ server = setupServer();
+ server.listen({ onUnhandledRequest: "bypass" });
+});
+
+afterAll(() => {
+ server.close();
+});
+
+afterEach(() => {
+ server.resetHandlers();
+});
+
+describe("OpenWeatherMapProvider", () => {
+ let OpenWeatherMapProvider;
+
+ beforeAll(async () => {
+ const module = await import("../../../../../../defaultmodules/weather/providers/openweathermap");
+ OpenWeatherMapProvider = module.default;
+ });
+
+ describe("Constructor & Configuration", () => {
+ it("should set config values from params", () => {
+ const provider = new OpenWeatherMapProvider({
+ lat: 48.14,
+ lon: 11.58,
+ apiKey: "test-key"
+ });
+ expect(provider.config.lat).toBe(48.14);
+ expect(provider.config.lon).toBe(11.58);
+ expect(provider.config.apiKey).toBe("test-key");
+ });
+
+ it("should have default values", () => {
+ const provider = new OpenWeatherMapProvider({ apiKey: "test" });
+ expect(provider.config.apiVersion).toBe("3.0");
+ expect(provider.config.weatherEndpoint).toBe("/onecall");
+ expect(provider.config.apiBase).toBe("https://api.openweathermap.org/data/");
+ });
+ });
+
+ describe("API Key Validation", () => {
+ it("should call error callback without API key", async () => {
+ const provider = new OpenWeatherMapProvider({ apiKey: "" });
+ const onError = vi.fn();
+ provider.setCallbacks(vi.fn(), onError);
+ await provider.initialize();
+ expect(onError).toHaveBeenCalledWith(
+ expect.objectContaining({ message: "API key is required" })
+ );
+ });
+
+ it("should not create fetcher without API key", async () => {
+ const provider = new OpenWeatherMapProvider({ apiKey: "" });
+ provider.setCallbacks(vi.fn(), vi.fn());
+ await provider.initialize();
+ expect(provider.fetcher).toBeNull();
+ });
+
+ it("should throw if setCallbacks not called before initialize", async () => {
+ const provider = new OpenWeatherMapProvider({ apiKey: "test" });
+ await expect(provider.initialize()).rejects.toThrow("setCallbacks");
+ });
+ });
+
+ describe("Current Weather Parsing", () => {
+ it("should parse onecall current weather data", async () => {
+ const provider = new OpenWeatherMapProvider({
+ lat: 48.14,
+ lon: 11.58,
+ apiKey: "test-key",
+ type: "current"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get("https://api.openweathermap.org/data/3.0/onecall", () => {
+ return HttpResponse.json(onecallData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(result.temperature).toBe(-0.27);
+ expect(result.windSpeed).toBe(3.09);
+ expect(result.windFromDirection).toBe(220);
+ expect(result.humidity).toBe(54);
+ expect(result.uvIndex).toBe(0);
+ expect(result.feelsLikeTemp).toBe(-3.9);
+ expect(result.weatherType).toBe("cloudy-windy");
+ expect(result.sunrise).toBeInstanceOf(Date);
+ expect(result.sunset).toBeInstanceOf(Date);
+ });
+
+ it("should include precipitation data in current weather", async () => {
+ const provider = new OpenWeatherMapProvider({
+ lat: 48.14,
+ lon: 11.58,
+ apiKey: "test-key",
+ type: "current"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get("https://api.openweathermap.org/data/3.0/onecall", () => {
+ return HttpResponse.json(onecallData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ // Real data has no precipitation
+ expect(result.rain).toBeUndefined();
+ expect(result.snow).toBeUndefined();
+ });
+ });
+
+ describe("Forecast Parsing", () => {
+ it("should parse daily forecast data", async () => {
+ const provider = new OpenWeatherMapProvider({
+ lat: 48.14,
+ lon: 11.58,
+ apiKey: "test-key",
+ type: "forecast"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get("https://api.openweathermap.org/data/3.0/onecall", () => {
+ return HttpResponse.json(onecallData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(Array.isArray(result)).toBe(true);
+ expect(result).toHaveLength(8);
+ expect(result[0].minTemperature).toBe(-11.86);
+ expect(result[0].maxTemperature).toBe(-0.27);
+ expect(result[0].snow).toBe(0.69);
+ expect(result[0].precipitationProbability).toBe(100);
+ });
+ });
+
+ describe("Hourly Parsing", () => {
+ it("should parse hourly forecast data", async () => {
+ const provider = new OpenWeatherMapProvider({
+ lat: 48.14,
+ lon: 11.58,
+ apiKey: "test-key",
+ type: "hourly"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get("https://api.openweathermap.org/data/3.0/onecall", () => {
+ return HttpResponse.json(onecallData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(Array.isArray(result)).toBe(true);
+ expect(result).toHaveLength(48);
+ expect(result[0].temperature).toBe(-0.66);
+ expect(result[0].precipitationProbability).toBe(0);
+ expect(result[0].rain).toBeUndefined();
+ });
+ });
+
+ describe("Timezone Handling", () => {
+ it("should set location name from timezone", async () => {
+ const provider = new OpenWeatherMapProvider({
+ lat: 48.14,
+ lon: 11.58,
+ apiKey: "test-key",
+ type: "current"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get("https://api.openweathermap.org/data/3.0/onecall", () => {
+ return HttpResponse.json(onecallData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ await dataPromise;
+
+ expect(provider.locationName).toBe("America/New_York");
+ });
+ });
+});
diff --git a/tests/unit/modules/default/weather/providers/pirateweather_spec.js b/tests/unit/modules/default/weather/providers/pirateweather_spec.js
new file mode 100644
index 00000000..e2e3a8e1
--- /dev/null
+++ b/tests/unit/modules/default/weather/providers/pirateweather_spec.js
@@ -0,0 +1,366 @@
+/**
+ * Pirate Weather Provider Tests
+ *
+ * Tests data parsing for current, forecast, and hourly weather types.
+ * Pirate Weather is a Dark Sky API compatible service.
+ */
+import { http, HttpResponse } from "msw";
+import { setupServer } from "msw/node";
+import { describe, it, expect, vi, beforeAll, afterAll, afterEach } from "vitest";
+
+import pirateweatherData from "../../../../../mocks/weather_pirateweather.json" with { type: "json" };
+
+const PIRATEWEATHER_URL = "https://api.pirateweather.net/forecast/*";
+
+let server;
+
+beforeAll(() => {
+ server = setupServer();
+ server.listen({ onUnhandledRequest: "bypass" });
+});
+
+afterAll(() => {
+ server.close();
+});
+
+afterEach(() => {
+ server.resetHandlers();
+});
+
+describe("PirateweatherProvider", () => {
+ let PirateweatherProvider;
+
+ beforeAll(async () => {
+ const module = await import("../../../../../../defaultmodules/weather/providers/pirateweather");
+ PirateweatherProvider = module.default || module;
+ });
+
+ describe("Constructor & Configuration", () => {
+ it("should set config values from params", () => {
+ const provider = new PirateweatherProvider({
+ apiKey: "test-api-key",
+ lat: 40.71,
+ lon: -74.0,
+ type: "current"
+ });
+ expect(provider.config.apiKey).toBe("test-api-key");
+ expect(provider.config.lat).toBe(40.71);
+ expect(provider.config.lon).toBe(-74.0);
+ });
+
+ it("should error if API key is missing", async () => {
+ const provider = new PirateweatherProvider({
+ lat: 40.71,
+ lon: -74.0
+ });
+
+ const errorPromise = new Promise((resolve) => {
+ provider.setCallbacks(vi.fn(), resolve);
+ });
+
+ await provider.initialize();
+
+ const error = await errorPromise;
+ expect(error.message).toContain("API key");
+ });
+ });
+
+ describe("Current Weather Parsing", () => {
+ it("should parse current weather data", async () => {
+ const provider = new PirateweatherProvider({
+ apiKey: "test-key",
+ lat: 40.71,
+ lon: -74.0,
+ type: "current"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get(PIRATEWEATHER_URL, () => {
+ return HttpResponse.json(pirateweatherData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(result).toBeDefined();
+ expect(result.temperature).toBe(-0.26);
+ expect(result.feelsLikeTemp).toBe(-4.77);
+ expect(result.windSpeed).toBe(2.32);
+ expect(result.windFromDirection).toBe(166);
+ expect(Math.round(result.humidity)).toBe(56); // 0.56 * 100 with rounding
+ });
+
+ it("should include sunrise/sunset from daily data", async () => {
+ const provider = new PirateweatherProvider({
+ apiKey: "test-key",
+ lat: 40.71,
+ lon: -74.0,
+ type: "current"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get(PIRATEWEATHER_URL, () => {
+ return HttpResponse.json(pirateweatherData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(result.sunrise).toBeInstanceOf(Date);
+ expect(result.sunset).toBeInstanceOf(Date);
+ });
+
+ it("should convert icon to weather type", async () => {
+ const provider = new PirateweatherProvider({
+ apiKey: "test-key",
+ lat: 40.71,
+ lon: -74.0,
+ type: "current"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get(PIRATEWEATHER_URL, () => {
+ return HttpResponse.json(pirateweatherData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ // "cloudy" icon from real data
+ expect(result.weatherType).toBe("cloudy");
+ });
+ });
+
+ describe("Forecast Parsing", () => {
+ it("should parse daily forecast data", async () => {
+ const provider = new PirateweatherProvider({
+ apiKey: "test-key",
+ lat: 40.71,
+ lon: -74.0,
+ type: "forecast"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get(PIRATEWEATHER_URL, () => {
+ return HttpResponse.json(pirateweatherData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(Array.isArray(result)).toBe(true);
+ expect(result).toHaveLength(8);
+ const day = result[0];
+ expect(day).toHaveProperty("date");
+ expect(day).toHaveProperty("minTemperature");
+ expect(day).toHaveProperty("maxTemperature");
+ expect(day).toHaveProperty("weatherType");
+ expect(day).toHaveProperty("precipitationProbability");
+ });
+
+ it("should convert precipitation accumulation from cm to mm", async () => {
+ const provider = new PirateweatherProvider({
+ apiKey: "test-key",
+ lat: 40.71,
+ lon: -74.0,
+ type: "forecast"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get(PIRATEWEATHER_URL, () => {
+ return HttpResponse.json(pirateweatherData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ // First day has precipAccumulation: 0.0 cm
+ expect(result[0].precipitationAmount).toBe(0);
+ });
+
+ it("should categorize precipitation by type", async () => {
+ const provider = new PirateweatherProvider({
+ apiKey: "test-key",
+ lat: 40.71,
+ lon: -74.0,
+ type: "forecast"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get(PIRATEWEATHER_URL, () => {
+ return HttpResponse.json(pirateweatherData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ // First day has precipType: "snow"
+ expect(result[0].rain).toBe(0);
+ expect(result[0].snow).toBe(0);
+
+ // Second day has precipType: "snow" with 0.0 accumulation
+ expect(result[1].rain).toBe(0);
+ expect(result[1].snow).toBe(0);
+ });
+
+ it("should convert precipitation probability to percentage", async () => {
+ const provider = new PirateweatherProvider({
+ apiKey: "test-key",
+ lat: 40.71,
+ lon: -74.0,
+ type: "forecast"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get(PIRATEWEATHER_URL, () => {
+ return HttpResponse.json(pirateweatherData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ // 0.33 -> 33%
+ expect(result[0].precipitationProbability).toBe(33);
+ });
+ });
+
+ describe("Hourly Parsing", () => {
+ it("should parse hourly forecast data", async () => {
+ const provider = new PirateweatherProvider({
+ apiKey: "test-key",
+ lat: 40.71,
+ lon: -74.0,
+ type: "hourly"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get(PIRATEWEATHER_URL, () => {
+ return HttpResponse.json(pirateweatherData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(Array.isArray(result)).toBe(true);
+ expect(result).toHaveLength(48);
+
+ const hour = result[0];
+ expect(hour).toHaveProperty("date");
+ expect(hour).toHaveProperty("temperature");
+ expect(hour).toHaveProperty("feelsLikeTemp");
+ expect(hour).toHaveProperty("windSpeed");
+ expect(hour).toHaveProperty("weatherType");
+ });
+
+ it("should handle hourly precipitation", async () => {
+ const provider = new PirateweatherProvider({
+ apiKey: "test-key",
+ lat: 40.71,
+ lon: -74.0,
+ type: "hourly"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get(PIRATEWEATHER_URL, () => {
+ return HttpResponse.json(pirateweatherData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ // First hour has 0.0 cm precipitation
+ expect(result[0].precipitationAmount).toBe(0);
+ expect(result[0].rain).toBe(0);
+ });
+ });
+
+ describe("Error Handling", () => {
+ it("should handle invalid JSON response", async () => {
+ const provider = new PirateweatherProvider({
+ apiKey: "test-key",
+ lat: 40.71,
+ lon: -74.0,
+ type: "current"
+ });
+
+ const errorPromise = new Promise((resolve) => {
+ provider.setCallbacks(vi.fn(), resolve);
+ });
+
+ server.use(
+ http.get(PIRATEWEATHER_URL, () => {
+ return HttpResponse.json({});
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const error = await errorPromise;
+ expect(error.message).toContain("No usable data");
+ });
+ });
+});
diff --git a/tests/unit/modules/default/weather/providers/smhi_spec.js b/tests/unit/modules/default/weather/providers/smhi_spec.js
new file mode 100644
index 00000000..b7e12117
--- /dev/null
+++ b/tests/unit/modules/default/weather/providers/smhi_spec.js
@@ -0,0 +1,208 @@
+/**
+ * SMHI Weather Provider Tests
+ *
+ * Tests data parsing for current, forecast, and hourly weather types.
+ * SMHI provides data only for Sweden, uses metric system.
+ */
+import { http, HttpResponse } from "msw";
+import { setupServer } from "msw/node";
+import { describe, it, expect, vi, beforeAll, afterAll, afterEach } from "vitest";
+
+import smhiData from "../../../../../mocks/weather_smhi.json" with { type: "json" };
+
+let server;
+
+beforeAll(() => {
+ server = setupServer();
+ server.listen({ onUnhandledRequest: "bypass" });
+});
+
+afterAll(() => {
+ server.close();
+});
+
+afterEach(() => {
+ server.resetHandlers();
+});
+
+describe("SMHIProvider", () => {
+ let SMHIProvider;
+
+ beforeAll(async () => {
+ const module = await import("../../../../../../defaultmodules/weather/providers/smhi");
+ SMHIProvider = module.default;
+ });
+
+ describe("Constructor & Configuration", () => {
+ it("should set config values from params", () => {
+ const provider = new SMHIProvider({
+ lat: 59.3293,
+ lon: 18.0686
+ });
+ expect(provider.config.lat).toBe(59.3293);
+ expect(provider.config.lon).toBe(18.0686);
+ expect(provider.config.precipitationValue).toBe("pmedian");
+ });
+
+ it("should fallback to pmedian for invalid precipitationValue", () => {
+ const provider = new SMHIProvider({
+ precipitationValue: "invalid"
+ });
+ expect(provider.config.precipitationValue).toBe("pmedian");
+ });
+
+ it("should accept valid precipitationValue options", () => {
+ for (const value of ["pmin", "pmean", "pmedian", "pmax"]) {
+ const provider = new SMHIProvider({ precipitationValue: value });
+ expect(provider.config.precipitationValue).toBe(value);
+ }
+ });
+ });
+
+ describe("Coordinate Validation", () => {
+ it("should limit coordinates to 6 decimal places", async () => {
+ const provider = new SMHIProvider({
+ lat: 59.32930123456789,
+ lon: 18.06860123456789
+ });
+ provider.setCallbacks(vi.fn(), vi.fn());
+
+ server.use(
+ http.get("https://opendata-download-metfcst.smhi.se/*", () => {
+ return HttpResponse.json(smhiData);
+ })
+ );
+
+ await provider.initialize();
+
+ // After validateCoordinates(config, 6), decimals should be truncated
+ expect(provider.config.lat.toString().split(".")[1]?.length).toBeLessThanOrEqual(6);
+ expect(provider.config.lon.toString().split(".")[1]?.length).toBeLessThanOrEqual(6);
+ });
+ });
+
+ describe("Current Weather Parsing", () => {
+ it("should parse current weather from timeSeries", async () => {
+ const provider = new SMHIProvider({
+ lat: 59.3293,
+ lon: 18.0686,
+ type: "current"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get("https://opendata-download-metfcst.smhi.se/*", () => {
+ return HttpResponse.json(smhiData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(result).toBeDefined();
+ expect(typeof result.temperature).toBe("number");
+ expect(typeof result.windSpeed).toBe("number");
+ expect(typeof result.humidity).toBe("number");
+ expect(result.sunrise).toBeInstanceOf(Date);
+ expect(result.sunset).toBeInstanceOf(Date);
+ });
+
+ it("should detect precipitation category correctly", async () => {
+ const provider = new SMHIProvider({
+ lat: 59.3293,
+ lon: 18.0686,
+ type: "current"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ // Use data with rain (pcat=3 at index 2)
+ const rainData = JSON.parse(JSON.stringify(smhiData));
+ // Make the rain entry the closest to "now"
+ rainData.timeSeries = [rainData.timeSeries[2]];
+ rainData.timeSeries[0].validTime = new Date().toISOString();
+
+ server.use(
+ http.get("https://opendata-download-metfcst.smhi.se/*", () => {
+ return HttpResponse.json(rainData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(result.rain).toBe(0.0); // pmedian value with pcat=3 (rain)
+ expect(result.precipitationAmount).toBe(0.0);
+ expect(result.snow).toBe(0);
+ });
+ });
+
+ describe("Forecast Parsing", () => {
+ it("should parse daily forecast data", async () => {
+ const provider = new SMHIProvider({
+ lat: 59.3293,
+ lon: 18.0686,
+ type: "forecast"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get("https://opendata-download-metfcst.smhi.se/*", () => {
+ return HttpResponse.json(smhiData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(Array.isArray(result)).toBe(true);
+ expect(result.length).toBeGreaterThan(0);
+
+ const firstDay = result[0];
+ expect(firstDay).toHaveProperty("date");
+ expect(firstDay).toHaveProperty("minTemperature");
+ expect(firstDay).toHaveProperty("maxTemperature");
+ expect(firstDay.minTemperature).toBeLessThanOrEqual(firstDay.maxTemperature);
+ });
+ });
+
+ describe("Error Handling", () => {
+ it("should call error callback on invalid data", async () => {
+ const provider = new SMHIProvider({
+ lat: 59.3293,
+ lon: 18.0686,
+ type: "current"
+ });
+
+ const errorPromise = new Promise((resolve) => {
+ provider.setCallbacks(vi.fn(), resolve);
+ });
+
+ server.use(
+ http.get("https://opendata-download-metfcst.smhi.se/*", () => {
+ return HttpResponse.json({ invalid: true });
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const error = await errorPromise;
+ expect(error).toHaveProperty("message");
+ });
+ });
+});
diff --git a/tests/unit/modules/default/weather/providers/ukmetofficedatahub_spec.js b/tests/unit/modules/default/weather/providers/ukmetofficedatahub_spec.js
new file mode 100644
index 00000000..7bda9a6b
--- /dev/null
+++ b/tests/unit/modules/default/weather/providers/ukmetofficedatahub_spec.js
@@ -0,0 +1,348 @@
+/**
+ * UK Met Office DataHub Weather Provider Tests
+ *
+ * Tests data parsing for current, forecast, and hourly weather types.
+ */
+import { http, HttpResponse } from "msw";
+import { setupServer } from "msw/node";
+import { describe, it, expect, vi, beforeAll, afterAll, afterEach } from "vitest";
+
+import hourlyData from "../../../../../mocks/weather_ukmetoffice.json" with { type: "json" };
+import dailyData from "../../../../../mocks/weather_ukmetoffice_daily.json" with { type: "json" };
+
+const UKMETOFFICE_HOURLY_URL = "https://data.hub.api.metoffice.gov.uk/sitespecific/v0/point/hourly*";
+const UKMETOFFICE_THREE_HOURLY_URL = "https://data.hub.api.metoffice.gov.uk/sitespecific/v0/point/three-hourly*";
+const UKMETOFFICE_DAILY_URL = "https://data.hub.api.metoffice.gov.uk/sitespecific/v0/point/daily*";
+
+/**
+ * Returns a copy of the daily mock response with dates shifted to today and future days.
+ * @param {object} source Source UK Met Office daily mock payload.
+ * @returns {object} Cloned payload with deterministic future dates in `timeSeries`.
+ */
+function withFutureDailyTimes (source) {
+ const clone = JSON.parse(JSON.stringify(source));
+ const today = new Date();
+ today.setUTCHours(0, 0, 0, 0);
+
+ clone.features[0].properties.timeSeries = clone.features[0].properties.timeSeries.map((day, index) => {
+ const shiftedDate = new Date(today);
+ shiftedDate.setUTCDate(today.getUTCDate() + index);
+
+ return {
+ ...day,
+ time: `${shiftedDate.toISOString().split("T")[0]}T00:00Z`
+ };
+ });
+
+ return clone;
+}
+
+let server;
+
+beforeAll(() => {
+ server = setupServer();
+ server.listen({ onUnhandledRequest: "bypass" });
+});
+
+afterAll(() => {
+ server.close();
+});
+
+afterEach(() => {
+ server.resetHandlers();
+});
+
+describe("UKMetOfficeDataHubProvider", () => {
+ let UKMetOfficeDataHubProvider;
+
+ beforeAll(async () => {
+ const module = await import("../../../../../../defaultmodules/weather/providers/ukmetofficedatahub");
+ UKMetOfficeDataHubProvider = module.default || module;
+ });
+
+ describe("Constructor & Configuration", () => {
+ it("should set config values from params", () => {
+ const provider = new UKMetOfficeDataHubProvider({
+ apiKey: "test-api-key",
+ lat: 51.5,
+ lon: -0.12,
+ type: "current"
+ });
+ expect(provider.config.apiKey).toBe("test-api-key");
+ expect(provider.config.lat).toBe(51.5);
+ expect(provider.config.lon).toBe(-0.12);
+ });
+
+ it("should error if API key is missing", async () => {
+ const provider = new UKMetOfficeDataHubProvider({
+ lat: 51.5,
+ lon: -0.12
+ });
+
+ const errorPromise = new Promise((resolve) => {
+ provider.setCallbacks(vi.fn(), resolve);
+ });
+
+ await provider.initialize();
+
+ const error = await errorPromise;
+ expect(error.message).toContain("API key");
+ });
+ });
+
+ describe("Forecast Type Mapping", () => {
+ it("should use hourly endpoint for current type", async () => {
+ const provider = new UKMetOfficeDataHubProvider({
+ apiKey: "test-key",
+ lat: 51.5,
+ lon: -0.12,
+ type: "current"
+ });
+
+ let requestedUrl = null;
+ server.use(
+ http.get(UKMETOFFICE_HOURLY_URL, ({ request }) => {
+ requestedUrl = request.url;
+ return HttpResponse.json(hourlyData);
+ })
+ );
+
+ provider.setCallbacks(vi.fn(), vi.fn());
+ await provider.initialize();
+ provider.start();
+
+ await new Promise((resolve) => setTimeout(resolve, 100));
+ expect(requestedUrl).toContain("/hourly?");
+ });
+
+ it("should use daily endpoint for forecast type", async () => {
+ const provider = new UKMetOfficeDataHubProvider({
+ apiKey: "test-key",
+ lat: 51.5,
+ lon: -0.12,
+ type: "forecast"
+ });
+
+ let requestedUrl = null;
+ server.use(
+ http.get(UKMETOFFICE_DAILY_URL, ({ request }) => {
+ requestedUrl = request.url;
+ return HttpResponse.json(dailyData);
+ })
+ );
+
+ provider.setCallbacks(vi.fn(), vi.fn());
+ await provider.initialize();
+ provider.start();
+
+ await new Promise((resolve) => setTimeout(resolve, 100));
+ expect(requestedUrl).toContain("/daily?");
+ });
+
+ it("should use three-hourly endpoint for hourly type", async () => {
+ const provider = new UKMetOfficeDataHubProvider({
+ apiKey: "test-key",
+ lat: 51.5,
+ lon: -0.12,
+ type: "hourly"
+ });
+
+ let requestedUrl = null;
+ server.use(
+ http.get(UKMETOFFICE_THREE_HOURLY_URL, ({ request }) => {
+ requestedUrl = request.url;
+ return HttpResponse.json(hourlyData);
+ })
+ );
+
+ provider.setCallbacks(vi.fn(), vi.fn());
+ await provider.initialize();
+ provider.start();
+
+ await new Promise((resolve) => setTimeout(resolve, 100));
+ expect(requestedUrl).toContain("/three-hourly?");
+ });
+ });
+
+ describe("Current Weather Parsing", () => {
+ it("should parse current weather from hourly data", async () => {
+ const provider = new UKMetOfficeDataHubProvider({
+ apiKey: "test-key",
+ lat: 51.5,
+ lon: -0.12,
+ type: "current"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get(UKMETOFFICE_HOURLY_URL, () => {
+ return HttpResponse.json(hourlyData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(result).toBeDefined();
+ expect(result.temperature).toBeDefined();
+ expect(result.windSpeed).toBeDefined();
+ expect(result.humidity).toBeDefined();
+ expect(result.weatherType).not.toBeNull();
+ });
+
+ it("should include sunrise/sunset from SunCalc", async () => {
+ const provider = new UKMetOfficeDataHubProvider({
+ apiKey: "test-key",
+ lat: 51.5,
+ lon: -0.12,
+ type: "current"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get(UKMETOFFICE_HOURLY_URL, () => {
+ return HttpResponse.json(hourlyData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(result.sunrise).toBeInstanceOf(Date);
+ expect(result.sunset).toBeInstanceOf(Date);
+ });
+
+ it("should convert weather code to weather type", async () => {
+ const provider = new UKMetOfficeDataHubProvider({
+ apiKey: "test-key",
+ lat: 51.5,
+ lon: -0.12,
+ type: "current"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get(UKMETOFFICE_HOURLY_URL, () => {
+ return HttpResponse.json(hourlyData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(result.weatherType).toBeTruthy();
+ });
+ });
+
+ describe("Forecast Parsing", () => {
+ it("should parse daily forecast data", async () => {
+ const provider = new UKMetOfficeDataHubProvider({
+ apiKey: "test-key",
+ lat: 51.5,
+ lon: -0.12,
+ type: "forecast"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get(UKMETOFFICE_DAILY_URL, () => {
+ return HttpResponse.json(withFutureDailyTimes(dailyData));
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(Array.isArray(result)).toBe(true);
+ expect(result.length).toBeGreaterThan(0);
+
+ const day = result[0];
+ expect(day).toHaveProperty("date");
+ expect(day).toHaveProperty("minTemperature");
+ expect(day).toHaveProperty("maxTemperature");
+ expect(day).toHaveProperty("weatherType");
+ });
+ });
+
+ describe("Hourly Parsing", () => {
+ it("should parse hourly forecast data", async () => {
+ const provider = new UKMetOfficeDataHubProvider({
+ apiKey: "test-key",
+ lat: 51.5,
+ lon: -0.12,
+ type: "hourly"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get(UKMETOFFICE_THREE_HOURLY_URL, () => {
+ return HttpResponse.json(hourlyData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(Array.isArray(result)).toBe(true);
+ expect(result.length).toBeGreaterThan(0);
+
+ const hour = result[0];
+ expect(hour).toHaveProperty("date");
+ expect(hour).toHaveProperty("temperature");
+ expect(hour).toHaveProperty("windSpeed");
+ expect(hour).toHaveProperty("weatherType");
+ });
+ });
+
+ describe("Error Handling", () => {
+ it("should handle invalid response", async () => {
+ const provider = new UKMetOfficeDataHubProvider({
+ apiKey: "test-key",
+ lat: 51.5,
+ lon: -0.12,
+ type: "current"
+ });
+
+ const errorPromise = new Promise((resolve) => {
+ provider.setCallbacks(vi.fn(), resolve);
+ });
+
+ server.use(
+ http.get(UKMETOFFICE_HOURLY_URL, () => {
+ return HttpResponse.json({});
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const error = await errorPromise;
+ expect(error).toHaveProperty("message");
+ });
+ });
+});
diff --git a/tests/unit/modules/default/weather/providers/weatherapi_spec.js b/tests/unit/modules/default/weather/providers/weatherapi_spec.js
new file mode 100644
index 00000000..413360f6
--- /dev/null
+++ b/tests/unit/modules/default/weather/providers/weatherapi_spec.js
@@ -0,0 +1,311 @@
+/**
+ * WeatherAPI Provider Tests
+ *
+ * Tests data parsing for current, forecast, and hourly weather types.
+ */
+import { http, HttpResponse } from "msw";
+import { setupServer } from "msw/node";
+import { describe, it, expect, vi, beforeAll, afterAll, afterEach } from "vitest";
+
+const WEATHER_API_URL = "https://api.weatherapi.com/v1/forecast.json*";
+
+/**
+ * Builds a stable WeatherAPI mock payload for current, daily, and hourly parsing tests.
+ * @returns {object} WeatherAPI forecast response fixture.
+ */
+function buildWeatherApiResponse () {
+ return {
+ location: {
+ name: "Toronto",
+ region: "Ontario",
+ country: "Canada"
+ },
+ current: {
+ last_updated_epoch: 4102444800,
+ temp_c: -2.5,
+ feelslike_c: -7.1,
+ humidity: 75,
+ wind_kph: 18,
+ wind_degree: 220,
+ condition: { code: 1003 },
+ is_day: 1,
+ snow_cm: 0.2,
+ precip_mm: 1.1,
+ uv: 2
+ },
+ forecast: {
+ forecastday: [
+ {
+ date: "2100-01-01",
+ date_epoch: 4102444800,
+ astro: {
+ sunrise: "07:45 AM",
+ sunset: "05:05 PM"
+ },
+ day: {
+ mintemp_c: -8,
+ maxtemp_c: -1,
+ avgtemp_c: -4,
+ avghumidity: 81,
+ totalsnow_cm: 0.6,
+ totalprecip_mm: 2,
+ maxwind_kph: 22,
+ uv: 1,
+ condition: { code: 1183 }
+ },
+ hour: [
+ {
+ time: "2100-01-01 01:00",
+ time_epoch: 4102448400,
+ temp_c: -5,
+ humidity: 85,
+ wind_kph: 15,
+ wind_degree: 210,
+ wind_dir: "SSW",
+ condition: { code: 1183 },
+ is_day: 0,
+ snow_cm: 0.1,
+ precip_mm: 0.5,
+ will_it_rain: 1,
+ will_it_snow: 0,
+ uv: 0
+ },
+ {
+ time: "2100-01-01 02:00",
+ time_epoch: 4102452000,
+ temp_c: -4.5,
+ humidity: 83,
+ wind_kph: 13,
+ wind_degree: 205,
+ wind_dir: "SSW",
+ condition: { code: 1003 },
+ is_day: 0,
+ snow_cm: 0,
+ precip_mm: 0.2,
+ will_it_rain: 0,
+ will_it_snow: 0,
+ uv: 0
+ },
+ {
+ time: "2100-01-01 03:00",
+ time_epoch: 4102455600,
+ temp_c: -4,
+ humidity: 80,
+ wind_kph: 12,
+ wind_degree: 200,
+ wind_dir: "SSW",
+ condition: { code: 1000 },
+ is_day: 0,
+ snow_cm: 0,
+ precip_mm: 0,
+ will_it_rain: 0,
+ will_it_snow: 0,
+ uv: 0
+ }
+ ]
+ },
+ {
+ date: "2100-01-02",
+ date_epoch: 4102531200,
+ astro: {
+ sunrise: "07:44 AM",
+ sunset: "05:06 PM"
+ },
+ day: {
+ mintemp_c: -7,
+ maxtemp_c: 0,
+ avgtemp_c: -3.3,
+ avghumidity: 78,
+ totalsnow_cm: 0,
+ totalprecip_mm: 0.4,
+ maxwind_kph: 20,
+ uv: 2,
+ condition: { code: 1006 }
+ },
+ hour: []
+ }
+ ]
+ }
+ };
+}
+
+let server;
+
+beforeAll(() => {
+ server = setupServer();
+ server.listen({ onUnhandledRequest: "bypass" });
+});
+
+afterAll(() => {
+ server.close();
+});
+
+afterEach(() => {
+ server.resetHandlers();
+});
+
+describe("WeatherAPIProvider", () => {
+ let WeatherAPIProvider;
+
+ beforeAll(async () => {
+ const module = await import("../../../../../../defaultmodules/weather/providers/weatherapi");
+ WeatherAPIProvider = module.default;
+ });
+
+ describe("Constructor & Configuration", () => {
+ it("should set config values from params", () => {
+ const provider = new WeatherAPIProvider({
+ lat: 43.65,
+ lon: -79.38,
+ apiKey: "test-key",
+ type: "current"
+ });
+ expect(provider.config.lat).toBe(43.65);
+ expect(provider.config.lon).toBe(-79.38);
+ expect(provider.config.apiKey).toBe("test-key");
+ expect(provider.config.type).toBe("current");
+ });
+
+ it("should have default values", () => {
+ const provider = new WeatherAPIProvider({ apiKey: "test-key" });
+ expect(provider.config.apiBase).toBe("https://api.weatherapi.com/v1");
+ expect(provider.config.type).toBe("current");
+ expect(provider.config.maxEntries).toBe(5);
+ expect(provider.config.updateInterval).toBe(10 * 60 * 1000);
+ });
+ });
+
+ describe("Current Weather Parsing", () => {
+ it("should parse current weather data correctly", async () => {
+ const provider = new WeatherAPIProvider({
+ lat: 43.65,
+ lon: -79.38,
+ apiKey: "test-key",
+ type: "current"
+ });
+
+ const dataPromise = new Promise((resolve, reject) => {
+ provider.setCallbacks(resolve, reject);
+ });
+
+ server.use(
+ http.get(WEATHER_API_URL, () => HttpResponse.json(buildWeatherApiResponse()))
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(result).toBeDefined();
+ expect(result.temperature).toBe(-2.5);
+ expect(result.feelsLikeTemp).toBe(-7.1);
+ expect(result.humidity).toBe(75);
+ expect(result.windSpeed).toBeCloseTo(5, 1);
+ expect(result.windFromDirection).toBe(220);
+ expect(result.weatherType).toBe("day-cloudy");
+ expect(result.sunrise).toBeInstanceOf(Date);
+ expect(result.sunset).toBeInstanceOf(Date);
+ expect(result.minTemperature).toBe(-8);
+ expect(result.maxTemperature).toBe(-1);
+ });
+ });
+
+ describe("Forecast Parsing", () => {
+ it("should parse daily forecast data correctly", async () => {
+ const provider = new WeatherAPIProvider({
+ lat: 43.65,
+ lon: -79.38,
+ apiKey: "test-key",
+ type: "forecast",
+ maxEntries: 2,
+ maxNumberOfDays: 2
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get(WEATHER_API_URL, () => HttpResponse.json(buildWeatherApiResponse()))
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(Array.isArray(result)).toBe(true);
+ expect(result).toHaveLength(2);
+ expect(result[0].minTemperature).toBe(-8);
+ expect(result[0].maxTemperature).toBe(-1);
+ expect(result[0].weatherType).toBe("day-sprinkle");
+ expect(result[0].sunrise).toBeInstanceOf(Date);
+ expect(result[0].sunset).toBeInstanceOf(Date);
+ });
+ });
+
+ describe("Hourly Parsing", () => {
+ it("should parse hourly forecast data correctly", async () => {
+ const provider = new WeatherAPIProvider({
+ lat: 43.65,
+ lon: -79.38,
+ apiKey: "test-key",
+ type: "hourly",
+ maxEntries: 3,
+ maxNumberOfDays: 1
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get(WEATHER_API_URL, () => HttpResponse.json(buildWeatherApiResponse()))
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(Array.isArray(result)).toBe(true);
+ expect(result).toHaveLength(3);
+ expect(result[0].temperature).toBe(-5);
+ expect(result[0].humidity).toBe(85);
+ expect(result[0].windFromDirection).toBe(210);
+ expect(result[0].weatherType).toBe("night-sprinkle");
+ expect(result[0].precipitationProbability).toBe(50);
+ });
+ });
+
+ describe("Error Handling", () => {
+ it("should call error callback on invalid API response", async () => {
+ const provider = new WeatherAPIProvider({
+ lat: 43.65,
+ lon: -79.38,
+ apiKey: "test-key",
+ type: "current"
+ });
+
+ const errorPromise = new Promise((resolve) => {
+ provider.setCallbacks(vi.fn(), resolve);
+ });
+
+ server.use(
+ http.get(WEATHER_API_URL, () => HttpResponse.json({
+ location: {},
+ current: {},
+ forecast: { forecastday: "invalid" }
+ }))
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const error = await errorPromise;
+ expect(error).toHaveProperty("message");
+ expect(error).toHaveProperty("translationKey");
+ });
+ });
+});
diff --git a/tests/unit/modules/default/weather/providers/weatherbit_spec.js b/tests/unit/modules/default/weather/providers/weatherbit_spec.js
new file mode 100644
index 00000000..8bea45f1
--- /dev/null
+++ b/tests/unit/modules/default/weather/providers/weatherbit_spec.js
@@ -0,0 +1,247 @@
+/**
+ * Weatherbit Weather Provider Tests
+ *
+ * Tests data parsing for current, forecast, and hourly weather types.
+ */
+import { http, HttpResponse } from "msw";
+import { setupServer } from "msw/node";
+import { describe, it, expect, vi, beforeAll, afterAll, afterEach } from "vitest";
+
+import currentData from "../../../../../mocks/weather_weatherbit.json" with { type: "json" };
+import forecastData from "../../../../../mocks/weather_weatherbit_forecast.json" with { type: "json" };
+import hourlyData from "../../../../../mocks/weather_weatherbit_hourly.json" with { type: "json" };
+
+const WEATHERBIT_CURRENT_URL = "https://api.weatherbit.io/v2.0/current*";
+const WEATHERBIT_FORECAST_URL = "https://api.weatherbit.io/v2.0/forecast/daily*";
+const WEATHERBIT_HOURLY_URL = "https://api.weatherbit.io/v2.0/forecast/hourly*";
+
+let server;
+
+beforeAll(() => {
+ server = setupServer();
+ server.listen({ onUnhandledRequest: "bypass" });
+});
+
+afterAll(() => {
+ server.close();
+});
+
+afterEach(() => {
+ server.resetHandlers();
+});
+
+describe("WeatherbitProvider", () => {
+ let WeatherbitProvider;
+
+ beforeAll(async () => {
+ const module = await import("../../../../../../defaultmodules/weather/providers/weatherbit");
+ WeatherbitProvider = module.default || module;
+ });
+
+ describe("Constructor & Configuration", () => {
+ it("should set config values from params", () => {
+ const provider = new WeatherbitProvider({
+ apiKey: "test-api-key",
+ lat: 40.71,
+ lon: -74.0,
+ type: "current"
+ });
+ expect(provider.config.apiKey).toBe("test-api-key");
+ expect(provider.config.lat).toBe(40.71);
+ expect(provider.config.lon).toBe(-74.0);
+ });
+
+ it("should error if API key is missing", async () => {
+ const provider = new WeatherbitProvider({
+ lat: 40.71,
+ lon: -74.0
+ });
+
+ const errorPromise = new Promise((resolve) => {
+ provider.setCallbacks(vi.fn(), resolve);
+ });
+
+ await provider.initialize();
+
+ const error = await errorPromise;
+ expect(error.message).toContain("API key");
+ });
+ });
+
+ describe("Current Weather Parsing", () => {
+ it("should parse current weather data", async () => {
+ const provider = new WeatherbitProvider({
+ apiKey: "test-key",
+ lat: 40.71,
+ lon: -74.0,
+ type: "current"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get(WEATHERBIT_CURRENT_URL, () => {
+ return HttpResponse.json(currentData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(result).toBeDefined();
+ expect(result.temperature).toBe(1);
+ expect(result.windSpeed).toBe(1.5);
+ expect(result.windFromDirection).toBe(210);
+ expect(result.humidity).toBe(47);
+ });
+
+ it("should parse sunrise/sunset from HH:mm format", async () => {
+ const provider = new WeatherbitProvider({
+ apiKey: "test-key",
+ lat: 40.71,
+ lon: -74.0,
+ type: "current"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get(WEATHERBIT_CURRENT_URL, () => {
+ return HttpResponse.json(currentData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(result.sunrise).toBeInstanceOf(Date);
+ expect(result.sunset).toBeInstanceOf(Date);
+ });
+
+ it("should convert icon code to weather type", async () => {
+ const provider = new WeatherbitProvider({
+ apiKey: "test-key",
+ lat: 40.71,
+ lon: -74.0,
+ type: "current"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get(WEATHERBIT_CURRENT_URL, () => {
+ return HttpResponse.json(currentData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(result.weatherType).not.toBeNull();
+ });
+ });
+
+ describe("Forecast Parsing", () => {
+ it("should parse daily forecast data", async () => {
+ const provider = new WeatherbitProvider({
+ apiKey: "test-key",
+ lat: 40.71,
+ lon: -74.0,
+ type: "forecast"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get(WEATHERBIT_FORECAST_URL, () => {
+ return HttpResponse.json(forecastData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(Array.isArray(result)).toBe(true);
+ expect(result.length).toBeGreaterThan(0);
+
+ const day = result[0];
+ expect(day).toHaveProperty("date");
+ expect(day).toHaveProperty("minTemperature");
+ expect(day).toHaveProperty("maxTemperature");
+ expect(day).toHaveProperty("weatherType");
+ expect(day).toHaveProperty("precipitationProbability");
+ });
+ });
+
+ describe("Hourly Parsing", () => {
+ it("should handle hourly API endpoint access error", async () => {
+ const provider = new WeatherbitProvider({
+ apiKey: "test-key",
+ lat: 40.71,
+ lon: -74.0,
+ type: "hourly"
+ });
+
+ const errorPromise = new Promise((resolve) => {
+ provider.setCallbacks(vi.fn(), resolve);
+ });
+
+ server.use(
+ http.get(WEATHERBIT_HOURLY_URL, () => {
+ return HttpResponse.json(hourlyData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const error = await errorPromise;
+
+ expect(error).toBeDefined();
+ expect(error.message || error).toContain("No usable data");
+ });
+ });
+
+ describe("Error Handling", () => {
+ it("should handle invalid response", async () => {
+ const provider = new WeatherbitProvider({
+ apiKey: "test-key",
+ lat: 40.71,
+ lon: -74.0,
+ type: "current"
+ });
+
+ const errorPromise = new Promise((resolve) => {
+ provider.setCallbacks(vi.fn(), resolve);
+ });
+
+ server.use(
+ http.get(WEATHERBIT_CURRENT_URL, () => {
+ return HttpResponse.json({ data: [] });
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const error = await errorPromise;
+ expect(error).toHaveProperty("message");
+ });
+ });
+});
diff --git a/tests/unit/modules/default/weather/providers/weatherflow_spec.js b/tests/unit/modules/default/weather/providers/weatherflow_spec.js
new file mode 100644
index 00000000..2eb2fdb4
--- /dev/null
+++ b/tests/unit/modules/default/weather/providers/weatherflow_spec.js
@@ -0,0 +1,264 @@
+/**
+ * WeatherFlow Weather Provider Tests
+ *
+ * Tests data parsing for current, forecast, and hourly weather types.
+ */
+import { http, HttpResponse } from "msw";
+import { setupServer } from "msw/node";
+import { describe, it, expect, vi, beforeAll, afterAll, afterEach } from "vitest";
+
+import weatherflowData from "../../../../../mocks/weather_weatherflow.json" with { type: "json" };
+
+const WEATHERFLOW_URL = "https://swd.weatherflow.com/swd/rest/better_forecast*";
+
+let server;
+
+beforeAll(() => {
+ server = setupServer();
+ server.listen({ onUnhandledRequest: "bypass" });
+});
+
+afterAll(() => {
+ server.close();
+});
+
+afterEach(() => {
+ server.resetHandlers();
+});
+
+describe("WeatherFlowProvider", () => {
+ let WeatherFlowProvider;
+
+ beforeAll(async () => {
+ const module = await import("../../../../../../defaultmodules/weather/providers/weatherflow");
+ WeatherFlowProvider = module.default || module;
+ });
+
+ describe("Constructor & Configuration", () => {
+ it("should set config values from params", () => {
+ const provider = new WeatherFlowProvider({
+ token: "test-token",
+ stationid: "12345",
+ type: "current"
+ });
+ expect(provider.config.token).toBe("test-token");
+ expect(provider.config.stationid).toBe("12345");
+ });
+
+ it("should error if token or stationid is missing", async () => {
+ const provider = new WeatherFlowProvider({});
+
+ const errorPromise = new Promise((resolve) => {
+ provider.setCallbacks(vi.fn(), resolve);
+ });
+
+ await provider.initialize();
+
+ const error = await errorPromise;
+ expect(error.message).toContain("token");
+ });
+ });
+
+ describe("Current Weather Parsing", () => {
+ it("should parse current weather data", async () => {
+ const provider = new WeatherFlowProvider({
+ token: "test-token",
+ stationid: "12345",
+ type: "current"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get(WEATHERFLOW_URL, () => {
+ return HttpResponse.json(weatherflowData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(result).toBeDefined();
+ expect(result.temperature).toBe(16);
+ expect(result.humidity).toBe(28);
+ expect(result.weatherType).not.toBeNull();
+ });
+
+ it("should convert wind speed from km/h to m/s", async () => {
+ const provider = new WeatherFlowProvider({
+ token: "test-token",
+ stationid: "12345",
+ type: "current"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get(WEATHERFLOW_URL, () => {
+ return HttpResponse.json(weatherflowData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ // Wind speed 15 km/h -> ~4.17 m/s
+ expect(result.windSpeed).toBeCloseTo(4.17, 1);
+ });
+
+ it("should include sunrise/sunset", async () => {
+ const provider = new WeatherFlowProvider({
+ token: "test-token",
+ stationid: "12345",
+ type: "current"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get(WEATHERFLOW_URL, () => {
+ return HttpResponse.json(weatherflowData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(result.sunrise).toBeInstanceOf(Date);
+ expect(result.sunset).toBeInstanceOf(Date);
+ });
+ });
+
+ describe("Forecast Parsing", () => {
+ it("should parse daily forecast data", async () => {
+ const provider = new WeatherFlowProvider({
+ token: "test-token",
+ stationid: "12345",
+ type: "forecast"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get(WEATHERFLOW_URL, () => {
+ return HttpResponse.json(weatherflowData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(Array.isArray(result)).toBe(true);
+ expect(result.length).toBeGreaterThan(0);
+
+ const day = result[0];
+ expect(day).toHaveProperty("date");
+ expect(day).toHaveProperty("minTemperature");
+ expect(day).toHaveProperty("maxTemperature");
+ expect(day).toHaveProperty("weatherType");
+ });
+ });
+
+ describe("Hourly Parsing", () => {
+ it("should parse hourly forecast data", async () => {
+ const provider = new WeatherFlowProvider({
+ token: "test-token",
+ stationid: "12345",
+ type: "hourly"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get(WEATHERFLOW_URL, () => {
+ return HttpResponse.json(weatherflowData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(Array.isArray(result)).toBe(true);
+ expect(result.length).toBeGreaterThan(0);
+
+ const hour = result[0];
+ expect(hour).toHaveProperty("date");
+ expect(hour).toHaveProperty("temperature");
+ expect(hour).toHaveProperty("windSpeed");
+ });
+
+ it("should aggregate UV data from hourly forecasts", async () => {
+ const provider = new WeatherFlowProvider({
+ token: "test-token",
+ stationid: "12345",
+ type: "forecast"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get(WEATHERFLOW_URL, () => {
+ return HttpResponse.json(weatherflowData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ // First day should have UV from hourly data
+ expect(result[0]).toHaveProperty("uvIndex");
+ expect(result[0].uvIndex).toBeGreaterThanOrEqual(0);
+ });
+ });
+
+ describe("Error Handling", () => {
+ it("should handle invalid response", async () => {
+ const provider = new WeatherFlowProvider({
+ token: "test-token",
+ stationid: "12345",
+ type: "current"
+ });
+
+ // Invalid responses return null without calling error callback
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get(WEATHERFLOW_URL, () => {
+ return HttpResponse.json({});
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+ expect(result).toBeNull();
+ });
+ });
+});
diff --git a/tests/unit/modules/default/weather/providers/weathergov_spec.js b/tests/unit/modules/default/weather/providers/weathergov_spec.js
new file mode 100644
index 00000000..81a7edd9
--- /dev/null
+++ b/tests/unit/modules/default/weather/providers/weathergov_spec.js
@@ -0,0 +1,412 @@
+/**
+ * Weather.gov Weather Provider Tests
+ *
+ * Tests data parsing for current, forecast, and hourly weather types.
+ * Weather.gov is the US National Weather Service API.
+ */
+import { http, HttpResponse } from "msw";
+import { setupServer } from "msw/node";
+import { describe, it, expect, vi, beforeAll, afterAll, afterEach } from "vitest";
+
+import pointsData from "../../../../../mocks/weather_weathergov_points.json" with { type: "json" };
+import stationsData from "../../../../../mocks/weather_weathergov_stations.json" with { type: "json" };
+import currentData from "../../../../../mocks/weather_weathergov_current.json" with { type: "json" };
+import forecastData from "../../../../../mocks/weather_weathergov_forecast.json" with { type: "json" };
+import hourlyData from "../../../../../mocks/weather_weathergov_hourly.json" with { type: "json" };
+
+const WEATHERGOV_POINTS_URL = "https://api.weather.gov/points/*";
+const WEATHERGOV_STATIONS_URL = "https://api.weather.gov/gridpoints/*/stations";
+const WEATHERGOV_CURRENT_URL = "https://api.weather.gov/stations/*/observations/latest";
+const WEATHERGOV_FORECAST_URL = "https://api.weather.gov/gridpoints/*/forecast*";
+const WEATHERGOV_HOURLY_URL = "https://api.weather.gov/gridpoints/*/forecast/hourly*";
+
+let server;
+
+beforeAll(() => {
+ server = setupServer(
+ // Default handlers for initialization
+ http.get(WEATHERGOV_POINTS_URL, () => {
+ return HttpResponse.json(pointsData);
+ }),
+ http.get(WEATHERGOV_STATIONS_URL, () => {
+ return HttpResponse.json(stationsData);
+ })
+ );
+ server.listen({ onUnhandledRequest: "bypass" });
+});
+
+afterAll(() => {
+ server.close();
+});
+
+afterEach(() => {
+ server.resetHandlers();
+ // Re-add default initialization handlers
+ server.use(
+ http.get(WEATHERGOV_POINTS_URL, () => {
+ return HttpResponse.json(pointsData);
+ }),
+ http.get(WEATHERGOV_STATIONS_URL, () => {
+ return HttpResponse.json(stationsData);
+ })
+ );
+});
+
+describe("WeatherGovProvider", () => {
+ let WeatherGovProvider;
+
+ beforeAll(async () => {
+ const module = await import("../../../../../../defaultmodules/weather/providers/weathergov");
+ WeatherGovProvider = module.default || module;
+ });
+
+ describe("Constructor & Configuration", () => {
+ it("should set config values from params", () => {
+ const provider = new WeatherGovProvider({
+ lat: 40.71,
+ lon: -74.0,
+ type: "current"
+ });
+ expect(provider.config.lat).toBe(40.71);
+ expect(provider.config.lon).toBe(-74.0);
+ expect(provider.config.type).toBe("current");
+ });
+
+ it("should have default update interval", () => {
+ const provider = new WeatherGovProvider({});
+ expect(provider.config.updateInterval).toBe(600000); // 10 minutes
+ });
+ });
+
+ describe("Two-Step Initialization", () => {
+ it("should fetch points URL and then stations URL", async () => {
+ const provider = new WeatherGovProvider({
+ lat: 40.71,
+ lon: -74.0,
+ type: "current"
+ });
+
+ provider.setCallbacks(vi.fn(), vi.fn());
+
+ let pointsRequested = false;
+ let stationsRequested = false;
+
+ server.use(
+ http.get(WEATHERGOV_POINTS_URL, () => {
+ pointsRequested = true;
+ return HttpResponse.json(pointsData);
+ }),
+ http.get(WEATHERGOV_STATIONS_URL, () => {
+ stationsRequested = true;
+ return HttpResponse.json(stationsData);
+ })
+ );
+
+ await provider.initialize();
+
+ expect(pointsRequested).toBe(true);
+ expect(stationsRequested).toBe(true);
+ expect(provider.locationName).toBe("Washington, DC");
+ });
+
+ it("should store forecast URLs after initialization", async () => {
+ const provider = new WeatherGovProvider({
+ lat: 40.71,
+ lon: -74.0
+ });
+
+ provider.setCallbacks(vi.fn(), vi.fn());
+ await provider.initialize();
+
+ expect(provider.forecastURL).toContain("forecast?units=si");
+ expect(provider.forecastHourlyURL).toContain("forecast/hourly?units=si");
+ expect(provider.stationObsURL).toContain("observations/latest");
+ });
+ });
+
+ describe("Current Weather Parsing", () => {
+ it("should parse current weather data", async () => {
+ const provider = new WeatherGovProvider({
+ lat: 40.71,
+ lon: -74.0,
+ type: "current"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get(WEATHERGOV_CURRENT_URL, () => {
+ return HttpResponse.json(currentData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(result).toBeDefined();
+ expect(result.temperature).toBe(-1);
+ expect(result.windSpeed).toBe(0);
+ expect(result.windFromDirection).toBe(0);
+ expect(result.humidity).toBe(64); // Rounded from 63.77
+ expect(result.weatherType).not.toBeNull();
+ });
+
+ it("should use heat index or wind chill for feels like temperature", async () => {
+ const provider = new WeatherGovProvider({
+ lat: 40.71,
+ lon: -74.0,
+ type: "current"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get(WEATHERGOV_CURRENT_URL, () => {
+ return HttpResponse.json(currentData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ // Real data has null windChill - falls back to temperature
+ expect(result.feelsLikeTemp).toBe(-1);
+ });
+
+ it("should include sunrise/sunset", async () => {
+ const provider = new WeatherGovProvider({
+ lat: 40.71,
+ lon: -74.0,
+ type: "current"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get(WEATHERGOV_CURRENT_URL, () => {
+ return HttpResponse.json(currentData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(result.sunrise).toBeInstanceOf(Date);
+ expect(result.sunset).toBeInstanceOf(Date);
+ });
+ });
+
+ describe("Forecast Parsing", () => {
+ it("should parse daily forecast data", async () => {
+ const provider = new WeatherGovProvider({
+ lat: 40.71,
+ lon: -74.0,
+ type: "forecast"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get(WEATHERGOV_FORECAST_URL, () => {
+ return HttpResponse.json(forecastData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(Array.isArray(result)).toBe(true);
+ expect(result.length).toBeGreaterThan(0);
+
+ const day = result[0];
+ expect(day).toHaveProperty("date");
+ expect(day).toHaveProperty("minTemperature");
+ expect(day).toHaveProperty("maxTemperature");
+ expect(day).toHaveProperty("weatherType");
+ expect(day).toHaveProperty("precipitationProbability");
+ });
+ });
+
+ describe("Hourly Parsing", () => {
+ it("should parse hourly forecast data", async () => {
+ const provider = new WeatherGovProvider({
+ lat: 40.71,
+ lon: -74.0,
+ type: "hourly"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get(WEATHERGOV_HOURLY_URL, () => {
+ return HttpResponse.json(hourlyData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(Array.isArray(result)).toBe(true);
+ expect(result).toHaveLength(156); // Real API returns 156 hourly periods
+ expect(result[0]).toHaveProperty("temperature");
+ expect(result[0]).toHaveProperty("windSpeed");
+ expect(result[0]).toHaveProperty("windFromDirection");
+ expect(result[0]).toHaveProperty("weatherType");
+ });
+
+ it("should convert wind direction strings to degrees", async () => {
+ const provider = new WeatherGovProvider({
+ lat: 40.71,
+ lon: -74.0,
+ type: "hourly"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get(WEATHERGOV_HOURLY_URL, () => {
+ return HttpResponse.json(hourlyData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ // Real data has "S" wind for both hours
+ expect(result[0].windFromDirection).toBe(180);
+ // Third hour also has "S" wind
+ expect(result[2].windFromDirection).toBe(180);
+ });
+
+ it("should parse wind speed with units", async () => {
+ const provider = new WeatherGovProvider({
+ lat: 40.71,
+ lon: -74.0,
+ type: "hourly"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get(WEATHERGOV_HOURLY_URL, () => {
+ return HttpResponse.json(hourlyData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ // Wind speeds should be converted from km/h to m/s
+ expect(result[0].windSpeed).toBeCloseTo(1.11, 1); // Real data: 4 km/h -> ~1.11 m/s
+ });
+ });
+
+ describe("Error Handling", () => {
+ it("should categorize DNS errors as retryable", async () => {
+ const provider = new WeatherGovProvider({
+ lat: 40.71,
+ lon: -74.0,
+ type: "current"
+ });
+
+ const errorPromise = new Promise((resolve) => {
+ provider.setCallbacks(vi.fn(), resolve);
+ });
+
+ server.use(
+ http.get(WEATHERGOV_POINTS_URL, () => {
+ return HttpResponse.error();
+ })
+ );
+
+ await provider.initialize();
+
+ // Should call error callback
+ const error = await errorPromise;
+ expect(error).toHaveProperty("message");
+ });
+
+ it("should handle invalid JSON response", async () => {
+ const provider = new WeatherGovProvider({
+ lat: 40.71,
+ lon: -74.0,
+ type: "current"
+ });
+
+ const errorPromise = new Promise((resolve) => {
+ provider.setCallbacks(vi.fn(), resolve);
+ });
+
+ server.use(
+ http.get(WEATHERGOV_CURRENT_URL, () => {
+ return HttpResponse.json({ properties: null });
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const error = await errorPromise;
+ expect(error.message).toContain("Invalid");
+ });
+ });
+
+ describe("Weather Type Conversion", () => {
+ it("should convert textDescription to weather types", async () => {
+ const provider = new WeatherGovProvider({
+ lat: 40.71,
+ lon: -74.0,
+ type: "current"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ const testData = JSON.parse(JSON.stringify(currentData));
+ testData.properties.textDescription = "Thunderstorm";
+
+ server.use(
+ http.get(WEATHERGOV_CURRENT_URL, () => {
+ return HttpResponse.json(testData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ // Thunderstorm should map to day or night thunderstorm
+ expect(["thunderstorm", "night-thunderstorm"]).toContain(result.weatherType);
+ });
+ });
+});
diff --git a/tests/unit/modules/default/weather/providers/yr_spec.js b/tests/unit/modules/default/weather/providers/yr_spec.js
new file mode 100644
index 00000000..4602a8d8
--- /dev/null
+++ b/tests/unit/modules/default/weather/providers/yr_spec.js
@@ -0,0 +1,287 @@
+/**
+ * Yr.no Weather Provider Tests
+ *
+ * Tests data parsing for current, forecast, and hourly weather types.
+ * Yr.no is the Norwegian Meteorological Institute API.
+ *
+ * Uses fake timers to ensure deterministic timeseries selection.
+ * The provider picks the closest past entry from timeseries based on new Date().
+ * Fixed to 2026-02-06T21:30:00Z → selects timeseries[0] at 21:00 with T=-5.8°C.
+ */
+import { http, HttpResponse } from "msw";
+import { setupServer } from "msw/node";
+import { describe, it, expect, vi, beforeAll, beforeEach, afterAll, afterEach } from "vitest";
+
+import yrData from "../../../../../mocks/weather_yr.json" with { type: "json" };
+
+const YR_FORECAST_URL = "https://api.met.no/weatherapi/locationforecast/**";
+const YR_SUNRISE_URL = "https://api.met.no/weatherapi/sunrise/**";
+
+// Fixed time: 30 minutes after the first timeseries entry (2026-02-06T21:00:00Z)
+// This ensures timeseries[0] is always chosen as the closest past entry.
+const FAKE_NOW = new Date("2026-02-06T21:30:00Z");
+
+let server;
+
+beforeAll(() => {
+ server = setupServer(
+ http.get(({ request }) => request.url.includes("/locationforecast/"), () => {
+ return HttpResponse.json(yrData);
+ }),
+ http.get(({ request }) => request.url.includes("/sunrise/"), () => {
+ return HttpResponse.json({
+ when: { interval: ["2026-02-06T00:00:00+01:00"] },
+ properties: {
+ sunrise: { time: "2026-02-06T08:30:00+01:00" },
+ sunset: { time: "2026-02-06T16:30:00+01:00" }
+ }
+ });
+ })
+ );
+ server.listen({ onUnhandledRequest: "bypass" });
+});
+
+afterAll(() => {
+ server.close();
+});
+
+beforeEach(() => {
+ vi.useFakeTimers({ now: FAKE_NOW });
+});
+
+afterEach(() => {
+ vi.useRealTimers();
+ server.resetHandlers();
+});
+
+describe("YrProvider", () => {
+ let YrProvider;
+
+ beforeAll(async () => {
+ const module = await import("../../../../../../defaultmodules/weather/providers/yr");
+ YrProvider = module.default;
+ });
+
+ describe("Constructor & Configuration", () => {
+ it("should set config values from params", () => {
+ const provider = new YrProvider({
+ lat: 59.91,
+ lon: 10.72,
+ altitude: 94
+ });
+ expect(provider.config.lat).toBe(59.91);
+ expect(provider.config.lon).toBe(10.72);
+ expect(provider.config.altitude).toBe(94);
+ });
+
+ it("should enforce minimum 10-minute update interval", () => {
+ const provider = new YrProvider({
+ updateInterval: 60000 // 1 minute - too short
+ });
+ expect(provider.config.updateInterval).toBe(600000);
+ });
+
+ it("should allow intervals >= 10 minutes", () => {
+ const provider = new YrProvider({
+ updateInterval: 900000 // 15 minutes
+ });
+ expect(provider.config.updateInterval).toBe(900000);
+ });
+ });
+
+ describe("Coordinate Validation", () => {
+ it("should limit coordinates to 4 decimal places", async () => {
+ const provider = new YrProvider({
+ lat: 59.91234567,
+ lon: 10.72345678
+ });
+ provider.setCallbacks(vi.fn(), vi.fn());
+
+ server.use(
+ http.get(YR_FORECAST_URL, () => {
+ return HttpResponse.json(yrData);
+ })
+ );
+
+ await provider.initialize();
+
+ expect(provider.config.lat.toString().split(".")[1]?.length).toBeLessThanOrEqual(4);
+ expect(provider.config.lon.toString().split(".")[1]?.length).toBeLessThanOrEqual(4);
+ });
+ });
+
+ describe("Current Weather Parsing", () => {
+ it("should parse current weather from timeseries", async () => {
+ const provider = new YrProvider({
+ lat: 59.91,
+ lon: 10.72,
+ type: "current"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get(YR_FORECAST_URL, () => {
+ return HttpResponse.json(yrData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(result).toBeDefined();
+ // With fake time at 21:30, provider selects timeseries[0] (21:00 UTC)
+ expect(result.temperature).toBe(-5.8);
+ expect(result.windSpeed).toBe(6.0);
+ expect(result.windFromDirection).toBe(37.0);
+ expect(result.humidity).toBe(66.5);
+ // 21:00 is after sunset (16:30), symbol_code "snow" maps to "snow"
+ expect(result.weatherType).toBe("snow");
+ });
+
+ it("should include sunrise/sunset from stellar data", async () => {
+ const provider = new YrProvider({
+ lat: 59.91,
+ lon: 10.72,
+ type: "current"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(result).toBeDefined();
+ expect(result.sunrise).toBeInstanceOf(Date);
+ expect(result.sunset).toBeInstanceOf(Date);
+ expect(result.sunset.getTime()).toBeGreaterThan(result.sunrise.getTime());
+ });
+ });
+
+ describe("Forecast Parsing", () => {
+ it("should parse daily forecast data", async () => {
+ const provider = new YrProvider({
+ lat: 59.91,
+ lon: 10.72,
+ type: "forecast"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get(YR_FORECAST_URL, () => {
+ return HttpResponse.json(yrData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(Array.isArray(result)).toBe(true);
+ expect(result.length).toBeGreaterThan(0);
+
+ const day = result[0];
+ expect(day).toHaveProperty("date");
+ expect(day).toHaveProperty("minTemperature");
+ expect(day).toHaveProperty("maxTemperature");
+ expect(day.minTemperature).toBeLessThanOrEqual(day.maxTemperature);
+ });
+ });
+
+ describe("Hourly Parsing", () => {
+ it("should parse hourly forecast data", async () => {
+ const provider = new YrProvider({
+ lat: 59.91,
+ lon: 10.72,
+ type: "hourly"
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ server.use(
+ http.get(YR_FORECAST_URL, () => {
+ return HttpResponse.json(yrData);
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ expect(Array.isArray(result)).toBe(true);
+ expect(result.length).toBeGreaterThan(0);
+
+ const hour = result[0];
+ expect(hour).toHaveProperty("temperature");
+ expect(hour).toHaveProperty("windSpeed");
+ expect(hour).toHaveProperty("precipitationAmount");
+ expect(hour).toHaveProperty("weatherType");
+ });
+ });
+
+ describe("Error Handling", () => {
+ it("should call error callback on invalid data", async () => {
+ const provider = new YrProvider({
+ lat: 59.91,
+ lon: 10.72,
+ type: "current"
+ });
+
+ const errorPromise = new Promise((resolve) => {
+ provider.setCallbacks(vi.fn(), resolve);
+ });
+
+ server.use(
+ http.get(YR_FORECAST_URL, () => {
+ return HttpResponse.json({ properties: {} });
+ })
+ );
+
+ await provider.initialize();
+ provider.start();
+
+ const error = await errorPromise;
+ expect(error).toHaveProperty("message");
+ });
+ });
+
+ describe("Weather Type Conversion", () => {
+ it("should convert yr symbol codes correctly", async () => {
+ const provider = new YrProvider({
+ lat: 59.91,
+ lon: 10.72,
+ type: "current",
+ currentForecastHours: 1
+ });
+
+ const dataPromise = new Promise((resolve) => {
+ provider.setCallbacks(resolve, vi.fn());
+ });
+
+ // Uses yrData from beforeAll which has symbol_code "snow"
+
+ await provider.initialize();
+ provider.start();
+
+ const result = await dataPromise;
+
+ // 21:00 is after sunset (16:30), next_1_hours symbol_code is "snow"
+ expect(result.weatherType).toBe("snow");
+ });
+ });
+});
diff --git a/tests/unit/modules/default/weather/weather_providers_spec.js b/tests/unit/modules/default/weather/weather_providers_spec.js
new file mode 100644
index 00000000..4d226da2
--- /dev/null
+++ b/tests/unit/modules/default/weather/weather_providers_spec.js
@@ -0,0 +1,189 @@
+/**
+ * Weather Provider Smoke Tests
+ *
+ * Tests basic provider functionality: configuration, callbacks, and validation.
+ * Parser logic with private methods (#) is validated through live testing.
+ */
+import { describe, it, expect, vi, beforeEach, beforeAll, afterAll } from "vitest";
+
+// Mock global fetch for location lookup
+const originalFetch = global.fetch;
+
+global.fetch = vi.fn(() => Promise.resolve({
+ ok: true,
+ json: () => Promise.resolve({ city: "Munich", locality: "Munich" })
+}));
+
+// Restore original fetch after all tests
+afterAll(() => {
+ global.fetch = originalFetch;
+});
+
+describe("Weather Provider Smoke Tests", () => {
+ describe("OpenMeteoProvider", () => {
+ let OpenMeteoProvider;
+ let provider;
+
+ beforeAll(async () => {
+ const module = await import("../../../../../defaultmodules/weather/providers/openmeteo");
+ OpenMeteoProvider = module.default;
+ });
+
+ beforeEach(() => {
+ provider = new OpenMeteoProvider({
+ lat: 48.14,
+ lon: 11.58,
+ type: "current",
+ updateInterval: 600000
+ });
+ });
+
+ describe("Constructor & Configuration", () => {
+ it("should set config values from params", () => {
+ expect(provider.config.lat).toBe(48.14);
+ expect(provider.config.lon).toBe(11.58);
+ expect(provider.config.type).toBe("current");
+ expect(provider.config.updateInterval).toBe(600000);
+ });
+
+ it("should have default values", () => {
+ const defaultProvider = new OpenMeteoProvider({});
+ expect(defaultProvider.config.lat).toBe(0);
+ expect(defaultProvider.config.lon).toBe(0);
+ expect(defaultProvider.config.type).toBe("current");
+ expect(defaultProvider.config.maxNumberOfDays).toBe(5);
+ });
+
+ it("should accept all supported types", () => {
+ expect(new OpenMeteoProvider({ type: "current" }).config.type).toBe("current");
+ expect(new OpenMeteoProvider({ type: "forecast" }).config.type).toBe("forecast");
+ expect(new OpenMeteoProvider({ type: "hourly" }).config.type).toBe("hourly");
+ });
+ });
+
+ describe("Callback Interface", () => {
+ it("should store callbacks via setCallbacks", () => {
+ const onData = vi.fn();
+ const onError = vi.fn();
+ provider.setCallbacks(onData, onError);
+ expect(provider.onDataCallback).toBe(onData);
+ expect(provider.onErrorCallback).toBe(onError);
+ });
+
+ it("should initialize without callbacks", async () => {
+ await expect(provider.initialize()).resolves.not.toThrow();
+ });
+ });
+
+ describe("Public Methods", () => {
+ it("should have start/stop methods", () => {
+ expect(typeof provider.start).toBe("function");
+ expect(typeof provider.stop).toBe("function");
+ });
+
+ it("should have initialize method", () => {
+ expect(typeof provider.initialize).toBe("function");
+ });
+
+ it("should have setCallbacks method", () => {
+ expect(typeof provider.setCallbacks).toBe("function");
+ });
+ });
+ });
+
+ describe("OpenWeatherMapProvider", () => {
+ let OpenWeatherMapProvider;
+ let provider;
+
+ beforeAll(async () => {
+ const module = await import("../../../../../defaultmodules/weather/providers/openweathermap");
+ OpenWeatherMapProvider = module.default;
+ });
+
+ beforeEach(() => {
+ provider = new OpenWeatherMapProvider({
+ lat: 48.14,
+ lon: 11.58,
+ apiKey: "test-api-key",
+ type: "current"
+ });
+ });
+
+ describe("Constructor & Configuration", () => {
+ it("should set config values from params", () => {
+ expect(provider.config.lat).toBe(48.14);
+ expect(provider.config.lon).toBe(11.58);
+ expect(provider.config.apiKey).toBe("test-api-key");
+ expect(provider.config.type).toBe("current");
+ });
+
+ it("should have default values", () => {
+ const defaultProvider = new OpenWeatherMapProvider({ apiKey: "test" });
+ expect(defaultProvider.config.apiVersion).toBe("3.0");
+ expect(defaultProvider.config.weatherEndpoint).toBe("/onecall");
+ expect(defaultProvider.config.apiBase).toBe("https://api.openweathermap.org/data/");
+ });
+
+ it("should accept all supported types", () => {
+ expect(new OpenWeatherMapProvider({ apiKey: "test", type: "current" }).config.type).toBe("current");
+ expect(new OpenWeatherMapProvider({ apiKey: "test", type: "forecast" }).config.type).toBe("forecast");
+ expect(new OpenWeatherMapProvider({ apiKey: "test", type: "hourly" }).config.type).toBe("hourly");
+ });
+ });
+
+ describe("API Key Validation", () => {
+ it("should call onErrorCallback if no API key provided", async () => {
+ const noKeyProvider = new OpenWeatherMapProvider({
+ lat: 48.14,
+ lon: 11.58,
+ apiKey: ""
+ });
+
+ const onError = vi.fn();
+ noKeyProvider.setCallbacks(vi.fn(), onError);
+ await noKeyProvider.initialize();
+
+ expect(onError).toHaveBeenCalledWith(
+ expect.objectContaining({
+ message: "API key is required"
+ })
+ );
+ });
+
+ it("should not create fetcher without API key", async () => {
+ const noKeyProvider = new OpenWeatherMapProvider({
+ apiKey: ""
+ });
+ noKeyProvider.setCallbacks(vi.fn(), vi.fn());
+ await noKeyProvider.initialize();
+
+ expect(noKeyProvider.fetcher).toBeNull();
+ });
+ });
+
+ describe("Callback Interface", () => {
+ it("should store callbacks via setCallbacks", () => {
+ const onData = vi.fn();
+ const onError = vi.fn();
+ provider.setCallbacks(onData, onError);
+ expect(provider.onDataCallback).toBe(onData);
+ expect(provider.onErrorCallback).toBe(onError);
+ });
+ });
+
+ describe("Public Methods", () => {
+ it("should have start/stop methods", () => {
+ expect(typeof provider.start).toBe("function");
+ expect(typeof provider.stop).toBe("function");
+ });
+
+ it("should have initialize method", () => {
+ expect(typeof provider.initialize).toBe("function");
+ });
+
+ it("should have setCallbacks method", () => {
+ expect(typeof provider.setCallbacks).toBe("function");
+ });
+ });
+ });
+});
diff --git a/tests/utils/weather_mocker.js b/tests/utils/weather_mocker.js
deleted file mode 100644
index c0ebbba1..00000000
--- a/tests/utils/weather_mocker.js
+++ /dev/null
@@ -1,52 +0,0 @@
-const fs = require("node:fs");
-const path = require("node:path");
-const exec = require("node:child_process").execSync;
-
-/**
- * @param {string} type what data to read, can be "current" "forecast" or "hourly
- * @param {object} extendedData extra data to add to the default mock data
- * @returns {string} mocked current weather data
- */
-const readMockData = (type, extendedData = {}) => {
- let fileName;
-
- switch (type) {
- case "forecast":
- fileName = "weather_forecast.json";
- break;
- case "hourly":
- fileName = "weather_hourly.json";
- break;
- case "current":
- default:
- fileName = "weather_current.json";
- break;
- }
-
- const fileData = JSON.parse(fs.readFileSync(path.resolve(`${__dirname}/../mocks/${fileName}`)).toString());
- const mergedData = JSON.stringify({ ...{}, ...fileData, ...extendedData });
- return mergedData;
-};
-
-const injectMockData = (configFileName, extendedData = {}) => {
- let mockWeather;
- if (configFileName.includes("forecast")) {
- mockWeather = readMockData("forecast", extendedData);
- } else if (configFileName.includes("hourly")) {
- mockWeather = readMockData("hourly", extendedData);
- } else {
- mockWeather = readMockData("current", extendedData);
- }
- let content = fs.readFileSync(configFileName).toString();
- content = content.replace("#####WEATHERDATA#####", mockWeather);
- const tempFile = configFileName.replace(".js", "_temp.js");
- fs.writeFileSync(tempFile, content);
- return tempFile;
-};
-
-const cleanupMockData = () => {
- const tempDir = path.resolve(`${__dirname}/../configs`).toString();
- exec(`find ${tempDir} -type f -name *_temp.js -delete`);
-};
-
-module.exports = { injectMockData, cleanupMockData };