emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] master 25c9cb7: Fix timezone detection of parse-iso8601-ti


From: Eli Zaretskii
Subject: [Emacs-diffs] master 25c9cb7: Fix timezone detection of parse-iso8601-time-string
Date: Sat, 24 Dec 2016 12:38:11 +0000 (UTC)

branch: master
commit 25c9cb77b4346c9912c995ca3a63fc7ab424795e
Author: Hong Xu <address@hidden>
Commit: Eli Zaretskii <address@hidden>

    Fix timezone detection of parse-iso8601-time-string
    
    * parse-time.el (parse-iso8601-time-string): Fix timezone
    parsing.  Add a doc string.  (Bug#25086)
    * editfns.c (Fdecode-time): Doc fix.
    * emacs-mime.texi (time-date): Add an example for
    parse-iso8601-time-string.
    * parse-time-tests.el (parse-time-tests): Add tests for
    parse-iso8601-time-string.
---
 doc/misc/emacs-mime.texi               |    3 +++
 lisp/calendar/parse-time.el            |   26 +++++++++++++++++++-------
 src/editfns.c                          |    2 +-
 test/lisp/calendar/parse-time-tests.el |   18 +++++++++++++++++-
 4 files changed, 40 insertions(+), 9 deletions(-)

diff --git a/doc/misc/emacs-mime.texi b/doc/misc/emacs-mime.texi
index 2b93587..9389435 100644
--- a/doc/misc/emacs-mime.texi
+++ b/doc/misc/emacs-mime.texi
@@ -1536,6 +1536,9 @@ Here's a bunch of time/date/second/day examples:
 (date-to-time "Sat Sep 12 12:21:54 1998 +0200")
 @result{} (13818 19266)
 
+(parse-iso8601-time-string "1998-09-12T12:21:54+0200")
address@hidden (13818 19266)
+
 (float-time '(13818 19266))
 @result{} 905595714.0
 
diff --git a/lisp/calendar/parse-time.el b/lisp/calendar/parse-time.el
index b62f9fa..ef7758d 100644
--- a/lisp/calendar/parse-time.el
+++ b/lisp/calendar/parse-time.el
@@ -202,7 +202,7 @@ any values that are unknown are returned as nil."
         (time-minute 2digit)
         (time-second 2digit)
         (time-secfrac "\\(\\.[0-9]+\\)?")
-        (time-numoffset (concat "[-+]\\(" time-hour "\\):" time-minute))
+        (time-numoffset (concat "\\([-+]\\)" time-hour ":?" time-minute "?"))
         (time-offset (concat "Z" time-numoffset))
         (partial-time (concat time-hour colon time-minute colon time-second
                               time-secfrac))
@@ -211,19 +211,22 @@ any values that are unknown are returned as nil."
         (date-time (concat full-date "T" full-time)))
     (list (concat "^" full-date)
          (concat "T" partial-time)
-         (concat "Z" time-numoffset)))
+         (concat "\\(Z\\|" time-numoffset "\\)")))
   "List of regular expressions matching ISO 8601 dates.
 1st regular expression matches the date.
 2nd regular expression matches the time.
 3rd regular expression matches the (optional) timezone specification.")
 
 (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'."
   (let* ((date-re (nth 0 parse-time-iso8601-regexp))
         (time-re (nth 1 parse-time-iso8601-regexp))
         (tz-re (nth 2 parse-time-iso8601-regexp))
-        re-start
-        time seconds minute hour fractional-seconds
-        day month year day-of-week dst tz)
+         re-start
+         time seconds minute hour fractional-seconds
+         day month year day-of-week dst tz)
     ;; We need to populate 'time' with
     ;; (SEC MIN HOUR DAY MON YEAR DOW DST TZ)
 
@@ -242,10 +245,19 @@ any values that are unknown are returned as nil."
                                                     "0"))
              re-start (match-end 0))
        (when (string-match tz-re date-string re-start)
-         (setq tz (match-string 1 date-string)))
+          (if (string= "Z" (match-string 1 date-string))
+              (setq tz 0)  ;; UTC timezone indicated by Z
+            (setq tz (+
+                      (* 3600
+                         (string-to-number (match-string 3 date-string)))
+                      (* 60
+                         (string-to-number
+                          (or (match-string 4 date-string) "0")))))
+            (when (string= "-" (match-string 2 date-string))
+              (setq tz (- tz)))))
        (setq time (list seconds minute hour day month year day-of-week dst 
tz))))
 
-    ;; Fall back to having Gnus do fancy things for us.
+    ;; Fall back to having `parse-time-string' do fancy things for us.
     (when (not time)
       (setq time (parse-time-string date-string)))
 
diff --git a/src/editfns.c b/src/editfns.c
index 6ea8cba..ccc78e1 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -2136,7 +2136,7 @@ format_time_string (char const *format, ptrdiff_t 
formatlen,
 
 DEFUN ("decode-time", Fdecode_time, Sdecode_time, 0, 2, 0,
        doc: /* Decode a time value as (SEC MINUTE HOUR DAY MONTH YEAR DOW DST 
UTCOFF).
-The optional SPECIFIED-TIME should be a list of (HIGH LOW . IGNORED),
+The optional TIME should be a list of (HIGH LOW . IGNORED),
 as from `current-time' and `file-attributes', or nil to use the
 current time.  It can also be a single integer number of seconds since
 the epoch.  The obsolete form (HIGH . LOW) is also still accepted.
diff --git a/test/lisp/calendar/parse-time-tests.el 
b/test/lisp/calendar/parse-time-tests.el
index 9bcf2b4..6dc2337 100644
--- a/test/lisp/calendar/parse-time-tests.el
+++ b/test/lisp/calendar/parse-time-tests.el
@@ -42,7 +42,23 @@
   (should (equal (parse-time-string "Monday, 22 february 2016 19:35:42 +0100")
                  '(42 35 19 22 2 2016 1 nil 3600)))
   (should (equal (parse-time-string "Monday, 22 february 2016 19:35:42 PDT")
-                 '(42 35 19 22 2 2016 1 t -25200))))
+                 '(42 35 19 22 2 2016 1 t -25200)))
+  (should (equal (parse-iso8601-time-string "1998-09-12T12:21:54-0200")
+                 '(13818 33666)))
+  (should (equal (parse-iso8601-time-string "1998-09-12T12:21:54-0230")
+                 '(13818 35466)))
+  (should (equal (parse-iso8601-time-string "1998-09-12T12:21:54-02:00")
+                 '(13818 33666)))
+  (should (equal (parse-iso8601-time-string "1998-09-12T12:21:54-02")
+                 '(13818 33666)))
+  (should (equal (parse-iso8601-time-string "1998-09-12T12:21:54+0230")
+                 '(13818 17466)))
+  (should (equal (parse-iso8601-time-string "1998-09-12T12:21:54+02")
+                 '(13818 19266)))
+  (should (equal (parse-iso8601-time-string "1998-09-12T12:21:54Z")
+                 '(13818 26466)))
+  (should (equal (parse-iso8601-time-string "1998-09-12T12:21:54")
+                 (encode-time 54 21 12 12 9 1998))))
 
 (provide 'parse-time-tests)
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]