From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Bob Rogers Newsgroups: gmane.emacs.bugs Subject: bug#52209: 28.0.60; [PATCH] date-to-time fails on pure dates Date: Sun, 19 Dec 2021 16:11:27 -0500 Message-ID: <25023.40959.627321.685762@orion.rgrjr.com> References: <7c22f300-eedb-da65-db02-e82025ec2f48@cs.ucla.edu> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="JRqshbaEP8" Content-Transfer-Encoding: 7bit Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="10106"; mail-complaints-to="usenet@ciao.gmane.io" Cc: Katsumi Yamaoka , 52209@debbugs.gnu.org To: Paul Eggert , Lars Ingebrigtsen Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Sun Dec 19 22:12:29 2021 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1mz3Tp-0002Pm-63 for geb-bug-gnu-emacs@m.gmane-mx.org; Sun, 19 Dec 2021 22:12:29 +0100 Original-Received: from localhost ([::1]:36272 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1mz3Tn-0005ND-Sm for geb-bug-gnu-emacs@m.gmane-mx.org; Sun, 19 Dec 2021 16:12:27 -0500 Original-Received: from eggs.gnu.org ([209.51.188.92]:42204) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1mz3TP-0005N4-0d for bug-gnu-emacs@gnu.org; Sun, 19 Dec 2021 16:12:03 -0500 Original-Received: from debbugs.gnu.org ([209.51.188.43]:36799) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1mz3TO-0008VZ-Ld for bug-gnu-emacs@gnu.org; Sun, 19 Dec 2021 16:12:02 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1mz3TO-0006uz-DR for bug-gnu-emacs@gnu.org; Sun, 19 Dec 2021 16:12:02 -0500 X-Loop: help-debbugs@gnu.org Resent-From: Bob Rogers Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sun, 19 Dec 2021 21:12:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 52209 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch Original-Received: via spool by 52209-submit@debbugs.gnu.org id=B52209.163994829226545 (code B ref 52209); Sun, 19 Dec 2021 21:12:02 +0000 Original-Received: (at 52209) by debbugs.gnu.org; 19 Dec 2021 21:11:32 +0000 Original-Received: from localhost ([127.0.0.1]:48345 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1mz3St-0006u4-TL for submit@debbugs.gnu.org; Sun, 19 Dec 2021 16:11:32 -0500 Original-Received: from rgrjr.com ([69.164.211.47]:36288) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1mz3Ss-0006tx-Fn for 52209@debbugs.gnu.org; Sun, 19 Dec 2021 16:11:31 -0500 Original-Received: from rgrjr.com (c-73-16-206-7.hsd1.ma.comcast.net [73.16.206.7]) by rgrjr.com (Postfix on openSUSE) with ESMTP id 2C2B11D6BB2; Sun, 19 Dec 2021 21:11:43 +0000 (UTC) Original-Received: from orion.rgrjr.com (orion.rgrjr.com [192.168.0.3]) by scorpio.rgrjr.com (Postfix on openSUSE GNU/Linux) with ESMTP id AA9A25FE79; Sun, 19 Dec 2021 16:11:29 -0500 (EST) In-Reply-To: <7c22f300-eedb-da65-db02-e82025ec2f48@cs.ucla.edu> X-Mailer: VM 7.19 under Emacs 29.0.50 X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.io gmane.emacs.bugs:222749 Archived-At: --JRqshbaEP8 Content-Type: text/plain; charset=us-ascii Content-Description: message body text Content-Transfer-Encoding: 7bit From: Paul Eggert Date: Sat, 4 Dec 2021 10:58:37 -0800 Unfortunately the latest change to time-date.el reintroduced Bug#52209. I installed the attached patch to fix this . . . I'm sure none of you will be surprised to learn that parse-time-string still doesn't recognize single-digit months or days, with the same fallback-to-the-epoch behavior that threw me for a loop originally. (format-time-string "%F %T %z" (date-to-time "2022-1-12")) => "1999-12-31 19:00:00 -0500" And adding a time makes it work again because it seems that timezone-make-date-arpa-standard does accept single-digit months and days. Go figure. The attached patch extends parse-time-string by using regexps instead of string manipulation of fixed-width fields. This could possibly break interface compatibility, especially if you expect anyone to customize parse-time-rules. So I will not be surprised if you decline to adopt it. > (These functions were never really intended to support parsing dates > like that -- only strict RFC822 date strings were originally supported, > but it's become more DWIM as time has passed. Yes, date-to-time has definitely ... evolved. My understanding is that date-to-time's RFC822 parsing is present only for backward compatibility, and that we shouldn't attempt to enhance it (here, the enhancement would be pointless as the RFC822 parsing fills in the blanks anyway). So the patch I just installed adds the new feature only for the normal path taken, when not doing the RFC822 hack. PS. Internet RFC 822 has been obsolete since 2001, and the Emacs code should be talking about RFC 5322 everywhere except when Emacs is explicitly supporting the obsolete standard instead of the current standard. And we should rename functions like rfc822-goto-eoh to rfc-email-goto-eoh, to help avoid confusion or further function renaming. But I digress.... Since Emacs time functions have evolved well beyond email, I would argue that even "rfc-email-" is too specific a prefix for them. So if this patch is not suitable, maybe it's (cough, cough) time for a new time and date parsing API that supports a broader range of human-generated dates and times, with better error handling and I18N support. WDYT? -- Bob Rogers http://www.rgrjr.com/ --JRqshbaEP8 Content-Type: text/x-patch Content-Description: Content-Disposition: inline; filename="rgr-extend-parse-time.patch" Content-Transfer-Encoding: 7bit diff --git a/lisp/calendar/parse-time.el b/lisp/calendar/parse-time.el index 5a3d2706af..4812dcbd1b 100644 --- a/lisp/calendar/parse-time.el +++ b/lisp/calendar/parse-time.el @@ -102,45 +102,25 @@ parse-time-rules ((3) (1 31)) ((4) parse-time-months) ((5) (100)) - ((2 1 0) - ,(lambda () (and (stringp parse-time-elt) - (= (length parse-time-elt) 8) - (= (aref parse-time-elt 2) ?:) - (= (aref parse-time-elt 5) ?:))) - [0 2] [3 5] [6 8]) ((8 7) parse-time-zoneinfo ,(lambda () (car parse-time-val)) ,(lambda () (cadr parse-time-val))) ((8) + "^[-+][0-9][0-9][0-9][0-9]$" ,(lambda () - (and (stringp parse-time-elt) - (= 5 (length parse-time-elt)) - (or (= (aref parse-time-elt 0) ?+) - (= (aref parse-time-elt 0) ?-)))) - ,(lambda () (* 60 (+ (cl-parse-integer parse-time-elt :start 3 :end 5) - (* 60 (cl-parse-integer parse-time-elt :start 1 :end 3))) - (if (= (aref parse-time-elt 0) ?-) -1 1)))) + (* 60 + (+ (cl-parse-integer parse-time-elt :start 3 :end 5) + (* 60 (cl-parse-integer parse-time-elt :start 1 :end 3))) + (if (= (aref parse-time-elt 0) ?-) -1 1)))) ((5 4 3) - ,(lambda () (and (stringp parse-time-elt) - (= (length parse-time-elt) 10) - (= (aref parse-time-elt 4) ?-) - (= (aref parse-time-elt 7) ?-))) - [0 4] [5 7] [8 10]) - ((2 1 0) - ,(lambda () (and (stringp parse-time-elt) - (= (length parse-time-elt) 5) - (= (aref parse-time-elt 2) ?:))) - [0 2] [3 5] ,(lambda () 0)) + "^\\([0-9][0-9][0-9][0-9]\\)-\\([0-9][0-9]?\\)-\\([0-9][0-9]?\\)$" + 1 2 3) ((2 1 0) - ,(lambda () (and (stringp parse-time-elt) - (= (length parse-time-elt) 4) - (= (aref parse-time-elt 1) ?:))) - [0 1] [2 4] ,(lambda () 0)) + "^\\([0-9][0-9]?\\):\\([0-9][0-9]\\)$" + 1 2 ,(lambda () 0)) ((2 1 0) - ,(lambda () (and (stringp parse-time-elt) - (= (length parse-time-elt) 7) - (= (aref parse-time-elt 1) ?:))) - [0 1] [2 4] [5 7]) + "^\\([0-9][0-9]?\\):\\([0-9][0-9]\\):\\([0-9][0-9]\\)$" + 1 2 3) ((5) (50 110) ,(lambda () (+ 1900 parse-time-elt))) ((5) (0 49) ,(lambda () (+ 2000 parse-time-elt)))) "(slots predicate extractor...)") @@ -173,7 +153,11 @@ parse-time-string (parse-time-val)) (when (and (not (nth (car slots) time)) ;not already set (setq parse-time-val - (cond ((and (consp predicate) + (cond ((stringp predicate) + (and (stringp parse-time-elt) + (string-match predicate + parse-time-elt))) + ((and (consp predicate) (not (functionp predicate))) (and (numberp parse-time-elt) (<= (car predicate) parse-time-elt) @@ -188,15 +172,15 @@ parse-time-string (setq exit t) (while slots (let ((new-val (if rule - (let ((this (pop rule))) - (if (vectorp this) - (cl-parse-integer - parse-time-elt - :start (aref this 0) - :end (aref this 1)) - (funcall this))) + (let* ((this (pop rule))) + (if (integerp this) + (cl-parse-integer + (match-string this parse-time-elt)) + (funcall this))) parse-time-val))) - (setf (nth (pop slots) time) new-val)))))))) + (setf (nth (pop slots) time) new-val)))))) + (unless exit + (message "unrecognized token '%s'" parse-time-elt)))) time)))) (defun parse-iso8601-time-string (date-string) diff --git a/test/lisp/calendar/parse-time-tests.el b/test/lisp/calendar/parse-time-tests.el index b706b73570..63b696db1d 100644 --- a/test/lisp/calendar/parse-time-tests.el +++ b/test/lisp/calendar/parse-time-tests.el @@ -45,6 +45,36 @@ parse-time-tests '(42 35 19 22 2 2016 1 nil -28800))) (should (equal (parse-time-string "Friday, 21 Sep 2018 13:47:58 PDT") '(58 47 13 21 9 2018 5 t -25200))) + (should (equal (parse-time-string "Friday, 21 Sep 2018 13:47:58") + '(58 47 13 21 9 2018 5 -1 nil))) + (should (equal (parse-time-string "Friday, 21 Sep 2018") + '(nil nil nil 21 9 2018 5 -1 nil))) + ;; Date can be numeric if separated by hyphens. + (should (equal (parse-time-string "Friday, 2018-09-21") + '(nil nil nil 21 9 2018 5 -1 nil))) + ;; Day of week is optional + (should (equal (parse-time-string "2018-09-21") + '(nil nil nil 21 9 2018 nil -1 nil))) + ;; The order of date, time, etc., does not matter. + (should (equal (parse-time-string "13:47:58, +0100, 2018-09-21, Friday") + '(58 47 13 21 9 2018 5 -1 3600))) + ;; Month, day, or both, can be a single digit. + (should (equal (parse-time-string "Friday, 2018-9-08") + '(nil nil nil 8 9 2018 5 -1 nil))) + (should (equal (parse-time-string "Friday, 2018-09-8") + '(nil nil nil 8 9 2018 5 -1 nil))) + (should (equal (parse-time-string "Friday, 2018-9-8") + '(nil nil nil 8 9 2018 5 -1 nil))) + ;; Time by itself is recognized as such. + (should (equal (parse-time-string "03:47:58") + '(58 47 3 nil nil nil nil -1 nil))) + ;; A leading zero for hours is optional. + (should (equal (parse-time-string "3:47:58") + '(58 47 3 nil nil nil nil -1 nil))) + ;; Missing seconds are assumed to be zero. + (should (equal (parse-time-string "3:47") + '(0 47 3 nil nil nil nil -1 nil))) + (should (equal (format-time-string "%Y-%m-%d %H:%M:%S" (parse-iso8601-time-string "1998-09-12T12:21:54-0200") t) --JRqshbaEP8--