如何在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
相关产品推荐
相关产品推荐

