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

如何在FullCalendar中按希伯来历月份自定义月网格视图?

希伯来历月份的FullCalendar自定义视图实现

需求背景

已通过dayCellContent结合Bootstrap在FullCalendar月网格单元格中展示希伯来日期,现需实现按希伯来历月份(如提斯利月Tishrei、赫舍梵月Cheshvan等)划分的月网格视图。

已实现的希伯来日期显示代码

// 表示希伯来历日的希伯来字母数组
const hebDateLetters = ['א', 'ב', 'ג', 'ד', 'ה', 'ו', 'ז', 'ח', 'ט', 'י', 'יא', 'יב', 'יג', 'יד', 'טו', 'טז', 'יז', 'יח', 'יט', 'כ', 'כא', 'כב', 'כג', 'כד', 'כה', 'כו', 'כז', 'כח', 'כט', 'ל']; 

// ...

dayCellContent: (info) => {
        var hebDate = new Intl.DateTimeFormat('he-IL-u-ca-hebrew', {day: 'numeric'}).format(info.date);
        var hebMonth = new Intl.DateTimeFormat('he-IL-u-ca-hebrew', {month: 'long'}).format(info.date);

        // 容器元素
        const container = document.createElement("div");
        container.setAttribute("class", "container p-1"); 

        // 第一行:希伯来日期
        const elRow1 = document.createElement("div");
        elRow1.setAttribute("class", 'row m-0 w-100');
        const elCol1 = document.createElement("div");
        elCol1.setAttribute("class", 'col p-0');
        // 每月第一天显示希伯来月份名称+日期,其余仅显示日期
        elCol1.innerText = hebDate !=1 ? hebDateLetters[hebDate-1] : hebDateLetters[hebDate-1] + " " + hebMonth; 
        elRow1.appendChild(elCol1);

        // 第二行:公历日期
        const elRow2 = document.createElement("div");
        elRow2.setAttribute("class", 'row m-0 w-100');
        const elCol2 = document.createElement("div");
        elCol2.setAttribute("class", 'col p-0 c-date');
        elCol2.innerText = info.date.getDate();
        elRow2.appendChild(elCol2);

        container.appendChild(elRow1);
        container.appendChild(elRow2);
        return {html: container.outerHTML};
      }

当前实现效果

当前日历效果

自定义希伯来历月份视图实现方案

核心思路

FullCalendar默认基于公历,要实现希伯来历月份视图,需自定义视图的日期范围逻辑,计算希伯来历每个月份的准确起止日期,再通过视图配置强制渲染该区间的日期。

具体实现代码

1. 希伯来历月份起止日期计算函数

// 获取希伯来历指定月份的起止日期(希伯来历月份从0开始,0=提斯利月Tishrei)
function getHebrewMonthRange(year, month) {
  // 创建希伯来历基准日期
  const hebrewDate = new Date(Date.UTC(year, 0, 1));
  hebrewDate.setUTCFullYear(year, month, 1);
  
  // 获取当月第一天
  const firstDay = new Date(hebrewDate);
  // 获取下个月第一天,减1天得到当月最后一天(解决希伯来历月份天数不固定问题)
  const nextMonth = new Date(firstDay);
  nextMonth.setUTCMonth(nextMonth.getUTCMonth() + 1);
  const lastDay = new Date(nextMonth);
  lastDay.setUTCDate(lastDay.getUTCDate() - 1);
  
  return { start: firstDay, end: lastDay };
}

2. FullCalendar自定义视图配置

