decaporg / decaporg/decap-cms

datetime widget corrupts year while typing (e.g. "2026" silently becomes "1906")

Open
#7,939 0 comments 0 reactions 0 assignees View on GitHub
area: extensions/widgets/datetime
Dominant language
JavaScript
Stars
19.4k
Forks
3.1k
Avg merge
1d 14h
Merged PRs (30d)
9

Description

**Describe the bug**

The `datetime` widget corrupts the year while it's being typed, rather than only after all digits are entered. Typing `2026` digit-by-digit can settle on a completely different year (e.g. `1906`) instead of `2026`.

**To Reproduce**

Config:
```yaml
- name: date
label: "Publish Date"
widget: datetime
format: "YYYY-MM-DD"
time_format: false
```

Steps:
1. Open an entry, focus the date field's year segment.
2. Type `2`, `0`, `2`, `6` in sequence (as a user naturally would).
3. Save the entry and inspect the resulting front matter `date`.

**Expected behavior**

The saved date has year `2026`.

**Actual behavior**

The saved date sometimes has an unrelated year such as `1906`. This isn't cosmetic — it silently corrupts saved content. In our case it also broke the page's generated URL (our permalink logic derives `/news/YYYY/MM/slug/` from this field), so a real article published to `/news/1906/08/...` instead of `/news/2026/08/...` and looked "missing" even though it built and deployed successfully.

**Root cause (as far as we could tell without stepping through the bundled/minified source)**

The widget appears to reparse/commit the year value on every keystroke rather than waiting for the full 4-digit entry. Mid-typing, a partial value gets interpreted through JavaScript's legacy 2-digit-year rule (`new Date` / `Date.parse`-style behavior where a 2-digit year 0–99 gets `1900` added to it). So an intermediate keystroke state during typing "2026" gets read as a 2-digit year, triggers the legacy `+1900` rule, and the corrupted value sticks even after the remaining digits are typed.

We confirmed:
- This is **not** a plain native `` quirk — the browser's own rolling-digit buffer for that control type handles fast sequential typing correctly on its own.
- Switching to `widget: date` isn't an option on this version (`"No control for widget 'date'"`).
- `picker_utc: true` has no effect on this — same corruption still occurs.

**Workaround**

Don't type the year at all: click "Now" to populate the field, then use the ↑/↓ arrow keys (or the browser's native spinner) on the focused year segment to adjust it. That path never triggers the bug. We've added this as a field-level `hint` in our config so editors don't lose content to it, but obviously that's just a stopgap — new/occasional editors still hit it.

**Environment**

- Decap version: `decap-cms-app 3.14.1` (loaded via `https://unpkg.com/decap-cms@^3.0.0/dist/decap-cms.js`)
- Backend: GitHub backend
- Browser: reproduced in a Chromium-based browser (Brave)

Happy to provide more repro detail or test a patch if that'd help — this one's a real content-corruption footgun for non-technical editors since nothing in the UI signals that anything went wrong.

Contributor guide

Open the contributing guide

Research direction

Start with the datetime widget in the Decap CMS JavaScript source and reproduce the issue using the YAML configuration and sequential year entry described here. Verify that typing 2026 preserves the complete year and that the saved front matter contains 2026 rather than a corrupted value; compare behavior with the documented arrow-key workaround.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
frontend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.