FullCalendar自定义时间格式:从12小时制到农历显示的实现

FullCalendar自定义时间格式:从12小时制到农历显示的实现

【免费下载链接】fullcalendar Full-sized drag & drop event calendar in JavaScript 【免费下载链接】fullcalendar 项目地址: https://gitcode.com/gh_mirrors/fu/fullcalendar

引言:时间格式的痛点与解决方案

在开发日程管理应用时,你是否曾遇到过时间显示不符合用户习惯的问题?例如,国际用户需要12小时制带AM/PM标识,国内用户可能需要农历显示,而企业用户则可能需要精确到秒的时间格式。FullCalendar作为一款功能强大的JavaScript日程库,提供了灵活的时间格式化机制,但许多开发者在面对复杂需求时仍感到困惑。

本文将系统讲解FullCalendar的时间格式化体系,从基础的12/24小时制切换,到高级的农历显示,帮助你掌握从简单配置到深度定制的全流程。读完本文后,你将能够:

  • 熟练配置内置时间格式选项
  • 自定义事件时间、槽位标签和列标题的显示格式
  • 集成第三方库实现农历等复杂历法显示
  • 解决时区转换和本地化显示的常见问题

FullCalendar时间格式化基础

核心格式化选项

FullCalendar提供了多个关键选项用于控制时间显示,这些选项在packages/core/src/options.ts中定义:

// 核心时间格式化选项
{
  slotLabelFormat: identity as Identity<FormatterInput | FormatterInput[]>,
  eventTimeFormat: createFormatter,
  columnHeaderFormat: { weekday: 'short', month: 'numeric', day: 'numeric' }
}

