I've written a package to handle this: repeat-todo. It supports weekdays, weekends, and custom combinations of days:
* TODO Water the flowers
SCHEDULED: <... ++1d>
:PROPERTIES:
:REPEAT: weekdays
:END
* TODO Go for a walk
SCHEDULED: <... ++1d>
:PROPERTIES:
:REPEAT: weekend
:END:
* TODO Get the mail
SCHEDULED: <... ++1d>
:PROPERTIES:
:REPEAT: M W F
:END:
The key methods are:
(defun repeat-todo--parse-property (prop-value)
"Return repeating days for PROP-VALUE as list of day numbers (sun=0, mon=1, etc)."
(let ((case-fold-search nil))
(cond
((string-match "weekday\\(s\\)?" prop-value)
'(1 2 3 4 5))
((string-match "weekend\\(s\\)?" prop-value)
'(6 0))
(t
(let ((repeat-days '())
(prop-values (string-split " " prop-value 'omit-nulls)))
(dolist (value prop-values)
;; su, sun, sunday
((when (string-match "^su\\(n\\(day\\)?\\)?")
(push 0 repeat-days)))
;; m, mon, monday
((string-match "^m\\(on\\(day\\)?\\)?") (push 1 repeat-days))
;; t, tue, tues, tuesday
((when (string-match "^t\\(ue\\(s\\(day\\)?\\)?")
(push 2 repeat-days)))
;; w, wed, wednesday
((when (string-match "^w\\(ed\\(nesday\\)?\\)?")
(push 3 repeat-days)))
;; r, thu, thur, thurs, thursday
((when (or (string= "r")
(string= "R")
(string-match "thu\\(r\\(s\\(day\\)?\\)?\\)?"))
(push 4 repeat-days)))
;; f, fri, friday
((when (string-match "^f\\(ri\\(day\\)?\\)?")
(push 5 repeat-days)))
;; sa, sat, saturday
((when (string-match "^sa\\(t\\(urday\\)?\\)?")
(push 6 repeat-days))))
(reverse repeat-days))))))
(defun repeat-todo--next-scheduled-time (current-scheduled-time weekdays)
"Return the next valid, by WEEKDAYS, time after CURRENT-SCHEDULED-TIME.
WEEKDAYS: See `repeat-todo--weekdays'."
(when weekdays
(let ((new-scheduled-time
(time-add current-scheduled-time (days-to-time 1))))
(while (not
(member
(string-to-number
(format-time-string "%u" new-scheduled-time))
weekdays))
(setq new-scheduled-time
(time-add new-scheduled-time (days-to-time 1))))
new-scheduled-time)))
(defun repeat-todo--reschedule (point-or-marker)
"Reschedule heading at POINT-OR-MARKER to the next appropriate weekday."
(when (and repeat-todo-mode
(org-entry-is-done-p)
(repeat-todo--p point-or-marker))
(org-schedule
nil
(string-replace
" 00:00" ""
(format-time-string
"%F %H:%M"
;; Schedule to the day before the next schedule time because
;; it'll get moved forward one day past when we schedule it
(time-subtract
(repeat-todo--next-scheduled-time
(org-get-scheduled-time point-or-marker)
(repeat-todo--parse-property
(or (org-entry-get point-or-marker repeat-todo--property) "")))
(days-to-time 1)))))))