ai_analysis/src/Service/TimeRangeResolver.php

65 lines
2.3 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Service;
final class TimeRangeResolver
{
private const DATE_FORMAT = 'Y/m/d';
public function __construct(private readonly string $timezone = 'Asia/Shanghai')
{
}
public function resolve(?string $date, ?string $timePreset, ?string $startDate, ?string $endDate): string
{
if ($this->filled($date)) {
return $date;
}
$now = new \DateTimeImmutable('now', new \DateTimeZone($this->timezone));
$preset = $this->filled($timePreset) ? $timePreset : 'today';
[$start, $end] = match ($preset) {
'today' => [$now, $now],
'yesterday' => [$now->modify('-1 day'), $now->modify('-1 day')],
'last_7_days' => [$now->modify('-6 days'), $now],
'last_30_days' => [$now->modify('-29 days'), $now],
'this_week' => [$now->modify('monday this week'), $now],
'last_week' => [$now->modify('monday last week'), $now->modify('sunday last week')],
'this_month' => [$now->modify('first day of this month'), $now],
'last_month' => [$now->modify('first day of last month'), $now->modify('last day of last month')],
'custom' => [$this->parseDate($startDate), $this->parseDate($endDate)],
default => throw new \InvalidArgumentException('Unsupported timePreset: ' . $preset),
};
if ($start > $end) {
throw new \InvalidArgumentException('startDate cannot be later than endDate.');
}
return $start->format(self::DATE_FORMAT) . '-' . $end->format(self::DATE_FORMAT);
}
private function parseDate(?string $date): \DateTimeImmutable
{
if (!$this->filled($date)) {
throw new \InvalidArgumentException('startDate and endDate are required when timePreset is custom.');
}
$normalized = str_replace('/', '-', $date);
$parsed = \DateTimeImmutable::createFromFormat('!Y-m-d', $normalized, new \DateTimeZone($this->timezone));
if (!$parsed instanceof \DateTimeImmutable) {
throw new \InvalidArgumentException('Invalid date format, expected YYYY-MM-DD.');
}
return $parsed;
}
private function filled(?string $value): bool
{
return $value !== null && trim($value) !== '';
}
}