Question

I'm trying to start an intervalled task that runs every x hours and y mins from a point in time.

Currently my cron looks like this.

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

    eg

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

If I schedule the above example before 3:22 it works at 3:22 then schedules the next run time @ 4 22

This is not what i have expected as the next time should be 4:13

From what I'm reading on the net I'm doing it wrong as this is ever x mins in a singular hour.

Can any one suggest what I'm doing wrong?

Also this is how I'm creating it(.net):

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

Solution 2

Mr marko was bang on the money here simple is better.

The below works just fine thanks man.

   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();
   }

OTHER TIPS

This is probably already too late but it looks like the cron expression you were trying to use actually had 3 things that were wrong with it.

Since you got your problem working using the repeatForever() method then perhaps you don't need to do any of this. The only drawback that I can see with going with the SimpleSchedule route is that you're losing a bit of the flexibility that you gain from using pure cron expressions (ie. if you want to allow your users to pass in a cron expression directly, for example, or if you want to support other systems that don't understand Quartz but are familiar with cron expressions). It really depends on the use case that you were using this for. Anyways, here is the explanation:

Explanation

Before going into the breakdown of your expression, one thing to understand about Quartz is that whenever you specify a time interval, the interval portion will repeat only up until the limit for the particular time value (59 for seconds and minutes, 23 for hours, 31 for days) without wrapping around to the next minute, hour, day, etc. If the (starting time + interval) goes over this limit, it's as if though the time doesn't exist (which it really doesn't if you think about it) and so Quartz skips it and goes on to the next interval that meets your schedule without going over. This is also the case even if you don't specify an interval.

In your example, 22/51, you wanted to schedule something every 51 minutes starting at minute 22. But what actually ended up happening is that you scheduled something every time the minute mark hit 22 without ever going to 13. This is because the starting time + the interval (22 + 51 = 73) went over the limit for the minutely interval which is 59. Quartz isn't smart enough to know that it should "wrap around" the extra minutes that went past 59 over to the next hour.

There is another issue here and it's that if you had specified a smaller time interval, like say 10, so that your expression was 22/10, then your schedule would execute every 10 minutes starting at minute 22 up until the minute limit of 59. So if you wanted to run something every 10 minutes starting at 4:22 then it would not have run at 4:02 and 4:12 like you might have expected it to. Again, this is due to the nature of how Quartz handles this.

Instead what you should do is use the special range character - to specify your minute range which will tell quartz that you want it to do a "wrap" for any minutes that go over the maximum. So your minute expression should actually be 22-21/51. This means that starting at minute 22 all the way to minute 21 (in other words a full hour from 22-59 and then from 0-21) you want to do something only every 51 minutes of those combined minutes. This will in effect get you over the 59 minute limit (or whatever time value you're using).

Examples

The official Quartz documentation actually has some examples which show what I am trying to explain. Here are a couple:

0 0/5 14 * * ?     Fire every 5 minutes starting at 2pm and ending at 2:55pm, every day

Notice how specifying 14 (2pm) as the starting hour doesn't mean that it will run every hour. What it means is that the schedule will run every 5 minutes starting at 2pm but it will never go past the 2-3pm range. If you wanted to run this every 5 minutes starting at 2pm for every hour of every day, then the expression would be 0 0/5 14-13 * * ? (the 14-13 means go from hours 14-23 and wrap around to hours 0-13 of the following day)

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

This is similar to the example above except that in addition to running something from 2-3pm they've added another hour range from 6-7pm using the , character along with the hour value 18.

Unfortunately the examples in the documentation are a bit lacking and don't cover all of the different combinations and use cases that you can encounter with Quartz. A tool that I've found invaluable to figuring this stuff out is this Cronmaker which you can use to verify your cron expressions.

Breakdown

Here is an explanation of the errors in your example cron expression:

22/51

This is the first issue with the expression. This means run every 51 minutes starting at 22 minutes (e.g. 3:22) up until the 59 minute mark for that hour but it won't wrap to the next hour at the 13 minute mark like you expect it to. See the lengthy explanation above.

3/0 

This is where the other 2 issues are at. The first is that, similar to the minute portion of the expression, by using the 3 on its own you're saying run starting at hour 3 and up until (but not including) hour 4. The second is that by using the /0 you're actually telling it to never repeat beyond beyond 3.

Solution

To achieve the schedule that you want of running something every 51 minutes starting at 3:22 am for every hour of every day you should use this:

0 22-21/51 3-2/1 * * ?

The /1 in the hour field is actually not necessary since by default it will repeat every hour but you can leave it in to explicitly show this. So you could simplify your expression to this if you wanted to:

0 22-21/51 3-2 * * ?

Notice how I specified the ranges for minutes and hours to ensure that they don't only execute up until the end of their particular limits (59 for minutes and 23 for hours).

Anyways, I hope this helps and sorry if my explanation was a little confusing. It's a little hard to describe and probably understand this stuff without trying it for yourself. Hopefully the examples made it a little clearer.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top