fix: incorrect seconds value for month

This commit is contained in:
contrapunctus 2021-07-08 08:46:53 +05:30
parent 9b69bbec8e
commit f51ccf7333
2 changed files with 86 additions and 37 deletions

View File

@ -975,7 +975,7 @@ A month is assumed to be 30 days, and a year 365 days."
(defvar chronometrist--format-duration-code-alist
`(("Y" "year" ,(* 365 24 60 60))
("M" "month" ,(* 30 7 24 60 60))
("M" "month" ,(* 30 24 60 60))
("W" "week" ,(* 7 24 60 60))
("D" "day" ,(* 24 60 60))
("h" "hour" ,(* 60 60))
@ -985,6 +985,8 @@ A month is assumed to be 30 days, and a year 365 days."
(defun chronometrist-format-duration (format-string seconds)
(cl-loop with case-fold-search = nil
;; look for unit specifiers in format-string and replace them with
;; duration values and (maybe) unit strings
for (code unit divisor) in chronometrist--format-duration-code-alist do
(when-let* ((code-regex (rx-to-string
`(and (group-n 1 (or "~" "%")) ,code) t))
@ -997,8 +999,7 @@ A month is assumed to be 30 days, and a year 365 days."
("%" (format "%s %s" quotient unit)))))
(setq format-string (replace-regexp-in-string
code-regex replace format-string t)
seconds (if (zerop quotient)
0 (% seconds quotient))))
seconds (if (zerop quotient) 0 (% seconds divisor))))
finally return format-string))
(defcustom chronometrist-update-interval 5

View File

@ -1969,7 +1969,7 @@ A month is assumed to be 30 days, and a year 365 days."
#+BEGIN_SRC emacs-lisp
(defvar chronometrist--format-duration-code-alist
`(("Y" "year" ,(* 365 24 60 60))
("M" "month" ,(* 30 7 24 60 60))
("M" "month" ,(* 30 24 60 60))
("W" "week" ,(* 7 24 60 60))
("D" "day" ,(* 24 60 60))
("h" "hour" ,(* 60 60))
@ -1979,6 +1979,8 @@ A month is assumed to be 30 days, and a year 365 days."
(defun chronometrist-format-duration (format-string seconds)
(cl-loop with case-fold-search = nil
;; look for unit specifiers in format-string and replace them with
;; duration values and (maybe) unit strings
for (code unit divisor) in chronometrist--format-duration-code-alist do
(when-let* ((code-regex (rx-to-string
`(and (group-n 1 (or "~" "%")) ,code) t))
@ -1991,48 +1993,94 @@ A month is assumed to be 30 days, and a year 365 days."
("%" (format "%s %s" quotient unit)))))
(setq format-string (replace-regexp-in-string
code-regex replace format-string t)
seconds (if (zerop quotient)
0 (% seconds quotient))))
seconds (if (zerop quotient) 0 (% seconds divisor))))
finally return format-string))
#+END_SRC
**** tests
*****
#+BEGIN_SRC emacs-lisp :tangle chronometrist-tests.el :load test
(ert-deftest chronometrist-format-duration ()
(should (equal (chronometrist-format-duration "~Y" 0) "0"))
(should (equal (chronometrist-format-duration "~M" 0) "0"))
(should (equal (chronometrist-format-duration "~W" 0) "0"))
(should (equal (chronometrist-format-duration "~D" 0) "0"))
(should (equal (chronometrist-format-duration "~h" 0) "0"))
(should (equal (chronometrist-format-duration "~m" 0) "0"))
(should (equal (chronometrist-format-duration "~s" 0) "0"))
(let* ((one-hour (* 60 60))
(one-day (* 24 one-hour))
(one-week (* one-day 7))
(one-month (* one-day 30))
(one-year (* one-day 365)))
(should (equal (chronometrist-format-duration "~Y" 0) "0"))
(should (equal (chronometrist-format-duration "~M" 0) "0"))
(should (equal (chronometrist-format-duration "~W" 0) "0"))
(should (equal (chronometrist-format-duration "~D" 0) "0"))
(should (equal (chronometrist-format-duration "~h" 0) "0"))
(should (equal (chronometrist-format-duration "~m" 0) "0"))
(should (equal (chronometrist-format-duration "~s" 0) "0"))
(should (equal (chronometrist-format-duration "%Y" 0) "0 years"))
(should (equal (chronometrist-format-duration "%M" 0) "0 months"))
(should (equal (chronometrist-format-duration "%W" 0) "0 weeks"))
(should (equal (chronometrist-format-duration "%D" 0) "0 days"))
(should (equal (chronometrist-format-duration "%h" 0) "0 hours"))
(should (equal (chronometrist-format-duration "%m" 0) "0 minutes"))
(should (equal (chronometrist-format-duration "%s" 0) "0 seconds"))
(should (equal (chronometrist-format-duration "%Y" 0) "0 years"))
(should (equal (chronometrist-format-duration "%M" 0) "0 months"))
(should (equal (chronometrist-format-duration "%W" 0) "0 weeks"))
(should (equal (chronometrist-format-duration "%D" 0) "0 days"))
(should (equal (chronometrist-format-duration "%h" 0) "0 hours"))
(should (equal (chronometrist-format-duration "%m" 0) "0 minutes"))
(should (equal (chronometrist-format-duration "%s" 0) "0 seconds"))
(should (equal (chronometrist-format-duration "%Y" 1) "0 years"))
(should (equal (chronometrist-format-duration "%M" 1) "0 months"))
(should (equal (chronometrist-format-duration "%W" 1) "0 weeks"))
(should (equal (chronometrist-format-duration "%D" 1) "0 days"))
(should (equal (chronometrist-format-duration "%h" 1) "0 hours"))
(should (equal (chronometrist-format-duration "%m" 1) "0 minutes"))
(should (equal (chronometrist-format-duration "%s" 1) "1 second"))
(should (equal (chronometrist-format-duration "%Y" 1) "0 years"))
(should (equal (chronometrist-format-duration "%M" 1) "0 months"))
(should (equal (chronometrist-format-duration "%W" 1) "0 weeks"))
(should (equal (chronometrist-format-duration "%D" 1) "0 days"))
(should (equal (chronometrist-format-duration "%h" 1) "0 hours"))
(should (equal (chronometrist-format-duration "%m" 1) "0 minutes"))
(should (equal (chronometrist-format-duration "%s" 1) "1 second"))
;; ISO format
(should
(equal "P1Y1M1W1DT10H10M10S"
(chronometrist-format-duration "P%YY%MM%WW%DDT%hH%mM%sS"
(+ (* 365 24 3600)
(* 30 24 3600)
(* 7 24 3600)
(* 24 3600)
(* 10 3600)
(* 10 60) 10)))))
(should (equal (chronometrist-format-duration "%Y" 60) "0 years"))
(should (equal (chronometrist-format-duration "%M" 60) "0 months"))
(should (equal (chronometrist-format-duration "%W" 60) "0 weeks"))
(should (equal (chronometrist-format-duration "%D" 60) "0 days"))
(should (equal (chronometrist-format-duration "%h" 60) "0 hours"))
(should (equal (chronometrist-format-duration "%m" 60) "1 minute"))
(should (equal (chronometrist-format-duration "%s" 60) "60 seconds"))
(should (equal (chronometrist-format-duration "%Y" (* 60 60)) "0 years"))
(should (equal (chronometrist-format-duration "%M" (* 60 60)) "0 months"))
(should (equal (chronometrist-format-duration "%W" (* 60 60)) "0 weeks"))
(should (equal (chronometrist-format-duration "%D" (* 60 60)) "0 days"))
(should (equal (chronometrist-format-duration "%h" (* 60 60)) "1 hour"))
(should (equal (chronometrist-format-duration "%m" (* 60 60)) "60 minutes"))
(should (equal (chronometrist-format-duration "%s" (* 60 60)) "3600 seconds"))
(should (equal (chronometrist-format-duration "%Y" one-day) "0 years"))
(should (equal (chronometrist-format-duration "%M" one-day) "0 months"))
(should (equal (chronometrist-format-duration "%W" one-day) "0 weeks"))
(should (equal (chronometrist-format-duration "%D" one-day) "1 day"))
(should (equal (chronometrist-format-duration "%h" one-day) "24 hours"))
(should (equal (chronometrist-format-duration "%m" one-day) "1440 minutes"))
(should (equal (chronometrist-format-duration "%s" one-day) "86400 seconds"))
(should (equal (chronometrist-format-duration "%Y" one-week) "0 years"))
(should (equal (chronometrist-format-duration "%M" one-week) "0 months"))
(should (equal (chronometrist-format-duration "%W" one-week) "1 week"))
(should (equal (chronometrist-format-duration "%D" one-week) "7 days"))
(should (equal (chronometrist-format-duration "%h" one-week) "168 hours"))
(should (equal (chronometrist-format-duration "%m" one-week) "10080 minutes"))
(should (equal (chronometrist-format-duration "%s" one-week) "604800 seconds"))
;; multiple unit specifiers
;; ISO format - all units, no unit strings
(should
(equal "P1Y1M1W1DT10H10M10S"
(chronometrist-format-duration "P~YY~MM~WW~DDT~hH~mM~sS"
(+ one-year one-month
one-week one-day
(* 10 one-hour)
(* 10 60) 10))))
;; all units with unit strings
(should
(equal (chronometrist-format-duration "%Y, %M, %W, %D, %h, %m, and %s"
(+ one-year one-month
one-week one-day
(* 10 one-hour)
(* 10 60) 10))
"1 year, 1 month, 1 week, 1 day, 10 hours, 10 minutes, and 10 seconds"))))
#+END_SRC
** Timer
Instead of the Emacs convention of pressing ~g~ to update, we keep buffers updated with a timer.