Skip to content

Commit f5c95b6

Browse files
committed
feat: support parsing of date range strings
1 parent 041a96b commit f5c95b6

File tree

2 files changed

+73
-27
lines changed

2 files changed

+73
-27
lines changed

src/date_utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -794,7 +794,7 @@ export function isDayDisabled(
794794
if (excludeDate instanceof Date) {
795795
return isSameDay(day, excludeDate);
796796
} else {
797-
return isSameDay(day, excludeDate.date ?? new Date());
797+
return isSameDay(day, excludeDate.date);
798798
}
799799
})) ||
800800
(excludeDateIntervals &&

src/index.tsx

Lines changed: 72 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,7 @@ export default class DatePicker extends Component<
565565
}
566566
};
567567

568+
// handleChange is called when user types in the textbox
568569
handleChange = (
569570
...allArgs: Parameters<Required<DatePickerProps>["onChangeRaw"]>
570571
) => {
@@ -585,36 +586,77 @@ export default class DatePicker extends Component<
585586
event?.target instanceof HTMLInputElement ? event.target.value : null,
586587
lastPreSelectChange: PRESELECT_CHANGE_VIA_INPUT,
587588
});
589+
588590
const {
589591
dateFormat = DatePicker.defaultProps.dateFormat,
590592
strictParsing = DatePicker.defaultProps.strictParsing,
593+
selectsRange,
594+
startDate,
595+
endDate,
591596
} = this.props;
592-
let date = parseDate(
593-
event?.target instanceof HTMLInputElement ? event.target.value : "",
594-
dateFormat,
595-
this.props.locale,
596-
strictParsing,
597-
this.props.minDate,
598-
);
599-
// Use date from `selected` prop when manipulating only time for input value
600-
if (
601-
this.props.showTimeSelectOnly &&
602-
this.props.selected &&
603-
date &&
604-
!isSameDay(date, this.props.selected)
605-
) {
606-
date = set(this.props.selected, {
607-
hours: getHours(date),
608-
minutes: getMinutes(date),
609-
seconds: getSeconds(date),
610-
});
611-
}
612-
if (
613-
date ||
614-
!(event?.target instanceof HTMLInputElement) ||
615-
!event?.target.value
616-
) {
617-
this.setSelected(date, event, true);
597+
598+
const value =
599+
event?.target instanceof HTMLInputElement ? event.target.value : "";
600+
601+
if (selectsRange) {
602+
const [valueStart, valueEnd] = value
603+
.split("-", 2)
604+
.map((val) => val.trim());
605+
const startDateNew = parseDate(
606+
valueStart ?? "",
607+
dateFormat,
608+
this.props.locale,
609+
strictParsing,
610+
);
611+
const endDateNew = parseDate(
612+
valueEnd ?? "",
613+
dateFormat,
614+
this.props.locale,
615+
strictParsing,
616+
);
617+
const startChanged = startDate?.getTime() !== startDateNew?.getTime();
618+
const endChanged = endDate?.getTime() !== endDateNew?.getTime();
619+
620+
if (!startChanged && !endChanged) {
621+
return;
622+
}
623+
624+
if (startDateNew && isDayDisabled(startDateNew, this.props)) {
625+
return;
626+
}
627+
if (endDateNew && isDayDisabled(endDateNew, this.props)) {
628+
return;
629+
}
630+
631+
this.props.onChange?.([startDateNew, endDateNew], event);
632+
} else {
633+
// not selectsRange
634+
let date = parseDate(
635+
value,
636+
dateFormat,
637+
this.props.locale,
638+
strictParsing,
639+
this.props.minDate,
640+
);
641+
642+
// Use date from `selected` prop when manipulating only time for input value
643+
if (
644+
this.props.showTimeSelectOnly &&
645+
this.props.selected &&
646+
date &&
647+
!isSameDay(date, this.props.selected)
648+
) {
649+
date = set(this.props.selected, {
650+
hours: getHours(date),
651+
minutes: getMinutes(date),
652+
seconds: getSeconds(date),
653+
});
654+
}
655+
656+
// Update selection if either (1) date was successfully parsed, or (2) input field is empty
657+
if (date || !value) {
658+
this.setSelected(date, event, true);
659+
}
618660
}
619661
};
620662

@@ -654,6 +696,7 @@ export default class DatePicker extends Component<
654696
}
655697
};
656698

699+
// setSelected is called either from handleChange (user typed date into textbox and it was parsed) or handleSelect (user selected date from calendar using mouse or keyboard)
657700
setSelected = (
658701
date: Date | null,
659702
event?: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>,
@@ -662,6 +705,7 @@ export default class DatePicker extends Component<
662705
) => {
663706
let changedDate = date;
664707

708+
// Early return if selected year/month/day is disabled
665709
if (this.props.showYearPicker) {
666710
if (
667711
changedDate !== null &&
@@ -697,6 +741,7 @@ export default class DatePicker extends Component<
697741
selectsMultiple
698742
) {
699743
if (changedDate !== null) {
744+
// Preserve previously selected time if only date is currently being changed
700745
if (
701746
this.props.selected &&
702747
(!keepInput ||
@@ -734,6 +779,7 @@ export default class DatePicker extends Component<
734779
this.setState({ monthSelectedIn: monthSelectedIn });
735780
}
736781
}
782+
737783
if (selectsRange) {
738784
const noRanges = !startDate && !endDate;
739785
const hasStartRange = startDate && !endDate;

0 commit comments

Comments
 (0)