WorldClock
The time now in several cities, ticking, with the day there and how far ahead or behind the first one each is.
Demo
- Ana, Ben
- Lee
Get it
It needs theme.qwe, as every component does; or take the whole kit, quillo-ui.qwe. Each component brings its own styles to the pages that show it.
$ curl -O https://quillolang.org/components/ui/theme.qwe$ curl -O https://quillolang.org/components/ui/world_clock.qwemain.qwe
import ui/theme.qwe use theme_cssuse ui/world_clock.qweroute GET / = <html><head><style>{theme_css}</style></head><body class="ui-root">...</body></html>Example
The code of the preview above.
demos/world_clock.qwe
view WorldClockDemo() = <div.demo-stack> <div id="world-clock-demo-now"> <WorldClock seconds={true} zones={[{ city: "Lisbon", zone: "Europe/Lisbon" }, { city: "New York", zone: "America/New_York" }, { city: "Mumbai", zone: "Asia/Kolkata" }, { city: "Tokyo", zone: "Asia/Tokyo" }]}/> </div> <div.demo-narrow id="world-clock-demo-fixed"> <WorldClock variant="list" hour12={true} at="2026-11-02T22:30:00Z" label="Team hours" zones={[{ city: "London", zone: "Europe/London", note: "Ana, Ben" }, { city: "San Francisco", zone: "America/Los_Angeles" }, { city: "Sydney", zone: "Australia/Sydney", note: "Lee" }, { city: "Kathmandu", zone: "+05:45" }]}/> </div> </div>Source
ui/world_clock.qwe
// WorldClock: the time now in several places, ticking each minute in the browser, each// with its city, the day there (Today, Tomorrow, Yesterday) and its difference from the// first one (+5h, −8h). Night hours are shaded. The server writes the time when it makes// the page, so it reads right before any script runs.//// <WorldClock zones={[{ city: "Lisbon", zone: "Europe/Lisbon" }, { city: "New York", zone: "America/New_York" },// { city: "Tokyo", zone: "Asia/Tokyo" }]}/>// <WorldClock zones={team} hour12={true} seconds={true} variant="list"/>//// zones: a list of { city, zone (an IANA name: "Europe/Paris", "UTC", or an offset// "+05:30"), note? (a line under the city: "Ana, Ben") }. The first is home: the others// say how far ahead or behind it they are, and which day it is there next to its day.// hour12: a 12-hour clock with AM/PM. seconds: show and tick the seconds too.// variant: "cards" (default, a row of tiles) or "list" (rows). at: a fixed moment to show// (an ISO date-time with an offset) instead of now, which then does not tick.// label: what screen readers call it ("World clock").import ui/theme.qwe use ui_clslet world_clock_css = css`.ui-world-clock { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; min-width: 0; margin: 0; padding: 0; list-style: none; font: 13px/1.35 var(--ui-font); color: var(--ui-fg); }.ui-world-clock-zone { display: grid; gap: 2px; padding: 12px 14px; border: 1px solid var(--ui-border); border-radius: var(--ui-radius); background: var(--ui-surface); }.ui-world-clock-night { background: color-mix(in srgb, var(--ui-fg) 6%, var(--ui-surface)); }.ui-world-clock-city { display: flex; align-items: center; justify-content: space-between; gap: 6px; font-weight: 600; }.ui-world-clock-city svg { flex: none; width: 14px; height: 14px; color: var(--ui-muted); }.ui-world-clock-time { font-size: 28px; font-weight: 650; line-height: 1.15; font-variant-numeric: tabular-nums; letter-spacing: -.01em; }.ui-world-clock-time small { margin-left: 3px; font-size: 13px; font-weight: 600; color: var(--ui-muted); letter-spacing: 0; }.ui-world-clock-meta { color: var(--ui-muted); font-size: 12px; }.ui-world-clock-note { color: var(--ui-muted); font-size: 12px; }.ui-world-clock-list { grid-template-columns: 1fr; gap: 0; border: 1px solid var(--ui-border); border-radius: var(--ui-radius); overflow: hidden; }.ui-world-clock-list .ui-world-clock-zone { grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 0 12px; border: 0; border-radius: 0; border-top: 1px solid var(--ui-border); }.ui-world-clock-list .ui-world-clock-zone:first-child { border-top: 0; }.ui-world-clock-list .ui-world-clock-time { grid-column: 2; grid-row: 1 / span 3; font-size: 22px; text-align: right; }`// Minutes east of UTC of an offset written "+05:30", "-04:00" or "Z".fn world_clock_offset(o: str) -> int { if o == "Z" || o == "" { return 0 } let sign = starts_with(o, "-") ? -1 : 1 sign * ((int(slice(o, 1, 3)) ?? 0) * 60 + (int(slice(o, 4, 6)) ?? 0))}// The difference between two offsets, as it reads: 300 is "+5h", -210 is "−3h 30m", 0 is "same time".fn world_clock_diff(m: int) -> str { if m == 0 { return "same time" } let a = abs(m) `${m > 0 ? "+" : "−"}${floor(a / 60)}h${a % 60 != 0 ? ` ${a % 60}m` : ""}`}component WorldClock(zones: list = [], hour12: bool = false, seconds: bool = false, variant: str = "cards", at: str? = null, label: str = "World clock", class: str? = null) { style global world_clock_css state tick = now() let fixed = at != null ? date.ms(at) : null let ms = fixed ?? tick if fixed == null { every(seconds ? 1000 : 15000, () => { tick = now() }) } let two = (n: int) => n < 10 ? `0${n}` : str(n) let home = len(zones) > 0 ? date.from_ms(ms, zones[0].zone) : null let home_day = home != null ? slice(home, 0, 10) : null let home_off = home != null ? world_clock_offset(slice(home, 19, len(home))) : 0 <ul class={ui_cls(["ui-world-clock", variant == "list" && "ui-world-clock-list", class])} aria-label={label}> {for [i, z] in enumerate(zones) => { let t = date.from_ms(ms, z.zone) let p = date.parts(t) let day = slice(t, 0, 10) let off = world_clock_offset(slice(t, 19, len(t))) let word = day == home_day ? "Today" : (day > home_day ? "Tomorrow" : "Yesterday") let h = hour12 ? (p.hour % 12 == 0 ? 12 : p.hour % 12) : p.hour let clock = `${hour12 ? str(h) : two(h)}:${two(p.minute)}${seconds ? `:${two(p.second)}` : ""}` let ampm = hour12 ? (p.hour < 12 ? "AM" : "PM") : null let night = p.hour < 6 || p.hour >= 20 <li key={`${z.city}-${i}`} class={ui_cls(["ui-world-clock-zone", night && "ui-world-clock-night"])} aria-label={`${z.city}: ${clock}${ampm != null ? ` ${ampm}` : ""}, ${date.format(day, "dddd")}${i > 0 ? `, ${world_clock_diff(off - home_off)}` : ""}`}> <span.ui-world-clock-city aria-hidden="true"> {z.city} {night ? <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8z"/></svg> : <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4"/></svg>} </span> <time.ui-world-clock-time datetime={t} aria-hidden="true">{clock}{ampm != null && <small>{ampm}</small>}</time> <span.ui-world-clock-meta aria-hidden="true">{word}{i > 0 ? `, ${world_clock_diff(off - home_off)}` : ""}</span> {z.note != null && <span.ui-world-clock-note>{z.note}</span>} </li> }} </ul>}Related
StopwatchA stopwatch to the hundredth: Start, Lap, Stop and Reset, with the laps listed and the fastest and slowest marked.7 views · 5 downloadsTimerA countdown set in minutes with Start, Pause and Reset, a ring that empties, presets, and a silent alert at zero.7 views · 7 downloadsAgendaListEvents grouped by day with the date at the left, each with its time, title and place; today and tomorrow named.6 views · 6 downloadsDayViewOne day as a column of hours with its events drawn at their times, side by side when they overlap, and all-day events above.7 views · 7 downloadsEventCardAn event as a card: a date block, title, time, place, a line about it, an optional picture and badge, and a button.7 views · 6 downloadsOpeningHoursA week's opening hours with today marked and whether it is open now, closing soon, or when it opens next.6 views · 6 downloads
Thread
Thread 0 posts
On WorldClock: questions, tips, corrections, and code that uses it.
No posts yet. The first one opens the thread.