Index: src/test/java/org/quartz/Quartz601Test.java
===================================================================
--- src/test/java/org/quartz/Quartz601Test.java	(revision 0)
+++ src/test/java/org/quartz/Quartz601Test.java	(revision 0)
@@ -0,0 +1,87 @@
+/* 
+ * Copyright 2007 OpenSymphony 
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not 
+ * use this file except in compliance with the License. You may obtain a copy 
+ * of the License at 
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0 
+ *   
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 
+ * License for the specific language governing permissions and limitations 
+ * under the License.
+ */
+package org.quartz;
+
+import junit.framework.TestCase;
+
+import java.text.ParseException;
+import java.util.Set;
+
+import org.quartz.*;
+
+public class Quartz601Test extends TestCase {
+
+    public void testNormal() {
+        for(int i=0; i<6; i++) {
+            assertParsesForField("0 15 10 * * ? 2005", i);
+        }
+    }
+    public void testSecond() {
+          assertParsesForField("58-4 5 21 ? * MON-FRI", 0);
+    }
+    public void testMinute() {
+          assertParsesForField("0 58-4 21 ? * MON-FRI", 1);
+    }
+    public void testHour() {
+          assertParsesForField("0 0/5 21-3 ? * MON-FRI", 2);
+    }
+    public void testDayOfWeekNumber() {
+          assertParsesForField("58 5 21 ? * 6-2", 5);
+    }
+    public void testDayOfWeek() {
+          assertParsesForField("58 5 21 ? * FRI-TUE", 5);
+    }
+    public void testDayOfMonth() {
+          assertParsesForField("58 5 21 28-5 1 ?", 3);
+    }
+    public void testMonth() {
+          assertParsesForField("58 5 21 ? 11-2 FRI", 4);
+    }
+    public void testAmbiguous() {
+          System.err.println( assertParsesForField("0 0 14-6 ? * FRI-MON", 2) );
+          System.err.println( assertParsesForField("0 0 14-6 ? * FRI-MON", 5) );
+
+          System.err.println( assertParsesForField("55-3 56-2 6 ? * FRI", 0) );
+          System.err.println( assertParsesForField("55-3 56-2 6 ? * FRI", 1) );
+    }
+
+    private Set assertParsesForField(String expression, int constant) {
+        try {
+            TestCronExpression cronExpression = new TestCronExpression(expression);
+            Set set = cronExpression.getSetPublic(constant);
+            if(set.size() == 0) {
+                fail("Empty field ["+constant+"] returned for " + expression);
+            }
+            return set;
+        } catch(ParseException pe) {
+            fail("Exception thrown during parsing: " + pe);
+        }
+        return null;  // not reachable
+    }
+
+}
+
+class TestCronExpression extends CronExpression {
+
+    public TestCronExpression(String cronExpression) throws ParseException {
+        super(cronExpression);
+    }
+
+    public Set getSetPublic(int constant) {
+        return super.getSet(constant);
+    }
+
+} 

Property changes on: src/test/java/org/quartz/Quartz601Test.java
___________________________________________________________________
Name: svn:eol-style
   + native

Index: src/java/org/quartz/CronExpression.java
===================================================================
--- src/java/org/quartz/CronExpression.java	(revision 763)
+++ src/java/org/quartz/CronExpression.java	(working copy)
@@ -161,6 +161,13 @@
  * <li>Support for specifying both a day-of-week and a day-of-month value is
  * not complete (you'll need to use the '?' character in on of these fields).
  * </li>
+ * <li>Overflowing ranges is supported - that is, having a larger number on 
+ * the left hand side than the right. You might do 22-2 to catch 10 o'clock 
+ * at night until 2 o'clock in the morning, or you might have NOV-FEB. It is 
+ * very important to note that overuse of overflowing ranges creates ranges 
+ * that don't make sense and no effort has been made to determine which 
+ * interpretation CronExpression chooses. An example would be 
+ * "0 0 14-6 ? * FRI-MON". </li>
  * </ul>
  * </p>
  * 
@@ -264,7 +271,7 @@
         testDateCal.add(Calendar.SECOND, -1);
         
         Date timeAfter = getTimeAfter(testDateCal.getTime());
-        
+
         return ((timeAfter != null) && (timeAfter.equals(originalDate)));
     }
     
@@ -345,7 +352,7 @@
     public String toString() {
         return cronExpression;
     }
-    
+
     /**
      * Indicates whether the specified cron expression can be parsed into a 
      * valid cron expression
@@ -433,7 +440,7 @@
 
     protected int storeExpressionVals(int pos, String s, int type)
         throws ParseException {
-        
+
         int incr = 0;
         int i = skipWhiteSpace(pos, s);
         if (i >= s.length()) {
@@ -477,11 +484,6 @@
                                     "Invalid Day-of-Week value: '" + sub
                                         + "'", i);
                         }
-                        if (sval > eval) {
-                            throw new ParseException(
-                                    "Invalid Day-of-Week sequence: " + sval 
-                                        + " > " + eval, i);
-                        }
                     } else if (c == '#') {
                         try {
                             i += 4;
@@ -953,8 +955,39 @@
             }
         }
 
+        // if the end of the range is before the start, then we need to overflow into 
+        // the next day, month etc. This is done by adding the maximum amount for that 
+        // type, and using modulus max to determine the value being added.
+        int max = -1;
+        if (stopAt < startAt) {
+            switch (type) {
+              case       SECOND : max = 60; break;
+              case       MINUTE : max = 60; break;
+              case         HOUR : max = 24; break;
+              case        MONTH : max = 12; break;
+              case  DAY_OF_WEEK : max = 7;  break;
+              case DAY_OF_MONTH : max = 31; break;
+              case         YEAR : throw new IllegalArgumentException("Start year must be less than stop year");
+              default           : throw new IllegalArgumentException("Unexpected type encountered");
+            }
+            stopAt += max;
+        }
+
         for (int i = startAt; i <= stopAt; i += incr) {
-            set.add(new Integer(i));
+            if (max == -1) {
+                // ie: there's no max to overflow over
+                set.add(new Integer(i));
+            } else {
+                // take the modulus to get the real value
+                int i2 = i % max;
+
+                // 1-indexed ranges should not include 0, and should include their max
+                if (i2 == 0 && (type == MONTH || type == DAY_OF_WEEK || type == DAY_OF_MONTH) ) {
+                    i2 = max;
+                }
+
+                set.add(new Integer(i2));
+            }
         }
     }
 
