Hi,

Here is a proposal for a new interactive function `org-todo-at` that
lets the user supply the time to be used for logging and recurrence
timestamps.

This is useful to me in habit tracking and on projects where the log
must be correct. It's not easy to do as a local customization without
patching org.el, because the inner `org-todo` is not passed the current
time, but fetches it from `org-current-effective-time`.

I implemented this by adding a global variable that takes precedence in
`org-current-effective-time`, and then use that variable in a local
binding over the inner `org-todo` call.

Yours,

Sigve Indregard

>From 01d80b9844edd790182588f32cdb7bffeee46c27 Mon Sep 17 00:00:00 2001
From: Sigve Indregard <sigve.indreg...@protonmail.com>
Date: Sat, 16 Aug 2025 21:42:38 +0200
Subject: [PATCH] lisp/org.el: add `org-todo-at`

* org.el: `org-todo-at` lets the user specify a timestamp for todo
logging and recurrence.

Sometimes TODOs are updated at a later time than the actual
completion. For habit-trackers, pedants and those using org to bill
customers, the log must be correct. To avoid this, they can bind
`org-todo-at` to some key and be prompted for a time to use as the
logging and recurrence timestamp.

TINYCHANGE
---
 lisp/org.el | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/lisp/org.el b/lisp/org.el
index 21622523b..84f24949a 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -9462,9 +9462,12 @@ nil or a string to be used for the todo mark." )
 
 (defvar org-agenda-headline-snapshot-before-repeat)
 
+(defvar org-override-time nil
+  "Place for `org-todo-at` to store user-entered time.")
+
 (defun org-current-effective-time ()
-  "Return current time adjusted for `org-extend-today-until' variable."
-  (let* ((ct (org-current-time))
+  "Return current time adjusted for `org-extend-today-until' variable"
+  (let* ((ct (or org-override-time (org-current-time)))
 	 (dct (decode-time ct))
 	 (ct1
 	  (cond
@@ -9475,6 +9478,12 @@ nil or a string to be used for the todo mark." )
 	   (t ct))))
     ct1))
 
+(defun org-todo-at (&optional arg)
+  "Like `org-todo` but prompts the user for the time of change."
+  (interactive "P")
+  (let ((org-override-time (org-read-date :to_time t)))
+    (org-todo arg)))
+
 (defun org-todo-yesterday (&optional arg)
   "Like `org-todo' but the time of change will be 23:59 of yesterday."
   (interactive "P")
-- 
2.50.1

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to