使用Dayjs适配器的MUI X DatePicker键盘输入非2565年佛历日期时始终提示无效日期
解决MUI X DatePicker佛历键盘输入无效日期问题
我之前做佛历适配的时候也踩过一模一样的坑!你的代码里已经配置了Dayjs的佛历插件和泰语本地化,但MUI的默认AdapterDayjs并没有内置佛历年份的解析逻辑——弹窗选择日期正常是因为组件内部用的是Dayjs对象传递,而键盘输入的是纯文本格式的佛历日期,适配器不知道要把BBBB格式的年份减543转成公历,所以非默认年份就会解析失败,返回“Invalid date”。
下面是具体的修复方案:
1. 自定义Dayjs适配器,重写解析逻辑
我们需要扩展AdapterDayjs,给它加上佛历转公历的解析规则。创建一个新文件比如AdapterDayjsBuddhist.js:
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; import dayjs from "dayjs"; export class AdapterDayjsBuddhist extends AdapterDayjs { parse(value, format) { // 仅处理包含佛历年份格式(BBBB)的输入 if (value && format.includes("BBBB")) { const dateParts = value.split("/"); // 确保输入是DD/MM/BBBB格式 if (dateParts.length === 3) { const [day, month, beYear] = dateParts; // 佛历转公历:减543 const adYear = parseInt(beYear, 10) - 543; // 组装成公历日期字符串后交给父类解析 const adDateStr = `${day}/${month}/${adYear}`; return super.parse(adDateStr, "DD/MM/YYYY"); } } // 其他情况用默认解析逻辑 return super.parse(value, format); } }
2. 修改组件代码,使用自定义适配器
把原来的AdapterDayjs替换成我们刚写的自定义适配器,同时还要调整日期范围的配置:
import { useState } from "react"; import { LocalizationProvider } from "@mui/x-date-pickers"; import { DatePicker } from "@mui/x-date-pickers/DatePicker"; import { TextField } from "@mui/material"; import dayjs from "dayjs"; import buddhistEra from "dayjs/plugin/buddhistEra"; import "dayjs/locale/th"; // 引入自定义佛历适配器 import { AdapterDayjsBuddhist } from "./AdapterDayjsBuddhist"; dayjs.locale("th"); dayjs.extend(buddhistEra); const dateformats = { year: "BBBB", monthAndYear: "MMMM BBBB", keyboardDate: "DD/MM/BBBB" }; export default function App() { const [protectionPrdFrom, setProtectionPrdFrom] = useState(dayjs()); return ( <div className="App"> {/* 用format方法输出佛历格式的日期,替代toString */} <h3>{protectionPrdFrom ? protectionPrdFrom.format("DD/MM/BBBB") : ""}</h3> <LocalizationProvider dateFormats={dateformats} dateAdapter={AdapterDayjsBuddhist} // 替换为自定义适配器 adapterLocale="th" > <DatePicker showToolbar {/* 日期范围要转成佛历对应的日期:公历日期加543年 */} maxDate={dayjs(new Date(3000, 11, 31)).add(543, "year")} minDate={dayjs(new Date(1990, 0, 1)).add(543, "year")} inputFormat="DD/MM/BBBB" views={["year", "month", "day"]} value={protectionPrdFrom} onChange={(date, keyboardDate) => { setProtectionPrdFrom(date); }} renderInput={(params) => ( <TextField {...params} size="small" fullWidth /> )} /> </LocalizationProvider> </div> ); }
几个关键细节要注意:
- 日期范围转换:原来的
maxDate和minDate是公历日期,必须用add(543, "year")转换成佛历对应的日期,不然组件的范围校验会出错。 - 日期显示格式:用
format("DD/MM/BBBB")替代默认的toString(),确保页面上显示的是标准佛历格式。 - 适配器的针对性处理:我们只在输入格式包含
BBBB时才做佛历转换,其他格式保持默认逻辑,避免影响其他场景的日期解析。
这样修改后,无论是弹窗选择还是键盘输入任意佛历年份,组件都能正确解析并返回有效的Dayjs对象啦~
内容的提问来源于stack exchange,提问作者Izle
相关产品推荐
相关产品推荐

