Fix off-by-one bug in ISO 8601 BC years
* lisp/calendar/iso8601.el (iso8601--year-match) (iso8601--full-date-match, iso8601--without-day-match) (iso8601--week-date-match, iso8601--ordinal-date-match) (iso8601-parse-date): Don’t bother to separate the year’s sign from the year, as that distinction is not needed: ISO 8601 uses astronomical year numbering with a year zero, which is what the Emacs time functions use, so there’s no need to treat nonpositive years specially. (iso8601--adjust-year): Remove; no longer needed since callers can just use string-to-number. * test/lisp/calendar/iso8601-tests.el (test-iso8601-date-years): Adjust test case to match fixed behavior.
This commit is contained in:
parent
aadf721676
commit
9d829b8be5
2 changed files with 18 additions and 33 deletions
|
@ -62,17 +62,17 @@
|
|||
regexps "\\|"))
|
||||
|
||||
(defconst iso8601--year-match
|
||||
"\\([+-]\\)?\\([0-9][0-9][0-9][0-9]\\)")
|
||||
"\\([+-]?[0-9][0-9][0-9][0-9]\\)")
|
||||
(defconst iso8601--full-date-match
|
||||
"\\([+-]\\)?\\([0-9][0-9][0-9][0-9]\\)-?\\([0-9][0-9]\\)-?\\([0-9][0-9]\\)")
|
||||
"\\([+-]?[0-9][0-9][0-9][0-9]\\)-?\\([0-9][0-9]\\)-?\\([0-9][0-9]\\)")
|
||||
(defconst iso8601--without-day-match
|
||||
"\\([+-]\\)?\\([0-9][0-9][0-9][0-9]\\)-\\([0-9][0-9]\\)")
|
||||
"\\([+-]?[0-9][0-9][0-9][0-9]\\)-\\([0-9][0-9]\\)")
|
||||
(defconst iso8601--outdated-date-match
|
||||
"--\\([0-9][0-9]\\)-?\\([0-9][0-9]\\)")
|
||||
(defconst iso8601--week-date-match
|
||||
"\\([+-]\\)?\\([0-9][0-9][0-9][0-9]\\)-?W\\([0-9][0-9]\\)-?\\([0-9]\\)?")
|
||||
"\\([+-]?[0-9][0-9][0-9][0-9]\\)-?W\\([0-9][0-9]\\)-?\\([0-9]\\)?")
|
||||
(defconst iso8601--ordinal-date-match
|
||||
"\\([+-]\\)?\\([0-9][0-9][0-9][0-9]\\)-?\\([0-9][0-9][0-9]\\)")
|
||||
"\\([+-]?[0-9][0-9][0-9][0-9]\\)-?\\([0-9][0-9][0-9]\\)")
|
||||
(defconst iso8601--date-match
|
||||
(iso8601--concat-regexps
|
||||
(list iso8601--year-match
|
||||
|
@ -145,21 +145,18 @@ See `decode-time' for the meaning of FORM."
|
|||
;; Just a year: [+-]YYYY.
|
||||
((iso8601--match iso8601--year-match string)
|
||||
(iso8601--decoded-time
|
||||
:year (iso8601--adjust-year (match-string 1 string)
|
||||
(match-string 2 string))))
|
||||
:year (string-to-number string)))
|
||||
;; Calendar dates: YYYY-MM-DD and variants.
|
||||
((iso8601--match iso8601--full-date-match string)
|
||||
(iso8601--decoded-time
|
||||
:year (iso8601--adjust-year (match-string 1 string)
|
||||
(match-string 2 string))
|
||||
:month (match-string 3 string)
|
||||
:day (match-string 4 string)))
|
||||
:year (string-to-number (match-string 1 string))
|
||||
:month (match-string 2 string)
|
||||
:day (match-string 3 string)))
|
||||
;; Calendar date without day: YYYY-MM.
|
||||
((iso8601--match iso8601--without-day-match string)
|
||||
(iso8601--decoded-time
|
||||
:year (iso8601--adjust-year (match-string 1 string)
|
||||
(match-string 2 string))
|
||||
:month (match-string 3 string)))
|
||||
:year (string-to-number string)
|
||||
:month (match-string 2 string)))
|
||||
;; Outdated date without year: --MM-DD
|
||||
((iso8601--match iso8601--outdated-date-match string)
|
||||
(iso8601--decoded-time
|
||||
|
@ -167,11 +164,10 @@ See `decode-time' for the meaning of FORM."
|
|||
:day (match-string 2 string)))
|
||||
;; Week dates: YYYY-Www-D
|
||||
((iso8601--match iso8601--week-date-match string)
|
||||
(let* ((year (iso8601--adjust-year (match-string 1 string)
|
||||
(match-string 2 string)))
|
||||
(week (string-to-number (match-string 3 string)))
|
||||
(day-of-week (and (match-string 4 string)
|
||||
(string-to-number (match-string 4 string))))
|
||||
(let* ((year (string-to-number string))
|
||||
(week (string-to-number (match-string 2 string)))
|
||||
(day-of-week (and (match-string 3 string)
|
||||
(string-to-number (match-string 3 string))))
|
||||
(jan-start (decoded-time-weekday
|
||||
(decode-time
|
||||
(iso8601--encode-time
|
||||
|
@ -199,9 +195,8 @@ See `decode-time' for the meaning of FORM."
|
|||
:day (decoded-time-day month-day)))))
|
||||
;; Ordinal dates: YYYY-DDD
|
||||
((iso8601--match iso8601--ordinal-date-match string)
|
||||
(let* ((year (iso8601--adjust-year (match-string 1 string)
|
||||
(match-string 2 string)))
|
||||
(ordinal (string-to-number (match-string 3 string)))
|
||||
(let* ((year (string-to-number (match-string 1 string)))
|
||||
(ordinal (string-to-number (match-string 2 string)))
|
||||
(month-day (date-ordinal-to-time year ordinal)))
|
||||
(iso8601--decoded-time :year year
|
||||
:month (decoded-time-month month-day)
|
||||
|
@ -209,16 +204,6 @@ See `decode-time' for the meaning of FORM."
|
|||
(t
|
||||
(signal 'wrong-type-argument string))))
|
||||
|
||||
(defun iso8601--adjust-year (sign year)
|
||||
(save-match-data
|
||||
(let ((year (if (stringp year)
|
||||
(string-to-number year)
|
||||
year)))
|
||||
(if (string= sign "-")
|
||||
;; -0001 is 2 BCE.
|
||||
(1- (- year))
|
||||
year))))
|
||||
|
||||
(defun iso8601-parse-time (string &optional form)
|
||||
"Parse STRING, which should be an ISO 8601 time string.
|
||||
The return value will be a `decode-time' structure with just the
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
(should (equal (iso8601-parse-date "1985")
|
||||
'(nil nil nil nil nil 1985 nil nil nil)))
|
||||
(should (equal (iso8601-parse-date "-0003")
|
||||
'(nil nil nil nil nil -4 nil nil nil)))
|
||||
'(nil nil nil nil nil -3 nil nil nil)))
|
||||
(should (equal (iso8601-parse-date "+1985")
|
||||
'(nil nil nil nil nil 1985 nil nil nil))))
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue