feat: ForecastMapper and file Cache

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
2026-09-11 14:38:30 +02:00
co-authored by Claude Fable 5.1
parent d657fd069f
commit 89e1e544c5
6 changed files with 253 additions and 1 deletions
+45
View File
@@ -0,0 +1,45 @@
<?php
declare(strict_types=1);
namespace Weerscherm;
/** Zet het "daily"-blok van Open-Meteo om naar 5 dagen vanaf morgen (index 0 is vandaag). */
final class ForecastMapper
{
private const DAYS = 5;
/**
* @param array<string, mixed> $daily
* @return list<array{date: string, weather_code: ?int, temp_max: ?float, temp_min: ?float, precip_mm: ?float, precip_prob: ?int}>
*/
public static function map(array $daily): array
{
$dates = is_array($daily['time'] ?? null) ? $daily['time'] : [];
$out = [];
for ($i = 1; $i <= self::DAYS && isset($dates[$i]); $i++) {
if (!is_string($dates[$i])) {
continue;
}
$out[] = [
'date' => $dates[$i],
'weather_code' => self::intOrNull($daily['weather_code'][$i] ?? null),
'temp_max' => self::floatOrNull($daily['temperature_2m_max'][$i] ?? null),
'temp_min' => self::floatOrNull($daily['temperature_2m_min'][$i] ?? null),
'precip_mm' => self::floatOrNull($daily['precipitation_sum'][$i] ?? null),
'precip_prob' => self::intOrNull($daily['precipitation_probability_max'][$i] ?? null),
];
}
return $out;
}
private static function floatOrNull(mixed $v): ?float
{
return is_int($v) || is_float($v) ? (float) $v : null;
}
private static function intOrNull(mixed $v): ?int
{
return is_int($v) || is_float($v) ? (int) round($v) : null;
}
}