Browse Source

org-clock: Simplify `untilnow' range logic

* lisp/org-clock.el (org-clock-special-range): Use nil to represent
* lisp/org-clock.el (org-clocktable-steps): For `untilnow' block, set
set timestamp to 2003.
* doc/ (The clock table): Document `untilnow' floor when
used with :step.

For `untilnow', org-clock-special-range sets the start to
"<-50001-11-30 Tue 00:00>", but org-parse-time-string actually assumes
a YYYY-MM-DD format and parses the year as 0001.  By chance, this is
still a really old date, so no one noticed.  However, with the port of
Emacs's fde99c729c (Port recent org-clock fix to POSIX time_t,
2018-03-28), test-org-clock/clocktable/ranges would fail if the system
supports the oldest date tried, "<-67715-09-22 Tue 17:51>".

But this "encode-time -> format-time-string -> org-parse-time-string"
dance is mostly unnecessary.  All the current org-clock-special-range
callers except for org-clocktable-steps (1) explicitly check if the
starting time is nil, (2) don't use the starting time, or (3) pass it
directly to org-clock-sum, which handles nil values.  And
org-clock-sum executes the same codepath when nil is passed instead of
"really old date".

Update org-clocktable-steps to use 2003 (the year Org was created) as
the starting point when org-clock-special-range returns nil for the
starting time.  This is more efficient because we don't needlessly
calculate steps over a large chunk of time that almost certainly
doesn't have any clocked time.  And it won't run into the portability
issues like Emacs's fde99c729c.  2003 _should_ be an appropriate
effective starting date, since we don't expect clocked time before the
existence of Org.  If this turns out to be an issue (e.g., someone
converted reports from a pre-Org and still makes clock tables that
include those times), we can make this value configurable.
Kyle Meyer 1 year ago
2 changed files with 172 additions and 168 deletions
  1. 165 162
  2. 7 6

File diff suppressed because it is too large
+ 165 - 162

+ 7 - 6

@@ -2128,7 +2128,8 @@ The return value is a list containing two internal times, one for
 the beginning of the range and one for its end, like the ones
 returned by `current-time' or `encode-time' and a string used to
 display information.  If AS-STRINGS is non-nil, the returned
-times will be formatted strings.
+times will be formatted strings.  Note that the first element is
+always nil when KEY is `untilnow'.
 If WSTART is non-nil, use this number to specify the starting day
 of a week (monday is 1).  If MSTART is non-nil, use this number
@@ -2245,9 +2246,7 @@ have priority."
     ;; Format start and end times according to AS-STRINGS.
     (let* ((start (pcase key
 		    (`interactive (org-read-date nil t nil "Range start? "))
-                    ;; In theory, all clocks started after the dawn of
-                    ;; humanity.
-		    (`untilnow (encode-time 0 0 0 0 0 -50000))
+		    (`untilnow nil)
 		    (_ (encode-time 0 m h d month y))))
 	   (end (pcase key
 		  (`interactive (org-read-date nil t nil "Range end? "))
@@ -2271,7 +2270,7 @@ have priority."
 	      (`untilnow "now"))))
       (if (not as-strings) (list start end text)
 	(let ((f (cdr org-time-stamp-formats)))
-	  (list (format-time-string f start)
+	  (list (and start (format-time-string f start))
 		(format-time-string f end)
@@ -2707,7 +2706,9 @@ The TS argument has the same type as the return values of
 	 cc tsb)
     (when block
       (setq cc (org-clock-special-range block nil t ws ms)
-	    ts (car cc)
+	    ts (or (car cc)
+		   ;; The year Org was born.
+		   "<2003-01-01 Thu 00:00>")
 	    te (nth 1 cc)))
      ((numberp ts)