这些选项接受两种类型的输入:

  • 字符串格式(如'HH:mm'
  • 对象格式(如{ hour: '2-digit', minute: '2-digit' }

12小时制与24小时制切换

最常见的需求是切换12小时制与24小时制显示,这可以通过eventTimeFormat选项实现:

// 24小时制配置(默认)
eventTimeFormat: {
  hour: '2-digit',
  minute: '2-digit',
  hour12: false // 关键参数:false为24小时制,true为12小时制
}

// 12小时制配置
eventTimeFormat: {
  hour: '2-digit',
  minute: '2-digit',
  hour12: true // 显示AM/PM
}

注意:在不同的本地化环境中,hour12的默认值可能不同。美国英语 locale 默认使用12小时制,而大多数其他 locale 默认使用24小时制。

常用时间格式字符串速查表

格式字符串描述示例
HH:mm24小时制,带分钟14:30
h:mm a12小时制,带AM/PM2:30 PM
HH:mm:ss带秒的24小时制14:30:45
yyyy-MM-dd年-月-日2023-10-05
MMM d, yyyy缩写月份和日期Oct 5, 2023

高级时间格式定制

按视图类型定制格式

不同的视图(月视图、周视图、日视图)可能需要不同的时间格式,可以通过对象形式为特定视图配置:

slotLabelFormat: {
  hour: '2-digit',
  minute: '2-digit',
  hour12: false
},
views: {
  timeGridDay: {
    slotLabelFormat: { // 仅应用于日视图
      hour: '2-digit',
      minute: '2-digit',
      second: '2-digit',
      hour12: false
    }
  },
  dayGridMonth: {
    columnHeaderFormat: { // 月视图的列标题格式
      weekday: 'long', // 完整星期名
      month: 'short',  // 缩写月份
      day: 'numeric'   // 日期数字
    }
  }
}

事件时间格式化实战

tests/src/legacy/eventTimeFormat.ts中可以找到事件时间格式化的测试案例,以下是实际应用示例:

// 基础事件时间格式
eventTimeFormat: {
  hour: '2-digit',
  minute: '2-digit',
  hour12: false
}

// 带秒的高精度格式
eventTimeFormat: {
  hour: '2-digit',
  minute: '2-digit',
  second: '2-digit',
  hour12: false
}

// 字符串简写形式
eventTimeFormat: 'HH:mm:ss' // 等同于上面的对象格式

槽位标签和列标题格式

除了事件时间,还可以自定义时间槽标签和列标题的格式:

// 槽位标签格式(左侧时间轴)
slotLabelFormat: {
  hour: '2-digit',
  minute: '2-digit',
  omitZeroMinute: true, // 当分钟为0时省略
  meridiem: 'short'    // 显示AM/PM(仅12小时制)
},

// 列标题格式(日历顶部日期)
columnHeaderFormat: {
  weekday: 'short',  // 星期缩写(如"周一")
  month: 'numeric',  // 数字月份
  day: 'numeric',    // 日期
  daySuffix: 'short' // 日期后缀(如"1st"、"2nd")
}

本地化与时区处理

多语言支持

FullCalendar通过locale选项支持多语言显示,需要引入相应的语言包:

import zhCN from '@fullcalendar/core/locales/zh-cn';

const calendar = new FullCalendar.Calendar(el, {
  locale: zhCN, // 设置为中文
  eventTimeFormat: {
    hour: '2-digit',
    minute: '2-digit',
    hour12: false // 中文环境默认使用24小时制
  }
});

时区配置

时区处理是时间显示的重要部分,在tests/src/datelib/main.ts中可以看到相关测试配置:

// 时区配置示例
{
  timeZone: 'UTC',          // 使用UTC时区
  // timeZone: 'local',     // 使用本地时区
  // timeZone: 'Asia/Shanghai' // 使用特定时区
}

当切换时区时,FullCalendar会自动调整所有时间显示:

// 动态切换时区
calendar.setOption('timeZone', 'America/New_York');

时区转换示例

以下是一个完整的时区转换示例,展示同一事件在不同时区的显示效果:

document.addEventListener('DOMContentLoaded', function() {
  const calendarEl = document.getElementById('calendar');
  
  const calendar = new FullCalendar.Calendar(calendarEl, {
    initialView: 'timeGridDay',
    events: [
      {
        title: '跨时区会议',
        start: '2023-10-05T12:00:00', // 事件原始时间(ISO格式)
        end: '2023-10-05T13:00:00',
        timeZone: 'UTC' // 事件所在时区
      }
    ],
    timeZone: 'Asia/Shanghai', // 初始显示时区
    eventTimeFormat: {
      hour: '2-digit',
      minute: '2-digit',
      hour12: false
    }
  });

  calendar.render();

  // 时区切换按钮
  document.getElementById('tz-utc').addEventListener('click', () => {
    calendar.setOption('timeZone', 'UTC');
  });
  
  document.getElementById('tz-shanghai').addEventListener('click', () => {
    calendar.setOption('timeZone', 'Asia/Shanghai');
  });
  
  document.getElementById('tz-newyork').addEventListener('click', () => {
    calendar.setOption('timeZone', 'America/New_York');
  });
});

高级定制:实现农历显示

集成农历库

要实现农历显示,需要集成第三方农历库,如lunar-javascript。以下是实现方案:

  1. 安装农历库:
npm install lunar-javascript
  1. 创建自定义格式化函数:
import { Solar, Lunar } from 'lunar-javascript';

// 自定义日期格式化函数
function formatWithLunar(date) {
  const solar = Solar.fromDate(date);
  const lunar = solar.getLunar();
  
  // 公历日期
  const solarStr = solar.toYmd();
  // 农历日期
  const lunarStr = `${lunar.getYearInChinese()}年${lunar.getMonthInChinese()}${lunar.getDayInChinese()}`;
  
  // 结合显示
  return `${solarStr} (${lunarStr}${lunar.isLeap() ? '闰' : ''})`;
}

自定义列标题组件

通过columnHeaderContent回调自定义列标题,集成农历显示:

columnHeaderContent: function(info) {
  const date = info.date;
  const solar = Solar.fromDate(date);
  const lunar = solar.getLunar();
  
  // 返回HTML元素
  const div = document.createElement('div');
  div.innerHTML = `
    <div class="solar-date">${date.getDate()}</div>
    <div class="lunar-date">${lunar.getDayInChinese()}</div>
    ${lunar.isFestive() ? `<div class="festival">${lunar.getFestive()}</div>` : ''}
  `;
  
  return div;
}

自定义事件时间显示

通过eventContent回调自定义事件时间显示,加入农历信息:

eventContent: function(info) {
  const start = info.event.start;
  const end = info.event.end;
  
  // 格式化公历时间
  const timeText = info.timeText;
  
  // 计算农历时间
  const lunarStart = Solar.fromDate(start).getLunar();
  const lunarTimeText = `农历${lunarStart.getMonthInChinese()}${lunarStart.getDayInChinese()}`;
  
  // 返回自定义内容
  return {
    html: `
      <div class="fc-title">${info.event.title}</div>
      <div class="fc-time">${timeText} (${lunarTimeText})</div>
    `
  };
}

农历样式美化

添加CSS样式美化农历显示效果:

/* 列标题农历样式 */
.fc-col-header-cell-cushion {
  display: flex;
  flex-direction: column;
}

.lunar-date {
  font-size: 12px;
  color: #666;
}

.festival {
  font-size: 10px;
  color: #ff4d4f;
}

/* 事件农历样式 */
.fc-event .fc-time {
  font-size: 12px;
}

常见问题与解决方案

格式不生效问题排查

如果时间格式设置不生效,可以按以下步骤排查:

  1. 检查是否使用了正确的选项名称(如eventTimeFormat而非eventDateFormat
  2. 确认格式对象的属性是否正确(参考Intl.DateTimeFormat文档)
  3. 检查是否有视图特定的格式覆盖了全局设置
  4. 验证是否正确引入了相关依赖和本地化文件

性能优化

当处理大量事件或复杂格式化时,可能需要优化性能:

// 使用缓存避免重复计算
const formatCache = new Map();

function cachedLunarFormat(date) {
  const key = date.toISOString();
  if (formatCache.has(key)) {
    return formatCache.get(key);
  }
  
  // 计算农历格式
  const result = formatWithLunar(date);
  formatCache.set(key, result);
  
  // 设置缓存过期(24小时)
  setTimeout(() => formatCache.delete(key), 86400000);
  
  return result;
}

完整示例代码

以下是集成农历显示的完整日历配置示例:

document.addEventListener('DOMContentLoaded', function() {
  const calendarEl = document.getElementById('calendar');
  
  const calendar = new FullCalendar.Calendar(calendarEl, {
    initialView: 'dayGridMonth',
    eventTimeFormat: {
      hour: '2-digit',
      minute: '2-digit',
      hour12: false
    },
    columnHeaderContent: function(info) {
      // 自定义列标题,显示农历
      const date = info.date;
      const solar = Solar.fromDate(date);
      const lunar = solar.getLunar();
      
      const div = document.createElement('div');
      div.className = 'lunar-header';
      div.innerHTML = `
        <div class="solar">${date.getDate()}</div>
        <div class="lunar">${lunar.getDayInChinese()}</div>
        ${lunar.isFestive() ? `<div class="festival">${lunar.getFestive()}</div>` : ''}
      `;
      return div;
    },
    eventContent: function(info) {
      // 事件内容自定义
      const start = info.event.start;
      const lunarStart = Solar.fromDate(start).getLunar();
      
      return {
        html: `
          <div class="event-title">${info.event.title}</div>
          <div class="event-time">${info.timeText}</div>
          <div class="event-lunar">农历${lunarStart.getMonthInChinese()}${lunarStart.getDayInChinese()}</div>
        `
      };
    },
    events: [
      {
        title: '农历新年活动',
        start: '2023-01-22',
        end: '2023-01-24'
      },
      // 更多事件...
    ]
  });

  calendar.render();
});

总结与展望

本文详细介绍了FullCalendar时间格式自定义的各个方面,从基础的12/24小时制切换,到高级的农历显示实现。我们学习了如何利用eventTimeFormatslotLabelFormatcolumnHeaderFormat等选项控制时间显示,以及如何通过localetimeZone选项处理本地化和时区问题。

通过第三方库的集成,我们实现了农历等复杂历法的显示,这展示了FullCalendar的灵活性和可扩展性。未来,随着国际化需求的增加,FullCalendar可能会提供更直接的多历法支持,但目前通过本文介绍的方法,已经可以满足大多数定制需求。

最后,建议在实际开发中:

  1. 根据用户群体选择合适的默认时间格式
  2. 提供时区和历法切换选项,增强用户体验
  3. 注意性能优化,特别是在处理复杂格式化时
  4. 充分测试不同浏览器和设备上的显示效果

希望本文能帮助你更好地掌握FullCalendar的时间格式化技巧,打造更符合用户需求的日程应用。

附录:常用格式化选项速查表

选项作用示例值
eventTimeFormat事件时间格式{ hour: '2-digit', minute: '2-digit' }
slotLabelFormat槽位标签格式'HH:mm'
columnHeaderFormat列标题格式{ weekday: 'short', day: 'numeric' }
locale本地化设置'zh-cn'
timeZone时区设置'Asia/Shanghai'
displayEventEnd是否显示结束时间true
allDayText"全天"文本"全天"
firstDay每周第一天1(周一)

【免费下载链接】fullcalendar Full-sized drag & drop event calendar in JavaScript 【免费下载链接】fullcalendar 项目地址: https://gitcode.com/gh_mirrors/fu/fullcalendar

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值