Skip to content

DateTimePicker day input issue #75530

Closed

Description

@anastis

Description

It looks like there is an issue updating the component's day field, when the value itself has been changed.

Step-by-step reproduction instructions

  1. Create a new or open an existing post.
  2. Click on the Publish field to expand the DateTimePicker control.
  3. Select February from the dropdown, or click on any February date on the calendar.
  4. Enter 30 into the Day field.
  5. Click just outside the day field, or hit tab to move focus.

The month dropdown and the calendar below, correctly change to March 2nd.
The day field shows 30.

  1. Click inside the day field, and out again (or move focus in and out again with shift-tab and tab)

The day field now is updated to the correct 02

Screenshots, screen recording, code snippet

Without the Gutenberg plugin enabled.

Image


With the Gutenberg v22.5.3 plugin enabled, once the day field loses focus:

Image

Environment info

  • WP: 6.9 & 6.9.1
  • Theme: Twenty Twenty-Five
  • Firefox & Chrome on MacOS & Windows

Please confirm that you have searched existing issues in the repo.

  • Yes

Please confirm that you have tested with all plugins deactivated except Gutenberg.

  • Yes

Please confirm which theme type you used for testing.

  • Block
  • Classic
  • Hybrid (e.g. classic with theme.json)
  • Not sure

