Čas a časové pásma
Každý okamih sa ukladá v UTC — starts_at, ends_at, doors_open_at, časové značky lifecycle, časy RSVP, created_at — bez ohľadu na app.timezone a každé podujatie nesie vlastné časové pásmo IANA. Cast UtcDateTime a StoresUtcTimestamps to zabezpečia aj v aplikácii, ktorá beží v America/New_York:
$event = Events::make('Jazz Night')->organizedBy($user)
->at($venue) // the venue's timezone: Europe/Bratislava
->startsAt('2026-11-14 20:00') // wall clock there, stored as 19:00 UTC
->duration('PT3H')
->create();
$event->starts_at; // CarbonImmutable in UTC
$event->startsAtLocal(); // CarbonImmutable in the event's own timezone
$event->starts_on; // '2026-11-14' — the local calendar day
Events::make('Webinar')->organizedBy($user)->timezone('America/New_York')
->startsAt('2026-11-14T20:00:00+01:00') // an offset (or Z, or a Carbon) is that instant
->create();Zadávanie
| Zadáte | Číta sa ako |
|---|---|
'2026-11-14 20:00' | Miestny čas v časovom pásme podujatia (bez posunu). |
'2026-11-14T20:00:00+01:00', '…Z' | Presne ten okamih. |
| CarbonInterface | Presne ten okamih. |
- Časové pásmo podujatia je v tomto poradí: explicitné ->timezone(), pásmo miesta konania, events.defaults.timezone, app.timezone.
- Settery môžu prísť v akomkoľvek poradí — ->startsAt()->timezone() aj ->timezone()->startsAt() dajú ten istý okamih —, pretože harmonogram sa vyrieši až pri create().
- Miestny čas v medzere pri prechode na letný čas (02:30 v noci, keď sa hodiny posúvajú dopredu) sa odmietne s InvalidEventScheduleException, nikdy sa potichu neposunie. Čas v prekryve pri prechode na zimný čas (02:30 v noci, keď sa hodiny vracajú) dostane skorší posun.
- starts_on a ends_on obsahujú miestne kalendárne dni — ends_on vrátane —, odvodené pri uložení, takže dotazy „v tento deň“ nepotrebujú tabuľky časových pásiem v databáze.
- Odpovede API vykresľujú časy v ISO-8601 s vlastným posunom podujatia; notifikácie ich ukazujú v časovom pásme podujatia s jeho skratkou.
Koniec, trvanie a dvere
->endsAt() alebo ->duration('3 hours'), 'PT3H' či CarbonInterval; bez oboch platí events.defaults.duration. Podujatie trvá najviac events.schedule.max_duration (P31D) a musí sa skončiť po začiatku. ->doorsOpenAt() musí byť v rámci 12 hodín pred začiatkom; celodenné podujatie čas otvorenia dverí nemá — ak mu ho zadáte, dostanete InvalidEventScheduleException, nikdy sa potichu nezahodí. Presun termínu čas otvorenia dverí zruší, pretože starý by mohol byť mimo nového okna — nastavte ho znova cez update().
Celodenné a viacdňové podujatia
Events::make('Festival')->organizedBy($user)->timezone('Europe/Bratislava')
->allDay('2026-07-17', through: '2026-07-19')
->create();
// starts and ends at local midnights; ends_on is 2026-07-19 (inclusive)
// calendar files use the exclusive end day (20260720), JSON-LD the inclusive oneCelodenné podujatie sa začína a končí o miestnej polnoci — na začiatku prvého dňa a na začiatku dňa po poslednom —, správne aj tam, kde sa čas mení práve o polnoci. Nemá čas otvorenia dverí a pripomína sa v events.reminders.all_day_at (09:00 miestneho času).
Zmena časov
- Na koncepte update() a edit() zmenia čokoľvek. Na ohlásenom podujatí ide nový začiatok cez reschedule(): účastníci dostanú správu a pôvodne ohlásený začiatok zostane v previous_starts_at.
- Zmena časového pásma zachová okamihy podujatia s konkrétnym časom — posunie sa jeho miestny čas — a dni celodenného podujatia: jeho miestne polnoci sa odvodia znova v novom pásme, takže kalendárové súbory aj JSON-LD si ponechajú tie isté dátumy.
- Samotné allDayThrough posunie posledný deň celodenného podujatia (null z neho urobí jednodňové); pri podujatí s konkrétnym časom je to InvalidEventScheduleException.
- Začiatok, koniec alebo trvanie zadané celodennému konceptu z neho urobí podujatie s konkrétnym časom.
Časové scopes
use RoundlyConsulting\Events\Models\Event;
Event::query()->upcoming(); // not started yet
Event::query()->ongoing(); // started and not ended
Event::query()->past(); // ended
Event::query()->between('2026-11-01', '2026-11-30'); // overlapping the range
Event::query()->startingBetween($from, $to); // starting inside it (from inclusive, to exclusive)
Event::query()->onLocalDate('2026-11-14'); // taking place that day, each on its own calendarScopes porovnávajú v UTC. Holé reťazce v between() a startingBetween() sa čítajú v events.defaults.timezone (inak v pásme aplikácie); Carbon je okamih. onLocalDate() číta každé podujatie podľa jeho vlastného kalendára a reťazec musí byť skutočný dátum Y-m-d — 2027-02-30 je InvalidEventScheduleException, nikdy sa neprečíta ako iný deň.
Prejavte lásku k open source
Tento balík je zadarmo pod licenciou MIT. Ak vám šetrí čas, jednorazový príspevok alebo členstvo na Patreone nám pomôže ho ďalej udržiavať, testovať a dokumentovať.
Ďalšie spôsoby podpory vrátane kryptomienOdoslaním daru súhlasíte s našimi podmienkami prijímania darov.
Chcete to zabudovať do svojho produktu?
Naše balíky integrujeme do zákazkových Laravel a AI riešení. Napíšte nám, na čom pracujete, a ozveme sa do 48 hodín.