summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Ingebrigtsen <larsi@gnus.org>2019-07-29 12:07:44 +0200
committerLars Ingebrigtsen <larsi@gnus.org>2019-07-29 12:07:44 +0200
commit57ca5db4c2dfceef28f0cb9f1398f4752ffaae51 (patch)
treeaa79e4150f67f89d475ccca91377ec2e796ba358
parenta00144abba5d79e07e0f6da33ff0b880beb9ad1b (diff)
downloademacs-57ca5db4c2dfceef28f0cb9f1398f4752ffaae51.tar.gz
Add support for times with time zones
-rw-r--r--lisp/calendar/iso8601.el44
-rw-r--r--test/lisp/calendar/iso8601-tests.el57
2 files changed, 83 insertions, 18 deletions
diff --git a/lisp/calendar/iso8601.el b/lisp/calendar/iso8601.el
index 5952586cc86..83b57a4f56a 100644
--- a/lisp/calendar/iso8601.el
+++ b/lisp/calendar/iso8601.el
@@ -56,11 +56,11 @@
(defconst iso8601--date-match
(iso8601--concat-regexps
(list iso8601--year-match
- iso8601--full-date-match
- iso8601--without-day-match
- iso8601--outdated-date-match
- iso8601--week-date-match
- iso8601--ordinal-date-match)))
+ iso8601--full-date-match
+ iso8601--without-day-match
+ iso8601--outdated-date-match
+ iso8601--week-date-match
+ iso8601--ordinal-date-match)))
(defconst iso8601--time-match
"\\([0-9][0-9]\\):?\\([0-9][0-9]\\)?:?\\([0-9][0-9]\\)?\\.?\\([0-9][0-9][0-9]\\)?")
@@ -68,6 +68,10 @@
(defconst iso8601--zone-match
"\\(Z\\|\\([-+]\\)?\\([0-9][0-9]\\):?\\([0-9][0-9]\\)?\\)")
+(defconst iso8601--full-time-match
+ (concat "\\(" (replace-regexp-in-string "(" "(?:" iso8601--time-match) "\\)"
+ "\\(" iso8601--zone-match "\\)?"))
+
(defconst iso8601--combined-match
(concat "\\(" iso8601--date-match "\\)"
"\\(?:T\\("
@@ -195,19 +199,25 @@ well as variants like \"2008W32\" (week number) and
(defun iso8601-parse-time (string)
"Parse STRING, which should be an ISO 8601 time string, and return a time value."
- (if (not (iso8601--match iso8601--time-match string))
+ (if (not (iso8601--match iso8601--full-time-match string))
(signal 'wrong-type-argument string)
- (let ((hour (string-to-number (match-string 1 string)))
- (minute (and (match-string 2 string)
- (string-to-number (match-string 2 string))))
- (second (and (match-string 3 string)
- (string-to-number (match-string 3 string))))
- ;; Hm...
- (_millisecond (and (match-string 4 string)
- (string-to-number (match-string 4 string)))))
- (iso8601--decoded-time :hour hour
- :minute (or minute 0)
- :second (or second 0)))))
+ (let ((time (match-string 1 string))
+ (zone (match-string 2 string)))
+ (if (not (iso8601--match iso8601--time-match time))
+ (signal 'wrong-type-argument string)
+ (let ((hour (string-to-number (match-string 1 time)))
+ (minute (and (match-string 2 time)
+ (string-to-number (match-string 2 time))))
+ (second (and (match-string 3 time)
+ (string-to-number (match-string 3 time))))
+ ;; Hm...
+ (_millisecond (and (match-string 4 time)
+ (string-to-number (match-string 4 time)))))
+ (iso8601--decoded-time :hour hour
+ :minute (or minute 0)
+ :second (or second 0)
+ :zone (and zone
+ (iso8601-parse-zone zone))))))))
(defun iso8601-parse-zone (string)
"Parse STRING, which should be an ISO 8601 time zone.
diff --git a/test/lisp/calendar/iso8601-tests.el b/test/lisp/calendar/iso8601-tests.el
index 8517e7dde5d..5403c8e2077 100644
--- a/test/lisp/calendar/iso8601-tests.el
+++ b/test/lisp/calendar/iso8601-tests.el
@@ -139,7 +139,7 @@
(should (equal (iso8601-parse-date "+19850412")
'(nil nil nil 12 4 1985 nil nil nil))))
-(ert-deftest standard-test-time-of-day ()
+(ert-deftest standard-test-time-of-day-local-time ()
(should (equal (iso8601-parse-time "152746")
'(46 27 15 nil nil nil nil nil nil)))
(should (equal (iso8601-parse-time "15:27:46")
@@ -153,4 +153,59 @@
(should (equal (iso8601-parse-time "15")
'(0 0 15 nil nil nil nil nil nil))))
+(ert-deftest standard-test-time-of-day-fractions ()
+ ;; decoded-time doesn't support sub-second times.
+ ;; (should (equal (iso8601-parse-time "152735,5")
+ ;; '(46 27 15 nil nil nil nil nil nil)))
+ ;; (should (equal (iso8601-parse-time "15:27:35,5")
+ ;; '(46 27 15 nil nil nil nil nil nil)))
+ )
+
+(ert-deftest standard-test-time-of-day-beginning-of-day ()
+ (should (equal (iso8601-parse-time "000000")
+ '(0 0 0 nil nil nil nil nil nil)))
+ (should (equal (iso8601-parse-time "00:00:00")
+ '(0 0 0 nil nil nil nil nil nil)))
+
+ (should (equal (iso8601-parse-time "0000")
+ '(0 0 0 nil nil nil nil nil nil)))
+ (should (equal (iso8601-parse-time "00:00")
+ '(0 0 0 nil nil nil nil nil nil))))
+
+(ert-deftest standard-test-time-of-day-utc ()
+ (should (equal (iso8601-parse-time "232030Z")
+ '(30 20 23 nil nil nil nil nil 0)))
+ (should (equal (iso8601-parse-time "23:20:30Z")
+ '(30 20 23 nil nil nil nil nil 0)))
+
+ (should (equal (iso8601-parse-time "2320Z")
+ '(0 20 23 nil nil nil nil nil 0)))
+ (should (equal (iso8601-parse-time "23:20Z")
+ '(0 20 23 nil nil nil nil nil 0)))
+
+ (should (equal (iso8601-parse-time "23Z")
+ '(0 0 23 nil nil nil nil nil 0))))
+
+
+(ert-deftest standard-test-time-of-day-zone ()
+ (should (equal (iso8601-parse-time "152746+0100")
+ '(46 27 15 nil nil nil nil nil 60)))
+ (should (equal (iso8601-parse-time "15:27:46+0100")
+ '(46 27 15 nil nil nil nil nil 60)))
+
+ (should (equal (iso8601-parse-time "152746+01")
+ '(46 27 15 nil nil nil nil nil 60)))
+ (should (equal (iso8601-parse-time "15:27:46+01")
+ '(46 27 15 nil nil nil nil nil 60)))
+
+ (should (equal (iso8601-parse-time "152746-0500")
+ '(46 27 15 nil nil nil nil nil -300)))
+ (should (equal (iso8601-parse-time "15:27:46-0500")
+ '(46 27 15 nil nil nil nil nil -300)))
+
+ (should (equal (iso8601-parse-time "152746-05")
+ '(46 27 15 nil nil nil nil nil -300)))
+ (should (equal (iso8601-parse-time "15:27:46-05")
+ '(46 27 15 nil nil nil nil nil -300))))
+
;;; iso8601-tests.el ends here