Skip to content

Commit 1459a6b

Browse files
authored
Experimental timezones.html
Not fully tested yet, built this with Claude 3.5 Sonnet
1 parent e16f128 commit 1459a6b

File tree

1 file changed

+187
-0
lines changed

1 file changed

+187
-0
lines changed

timezones.html

+187
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Timezone Converter</title>
7+
<style>
8+
body {
9+
font-family: Arial, sans-serif;
10+
max-width: 800px;
11+
margin: 0 auto;
12+
padding: 20px;
13+
}
14+
table {
15+
width: 100%;
16+
border-collapse: collapse;
17+
margin-top: 20px;
18+
}
19+
th, td {
20+
border: 1px solid #ddd;
21+
padding: 8px;
22+
text-align: left;
23+
}
24+
th {
25+
background-color: #f2f2f2;
26+
}
27+
form {
28+
display: flex;
29+
flex-wrap: wrap;
30+
gap: 10px;
31+
align-items: center;
32+
margin-bottom: 20px;
33+
}
34+
label {
35+
margin-right: 5px;
36+
}
37+
#error {
38+
color: red;
39+
font-weight: bold;
40+
}
41+
</style>
42+
</head>
43+
<body>
44+
<h1>Timezone Converter</h1>
45+
<form id="timeForm">
46+
<label for="dateTime">Select Date and Time:</label>
47+
<input type="datetime-local" id="dateTime" required>
48+
<label for="timezone">in timezone:</label>
49+
<select id="timezone"></select>
50+
</form>
51+
<div id="error"></div>
52+
<div id="result"></div>
53+
54+
<script>
55+
const dateTimeInput = document.getElementById('dateTime');
56+
const timezoneSelect = document.getElementById('timezone');
57+
const resultDiv = document.getElementById('result');
58+
const errorDiv = document.getElementById('error');
59+
60+
const timezones = [
61+
{ name: 'UTC', zone: 'UTC' },
62+
{ name: 'New York', zone: 'America/New_York' },
63+
{ name: 'Los Angeles', zone: 'America/Los_Angeles' },
64+
{ name: 'Chicago', zone: 'America/Chicago' },
65+
{ name: 'London', zone: 'Europe/London' },
66+
{ name: 'Paris', zone: 'Europe/Paris' },
67+
{ name: 'Tokyo', zone: 'Asia/Tokyo' },
68+
{ name: 'Sydney', zone: 'Australia/Sydney' },
69+
{ name: 'Dubai', zone: 'Asia/Dubai' },
70+
{ name: 'Moscow', zone: 'Europe/Moscow' }
71+
];
72+
73+
try {
74+
const userTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
75+
console.log('User timezone:', userTimezone);
76+
77+
// Populate timezone select
78+
timezones.forEach(tz => {
79+
const option = document.createElement('option');
80+
option.value = tz.zone;
81+
option.textContent = `${tz.name} (${tz.zone})`;
82+
timezoneSelect.appendChild(option);
83+
});
84+
85+
// Set default timezone to user's timezone
86+
timezoneSelect.value = userTimezone;
87+
88+
function updateUrlHash(dateTime, timezone) {
89+
const timestamp = dateTime.getTime();
90+
history.replaceState(null, null, `#${timestamp},${timezone}`);
91+
}
92+
93+
function getDateTimeFromHash() {
94+
const hash = window.location.hash.slice(1);
95+
if (hash) {
96+
const [timestamp, timezone] = hash.split(',');
97+
return {
98+
dateTime: new Date(parseInt(timestamp)),
99+
timezone: timezone || userTimezone
100+
};
101+
}
102+
return null;
103+
}
104+
105+
function formatDate(date, timezone) {
106+
return date.toLocaleString('en-US', { timeZone: timezone, dateStyle: 'full', timeStyle: 'long' });
107+
}
108+
109+
function displayResults(dateTime, inputTimezone) {
110+
let html = '<table><tr><th>Timezone</th><th>Date & Time</th></tr>';
111+
timezones.forEach(tz => {
112+
html += `<tr><td>${tz.name} (${tz.zone})</td><td>${formatDate(dateTime, tz.zone)}</td></tr>`;
113+
});
114+
html += '</table>';
115+
resultDiv.innerHTML = html;
116+
}
117+
118+
function updateResults() {
119+
try {
120+
console.log('Updating results...');
121+
const inputDate = new Date(dateTimeInput.value);
122+
console.log('Input date:', inputDate);
123+
const inputTimezone = timezoneSelect.value;
124+
console.log('Input timezone:', inputTimezone);
125+
const utcDate = new Date(inputDate.toLocaleString('en-US', { timeZone: 'UTC' }));
126+
console.log('UTC date:', utcDate);
127+
updateUrlHash(utcDate, inputTimezone);
128+
displayResults(utcDate, inputTimezone);
129+
errorDiv.textContent = '';
130+
} catch (error) {
131+
console.error('Error in updateResults:', error);
132+
errorDiv.textContent = 'Error updating results: ' + error.message;
133+
}
134+
}
135+
136+
function setDateTimeInputValue(date, timezone) {
137+
const localDate = new Date(date.toLocaleString('en-US', { timeZone: timezone }));
138+
dateTimeInput.value = localDate.toISOString().slice(0, 16);
139+
}
140+
141+
// Event listeners for real-time updates
142+
dateTimeInput.addEventListener('input', updateResults);
143+
timezoneSelect.addEventListener('change', updateResults);
144+
145+
window.addEventListener('load', () => {
146+
try {
147+
console.log('Window loaded');
148+
const hashData = getDateTimeFromHash();
149+
if (hashData) {
150+
console.log('Hash data:', hashData);
151+
timezoneSelect.value = hashData.timezone;
152+
setDateTimeInputValue(hashData.dateTime, hashData.timezone);
153+
displayResults(hashData.dateTime, hashData.timezone);
154+
} else {
155+
console.log('No hash data, using current time');
156+
setDateTimeInputValue(new Date(), userTimezone);
157+
updateResults();
158+
}
159+
} catch (error) {
160+
console.error('Error in load event:', error);
161+
errorDiv.textContent = 'Error loading initial data: ' + error.message;
162+
}
163+
});
164+
165+
window.addEventListener('hashchange', () => {
166+
try {
167+
console.log('Hash changed');
168+
const hashData = getDateTimeFromHash();
169+
if (hashData) {
170+
console.log('New hash data:', hashData);
171+
timezoneSelect.value = hashData.timezone;
172+
setDateTimeInputValue(hashData.dateTime, hashData.timezone);
173+
displayResults(hashData.dateTime, hashData.timezone);
174+
}
175+
} catch (error) {
176+
console.error('Error in hashchange event:', error);
177+
errorDiv.textContent = 'Error processing URL: ' + error.message;
178+
}
179+
});
180+
181+
} catch (error) {
182+
console.error('Initialization error:', error);
183+
errorDiv.textContent = 'Initialization error: ' + error.message;
184+
}
185+
</script>
186+
</body>
187+
</html>

0 commit comments

Comments
 (0)