Skip to content

Commit 44ae9b8

Browse files
committed
TimePicker: stop routing UTCDateMini through date-fns/startOfMinute
Replaces `startOfMinute( inputToDate(...) )` with a small local helper that mutates the seconds/ms on the `UTCDateMini` directly. In `date-fns` v4, `startOfMinute` calls `toDate()`, which goes through `constructFrom()` and does `new input.constructor(value)`. With our `UTCDateMini` (extends `Date`) plus `timezone-mock` swapping the global `Date` in tests, that re-construction trips MockDate's "Unhandled type passed... object" assertion, breaking 50+ DateTimePicker/TimePicker tests. Setting seconds and milliseconds via the UTCDateMini's own setSeconds keeps the truncation in UTC (UTCDateMini's prototype shim reroutes setSeconds to setUTCSeconds), preserves the existing #15495 behaviour, and decouples this code path from `date-fns` — useful for future upgrades.
1 parent a766c77 commit 44ae9b8

1 file changed

Lines changed: 17 additions & 6 deletions

File tree

  • packages/components/src/date-time/time-picker

packages/components/src/date-time/time-picker/index.tsx

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { startOfMinute } from 'date-fns';
21
import { useState, useMemo, useEffect } from '@wordpress/element';
32
import { __ } from '@wordpress/i18n';
43
import { date as formatDate } from '@wordpress/date';
@@ -29,6 +28,21 @@ import { TimeInput } from './time-input';
2928

3029
const VALID_DATE_ORDERS = [ 'dmy', 'mdy', 'ymd' ];
3130

31+
/*
32+
* Truncate to the start of the minute (see #15495). Avoids `date-fns`
33+
* helpers that route through `toDate()` — in v4 that path constructs a
34+
* new instance via `new input.constructor(value)`, which fails when
35+
* combined with `@date-fns/utc`'s `UTCDateMini` and `timezone-mock`
36+
* during tests. Setting seconds/ms directly on the UTCDateMini sticks
37+
* to UTC because UTCDateMini's prototype shim reroutes setSeconds to
38+
* setUTCSeconds.
39+
*/
40+
function truncateToMinute( currentTime: TimeInputValue | undefined ): Date {
41+
const date = inputToDate( currentTime ?? new Date() );
42+
date.setSeconds( 0, 0 );
43+
return date;
44+
}
45+
3246
/**
3347
* TimePicker is a React component that renders form inputs for time and date selection. It can be used independently or as part of the `DateTimePicker` component.
3448
*
@@ -56,15 +70,12 @@ export function TimePicker( {
5670
dateOrder: dateOrderProp,
5771
hideLabelFromVision = false,
5872
}: TimePickerProps ) {
59-
const [ date, setDate ] = useState( () =>
60-
// Truncate the date at the minutes, see: #15495.
61-
startOfMinute( inputToDate( currentTime ?? new Date() ) )
62-
);
73+
const [ date, setDate ] = useState( () => truncateToMinute( currentTime ) );
6374

6475
// Reset the state when currentTime changed.
6576
// TODO: useEffect() shouldn't be used like this, causes an unnecessary render
6677
useEffect( () => {
67-
setDate( startOfMinute( inputToDate( currentTime ?? new Date() ) ) );
78+
setDate( truncateToMinute( currentTime ) );
6879
}, [ currentTime ] );
6980

7081
const monthOptions = [

0 commit comments

Comments
 (0)