Library / SDK
spencermountain/spacetime avatar
spencermountain/spacetime

spacetime: a JavaScript date calculator for remote timezones

A lightweight javascript timezone library

4,107 stars190 forksJavaScriptNOASSERTION

At a glance

What is it?
spencermountain/spacetime is a zero-dependency JavaScript library for doing date math across timezones, with daylight savings and leap years handled for you. It is small, immutable, and aimed at front-end and Node code that needs timezone conversion without pulling in a full date framework.
Who is it for?
Adopt spacetime if you need remote-timezone date math in JavaScript and want an immutable, Moment-like API without a large dependency. Do not adopt it if you need full locale and calendar-system formatting, or if you expect the README to walk you through every edge case; parts of the API live in the linked Observable notebook and the wiki.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The gap spacetime fills: date math across timezones

The README opens with a plain complaint: people can do math in their head but not date math, and there is no real date calculator. The examples it gives are the kind of question a user actually asks: how many days until the end of the year, what time was it 11 hours ago, is it lunchtime in France. spacetime positions itself as the answer to those, rather than as a full formatting framework. It is for JavaScript developers who need to move a moment between timezones, subtract hours, compare against a wall-clock time, or ask whether it is a given season or quarter. The README lists the intended capabilities directly: calculate time in remote timezones, support daylight savings, leap years and hemispheres, and expose a Moment-like API that is immutable. If your problem is "what is this timestamp in Europe/Paris, and how many days is that from the end of the year," this is the target. If your problem is rendering dates in thirty locales with correct month names and calendar systems, that is a different library.

How spacetime handles timezones without the Intl API

The README states the library has zero dependencies and does not use the Intl API. That is a deliberate design choice with a visible consequence: the timezone data has to ship with the package. The repository layout confirms this. There is a top-level zonefile/ directory, and package.json includes "zonefile" in the files array alongside src, builds, api and types. A build step named pack runs node ./zonefile/pack.js, and a separate build:tz script runs node ./scripts/tz/update.js. So timezone rules are packed into the library rather than read from the host environment at runtime. The README also says the library has frequent updates for approaching DST changes, which follows from that model: if the rules are baked in, they need refreshing when governments change them. The API itself is immutable, so methods return new objects rather than mutating the existing one, and the README describes the surface as Moment-like. Inputs are flexible. The README shows epoch milliseconds, arrays in [yyyy, m, d] form with zero-based months and 1-based days, ISO strings, and a timezone as an optional second parameter. It also documents helpers like spacetime.now(), spacetime.today(), spacetime.tomorrow(), spacetime.min() and spacetime.max().

Installing spacetime and running a first timezone conversion

The README gives the install command as npm install spacetime. That is the whole install step; there is no configuration file and no service to run. In a CommonJS context the README shows requiring the package and calling spacetime.now() with a timezone, then using dayName() and isAsleep(). Note that isAsleep() is a library-specific helper, not a browser API.

js
const spacetime = require('spacetime')
let d = spacetime.now('Europe/Paris')
d.dayName()
//'Wednesday'
d.isAsleep()
//true

For TypeScript, Babel or Deno, the README shows an ES module import and the format('nice') output, which produces a human-readable string such as 'Apr 1st, 4:32pm'. The package.json exports map points the import condition at ./builds/spacetime.mjs and the require condition at ./builds/spacetime.cjs, with types at ./types/index.d.ts and ./types/index.d.cts.

ts
import spacetime from 'spacetime'
let d = spacetime.now()
d.format('nice')
//'Apr 1st, 4:32pm'

If you would rather not use a bundler at all, the README shows a script tag against unpkg, then constructing a date with an explicit timezone, setting a time, and calling goto() to convert. The README's example converts 'March 1 2012' in America/New_York set to 4:20pm into America/Los_Angeles, and the comment shows the result as '1:20pm'.

html
<script src="https://unpkg.com/spacetime"></script>
<script>
  var d = spacetime('March 1 2012', 'America/New_York')
  d = d.time('4:20pm')
  d = d.goto('America/Los_Angeles')
  d.time()
  //'1:20pm'
</script>

Once that runs, you have the core loop: construct a moment with a zone, adjust it, move it to another zone, read it back. The README's opening example also shows diff() against endOf('year') with a 'days' unit and subtract(11, 'hours') followed by time().

Where spacetime is the wrong tool

