Reputation: 6512
I have tasks that I do every day (e.g bugzilla triage), but I only do those Monday to friday. Not on the weekends.
When I use something like this:
SCHEDULED: <2015-02-07 Sat ++1d>
It repeats it every day, including weekends. Can I change this?
Upvotes: 40
Views: 12254
Reputation: 11
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)))))))
Upvotes: 1
Reputation: 23
I had the same requirement and was able to resolve it by writing my own code. You can find it here:
https://gist.github.com/jsntn/542443e8505d62cac635eacd8bce458a
Note: ensure that the TODO task has the workday
tag set, like this:
* Task :workday:
SCHEDULED: <2024-08-02 Fri .+1d>
Upvotes: 0
Reputation: 11
There is the Habit Plus package, at https://github.com/myshevchuk/org-habit-plus, which augments the Habits functionality in Org Mode.
See Org Mode Habits in the manual: https://orgmode.org/manual/Tracking-your-habits.html
From the Readme.org at the Habits Plus github page:
Installation
As simple as putting the org-habit-plus.el into the load path and adding org-habit-plus to the org-modules list.
How it works
As simple as specifying the weekdays (1 = Monday, 7 = Sunday, space separated), on which a habit is expected to be performed, in the :HABIT_WEEKDAYS: property.
So, first you would enable the Habits module in Org and set your task as a habit, specifying how often it repeats. See the Org manual link above for details.
Then you would install Habits Plus. See the github page for the org-habit-plus.el file.
Then you would add a :HABIT_WEEKDAYS: property to your habit and give that property a value of 1 2 3 4 5
to indicate it should be completed Monday through Friday.
Upvotes: 1
Reputation: 331
One way is to simply have a TODO for each week day, eg:
* TODO My task
SCHEDULED: <2015-02-09 Mon ++1w>
* TODO My task
SCHEDULED: <2015-02-10 Tue ++1w>
This is different than another answer:
* TODO My task
SCHEDULED: <2015-02-09 Mon ++1w>
SCHEDULED: <2015-02-10 Tue ++1w>
SCHEDULED: <2015-02-11 Wed ++1w>
SCHEDULED: <2015-02-12 Thu ++1w>
SCHEDULED: <2015-02-13 Fri ++1w>
Which has an issue, as pointed out by someone:
There is an issue with this. When I close a task, it moves all the scheduled items forward by a week, not just the one that is due :-/
This issue occurs because all timestamps are associated with one TODO.
Upvotes: 14
Reputation: 2690
If you just need a reminder, and don't need to mark them as 'DONE' in your org-file, you could use the calendar integration for these situations.
** Triage Bugzilla Entries 09:00-10:00
<%%(memq (calendar-day-of-week date) '(1 2 3 4 5))>
This will insert an entry into your daily agenda for weekdays only, but not a task.
Upvotes: 34
Reputation: 671
Unfortunately, org-mode doesn't seem to support this in a simple command, but you can replicate this by setting up multiple weekly repeats for the same item like so:
* TODO My task
SCHEDULED: <2015-02-09 Mon ++1w>
SCHEDULED: <2015-02-10 Tue ++1w>
SCHEDULED: <2015-02-11 Wed ++1w>
SCHEDULED: <2015-02-12 Thu ++1w>
SCHEDULED: <2015-02-13 Fri ++1w>
Upvotes: 11