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

Angular Calendar夏令时时区下周视图时间显示异常求助

Angular Calendar周视图夏令时时区重复时间问题修复方案

问题背景

使用angular-calendar周视图并配置[hourSegmentTemplate]后,在开启自动夏令时的时区(如UTC+01:00布鲁塞尔/哥本哈根/马德里/巴黎)下,时间轴出现重复小时(如连续两个3am),同时事件回调返回的时间值也存在错误,官方示例也可复现该问题。

修复方案

1. 统一时区处理逻辑

强制使用UTC或指定时区处理日期,规避夏令时切换带来的时间歧义:

  • 初始化viewDate时使用UTC时间:
    this.viewDate = new Date(Date.UTC(
      new Date().getUTCFullYear(),
      new Date().getUTCMonth(),
      new Date().getUTCDate()
    ));
    
  • 处理eventTimesChanged回调时,手动校正时区偏移:
    handleEditEvent(event: { event: CalendarEvent, newStart: Date, newEnd: Date }) {
      // 以欧洲中部时区为例,夏令时偏移为120分钟,非夏令时为60分钟
      const isDST = this.isInDST(event.newStart);
      const timezoneOffset = isDST ? 120 : 60;
      const correctedStart = new Date(event.newStart.getTime() + timezoneOffset * 60 * 1000);
      const correctedEnd = new Date(event.newEnd.getTime() + timezoneOffset * 60 * 1000);
      
      event.event.start = correctedStart;
      event.event.end = correctedEnd;
    }
    

2. 自定义小时段时间格式化

修改hourSegmentTemplate,通过自定义方法计算并显示正确时间,绕过库内置的时区bug:

  • 模板代码:
    <ng-template #weekViewHourSegmentTemplate let-segment="segment">
      <div class="cal-hour-segment">
        <span class="cal-time">{{ formatSegmentTime(segment.date) }}</span>
      </div>
    </ng-template>
    
  • 组件中实现格式化方法(适配欧洲中部夏令时规则):
    formatSegmentTime(date: Date): string {
      let hour = date.getHours();
      // 处理夏令时结束当天的重复小时(10月最后一个周日的2-3am时段)
      if (this.isDstTransitionHour(date)) {
        hour -= 1;
      }
      // 转换为12小时制格式
      const period = hour >= 12 ? 'pm' : 'am';
      const displayHour = hour % 12 === 0 ? 12 : hour % 12;
      return `${displayHour} ${period}`;
    }
    
    // 判断是否处于欧洲中部夏令时区间
    isInDST(date: Date): boolean {
      const year = date.getFullYear();
      const dstStart = this.getLastSunday(year, 2); // 3月最后一个周日
      dstStart.setHours(2, 0, 0);
      const dstEnd = this.getLastSunday(year, 9); // 10月最后一个周日
      dstEnd.setHours(3, 0, 0);
      return date >= dstStart && date < dstEnd;
    }
    
    // 判断是否是夏令时结束时的重复小时段
    isDstTransitionHour(date: Date): boolean {
      const dstEnd = this.getLastSunday(date.getFullYear(), 9);
      dstEnd.setHours(2, 0, 0);
      const transitionEnd = new Date(dstEnd.getTime() + 3600000);
      return date >= dstEnd && date < transitionEnd;
    }
    
    // 获取指定年月的最后一个周日
    getLastSunday(year: number, month: number): Date {
      const lastDay = new Date(year, month + 1, 0);
      const dayDiff = lastDay.getDay() === 0 ? 0 : lastDay.getDay();
      return new Date(year, month, lastDay.getDate() - dayDiff);
    }
    

3. 升级组件版本

检查angular-calendar是否有最新版本修复了该时区问题,执行升级命令:

npm install angular-calendar@latest --save

4. 临时应急方案

若上述方案暂无法实施,可临时关闭系统的「自动夏令时调整」选项,避免时间重复问题,但此为临时措施,不推荐长期使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 12:32:08