Strona domowa

Witam na mojej prywatnej stronie internetowej!

[If this is all Polish to you, click here: English]

Uwaga: z oczywistych powodów nie mogę zagwarantować swojej nieomylności, choć staram się o zgodność tego, co piszę, z Prawdą. Jest również oczywiste, że nie gwarantuję takiej zgodności w przypadku komentarzy. Umieszczenie linku do strony spoza niniejszego serwisu nie musi oznaczać, że podzielam poglądy autora tej strony, a jedynie, że uważam ją za wartościową z takich czy innych powodów.

Marcin ‘mbork’ Borkowski

2025-09-22 Faking today's date in Org

A long time ago I wrote about the datefudge tool, which can be very useful to test time-related code (not only in Elisp). Today I’m going to write about another way of solving a similar problem.

I am currently building (yet another) tool on top of Org mode. This tool heavily uses the notion of “today”. I made a conscious effort to always use the org-today function to get today’s date, precisely because I want to be able to mock it for tests.

However, writing automated tests is one thing, and testing stuff manually while developing it is another – both have their place. I thought that it would be pretty cool if I could interactively make org-today return any given date, so that I’d be able to test things quickly.

One thing that bothers me is this. Assuming I write an interactive wrapper around (advice-add 'org-today :override ...), how do I make sure I won’t forget to remove that advice?

And then, an idea occurred to me. I could (again!) write my own version of execute-extended-command which would first ask for a date (using org-read-date, of course) and then run the given command with org-today advised.

;;; -*- lexical-binding: t -*-

(defun org-fake-today--create-advice (fake-date)
  "Return the function used to advise `org-today'."
  (lambda () fake-date))

(defun org-fake-today-execute-command (prefix-arg)
  "Execute a command with `org-today' temporarily advised.
First ask the user for the date."
  (interactive "P")
  (advice-add
   'org-today
   :override (org-fake-today--create-advice
              (time-to-days
               (org-read-date nil t)))
   '((name . org-fake-today)))
  (execute-extended-command prefix-arg)
  (advice-remove 'org-today 'org-fake-today))

(global-set-key (kbd "C-s-X") #'org-fake-today-execute-command)

Note the comment setting lexical-binding to t in the first line – we need the value returned from org-fake-today--create-advice to be a closure which will take the place of org-today. This means that the above snippet needs to be in a file on its own – or a part of a file where lexical binding is on.

And now I can say, for example, this: C-s-X -7 RET org-agenda RET a and see the agenda as it had been shown a week ago. How cool is that?

CategoryEnglish, CategoryBlog, CategoryEmacs, CategoryOrgMode

Comments on this page

More...