Skip to content

Commit 11d37fa

Browse files
fix: don't constrain day
1 parent 48bcd5a commit 11d37fa

File tree

3 files changed

+47
-38
lines changed

3 files changed

+47
-38
lines changed

packages/@internationalized/date/src/CalendarDate.ts

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,8 @@ export class CalendarDate {
102102
* Returns a new `CalendarDate` with the given field adjusted by a specified amount.
103103
* When the resulting value reaches the limits of the field, it wraps around.
104104
*/
105-
cycle(field: DateField, amount: number, options?: CycleOptions): CalendarDate {
106-
return cycleDate(this, field, amount, options);
105+
cycle(field: DateField, amount: number, options?: CycleOptions, ignoreDay?: boolean): CalendarDate {
106+
return cycleDate(this, field, amount, options, ignoreDay);
107107
}
108108

109109
/** Converts the date to a native JavaScript Date object, with the time set to midnight in the given time zone. */
@@ -216,10 +216,10 @@ export class CalendarDateTime {
216216
/** The millisecond in the second. */
217217
public readonly millisecond: number;
218218

219-
constructor(year: number, month: number, day: number, hour?: number, minute?: number, second?: number, millisecond?: number);
220-
constructor(era: string, year: number, month: number, day: number, hour?: number, minute?: number, second?: number, millisecond?: number);
221-
constructor(calendar: Calendar, year: number, month: number, day: number, hour?: number, minute?: number, second?: number, millisecond?: number);
222-
constructor(calendar: Calendar, era: string, year: number, month: number, day: number, hour?: number, minute?: number, second?: number, millisecond?: number);
219+
constructor(year: number, month: number, day: number, hour?: number, minute?: number, second?: number, millisecond?: number, ignoreDay?: boolean);
220+
constructor(era: string, year: number, month: number, day: number, hour?: number, minute?: number, second?: number, millisecond?: number, ignoreDay?: boolean);
221+
constructor(calendar: Calendar, year: number, month: number, day: number, hour?: number, minute?: number, second?: number, millisecond?: number, ignoreDay?: boolean);
222+
constructor(calendar: Calendar, era: string, year: number, month: number, day: number, hour?: number, minute?: number, second?: number, millisecond?: number, ignoreDay?: boolean);
223223
constructor(...args: any[]) {
224224
let [calendar, era, year, month, day] = shiftArgs(args);
225225
this.calendar = calendar;
@@ -231,16 +231,17 @@ export class CalendarDateTime {
231231
this.minute = args.shift() || 0;
232232
this.second = args.shift() || 0;
233233
this.millisecond = args.shift() || 0;
234+
const ignoreDay = args.shift() || 0;
234235

235-
constrain(this);
236+
constrain(this, ignoreDay);
236237
}
237238

238239
/** Returns a copy of this date. */
239-
copy(): CalendarDateTime {
240+
copy(ignoreDay?: boolean): CalendarDateTime {
240241
if (this.era) {
241-
return new CalendarDateTime(this.calendar, this.era, this.year, this.month, this.day, this.hour, this.minute, this.second, this.millisecond);
242+
return new CalendarDateTime(this.calendar, this.era, this.year, this.month, this.day, this.hour, this.minute, this.second, this.millisecond, ignoreDay);
242243
} else {
243-
return new CalendarDateTime(this.calendar, this.year, this.month, this.day, this.hour, this.minute, this.second, this.millisecond);
244+
return new CalendarDateTime(this.calendar, this.year, this.month, this.day, this.hour, this.minute, this.second, this.millisecond, ignoreDay);
244245
}
245246
}
246247

@@ -255,8 +256,8 @@ export class CalendarDateTime {
255256
}
256257

257258
/** Returns a new `CalendarDateTime` with the given fields set to the provided values. Other fields will be constrained accordingly. */
258-
set(fields: DateFields & TimeFields): CalendarDateTime {
259-
return set(setTime(this, fields), fields);
259+
set(fields: DateFields & TimeFields, ignoreDay?: boolean): CalendarDateTime {
260+
return set(setTime(this, fields), fields, ignoreDay);
260261
}
261262

262263
/**

packages/@internationalized/date/src/manipulation.ts

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -113,18 +113,22 @@ function balanceDay(date: Mutable<AnyCalendarDate>) {
113113
}
114114
}
115115

116-
function constrainMonthDay(date: Mutable<AnyCalendarDate>) {
116+
function constrainMonthDay(date: Mutable<AnyCalendarDate>, ignoreDay?: boolean) {
117117
date.month = Math.max(1, Math.min(date.calendar.getMonthsInYear(date), date.month));
118-
date.day = Math.max(1, Math.min(date.calendar.getMaxDays(), date.day));
118+
if(ignoreDay) {
119+
date.day = Math.max(1, Math.min(date.calendar.getMaxDays(), date.day));
120+
}else {
121+
date.day = Math.max(1, Math.min(date.calendar.getDaysInMonth(date), date.day));
122+
}
119123
}
120124

121-
export function constrain(date: Mutable<AnyCalendarDate>): void {
125+
export function constrain(date: Mutable<AnyCalendarDate>, ignoreDay?: boolean): void {
122126
if (date.calendar.constrainDate) {
123-
date.calendar.constrainDate(date);
127+
date.calendar.constrainDate(date);
124128
}
125129

126130
date.year = Math.max(1, Math.min(date.calendar.getYearsInEra(date), date.year));
127-
constrainMonthDay(date);
131+
constrainMonthDay(date, ignoreDay);
128132
}
129133

130134
export function invertDuration(duration: DateTimeDuration): DateTimeDuration {
@@ -144,10 +148,10 @@ export function subtract(date: CalendarDate | CalendarDateTime, duration: DateTi
144148
return add(date, invertDuration(duration));
145149
}
146150

147-
export function set(date: CalendarDateTime, fields: DateFields): CalendarDateTime;
148-
export function set(date: CalendarDate, fields: DateFields): CalendarDate;
149-
export function set(date: CalendarDate | CalendarDateTime, fields: DateFields): Mutable<AnyCalendarDate> {
150-
let mutableDate: Mutable<AnyCalendarDate> = date.copy();
151+
export function set(date: CalendarDateTime, fields: DateFields, ignoreDay?: boolean): CalendarDateTime;
152+
export function set(date: CalendarDate, fields: DateFields, ignoreDay?: boolean): CalendarDate;
153+
export function set(date: CalendarDate | CalendarDateTime, fields: DateFields, ignoreDay?: boolean): Mutable<AnyCalendarDate> {
154+
let mutableDate: Mutable<AnyCalendarDate> = date.copy(ignoreDay);
151155

152156
if (fields.era != null) {
153157
mutableDate.era = fields.era;
@@ -165,7 +169,7 @@ export function set(date: CalendarDate | CalendarDateTime, fields: DateFields):
165169
mutableDate.day = fields.day;
166170
}
167171

168-
constrain(mutableDate);
172+
constrain(mutableDate, ignoreDay);
169173
return mutableDate;
170174
}
171175

@@ -243,9 +247,9 @@ export function subtractTime(time: Time, duration: TimeDuration): Time {
243247
return addTime(time, invertDuration(duration));
244248
}
245249

246-
export function cycleDate(value: CalendarDateTime, field: DateField, amount: number, options?: CycleOptions): CalendarDateTime;
247-
export function cycleDate(value: CalendarDate, field: DateField, amount: number, options?: CycleOptions): CalendarDate;
248-
export function cycleDate(value: CalendarDate | CalendarDateTime, field: DateField, amount: number, options?: CycleOptions): Mutable<CalendarDate | CalendarDateTime> {
250+
export function cycleDate(value: CalendarDateTime, field: DateField, amount: number, options?: CycleOptions, ignoreDay?: boolean): CalendarDateTime;
251+
export function cycleDate(value: CalendarDate, field: DateField, amount: number, options?: CycleOptions, ignoreDay?: boolean): CalendarDate;
252+
export function cycleDate(value: CalendarDate | CalendarDateTime, field: DateField, amount: number, options?: CycleOptions, ignoreDay?: boolean): Mutable<CalendarDate | CalendarDateTime> {
249253
let mutable: Mutable<CalendarDate | CalendarDateTime> = value.copy();
250254

251255
switch (field) {
@@ -259,7 +263,7 @@ export function cycleDate(value: CalendarDate | CalendarDateTime, field: DateFie
259263
mutable.era = eras[eraIndex];
260264

261265
// Constrain the year and other fields within the era, so the era doesn't change when we balance below.
262-
constrain(mutable);
266+
constrain(mutable, ignoreDay);
263267
break;
264268
}
265269
case 'year': {
@@ -284,7 +288,11 @@ export function cycleDate(value: CalendarDate | CalendarDateTime, field: DateFie
284288
mutable.month = cycleValue(value.month, amount, 1, value.calendar.getMonthsInYear(value), options?.round);
285289
break;
286290
case 'day':
287-
mutable.day = cycleValue(value.day, amount, 1, value.calendar.getMaxDays(), options?.round);
291+
if(ignoreDay) {
292+
mutable.day = cycleValue(value.day, amount, 1, value.calendar.getMaxDays(), options?.round);
293+
}else {
294+
mutable.day = cycleValue(value.day, amount, 1, value.calendar.getDaysInMonth(value), options?.round);
295+
}
288296
break;
289297
default:
290298
throw new Error('Unsupported field ' + field);
@@ -294,7 +302,7 @@ export function cycleDate(value: CalendarDate | CalendarDateTime, field: DateFie
294302
value.calendar.balanceDate(mutable);
295303
}
296304

297-
constrain(mutable);
305+
constrain(mutable, ignoreDay);
298306
return mutable;
299307
}
300308

packages/@react-stately/datepicker/src/useDateFieldState.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -455,14 +455,14 @@ export function useDateFieldState<T extends DateValue = DateValue>(props: DateFi
455455
let isPM = displayValue.hour >= 12;
456456
let shouldBePM = placeholder.hour >= 12;
457457
if (isPM && !shouldBePM) {
458-
value = displayValue.set({hour: displayValue.hour - 12});
458+
value = displayValue.set({hour: displayValue.hour - 12}, true);
459459
} else if (!isPM && shouldBePM) {
460-
value = displayValue.set({hour: displayValue.hour + 12});
460+
value = displayValue.set({hour: displayValue.hour + 12}, true);
461461
}
462462
} else if (part === 'hour' && 'hour' in displayValue && displayValue.hour >= 12 && validSegments.dayPeriod) {
463-
value = displayValue.set({hour: placeholder['hour'] + 12});
463+
value = displayValue.set({hour: placeholder['hour'] + 12}, true);
464464
} else if (part in displayValue) {
465-
value = displayValue.set({[part]: placeholder[part]});
465+
value = displayValue.set({[part]: placeholder[part]}, true);
466466
}
467467
updatePlaceholder(value);
468468
},
@@ -644,23 +644,23 @@ function addSegment(value: DateValue, part: string, amount: number, options: Int
644644
case 'year':
645645
case 'month':
646646
case 'day':
647-
return value.cycle(part, amount, {round: part === 'year'});
647+
return value.cycle(part, amount, {round: part === 'year'}, true);
648648
}
649649

650650
if ('hour' in value) {
651651
switch (part) {
652652
case 'dayPeriod': {
653653
let hours = value.hour;
654654
let isPM = hours >= 12;
655-
return value.set({hour: isPM ? hours - 12 : hours + 12});
655+
return value.set({hour: isPM ? hours - 12 : hours + 12}, true);
656656
}
657657
case 'hour':
658658
case 'minute':
659659
case 'second':
660660
return value.cycle(part, amount, {
661661
round: part !== 'hour',
662662
hourCycle: options.hour12 ? 12 : 24
663-
});
663+
}, true);
664664
}
665665
}
666666

@@ -673,7 +673,7 @@ function setSegment(value: DateValue, part: string, segmentValue: number | strin
673673
case 'month':
674674
case 'year':
675675
case 'era':
676-
return value.set({[part]: segmentValue});
676+
return value.set({[part]: segmentValue}, true);
677677
}
678678

679679
if ('hour' in value && typeof segmentValue === 'number') {
@@ -685,7 +685,7 @@ function setSegment(value: DateValue, part: string, segmentValue: number | strin
685685
if (isPM === wasPM) {
686686
return value;
687687
}
688-
return value.set({hour: wasPM ? hours - 12 : hours + 12});
688+
return value.set({hour: wasPM ? hours - 12 : hours + 12}, true);
689689
}
690690
case 'hour':
691691
// In 12 hour time, ensure that AM/PM does not change
@@ -702,7 +702,7 @@ function setSegment(value: DateValue, part: string, segmentValue: number | strin
702702
// fallthrough
703703
case 'minute':
704704
case 'second':
705-
return value.set({[part]: segmentValue});
705+
return value.set({[part]: segmentValue}, true);
706706
}
707707
}
708708

0 commit comments

Comments
 (0)