$ids * @return array> */ public function run(array $ids, string $timezone, bool $apply = false, bool $all = false, bool $reverse = false): array { if (! in_array($timezone, DateTimeZone::listIdentifiers(DateTimeZone::ALL_WITH_BC), true)) { throw new InvalidArgumentException('Zona horaria inválida.'); } if ($all === ($ids !== [])) { throw new InvalidArgumentException('Indicar --all o --ids, exclusivamente una opción.'); } return DB::transaction(function () use ($ids, $timezone, $apply, $all, $reverse): array { $query = DB::table('validity_times')->orderBy('id'); $all ? $query->where('type', 'fixed_window') : $query->whereIn('id', $ids); if ($apply) { $query->lockForUpdate(); } $rows = $query->get(); if (! $all && $rows->count() !== count(array_unique($ids))) { throw new InvalidArgumentException('Uno o más IDs no existen.'); } if ($rows->contains(fn ($row): bool => $row->type !== 'fixed_window')) { throw new InvalidArgumentException('Sólo se admiten IDs de fixed_window.'); } $source = $reverse ? 'UTC' : $timezone; $target = $reverse ? $timezone : 'UTC'; $result = []; foreach ($rows as $row) { $convert = fn (?string $value): ?string => $value === null ? null : CarbonImmutable::parse($value, $source)->setTimezone($target)->format('Y-m-d H:i:s'); $start = $convert($row->fixed_starts_at); $end = $convert($row->fixed_expires_at); $result[] = [ 'id' => $row->id, 'original_start' => $row->fixed_starts_at, 'original_end' => $row->fixed_expires_at, 'result_start' => $start, 'result_end' => $end, ]; if ($apply) { DB::table('validity_times')->where('id', $row->id)->update([ 'fixed_starts_at' => $start, 'fixed_expires_at' => $end, ]); } } return $result; }); } }