Skip to content

date: drop a trailing backslash instead of formatting it as "undefined" - #81528

Open
Kgupta62 wants to merge 1 commit into
WordPress:trunkfrom
Kgupta62:fix/date-trailing-backslash
Open

date: drop a trailing backslash instead of formatting it as "undefined"#81528
Kgupta62 wants to merge 1 commit into
WordPress:trunkfrom
Kgupta62:fix/date-trailing-backslash

Conversation

@Kgupta62

Copy link
Copy Markdown
Contributor

What?

format() no longer emits the literal string undefined when the format string ends with a backslash.

Why?

The escape branch consumes the next character with no bounds check:

if ( '\\' === char ) {
	i++;
	newFormat.push( '[' + dateFormat[ i ] + ']' );
	continue;
}

For a trailing backslash there is no next character, so dateFormat[ i ] is undefined, string concatenation stringifies it, and moment renders it as a literal:

  • date( 'Y\\', … )"2019undefined" (expected "2019")
  • date( 'Y-m-d\\', … )"2019-06-18undefined" (expected "2019-06-18")

The JSDoc points at PHP's date() as the reference, and PHP emits nothing for a dangling trailing backslash. A user who mistypes a date format in Settings → General, or a plugin that builds a format by concatenation, gets the word "undefined" printed in every date on the site.

How?

Only push the escaped character when there is one. Two unit tests cover a trailing backslash on its own and after a full date format; both fail on trunk with the output above.

Out of scope: a format string consisting of only a backslash. With this change it behaves exactly like an empty format string, which moment renders as an ISO date. That is the pre-existing behaviour of an empty format and is left alone here.

Testing Instructions

npm run test:unit -- packages/date

By hand:

  1. Go to Settings → General and set the custom date format to Y-m-d\ (with the trailing backslash).
  2. View a post on the front end, or the post list in the editor.
  3. Before this change the date reads 2026-08-12undefined; after it, 2026-08-12.

Testing Instructions for Keyboard

n/a — no interaction changes.

Use of AI Tools

AI tooling (Claude Code) was used to help find this defect and draft the fix and tests. I confirmed the wrong output on trunk myself, verified the tests fail before the change and pass after, and take responsibility for the code in this PR.

@github-actions github-actions Bot added the [Package] Date /packages/date label Aug 12, 2026
@github-actions

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

Unlinked Accounts

The following contributors have not linked their GitHub and WordPress.org accounts: @Kgupta62.

Contributors, please read how to link your accounts to ensure your work is properly credited in WordPress releases.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Unlinked contributors: Kgupta62.


To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

Comment on lines +429 to +434
// Add next character, then move on. A backslash that ends the
// format has nothing to escape, so it is dropped, as in PHP.
i++;
newFormat.push( '[' + dateFormat[ i ] + ']' );
if ( i < dateFormat.length ) {
newFormat.push( '[' + dateFormat[ i ] + ']' );
}

@im3dabasia im3dabasia Aug 12, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you share the motivation? This has behaved this way since long, with no linked issue and no sign of anyone hitting it, the trigger is a format string someone would have to mistype by hand.

I'd gently push back on changing long-standing behaviour that isn't causing a reported problem. Each one still costs review time and carries regression risk, without a case on the other side of the ledger.

Same applies to a few of your other open PRs, the effort is appreciated, I'd just love to see it pointed at reported issues.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @im3dabasia — the pushback is fair, and I agree with the principle. Here the trigger is not only a hand-mistyped constant, so let me lay it out.

The Date / Post Date block ships a free-text Custom format field — <TextControl label="Custom format"> in packages/block-editor/src/components/date-format-picker/index.js — and it calls onChange on every keystroke straight into the block's format attribute. The editor preview renders that string with dateI18n( format || siteFormat, … ) (packages/block-library/src/post-date/edit.js:103), while the front end renders the same string through PHP wp_date().

Two consequences:

  1. Anyone escaping a literal — typing \a\t for "at", say — has \ as the last character for one keystroke, and in that moment the editor preview prints undefined where PHP prints nothing.
  2. A format saved with a trailing backslash renders 2019-06-18undefined in the editor and 2019-06-18 on the front end.

That is an editor/front-end mismatch on a field users type into, which is the case I would want on the other side of the ledger.

The patch only touches the branch where the backslash has nothing left to escape — the escape behaviour itself is unchanged, it just stops emitting [undefined] into the moment format and matches PHP date().

On the broader point: taken on board. I will point the rest at reported issues rather than open more of these, and I am happy to close this one if you still think the trigger is too narrow to be worth the review time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Package] Date /packages/date

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants