function init() {
initTimeVisualizer("time-timeVisualizer");
}
export function updateTime() {
const cities = [
{ name: "Tokyo", tz: "Asia/Tokyo", note: "JST" },
{ name: "Berlin", tz: "Europe/Berlin", note: "CET, CEST from last Sunday in March at 02:00 to last Sunday in October at 03:00" },
{ name: "London", tz: "Europe/London", note: "GMT, BST from last Sunday of March to last Sunday of October" },
{ name: "Lima", tz: "America/Lima", note: "aka: \"PET\""},
{ name: "Santiago", tz: "America/Santiago", note: "aka: \"CLT\""},
{ name: "New York", tz: "America/New_York", note: "EST, EDT from second Sunday in March at 02:00 to first Sunday in November at 02:00" },
{ name: "Chicago", tz: "America/Chicago", note: "CST, CDT from second Sunday in March at 02:00 to first Sunday in November at 02:00" },
{ name: "Denver", tz: "America/Denver", note: "MST, MDT from second Sunday in March at 02:00 to first Sunday in November at 02:00" },
{ name: "Los Angeles", tz: "America/Los_Angeles", note: "PST, PDT from second Sunday in March at 02:00 to first Sunday in November at 02:00" },
{ name: "Arizona", tz: "America/Denver", note: "MST" },
{ name: "Anchorage", tz: "America/Anchorage", note: "AKST, AKDT from second Sunday in March at 02:00 to first Sunday in November at 02:00" },
{ name: "Honolulu", tz: "Pacific/Honolulu", note: "HST" },
];
const escapeHtml = str => str.replace(/[&<>"']/g, c => `${c.charCodeAt(0)};`);
const now = new Date();
const locale = "en-US";
let output = "
";
// Tokyo datetime header
const tokyoDate = new Intl.DateTimeFormat("ja-JP", {
calendar: 'japanese', era: 'long',
year: "numeric", month: "numeric", day: "numeric", weekday: "long",
hour: "2-digit", minute: "2-digit", hour12: false,
timeZone: "Asia/Tokyo"
}).format(now);
const qw = getDateInfo(now); // quarter and ISO8601 week
let s = `Tokyo: (Q${qw.quarter}) (W${qw.isoWeek.toString().padStart(2, '0')}) ${tokyoDate}\n`;
document.getElementById("time-localClock").innerText = s;
// Time in other cities
cities.forEach(city => {
const formatter = new Intl.DateTimeFormat(locale, {
year: "numeric", month: "2-digit", day: "2-digit", weekday: "short",
hour: "2-digit", minute: "2-digit", hour12: false,
timeZoneName: "shortOffset",
timeZone: city.tz
})
const parts = formatter.formatToParts(now);
const t = {
time: parts.slice(8, -1).map(part => part.value).join('').trim(),
offset: parts.find(part => part.type === "timeZoneName")?.value.replace("GMT", "UTC"),
timeZoneName: new Intl.DateTimeFormat(locale, { timeZoneName: 'long', timeZone: city.tz })
.formatToParts(now).find(part => part.type === "timeZoneName")?.value,
}
t.dst = ["Daylight", "Summer"].some(sub => t.timeZoneName.includes(sub));
//const timeData = parts.reduce((obj, part) => { obj[part.type] = obj[part.value]; return obj; }, {})
const offsetAndDST = `${t.offset}` + (t.dst ? "+1" : "");
output += `- ${city.name}: ${t.time} (${offsetAndDST})
`;
});
output += "
"
document.getElementById("time-worldClock").innerHTML = output.trim();
}
function getQuarter(date) {
const month = date.getMonth(); // 0-11 (January is 0)
return Math.floor(month / 3) + 1; // Returns 1-4
}
function getISOWeek(date) {
const tempDate = new Date(date);
tempDate.setHours(0, 0, 0, 0);
tempDate.setDate(tempDate.getDate() + 3 - ((tempDate.getDay() + 6) % 7)); // Move to nearest Thursday
const firstThursday = new Date(tempDate.getFullYear(), 0, 4); // First Thursday of the year
firstThursday.setDate(firstThursday.getDate() + 3 - ((firstThursday.getDay() + 6) % 7));
const weekNumber = Math.round(((tempDate - firstThursday) / 86400000) / 7) + 1;
return weekNumber;
}
function getDateInfo(date) {
return {
quarter: getQuarter(date),
isoWeek: getISOWeek(date),
year: date.getFullYear()
};
}
function initTimeVisualizer(containerId) {
const grid = document.createElement('div');
grid.className = 'grid';
document.getElementById(containerId).appendChild(grid);
function updateTime() {
grid.innerHTML = '';
const now = new Date();
const hours = now.getHours();
const minutes = now.getMinutes();
for (let i = 0; i < 24; i++) {
const cell = document.createElement('div');
cell.className = 'cell';
if (i >= 20 || i < 4) cell.classList.add('sleep');
if (i < hours) cell.classList.add('past');
if (i === hours) {
cell.classList.add('current');
const fillPercentage = (minutes / 60) * 100;
cell.style.setProperty('--fill', `${fillPercentage}%`);
const line = document.createElement('div');
line.className = 'timeline';
line.style.left = `calc(${fillPercentage}% - 1px)`;
cell.appendChild(line);
}
grid.appendChild(cell);
}
}
updateTime();
setInterval(updateTime, 60000); // 1min
}
init()