From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.ciao.gmane.io!not-for-mail From: Paul Eggert Newsgroups: gmane.emacs.bugs Subject: bug#39001: parse-time-string fails to parse Info node's example Date: Wed, 15 Jan 2020 17:45:02 -0800 Organization: UCLA Computer Science Department Message-ID: <1d6510ff-910a-8294-09a1-1b9c6f2ce5ed@cs.ucla.edu> References: Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------1B88AEAAE29D19D80D64FD87" Injection-Info: ciao.gmane.io; posting-host="ciao.gmane.io:159.69.161.202"; logging-data="74824"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.3.1 Cc: 39001-done@debbugs.gnu.org To: mark skilbeck Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Thu Jan 16 02:50:16 2020 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 1iruIa-000JOx-0L for geb-bug-gnu-emacs@m.gmane-mx.org; Thu, 16 Jan 2020 02:50:16 +0100 Original-Received: from localhost ([::1]:35112 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iruIY-0006qw-VA for geb-bug-gnu-emacs@m.gmane-mx.org; Wed, 15 Jan 2020 20:50:14 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:39490) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iruEa-00052j-1L for bug-gnu-emacs@gnu.org; Wed, 15 Jan 2020 20:46:10 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iruEX-0001V4-Qo for bug-gnu-emacs@gnu.org; Wed, 15 Jan 2020 20:46:07 -0500 Original-Received: from debbugs.gnu.org ([209.51.188.43]:58798) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iruEU-0001SG-9c for bug-gnu-emacs@gnu.org; Wed, 15 Jan 2020 20:46:03 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1iruEU-0002QU-7o for bug-gnu-emacs@gnu.org; Wed, 15 Jan 2020 20:46:02 -0500 In-Reply-To: Resent-From: Paul Eggert Original-Sender: "Debbugs-submit" Resent-To: bug-gnu-emacs@gnu.org Resent-Date: Thu, 16 Jan 2020 01:46:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: cc-closed 39001 X-GNU-PR-Package: emacs Mail-Followup-To: 39001@debbugs.gnu.org, eggert@cs.ucla.edu, markskilbeck@gmail.com Original-Received: via spool by 39001-done@debbugs.gnu.org id=D39001.15791391139259 (code D ref 39001); Thu, 16 Jan 2020 01:46:02 +0000 Original-Received: (at 39001-done) by debbugs.gnu.org; 16 Jan 2020 01:45:13 +0000 Original-Received: from localhost ([127.0.0.1]:36538 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1iruDg-0002PG-Tc for submit@debbugs.gnu.org; Wed, 15 Jan 2020 20:45:13 -0500 Original-Received: from zimbra.cs.ucla.edu ([131.179.128.68]:33362) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1iruDe-0002Ox-Lc for 39001-done@debbugs.gnu.org; Wed, 15 Jan 2020 20:45:11 -0500 Original-Received: from localhost (localhost [127.0.0.1]) by zimbra.cs.ucla.edu (Postfix) with ESMTP id 91B15160072; Wed, 15 Jan 2020 17:45:04 -0800 (PST) Original-Received: from zimbra.cs.ucla.edu ([127.0.0.1]) by localhost (zimbra.cs.ucla.edu [127.0.0.1]) (amavisd-new, port 10032) with ESMTP id g_12mUuXe8ev; Wed, 15 Jan 2020 17:45:03 -0800 (PST) Original-Received: from localhost (localhost [127.0.0.1]) by zimbra.cs.ucla.edu (Postfix) with ESMTP id 681A9160081; Wed, 15 Jan 2020 17:45:03 -0800 (PST) X-Virus-Scanned: amavisd-new at zimbra.cs.ucla.edu Original-Received: from zimbra.cs.ucla.edu ([127.0.0.1]) by localhost (zimbra.cs.ucla.edu [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id 70AfckZ58foN; Wed, 15 Jan 2020 17:45:03 -0800 (PST) Original-Received: from Penguin.CS.UCLA.EDU (Penguin.CS.UCLA.EDU [131.179.64.200]) by zimbra.cs.ucla.edu (Postfix) with ESMTPSA id 4709D160072; Wed, 15 Jan 2020 17:45:03 -0800 (PST) Content-Language: en-US X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.51.188.43 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:174688 Archived-At: This is a multi-part message in MIME format. --------------1B88AEAAE29D19D80D64FD87 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Thanks for the bug report. I fixed the code so that it matches the documentation by installing the attached patches into Emacs master. The first patch is the fix, the second is merely refactoring. --------------1B88AEAAE29D19D80D64FD87 Content-Type: text/x-patch; charset=UTF-8; name="0001-parse-time-string-now-parses-ISO-8601-format-strings.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename*0="0001-parse-time-string-now-parses-ISO-8601-format-strings.pa"; filename*1="tch" >From 33d9ca387824e050650b49a60083e4e4cb4e3d11 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Wed, 15 Jan 2020 17:36:59 -0800 Subject: [PATCH 1/2] parse-time-string now parses ISO 8601 format strings * lisp/calendar/parse-time.el (parse-time-string): Parse strings in ISO 8601 format too (Bug#39001). (parse-time--rfc-822ish): New internal function, containing most of the old parse-time-string implementation. (parse-iso8601-time-string): Simplify, now that parse-time-string groks ISO 8601. --- etc/NEWS | 3 +++ lisp/calendar/parse-time.el | 25 ++++++++++++++----------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index 0e43c321d8..3d5915a377 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -70,6 +70,9 @@ called when the function object is garbage-collected. Use 'set_function_finalizer' to set the finalizer and 'get_function_finalizer' to retrieve it. +** 'parse-time-string' can now parse ISO 8601 format strings, +such as "2020-01-15T16:12:21-08:00". + * Changes in Emacs 28.1 on Non-Free Operating Systems diff --git a/lisp/calendar/parse-time.el b/lisp/calendar/parse-time.el index 7110a81f0d..4d4f88efff 100644 --- a/lisp/calendar/parse-time.el +++ b/lisp/calendar/parse-time.el @@ -149,13 +149,20 @@ parse-time-rules ;;;###autoload (defun parse-time-string (string) "Parse the time in STRING into (SEC MIN HOUR DAY MON YEAR DOW DST TZ). -STRING should be something resembling an RFC 822 (or later) date-time, e.g., -\"Fri, 25 Mar 2016 16:24:56 +0100\", but this function is +STRING should be an ISO 8601 time string, e.g., \"2020-01-15T16:12:21-08:00\", +or something resembling an RFC 822 (or later) date-time, e.g., +\"Wed, 15 Jan 2020 16:12:21 -0800\". This function is somewhat liberal in what format it accepts, and will attempt to return a \"likely\" value even for somewhat malformed strings. The values returned are identical to those of `decode-time', but any unknown values other than DST are returned as nil, and an unknown DST value is returned as -1." + (condition-case () + (decoded-time-set-defaults (iso8601-parse string)) + (wrong-type-argument + (parse-time--rfc-822ish string)))) + +(defun parse-time--rfc-822ish (string) (let ((time (list nil nil nil nil nil nil nil -1 nil)) (temp (parse-time-tokenize (downcase string)))) (while temp @@ -196,15 +203,11 @@ parse-time-string time)) (defun parse-iso8601-time-string (date-string) - "Parse an ISO 8601 time string, such as 2016-12-01T23:35:06-05:00. -If DATE-STRING cannot be parsed, it falls back to -`parse-time-string'." - (when-let ((time - (if (iso8601-valid-p date-string) - (decoded-time-set-defaults (iso8601-parse date-string)) - ;; Fall back to having `parse-time-string' do fancy - ;; things for us. - (parse-time-string date-string)))) + "Parse an ISO 8601 time string, such as \"2020-01-15T16:12:21-08:00\". +Fall back on parsing something resembling an RFC 822 (or later) date-time. +This function is like `parse-time-string' except that it returns +a Lisp timestamp when successful." + (when-let ((time (parse-time-string date-string))) (encode-time time))) (provide 'parse-time) -- 2.24.1 --------------1B88AEAAE29D19D80D64FD87 Content-Type: text/x-patch; charset=UTF-8; name="0002-Refactor-parse-time-string.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="0002-Refactor-parse-time-string.patch" >From d3db908ffbfa17ff74080455ac0520c663f920ee Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Wed, 15 Jan 2020 17:41:42 -0800 Subject: [PATCH 2/2] Refactor parse-time-string * lisp/calendar/parse-time.el (parse-time--rfc-822ish): Remove, and fold its body into its only caller. --- lisp/calendar/parse-time.el | 79 ++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 41 deletions(-) diff --git a/lisp/calendar/parse-time.el b/lisp/calendar/parse-time.el index 4d4f88efff..6a4612297c 100644 --- a/lisp/calendar/parse-time.el +++ b/lisp/calendar/parse-time.el @@ -160,47 +160,44 @@ parse-time-string (condition-case () (decoded-time-set-defaults (iso8601-parse string)) (wrong-type-argument - (parse-time--rfc-822ish string)))) - -(defun parse-time--rfc-822ish (string) - (let ((time (list nil nil nil nil nil nil nil -1 nil)) - (temp (parse-time-tokenize (downcase string)))) - (while temp - (let ((parse-time-elt (pop temp)) - (rules parse-time-rules) - (exit nil)) - (while (and rules (not exit)) - (let* ((rule (pop rules)) - (slots (pop rule)) - (predicate (pop rule)) - (parse-time-val)) - (when (and (not (nth (car slots) time)) ;not already set - (setq parse-time-val - (cond ((and (consp predicate) - (not (functionp predicate))) - (and (numberp parse-time-elt) - (<= (car predicate) parse-time-elt) - (or (not (cdr predicate)) - (<= parse-time-elt - (cadr predicate))) - parse-time-elt)) - ((symbolp predicate) - (cdr (assoc parse-time-elt - (symbol-value predicate)))) - ((funcall predicate))))) - (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))) - parse-time-val))) - (setf (nth (pop slots) time) new-val)))))))) - time)) + (let ((time (list nil nil nil nil nil nil nil -1 nil)) + (temp (parse-time-tokenize (downcase string)))) + (while temp + (let ((parse-time-elt (pop temp)) + (rules parse-time-rules) + (exit nil)) + (while (and rules (not exit)) + (let* ((rule (pop rules)) + (slots (pop rule)) + (predicate (pop rule)) + (parse-time-val)) + (when (and (not (nth (car slots) time)) ;not already set + (setq parse-time-val + (cond ((and (consp predicate) + (not (functionp predicate))) + (and (numberp parse-time-elt) + (<= (car predicate) parse-time-elt) + (or (not (cdr predicate)) + (<= parse-time-elt + (cadr predicate))) + parse-time-elt)) + ((symbolp predicate) + (cdr (assoc parse-time-elt + (symbol-value predicate)))) + ((funcall predicate))))) + (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))) + parse-time-val))) + (setf (nth (pop slots) time) new-val)))))))) + time)))) (defun parse-iso8601-time-string (date-string) "Parse an ISO 8601 time string, such as \"2020-01-15T16:12:21-08:00\". -- 2.24.1 --------------1B88AEAAE29D19D80D64FD87--