diff --git a/site/collections/termine.php b/site/collections/termine.php
index 1b60e3f..6e7e3e3 100644
--- a/site/collections/termine.php
+++ b/site/collections/termine.php
@@ -1,66 +1,142 @@
-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 '
Kalender konnte nicht geladen werden.
';
+if (!$ics) {
+ echo 'Kalender konnte nicht geladen werden.
';
- 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;
};
+
diff --git a/site/snippets/home-termine.php b/site/snippets/home-termine.php
index 5cd7c96..e734ec6 100644
--- a/site/snippets/home-termine.php
+++ b/site/snippets/home-termine.php
@@ -1,34 +1,34 @@
format('Ymd');
+// Aktuelles Datum
+$today = new DateTime()->format('Ymd');
- // Nur zukünftige Termine anzeigen
- $future_events = array_filter($events, function ($event) use ($today) {
- return isset($event['DTSTART']) && $event['DTSTART'] >= $today;
- });
+// Nur zukünftige Termine anzeigen
+$future_events = array_filter($events, function ($event) use ($today) {
+ return isset($event['DTSTART']) && $event['DTSTART'] >= $today;
+});
- // Termine nach DTSTART in aufsteigender Reihenfolge sortieren
- usort($future_events, function ($a, $b) {
- return $a['DTSTART'] <=> $b['DTSTART'];
- });
+// Termine nach DTSTART in aufsteigender Reihenfolge sortieren
+usort($future_events, function ($a, $b) {
+ return $a['DTSTART'] <=> $b['DTSTART'];
+});
- // --- Deutsche Monatsnamen ---
- $de_months = [
- '01' => 'Jan',
- '02' => 'Feb',
- '03' => 'Mrz',
- '04' => 'Apr',
- '05' => 'Mai',
- '06' => 'Jun',
- '07' => 'Jul',
- '08' => 'Aug',
- '09' => 'Sep',
- '10' => 'Okt',
- '11' => 'Nov',
- '12' => 'Dez',
- ];
+// --- Deutsche Monatsnamen ---
+$de_months = [
+ '01' => 'Jan',
+ '02' => 'Feb',
+ '03' => 'Mrz',
+ '04' => 'Apr',
+ '05' => 'Mai',
+ '06' => 'Jun',
+ '07' => 'Jul',
+ '08' => 'Aug',
+ '09' => 'Sep',
+ '10' => 'Okt',
+ '11' => 'Nov',
+ '12' => 'Dez',
+];
?>
@@ -43,16 +43,19 @@
-
= $event["SUMMARY"] ?>
- ab Uhr
+ = $event['SUMMARY'] ?>
+
+
+ ab Uhr
+
+ ganztägig
+
+
@@ -169,6 +182,45 @@
// Initialer Aufruf
updateArrowState();
+ // Zeitzonenkonvertierung für lokale Zeiten
+ function convertTimesToLocal() {
+ const timeElements = document.querySelectorAll('.local-time');
+ timeElements.forEach(element => {
+ const isoDate = element.getAttribute('data-iso-date');
+ if (isoDate) {
+ try {
+ // Erstelle ein Date-Objekt aus der ISO-Date
+ // JavaScript erkennt automatisch UTC-Zeiten (mit Z oder +00:00)
+ const date = new Date(isoDate);
+
+ // Prüfe ob das Datum gültig ist
+ if (isNaN(date.getTime())) {
+ console.warn('Ungültiges Datum:', isoDate);
+ return;
+ }
+
+ // Formatiere die Zeit in der lokalen Zeitzone des Browsers
+ const localTime = date.toLocaleTimeString('de-DE', {
+ hour: '2-digit',
+ minute: '2-digit',
+ hour12: false
+ });
+
+ // Aktualisiere den Text
+ element.textContent = localTime;
+
+ // Debug-Information (kann später entfernt werden)
+ console.log('Konvertiert:', isoDate, '->', localTime, 'in Zeitzone:', Intl.DateTimeFormat().resolvedOptions().timeZone);
+ } catch (error) {
+ console.warn('Fehler bei der Zeitzonenkonvertierung:', error, 'für Datum:', isoDate);
+ }
+ }
+ });
+ }
+
+ // Zeitzonenkonvertierung beim Laden der Seite
+ convertTimesToLocal();
+
// Responsives Verhalten - bei Fenstergröße-Änderung
window.addEventListener('resize', () => {
// Anzahl der Karten je nach Bildschirmgröße anpassen
diff --git a/site/snippets/termine.php b/site/snippets/termine.php
index 7274264..f5e9cb3 100644
--- a/site/snippets/termine.php
+++ b/site/snippets/termine.php
@@ -4,77 +4,77 @@ $events = collection('termine');
// Nur Events mit DTSTART berücksichtigen
$events = array_filter($events, function ($event) {
- return isset($event['DTSTART']) && ! empty($event['DTSTART']);
+ return isset($event['DTSTART']) && !empty($event['DTSTART']);
});
// Nach Datum sortieren
usort($events, function ($a, $b) {
- return strcmp($a['DTSTART'], $b['DTSTART']);
+ return strcmp($a['DTSTART'], $b['DTSTART']);
});
// Aktuelles Datum
-$today = (new DateTime())->format('Ymd');
+$today = new DateTime()->format('Ymd');
// Nur zukünftige Termine anzeigen
$future_events = array_filter($events, function ($event) use ($today) {
- return isset($event['DTSTART']) && $event['DTSTART'] >= $today;
+ return isset($event['DTSTART']) && $event['DTSTART'] >= $today;
});
// --- Deutsche Monatsnamen ---
$de_months = [
- '01' => 'Januar',
- '02' => 'Februar',
- '03' => 'März',
- '04' => 'April',
- '05' => 'Mai',
- '06' => 'Juni',
- '07' => 'Juli',
- '08' => 'August',
- '09' => 'September',
- '10' => 'Oktober',
- '11' => 'November',
- '12' => 'Dezember',
+ '01' => 'Januar',
+ '02' => 'Februar',
+ '03' => 'März',
+ '04' => 'April',
+ '05' => 'Mai',
+ '06' => 'Juni',
+ '07' => 'Juli',
+ '08' => 'August',
+ '09' => 'September',
+ '10' => 'Oktober',
+ '11' => 'November',
+ '12' => 'Dezember',
];
// --- Gruppierung aller Termine nach Jahr und Monat für die Sidebar ---
function group_events_by_year_month($events)
{
- $grouped = [];
- foreach ($events as $event) {
- if ( ! isset($event['DTSTART'])) {
- continue;
- }
- $date = $event['DTSTART'];
- $year = substr($date, 0, 4);
- $month = substr($date, 4, 2);
- $grouped[$year][$month][] = $event;
- }
- krsort($grouped); // Jahre absteigend
- foreach ($grouped as &$months) {
- krsort($months); // Monate absteigend
+ $grouped = [];
+ foreach ($events as $event) {
+ if (!isset($event['DTSTART'])) {
+ continue;
}
+ $date = $event['DTSTART'];
+ $year = substr($date, 0, 4);
+ $month = substr($date, 4, 2);
+ $grouped[$year][$month][] = $event;
+ }
+ krsort($grouped); // Jahre absteigend
+ foreach ($grouped as &$months) {
+ krsort($months); // Monate absteigend
+ }
- return $grouped;
+ return $grouped;
}
$all_events_grouped = group_events_by_year_month($events);
// --- Filter aus URL ---
-$filter_jahr = $_GET['jahr'] ?? null;
+$filter_jahr = $_GET['jahr'] ?? null;
$filter_monat = $_GET['monat'] ?? null;
if ($filter_jahr && $filter_monat) {
- $filtered_events = array_filter($events, function ($event) use ($filter_jahr, $filter_monat) {
- $date = $event['DTSTART'] ?? '';
+ $filtered_events = array_filter($events, function ($event) use ($filter_jahr, $filter_monat) {
+ $date = $event['DTSTART'] ?? '';
- return substr($date, 0, 4) === $filter_jahr && substr($date, 4, 2) === $filter_monat;
- });
+ return substr($date, 0, 4) === $filter_jahr && substr($date, 4, 2) === $filter_monat;
+ });
} elseif ($filter_jahr) {
- $filtered_events = array_filter($events, function ($event) use ($filter_jahr) {
- $date = $event['DTSTART'] ?? '';
+ $filtered_events = array_filter($events, function ($event) use ($filter_jahr) {
+ $date = $event['DTSTART'] ?? '';
- return substr($date, 0, 4) === $filter_jahr;
- });
+ return substr($date, 0, 4) === $filter_jahr;
+ });
} else {
- $filtered_events = $future_events;
+ $filtered_events = $future_events;
}
?>
@@ -85,54 +85,43 @@ if ($filter_jahr && $filter_monat) {
Termine nach Jahr/Monat
- $months): ?>
+ $months): ?>
-
-
-
+
\ No newline at end of file