You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 17:37:40