Compatibility-first migration bridge away from moment.js
Compatibility
Compatibility should be inspectable.
This page exists to show what matches moment.js, what is partial, what is unsupported, and
where teams should read more before rollout.
How To Read This Page
The goal is not to make a sweeping claim that every behavior is identical in every context.
The goal is to make the current state legible enough that a staff engineer or maintainer can
decide whether a controlled evaluation is justified.
Read compatibility as a scoped claim, not a universal promise.
Pay extra attention to parsing, invalid inputs, offsets, and locale-sensitive output.
Prefer behavior comparisons against your own production fixtures before broad rollout.
Recommended entry point: Use mmntjs/lite (55.2KB raw bundled) for most
evaluations. It covers the same compatibility-verified parsing, formatting, add/subtract,
diff, and comparison paths as the default entry, without the full-compat surface. The
full mmntjs entry (179.5KB raw bundled) is available when your codebase needs
moment.utc(), moment.parseZone(), duration helpers, or
locale-rich tokens like MMMM and dddd without plugin imports.
Current Evidence
630/630 moment.js 2.30.1 official test suite passing
2,063/2,063 current curated `bun run test` suite passing
3,846 timezone, DST, and timezone-package test cases passing across six timezones
112 property-style oracle tests with tens of thousands of assertions against upstream moment.js
11 coverage-guided fuzz harnesses plus a grammar-based ISO generator
Comparison Policy
Prefer documented scope over blanket claims.
Treat compatibility bugs as release-relevant changes, not as incidental cleanup.
Keep known differences visible enough that migration reviewers can use them directly.
In practice, that means a page like this should help a reviewer answer two questions: what
behavior appears compatible enough to evaluate now, and where should we add targeted checks
before widening scope?
Matrix
Area
Status
Notes
Formatting
Compatible
Token and locale output are covered by upstream and locale-derived tests.
Manipulation
Compatible
add/subtract/startOf/endOf semantics are treated as compatibility-critical.
Query and comparison
Compatible
diff and comparison methods are covered by oracle and property tests.
Duration
Compatible
Construction, normalization, and relative-time behavior are part of the test matrix.
Locale
Compatible
Locale behavior is validated against the upstream locale suite.
UTC and parseZone
Compatible
UTC and fixed-offset behavior are tested; timezone package provides compatible IANA timezone data support.
Invalid dates
Compatible
Examples: moment("2024-02-31"), moment("not-a-date"), moment([2024, 1, 31]), and moment.invalid().
Parsing
Mostly compatible
Standard ISO, RFC 2822, custom format, array, object, sign-prefixed, and control-character inputs match moment.js. One known difference is mixed input like "93280531 09-3911".
Status Vocabulary
Compatible: Behavior is expected to match within the documented scope and is covered by direct tests.
Mostly compatible: Behavior is broadly aligned, but some known edge cases remain and are documented.
Partial: Useful support exists, but adoption should be limited to the documented subset.
Not supported: Do not assume equivalent behavior without a dedicated compatibility layer.
Known Differences
Current known gaps are concentrated in specific parsing edge cases rather than broad API areas.
One concrete example is mixed input "93280531 09-3911".
Invalid-date and offset-sensitive behavior are documented explicitly because they drive migration risk.
Compatibility claims should always be read with the documented scope in mind.
Known parsing difference example: "93280531 09-3911" renders a different local date/time from moment.js.
Core mmntjs covers UTC and fixed-offset behavior; full IANA timezone data is a separate package.
Locale files stay pure data by default, with optional locale-auto/* side-effect entries for one-line migration.
This is intentionally plain language. The audience for this page is trying to assess adoption
risk, not to decode whether caveats are being softened by marketing.
Highest-Risk Evaluation Areas
Parsing
Check the exact inputs your app already relies on: ISO strings, RFC 2822 mail dates, custom format strings, and array inputs like [2024, 0, 1]. One current known difference is mixed input like "93280531 09-3911".
Invalid dates
Examples: moment("2024-02-31"), moment("not-a-date"), moment([2024, 1, 31]), and moment.invalid(). Check how they behave in isValid(), format(), diff(), and comparisons.
Timezone and offsets
UTC and fixed-offset flows need explicit review around keepLocalTime, parseZone, and DST-adjacent transitions.
Parsing Edge Cases
One current known parsing-difference input is:
"93280531 09-3911"
Invalid Date Examples
Examples of invalid inputs and invalid values:
moment("2024-02-31").isValid() // falsemoment.invalid().format() // "Invalid date"moment("not-a-date").diff(moment("2024-01-01")) // invalid-path behavior should match moment.js
Unsupported Or Separate Scope
Assume core mmntjs does not provide an IANA timezone database by itself.
Treat known parsing edge cases as migration review items, not invisible footnotes.
Use separate timezone support when your application depends on moment-timezone-style data behavior.
For most teams, this means the first migration question is not "is everything identical?"
but "does the subset we rely on behave the same under our tests and fixtures?" This page is
meant to support that narrower and more useful decision.