History | Log In     View a printable version of the current page.  
Issue Details (XML | Word | Printable)

Key: QUARTZ-533
Type: Bug Bug
Status: Closed Closed
Resolution: Fixed
Priority: Critical Critical
Assignee: James House
Reporter: Aaron Craven
Votes: 0
Watchers: 1
Operations

If you were logged in you would be able to see more operations.
Quartz Scheduler

Bug when using '/' character in day-of-month expression in CronExpression/CronTrigger

Created: 23/Nov/06 12:35 PM   Updated: 01/Dec/06 11:55 AM
Component/s: Core, Triggers
Affects Version/s: 1.5, 1.4.2, 1.4.3, 1.4.4, 1.4.5, 1.5.1, 1.5.2
Fix Version/s: 1.6.1

Flags: Important


 Description  « Hide
Please see http://forums.opensymphony.com/thread.jspa?threadID=50883&tstart=0

There appears to be a severe bug in CronExpression (or CronTrigger, depending what version of quartz is being used) that prevents correct handling of trigger calculation in some situations. In particular, the problem can be reproduced with the following code:

SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yy");
            CronTrigger fiveDayTrigger = new CronTrigger("fiveTrigger", "TEST", "0 0 12 1/5 * ? *");
            fiveDayTrigger.setStartTime(dateFormat.parse("02/25/07"));
            fiveDayTrigger.setEndTime(dateFormat.parse("03/31/07"));
            
Date now = new Date();
            Date nextFireTime = fiveDayTrigger.getFireTimeAfter(dateFormat.parse("1/31/07"));
            while (nextFireTime != null) {
                System.out.println(dateFormat.format(nextFireTime));
                nextFireTime = fiveDayTrigger.getFireTimeAfter(nextFireTime);
            }

(Note that the above code does not add the trigger to the scheduler, which does not make it a complete test, but I have tried adding this step with no effect on the results)

Running this code, you'll note that 3/1/2007 is skipped. Tracing the code, it appears to me that the problem is somewhere in CronExpression.getTimeAfter(Date).

Again, please see the mentioned forum entry for more information.

 All   Comments   Change History      Sort Order:
Christophe Roudet - [27/Nov/06 04:41 PM ]
  in CronExpression.getTimeAfter(Date), adding a few lines seems to fix this issue:
.....
 tcal.set(Calendar.HOUR_OF_DAY, hr);
                    tcal.set(Calendar.DAY_OF_MONTH, day);
                    tcal.set(Calendar.MONTH, mon - 1);
                    Date nTime = tcal.getTime();
                    if(nTime.before(afterTime)) {
                        day = ((Integer) daysOfMonth.first()).intValue();;
                        mon++;
                    }
                } else if (st != null && st.size() != 0) {
                    t = day;
                    day = ((Integer) st.first()).intValue();
// ============ Patch ===========
// check if 'day' should be taken in next month
                    int lastDay = getLastDayOfMonth(mon, cl.get(Calendar.YEAR));
                    if (day > lastDay) {
                      day = ((Integer) daysOfMonth.first()).intValue();;
                      mon++;
                    }
// ==============================
                } else {
                    day = ((Integer) daysOfMonth.first()).intValue();
                    mon++;
                }
                
if (day != t || mon != tmon) {
                    cl.set(Calendar.SECOND, 0);
                    cl.set(Calendar.MINUTE, 0);
                    cl.set(Calendar.HOUR_OF_DAY, 0);
...

James House - [29/Nov/06 05:05 PM ]
thanks for the patch, with a quick look it appears to be right on the money.

James House - [01/Dec/06 11:51 AM ]
...I suppose this was never found because usage of the '/' character in the day-of-month field has very limited practical use, due to the fact that it doesn't give you true "every N days" semantics.