Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
f84a158
fix: Constrain day on blur
boutahlilsoufiane Jun 11, 2025
38ab4fe
Merge branch 'main' of https://github.com/boutahlilsoufiane/react-spe…
boutahlilsoufiane Jun 21, 2025
2611a8e
feat: add tests
boutahlilsoufiane Jul 2, 2025
f130aae
feat: add blur
boutahlilsoufiane Jul 11, 2025
577bcdb
feat: update constrain
boutahlilsoufiane Jul 16, 2025
56c5849
feat: change NumberFormat
boutahlilsoufiane Jul 16, 2025
596af68
feat: fix tests
boutahlilsoufiane Jul 17, 2025
9a30cc2
feat: fix tests
boutahlilsoufiane Jul 18, 2025
56fe492
fix: remove unnecessary changes
boutahlilsoufiane Jul 18, 2025
dd9675b
fix: improve tests
boutahlilsoufiane Jul 18, 2025
ac477ec
fix: improve tests
boutahlilsoufiane Jul 18, 2025
ab552f9
fix: fix tests
boutahlilsoufiane Jul 22, 2025
5d98150
fix: Fix clear timefield
boutahlilsoufiane Jul 24, 2025
53fb4d7
fix: Fix tests
boutahlilsoufiane Jul 24, 2025
4cc6ffc
fix: Fix tests RangeDatePicker
boutahlilsoufiane Jul 26, 2025
4eb5712
fix: Fix increment value
boutahlilsoufiane Jul 27, 2025
c9945d5
fix: Fix DateRnagePickers tests
boutahlilsoufiane Jul 27, 2025
28e3927
fix: Fix test DateField.test.js
boutahlilsoufiane Jul 27, 2025
3fc093f
fix: Fix tests
boutahlilsoufiane Jul 28, 2025
b60fe24
fix: Fix tests
boutahlilsoufiane Jul 28, 2025
6c0645b
fix: Remove unnecessary changes
boutahlilsoufiane Jul 28, 2025
18967fc
fix: Add max days
boutahlilsoufiane Jul 29, 2025
6990d69
Merge branch 'main' of https://github.com/boutahlilsoufiane/react-spe…
boutahlilsoufiane Jul 29, 2025
4701afa
fix: Fix tests
boutahlilsoufiane Aug 1, 2025
8acff74
refactor: remove useRef
boutahlilsoufiane Aug 2, 2025
6a0a839
refactor: use useState
boutahlilsoufiane Aug 3, 2025
4500be8
refactor: don't update placeholder
boutahlilsoufiane Aug 3, 2025
2493f45
refactor: Remove comment
boutahlilsoufiane Aug 3, 2025
1bc224d
refactor: Remove currentValue
boutahlilsoufiane Aug 4, 2025
3fd1d6f
test: Fix linting issues
boutahlilsoufiane Aug 4, 2025
bf0d184
test: Fix linting issues
boutahlilsoufiane Aug 4, 2025
7d281e3
fix: Fix linting issue
boutahlilsoufiane Aug 4, 2025
46c9e71
fix: Fix linting issues
boutahlilsoufiane Aug 4, 2025
296d894
refactor: Add description
boutahlilsoufiane Aug 4, 2025
48bcd5a
fix: revert changes
boutahlilsoufiane Aug 20, 2025
11d37fa
fix: don't constrain day
boutahlilsoufiane Aug 20, 2025
b0f2963
fix: Fix linting issues
boutahlilsoufiane Aug 21, 2025
2d4520e
Merge branch 'main' of https://github.com/boutahlilsoufiane/react-spe…
boutahlilsoufiane Aug 21, 2025
af7884d
fix: Fix linting issues
boutahlilsoufiane Aug 21, 2025
27bed18
fix: Fix linting issues
boutahlilsoufiane Aug 21, 2025
0096396
fix: don't constrain day
boutahlilsoufiane Aug 30, 2025
5f5d411
fix: Fix linting issues
boutahlilsoufiane Aug 30, 2025
cfad64d
fix: fix rule no dup class members
boutahlilsoufiane Aug 30, 2025
984ae81
fix: fix rule no dup class members
boutahlilsoufiane Aug 30, 2025
673361b
Merge branch 'main' into constrain-date
boutahlilsoufiane Aug 30, 2025
47d9cab
Merge branch 'main' into constrain-date
snowystinger Sep 9, 2025
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
87 changes: 48 additions & 39 deletions packages/@internationalized/date/src/CalendarDate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,27 +59,27 @@ export class CalendarDate {
/** The day number within the month. */
public readonly day: number;

constructor(year: number, month: number, day: number);
constructor(era: string, year: number, month: number, day: number);
constructor(calendar: Calendar, year: number, month: number, day: number);
constructor(calendar: Calendar, era: string, year: number, month: number, day: number);
constructor(year: number, month: number, day: number, constrainDay?: boolean);
constructor(era: string, year: number, month: number, day: number, constrainDay?: boolean);
constructor(calendar: Calendar, year: number, month: number, day: number, constrainDay?: boolean);
constructor(calendar: Calendar, era: string, year: number, month: number, day: number, constrainDay?: boolean);
constructor(...args: any[]) {
let [calendar, era, year, month, day] = shiftArgs(args);
let [calendar, era, year, month, day, constrainDay] = shiftArgs(args);
this.calendar = calendar;
this.era = era;
this.year = year;
this.month = month;
this.day = day;

constrain(this);
constrain(this, constrainDay);
}

/** Returns a copy of this date. */
copy(): CalendarDate {
copy(constrainDay?: boolean): CalendarDate {
if (this.era) {
return new CalendarDate(this.calendar, this.era, this.year, this.month, this.day);
return new CalendarDate(this.calendar, this.era, this.year, this.month, this.day, constrainDay);
} else {
return new CalendarDate(this.calendar, this.year, this.month, this.day);
return new CalendarDate(this.calendar, this.year, this.month, this.day, constrainDay);
}
}

Expand All @@ -94,16 +94,16 @@ export class CalendarDate {
}

/** Returns a new `CalendarDate` with the given fields set to the provided values. Other fields will be constrained accordingly. */
set(fields: DateFields): CalendarDate {
return set(this, fields);
set(fields: DateFields, constrainDay?: boolean): CalendarDate {
return set(this, fields, constrainDay);
}

/**
* Returns a new `CalendarDate` with the given field adjusted by a specified amount.
* When the resulting value reaches the limits of the field, it wraps around.
*/
cycle(field: DateField, amount: number, options?: CycleOptions): CalendarDate {
return cycleDate(this, field, amount, options);
cycle(field: DateField, amount: number, options?: CycleOptions, constrainDay?: boolean): CalendarDate {
return cycleDate(this, field, amount, options, constrainDay);
}

/** Converts the date to a native JavaScript Date object, with the time set to midnight in the given time zone. */
Expand Down Expand Up @@ -165,8 +165,8 @@ export class Time {
}

/** Returns a new `Time` with the given fields set to the provided values. Other fields will be constrained accordingly. */
set(fields: TimeFields): Time {
return setTime(this, fields);
set(fields: TimeFields, constrainDay?: boolean): Time {
return setTime(this, fields, constrainDay);
}

/**
Expand Down Expand Up @@ -216,10 +216,10 @@ export class CalendarDateTime {
/** The millisecond in the second. */
public readonly millisecond: number;

constructor(year: number, month: number, day: number, hour?: number, minute?: number, second?: number, millisecond?: number);
constructor(era: string, year: number, month: number, day: number, hour?: number, minute?: number, second?: number, millisecond?: number);
constructor(calendar: Calendar, year: number, month: number, day: number, hour?: number, minute?: number, second?: number, millisecond?: number);
constructor(calendar: Calendar, era: string, year: number, month: number, day: number, hour?: number, minute?: number, second?: number, millisecond?: number);
constructor(year: number, month: number, day: number, hour?: number, minute?: number, second?: number, millisecond?: number, constrainDay?: boolean);
constructor(era: string, year: number, month: number, day: number, hour?: number, minute?: number, second?: number, millisecond?: number, constrainDay?: boolean);
constructor(calendar: Calendar, year: number, month: number, day: number, hour?: number, minute?: number, second?: number, millisecond?: number, constrainDay?: boolean);
constructor(calendar: Calendar, era: string, year: number, month: number, day: number, hour?: number, minute?: number, second?: number, millisecond?: number, constrainDay?: boolean);
constructor(...args: any[]) {
let [calendar, era, year, month, day] = shiftArgs(args);
this.calendar = calendar;
Expand All @@ -231,16 +231,17 @@ export class CalendarDateTime {
this.minute = args.shift() || 0;
this.second = args.shift() || 0;
this.millisecond = args.shift() || 0;
const constrainDay = args.shift() || 0;

constrain(this);
constrain(this, constrainDay);
}

/** Returns a copy of this date. */
copy(): CalendarDateTime {
copy(constrainDay?: boolean): CalendarDateTime {
if (this.era) {
return new CalendarDateTime(this.calendar, this.era, this.year, this.month, this.day, this.hour, this.minute, this.second, this.millisecond);
return new CalendarDateTime(this.calendar, this.era, this.year, this.month, this.day, this.hour, this.minute, this.second, this.millisecond, constrainDay);
} else {
return new CalendarDateTime(this.calendar, this.year, this.month, this.day, this.hour, this.minute, this.second, this.millisecond);
return new CalendarDateTime(this.calendar, this.year, this.month, this.day, this.hour, this.minute, this.second, this.millisecond, constrainDay);
}
}

Expand All @@ -255,21 +256,21 @@ export class CalendarDateTime {
}

/** Returns a new `CalendarDateTime` with the given fields set to the provided values. Other fields will be constrained accordingly. */
set(fields: DateFields & TimeFields): CalendarDateTime {
return set(setTime(this, fields), fields);
set(fields: DateFields & TimeFields, constrainDay?: boolean): CalendarDateTime {
return set(setTime(this, fields), fields, constrainDay);
}

/**
* Returns a new `CalendarDateTime` with the given field adjusted by a specified amount.
* When the resulting value reaches the limits of the field, it wraps around.
*/
cycle(field: DateField | TimeField, amount: number, options?: CycleTimeOptions): CalendarDateTime {
cycle(field: DateField | TimeField, amount: number, options?: CycleTimeOptions, constrainDay?: boolean): CalendarDateTime {
switch (field) {
case 'era':
case 'year':
case 'month':
case 'day':
return cycleDate(this, field, amount, options);
return cycleDate(this, field, amount, options, constrainDay);
default:
return cycleTime(this, field, amount, options);
}
Expand Down Expand Up @@ -328,10 +329,10 @@ export class ZonedDateTime {
/** The UTC offset for this time, in milliseconds. */
public readonly offset: number;

constructor(year: number, month: number, day: number, timeZone: string, offset: number, hour?: number, minute?: number, second?: number, millisecond?: number);
constructor(era: string, year: number, month: number, day: number, timeZone: string, offset: number, hour?: number, minute?: number, second?: number, millisecond?: number);
constructor(calendar: Calendar, year: number, month: number, day: number, timeZone: string, offset: number, hour?: number, minute?: number, second?: number, millisecond?: number);
constructor(calendar: Calendar, era: string, year: number, month: number, day: number, timeZone: string, offset: number, hour?: number, minute?: number, second?: number, millisecond?: number);
constructor(year: number, month: number, day: number, timeZone: string, offset: number, hour?: number, minute?: number, second?: number, millisecond?: number, constrainDay?: boolean);
constructor(era: string, year: number, month: number, day: number, timeZone: string, offset: number, hour?: number, minute?: number, second?: number, millisecond?: number, constrainDay?: boolean);
constructor(calendar: Calendar, year: number, month: number, day: number, timeZone: string, offset: number, hour?: number, minute?: number, second?: number, millisecond?: number, constrainDay?: boolean);
constructor(calendar: Calendar, era: string, year: number, month: number, day: number, timeZone: string, offset: number, hour?: number, minute?: number, second?: number, millisecond?: number, constrainDay?: boolean);
constructor(...args: any[]) {
let [calendar, era, year, month, day] = shiftArgs(args);
let timeZone = args.shift();
Expand All @@ -347,16 +348,17 @@ export class ZonedDateTime {
this.minute = args.shift() || 0;
this.second = args.shift() || 0;
this.millisecond = args.shift() || 0;
const constrainDay = args.shift() || 0;

constrain(this);
constrain(this, constrainDay);
}

/** Returns a copy of this date. */
copy(): ZonedDateTime {
copy(constrainDay?: boolean): ZonedDateTime {
if (this.era) {
return new ZonedDateTime(this.calendar, this.era, this.year, this.month, this.day, this.timeZone, this.offset, this.hour, this.minute, this.second, this.millisecond);
return new ZonedDateTime(this.calendar, this.era, this.year, this.month, this.day, this.timeZone, this.offset, this.hour, this.minute, this.second, this.millisecond, constrainDay);
} else {
return new ZonedDateTime(this.calendar, this.year, this.month, this.day, this.timeZone, this.offset, this.hour, this.minute, this.second, this.millisecond);
return new ZonedDateTime(this.calendar, this.year, this.month, this.day, this.timeZone, this.offset, this.hour, this.minute, this.second, this.millisecond, constrainDay);
}
}

Expand All @@ -371,16 +373,23 @@ export class ZonedDateTime {
}

/** Returns a new `ZonedDateTime` with the given fields set to the provided values. Other fields will be constrained accordingly. */
set(fields: DateFields & TimeFields, disambiguation?: Disambiguation): ZonedDateTime {
return setZoned(this, fields, disambiguation);
set(fields: DateFields & TimeFields, value?: Disambiguation | boolean): ZonedDateTime {
let disambiguation, constrainDay = false;
if (value && typeof value === 'string') {
disambiguation = value;
} else if (value && typeof value === 'boolean') {
constrainDay = value;
}
return setZoned(this, fields, disambiguation, constrainDay);
}


/**
* Returns a new `ZonedDateTime` with the given field adjusted by a specified amount.
* When the resulting value reaches the limits of the field, it wraps around.
*/
cycle(field: DateField | TimeField, amount: number, options?: CycleTimeOptions): ZonedDateTime {
return cycleZoned(this, field, amount, options);
cycle(field: DateField | TimeField, amount: number, options?: CycleTimeOptions, constrainDay?: boolean): ZonedDateTime {
return cycleZoned(this, field, amount, options, constrainDay);
}

/** Converts the date to a native JavaScript Date object. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ export class BuddhistCalendar extends GregorianCalendar {
getDaysInMonth(date: AnyCalendarDate): number {
return super.getDaysInMonth(toGregorian(date));
}

balanceDate(): void {}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ export class EthiopicCalendar implements Calendar {
return getDaysInMonth(date.year, date.month);
}

getMaxDays(): number {
return 30;
}

getMonthsInYear(): number {
return 13;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ export class GregorianCalendar implements Calendar {
return 12;
}

getMaxDays(): number {
return 31;
}

getDaysInYear(date: AnyCalendarDate): number {
return isLeapYear(date.year) ? 366 : 365;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,10 @@ export class HebrewCalendar implements Calendar {
return getDaysInMonth(date.year, date.month);
}

getMaxDays(): number {
return 30;
}

getMonthsInYear(date: AnyCalendarDate): number {
return isLeapYear(date.year) ? 13 : 12;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ export class IslamicCivilCalendar implements Calendar {
return length;
}

getMaxDays(): number {
return 30;
}

getMonthsInYear(): number {
return 12;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ export class PersianCalendar implements Calendar {
return isLeapYear ? 30 : 29;
}

getMaxDays(): number {
return 31;
}

getEras(): string[] {
return ['AP'];
}
Expand Down
4 changes: 2 additions & 2 deletions packages/@internationalized/date/src/conversion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ export function toTime(dateTime: CalendarDateTime | ZonedDateTime): Time {
}

/** Converts a date from one calendar system to another. */
export function toCalendar<T extends AnyCalendarDate>(date: T, calendar: Calendar): T {
export function toCalendar<T extends AnyCalendarDate>(date: T, calendar: Calendar, constrainDay?: boolean): T {
if (isEqualCalendar(date.calendar, calendar)) {
return date;
}
Expand All @@ -271,7 +271,7 @@ export function toCalendar<T extends AnyCalendarDate>(date: T, calendar: Calenda
copy.year = calendarDate.year;
copy.month = calendarDate.month;
copy.day = calendarDate.day;
constrain(copy);
constrain(copy, constrainDay);
return copy;
}

Expand Down
Loading