fedi-feed-router/app/Support/DateRange.php

74 lines
2.1 KiB
PHP
Raw Normal View History

<?php
namespace App\Support;
use Illuminate\Support\Carbon;
use InvalidArgumentException;
class DateRange
{
public const MAX_DAYS = 731;
public function __construct(
public readonly Carbon $from,
public readonly Carbon $to,
) {
if ($to->lessThan($from)) {
throw new InvalidArgumentException('The end of a date range cannot precede its start.');
}
}
public static function preset(string $preset): self
{
$now = Carbon::now();
return match ($preset) {
'today' => new self($now->copy()->startOfDay(), $now->copy()->endOfDay()),
'week' => new self($now->copy()->startOfWeek(), $now->copy()->endOfWeek()),
'month' => new self($now->copy()->startOfMonth(), $now->copy()->endOfMonth()),
'year' => new self($now->copy()->startOfYear(), $now->copy()->endOfYear()),
'all' => new self(Carbon::createFromTimestamp(0), $now->copy()->endOfDay()),
default => throw new InvalidArgumentException("Unknown date range preset [{$preset}]."),
};
}
/**
* @return array<string, string>
*/
public static function presets(): array
{
return [
'today' => 'Today',
'week' => 'This Week',
'month' => 'This Month',
'year' => 'This Year',
'all' => 'All Time',
];
}
/**
* Every day the range touches, as Y-m-d, so callers can zero-fill empty buckets.
*
* @return array<int, string>
*/
public function days(): array
{
$days = [];
$cursor = $this->from->copy()->startOfDay();
$last = $this->to->copy()->startOfDay();
if ($cursor->diffInDays($last) >= self::MAX_DAYS) {
throw new InvalidArgumentException(
'A range wider than '.self::MAX_DAYS.' days cannot be bucketed by day; bucket by month instead.'
);
}
while ($cursor->lessThanOrEqualTo($last)) {
$days[] = $cursor->toDateString();
$cursor->addDay();
}
return $days;
}
}