The README is explicit that the library is small, and small has costs. It does not use Intl, so anything Intl would give you for free, such as locale-aware month and weekday names in arbitrary languages, is not the point of this package. The formatting you get is the library's own, including the 'nice' format shown in the README. If your product needs localized date rendering across many locales, that is outside what the README claims. The bundled zonefile is also a maintenance surface. Because rules are packed into the package rather than queried from the runtime, a government changing its DST rules means waiting for a library release that updates the zonefile. The README acknowledges this pattern by noting frequent updates for approaching DST changes, which is honest but also an admission that the data goes stale between releases. There is a second documentation limit worth flagging. The README links a full API to an Observable notebook and a wiki for inputs and TypeScript, and there is an AGENTS.md file for LLM docs. The README itself is a tour, not a reference. If you need a guaranteed contract for an unusual method, you will be reading the notebook, the wiki or the source. Finally, if your requirement is a full date framework with plugins for durations, locales and calendar systems, spacetime is a narrower instrument.

spacetime compared with Moment and date-fns

The README itself frames the API as Moment-like but immutable, which is the clearest available comparison. Moment's API is the reference point the author chose, so anyone migrating from Moment will recognize method names and the general shape of chaining. The difference the README stresses is immutability: methods return new objects rather than changing the one you hold. That matters in shared state and in React-style rendering, where an accidental mutation is a bug that is hard to trace. date-fns is the other natural reference point for a small JavaScript date library, and the difference in approach is structural. date-fns is a collection of functions over native Date objects, while spacetime wraps a moment in its own object with timezone awareness and a bundled zonefile. The README's zero-dependency and no-Intl claims are the distinguishing facts here: spacetime carries its own timezone rules, which is why it can do remote-timezone math in environments where Intl is missing or inconsistent, and why it needs zonefile updates. If you want tree-shakeable pure functions over native dates, date-fns is the closer fit. If you want an object you can move between named zones and compare against wall-clock times, spacetime is built for that.

Maintenance, releases and what the licence file actually says

The repository is not archived, and the last push was on 2026-09-22, so the project is being touched. The release history supports the claim in the README about frequent updates: 7.13.0 on 2026-06-23, 7.14.0 on 2026-09-11, and 7.15.0 on 2026-09-19. That cadence is consistent with a library that ships timezone data and needs to refresh it. The package.json version is 7.15.0, matching the latest release. On the build side, package.json defines scripts for build, build:tz, pack, test, test:types, coverage and lint, and the test script runs tape over test/**/*.test.js piped to tap-dancer. There is a test:release script and a codecov configuration file in the repository root. For upgrade cost, the practical question is whether the zonefile changed and whether your bundler picks up the right export condition. The exports map separates import and require targets, so an ESM project gets builds/spacetime.mjs and a CommonJS project gets builds/spacetime.cjs. The licence is the part to check yourself. The repository metadata reports the licence as NOASSERTION, which means the automated detection could not classify it, and there is a LICENSE file at the repository root. Read that file before you ship. Nothing here is legal advice, and the package metadata alone will not tell you what the terms are.

Editorial conclusion

Adopt spacetime if you need remote-timezone date math in JavaScript and want an immutable, Moment-like API without a large dependency. Do not adopt it if you need full locale and calendar-system formatting, or if you expect the README to walk you through every edge case; parts of the API live in the linked Observable notebook and the wiki. Before committing, check that the timezone identifiers you rely on are present in the zonefile, and confirm the exports in package.json match how your bundler resolves ESM and CommonJS.

Frequently asked questions

How do I install spacetime in a JavaScript project?

The README gives the command as npm install spacetime. There is no configuration step and no service to run; after installing you require or import the package and call spacetime.now() with an optional timezone.

Does spacetime use the Intl API for timezone data?

No. The README lists zero dependencies and explicitly says no Intl API. Timezone rules ship with the package in the zonefile directory, which is why the project publishes frequent updates for approaching DST changes.

Can spacetime convert a time from one timezone to another?

Yes. The README's browser example constructs a date in America/New_York, sets the time to 4:20pm, calls goto('America/Los_Angeles'), and the comment shows the result as '1:20pm'.

Is spacetime mutable like Moment?

The README describes the API as Moment-like but immutable, so methods return new objects instead of changing the one you already hold.

What is the licence for spacetime?

The repository metadata reports the licence as NOASSERTION, and a LICENSE file sits at the repository root. The metadata does not identify the terms, so read that file before shipping the package.

Official sources

  1. Issues
  2. Project website
  3. README
  4. Releases
  5. spencermountain/spacetime on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/spencermountain-spacetime.svg)](https://hysenlabs.com/projects/spencermountain-spacetime)