document.addEventListener('DOMContentLoaded', function() {
  const calendarEl = document.getElementById('calendar');

  const calendar = new FullCalendar.Calendar(calendarEl, {
    initialView: 'hebrewMonth',
    views: {
      hebrewMonth: {
        type: 'dayGridMonth',
        duration: { months: 1 },
        // 视图日期范围修正逻辑
        datesSet: function(info) {
          // 将当前视图的公历日期转换为希伯来历的年、月
          const hebrewCurrent = new Intl.DateTimeFormat('he-IL-u-ca-hebrew', {
            year: 'numeric',
            month: 'numeric',
            timeZone: 'UTC'
          }).formatToParts(info.currentStart);
          
          const hebrewYear = parseInt(hebrewCurrent.find(part => part.type === 'year').value);
          const hebrewMonth = parseInt(hebrewCurrent.find(part => part.type === 'month').value) - 1; // 转为0索引
          
          // 获取希伯来历当月的准确起止日期
          const { start, end } = getHebrewMonthRange(hebrewYear, hebrewMonth);
          
          // 若当前视图日期范围不符,自动跳转到希伯来历当月
          if (info.currentStart.getTime() !== start.getTime()) {
            calendar.gotoDate(start);
          }
        },
        // 自定义视图标题:显示希伯来历月份+年份
        titleFormat: function(date) {
          return new Intl.DateTimeFormat('he-IL-u-ca-hebrew', {
            year: 'numeric',
            month: 'long',
            timeZone: 'UTC'
          }).format(date.start);
        }
      }
    },
    // 优化希伯来日期显示:区分当前希伯来历月份与其他月份日期
    dayCellContent: (info) => {
      const hebDateParts = new Intl.DateTimeFormat('he-IL-u-ca-hebrew', {
        day: 'numeric',
        month: 'numeric',
        timeZone: 'UTC'
      }).formatToParts(info.date);
      
      const hebDay = hebDateParts.find(part => part.type === 'day').value;
      const hebMonth = hebDateParts.find(part => part.type === 'month').value;
      // 获取当前视图对应的希伯来历月份
      const currentHebrewMonth = new Intl.DateTimeFormat('he-IL-u-ca-hebrew', {
        month: 'numeric',
        timeZone: 'UTC'
      }).format(calendar.view.currentStart);
      
      const hebDateLetters = ['א', 'ב', 'ג', 'ד', 'ה', 'ו', 'ז', 'ח', 'ט', 'י', 'יא', 'יב', 'יג', 'יד', 'טו', 'טז', 'יז', 'יח', 'יט', 'כ', 'כא', 'כב', 'כג', 'כד', 'כה', 'כו', 'כז', 'כח', 'כט', 'ל'];
      const hebMonthName = new Intl.DateTimeFormat('he-IL-u-ca-hebrew', {month: 'long', timeZone: 'UTC'}).format(info.date);
      
      const container = document.createElement("div");
      container.setAttribute("class", "container p-1");
      
      const elRow1 = document.createElement("div");
      elRow1.setAttribute("class", 'row m-0 w-100');
      const elCol1 = document.createElement("div");
      elCol1.setAttribute("class", 'col p-0');
      
      // 当前希伯来历月份正常显示,其他月份日期灰化
      if (hebMonth === currentHebrewMonth) {
        elCol1.innerText = hebDay != 1 ? hebDateLetters[hebDay - 1] : hebDateLetters[hebDay - 1] + " " + hebMonthName;
      } else {
        elCol1.innerText = hebDateLetters[hebDay - 1];
        elCol1.style.opacity = 0.5;
      }
      
      elRow1.appendChild(elCol1);
      
      const elRow2 = document.createElement("div");
      elRow2.setAttribute("class", 'row m-0 w-100');
      const elCol2 = document.createElement("div");
      elCol2.setAttribute("class", 'col p-0 c-date');
      elCol2.innerText = info.date.getDate();
      if (hebMonth !== currentHebrewMonth) {
        elCol2.style.opacity = 0.5;
      }
      
      elRow2.appendChild(elCol2);
      container.appendChild(elRow1);
      container.appendChild(elRow2);
      
      return {html: container.outerHTML};
    },
    // 导航工具栏配置
    headerToolbar: {
      left: 'prev,next today',
      center: 'title',
      right: 'hebrewMonth'
    }
  });

  calendar.render();
});

关键说明

  • getHebrewMonthRange函数解决了希伯来历月份天数不固定的问题,能准确计算每个希伯来历月份的起止日期。
  • 自定义视图hebrewMonth通过datesSet回调修正视图的日期范围,确保始终显示完整的希伯来历月份。
  • 重写titleFormat替换默认公历标题,显示希伯来历的月份和年份。
  • 在dayCellContent中区分当前希伯来历月份与其他月份的日期,优化视觉体验。

内容的提问来源于stack exchange,提问作者TKG

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 01:45:17