From e330999cefe40d6d9a2f25abfd48b1f332b3688d Mon Sep 17 00:00:00 2001 From: Max Nikulin Date: Fri, 8 Apr 2022 23:10:50 +0700 Subject: [PATCH] org-macs.el: Introduce a helper for `encode-time' * lisp/org-macs.el (org-encode-time): New compatibility and convenience helper macro to allow a list for time components or separate arguments independently of Emacs version. * testing/lisp/test-org.el (test-org/org-encode-time): Tests for various ways to call `org-encode-time'. Ensure recommended way to call `encode-time' for Emacs-27 and newer with hope to avoid bugs due to attempts to modernize the code similar to bug#54731. --- lisp/org-macs.el | 20 ++++++++++++++++++ testing/lisp/test-org.el | 45 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/lisp/org-macs.el b/lisp/org-macs.el index a09115e7c..7e8c23d09 100644 --- a/lisp/org-macs.el +++ b/lisp/org-macs.el @@ -1225,6 +1225,26 @@ nil, just return 0." (b (org-2ft b))) (and (> a 0) (> b 0) (\= a b)))) +(if (version< emacs-version "27.1") + (defmacro org-encode-time (&rest time) + (if (cdr time) + `(encode-time ,@time) + `(apply #'encode-time ,(car time)))) + (defmacro org-encode-time (&rest time) + (pcase (length time) + (1 `(encode-time ,(car time))) + (6 `(encode-time (list ,@time nil -1 nil))) + (9 `(encode-time (list ,@time))) + (_ (error "`org-encode-time' may be called with 1, 6, or 9 arguments but %d given" + (length time)))))) +(put 'org-encode-time 'function-documentation + "Compatibility and convenience helper for `encode-time'. +May be called with 9 components list (SECONDS ... YEAR IGNORED DST ZONE) +as the recommended way since Emacs-27 or with 6 or 9 separate arguments +similar to the only possible variant for Emacs-26 and earlier. +Warning: use -1 for DST that means guess actual value, nil means no +daylight saving time and may be wrong at particular time.") + (defun org-parse-time-string (s &optional nodefault) "Parse Org time string S. diff --git a/testing/lisp/test-org.el b/testing/lisp/test-org.el index 6aecc3af8..a0ed36362 100644 --- a/testing/lisp/test-org.el +++ b/testing/lisp/test-org.el @@ -179,6 +179,51 @@ ;;; Date and time analysis +(ert-deftest test-org/org-encode-time () + "Test various ways to call `org-encode-time'" + ;; list as the sole argument + (should (string-equal + "2022-03-24 23:30:01" + (format-time-string + "%F %T" + (org-encode-time '(01 30 23 24 03 2022 nil -1 nil))))) + ;; SECOND...YEAR + (should (string-equal + "2022-03-24 23:30:02" + (format-time-string + "%F %T" + (org-encode-time 02 30 23 24 03 2022)))) + ;; SECOND...YEAR IGNORED DST ZONE + (should (string-equal + "2022-03-24 23:30:03" + (format-time-string + "%F %T" + (org-encode-time 03 30 23 24 03 2022 nil -1 nil)))) + ;; function call + (should (string-equal + "2022-03-24 23:30:04" + (format-time-string + "%F %T" + (org-encode-time (apply #'list 04 30 23 '(24 03 2022 nil -1 nil)))))) + ;; wrong number of arguments + (if (not (version< emacs-version "27.1")) + (should-error (string-equal + "2022-03-24 23:30:05" + (format-time-string + "%F %T" + (org-encode-time 05 30 23 24 03 2022 nil))))) + ;; daylight saving time + (let ((tz (getenv "TZ"))) + (unwind-protect + (progn + (setenv "TZ" "Europe/Madrid") + (should (string-equal + "2022-03-31 23:30:06" + (format-time-string + "%F %T" + (org-encode-time 06 30 23 31 03 2022))))) + (setenv "TZ" tz)))) + (ert-deftest test-org/org-read-date () "Test `org-read-date' specifications." ;; Parse ISO date with abbreviated year and month. -- 2.25.1