65 lines
2.3 KiB
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) !== '';
|
|
}
|
|
}
|