EHLOVader/isitdaylightsaving: The Static Site That Knows Your Timezone Is Lying

A tiny Astro utility turns a notoriously slippery calendar problem into a yes-or-no answer, using build-time data, a browser-side Web Component, and almost no JavaScript.

6 min read View on GitHub More from EHLOVader

A split editorial scene shows a static print press on one side and a live clock face on the other. Between them sits a small browser window displaying a yes-or-no daylight saving result, while a fan of timezone placards suggests a catalog baked into the page. The image explains how the site stays static while still producing a live, user-specific answer.
The trick is not to make the whole page dynamic. It is to reserve dynamism for the one question only the browser can answer.
Key Takeaways

Daylight saving time is a trap disguised as a calendar rule. It depends on where you are, what date it is, and which timezone database you trust. EHLOVader/isitdaylightsaving answers that mess with a static Astro site that behaves like a live service.

That sounds contradictory until you look at the split. The site prebuilds the world it can know, then lets the browser settle the only question that is truly local: whether you are in DST right now.

How the Trick Works

The page is static until the browser resolves the one variable the server cannot know.

<is-dst data-tz="Europe/London"></is-dst>

<script>
  class IsDST extends HTMLElement {
    connectedCallback() {
      const zone = this.dataset.tz || Intl.DateTimeFormat().resolvedOptions().timeZone;
      const now = luxon.DateTime.local().setZone(zone);
      this.textContent = now.isInDST ? 'yes' : 'no';
    }
  }
  customElements.define('is-dst', IsDST);
</script>

The World Is Built at Build Time

The cleverest part of the repo is not the checker. It is the route generation. In getStaticPaths(), the build fetches the available timezone list from TimeAPI.io, then turns that catalog into static pages under /tz/. The site learns the global map once, before deploy, and never needs the API again afterward.

ResponsibilityBuild timeBrowser time
Timezone catalogFetched from TimeAPI.io and turned into routesNot needed
Page structureAstro renders static HTMLNot needed
DST decisionNot decided yetLuxon checks the relevant zone
Failure modeBuild fails if the timezone source is unavailableThe deployed site keeps working independently
Cost modelOne network fetch during buildA tiny client-side check

That trade-off is honest. If the upstream timezone API is down during CI, the build breaks. But once the site ships, it is self-contained. The runtime footprint stays tiny because the expensive part was paid once.

A close-up customs desk for timezones shows preprinted cards being stamped on one side and a browser window selecting one card on the other. A small DST badge appears after the selection, turning the scene into a visual metaphor for build-time data being handed to browser-time logic. The image explains the division between baked-in route generation and local evaluation.
The build stamps the timezone inventory first. The browser only picks the right card and asks the final question.

Why Web Components Beat a Bigger Framework Here

This repo could have reached for a heavier client framework. It did not need to. The question is binary, the DOM update is tiny, and the result is a better fit for a Web Component than a full app runtime.

ChoiceWhat it buysWhat it costs
Vanilla Web ComponentTiny script, direct DOM control, reusable checkerLess abstraction, more manual wiring
Server-rendered checkerCentralized logic, easy to query from the backendRequires a server or SSR path
Full client frameworkRich composition and state handlingToo much machinery for a yes/no utility

That restraint matters. The component reads either the local browser timezone or the data-tz attribute on a timezone page, hands the zone to Luxon, and writes back a boolean. No state machine. No hydration drama. Just enough JavaScript to answer the question.

The Timezone Index Is a Map, Not a Database

The /tz index does a different kind of work. Instead of making the browser smarter, it organizes the baked-in catalog into something legible. The page groups timezones and lays them out in columns, turning a long list into a navigable atlas.

ViewWhat it optimizes forWhy it works
Root pageImmediate answerIt asks the browser one local question
/tz indexBrowsingIt turns a raw catalog into a readable map
/tz/[zone] pagesSpecificityIt reuses the same tiny checker with a different zone

That is the broader lesson. Modern utility sites do not need to be big to feel complete. They need to put each concern in the right place, then stop.

What This Repo Says About Modern Utility Sites

isitdaylightsaving is a simple Python library for checking if daylight saving time is currently in effect.

The quote is plain, and that is part of the appeal. The project is a single-purpose utility with a single-purpose architecture. Astro handles the static shell, a Web Component handles the local truth, and build-time data handles the global map. The result is a small site that behaves with more intelligence than its size suggests.