aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJD Smith2024-07-11 16:24:17 -0400
committerEli Zaretskii2024-12-21 12:29:54 +0200
commit308d5d54737917d449bfc0bf80815537eef69446 (patch)
treeb56e09ab5290ed940b54de1be5abeff1be0d1a5f
parentbf41ff24b9ab9c7426b3b3f1c1902b301e9f08a4 (diff)
downloademacs-308d5d54737917d449bfc0bf80815537eef69446.tar.gz
emacs-308d5d54737917d449bfc0bf80815537eef69446.zip
'seconds-to-string': new optional arguments for readable strings
* lisp/calendar/time-date.el (seconds-to-string): Accept new optional arguments READABLE, ABBREV, and PRECISION, and format the output string accordingly. (Bug#71572) * doc/lispref/os.texi (Time Calculations): * etc/NEWS: Document the new arguments of 'seconds-to-string'.
-rw-r--r--doc/lispref/os.texi6
-rw-r--r--etc/NEWS12
-rw-r--r--lisp/calendar/time-date.el82
3 files changed, 94 insertions, 6 deletions
diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi
index be26fb5063c..a3ba27bdf24 100644
--- a/doc/lispref/os.texi
+++ b/doc/lispref/os.texi
@@ -2204,6 +2204,12 @@ Return the date of @var{ordinal} in @var{year} as a decoded time
2204structure. For instance, the 120th day in 2004 is April 29th. 2204structure. For instance, the 120th day in 2004 is April 29th.
2205@end defun 2205@end defun
2206 2206
2207@defun seconds-to-string delay &optional readable abbrev precision
2208Return a string describing a given @var{delay} (in seconds). Optional
2209arguments can be used to configure a human readable delay using various
2210formats. For example, a delay of 9861.5 seconds with @var{readable} set
2211to the symbol @code{expanded} returns @samp{2 hours 44 minutes}.
2212
2207@node Timers 2213@node Timers
2208@section Timers for Delayed Execution 2214@section Timers for Delayed Execution
2209@cindex timers 2215@cindex timers
diff --git a/etc/NEWS b/etc/NEWS
index 9a7b320acdb..5b0c89b6b20 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -883,6 +883,9 @@ destination window is chosen using 'display-buffer-alist'. Example:
883 883
884** Nested backquotes are not supported any more in Pcase patterns. 884** Nested backquotes are not supported any more in Pcase patterns.
885 885
886---
887** The obsolete variable `redisplay-dont-pause' has been removed.
888
886** The 'rx' category name 'chinese-two-byte' must now be spelled correctly. 889** The 'rx' category name 'chinese-two-byte' must now be spelled correctly.
887An old alternative name (without the first 'e') has been removed. 890An old alternative name (without the first 'e') has been removed.
888 891
@@ -919,8 +922,13 @@ restore the old behavior, you can set 'eshell-pwd-convert-function' to
919 922
920* Lisp Changes in Emacs 31.1 923* Lisp Changes in Emacs 31.1
921 924
922--- 925** Time & Date
923** The obsolete variable `redisplay-dont-pause' has been removed. 926
927+++
928*** 'seconds-to-string' supports new formatting options.
929Optional arguments are provided to produce human-readable time-duration
930strings in a variety of formats, for example "6 months 3 weeks" or "5m
93152.5s".
924 932
925** New function 'native-compile-directory'. 933** New function 'native-compile-directory'.
926This function natively-compiles all Lisp files in a directory and in its 934This function natively-compiles all Lisp files in a directory and in its
diff --git a/lisp/calendar/time-date.el b/lisp/calendar/time-date.el
index 9a2fb45e3bc..9b85acf1dd0 100644
--- a/lisp/calendar/time-date.el
+++ b/lisp/calendar/time-date.el
@@ -403,11 +403,85 @@ right of \"%x\", trailing zero units are not output."
403 (list (* 3600 24 400) "d" (* 3600.0 24.0)) 403 (list (* 3600 24 400) "d" (* 3600.0 24.0))
404 (list nil "y" (* 365.25 24 3600))) 404 (list nil "y" (* 365.25 24 3600)))
405 "Formatting used by the function `seconds-to-string'.") 405 "Formatting used by the function `seconds-to-string'.")
406
407(defvar seconds-to-string-readable
408 `(("Y" "year" "years" ,(round (* 60 60 24 365.2425)))
409 ("M" "month" "months" ,(round (* 60 60 24 30.436875)))
410 ("w" "week" "weeks" ,(* 60 60 24 7))
411 ("d" "day" "days" ,(* 60 60 24))
412 ("h" "hour" "hours" ,(* 60 60))
413 ("m" "minute" "minutes" 60)
414 ("s" "second" "seconds" 1))
415 "Formatting used by the function `seconds-to-string' with READABLE set.
416The format is an alist, with string keys ABBREV-UNIT, and elements like:
417
418 (ABBREV-UNIT UNIT UNIT-PLURAL SECS)
419
420where UNIT is a unit of time, ABBREV-UNIT is the abreviated form of
421UNIT, UNIT-PLURAL is the plural form of UNIT, and SECS is the number of
422seconds per UNIT.")
423
406;;;###autoload 424;;;###autoload
407(defun seconds-to-string (delay) 425(defun seconds-to-string (delay &optional readable abbrev precision)
408 ;; FIXME: There's a similar (tho fancier) function in mastodon.el! 426 "Convert time interval DELAY (in seconds) to a string.
409 "Convert the time interval in seconds to a short string." 427By default, the returned string is formatted as a float in the smallest
410 (cond ((> 0 delay) (concat "-" (seconds-to-string (- delay)))) 428unit from the variable `seconds-to-string' that is longer than DELAY,
429and a precision of two. If READABLE is non-nil, convert DELAY into a
430readable string, using the information provided in the variable
431`seconds-to-string-readable'. If it is the symbol `expanded', use two
432units to describe DELAY, if appropriate. E.g. \"1 hour 32 minutes\".
433If ABBREV is non-nil, abbreviate the readable units. If PRECISION is a
434whole number, round the value associated with the smallest displayed
435unit to that many digits after the decimal. If it is a non-negative
436float less than 1.0, round to that value."
437 (cond ((< delay 0)
438 (concat "-" (seconds-to-string (- delay) readable precision)))
439 (readable
440 (let* ((stsa seconds-to-string-readable)
441 (expanded (eq readable 'expanded))
442 digits
443 (round-to (cond ((wholenump precision)
444 (setq digits precision)
445 (expt 10 (- precision)))
446 ((and (floatp precision) (< precision 1.))
447 (setq digits (- (floor (log precision 10))))
448 precision)
449 (t (setq digits 0) 1)))
450 (dformat (if (> digits 0) (format "%%0.%df" digits)))
451 (padding (if abbrev "" " "))
452 here cnt cnt-pre here-pre cnt-val isfloatp)
453 (if (= (round delay round-to) 0)
454 (format "0%s" (if abbrev "s" " seconds"))
455 (while (and (setq here (pop stsa)) stsa
456 (< (/ delay (nth 3 here)) 1)))
457 (or (and
458 expanded stsa ; smaller unit remains
459 (progn
460 (setq
461 here-pre here here (car stsa)
462 cnt-pre (floor (/ (float delay) (nth 3 here-pre)))
463 cnt (round
464 (/ (- (float delay) (* cnt-pre (nth 3 here-pre)))
465 (nth 3 here))
466 round-to))
467 (if (> cnt 0) t (setq cnt cnt-pre here here-pre here-pre nil))))
468 (setq cnt (round (/ (float delay) (nth 3 here)) round-to)))
469 (setq cnt-val (* cnt round-to)
470 isfloatp (and (> digits 0)
471 (> (- cnt-val (floor cnt-val)) 0.)))
472 (cl-labels
473 ((unit (val here &optional plural)
474 (cond (abbrev (car here))
475 ((and (not plural) (<= (floor val) 1)) (nth 1 here))
476 (t (nth 2 here)))))
477 (concat
478 (when here-pre
479 (concat (number-to-string cnt-pre) padding
480 (unit cnt-pre here-pre) " "))
481 (if isfloatp (format dformat cnt-val)
482 (number-to-string (floor cnt-val)))
483 padding
484 (unit cnt-val here isfloatp)))))) ; float formats are always plural
411 ((= 0 delay) "0s") 485 ((= 0 delay) "0s")
412 (t (let ((sts seconds-to-string) here) 486 (t (let ((sts seconds-to-string) here)
413 (while (and (car (setq here (pop sts))) 487 (while (and (car (setq here (pop sts)))