summaryrefslogtreecommitdiff
path: root/lisp/calendar/time-date.el
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2019-08-16 22:09:04 -0700
committerPaul Eggert <eggert@cs.ucla.edu>2019-08-16 23:25:07 -0700
commit37257d6acadff17bd1e52cfa460950bcb684c5c3 (patch)
treeab7088cfa725561c8456f388cff79466948b3532 /lisp/calendar/time-date.el
parentd7c9ed8445d13de7350be3360d68717362f89929 (diff)
downloademacs-37257d6acadff17bd1e52cfa460950bcb684c5c3.tar.gz
More-compatible subsecond calendrical timestamps
Instead of appending a subseconds member to the result of ‘decode-time’, this keeps the format unchanged unless you give a new optional argument to ‘decode-time’. Also, the augmented format now puts the subsecond info in the SECONDS element, so the total number of elements is unchanged; this is more compatible with code that expects the traditional 9 elements, such as ‘(pcase decoded-time (`(,SEC ,MIN ,HOUR ,DAY ,MON ,YEAR ,DOW ,DST ,ZONE) ...) ...)’. * doc/lispref/os.texi, doc/misc/emacs-mime.texi, etc/NEWS: * lisp/net/soap-client.el (soap-decode-date-time): * lisp/simple.el (decoded-time): Document the new behavior. * lisp/calendar/icalendar.el (icalendar--decode-isodatetime): * lisp/calendar/iso8601.el (iso8601-parse) (iso8601-parse-time, iso8601-parse-duration) (iso8601--decoded-time): * lisp/calendar/parse-time.el (parse-time-string): * lisp/calendar/time-date.el (decoded-time-add) (decoded-time--alter-second): * lisp/org/org.el (org-parse-time-string): * lisp/simple.el (decoded-time): * src/timefns.c (Fdecode_time, Fencode_time): * test/lisp/calendar/icalendar-tests.el: (icalendar--decode-isodatetime): * test/lisp/calendar/iso8601-tests.el (test-iso8601-date-years) (test-iso8601-date-dates, test-iso8601-date-obsolete) (test-iso8601-date-weeks, test-iso8601-date-ordinals) (test-iso8601-time, test-iso8601-combined) (test-iso8601-duration, test-iso8601-intervals) (standard-test-dates, standard-test-time-of-day-fractions) (standard-test-time-of-day-beginning-of-day) (standard-test-time-of-day-utc) (standard-test-time-of-day-zone) (standard-test-date-and-time-of-day, standard-test-interval): * test/lisp/calendar/parse-time-tests.el (parse-time-tests): * test/src/timefns-tests.el (format-time-string-with-zone) (encode-time-dst-numeric-zone): Revert recent changes that added a SUBSECS member to calendrical timestamps, since that component is no longer present (the info, if any, is now in the SECONDS member). * lisp/calendar/time-date.el (decoded-time-add) (decoded-time--alter-second): Support fractional seconds in the new form. Simplify. * src/timefns.c (Fdecode_time): Support new arg FORM. (Fencode_time): Support subsecond resolution. * test/src/timefns-tests.el (format-time-string-with-zone) (decode-then-encode-time): Test subsecond calendrical timestamps.
Diffstat (limited to 'lisp/calendar/time-date.el')
-rw-r--r--lisp/calendar/time-date.el75
1 files changed, 26 insertions, 49 deletions
diff --git a/lisp/calendar/time-date.el b/lisp/calendar/time-date.el
index fa5e886869a..f3d252f03c6 100644
--- a/lisp/calendar/time-date.el
+++ b/lisp/calendar/time-date.el
@@ -420,26 +420,13 @@ changes in daylight saving time are not taken into account."
;; Do the time part, which is pretty simple (except for leap
;; seconds, I guess).
- (setq seconds (+ (* (or (decoded-time-hour delta) 0) 3600)
- (* (or (decoded-time-minute delta) 0) 60)
- (or (decoded-time-second delta) 0)))
- (when (decoded-time-subsec delta)
- (let* ((subsec (time-convert (time-add (decoded-time-subsec time)
- (decoded-time-subsec delta))
- t))
- (s (time-convert subsec 'integer)))
- (setq seconds (+ seconds s))
- (setf (decoded-time-subsec time) (time-subtract subsec s))))
-
;; Time zone adjustments are basically the same as time adjustments.
- (setq seconds (+ seconds (or (decoded-time-zone delta) 0)))
-
- (cond
- ((> seconds 0)
- (decoded-time--alter-second time seconds t))
- ((< seconds 0)
- (decoded-time--alter-second time (abs seconds) nil)))
+ (setq seconds (time-add (+ (* (or (decoded-time-hour delta) 0) 3600)
+ (* (or (decoded-time-minute delta) 0) 60)
+ (or (decoded-time-zone delta) 0))
+ (or (decoded-time-second delta) 0)))
+ (decoded-time--alter-second time seconds)
time))
(defun decoded-time--alter-month (time increase)
@@ -472,38 +459,31 @@ changes in daylight saving time are not taken into account."
(date-days-in-month (decoded-time-year time)
(decoded-time-month time))))))
-(defun decoded-time--alter-second (time seconds increase)
- "Increase or decrease the time in TIME by SECONDS."
- (let ((old (+ (* (or (decoded-time-hour time) 0) 3600)
- (* (or (decoded-time-minute time) 0) 60)
- (or (decoded-time-second time) 0))))
-
- (if increase
- (progn
- (setq old (+ old seconds))
- (setf (decoded-time-second time) (% old 60)
- (decoded-time-minute time) (% (/ old 60) 60)
- (decoded-time-hour time) (% (/ old 3600) 24))
- ;; Hm... DST...
- (let ((days (/ old (* 60 60 24))))
- (while (> days 0)
- (decoded-time--alter-day time t)
- (cl-decf days))))
- (setq old (abs (- old seconds)))
- (setf (decoded-time-second time) (% old 60)
- (decoded-time-minute time) (% (/ old 60) 60)
- (decoded-time-hour time) (% (/ old 3600) 24))
- ;; Hm... DST...
- (let ((days (/ old (* 60 60 24))))
- (while (> days 0)
- (decoded-time--alter-day time nil)
- (cl-decf days))))))
+(defun decoded-time--alter-second (time seconds)
+ "Increase the time in TIME by SECONDS."
+ (let* ((secsperday 86400)
+ (old (time-add (+ (* 3600 (or (decoded-time-hour time) 0))
+ (* 60 (or (decoded-time-minute time) 0)))
+ (or (decoded-time-second time) 0)))
+ (new (time-add old seconds)))
+ ;; Hm... DST...
+ (while (time-less-p new 0)
+ (decoded-time--alter-day time nil)
+ (setq new (time-add new secsperday)))
+ (while (not (time-less-p new secsperday))
+ (decoded-time--alter-day time t)
+ (setq new (time-subtract new secsperday)))
+ (let ((sec (time-convert new 'integer)))
+ (setf (decoded-time-second time) (time-add (% sec 60)
+ (time-subtract new sec))
+ (decoded-time-minute time) (% (/ sec 60) 60)
+ (decoded-time-hour time) (/ sec 3600)))))
(cl-defun make-decoded-time (&key second minute hour
day month year
- dst zone subsec)
+ dst zone)
"Return a `decoded-time' structure with only the keywords given filled out."
- (list second minute hour day month year nil dst zone subsec))
+ (list second minute hour day month year nil dst zone))
(defun decoded-time-set-defaults (time &optional default-zone)
"Set any nil values in `decoded-time' TIME to default values.
@@ -533,9 +513,6 @@ TIME is modified and returned."
(when (and (not (decoded-time-zone time))
default-zone)
(setf (decoded-time-zone time) 0))
-
- (unless (decoded-time-subsec time)
- (setf (decoded-time-subsec time) 0))
time)
(provide 'time-date)