diff options
| author | Hong Xu | 2016-12-24 14:35:12 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2016-12-24 14:35:12 +0200 |
| commit | 25c9cb77b4346c9912c995ca3a63fc7ab424795e (patch) | |
| tree | 1b450c512afd6cbd8cbd3519797369c16accb1cb | |
| parent | e36a3882c338765a9ddfebfc160e5a298933f233 (diff) | |
| download | emacs-25c9cb77b4346c9912c995ca3a63fc7ab424795e.tar.gz emacs-25c9cb77b4346c9912c995ca3a63fc7ab424795e.zip | |
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.
| -rw-r--r-- | doc/misc/emacs-mime.texi | 3 | ||||
| -rw-r--r-- | lisp/calendar/parse-time.el | 26 | ||||
| -rw-r--r-- | src/editfns.c | 2 | ||||
| -rw-r--r-- | 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 2b935870dae..9389435faf1 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: | |||
| 1536 | (date-to-time "Sat Sep 12 12:21:54 1998 +0200") | 1536 | (date-to-time "Sat Sep 12 12:21:54 1998 +0200") |
| 1537 | @result{} (13818 19266) | 1537 | @result{} (13818 19266) |
| 1538 | 1538 | ||
| 1539 | (parse-iso8601-time-string "1998-09-12T12:21:54+0200") | ||
| 1540 | @result{} (13818 19266) | ||
| 1541 | |||
| 1539 | (float-time '(13818 19266)) | 1542 | (float-time '(13818 19266)) |
| 1540 | @result{} 905595714.0 | 1543 | @result{} 905595714.0 |
| 1541 | 1544 | ||
diff --git a/lisp/calendar/parse-time.el b/lisp/calendar/parse-time.el index b62f9fa7941..ef7758df442 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." | |||
| 202 | (time-minute 2digit) | 202 | (time-minute 2digit) |
| 203 | (time-second 2digit) | 203 | (time-second 2digit) |
| 204 | (time-secfrac "\\(\\.[0-9]+\\)?") | 204 | (time-secfrac "\\(\\.[0-9]+\\)?") |
| 205 | (time-numoffset (concat "[-+]\\(" time-hour "\\):" time-minute)) | 205 | (time-numoffset (concat "\\([-+]\\)" time-hour ":?" time-minute "?")) |
| 206 | (time-offset (concat "Z" time-numoffset)) | 206 | (time-offset (concat "Z" time-numoffset)) |
| 207 | (partial-time (concat time-hour colon time-minute colon time-second | 207 | (partial-time (concat time-hour colon time-minute colon time-second |
| 208 | time-secfrac)) | 208 | time-secfrac)) |
| @@ -211,19 +211,22 @@ any values that are unknown are returned as nil." | |||
| 211 | (date-time (concat full-date "T" full-time))) | 211 | (date-time (concat full-date "T" full-time))) |
| 212 | (list (concat "^" full-date) | 212 | (list (concat "^" full-date) |
| 213 | (concat "T" partial-time) | 213 | (concat "T" partial-time) |
| 214 | (concat "Z" time-numoffset))) | 214 | (concat "\\(Z\\|" time-numoffset "\\)"))) |
| 215 | "List of regular expressions matching ISO 8601 dates. | 215 | "List of regular expressions matching ISO 8601 dates. |
| 216 | 1st regular expression matches the date. | 216 | 1st regular expression matches the date. |
| 217 | 2nd regular expression matches the time. | 217 | 2nd regular expression matches the time. |
| 218 | 3rd regular expression matches the (optional) timezone specification.") | 218 | 3rd regular expression matches the (optional) timezone specification.") |
| 219 | 219 | ||
| 220 | (defun parse-iso8601-time-string (date-string) | 220 | (defun parse-iso8601-time-string (date-string) |
| 221 | "Parse an ISO 8601 time string, such as 2016-12-01T23:35:06-05:00. | ||
| 222 | If DATE-STRING cannot be parsed, it falls back to | ||
| 223 | `parse-time-string'." | ||
| 221 | (let* ((date-re (nth 0 parse-time-iso8601-regexp)) | 224 | (let* ((date-re (nth 0 parse-time-iso8601-regexp)) |
| 222 | (time-re (nth 1 parse-time-iso8601-regexp)) | 225 | (time-re (nth 1 parse-time-iso8601-regexp)) |
| 223 | (tz-re (nth 2 parse-time-iso8601-regexp)) | 226 | (tz-re (nth 2 parse-time-iso8601-regexp)) |
| 224 | re-start | 227 | re-start |
| 225 | time seconds minute hour fractional-seconds | 228 | time seconds minute hour fractional-seconds |
| 226 | day month year day-of-week dst tz) | 229 | day month year day-of-week dst tz) |
| 227 | ;; We need to populate 'time' with | 230 | ;; We need to populate 'time' with |
| 228 | ;; (SEC MIN HOUR DAY MON YEAR DOW DST TZ) | 231 | ;; (SEC MIN HOUR DAY MON YEAR DOW DST TZ) |
| 229 | 232 | ||
| @@ -242,10 +245,19 @@ any values that are unknown are returned as nil." | |||
| 242 | "0")) | 245 | "0")) |
| 243 | re-start (match-end 0)) | 246 | re-start (match-end 0)) |
| 244 | (when (string-match tz-re date-string re-start) | 247 | (when (string-match tz-re date-string re-start) |
| 245 | (setq tz (match-string 1 date-string))) | 248 | (if (string= "Z" (match-string 1 date-string)) |
| 249 | (setq tz 0) ;; UTC timezone indicated by Z | ||
| 250 | (setq tz (+ | ||
| 251 | (* 3600 | ||
| 252 | (string-to-number (match-string 3 date-string))) | ||
| 253 | (* 60 | ||
| 254 | (string-to-number | ||
| 255 | (or (match-string 4 date-string) "0"))))) | ||
| 256 | (when (string= "-" (match-string 2 date-string)) | ||
| 257 | (setq tz (- tz))))) | ||
| 246 | (setq time (list seconds minute hour day month year day-of-week dst tz)))) | 258 | (setq time (list seconds minute hour day month year day-of-week dst tz)))) |
| 247 | 259 | ||
| 248 | ;; Fall back to having Gnus do fancy things for us. | 260 | ;; Fall back to having `parse-time-string' do fancy things for us. |
| 249 | (when (not time) | 261 | (when (not time) |
| 250 | (setq time (parse-time-string date-string))) | 262 | (setq time (parse-time-string date-string))) |
| 251 | 263 | ||
diff --git a/src/editfns.c b/src/editfns.c index 6ea8cbaf5e4..ccc78e12758 100644 --- a/src/editfns.c +++ b/src/editfns.c | |||
| @@ -2136,7 +2136,7 @@ format_time_string (char const *format, ptrdiff_t formatlen, | |||
| 2136 | 2136 | ||
| 2137 | DEFUN ("decode-time", Fdecode_time, Sdecode_time, 0, 2, 0, | 2137 | DEFUN ("decode-time", Fdecode_time, Sdecode_time, 0, 2, 0, |
| 2138 | doc: /* Decode a time value as (SEC MINUTE HOUR DAY MONTH YEAR DOW DST UTCOFF). | 2138 | doc: /* Decode a time value as (SEC MINUTE HOUR DAY MONTH YEAR DOW DST UTCOFF). |
| 2139 | The optional SPECIFIED-TIME should be a list of (HIGH LOW . IGNORED), | 2139 | The optional TIME should be a list of (HIGH LOW . IGNORED), |
| 2140 | as from `current-time' and `file-attributes', or nil to use the | 2140 | as from `current-time' and `file-attributes', or nil to use the |
| 2141 | current time. It can also be a single integer number of seconds since | 2141 | current time. It can also be a single integer number of seconds since |
| 2142 | the epoch. The obsolete form (HIGH . LOW) is also still accepted. | 2142 | 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 9bcf2b4a53c..6dc23372f24 100644 --- a/test/lisp/calendar/parse-time-tests.el +++ b/test/lisp/calendar/parse-time-tests.el | |||
| @@ -42,7 +42,23 @@ | |||
| 42 | (should (equal (parse-time-string "Monday, 22 february 2016 19:35:42 +0100") | 42 | (should (equal (parse-time-string "Monday, 22 february 2016 19:35:42 +0100") |
| 43 | '(42 35 19 22 2 2016 1 nil 3600))) | 43 | '(42 35 19 22 2 2016 1 nil 3600))) |
| 44 | (should (equal (parse-time-string "Monday, 22 february 2016 19:35:42 PDT") | 44 | (should (equal (parse-time-string "Monday, 22 february 2016 19:35:42 PDT") |
| 45 | '(42 35 19 22 2 2016 1 t -25200)))) | 45 | '(42 35 19 22 2 2016 1 t -25200))) |
| 46 | (should (equal (parse-iso8601-time-string "1998-09-12T12:21:54-0200") | ||
| 47 | '(13818 33666))) | ||
| 48 | (should (equal (parse-iso8601-time-string "1998-09-12T12:21:54-0230") | ||
| 49 | '(13818 35466))) | ||
| 50 | (should (equal (parse-iso8601-time-string "1998-09-12T12:21:54-02:00") | ||
| 51 | '(13818 33666))) | ||
| 52 | (should (equal (parse-iso8601-time-string "1998-09-12T12:21:54-02") | ||
| 53 | '(13818 33666))) | ||
| 54 | (should (equal (parse-iso8601-time-string "1998-09-12T12:21:54+0230") | ||
| 55 | '(13818 17466))) | ||
| 56 | (should (equal (parse-iso8601-time-string "1998-09-12T12:21:54+02") | ||
| 57 | '(13818 19266))) | ||
| 58 | (should (equal (parse-iso8601-time-string "1998-09-12T12:21:54Z") | ||
| 59 | '(13818 26466))) | ||
| 60 | (should (equal (parse-iso8601-time-string "1998-09-12T12:21:54") | ||
| 61 | (encode-time 54 21 12 12 9 1998)))) | ||
| 46 | 62 | ||
| 47 | (provide 'parse-time-tests) | 63 | (provide 'parse-time-tests) |
| 48 | 64 | ||