Enhances event handling with timezone support
Adds timezone handling to the event parsing and formatting logic. This allows events to be displayed in the user's local timezone, improving the user experience. Also restructures the event display on the "Termine" page to include a sidebar for filtering by year and month.
This commit is contained in:
+115
-39
@@ -1,66 +1,142 @@
|
||||
<?php
|
||||
|
||||
<?php
|
||||
// URL der öffentlichen ICS-Datei
|
||||
define(
|
||||
'CAL_URL',
|
||||
'https://calendar.google.com/calendar/ical/jv1bq94un3ivoa8ka0rk9ngq4k%40group.calendar.google.com/public/basic.ics',
|
||||
'CAL_URL',
|
||||
'https://calendar.google.com/calendar/ical/jv1bq94un3ivoa8ka0rk9ngq4k%40group.calendar.google.com/public/basic.ics',
|
||||
);
|
||||
|
||||
function format_ics_date($date)
|
||||
{
|
||||
// Unterstützt sowohl ganztägige als auch Zeitangaben
|
||||
if (strpos($date, 'T') !== false) {
|
||||
// Unterstützt sowohl ganztägige als auch Zeitangaben
|
||||
if (strpos($date, 'T') !== false) {
|
||||
$dt = DateTime::createFromFormat('Ymd\THis', substr($date, 0, 15));
|
||||
|
||||
return $dt ? $dt->format('d.m.Y H:i') : $date;
|
||||
} else {
|
||||
$dt = DateTime::createFromFormat('Ymd', $date);
|
||||
|
||||
return $dt ? $dt->format('d.m.Y') : $date;
|
||||
}
|
||||
}
|
||||
|
||||
function format_ics_date_with_timezone($date, $timezone = null)
|
||||
{
|
||||
// Unterstützt sowohl ganztägige als auch Zeitangaben
|
||||
if (strpos($date, 'T') !== false) {
|
||||
$dt = null;
|
||||
|
||||
// Prüfe ob es eine UTC-Zeit ist (endet mit Z)
|
||||
if (substr($date, -1) === 'Z') {
|
||||
// UTC-Zeit: 20250405T130000Z
|
||||
$utc_date = substr($date, 0, -1); // Entferne das Z
|
||||
$dt = DateTime::createFromFormat('Ymd\THis', $utc_date, new DateTimeZone('UTC'));
|
||||
} elseif ($timezone) {
|
||||
// Zeitzone angegeben: 20250405T130000 mit TZID
|
||||
try {
|
||||
$dt = new DateTime($date, new DateTimeZone($timezone));
|
||||
} catch (Exception $e) {
|
||||
// Fallback auf lokale Zeit
|
||||
$dt = DateTime::createFromFormat('Ymd\THis', substr($date, 0, 15));
|
||||
|
||||
return $dt ? $dt->format('d.m.Y H:i') : $date;
|
||||
}
|
||||
} else {
|
||||
$dt = DateTime::createFromFormat('Ymd', $date);
|
||||
|
||||
return $dt ? $dt->format('d.m.Y') : $date;
|
||||
// Lokale Zeit ohne Zeitzone
|
||||
$dt = DateTime::createFromFormat('Ymd\THis', substr($date, 0, 15));
|
||||
}
|
||||
|
||||
if ($dt) {
|
||||
// ISO 8601 Format für JavaScript
|
||||
$iso_date = $dt->format('Y-m-d\TH:i:sP'); // P = Zeitzone
|
||||
$display_date = $dt->format('d.m.Y H:i');
|
||||
|
||||
return [
|
||||
'iso' => $iso_date,
|
||||
'display' => $display_date,
|
||||
'has_time' => true,
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'iso' => $date,
|
||||
'display' => $date,
|
||||
'has_time' => true,
|
||||
];
|
||||
} else {
|
||||
$dt = DateTime::createFromFormat('Ymd', $date);
|
||||
|
||||
if ($dt) {
|
||||
$iso_date = $dt->format('Y-m-d');
|
||||
$display_date = $dt->format('d.m.Y');
|
||||
|
||||
return [
|
||||
'iso' => $iso_date,
|
||||
'display' => $display_date,
|
||||
'has_time' => false,
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'iso' => $date,
|
||||
'display' => $date,
|
||||
'has_time' => false,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// ICS-Datei laden
|
||||
$ics = @file_get_contents(CAL_URL);
|
||||
if (! $ics) {
|
||||
echo '<div class="text-red-600">Kalender konnte nicht geladen werden.</div>';
|
||||
if (!$ics) {
|
||||
echo '<div class="text-red-600">Kalender konnte nicht geladen werden.</div>';
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
// Termine parsen
|
||||
function parse_ics($ics)
|
||||
{
|
||||
$lines = explode("\n", $ics);
|
||||
$events = [];
|
||||
$event = [];
|
||||
$inEvent = false;
|
||||
foreach ($lines as $line) {
|
||||
$line = trim($line);
|
||||
if ($line === 'BEGIN:VEVENT') {
|
||||
$inEvent = true;
|
||||
$event = [];
|
||||
} elseif ($line === 'END:VEVENT') {
|
||||
$inEvent = false;
|
||||
$events[] = $event;
|
||||
} elseif ($inEvent) {
|
||||
// Property kann Parameter enthalten, z.B. DTSTART;TZID=Europe/Berlin:20240701T19000000
|
||||
$parts = explode(':', $line, 2);
|
||||
if (count($parts) === 2) {
|
||||
$key = $parts[0];
|
||||
$val = $parts[1];
|
||||
// Nur den eigentlichen Property-Namen extrahieren
|
||||
$key = strtoupper(preg_replace('/;.+$/', '', $key));
|
||||
$event[$key] = $val;
|
||||
}
|
||||
}
|
||||
}
|
||||
$lines = explode("\n", $ics);
|
||||
$events = [];
|
||||
$event = [];
|
||||
$inEvent = false;
|
||||
foreach ($lines as $line) {
|
||||
$line = trim($line);
|
||||
if ($line === 'BEGIN:VEVENT') {
|
||||
$inEvent = true;
|
||||
$event = [];
|
||||
} elseif ($line === 'END:VEVENT') {
|
||||
$inEvent = false;
|
||||
$events[] = $event;
|
||||
} elseif ($inEvent) {
|
||||
// Property kann Parameter enthalten, z.B. DTSTART;TZID=Europe/Berlin:20240701T19000000
|
||||
$parts = explode(':', $line, 2);
|
||||
if (count($parts) === 2) {
|
||||
$key = $parts[0];
|
||||
$val = $parts[1];
|
||||
|
||||
return $events;
|
||||
// Zeitzoneninformation extrahieren
|
||||
$timezone = null;
|
||||
if (preg_match('/TZID=([^:;]+)/', $key, $matches)) {
|
||||
$timezone = $matches[1];
|
||||
}
|
||||
|
||||
// Nur den eigentlichen Property-Namen extrahieren
|
||||
$cleanKey = strtoupper(preg_replace('/;.+$/', '', $key));
|
||||
$event[$cleanKey] = $val;
|
||||
|
||||
// Zeitzoneninformation separat speichern
|
||||
if ($timezone && in_array($cleanKey, ['DTSTART', 'DTEND'])) {
|
||||
$event[$cleanKey . '_TZID'] = $timezone;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $events;
|
||||
}
|
||||
|
||||
$events = parse_ics($ics);
|
||||
|
||||
return function () use ($events) {
|
||||
return $events;
|
||||
return $events;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user