diff --git a/lisp/calendar/time-date.el b/lisp/calendar/time-date.el index 09b4cfb0edf..1d792952f98 100644 --- a/lisp/calendar/time-date.el +++ b/lisp/calendar/time-date.el @@ -305,7 +305,7 @@ right of \"%x\", trailing zero units are not output." ("x"))) (case-fold-search t) spec match usedunits zeroflag larger prev name unit num - leading-zeropos trailing-zeropos fraction + leading-zeropos trailing-zeropos fraction minus chop-leading chop-trailing) (while (string-match "%\\.?[0-9]*\\(,[0-9]\\)?\\(.\\)" string start) (setq start (match-end 0) @@ -327,8 +327,11 @@ right of \"%x\", trailing zero units are not output." (error "Units are not in decreasing order of size")) (unless (numberp seconds) (setq seconds (float-time seconds))) - (setq fraction (mod seconds 1) - seconds (round seconds)) + (setq minus (when (< seconds 0) "-") ; Treat -0.0 like 0.0. + seconds (abs seconds) + seconds (let ((s (floor seconds))) + (setq fraction (- seconds s)) + s)) (dolist (u units) (setq spec (car u) name (cadr u) @@ -392,8 +395,8 @@ right of \"%x\", trailing zero units are not output." ;; string in full. (when (equal string "") (setq string pre))) - (setq string (replace-regexp-in-string "%[zx]" "" string))) - (string-trim (string-replace "%%" "%" string))) + (setq string (replace-regexp-in-string "%[zx]" "" string)) + (concat minus (string-trim (string-replace "%%" "%" string))))) (defvar seconds-to-string (list (list 1 "ms" 0.001) diff --git a/test/lisp/calendar/time-date-tests.el b/test/lisp/calendar/time-date-tests.el index 3a69a0c7b18..b8d3381528e 100644 --- a/test/lisp/calendar/time-date-tests.el +++ b/test/lisp/calendar/time-date-tests.el @@ -106,24 +106,31 @@ (should-error (date-days-in-month 2020 'foo))) (ert-deftest test-format-seconds () - (should (equal (format-seconds "%y %d %h %m %s %%" 0) "0 0 0 0 0 %")) - (should (equal (format-seconds "%y %d %h %m %s %%" 9999999) "0 115 17 46 39 %")) - (should (equal (format-seconds "%y %d %h %m %z %s %%" 1) "1 %")) - (should (equal (format-seconds "%mm %ss" 66) "1m 6s")) - (should (equal (format-seconds "%mm %5ss" 66) "1m 6s")) - (should (equal (format-seconds "%mm %.5ss" 66.4) "1m 00006s")) - - (should (equal (format-seconds "%mm %,1ss" 66.4) "1m 6.4s")) - (should (equal (format-seconds "%mm %5,1ss" 66.4) "1m 6.4s")) - (should (equal (format-seconds "%mm %.5,1ss" 66.4) "1m 006.4s")) - - (should (equal (format-seconds "%hh %z%x%mm %ss" (* 60 2)) "2m")) - (should (equal (format-seconds "%hh %z%mm %ss" (* 60 2)) "2m 0s")) - (should (equal (format-seconds "%hh %x%mm %ss" (* 60 2)) "0h 2m")) - (should (equal (format-seconds "%hh %x%mm %ss" 0) "0h 0m 0s")) - ;; Bug#70322 - (should (equal (format-seconds "%y %z%d %h %m %s %%" 9999999) "115 17 46 39 %")) - (should (equal (format-seconds "%Y, %D, %H, %M, %z%S" 0) "0 seconds"))) + (let ((format-seconds-list + '(("%y %d %h %m %s %%" 0 "0 0 0 0 0 %") + ("%y %d %h %m %s %%" 0 "0 0 0 0 0 %") + ("%y %d %h %m %s %%" 9999999 "0 115 17 46 39 %") + ("%y %d %h %m %z %s %%" 1 "1 %") + ("%mm %ss" 66 "1m 6s") + ("%mm %5ss" 66 "1m 6s") + ("%mm %.5ss" 66.4 "1m 00006s") + ("%mm %,1ss" 66.4 "1m 6.4s") + ("%mm %5,1ss" 66.4 "1m 6.4s") + ("%mm %.5,1ss" 66.4 "1m 006.4s") + ("%hh %z%x%mm %ss" 120 "2m") + ("%hh %z%mm %ss" 120 "2m 0s") + ("%hh %x%mm %ss" 120 "0h 2m") + ("%hh %x%mm %ss" 0 "0h 0m 0s") + ("%y %z%d %h %m %s %%" 9999999 "115 17 46 39 %") + ("%Y, %D, %H, %M, %z%S" 0 "0 seconds")))) + (dolist (fs format-seconds-list) + (let ((string (nth 0 fs)) + (seconds (nth 1 fs)) + (expected (nth 2 fs))) + (should (equal (format-seconds string seconds) expected)) + (when (< 0 seconds) + (should (equal (format-seconds string (- seconds)) + (concat "-" expected)))))))) (ert-deftest test-ordinal () (should (equal (date-ordinal-to-time 2008 271)