Is it possible to refile a dated item into the appropriate place in a datetree?

I have seen some posts that describe the use of org-archive-location but I cannot get that to work - perhaps its the wrong thing to use?

  • Maybe I don't understand your question correctly, but have you tried org-refile? I use it all the time with datetrees as targets.
    – Brian Z
    Apr 10 '15 at 0:56
  • 1
    This question was asked on Stack Overflow. Maybe one of those answer will work for you?
    – erikstokes
    Apr 10 '15 at 1:06
  • What's the date on the item? There can be several types -- timestamp, schedule, deadline.
    – sanityinc
    Apr 10 '15 at 8:39
  • @sanityinc something like [2015-03-17 Tue 21:32] Apr 10 '15 at 20:38
  • @erikstokes that might do it - I'll try it, thanks. Apr 10 '15 at 20:40

I posted a previous version of this code to answer a similar question on Stack Overflow. This version is slightly imporoved.

You can select a file to refile into and if the entry has no timestamp, the current date is used.

(defun org-refile-to-datetree (&optional file)
  "Refile a subtree to a datetree corresponding to it's timestamp.

The current time is used if the entry has no timestamp. If FILE
is nil, refile in the current file."
  (interactive "f")
  (let* ((datetree-date (or (org-entry-get nil "TIMESTAMP" t)
                            (org-read-date t nil "now")))
         (date (org-date-to-gregorian datetree-date))
    (with-current-buffer (current-buffer)
        (if file (find-file file))
        (org-datetree-find-date-create date)
        (org-end-of-subtree t)
        (goto-char (point-max))
        (org-paste-subtree 4)

Edit: According to the manual save-excursion should be used within with-current-buffer to avoid certain side-effects.

  • Excellent! Thank you very much! Helped me a lot.
    – Ugur
    Nov 24 '20 at 10:21
  • This code is very useful! :) I am just wondering, why do you need (show-subtree) after (org-narrow-to-subtree)? Also, why do you need (goto-char (point-max)) after (newline)? Jul 17 '21 at 16:04

The accepted answer is likely to work, but misses some things. In particular, since it does the refiling itself, it won't trigger the actions from org-log-refile and the like.

Based in part on some other code from a site I now can't find, I put together the following:

(defun my/org-read-datetree-date (d)
  "Parse a time string D and return a date to pass to the datetree functions."
  (let ((dtmp (nthcdr 3 (parse-time-string d))))
    (list (cadr dtmp) (car dtmp) (caddr dtmp))))

(defun my/org-refile-to-archive-datetree ()
  "Refile an entry to a datetree under an archive."
  (require 'org-datetree)
  (let ((datetree-date (my/org-read-datetree-date (org-read-date t nil))))
    (org-refile nil nil (list nil (buffer-file-name) nil
                                (org-datetree-find-date-create datetree-date)))))
  (setq this-command 'my/org-refile-to-journal))

This passes the target location to org-refile itself, which can thus do the correct subsidiary processing. My particular setup is to refile to an archive in the same file, which has a DATE_TREE property in order to cause the datetree functions to work underneath it. If you want to specify a file, you can wrap the call in with-current-buffer and use find-file inside.

  • thanks. When I refile using my/org-refile-to-archive-datetree, though, the heading is not refiled as a child of the datetree, but as a top-level heading directly below the new date entry...do you have any suggestions?
    – Henry
    Jan 11 '18 at 14:45
  • Because of a version change since the original answer, I have modified the function as follows: (defun org-read-datetree-date (d) "Parse a time string D and return a date to pass to the datetree functions." (let ((dtmp (nthcdr 3 (parse-time-string d)))) (list (cadr dtmp) (car dtmp) (caddr dtmp))))
    – Henry
    Jan 16 '18 at 19:44

The previous answer by Tom Hunt is almost ok, but org-refile needs both the file and the position in the file as the rfloc argument. Unfortunately, org-datetree-find-date-create does not return this position. (Is it something that changed in recent versions of Org mode?) So here is a slightly enhanced version of the same function:

(defun my/org-refile-to-archive-datetree (&optional bfn)
  "Refile an entry to a datetree under an archive."
  (require 'org-datetree)
  (let* ((bfn (or bfn (find-file-noselect (expand-file-name "~/Org/Diary.org"))))
         (datetree-date (my/org-read-datetree-date (org-read-date t nil))))
    (org-refile nil nil (list nil (buffer-file-name bfn) nil
                              (with-current-buffer bfn
                                  (org-datetree-find-date-create datetree-date)
  (setq this-command 'my/org-refile-to-journal))

I added an optional buffer-file-name argument and as a default value, I am using my ~/Org/Diary.org journal file.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.