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

如何通过配置为Quartz任务添加日历以屏蔽节假日执行?

Quartz触发器节假日停止执行的配置方案

问题背景

我希望部分Quartz任务在节假日停止执行,Quartz官方文档提到:

实现ICalendar接口的Quartz.NET Calendar对象可在触发器存入调度器时与其关联,用于排除触发调度中的特定时间段。例如,可创建一个每周一至周五上午9:30执行的触发器,再添加排除所有公司节假日的Calendar。

我的触发器是通过配置文件定义的,示例如下:

<trigger> 
  <simple> 
    <name>a trigger</name> 
    <group>a trigger group</group> 
    <description>a trigger description</description> 
    <job-name>AJobName</job-name> 
    <job-group>a job group</job-group> 
    <job-data-map> 
      <entry> 
        <key>param1</key> 
        <value>param1value</value> 
      </entry> 
    </job-data-map> 
    <repeat-count>-1</repeat-count> 
    <repeat-interval>300000</repeat-interval> 
  </simple> 
</trigger> 

想请教两个问题:

  1. 能否在不修改C#代码的情况下,让触发器在节假日日历指定的日期不执行?
  2. 如果不行,能否保留配置文件中的触发器定义,仅在代码中添加日历并关联到指定触发器?

注:不需要通过代码创建触发器并关联日历的方案。


解答

1. 纯配置文件实现的可能性

很遗憾,仅靠Quartz.NET的原生配置文件是做不到直接关联日历的。Quartz的XML配置(无论是核心配置文件还是自定义触发器配置文件)并没有提供直接配置Calendar并关联到触发器的节点或属性。Calendar的注册和关联逻辑目前只能通过代码层面完成,没办法完全脱离C#代码实现。

2. 保留配置文件触发器,代码中关联日历的方案

这个是完全可行的,而且能满足你保留现有配置定义的需求,具体步骤如下:

  • 第一步:实现自定义节假日日历
    先写一个继承BaseCalendar(或直接实现ICalendar接口)的自定义日历类,比如HolidayCalendar,在里面定义需要排除的节假日日期(可以从配置文件、数据库等外部源加载,避免硬编码)。示例代码:

    public class HolidayCalendar : BaseCalendar
    {
        private readonly HashSet<DateTime> _holidays = new HashSet<DateTime>();
    
        public HolidayCalendar()
        {
            // 这里可以从配置文件、数据库读取节假日列表
            _holidays.Add(new DateTime(2024, 1, 1));
            _holidays.Add(new DateTime(2024, 2, 10));
            // 其他节假日...
        }
    
        public override bool IsTimeIncluded(DateTimeOffset timeUtc)
        {
            DateTime localDate = timeUtc.LocalDateTime.Date;
            return !_holidays.Contains(localDate);
        }
    }
    
  • 第二步:在调度器初始化时关联日历与触发器
    当你从配置文件加载完所有触发器之后,在调度器启动前,注册自定义日历,然后找到指定的触发器(通过配置里的名称和组),将两者关联起来。示例代码:

    // 假设已通过配置加载好调度器实例
    IScheduler scheduler = await SchedulerFactory.GetDefaultScheduler();
    
    // 注册自定义节假日日历,给日历命名为"holidayCalendar"
    ICalendar holidayCalendar = new HolidayCalendar();
    await scheduler.AddCalendar("holidayCalendar", holidayCalendar, false, false);
    
    // 找到配置中定义的目标触发器
    TriggerKey triggerKey = new TriggerKey("a trigger", "a trigger group");
    ITrigger targetTrigger = await scheduler.GetTrigger(triggerKey);
    
    // 为触发器关联日历,设置为排除模式(日历中的日期不执行任务)
    targetTrigger = targetTrigger.GetTriggerBuilder()
        .ModifiedByCalendar("holidayCalendar")
        .Build();
    
    // 更新调度器中的触发器
    await scheduler.RescheduleJob(triggerKey, targetTrigger);
    
    // 启动调度器
    await scheduler.Start();
    

这样一来,你完全保留了原有的配置文件触发器定义,只需要在调度器初始化的代码里添加几行逻辑,就能把指定触发器和节假日日历关联起来,实现节假日停止执行的需求。


内容的提问来源于stack exchange,提问作者Michel van Engelen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 06:45:05