diff --git a/zeitzonen/index.html b/zeitzonen/index.html
index 9da9803..1381d77 100644
--- a/zeitzonen/index.html
+++ b/zeitzonen/index.html
@@ -431,21 +431,21 @@
// Timezone data
const majorTimezones = [
- { label: "Pacific (Los Angeles)", id: "America/Los_Angeles", offset: -8 },
- { label: "Mountain (Denver)", id: "America/Denver", offset: -7 },
- { label: "Central (Chicago)", id: "America/Chicago", offset: -6 },
- { label: "Eastern (New York)", id: "America/New_York", offset: -5 },
- { label: "Brasilien (São Paulo)", id: "America/Sao_Paulo", offset: -3 },
- { label: "Großbritannien (London)", id: "Europe/London", offset: 0 },
- { label: "Westeuropa (Paris, Berlin)", id: "Europe/Berlin", offset: 1 },
- { label: "Osteuropa (Athen)", id: "Europe/Athens", offset: 2 },
- { label: "Moskau", id: "Europe/Moscow", offset: 3 },
- { label: "Dubai", id: "Asia/Dubai", offset: 4 },
- { label: "Indien (Mumbai)", id: "Asia/Kolkata", offset: 5.5 },
- { label: "China (Peking)", id: "Asia/Shanghai", offset: 8 },
- { label: "Japan (Tokio)", id: "Asia/Tokyo", offset: 9 },
- { label: "Australien (Sydney)", id: "Australia/Sydney", offset: 10 },
- { label: "Neuseeland (Auckland)", id: "Pacific/Auckland", offset: 12 }
+ { label: "Pacific (Los Angeles)", id: "America/Los_Angeles" },
+ { label: "Mountain (Denver)", id: "America/Denver" },
+ { label: "Central (Chicago)", id: "America/Chicago" },
+ { label: "Eastern (New York)", id: "America/New_York" },
+ { label: "Brasilien (São Paulo)", id: "America/Sao_Paulo" },
+ { label: "Großbritannien (London)", id: "Europe/London" },
+ { label: "Westeuropa (Paris, Berlin)", id: "Europe/Berlin" },
+ { label: "Osteuropa (Athen)", id: "Europe/Athens" },
+ { label: "Moskau", id: "Europe/Moscow" },
+ { label: "Dubai", id: "Asia/Dubai" },
+ { label: "Indien (Mumbai)", id: "Asia/Kolkata" },
+ { label: "China (Peking)", id: "Asia/Shanghai" },
+ { label: "Japan (Tokio)", id: "Asia/Tokyo" },
+ { label: "Australien (Sydney)", id: "Australia/Sydney" },
+ { label: "Neuseeland (Auckland)", id: "Pacific/Auckland" }
];
// Populate timezone dropdowns
@@ -618,17 +618,22 @@
container.innerHTML = '';
majorTimezones.forEach(tz => {
- // Create a timezone card
const card = document.createElement('div');
card.className = 'timezone-card';
-
- const dateInTimezone = getDateInTimezone(referenceDate, tz.id);
+ // Format time and date using Intl.DateTimeFormat for the specific timezone
+ const timeFormatter = new Intl.DateTimeFormat('de-DE', { timeZone: tz.id, hour: '2-digit', minute: '2-digit' });
+ const dateFormatter = new Intl.DateTimeFormat('de-DE', { timeZone: tz.id, year: 'numeric', month: '2-digit', day: '2-digit' });
+
+ const timeStr = timeFormatter.format(referenceDate);
+ const dateStr = dateFormatter.format(referenceDate);
+ const offsetStr = getTimezoneOffsetString(referenceDate, tz.id);
+
card.innerHTML = `
${tz.label}
- ${dateInTimezone.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}
- ${dateInTimezone.toLocaleDateString()}
- ${getTimezoneOffsetString(dateInTimezone, tz.id)}
+ ${timeStr}
+ ${dateStr}
+ ${offsetStr}
`;
container.appendChild(card);
@@ -637,66 +642,119 @@
// Calculate and show timezone results
document.getElementById('calculate-btn').addEventListener('click', () => {
- const dateStr = dateInput.value;
- const timeStr = timeInput.value;
- const sourceTimezone = sourceTimezoneSelect.value;
- const targetTimezone = targetTimezoneSelect.value;
+ const dateStr = dateInput.value; // "YYYY-MM-DD"
+ const timeStr = timeInput.value; // "HH:mm"
+ const sourceTimezoneId = sourceTimezoneSelect.value;
+ const targetTimezoneId = targetTimezoneSelect.value;
- if (!dateStr || !timeStr) {
- alert('Bitte gib ein Datum und eine Zeit ein');
+ if (!dateStr || !timeStr || !sourceTimezoneId || !targetTimezoneId) {
+ alert('Bitte gib ein Datum, eine Zeit und beide Zeitzonen an.');
return;
}
- // Create date object from inputs
- const [year, month, day] = dateStr.split('-').map(Number);
- const [hours, minutes] = timeStr.split(':').map(Number);
-
- // Erstelle ein Datum im lokalen Format
- const inputDate = new Date(year, month - 1, day, hours, minutes);
-
- // Wir erstellen eine Referenzzeit, die der Eingabe in der Quell-Zeitzone entspricht
- const utcMilliseconds = Date.UTC(year, month - 1, day, hours, minutes);
- const sourceOffset = getTimezoneOffsetHours(sourceTimezone) * 60 * 60 * 1000;
- const referenceDate = new Date(utcMilliseconds - sourceOffset);
+ try {
+ // --- Korrekte Logik zur Erstellung des Referenz-Zeitpunkts ---
- // Zeige nur die Quell- und Zielzeitzone an
- displayConversionResult(referenceDate, sourceTimezone, targetTimezone);
+ // 1. Parse input date/time components
+ const [year, month, day] = dateStr.split('-').map(Number);
+ const [hours, minutes] = timeStr.split(':').map(Number);
+
+ // 2. Helper function to get offset in hours for a given date and timezone
+ function getOffsetHours(date, timezone) {
+ try {
+ const formatter = new Intl.DateTimeFormat('en-US', {
+ timeZone: timezone,
+ timeZoneName: 'longOffset' // e.g., GMT-07:00 or GMT+02:00
+ });
+ const parts = formatter.formatToParts(date);
+ const offsetPart = parts.find(part => part.type === 'timeZoneName');
+ if (offsetPart) {
+ // Extract hours and minutes from GMT string (e.g., "GMT-7", "GMT+5:30")
+ const match = offsetPart.value.match(/GMT([-+])(\d{1,2})(?::(\d{2}))?/);
+ if (match) {
+ const sign = match[1] === '-' ? -1 : 1;
+ const hourOffset = parseInt(match[2], 10);
+ const minuteOffset = match[3] ? parseInt(match[3], 10) : 0;
+ return sign * (hourOffset + minuteOffset / 60);
+ }
+ }
+ } catch (e) {
+ console.warn(`Could not determine offset for timezone ${timezone}`, e);
+ }
+ // Fallback: Browser's local offset for the given date (less accurate for the *target* zone)
+ console.warn(`Falling back to local offset for timezone ${timezone}`);
+ return -date.getTimezoneOffset() / 60;
+ }
+
+ // 3. Estimate the UTC time by initially assuming the input time *was* UTC.
+ // We need a Date object to pass to getOffsetHours.
+ const guessedUtcMillis = Date.UTC(year, month - 1, day, hours, minutes);
+ const tempDate = new Date(guessedUtcMillis);
+
+ // 4. Get the actual offset of the source timezone *at that time*.
+ const sourceOffsetHours = getOffsetHours(tempDate, sourceTimezoneId);
+
+ // 5. Calculate the correct UTC milliseconds.
+ // The input time (e.g., 20:00 Berlin) corresponds to a UTC time that is
+ // 'sourceOffsetHours' earlier than 20:00 UTC.
+ // So, we subtract the offset from the initial UTC guess.
+ const correctUtcMillis = guessedUtcMillis - (sourceOffsetHours * 3600 * 1000);
+
+ // 6. Create the final Date object representing the correct moment in time.
+ const referenceDate = new Date(correctUtcMillis);
+
+ // 7. Display the results using this correct referenceDate.
+ displayConversionResult(referenceDate, sourceTimezoneId, targetTimezoneId);
+
+ } catch (error) {
+ console.error("Fehler bei der Zeitzonenberechnung:", error);
+ // Add more specific error message if Intl fails (e.g., invalid timezone ID)
+ if (error instanceof RangeError) {
+ alert(`Fehler: Eine der angegebenen Zeitzonen ('${sourceTimezoneId}' oder '${targetTimezoneId}') ist ungültig oder wird vom Browser nicht unterstützt.`);
+ } else {
+ alert("Ein unerwarteter Fehler bei der Berechnung der Zeit ist aufgetreten. Bitte überprüfe die Eingabe.");
+ }
+ }
});
// Display conversion result between source and target timezone
- function displayConversionResult(referenceDate, sourceTimezone, targetTimezone) {
+ function displayConversionResult(referenceDate, sourceTimezoneId, targetTimezoneId) {
const container = document.getElementById('timezone-result');
container.innerHTML = '';
- const sourceTz = majorTimezones.find(tz => tz.id === sourceTimezone);
- const targetTz = majorTimezones.find(tz => tz.id === targetTimezone);
+ const sourceTzData = majorTimezones.find(tz => tz.id === sourceTimezoneId);
+ const targetTzData = majorTimezones.find(tz => tz.id === targetTimezoneId);
- if (!sourceTz || !targetTz) return;
-
- // Quell-Zeitzone Karte
- const sourceCard = document.createElement('div');
- sourceCard.className = 'timezone-card';
- const dateInSourceTimezone = getDateInTimezone(referenceDate, sourceTimezone);
-
- sourceCard.innerHTML = `
- ${sourceTz.label}
- ${dateInSourceTimezone.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}
- ${dateInSourceTimezone.toLocaleDateString()}
- ${getTimezoneOffsetString(dateInSourceTimezone, sourceTimezone)}
- `;
-
- // Ziel-Zeitzone Karte
- const targetCard = document.createElement('div');
- targetCard.className = 'timezone-card';
- const dateInTargetTimezone = getDateInTimezone(referenceDate, targetTimezone);
-
- targetCard.innerHTML = `
- ${targetTz.label}
- ${dateInTargetTimezone.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}
- ${dateInTargetTimezone.toLocaleDateString()}
- ${getTimezoneOffsetString(dateInTargetTimezone, targetTimezone)}
- `;
+ if (!sourceTzData || !targetTzData) {
+ console.error("Source or target timezone data not found in majorTimezones list.");
+ return;
+ }
+ // --- Funktion zum Erstellen einer Karte ---
+ function createResultCard(timezoneData, dateToFormat) {
+ const card = document.createElement('div');
+ card.className = 'timezone-card';
+
+ const timeFormatter = new Intl.DateTimeFormat('de-DE', { timeZone: timezoneData.id, hour: '2-digit', minute: '2-digit' });
+ const dateFormatter = new Intl.DateTimeFormat('de-DE', { timeZone: timezoneData.id, year: 'numeric', month: '2-digit', day: '2-digit' });
+
+ const timeStr = timeFormatter.format(dateToFormat);
+ const dateStr = dateFormatter.format(dateToFormat);
+ const offsetStr = getTimezoneOffsetString(dateToFormat, timezoneData.id);
+
+ card.innerHTML = `
+ ${timezoneData.label}
+ ${timeStr}
+ ${dateStr}
+ ${offsetStr}
+ `;
+ return card;
+ }
+
+ // Erstelle Quell- und Ziel-Karten
+ const sourceCard = createResultCard(sourceTzData, referenceDate);
+ const targetCard = createResultCard(targetTzData, referenceDate);
+
container.appendChild(sourceCard);
// Pfeil zwischen den Karten
@@ -708,78 +766,41 @@
container.appendChild(targetCard);
}
- // Helper function to get a date object in a specific timezone
- function getDateInTimezone(date, timezone) {
- // Nutze die eingebaute Zeitzonenunterstützung von JavaScript
- const options = { timeZone: timezone };
- const formatter = new Intl.DateTimeFormat('en-US', {
- ...options,
- year: 'numeric',
- month: 'numeric',
- day: 'numeric',
- hour: 'numeric',
- minute: 'numeric',
- second: 'numeric',
- hour12: false
- });
-
- const parts = formatter.formatToParts(date);
- const dateObj = {};
-
- parts.forEach(part => {
- if (part.type !== 'literal') {
- dateObj[part.type] = part.value;
- }
- });
-
- return new Date(
- dateObj.year,
- parseInt(dateObj.month, 10) - 1,
- dateObj.day,
- dateObj.hour,
- dateObj.minute,
- dateObj.second
- );
- }
-
// Helper function to get timezone offset string (e.g., GMT+1)
function getTimezoneOffsetString(date, timezone) {
- if (timezone) {
- // Ermittle den tatsächlichen Offset für das Datum in der Zeitzone
- const testDate = new Date(date); // Wir erstellen eine Kopie
-
- // Formatiere das Datum in der angegebenen Zeitzone und hole den Offset
+ try {
+ // Nutze Intl.DateTimeFormat, um den Offset für das spezifische Datum und die Zeitzone zu erhalten
const formatter = new Intl.DateTimeFormat('en-US', {
timeZone: timezone,
- timeZoneName: 'longOffset'
+ timeZoneName: 'longOffset' // Gibt z.B. "GMT+01:00" zurück
});
- // Extrahiere den GMT-Offset-String aus der formatierten Ausgabe
- const formattedDate = formatter.format(testDate);
- const offsetMatch = formattedDate.match(/GMT([-+]\d+)/);
+ // Formatiere das Datum, um den Offset-String zu extrahieren
+ const formattedParts = formatter.formatToParts(date);
+ const offsetPart = formattedParts.find(part => part.type === 'timeZoneName');
- if (offsetMatch) {
- return `GMT${offsetMatch[1]}`;
- }
-
- // Fallback: Verwende den statischen Offset aus majorTimezones
- const tz = majorTimezones.find(t => t.id === timezone);
- if (tz) {
- const sign = tz.offset >= 0 ? '+' : '-';
- return `GMT${sign}${Math.abs(tz.offset)}`;
+ if (offsetPart) {
+ // Extrahiere den numerischen Teil (z.B. +1, -8)
+ const match = offsetPart.value.match(/GMT([-+]\d{1,2}(?::\d{2})?)/);
+ if (match && match[1]) {
+ // Vereinfache zu GMT+X oder GMT-X
+ const numericOffset = parseInt(match[1].split(':')[0], 10);
+ const sign = numericOffset >= 0 ? '+' : '-';
+ return `GMT${sign}${Math.abs(numericOffset)}`;
+ }
+ return offsetPart.value; // Fallback auf den vollen String
}
+ } catch (error) {
+ console.warn(`Konnte Offset für Zeitzone ${timezone} nicht ermitteln:`, error);
+ // Fallback: Verwende den Offset der lokalen Zeitzone des Browsers für dieses Datum
+ const localOffsetMinutes = date.getTimezoneOffset();
+ const offsetHours = -localOffsetMinutes / 60;
+ const sign = offsetHours >= 0 ? '+' : '-';
+ return `GMT${sign}${Math.abs(offsetHours)} (Lokal)`;
}
-
- // Wenn keine Zeitzone angegeben oder gefunden wurde, verwende den lokalen Offset
- const offset = date.getTimezoneOffset() * -1 / 60;
- const sign = offset >= 0 ? '+' : '-';
- return `GMT${sign}${Math.abs(offset)}`;
- }
- // Helper function to get timezone offset in hours
- function getTimezoneOffsetHours(timezone) {
- const tz = majorTimezones.find(t => t.id === timezone);
- return tz ? tz.offset : 0;
+ // Sicherer Fallback, falls alles fehlschlägt
+ return 'GMT?';
}
// Generate initial timezone cards