This way I get the error Invalid time specification
.
OK. Maybe I need to encode times first:
Indeed.
Now I get the error Wrong type argument: fixnump, nil
.
This is because parse-time-string
is documented as returning nil
for unknown entries, such as those for the date (emphasis mine):
parse-time-string is a compiled Lisp function in `parse-time.el'.
(parse-time-string STRING)
Probably introduced at or before Emacs version 27.1.
Parse the time in STRING into (SEC MIN HOUR DAY MON YEAR DOW DST TZ).
STRING should be an ISO 8601 time string, e.g., "2020-01-15T16:12:21-08:00",
or something resembling an RFC 822 (or later) date-time, e.g.,
"Wed, 15 Jan 2020 16:12:21 -0800". This function is
somewhat liberal in what format it accepts, and will attempt to
return a "likely" value even for somewhat malformed strings.
The values returned are identical to those of `decode-time', but
any unknown values other than DST are returned as nil, and an
^^^^^^^^^^^^^^^
unknown DST value is returned as -1.
For example:
(parse-time-string "12:04")
;; => (0 4 12 nil nil nil nil -1 nil)
This result cannot be handled directly by other time functions, so those nil
s need filling in. Emacs 27 introduced the handy utility function decoded-time-set-defaults
for this purpose:
decoded-time-set-defaults is a compiled Lisp function in `time-date.el'.
(decoded-time-set-defaults TIME &optional DEFAULT-ZONE)
Set any nil values in `decoded-time' TIME to default values.
The default value is based on January 1st, 1970 at midnight.
TIME is modified and returned.
Behold:
(decoded-time-set-defaults (parse-time-string "12:04"))
;; => (0 4 12 1 1 0 nil -1 nil)
Putting it all together (note that the new calling convention of encode-time
accepts a decoded time as a single list argument):
(require 'time-date)
(defun my-mins-between (time1 time2)
"Return the minutes between HH:mm strings TIME1 and TIME2."
(let ((diff (apply #'time-subtract
(mapcar (lambda (time)
(encode-time (decoded-time-set-defaults
(parse-time-string time))))
(list time1 time2)))))
(/ (float-time diff) 60)))
(my-mins-between "12:04" "11:30")
;; => 34.0
Or you can declare technical bankruptcy and rely on Org parsing functions instead. Since Org 9.1:
(- (org-duration-to-minutes "12:04")
(org-duration-to-minutes "11:30"))
;; => 34.0
In older Org versions:
(- (org-hh:mm-string-to-minutes "12:04")
(org-hh:mm-string-to-minutes "11:30"))
;; => 34
(- (org-duration-string-to-minutes "12:04")
(org-duration-string-to-minutes "11:30"))
;; => 34
References