Skip to content

Why Doran

Doran's core is a zero-dependency, immutable, tree-shakeable Jalali engine with IANA time zones built in. Against the usual stack — moment + moment-jalaali — that translates into a much smaller bundle and faster hot paths, with no second library for time zones.

Bundle size

Measured with the same pipeline (esbuild --minify, then gzip) so the numbers are comparable — not pulled from different sources.

SetupMinifiedGzipped
moment + moment-jalaali85.5 kB25.1 kB
dayjs + jalaliday16.0 kB6.2 kB
@doranjs/core (full barrel)23.5 kB7.9 kB
@doranjs/coreDoranDate + format19.1 kB6.3 kB
@doranjs/core — conversion primitives only4.6 kB1.8 kB
@doranjs/coreDuration only5.3 kB1.8 kB

Doran is roughly 3× smaller gzipped than moment + moment-jalaali — a real migration dropped ~63 kB from an app bundle by removing moment. It is in the same class as dayjs + a Jalali plugin, but zero-dependency, with IANA time zones built in (no moment-timezone), immutable, and Jalali as a first-class calendar rather than a plugin.

Tree-shaking

@doranjs/core is "sideEffects": false and fully ESM, so bundlers drop what you don't import. Pull only what you use:

ts
// Just the calendar math — ~1.8 kB gzipped, no formatter, no parser.
import { jalaliToGregorian, gregorianToJalali } from '@doranjs/core';

Import named exports (not import * as), and let your bundler do the rest.

Performance

Operations per second, higher is better. @doranjs/core vs moment + moment-jalaali, Node 20, both pinned to a fixed time zone for a fair comparison (moment-jalaali is not time-zone-aware by default).

Operation@doranjs/coremoment + moment-jalaaliSpeedup
format~315,000~289,0001.1×
parse~210,000~128,0001.7×
construct~250,000~127,0002.0×
diff (days)~38,000,000~2,200,00017×

Reproduce locally:

sh
pnpm --filter @doranjs/core build
node packages/core/bench/index.mjs

Reuse the time zone

Constructing with an explicit { timeZone } (or the system default once) lets Doran cache the underlying Intl.DateTimeFormat. Re-resolving the system zone on every call is the one thing that measurably slows construction down.

Beyond the numbers

  • Zero runtime dependencies — nothing to audit or get a CVE from.
  • Time zones built in — DST-correct IANA conversion without a second package.
  • Immutable — every operation returns a new instance; no accidental mutation.
  • One instant, two calendarstoISOString() for your backend, format() for Jalali display. See Backends & serialization.
  • TypeScript-native, with a familiar dayjs/moment token vocabulary.

CI guards the published bundle with a gzip budget (scripts/size-check.mjs), so these numbers stay honest as the library grows.

Released under the MIT License.