Skip to content

fix(date-fns): format() returns formatted string (was undefined)#993

Merged
proggeramlug merged 1 commit into
mainfrom
worktree-agent-a3b708671bdd25be9
May 18, 2026
Merged

fix(date-fns): format() returns formatted string (was undefined)#993
proggeramlug merged 1 commit into
mainfrom
worktree-agent-a3b708671bdd25be9

Conversation

@proggeramlug
Copy link
Copy Markdown
Contributor

Summary

  • import { format } from 'date-fns'; format(new Date(2020, 0, 6), 'yyyy-MM-dd') was compiling and running cleanly but printing undefined. The manifest declared method("date-fns", "format", ...) but NATIVE_MODULE_TABLE in lower_call.rs had no module: "date-fns" rows, so native_module_lookup returned None and the call fell through to the unknown-native branch.
  • Added twelve dispatch rows covering the manifest surface (format, parseISO, addDays/Months/Years, differenceInDays/Hours/Minutes, isAfter/Before, startOfDay/endOfDay). All has_receiver: false since date-fns is a functional API.
  • Rewrote js_datefns_format to handle date-fns's lowercase Unicode-LDML tokens (yyyy/MM/dd/HH/mm/ss/...) and format in chrono::Local so the day-of-month matches Node on a non-UTC machine. The prior implementation reused js_dayjs_format, which only recognises uppercase YYYY/DD and formats in UTC — wrong on both counts for date-fns.

Test plan

  • Original repro format(new Date(2020, 0, 6), 'yyyy-MM-dd') now prints 2020-01-06 (matched byte-for-byte against node --experimental-strip-types).
  • format(d, 'yyyy'), format(d, 'MM'), format(d, 'dd'), typeof format(d, 'yyyy') all match Node output.
  • test-files/test_date_fns_format.ts extended with end-to-end format(...) checks alongside the existing regex-token regression cases; existing regex output unchanged.
  • cargo build --release -p perry-runtime -p perry-stdlib -p perry-jsruntime -p perry clean.

Wires the missing NATIVE_MODULE_TABLE rows for `date-fns` so the
manifest's `method("date-fns", "format", false, _)` actually reaches
`js_datefns_format` at codegen, and rewrites the runtime impl to handle
date-fns's lowercase LDML tokens (`yyyy/MM/dd`) in local time instead of
delegating to the dayjs formatter (which only understands uppercase
tokens and formats in UTC).
@proggeramlug proggeramlug merged commit b54fd92 into main May 18, 2026
5 of 9 checks passed
@proggeramlug proggeramlug deleted the worktree-agent-a3b708671bdd25be9 branch May 18, 2026 06:01
proggeramlug added a commit that referenced this pull request May 18, 2026
PR #993 only emitted runs of repeated letters, so date-fns ordinal
tokens like `do` were split into a `d` run ("6") and a lone `o` which
fell into the unknown-letter catch-all ("o") — producing
"January 6o 2020" instead of "January 6th 2020".

Extends the token loop to:

- Detect single-letter run + literal `o` over the date-fns ordinal
  alphabet ([yYQqMLwIdDecihHKkms]o) and emit an English ordinal via a
  new `english_ordinal()` helper (handles 11/12/13 → "th").
- Differentiate AM/PM by run length: a/aa = AM/PM, aaa = am/pm,
  aaaa = a.m./p.m., aaaaa = a/p.

Test fixture extended to cover yyyy-MM-dd HH:mm:ss, MMMM do yyyy, EEEE,
do/Mo/yo, and the four a-variants — all match `node --experimental-strip-types`
on date-fns@4.1.0 byte-for-byte.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant