使用quartz-scheduler(cron)如何设置偏移基准时间?

时间:2014-04-30 06:32:39

标签: cron quartz.net

我正在尝试启动一个间隔任务,每隔x小时运行一次,并从某个时间点开始运行。

目前我的cron看起来像这样。

    0 <OffsetMinsAmount>/<Mins Increment> <OffsetHoursAmount>/<Hours Increment> ? * *

    eg

    0 22/51 3/0 ? * * // starting at 3:22 every 51 mins do x

如果我在3:22之前安排上述示例,它将在3:22工作,然后安排下一次运行时间@ 4 22

这不是我预期的,因为下次应该是4:13

从我在网上阅读的内容来看,我做错了,因为这在一个小时内就是x分钟。

任何人都可以提出我做错的事吗?

这也是我创建它的方式(.net):

    trigger = TriggerBuilder.Create()
                            .WithCronSchedule(cronExpression, x => x.WithMisfireHandlingInstructionDoNothing())
                            .StartAt(schedulerTask.Start.ToUniversalTime())
                            .EndAt(null)
                            .Build();

2 个答案:

答案 0 :(得分:1)

这可能已经太晚了,但看起来你试图使用的cron表达式实际上有3个错误的东西。

由于您使用repeatForever()方法解决了问题,因此您可能不需要执行任何操作。使用SimpleSchedule路径我可以看到的唯一缺点是,您正在失去使用纯cron表达式所获得的一点灵活性(即,如果您希望允许用户传入cron表达式)例如,或者如果你想支持其他不了解Quartz但熟悉cron表达式的系统,或者如果你想支持其他系统。这实际上取决于您使用它的用例。无论如何,这是解释:

<强>解释

在进入表达式细分之前,有一点需要了解的是Quartz,每当你指定一个时间间隔时,间隔部分将只重复到特定时间值的限制(59秒,秒和分钟,23如果(开始时间+间隔)超过这个限制,它就好像虽然时间不存在(如果你考虑它,它真的没有),所以Quartz会跳过它并继续下一个符合你日程安排的时间间隔而不会过去。即使您没有指定间隔,情况也是如此。

在您的示例22/51中,您希望从51分钟开始每隔22分钟安排一次。但实际上最终发生的事情是,每当分钟标记达到22而你没有前往13时,你就安排了一些事情。这是因为开始时间+间隔(22 + 51 = 73)超过了59的微小间隔的限制。 Quartz不够聪明,知道它应该包裹着#34;超过59到下一个小时的额外分钟。

这里还有另一个问题,如果你指定了一个较小的时间间隔,比如说10,那么你的表达式是22/10,那么你的日程安排就会执行{ {1}}分钟从分钟10开始直至22的分钟限制。因此,如果您希望从59开始每隔10分钟运行一次,那么它就不会像您预期的那样在4:224:02运行。同样,这是由于Quartz处理这个问题的本质。

相反,你应该做的是使用特殊范围字符4:12来指定你的分钟范围,这将告诉石英你希望它做什么&#34;包裹&#34;对于超过最大值的任何分钟。所以你的分钟表达式实际上应该是-。这意味着从分钟22-21/51开始一直到分钟22(换句话说,距离21一整小时,然后从22-59开始)你想要只做每一件事这些合计分钟的0-21分钟。这实际上可以让您超过51分钟限制(或您正在使用的任何时间价值)。

<强>实施例

官方Quartz documentation实际上有一些例子显示我想要解释的内容。这是一对夫妇:

59

注意如何指定14(2pm)作为起始小时并不意味着它将每小时运行一次。这意味着时间表将从下午2点开始每5分钟运行一次,但绝不会超过2-3pm范围。如果你想每天每小时从下午2点开始每隔5分钟运行一次,那么表达式就是0 0/5 14 * * ? Fire every 5 minutes starting at 2pm and ending at 2:55pm, every day 0 0/5 14-13 * * ?表示从小时14-13开始,然后环绕几小时第二天的14-23

0-13

这与上面的示例类似,只是除了从0 0/5 14,18 * * ? Fire every 5 minutes starting at 2pm and ending at 2:55pm, AND fire every 5 minutes starting at 6pm and ending at 6:55pm, every day 运行某些内容之外,他们还使用2-3pm字符和小时添加了6-7pm的另一个小时范围价值,

不幸的是,文档中的示例有点缺乏,并且没有涵盖Quartz可能遇到的所有不同组合和用例。我发现一个非常有价值的工具可以用Cronmaker来验证你的cron表达式。

<强>击穿

以下是对示例cron表达式中的错误的解释:

18

这是表达式的第一个问题。这意味着从22分钟(例如3:22)开始每51分钟一直运行直到该小时的59分钟标记,但它不会像你期望的那样在13分钟的标记处包裹到下一个小时。请参阅上面的冗长解释。

22/51

这是其他两个问题所在。第一个是,与表达式的分钟部分类似,通过单独使用3/0 ,您可以说从第3小时开始直到(但不包括)第4小时开始运行。第二个是通过使用3你实际上告诉它永远不会重复超过3。

<强>解决方案

为了实现你想要每天每小时从早上3:22开始每51分钟运行一次的时间表你应该使用它:

/0

小时字段中的0 22-21/51 3-2/1 * * ? 实际上不是必需的,因为默认情况下它会每小时重复一次,但您可以将其保留以明确显示。因此,如果您想:

,可以将表达式简化为此
/1

请注意我如何指定分钟和小时的范围,以确保它们不会执行到特定限制结束时(59分钟和23小时)。

无论如何,我希望如果我的解释有点令人困惑,这会有所帮助。如果不为自己尝试,很难描述并且可能理解这些东西。希望这些例子让它更清晰一点。

答案 1 :(得分:0)

马克先生对这里的钱很感兴趣简单就好了。

下面的工作很好,谢谢你。

   int mins;
   if (int.TryParse(schedulerTask.Data, out mins) && mins > 0)
   {
       trigger = TriggerBuilder.Create()
           .WithSimpleSchedule(x => x
               .WithIntervalInMinutes(mins)
               .RepeatForever()
               .WithMisfireHandlingInstructionNextWithRemainingCount())
           .StartAt(schedulerTask.Start.ToUniversalTime())
           .EndAt(null)
           .Build();
   }