From 1007a7987451ece9c7c7e4afa90f7d089dbf7251 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ulrich=20M=C3=BCller?= Date: Wed, 14 Aug 2024 13:57:16 +0200 Subject: [PATCH] Drop fallback code in date-to-time, update documentation * lisp/calendar/time-date.el (date-to-time): Drop fallback code. Document that the default timezone is local time, rather than GMT. * test/lisp/calendar/time-date-tests.el (test-date-to-time): Add more test cases. * doc/lispref/os.texi (Time Parsing): Document that 'date-to-time' defaults to local time. * etc/NEWS: Announce the change. (Bug#72570) (cherry picked from commit 49e7f1b92daaaa12e42de93d1f7604ae0a1bbeaa) --- doc/lispref/os.texi | 4 ++-- etc/NEWS | 9 +++++++++ lisp/calendar/time-date.el | 19 ++++--------------- test/lisp/calendar/time-date-tests.el | 24 ++++++++++++++++++++++-- 4 files changed, 37 insertions(+), 19 deletions(-) diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi index 5839de4a650..ddaa1de221c 100644 --- a/doc/lispref/os.texi +++ b/doc/lispref/os.texi @@ -1788,8 +1788,8 @@ Conversion}). This function parses the time-string @var{string} and returns the corresponding Lisp timestamp. The argument @var{string} should represent a date-time, and should be in one of the forms recognized by -@code{parse-time-string} (see below). This function assumes Universal -Time if @var{string} lacks explicit time zone information, +@code{parse-time-string} (see below). This function assumes local time +if @var{string} lacks explicit time zone information, and assumes earliest values if @var{string} lacks month, day, or time. The operating system limits the range of time and zone values. @end defun diff --git a/etc/NEWS b/etc/NEWS index af8d7fee29d..b64a716e565 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -251,6 +251,15 @@ language A. If supplied, 'string-pixel-width' will use any face remappings from BUFFER when computing the string's width. ++++ +** 'date-to-time' now defaults to local time +The function now assumes local time instead of Universal Time when +its argument lacks explicit time zone information. This has been the +de-facto behavior since Emacs 24 although documentation said otherwise. +Also, the fallback on 'timezone-make-date-arpa-standard' has been +removed because its supported date styles can be handled by +'parse-time-string'. + * Changes in Emacs 31.1 on Non-Free Operating Systems diff --git a/lisp/calendar/time-date.el b/lisp/calendar/time-date.el index b441974b943..9a2fb45e3bc 100644 --- a/lisp/calendar/time-date.el +++ b/lisp/calendar/time-date.el @@ -145,14 +145,10 @@ it is assumed that PICO was omitted and should be treated as zero." (autoload 'timezone-make-date-arpa-standard "timezone") ;;;###autoload -;; `parse-time-string' isn't sufficiently general or robust. It fails -;; to grok some of the formats that timezone does (e.g. dodgy -;; post-2000 stuff from some Elms) and either fails or returns bogus -;; values. timezone-make-date-arpa-standard should help. (defun date-to-time (date) "Parse a string DATE that represents a date-time and return a time value. DATE should be in one of the forms recognized by `parse-time-string'. -If DATE lacks timezone information, GMT is assumed." +If DATE lacks time zone information, local time is assumed." (condition-case err ;; Parse DATE. If it contains a year, use defaults for other components. ;; Then encode the result; this signals an error if the year is missing, @@ -164,16 +160,9 @@ If DATE lacks timezone information, GMT is assumed." (decoded-time-set-defaults parsed)) (encode-time parsed)) (error - (let ((overflow-error '(error "Specified time is not representable"))) - (if (equal err overflow-error) - (signal (car err) (cdr err)) - (condition-case err - (encode-time (parse-time-string - (timezone-make-date-arpa-standard date))) - (error - (if (equal err overflow-error) - (signal (car err) (cdr err)) - (error "Invalid date: %s" date))))))))) + (if (equal err '(error "Specified time is not representable")) + (signal (car err) (cdr err)) + (error "Invalid date: %s" date))))) ;;;###autoload (defalias 'time-to-seconds #'float-time) diff --git a/test/lisp/calendar/time-date-tests.el b/test/lisp/calendar/time-date-tests.el index 6512dd0bd07..f8e434e17b1 100644 --- a/test/lisp/calendar/time-date-tests.el +++ b/test/lisp/calendar/time-date-tests.el @@ -42,8 +42,28 @@ '(1 2 3 4)))) (ert-deftest test-date-to-time () - (should (equal (format-time-string "%F %T" (date-to-time "2021-12-04")) - "2021-12-04 00:00:00"))) + (let ((date-list + '(("2021-12-04" (00 00 00 04 12 2021 nil -1 nil)) + ("2006-05-04T03:02:01Z" (01 02 03 04 05 2006 nil nil 0)) + ;; Test cases from timezone-parse-date docstring + ("14 Apr 89 03:20" (00 20 03 14 04 1989 nil -1 nil)) + ("14 Apr 89 03:20:12 GMT" (12 20 03 14 04 1989 nil nil 0)) + ("Fri, 17 Mar 89 4:01" (00 01 04 17 03 1989 nil -1 nil)) + ("Fri, 17 Mar 89 4:01:33 GMT" (33 01 04 17 03 1989 nil nil 0)) + ("Mon Jan 16 16:12 1989" (00 12 16 16 01 1989 nil -1 nil)) + ("Mon Jan 16 16:12:37 GMT 1989" (37 12 16 16 01 1989 nil nil 0)) + ("Thu, 11 Apr 16:17:12 91" (12 17 16 11 04 1991 nil -1 nil)) + ("Mon, 6 Jul 16:47:20 T 1992" (20 47 16 06 07 1992 nil -1 nil)) + ("1996-06-24 21:13:12" (12 13 21 24 06 1996 nil -1 nil)) + ("19960624t211312" (12 13 21 24 06 1996 nil -1 nil)) + ;; These are parsed incorrectly: + ;; "6 May 1992 1641-JST (Wednesday)" + ;; "22-AUG-1993 10:59:12.82" + ;; "1996-06-24 21:13-ZONE" + ))) + (dolist (date date-list) + (should (equal (date-to-time (car date)) + (encode-time (cadr date))))))) (ert-deftest test-days-between () (should (equal (days-between "2021-10-22" "2020-09-29") 388))) -- 2.39.2