   "Return a list with the year, month and day fields split"
   (let ((fields (split-string descriptor-string "[/\\-]" t))
         constrain-year constrain-month constrain-day)
-    (setq constrain-year (ledger-schedule-constrain-year (nth 0 fields)))
-    (setq constrain-month (ledger-schedule-constrain-month (nth 1 fields)))
-    (setq constrain-day (ledger-schedule-constrain-day (nth 2 fields)))
+    (setq constrain-year (ledger-schedule-constrain-year (nth 0 fields) (nth 1 fields) (nth 2 fields)))
+    (setq constrain-month (ledger-schedule-constrain-month (nth 0 fields) (nth 1 fields) (nth 2 fields)))
+    (setq constrain-day (ledger-schedule-constrain-day (nth 0 fields) (nth 1 fields) (nth 2 fields)))
 
     (list 'and constrain-year constrain-month constrain-day)))
 
-(defun ledger-schedule-constrain-year (str)
+(defun ledger-schedule-constrain-year (year-desc month-desc day-desc)
   (let ((year-match t))
-    (cond ((string= str "*")
+    (cond ((string= year-desc "*")
            year-match)
-          ((/= 0 (setq year-match (string-to-number str)))
+          ((/= 0 (setq year-match (string-to-number year-desc)))
            `(eq (nth 5 (decode-time date)) ,year-match))
           (t
-           (error "Improperly specified year constraint: %s" str)))))
-
-(defun ledger-schedule-constrain-month (str)
-
-  (let ((month-match t))
-    (cond ((string= str "*")
-           month-match)  ;; always match
-          ((/= 0 (setq month-match (string-to-number str)))
-           (if (between month-match 1 12) ;; no month specified, assume 31 days.
-               `(eq (nth 4 (decode-time date)) ,month-match)
-             (error "ledger-schedule-constrain-numerical-month: month out of range %S" month-match)))
-          (t
-           (error "Improperly specified month constraint: %s" str)))))
-
-(defun ledger-schedule-constrain-day (str)
-  (let ((day-match t))
-    (cond ((string= str "*")
-           t)
-          ((/= 0 (setq day-match (string-to-number str)))
-           `(eq (nth 3 (decode-time date)) ,day-match))
-          (t
-           (error "Improperly specified day constraint: %s" str)))))
+           (error "Improperly specified year constraint: %s %s %s" year-desc month-desc day-desc)))))
+
+(defun ledger-schedule-constrain-month (year-desc month-desc day-desc)
+	(cond ((string= month-desc "*")
+				 t)  ;; always match
+				((string= month-desc "E")  ;; Even
+				 `(evenp (nth 4 (decode-time date))))
+				((string= month-desc "O")  ;; Odd
+				 `(oddp (nth 4 (decode-time date))))
+				((/= 0 (string-to-number month-desc)) ;; Starts with number
+				 `(memq (nth 4 (decode-time date)) ',(mapcar 'string-to-number (split-string month-desc ","))))
+				(t
+				 (error "Improperly specified month constraint: %s %s %s" year-desc month-desc day-desc))))
+
+(defun ledger-schedule-constrain-day (year-desc month-desc day-desc)
+	(cond ((string= day-desc "*")
+				 t)
+				((/= 0 (string-to-number day-desc))
+				 `(memq (nth 3 (decode-time date)) ',(mapcar 'string-to-number (split-string day-desc ","))))
+				(t
+				 (error "Improperly specified day constraint: %s %s %s" year-desc month-desc day-desc))))
 
 (defun ledger-schedule-parse-date-descriptor (descriptor)
   "Parse the date descriptor, return the evaluator"

              (push (ledger-schedule-compile-constraints newcar) result)) )
          (setq descriptor-string-list (cdr descriptor-string-list)))

        ;; tie up all the clauses in a big or and lambda, and return
        ;; the lambda function as list to be executed by funcall
        `(lambda (date)
           ,(nconc (list 'or) (nreverse result) descriptor-string-list)))))

    items))

(defun ledger-schedule-already-entered (candidate buffer)
	"return TRUE if CANDIDATE is already in BUFFER"
  (let ((target-date (format-time-string date-format (car candidate)))
        (target-payee (cadr candidate)))
    nil))
