Back to browse

ZoneMapzone World Clock

by zzjoey·Feb 25, 2026·2 points·0 comments

AI Analysis

●●●BangerWizardryEye CandyCozy

Pixel-perfect day/night terminator plus zero-latency map scrub without React renders.

Strengths
  • Genuine technical insight: USNO solar declination math for accurate day/night boundary, not lazy hacks
  • Map-drag-equals-time-scrub mechanic is intuitive and novel—spatial metaphor for temporal offset
  • Canvas-bypass optimization shows real performance care; fluid interaction without framework overhead
Weaknesses
  • Core use case (team scheduling across zones) already solved by Calendly, World Time Buddy
  • Relies on intuitive map metaphor—unclear if this faster than typing 'what time is 3pm EST in Singapore'
Category
Target Audience

Remote teams, scheduling coordinators, time zone enthusiasts

Similar To

World Time Buddy · Every Time Zone · Timezone.io

Post Description

I built this because I kept needing to answer "when is 3pm EST for my teammate in Singapore" and none of the existing tools felt right for me - they're mostly lists. I wanted a map where time differences are spatially obvious.

A few things that were technically interesting to build: The day/night terminator. It's not just a shaded half-sphere. I implemented a simplified USNO solar declination algorithm, computing the subsolar point for a given UTC timestamp, then tracing the great-circle terminator and sampling which side each pixel falls on. It renders pixel-by-pixel onto a Canvas overlay above the SVG map. During drag it bypasses React's render cycle entirely and draws directly on the canvas ref for zero-latency feedback. The map drag = time scrub. Dragging the map horizontally shifts time - one full map width equals 24 hours (1440 minutes). The math is straightforward (pixel delta → minute delta → new Date), but making it feel fluid required some care. City card updates use useDeferredValue so the main thread prioritizes the drag over re-rendering all the cards. URL state. The current city list, base city, and manual time are encoded in the URL and debounced at 500ms so you can share or bookmark a specific view. Restoring from URL has to deal with two city sources: ~306 hardcoded IANA cities and ~33k GeoNames cities that live in localStorage after a search. The GeoNames dataset was 33,334 cities after deduplication-by-timezone. I build a JSON file at deploy time rather than hitting the GeoNames API at runtime. Stack: React 18, TypeScript strict, Vite, Tailwind, Framer Motion, D3-geo Mercator, date-fns-tz, Hono for the city search API. MIT licensed.

Source: https://github.com/zzjoey/ZoneMap Live: https://zonemap.live

Known rough edges: mobile layout is functional but cramped, and the terminator calculation skips atmospheric refraction so it's off by ~0.5° at the poles.

Similar Projects