World Clock
The time in one or more places, live or at a given moment, with an optional working-hours overlap planner.
≈ 853 tokens per use (tool 580 · guidance 247 · typical payload 26)How token costs are estimated
Example: World Clock
What time is it in DC?
- Washington, DC
When to use
- The user asks what time it is somewhere, or wants clocks for several places.
- The user wants a time converted between zones: "when is 3 pm Lisbon in San Francisco?"
- The user wants to find a meeting time across zones (set
planner).
When not to use
- A single conversion the user only needs as a fact in a sentence, with no other places.
- Scheduling against real calendars. Fetch availability and use a Slot Picker.
- Counting down to something. Use a Timer.
How the agent should use it
- Use IANA timezones (
Asia/Kolkata), never abbreviations like "IST", which are ambiguous. - Put the reference place first. Offsets ("+7 h"), day relations ("Tomorrow") and the planner day are all relative to the first clock.
- For a conversion, set
referenceTimeas an ISO date-time with that place's offset, and put that place first. Omit it for "now". - Only set
plannerwhen the user wants to find a time. Schedule nothing until apick-timeresult arrives, then confirm it.
How it works
- Analog (the default for up to 4 clocks): SVG faces with all 12 hour numerals (
numerals: "quarters"keeps only 12, 3, 6 and 9), hour and minute hands, and a thin accent second hand. Up to 4 faces sit in a row on a wide card and 2 on a narrow one (container query). Below each face: the place, then one line with the day relative to the first clock and the offset from it ("Tomorrow · +16 h", "Today · −3 h", "+5:30 h" for half-hour zones). The first clock shows just "Today". With more than 4 clocks, orstyle: "digital", it's a list of rows with large tabular times. - Day and night faces: a face is light (white, dark numerals) when it's 06:00–17:59 in that zone, and dark (near-black, light numerals) otherwise. The face colors are fixed, the same in light and dark themes, and numerals clear 4.5:1 on both. Day or night is also announced as text, never color only.
- Live time: nothing time-related renders on the server (skeleton faces), and the clock starts after mount. The second hand sweeps with
requestAnimationFrameonly while the page is visible, without re-rendering React each frame. With reduced motion the second hand is hidden and the minute hand moves once a minute. - Accessibility: each face is
role="img"with a name like "Washington, DC, 12:18 PM, Thursday" that changes at most once a minute, so screen readers aren't flooded. Day or night is announced as text. referenceTime: the header reads "3:00 PM in Lisbon is…" and the hands are static. It renders the same on the server and the client.- Planner: the overlap comes first, in large text ("16:00–18:00 Tel Aviv · 08:00–10:00 Austin", or "No overlap in working hours"), then a strip per place on a shared 24-hour timeline (the planner
datein the first clock's zone; 23 or 25 hours on a DST day), with working hours shaded and the overlap stronger. Each overlap hour is a button that sendspick-time. The working-hours window is read to screen readers; the footer appears only once a time is picked. - Formatting: times use
Intlwith thelocalehost prop,"en-US"by default, so server and client agree.hour12forces a 12- or 24-hour clock. Offsets are computed for the exact instant, so DST and half-hour zones come out right.
Installation
npx shadcn@latest add https://your-site.com/r/world-clock.json
Usage
import { tool } from "ai"
import { worldClockTool } from "@/components/genui/world-clock.schema"
const tools = {
[worldClockTool.name]: tool({
description: worldClockTool.description,
inputSchema: worldClockTool.inputSchema,
}),
}Without planner the clocks are the whole answer, so give the tool an execute that returns immediately. With it, leave out execute and complete the call with the user's pick:
<WorldClock
{...part.input}
status={part.state === "input-streaming" ? "streaming" : undefined}
result={part.state === "output-available" ? part.output : undefined}
onResult={(output) =>
addToolResult({ tool: "show_clocks", toolCallId: part.toolCallId, output })
}
/>The agent receives:
{ action: "pick-time", at: "2026-10-14T13:00:00.000Z" }With LangGraph
Push it from a graph node with ui.push({ name: "show_clocks", props: { toolCallId, ...args } }, { message }), and render the thread's UI messages with the Renderer.
Restoring from history
Pass the stored pick back as result. The planner shows the picked hour, locked, and never calls onResult again.
<WorldClock
{...part.input}
result={part.state === "output-available" ? part.output : undefined}
/>Schema
| Prop | Type | Notes |
|---|---|---|
clocks | { id, label, code?, timeZone }[] | 1–6 places. The first is the reference |
style | "analog" | "digital" | Default: analog for up to 4 clocks |
numerals | "all" | "quarters" | Analog faces. Default "all"; "quarters" shows 12, 3, 6, 9 |
referenceTime | string? | ISO date-time with offset. Shows that moment instead of now |
hour12 | boolean? | Force a 12- or 24-hour clock |
planner | { workingHours: { start, end }, date }? | HH:mm local hours and a YYYY-MM-DD day in the first clock's zone |
Clock
| Field | Type | Notes |
|---|---|---|
id | string | Stable identifier |
label | string | "Washington, DC" |
code | string? | Up to 4 characters, shown on the face: "DC" |
timeZone | string | IANA zone, e.g. America/New_York |
Host props: status (streaming, ready, picked), onResult, result, locale and className.