Migrating to atemporal
A modern, Temporal-powered date-time library with a familiar Day.js-inspired API. Atemporal is an ergonomic wrapper whose principal representation is Temporal.ZonedDateTime; it is not a promise of full Temporal-model exposure or full compatibility with each source library.
Guides by source library
- Migrating from Day.js — most teams are here; format tokens and common APIs are familiar. See the Day.js compatibility matrix for reviewed scope.
- Migrating from Luxon — both libraries are immutable and IANA-aware; the surface maps cleanly.
- Migrating from moment.js — review the documented mappings before migration.
- Migrating from raw TC39 Temporal — atemporal is a friendly layer on top, not a replacement.
Why migrate?
| Reason | Details |
|---|---|
| Measured size evidence | See the generated size report; core, tarball, and application-bundle measurements differ. |
| Temporal runtime | @js-temporal/polyfill is a direct runtime dependency; its application-bundle cost is measured separately. |
| Migration scope | The versioned compatibility matrix identifies supported mappings and semantic differences. |
Review compatibility before migration
Shared method names do not establish equivalent semantics. Review construction, time zones, formatting tokens, duration values, locale behavior, plugins, and raw Date conversions in the source-library guide. The Day.js matrix labels each reviewed item as compatible, semantically different, plugin-required, unsupported, or better served by a different approach.
Migrating a large codebase
There is currently no official atemporal codemod. Do not depend on an unpublished @atemporal/codemod package or an external transformation as part of your migration plan.
For large codebases, migrate in small batches and use the source-library guide and compatibility matrix as the review checklist. A focused search-and-replace is usually sufficient for routine imports and construction; review time-zone parsing, DST behavior, duration values, plugins, and raw Date conversions manually. If your team owns an internal AST transform, treat its output as a candidate change and run the same tests and semantic review as hand-written migrations.
After the migration
- Enable strict mode in your test suite:ts
// jest.setup.ts import atemporal from 'atemporal'; atemporal.setStrictMode(true); - Switch untrusted user input to
atemporal.try()oratemporal.validate(). - Add the new
atemporal.presets.*constants to your codebase. - Update your CI to require TypeScript strict mode (now safe with atemporal's public typings).
Upgrading to v1.5
v1.5 is additive: atemporal(input, timeZone?) and existing plugins keep their compatibility behaviour. New applications should use the explicit boundary APIs when their data model needs a deterministic failure policy.
- Use
atemporal.parse(input, options)to throwInvalidDateErrorfor invalid values. Its defaults reject invalid calendar fields and DST gaps or overlaps. - Use
atemporal.tryParse(input, options)when invalid user input should becomenullinstead of an exception. - Select
disambiguation: "earlier","later", or"compatible"only as an intentional domain rule; the default is"reject". getLoadedPlugins()still reports official plugins only. UsegetAppliedExtensions()when diagnostics need to include third-party extensions that explicitly declare an ID.- Use
getDiagnostics(),clearCaches(),resetDiagnostics(), andprewarm()instead of importing anyatemporal/src/...implementation detail.
Preparing for v2
v2 raises the Node.js floor from 18 to 22. It supports Node 22, 24, and 26. Browser support remains available through the packaged Temporal runtime detection path and bundler fixtures. Upgrade the runtime before adopting v2; the existing callable wrapper facade remains available during the migration.