diff --git a/packages/x-date-pickers-pro/src/DateRangeCalendar/DateRangeCalendar.tsx b/packages/x-date-pickers-pro/src/DateRangeCalendar/DateRangeCalendar.tsx index 0c1e0f734bec..6c6379c2b433 100644 --- a/packages/x-date-pickers-pro/src/DateRangeCalendar/DateRangeCalendar.tsx +++ b/packages/x-date-pickers-pro/src/DateRangeCalendar/DateRangeCalendar.tsx @@ -264,6 +264,7 @@ const DateRangeCalendar = React.forwardRef(function DateRangeCalendar( rangePosition, allowRangeFlip, shouldMergeDateAndTime: true, + referenceDate, }); const isNextSectionAvailable = availableRangePositions.includes(nextSelection); diff --git a/packages/x-date-pickers-pro/src/DesktopDateTimeRangePicker/tests/DesktopDateTimeRangePicker.test.tsx b/packages/x-date-pickers-pro/src/DesktopDateTimeRangePicker/tests/DesktopDateTimeRangePicker.test.tsx index 228a8728d448..e8537c5cfc1d 100644 --- a/packages/x-date-pickers-pro/src/DesktopDateTimeRangePicker/tests/DesktopDateTimeRangePicker.test.tsx +++ b/packages/x-date-pickers-pro/src/DesktopDateTimeRangePicker/tests/DesktopDateTimeRangePicker.test.tsx @@ -39,6 +39,22 @@ describe('', () => { expect(expectFieldValueV7(startSectionsContainer, '01/11/2018 04:05 PM')); expect(expectFieldValueV7(endSectionsContainer, '01/11/2018 05:10 PM')); }); + + it('should use time from `referenceDate` when selecting the day', () => { + render( + , + ); + + openPicker({ type: 'date-time-range', variant: 'desktop', initialFocus: 'start' }); + + fireEvent.click(screen.getByRole('gridcell', { name: '11' })); + + expect(screen.getByRole('option', { name: '2 hours', selected: true })).not.to.equal(null); + expect(screen.getByRole('option', { name: '15 minutes', selected: true })).not.to.equal(null); + expect(screen.getByRole('option', { name: 'PM', selected: true })).not.to.equal(null); + const startSectionsContainer = getFieldSectionsContainer(0); + expect(expectFieldValueV7(startSectionsContainer, '04/11/2022 02:15 PM')); + }); }); describe('disabled dates', () => { diff --git a/packages/x-date-pickers-pro/src/internals/utils/date-range-manager.test.ts b/packages/x-date-pickers-pro/src/internals/utils/date-range-manager.test.ts index 6f96c2411492..546704091800 100644 --- a/packages/x-date-pickers-pro/src/internals/utils/date-range-manager.test.ts +++ b/packages/x-date-pickers-pro/src/internals/utils/date-range-manager.test.ts @@ -18,6 +18,15 @@ describe('date-range-manager', () => { expectedRange: [start2018, null], expectedNextSelection: 'end' as const, }, + { + range: [null, null], + rangePosition: 'start' as const, + newDate: start2018, + expectedRange: [start2018At4PM, null], + expectedNextSelection: 'end' as const, + shouldMergeDateAndTime: true, + referenceDate: start2018At4PM, + }, { range: [start2018, null], rangePosition: 'start' as const, @@ -99,7 +108,16 @@ describe('date-range-manager', () => { expectedNextSelection: 'start' as const, }, ].forEach( - ({ range, rangePosition, newDate, expectedRange, allowRangeFlip, expectedNextSelection }) => { + ({ + range, + rangePosition, + newDate, + expectedRange, + allowRangeFlip, + expectedNextSelection, + shouldMergeDateAndTime, + referenceDate, + }) => { it(`calculateRangeChange should return ${expectedRange} when selecting ${rangePosition} of ${range} with user input ${newDate}`, () => { expect( calculateRangeChange({ @@ -108,6 +126,8 @@ describe('date-range-manager', () => { newDate, rangePosition, allowRangeFlip, + shouldMergeDateAndTime, + referenceDate, }), ).to.deep.equal({ nextSelection: expectedNextSelection, diff --git a/packages/x-date-pickers-pro/src/internals/utils/date-range-manager.ts b/packages/x-date-pickers-pro/src/internals/utils/date-range-manager.ts index 32f5e29d2a16..43eca190c54c 100644 --- a/packages/x-date-pickers-pro/src/internals/utils/date-range-manager.ts +++ b/packages/x-date-pickers-pro/src/internals/utils/date-range-manager.ts @@ -14,6 +14,7 @@ interface CalculateRangeChangeOptions { */ allowRangeFlip?: boolean; shouldMergeDateAndTime?: boolean; + referenceDate?: PickerValidDate; } interface CalculateRangeChangeResponse { @@ -28,6 +29,7 @@ export function calculateRangeChange({ rangePosition, allowRangeFlip = false, shouldMergeDateAndTime = false, + referenceDate, }: CalculateRangeChangeOptions): CalculateRangeChangeResponse { const [start, end] = range; @@ -41,21 +43,26 @@ export function calculateRangeChange({ } } + const newSelectedDate = + referenceDate && selectedDate && shouldMergeDateAndTime + ? mergeDateAndTime(utils, selectedDate, referenceDate) + : selectedDate; + if (rangePosition === 'start') { const truthyResult: CalculateRangeChangeResponse = allowRangeFlip - ? { nextSelection: 'start', newRange: [end!, selectedDate] } - : { nextSelection: 'end', newRange: [selectedDate, null] }; - return Boolean(end) && utils.isAfter(selectedDate!, end!) + ? { nextSelection: 'start', newRange: [end!, newSelectedDate] } + : { nextSelection: 'end', newRange: [newSelectedDate, null] }; + return Boolean(end) && utils.isAfter(newSelectedDate!, end!) ? truthyResult - : { nextSelection: 'end', newRange: [selectedDate, end] }; + : { nextSelection: 'end', newRange: [newSelectedDate, end] }; } const truthyResult: CalculateRangeChangeResponse = allowRangeFlip - ? { nextSelection: 'end', newRange: [selectedDate, start!] } - : { nextSelection: 'end', newRange: [selectedDate, null] }; - return Boolean(start) && utils.isBeforeDay(selectedDate!, start!) + ? { nextSelection: 'end', newRange: [newSelectedDate, start!] } + : { nextSelection: 'end', newRange: [newSelectedDate, null] }; + return Boolean(start) && utils.isBeforeDay(newSelectedDate!, start!) ? truthyResult - : { nextSelection: 'start', newRange: [start, selectedDate] }; + : { nextSelection: 'start', newRange: [start, newSelectedDate] }; } export function calculateRangePreview(options: CalculateRangeChangeOptions): PickerRangeValue {