Rewrite timestamps in Org-export
August 29, 2023
While making figuring out how much running I’ve done this summer, I realized that I wanted to gussy up the way that published timestamps look. The way it looks in Emacs is more like this:
| Date | Distance (km) | Time | Minutes | Pace (min/km) |
|------------------+---------------+----------+---------+---------------|
| [2023-07-22 Sat] | 12.93 | 01:30:31 | 90.52 | 7.0 |
| [2023-06-17 Sat] | 13.40 | 01:11:58 | 71.97 | 5.4 |
| [2023-06-10 Sat] | 17.52 | 01:58:23 | 118.38 | 6.8 |
#+TBLFM: $4='(org-duration-to-minutes $3);%.2f::$5='(/ $4 $2);%.1fN
I want to keep those in the actual file, but maybe make them look nicer for humans when I export it. I use ox-hugo and Org-mode’s built-in publish so I can use a convenient feature, org-export-filter-timestamp-functions
. It’s a list of functions to run specifically on timestamps on export, so that seems remarkably convenient.
(with-eval-after-load 'ox
(require 'ox-icalendar)
(add-to-list 'org-export-filter-timestamp-functions
#'env-filter-timestamp))
I started by adding a custom function to org-export-filter-timestamp-functions
which I’ll set up now.
(defun env-filter-timestamp (string _backend _comm)
"Remove [<>] around time-stamps from STRING.
I actually don't know what _COMM is. BACKEND is the type of
conversion we're doing, in this case either some form of
HTML/Markdown or LaTeX. The filter receives the entire output
timestamp as STRING and then processes it before saving."
(if (string-match-p ":" string)
(format-time-string "%A, %B %-e, %Y at %H:%M"
(org-time-string-to-time string))
(format-time-string "%A, %B %-e, %Y"
(org-time-string-to-time string))))
The function which I’m calling env-filter-timestamp
takes three things, a string which is timestamp from the Org file, the output backend such as Markdown, HTML or Hugo, and something called a communication channel plist. No idea what that is.
I’m not sure if there’s a better way to figure out if the timestamp has an actual time in it. I tried the function org-timestamp-has-time-p
but it didn’t work the way I wanted, so I just look to see if there’s a colon that must be present as the HH:MM separator. Emacs time conversion does not make sense to me, so I use Org’s system. That’s not an issue here as I can rely on it existing. It’s pretty easy to make work; format-time-string
requires time in the form of (TICKS . HZ)
which is what the function org-times-string-to-time
provides. So it’s easy to format the time any way I want here. And look at how nice it came out (this is a copy-paste from above):
Date | Distance (km) | Time | Minutes | Pace (min/km) |
---|---|---|---|---|
Saturday, July 22, 2023 | 12.93 | 01:30:31 | 90.52 | 7.0 |
Saturday, June 17, 2023 | 13.40 | 01:11:58 | 71.97 | 5.4 |
Saturday, June 10, 2023 | 17.52 | 01:58:23 | 118.38 | 6.8 |
See? That’s great!