When try to print timedelta as below:

#+BEGIN_SRC elisp :results output
(print (time-subtract
    (parse-time-string "2018-10-20 08:50:36.343")
    (parse-time-string "2018-10-20 08:47:43.029")))

: (-7 3 0 0)

The output format looks wired:

  1. The seconds is negative.
  2. Output format not readable, I wish it's "00:02:53.314".
  • parse-time-string will decode integer seconds, so you'll need to parse fractional seconds separately.
    – Juancho
    Commented Oct 20, 2018 at 16:47
  • 1
    I think you want to feed those values to format-time-string.
    – wvxvw
    Commented Oct 21, 2018 at 13:04

2 Answers 2


#'time-subtract's docstring says "See ‘current-time-string’ for the various forms of a time value." #'current-time-string specifies times to be in this format:

If SPECIFIED-TIME is given, it is a time to format instead of the current time. The argument should have the form (HIGH LOW . IGNORED).

However, #'parse-time-string says this:

Parse the time-string STRING into (SEC MIN HOUR DAY MON YEAR DOW DST TZ).

So one shouldn't pass this value into #'time-subtract. But there is #'date-to-time:

ELISP> (date-to-time "2018-10-20 08:50:36.343")
(23499 9372)

And we can pass these values to #'time-subtract:

ELISP> (time-subtract (date-to-time "2018-10-20 08:50:36.343") 
                      (date-to-time "2018-10-20 08:47:43.029"))
(0 173)

This makes sense; 8:50:36 is exactly 173 seconds after 8:47:43! Cool! Note that this throws away the milliseconds in the timestamps. This is a limitation of how Emacs deals with time.

Now let's get it into the output format you want: 00:02:53.314. We can use #'format-time-string to do so:

ELISP> (format-time-string "%H:%M:%S"
                           (time-subtract (date-to-time "2018-10-20 08:50:36.343")
                                          (date-to-time "2018-10-20 08:47:43.029"))

Note that you have to give the third argument ZONE to #'format-time-string, or it will format it in your local time zone. Passing t there formats it in UTC. This is definitely confusing.


That way it seems to produce something reasonable:

#+BEGIN_SRC elisp :results output
(print (time-subtract
    (parse-iso8601-time-string "2018-10-20 08:50:36")
    (parse-iso8601-time-string "2018-10-20 08:47:43")))


: : (0 173)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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