Activity

  1. added
    [Type] BugAn existing feature does not function as intended
    on Feb 13, 2026
  2. t-hamano commented on Feb 14, 2026

    @t-hamano
    Contributor

    Thanks for the report.

    It appears that an unintended problem occurs when a day that does not exist in the month is specified.

    • Set the date to March 31st.
    • Change the month to February. The UI crashes.
    0022d112383d1eee52d1d0b0140e3991.mp4

    The UI crash is a particularly serious issue, so let's fix it in WordPress 7.0.

  3. t-hamano commented on Feb 14, 2026

    @t-hamano
    Contributor

    I discovered that the UI crash was caused by #73887. My guess is that some of the setInConfiguredTimezone() functions added by #73887 create invalid date objects that don't exist, such as February 31st.

    @aduth @tyxla, seems like one of the following processes should be added when the date overflows. What do you think?

    • Convert to an actual date that exists. For example, convert February 31st to March 3rd.
    • Truncate the overflowed date. For example, convert February 31st to February 28th.
  4. aduth commented on Feb 16, 2026

    @aduth
    Member

    There have been a couple related issues and pull requests around this in the past couple weeks which address some (but maybe not all) of these types of invalid date entries:

    #75254 was fixed in #75343, though I think the behavior there is about year values fewer than 4 characters.

    #75285 is likely to be the more holistic fix, likely also addressing this issue as well in how it guards against updating invalid dates. If I understand, the behavior there is to reset the value to the last good value when blurring if the new date would be invalid.

    cc @getdave

  5. tyxla commented on Feb 22, 2026

    @tyxla
    Member

    Yep, I agree with @t-hamano that the behavior should work similarly to how Date() works in JavaScript (it handles leap year and any other subtleties already):

    Image

    @getdave was working on some improvements here, and we discovered some additional pre-existing issues while working on #75285. My understanding is @getdave will get back to this at some point as the more important work on 7.0 cools down. Let's make sure to create issues with those, so we don't lose track of them.

  6. t-hamano commented on Mar 11, 2026

    @t-hamano
    Contributor

    It appears that an unintended problem occurs when a day that does not exist in the month is specified.

    • Set the date to March 31st.
    • Change the month to February. The UI crashes.

    Since this issue first occurred in 7.0, I think it should be fixed in the 7.0 release. What do you think about extracting only the invalid data guard processing from #75285 and merging it first? In other words, the code looks like this:

    diff --git a/packages/components/src/date-time/time/index.tsx b/packages/components/src/date-time/time/index.tsx
    index 245446736e8..ccd88562aa0 100644
    --- a/packages/components/src/date-time/time/index.tsx
    +++ b/packages/components/src/date-time/time/index.tsx
    @@ -106,8 +106,23 @@ export function TimePicker( {
                    [ date ]
            );
     
    +       const updateDate = ( newDate: Date ) => {
    +               // Guard against Invalid Date propagation.
    +               if (
    +                       newDate instanceof Date &&
    +                       ! Number.isFinite( newDate.getTime() )
    +               ) {
    +                       return;
    +               }
    +
    +               setDate( newDate );
    +               onChange?.( formatDate( TIMEZONELESS_FORMAT, newDate ) );
    +       };
    +
            const buildNumberControlChangeCallback = ( method: 'date' | 'year' ) => {
                    const callback: InputChangeCallback = ( value, { event } ) => {
    +                       // validateInputElementTarget checks event.target.validity.valid,
    +                       // which catches empty values via the 'required' attribute
                            if ( ! validateInputElementTarget( event ) ) {
                                    return;
                            }
    @@ -120,8 +135,7 @@ export function TimePicker( {
                            const newDate = setInConfiguredTimezone( date, {
                                    [ method ]: numberValue,
                            } );
    -                       setDate( newDate );
    -                       onChange?.( formatDate( TIMEZONELESS_FORMAT, newDate ) );
    +                       updateDate( newDate );
                    };
                    return callback;
            };
    @@ -136,8 +150,7 @@ export function TimePicker( {
                            hours: newHours,
                            minutes: newMinutes,
                    } );
    -               setDate( newDate );
    -               onChange?.( formatDate( TIMEZONELESS_FORMAT, newDate ) );
    +               updateDate( newDate );
            };
     
            const dayField = (
    @@ -175,8 +188,7 @@ export function TimePicker( {
                                            const newDate = setInConfiguredTimezone( date, {
                                                    month: Number( value ) - 1,
                                            } );
    -                                       setDate( newDate );
    -                                       onChange?.( formatDate( TIMEZONELESS_FORMAT, newDate ) );
    +                                       updateDate( newDate );
                                    } }
                            />
                    </MonthSelectWrapper>
  7. moved this from 📥 Todo to 🗣️ In Discussion / Needs Decision in WordPress 7.0 Editor Taskson Mar 11, 2026
  8. tyxla commented on Mar 11, 2026

    @tyxla
    Member

    What do you think about extracting only the invalid data guard processing from #75285 and merging it first?

    Yeah, I was mostly worried about the initial implementation of that, but the most recent one with newDate instanceof Date && ! Number.isFinite( newDate.getTime() ) should do the job.

    @getdave @aduth is adding the guard, something we can do in the next few days, so it will be part of the release?

  9. aduth commented on Mar 11, 2026

    @aduth
    Member

    @getdave @aduth is adding the guard, something we can do in the next few days, so it will be part of the release?

    I'll look to get a pull request put together today 👍

  10. aduth commented on Mar 11, 2026

    @aduth
    Member

    One potential downside of that simple solution is that it could prevent user interactions in ways that are confusing: For example, if I set the date as 31 March 2026 and then change the dropdown month from March to February, then the UI would appear to be unresponsive, as it disallows the change to 31 February 2026 since it's an invalid date.

  11. aduth commented on Mar 11, 2026

    @aduth
    Member

    I found a pretty simple solution to restore the date clamping to prevent invalid dates from being selected. Though it requires a bit more work to ensure that the input value is synced correctly to the clamped date.

    Interestingly, this wasn't really working very well before either. For example, entering 30 February 2026 in WordPress 6.9 and then tabbing will cause the text field to show as 30 March 2026 but the actual selected date is 02 March 2026.

    calendar-6.9.mov
  12. aduth commented on Mar 11, 2026

    @aduth
    Member

    #76400 should be sufficient to address most of the problems:

    • Avoids crash when given date out of bounds
    • Correctly reflects bounded value in input field after blur
    • Prevents ArrowUp day increment beyond valid day for month

    As part of this, I also discovered some fundamental issues with InputControl "draft" tracking that I am trying to address in #76399 and was originally targeted at the input value de-sync problem described in my previous comment. I think this is still an issue (the test case added there feels like something we should support), but it has some gnarly knock-on effects for components that depended on its broken behavior.

  13. moved this from 🗣️ In Discussion / Needs Decision to 🏗️ In Progress in WordPress 7.0 Editor Taskson Mar 12, 2026
  14. moved this from 🏗️ In Progress to ✅ Done in WordPress 7.0 Editor Taskson Mar 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

[Package] Components/packages/components[Status] In ProgressTracking issues with work in progress[Type] BugAn existing feature does not function as intended

Type

No type

Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions