From 8fdcca3f3b0cf3e890149eb79ea6c7970b7d2cfa 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 (org-test-with-timezone): New macro to ensure that some code is executed with or without daylight saving time or other time shifts by setting certain TZ environment value. * 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 | 56 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/lisp/org-macs.el b/lisp/org-macs.el index a09115e7c..85dd20028 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 ,@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..aa3f9a3f6 100644 --- a/testing/lisp/test-org.el +++ b/testing/lisp/test-org.el @@ -24,6 +24,20 @@ (eval-and-compile (require 'cl-lib)) + +;;; Helpers + +(defmacro org-test-with-timezone (tz &rest body) + "Evaluate BODY with TZ environment temporary set to the passed value." + (declare (indent 1)) + (org-with-gensyms (tz-saved) + `(let ((,tz-saved (getenv "TZ"))) + (unwind-protect + (progn + (setenv "TZ" ,tz) + ,@body) + (setenv "TZ" ,tz-saved))))) + ;;; Comments @@ -179,6 +193,48 @@ ;;; Date and time analysis +(ert-deftest test-org/org-encode-time () + "Test various ways to call `org-encode-time'" + (org-test-with-timezone "UTC" + ;; list as the sole argument + (should (string-equal + "2022-03-24 23:30:01" + (format-time-string + "%F %T" + (org-encode-time '(1 30 23 24 3 2022 nil -1 nil))))) + ;; SECOND...YEAR + (should (string-equal + "2022-03-24 23:30:02" + (format-time-string + "%F %T" + (org-encode-time 2 30 23 24 3 2022)))) + ;; SECOND...YEAR IGNORED DST ZONE + (should (string-equal + "2022-03-24 23:30:03" + (format-time-string + "%F %T" + (org-encode-time 3 30 23 24 3 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 4 30 23 '(24 3 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 5 30 23 24 3 2022 nil)))))) + ;; daylight saving time + (org-test-with-timezone "Europe/Madrid" + (should (string-equal + "2022-03-31 23:30:06" + (format-time-string + "%F %T" + (org-encode-time 6 30 23 31 3 2022)))))) + (ert-deftest test-org/org-read-date () "Test `org-read-date' specifications." ;; Parse ISO date with abbreviated year and month. -- 2.25.1