utc(), Carbon::parse($periodEnd)->utc(), ]; } /** * @return array{0: string, 1: string} */ public static function boundStrings(string $periodStart, string $periodEnd): array { [$start, $end] = self::bounds($periodStart, $periodEnd); return [$start->toDateTimeString(), $end->toDateTimeString()]; } /** * 开账 API:支持 `Y-m-d` 或带时刻字符串;前者按 UTC 自然日扩界,后者按 UTC 解释。 * * @return array{0: string, 1: string} */ public static function normalizeInputBounds(string $periodStart, string $periodEnd): array { $startRaw = trim($periodStart); $endRaw = trim($periodEnd); if ($startRaw === '' || $endRaw === '') { throw ValidationException::withMessages([ 'period_start' => ['required'], ]); } $startAt = self::isDateOnly($startRaw) ? Carbon::parse($startRaw.' 00:00:00', 'UTC') : Carbon::parse($startRaw)->utc(); $endAt = self::isDateOnly($endRaw) ? Carbon::parse($endRaw.' 23:59:59', 'UTC') : Carbon::parse($endRaw)->utc(); if ($endAt->lessThan($startAt)) { throw ValidationException::withMessages([ 'period_end' => ['after:period_start'], ]); } return [$startAt->toDateTimeString(), $endAt->toDateTimeString()]; } private static function isDateOnly(string $value): bool { return (bool) preg_match('/^\d{4}-\d{2}-\d{2}$/', $value); } }