Skip to content
Merged
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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]
### Fixed
- #### Calendar & Date picker
- Incorrect date rollover for in certain scenarios [#1710](https://github.com/IgniteUI/igniteui-webcomponents/issues/1710)

## [6.0.1] - 2025-05-28
### Added
- #### Radio group
Expand Down
15 changes: 5 additions & 10 deletions src/components/calendar/model.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,20 +127,15 @@ describe('Calendar day model', () => {
const nonLeapFebruary = leapFebruary.set({ year: 2023 });
let { year, month, date } = nonLeapFebruary;

// Shift to first day of next month -> 2024/03/01
expect([year, month, date]).to.eql([2023, 2, 1]);

const lastDayOfJuly = new CalendarDay({
year: 2024,
month: 6,
date: 31,
});
// Shift to last day of the current month -> 2023-02-28
expect([year, month, date]).to.eql([2023, 1, 28]);

const lastDayOfJuly = new CalendarDay({ year: 2024, month: 6, date: 31 });
const lastDayOfApril = lastDayOfJuly.set({ month: 3 });
({ year, month, date } = lastDayOfApril);

// April does not have 31 days so shift to first day of May
expect([year, month, date]).to.eql([2024, 4, 1]);
// April does not have 31 days so clamp to the last day of April
expect([year, month, date]).to.eql([2024, 3, 30]);
});
});

Expand Down
22 changes: 16 additions & 6 deletions src/components/calendar/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ function checkRollover(original: CalendarDay, modified: CalendarDay) {

/* blazorSuppress */
export class CalendarDay {
private _date!: Date;
private readonly _date: Date;

/** Constructs and returns the current day. */
public static get today() {
Expand Down Expand Up @@ -77,11 +77,21 @@ export class CalendarDay {
* Returns a new instance with values replaced.
*/
public set(args: Partial<CalendarDayParams>) {
return new CalendarDay({
year: args.year ?? this.year,
month: args.month ?? this.month,
date: args.date ?? this.date,
});
const year = args.year ?? this.year;
const month = args.month ?? this.month;
const date = args.date ?? this.date;

const temp = new Date(year, month, date);

if (date > 0 && temp.getMonth() !== month) {
return new CalendarDay({
year,
month,
date: new Date(year, month + 1, 0).getDate(),
});
}

return new CalendarDay({ year, month, date });
}

public add(unit: DayInterval, value: number) {
Expand Down
43 changes: 42 additions & 1 deletion src/components/date-picker/date-picker.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { elementUpdated, expect, fixture, html } from '@open-wc/testing';
import { spy } from 'sinon';
import IgcCalendarComponent from '../calendar/calendar.js';
import { getCalendarDOM, getDayViewDOM } from '../calendar/helpers.spec.js';
import {
getCalendarDOM,
getDOMDate,
getDayViewDOM,
} from '../calendar/helpers.spec.js';
import { CalendarDay, toCalendarDay } from '../calendar/model.js';
import { DateRangeType } from '../calendar/types.js';
import {
Expand Down Expand Up @@ -897,6 +901,43 @@ describe('Date picker', () => {
expect(picker.open).to.be.true;
});

it('issue 1710', async () => {
const activeDate = new CalendarDay({ year: 2025, month: 4, date: 29 });
const targetDate = activeDate.add('day', 2);

// Select the last date of May
picker.activeDate = activeDate.native;
await picker.show();

const calendarDOM = getCalendarDOM(calendar);
const lastOfMay = getDOMDate(targetDate, calendarDOM.views.days);

simulateClick(lastOfMay);
await elementUpdated(picker);

expect(checkDatesEqual(picker.value!, targetDate));

// Open the picker and switch to months view
await picker.show();

simulateClick(calendarDOM.navigation.months);
await elementUpdated(picker);

const monthElements = Array.from(
calendarDOM.views.months.renderRoot.querySelectorAll<HTMLElement>(
'[role="gridcell"]'
)
);

const monthNames = new Set(monthElements.map((each) => each.innerText));
const selectedMonths = monthElements.filter((each) =>
each.matches('[aria-selected="true"]')
);

expect(monthNames).lengthOf(12);
expect(selectedMonths).lengthOf(1);
});

describe('Readonly state', () => {
describe('Dropdown mode', () => {
beforeEach(async () => {
Expand Down