I am currently using Mui Datepicker library from @mui/x-date-pickers/DatePicker
.
Here's my sample code
<LocalizationProvider dateAdapter={AdapterDateFns}>
<DatePicker
inputFormat="MM/dd/yy"
value={date}
minDate={new Date()}
disablePast
onChange={(newValue) => {
console.log("new value", newValue)
setDate(newValue);
}}
renderInput={(props) => (
<TextField
autoFocus
size="small"
{...props}
inputProps={{
...props.inputProps,
autocomplete: 'off',
placeholder: 'MM/DD/YY',
}}
/>
)}
/>
</LocalizationProvider>
Now, I would like to use MM/dd/yy
as the date format. But when I type in 10/30/99, it returns a date 10/30/1999. I would like it to return 10/30/2099.
It is happening because the library is trying to predict the nearest year to 99 from the current date (reference date).
Is there a way to ensure I only get future dates. So in this case it returns the year 2099 instead of 1999.
I tried setting minDate={new Date()}
and disablePast
, but it didn't work.
codesandbox link here
Thanks in advance.
If I understand correctly, you want to use MM/dd/yy
as the date format, but always get a future date as the result. For example, if you type in 10/30/99
, you want to get 10/30/2099
, not 10/30/1999
.
Unfortunately, the MUI X DatePicker does not have a built-in option to do that. It uses the date-fns
library to parse the date string. This is similar to the shortYearCutoff
option of jQuery DatePicker.
According to date-fns documentation
yy will try to guess the century of two digit year by proximity with referenceDate:
For example:
console.log(parse("11/11/99", "MM/dd/yy", new Date())); // 1999-11-11
console.log(parse("11/11/73", "MM/dd/yy", new Date())); // 1973-11-11
console.log(parse("11/11/72", "MM/dd/yy", new Date())); // 2072-11-11
console.log(parse("11/11/50", "MM/dd/yy", new Date())); // 2050-11-11
console.log(parse("11/11/7", "MM/dd/yy", new Date())); // 2007-11-11
One possible solution is to override parse
method of AdapterDateFns
.
For example:
class FutureDateAdapter extends AdapterDateFns {
constructor(props = {}) {
super(props);
this.parse = (value, formatString) => {
if (value === null) {
return null;
}
const date = new Date();
const newDate = addYears(date, 50);
return parse(value, formatString, newDate);
};
}
}
And then:
<LocalizationProvider dateAdapter={FutureDateAdapter}>
<DatePicker
inputFormat="MM/dd/yy"
value={date}
onChange={setDate}
renderInput={(props) => (
<TextField
autoFocus
size="small"
{...props}
inputProps={{
...props.inputProps,
autoComplete: "off",
placeholder: "MM/DD/YY",
}}
/>
)}
/>
</LocalizationProvider>;
It does not handle the case when the input date is between 01/01/23 and today. In that case, it will return the past date instead of the future date.
If you want to get only the future date, you can use the startOfDay
and compareAsc
methods from date-fns
instead.
For example:
class FutureDateAdapter extends AdapterDateFns {
constructor(props = {}) {
super(props);
this.parse = (value, formatString) => {
if (value === null) {
return null;
}
const newDate = new Date();
const parsedDate = parse(value, formatString, newDate);
const today = startOfDay(newDate);
if (compareAsc(parsedDate, today) === -1) {
return addYears(parsedDate, 100);
}
return parsedDate;
};
}
}
You can see the whole example here.