iso8601--duration-combined-match)))
(defun iso8601-parse (string)
- "Parse an ISO 8601 date/time string and return a `decoded-time' structure.
+ "Parse an ISO 8601 date/time string and return a `decode-time' structure.
The ISO 8601 date/time strings look like \"2008-03-02T13:47:30\",
but shorter, incomplete strings like \"2008-03-02\" are valid, as
well as variants like \"2008W32\" (week number) and
-\"2008-234\" (ordinal day number)."
+\"2008-234\" (ordinal day number).
+
+The `decode-time' value returned will have the same precision as
+STRING, so if a sub-second STRING is passed in, the `decode-time'
+seconds field will be on the (SECONDS . HZ) format."
(if (not (iso8601-valid-p string))
(signal 'wrong-type-argument string)
(let* ((date-string (match-string 1 string))
date)))
(defun iso8601-parse-date (string)
- "Parse STRING (in ISO 8601 format) and return a decoded time value."
+ "Parse STRING (in ISO 8601 format) and return a `decode-time' value."
(cond
;; Just a year: [-+]YYYY.
((iso8601--match iso8601--year-match string)
year))))
(defun iso8601-parse-time (string)
- "Parse STRING, which should be an ISO 8601 time string, and return a time value."
+ "Parse STRING, which should be an ISO 8601 time string.
+The return value will be a `decode-time' structure with just the
+hour/minute/seconds/zone fields filled in."
(if (not (iso8601--match iso8601--full-time-match string))
(signal 'wrong-type-argument string)
(let ((time (match-string 1 string))
(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)
+ (fraction (and (match-string 4 time)
(string-to-number (match-string 4 time)))))
+ (when fraction
+ (cond
+ ;; Sub-second time.
+ (second
+ (let ((digits (1+ (truncate (log fraction 10)))))
+ (setq second (cons (+ (* second (expt 10 digits))
+ fraction)
+ (expt 10 digits)))))
+ ;; Fractional minute.
+ (minute
+ (setq second (iso8601--decimalize fraction 60)))
+ (hour
+ ;; Fractional hour.
+ (setq minute (iso8601--decimalize fraction 60)))))
(iso8601--decoded-time :hour hour
:minute (or minute 0)
:second (or second 0)
(* 60 (iso8601-parse-zone
zone)))))))))
+(defun iso8601--decimalize (fraction base)
+ (round (* base (/ (float fraction)
+ (expt 10 (1+ (truncate (log fraction 10))))))))
+
(defun iso8601-parse-zone (string)
"Parse STRING, which should be an ISO 8601 time zone.
Return the number of minutes."
(should (equal (iso8601-parse-time "15")
'(0 0 15 nil nil nil nil nil nil))))
-;; Not implemented yet.
-
-;; (ert-deftest standard-test-time-of-day-fractions ()
-;; (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)))
-
-;; (should (equal (iso8601-parse-time "2320,8")
-;; '(46 27 15 nil nil nil nil nil nil)))
-;; (should (equal (iso8601-parse-time "23:20,8")
-;; '(46 27 15 nil nil nil nil nil nil)))
-
-;; (should (equal (iso8601-parse-time "23,3")
-;; '(46 27 15 nil nil nil nil nil nil))))
-
-;; (ert-deftest nonstandard-test-time-of-day-decimals ()
-;; (should (equal (iso8601-parse-time "15:27:35.123")
-;; '(46 27 15 nil nil nil nil nil nil))))
+(ert-deftest standard-test-time-of-day-fractions ()
+ (should (equal (iso8601-parse-time "152735,5")
+ '((355 . 10) 27 15 nil nil nil nil nil nil)))
+ (should (equal (iso8601-parse-time "15:27:35,5")
+ '((355 . 10) 27 15 nil nil nil nil nil nil)))
+
+ (should (equal (iso8601-parse-time "2320,5")
+ '(30 20 23 nil nil nil nil nil nil)))
+ (should (equal (iso8601-parse-time "23:20,8")
+ '(48 20 23 nil nil nil nil nil nil)))
+
+ (should (equal (iso8601-parse-time "23,3")
+ '(0 18 23 nil nil nil nil nil nil))))
+
+(ert-deftest nonstandard-test-time-of-day-decimals ()
+ (should (equal (iso8601-parse-time "15:27:35.123")
+ '((35123 . 1000) 27 15 nil nil nil nil nil nil)))
+ (should (equal (iso8601-parse-time "15:27:35.123456789")
+ '((35123456789 . 1000000000) 27 15 nil nil nil nil nil nil))))
(ert-deftest standard-test-time-of-day-beginning-of-day ()
(should (equal (iso8601-parse-time "000000")