Skip to content

xport: preserve trailing period when reconstructing formats - #415

Merged
evanmiller merged 2 commits into
WizardMac:devfrom
hadley:fix-xport-format-trailing-period
Oct 20, 2026
Merged

evanmiller merged 2 commits into
WizardMac:devfrom
hadley:fix-xport-format-trailing-period

Conversation

@hadley

@hadley hadley commented Oct 20, 2026

Copy link
Copy Markdown
Contributor

🤖 Written by AI 🤖

The XPT namestr stores format name, width, and decimals as separate fields, so xport_parse_format() consumes the period when writing. But xport_construct_format() only re-added a period when the format had decimals, so formats round-trip lossily:

  • DATE9. → read back as DATE9
  • DATETIME20.2 → read back correctly (has decimals)

This trips up workflows that compare attributes between a dataset and the XPT written from it (e.g. tidyverse/haven#782), and disagrees with the sas7bdat reader, which stores the format string verbatim.

The fix appends the period whenever a width is present; formats with no width (e.g. $) are unaffected. Verified via haven's XPT round-trip tests: DATE9. now round-trips as DATE9., and $, 10.3, COMMA10.3 etc. are unchanged.

xport_construct_format() only emitted a period when the format had
decimals, so a format written as DATE9. was read back as DATE9. Since
the format name, width, and decimals are stored separately in the
namestr, the trailing period must be re-added whenever a width is
present (formats with no width, like $, are unaffected).

Reported in tidyverse/haven#782.
hadley added a commit to tidyverse/haven that referenced this pull request Oct 20, 2026
`read_xpt()` now takes `meta()@width` from the namestr format width (nfl, exposed by ReadStat as `display_width`) instead of the storage width, so width metadata round-trips through `write_xpt()`. sas7bdat is unaffected since it doesn't set `display_width`.

The trailing-period part of #782 is fixed upstream in WizardMac/ReadStat#415 and will land with the next vendored ReadStat update. Also disable clang-format for the vendored `src/readstat/` directory.

Fixes #782.
@evanmiller

Copy link
Copy Markdown
Contributor

Looks like tests are failing?

@hadley

hadley commented Oct 20, 2026

Copy link
Copy Markdown
Contributor Author

Oops, I will go castigate my AI.

XPORT can't record whether a format had a trailing period, and now
always reconstructs it, so test with formats that include it.
@evanmiller
evanmiller merged commit 4fbf1d8 into WizardMac:dev Oct 20, 2026
14 checks passed
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.

2 participants