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

使用FullCalendar基于rrule字符串生成带时长日历的时间异常问题

问题:FullCalendar重复事件时间显示异常

我需要基于以下三个变量构建日历:

  • dtstart = '20240820T170000';
  • dtend = '20240820T190000';
  • rrule = 'FREQ=WEEKLY;UNTIL=20240917T235959Z;BYDAY=TU;WKST=SU';

我编写了如下代码:

<!DOCTYPE html>
<html>

<head>
    <link href='https://unpkg.com/fullcalendar@5.11.5/main.min.css' rel='stylesheet' />
    <script src='https://unpkg.com/fullcalendar@5.11.5/main.min.js'></script>
    <script src='https://cdn.jsdelivr.net/npm/rrule@2.6.4/dist/es5/rrule.min.js'></script>
    <script src='https://cdn.jsdelivr.net/npm/@fullcalendar/rrule@5.11.5/main.global.min.js'></script>

    <script>
        document.addEventListener('DOMContentLoaded', function () {
            var calendarEl = document.getElementById('calendar');

            // Event details
            var dtstart = '20240820T170000';
            var dtend = '20240820T190000';
            var rrule = 'FREQ=WEEKLY;UNTIL=20240917T235959Z;BYDAY=TU;WKST=SU';

            // Function to calculate duration from DTSTART and DTEND
            function calculateDuration(dtstart, dtend) {
                var start = new Date(dtstart);
                var end = new Date(dtend);
                var durationInMs = end - start;
                var durationInHours = durationInMs / (1000 * 60 * 60);
                return durationInHours + ':00';
            }

            var duration = calculateDuration(dtstart, dtend);

            var calendarConfig = {
                firstDay: 1,
                headerToolbar: {
                    right: 'dayGridMonth,timeGridWeek,timeGridDay',
                    center: 'title',
                    left: 'prevYear,prev,next,nextYear'
                },
                initialDate: dtstart,
                events: []
            };

            var rruleString = 'DTSTART:' + dtstart + '\nRRULE:' + rrule;
            calendarConfig.events.push({
                title: '{{ view.field.title.original_value }}',
                rrule: rruleString,
                duration: duration // Use calculated duration
            });

            var calendar = new FullCalendar.Calendar(calendarEl, calendarConfig);

            calendar.render();
        });
    </script>
</head>

<body>
    <div id='calendar'></div>
</body>

</html>

目前日历已正确识别事件的日期,但事件的时间显示异常:

日期显示正常👍:
日期显示正常

时间显示异常👎:
时间显示异常

请问这是什么原因?


原因及解决方法

核心问题1:时区不匹配

你的dtstart是不带时区标识的本地时间(20240820T170000),但rrule中的UNTIL参数带了Z后缀(表示UTC时区)。FullCalendar解析时会默认把无时区的DTSTART也当成UTC时间处理,导致本地显示的时间和预期出现偏移。

核心问题2:Duration格式错误

FullCalendar要求duration属性使用ISO 8601时长格式(比如PT2H表示2小时),但你当前返回的是2:00这种自定义格式,无法被正确解析,进而导致事件时间计算错误。

修复方案

方案一:统一时区+修正Duration格式

  1. 给dtstart添加时区标识(比如你的本地时区是东八区,就写成20240820T170000+08:00),同时把rrule中的UNTIL改成对应时区的时间(去掉Z,写成20240917T235959+08:00),保证时区统一。
  2. 修改calculateDuration函数,返回ISO 8601格式的时长:
function calculateDuration(dtstart, dtend) {
    var start = new Date(dtstart);
    var end = new Date(dtend);
    var durationInMs = end - start;
    var hours = Math.floor(durationInMs / (1000 * 60 * 60));
    var minutes = Math.floor((durationInMs % (1000 * 60 * 60)) / (1000 * 60));
    return `PT${hours}H${minutes}M`;
}

方案二:使用RRule对象替代字符串(更推荐)

直接用rrule.js创建规则对象,避免手动拼接字符串的时区和格式问题:

// 替换原事件添加的代码
var rule = new RRule({
  freq: RRule.WEEKLY,
  until: new Date('2024-09-17T23:59:59'),
  byweekday: [RRule.TU],
  wkst: RRule.SU,
  dtstart: new Date(dtstart)
});

calendarConfig.events.push({
  title: '{{ view.field.title.original_value }}',
  rrule: rule,
  duration: 'PT2H' // 直接指定2小时的ISO时长
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 01:24:51