add(new DateInterval('PT' . $durationMinutes . 'M')); } function webinar_time_label(DateTimeInterface $start, string $timezone): string { $localStart = DateTimeImmutable::createFromInterface($start)->setTimezone(new DateTimeZone($timezone)); return strtoupper($localStart->format('gA T')); } function webinar_utc_stamp(DateTimeInterface $dateTime): string { return DateTimeImmutable::createFromInterface($dateTime) ->setTimezone(new DateTimeZone('UTC')) ->format('Ymd\THis\Z'); } function webinar_schedule_data(array $webinar, int $durationMinutes = 60): array { $title = trim((string) ($webinar['title'] ?? '')); if ($title === '') { $title = webinar_default_title(); } $start = webinar_start_datetime($webinar); $end = webinar_end_datetime($start, $durationMinutes); $berlin = webinar_time_label($start, 'Europe/Berlin'); $newYork = webinar_time_label($start, 'America/New_York'); $losAngeles = webinar_time_label($start, 'America/Los_Angeles'); return [ 'title' => $title, 'start' => $start, 'end' => $end, 'date_long' => $start->format('l, F j, Y'), 'berlin_label' => $berlin, 'new_york_label' => $newYork, 'los_angeles_label' => $losAngeles, 'timezone_line' => $berlin . ' | ' . $newYork . ' | ' . $losAngeles, 'hero_line' => strtoupper($start->format('l, F j') . ' | ' . $newYork . ' | ' . $losAngeles . ' | ' . $berlin), 'calendar_sentence' => 'Professional Vibe-Coding Webinar. Join us on ' . $start->format('F jS') . ' at ' . $berlin . ' | ' . $newYork . ' | ' . $losAngeles . ' to learn the fastest way to go from an idea to a working app you own.', 'calendar_description' => "Professional Vibe-Coding Webinar Join us for this webinar on " . $start->format('F jS') . ' at ' . $berlin . ' | ' . $newYork . ' | ' . $losAngeles . '. The fastest way to go from an idea to a working app you own, running on your server, with your database, using real frameworks.', ]; }