Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions core/src/components/datetime/test/manipulation.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,38 @@ describe('validateParts()', () => {
})
).toEqual({ month: 1, day: 1, year: 2022, hour: 9, minute: 30 });
});
it('should not mutate the max parts when the day does not exist in the new month', () => {
// Selecting March 31 and then April on the month wheel produces April 31.
const maxParts = { month: 4, day: 20, year: 2024, hour: 23, minute: 59 };

expect(validateParts({ month: 4, day: 31, year: 2024, hour: 23, minute: 59 }, undefined, maxParts)).toEqual({
month: 4,
day: 20,
year: 2024,
hour: 23,
minute: 59,
});
expect(maxParts).toEqual({ month: 4, day: 20, year: 2024, hour: 23, minute: 59 });
});
it('should not mutate the min parts when the day does not exist in the new month', () => {
const minParts = { month: 3, day: 1, year: 2024, hour: 0, minute: 0 };

const result = validateParts({ month: 2, day: 31, year: 2024, hour: 0, minute: 0 }, minParts);
expect(result).toEqual({ month: 3, day: 1, year: 2024, hour: 0, minute: 0 });
expect(minParts).toEqual({ month: 3, day: 1, year: 2024, hour: 0, minute: 0 });
});
it('should move the time back in bounds when the fixed day lands on the max day', () => {
// February 31 becomes February 29, which is the max day, so the max time applies.
expect(
validateParts({ month: 2, day: 31, year: 2024, hour: 23, minute: 0 }, undefined, {
month: 2,
day: 29,
year: 2024,
hour: 20,
minute: 0,
})
).toEqual({ month: 2, day: 29, year: 2024, hour: 20, minute: 0 });
});
});

describe('getClosestValidDate()', () => {
Expand Down
16 changes: 13 additions & 3 deletions core/src/components/datetime/utils/manipulation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ export const validateParts = (
maxParts?: DatetimeParts
): DatetimeParts => {
const { month, day, year } = parts;
const partsCopy = clampDate({ ...parts }, minParts, maxParts);
const dayInMonth = { ...parts };

const numDays = getNumDaysInMonth(month, year);

Expand All @@ -351,11 +351,21 @@ export const validateParts = (
* is greater than the day we want
* to set, update the DatetimeParts
* day field to be the max days.
* This is done before clamping so that
* the fixed day is also checked against
* the min/max bounds.
*/
if (day !== null && numDays < day) {
partsCopy.day = numDays;
dayInMonth.day = numDays;
}

/**
* clampDate can return the minParts or maxParts
* object itself, so copy the result to avoid
* changing the bounds when updating the time below.
*/
const partsCopy = { ...clampDate(dayInMonth, minParts, maxParts) };

/**
* If value is same day as min day,
* make sure the time value is in bounds.
Expand Down Expand Up @@ -391,7 +401,7 @@ export const validateParts = (
* If value is same day as max day,
* make sure the time value is in bounds.
*/
if (maxParts !== undefined && isSameDay(parts, maxParts)) {
if (maxParts !== undefined && isSameDay(partsCopy, maxParts)) {
/**
* If the hour is out of bounds,
* update both the hour and minute.
Expand Down
Loading