diff options
| author | Lute Kamstra | 2005-03-23 10:09:18 +0000 |
|---|---|---|
| committer | Lute Kamstra | 2005-03-23 10:09:18 +0000 |
| commit | ca2d9ad84391dcb97ce9b9514a7b3377be3d68c2 (patch) | |
| tree | 9c5b6a34514a7320af272b753efcdf21a62ea8d4 | |
| parent | 8725c7925ef1ce95efb1f50d48d17f437e9c46a4 (diff) | |
| download | emacs-ca2d9ad84391dcb97ce9b9514a7b3377be3d68c2.tar.gz emacs-ca2d9ad84391dcb97ce9b9514a7b3377be3d68c2.zip | |
Add comment on time value formats. Don't require parse-time.
(with-decoded-time-value): New macro.
(encode-time-value): New function.
(time-to-seconds, time-less-p, time-subtract, time-add): Use them.
(days-to-time): Return a valid time value when arg is huge.
(time-since): Use time-subtract.
(time-to-number-of-days): Use time-to-seconds.
| -rw-r--r-- | lisp/ChangeLog | 11 | ||||
| -rw-r--r-- | lisp/calendar/time-date.el | 157 |
2 files changed, 120 insertions, 48 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 4e2472e70f9..b199bf9e3bf 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,14 @@ | |||
| 1 | 2005-03-23 Lute Kamstra <lute@gnu.org> | ||
| 2 | |||
| 3 | * calendar/time-date.el: Add comment on time value formats. Don't | ||
| 4 | require parse-time. | ||
| 5 | (with-decoded-time-value): New macro. | ||
| 6 | (encode-time-value): New function. | ||
| 7 | (time-to-seconds, time-less-p, time-subtract, time-add): Use them. | ||
| 8 | (days-to-time): Return a valid time value when arg is huge. | ||
| 9 | (time-since): Use time-subtract. | ||
| 10 | (time-to-number-of-days): Use time-to-seconds. | ||
| 11 | |||
| 1 | 2005-03-23 David Ponce <david@dponce.com> | 12 | 2005-03-23 David Ponce <david@dponce.com> |
| 2 | 13 | ||
| 3 | * recentf.el: (recentf-keep): New option. | 14 | * recentf.el: (recentf-keep): New option. |
diff --git a/lisp/calendar/time-date.el b/lisp/calendar/time-date.el index 3a850717298..a4acb8b9291 100644 --- a/lisp/calendar/time-date.el +++ b/lisp/calendar/time-date.el | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | ;;; time-date.el --- date and time handling functions | 1 | ;;; time-date.el --- date and time handling functions |
| 2 | ;; Copyright (C) 1998, 1999, 2000, 2004 Free Software Foundation, Inc. | 2 | ;; Copyright (C) 1998, 1999, 2000, 2004, 2005 Free Software Foundation, Inc. |
| 3 | 3 | ||
| 4 | ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org> | 4 | ;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org> |
| 5 | ;; Masanobu Umeda <umerin@mse.kyutech.ac.jp> | 5 | ;; Masanobu Umeda <umerin@mse.kyutech.ac.jp> |
| @@ -24,9 +24,71 @@ | |||
| 24 | 24 | ||
| 25 | ;;; Commentary: | 25 | ;;; Commentary: |
| 26 | 26 | ||
| 27 | ;; Time values come in three formats. The oldest format is a cons | ||
| 28 | ;; cell of the form (HIGH . LOW). This format is obsolete, but still | ||
| 29 | ;; supported. The two other formats are the lists (HIGH LOW) and | ||
| 30 | ;; (HIGH LOW MICRO). The first two formats specify HIGH * 2^16 + LOW | ||
| 31 | ;; seconds; the third format specifies HIGH * 2^16 + LOW + MICRO / | ||
| 32 | ;; 1000000 seconds. We should have 0 <= MICRO < 1000000 and 0 <= LOW | ||
| 33 | ;; < 2^16. If the time value represents a point in time, then HIGH is | ||
| 34 | ;; nonnegative. If the time value is a time difference, then HIGH can | ||
| 35 | ;; be negative as well. The macro `with-decoded-time-value' and the | ||
| 36 | ;; function `encode-time-value' make it easier to deal with these | ||
| 37 | ;; three formats. See `time-subtract' for an example of how to use | ||
| 38 | ;; them. | ||
| 39 | |||
| 27 | ;;; Code: | 40 | ;;; Code: |
| 28 | 41 | ||
| 29 | (require 'parse-time) | 42 | (defmacro with-decoded-time-value (varlist &rest body) |
| 43 | "Decode a time value and bind it according to VARLIST, then eval BODY. | ||
| 44 | |||
| 45 | The value of the last form in BODY is returned. | ||
| 46 | |||
| 47 | Each element of the list VARLIST is a list of the form | ||
| 48 | \(HIGH-SYMBOL LOW-SYMBOL MICRO-SYMBOL [TYPE-SYMBOL] TIME-VALUE). | ||
| 49 | The time value TIME-VALUE is decoded and the result it bound to | ||
| 50 | the symbols HIGH-SYMBOL, LOW-SYMBOL and MICRO-SYMBOL. | ||
| 51 | |||
| 52 | The optional TYPE-SYMBOL is bound to the type of the time value. | ||
| 53 | Type 0 is the cons cell (HIGH . LOW), type 1 is the list (HIGH | ||
| 54 | LOW), and type 3 is the list (HIGH LOW MICRO)." | ||
| 55 | (declare (indent 1) | ||
| 56 | (debug ((&rest (symbolp symbolp symbolp &or [symbolp form] form)) | ||
| 57 | body))) | ||
| 58 | (if varlist | ||
| 59 | (let* ((elt (pop varlist)) | ||
| 60 | (high (pop elt)) | ||
| 61 | (low (pop elt)) | ||
| 62 | (micro (pop elt)) | ||
| 63 | (type (unless (eq (length elt) 1) | ||
| 64 | (pop elt))) | ||
| 65 | (time-value (car elt)) | ||
| 66 | (gensym (make-symbol "time"))) | ||
| 67 | `(let* ,(append `((,gensym ,time-value) | ||
| 68 | (,high (pop ,gensym)) | ||
| 69 | ,low ,micro) | ||
| 70 | (when type `(,type))) | ||
| 71 | (if (consp ,gensym) | ||
| 72 | (progn | ||
| 73 | (setq ,low (pop ,gensym)) | ||
| 74 | (if ,gensym | ||
| 75 | ,(append `(setq ,micro (car ,gensym)) | ||
| 76 | (when type `(,type 2))) | ||
| 77 | ,(append `(setq ,micro 0) | ||
| 78 | (when type `(,type 1))))) | ||
| 79 | ,(append `(setq ,low ,gensym ,micro 0) | ||
| 80 | (when type `(,type 0)))) | ||
| 81 | (with-decoded-time-value ,varlist ,@body))) | ||
| 82 | `(progn ,@body))) | ||
| 83 | |||
| 84 | (defun encode-time-value (high low micro type) | ||
| 85 | "Encode HIGH, LOW, and MICRO into a time value of type TYPE. | ||
| 86 | Type 0 is the cons cell (HIGH . LOW), type 1 is the list (HIGH LOW), | ||
| 87 | and type 3 is the list (HIGH LOW MICRO)." | ||
| 88 | (cond | ||
| 89 | ((eq type 0) (cons high low)) | ||
| 90 | ((eq type 1) (list high low)) | ||
| 91 | ((eq type 2) (list high low micro)))) | ||
| 30 | 92 | ||
| 31 | (autoload 'timezone-make-date-arpa-standard "timezone") | 93 | (autoload 'timezone-make-date-arpa-standard "timezone") |
| 32 | 94 | ||
| @@ -49,33 +111,37 @@ | |||
| 49 | (defun time-to-seconds (time) | 111 | (defun time-to-seconds (time) |
| 50 | "Convert time value TIME to a floating point number. | 112 | "Convert time value TIME to a floating point number. |
| 51 | You can use `float-time' instead." | 113 | You can use `float-time' instead." |
| 52 | (+ (* (car time) 65536.0) | 114 | (with-decoded-time-value ((high low micro time)) |
| 53 | (cadr time) | 115 | (+ (* 1.0 high #x10000) |
| 54 | (/ (or (nth 2 time) 0) 1000000.0))) | 116 | low |
| 117 | (/ micro 1000000.0)))) | ||
| 55 | 118 | ||
| 56 | ;;;###autoload | 119 | ;;;###autoload |
| 57 | (defun seconds-to-time (seconds) | 120 | (defun seconds-to-time (seconds) |
| 58 | "Convert SECONDS (a floating point number) to a time value." | 121 | "Convert SECONDS (a floating point number) to a time value." |
| 59 | (list (floor seconds 65536) | 122 | (list (floor seconds #x10000) |
| 60 | (floor (mod seconds 65536)) | 123 | (floor (mod seconds #x10000)) |
| 61 | (floor (* (- seconds (ffloor seconds)) 1000000)))) | 124 | (floor (* (- seconds (ffloor seconds)) 1000000)))) |
| 62 | 125 | ||
| 63 | ;;;###autoload | 126 | ;;;###autoload |
| 64 | (defun time-less-p (t1 t2) | 127 | (defun time-less-p (t1 t2) |
| 65 | "Say whether time value T1 is less than time value T2." | 128 | "Say whether time value T1 is less than time value T2." |
| 66 | (or (< (car t1) (car t2)) | 129 | (with-decoded-time-value ((high1 low1 micro1 t1) |
| 67 | (and (= (car t1) (car t2)) | 130 | (high2 low2 micro2 t2)) |
| 68 | (< (nth 1 t1) (nth 1 t2))))) | 131 | (or (< high1 high2) |
| 132 | (and (= high1 high2) | ||
| 133 | (or (< low1 low2) | ||
| 134 | (and (= low1 low2) | ||
| 135 | (< micro1 micro2))))))) | ||
| 69 | 136 | ||
| 70 | ;;;###autoload | 137 | ;;;###autoload |
| 71 | (defun days-to-time (days) | 138 | (defun days-to-time (days) |
| 72 | "Convert DAYS into a time value." | 139 | "Convert DAYS into a time value." |
| 73 | (let* ((seconds (* 1.0 days 60 60 24)) | 140 | (let* ((seconds (* 1.0 days 60 60 24)) |
| 74 | (rest (expt 2 16)) | 141 | (high (condition-case nil (floor (/ seconds #x10000)) |
| 75 | (ms (condition-case nil (floor (/ seconds rest)) | 142 | (range-error most-positive-fixnum)))) |
| 76 | (range-error (expt 2 16))))) | 143 | (list high (condition-case nil (floor (- seconds (* 1.0 high #x10000))) |
| 77 | (list ms (condition-case nil (round (- seconds (* ms rest))) | 144 | (range-error #xffff))))) |
| 78 | (range-error (expt 2 16)))))) | ||
| 79 | 145 | ||
| 80 | ;;;###autoload | 146 | ;;;###autoload |
| 81 | (defun time-since (time) | 147 | (defun time-since (time) |
| @@ -84,11 +150,7 @@ TIME should be either a time value or a date-time string." | |||
| 84 | (when (stringp time) | 150 | (when (stringp time) |
| 85 | ;; Convert date strings to internal time. | 151 | ;; Convert date strings to internal time. |
| 86 | (setq time (date-to-time time))) | 152 | (setq time (date-to-time time))) |
| 87 | (let* ((current (current-time)) | 153 | (time-subtract (current-time) time)) |
| 88 | (rest (when (< (nth 1 current) (nth 1 time)) | ||
| 89 | (expt 2 16)))) | ||
| 90 | (list (- (+ (car current) (if rest -1 0)) (car time)) | ||
| 91 | (- (+ (or rest 0) (nth 1 current)) (nth 1 time))))) | ||
| 92 | 154 | ||
| 93 | ;;;###autoload | 155 | ;;;###autoload |
| 94 | (defalias 'subtract-time 'time-subtract) | 156 | (defalias 'subtract-time 'time-subtract) |
| @@ -97,37 +159,36 @@ TIME should be either a time value or a date-time string." | |||
| 97 | (defun time-subtract (t1 t2) | 159 | (defun time-subtract (t1 t2) |
| 98 | "Subtract two time values. | 160 | "Subtract two time values. |
| 99 | Return the difference in the format of a time value." | 161 | Return the difference in the format of a time value." |
| 100 | (let ((borrow (< (cadr t1) (cadr t2)))) | 162 | (with-decoded-time-value ((high low micro type t1) |
| 101 | (list (- (car t1) (car t2) (if borrow 1 0)) | 163 | (high2 low2 micro2 type2 t2)) |
| 102 | (- (+ (if borrow 65536 0) (cadr t1)) (cadr t2))))) | 164 | (setq high (- high high2) |
| 165 | low (- low low2) | ||
| 166 | micro (- micro micro2) | ||
| 167 | type (max type type2)) | ||
| 168 | (when (< micro 0) | ||
| 169 | (setq low (1- low) | ||
| 170 | micro (+ micro 1000000))) | ||
| 171 | (when (< low 0) | ||
| 172 | (setq high (1- high) | ||
| 173 | low (+ low #x10000))) | ||
| 174 | (encode-time-value high low micro type))) | ||
| 103 | 175 | ||
| 104 | ;;;###autoload | 176 | ;;;###autoload |
| 105 | (defun time-add (t1 t2) | 177 | (defun time-add (t1 t2) |
| 106 | "Add two time values. One should represent a time difference." | 178 | "Add two time values. One should represent a time difference." |
| 107 | (let ((high (car t1)) | 179 | (with-decoded-time-value ((high low micro type t1) |
| 108 | (low (if (consp (cdr t1)) (nth 1 t1) (cdr t1))) | 180 | (high2 low2 micro2 type2 t2)) |
| 109 | (micro (if (numberp (car-safe (cdr-safe (cdr t1)))) | 181 | (setq high (+ high high2) |
| 110 | (nth 2 t1) | 182 | low (+ low low2) |
| 111 | 0)) | 183 | micro (+ micro micro2) |
| 112 | (high2 (car t2)) | 184 | type (max type type2)) |
| 113 | (low2 (if (consp (cdr t2)) (nth 1 t2) (cdr t2))) | 185 | (when (>= micro 1000000) |
| 114 | (micro2 (if (numberp (car-safe (cdr-safe (cdr t2)))) | 186 | (setq low (1+ low) |
| 115 | (nth 2 t2) | 187 | micro (- micro 1000000))) |
| 116 | 0))) | 188 | (when (>= low #x10000) |
| 117 | ;; Add | 189 | (setq high (1+ high) |
| 118 | (setq micro (+ micro micro2)) | 190 | low (- low #x10000))) |
| 119 | (setq low (+ low low2)) | 191 | (encode-time-value high low micro type))) |
| 120 | (setq high (+ high high2)) | ||
| 121 | |||
| 122 | ;; Normalize | ||
| 123 | ;; `/' rounds towards zero while `mod' returns a positive number, | ||
| 124 | ;; so we can't rely on (= a (+ (* 100 (/ a 100)) (mod a 100))). | ||
| 125 | (setq low (+ low (/ micro 1000000) (if (< micro 0) -1 0))) | ||
| 126 | (setq micro (mod micro 1000000)) | ||
| 127 | (setq high (+ high (/ low 65536) (if (< low 0) -1 0))) | ||
| 128 | (setq low (logand low 65535)) | ||
| 129 | |||
| 130 | (list high low micro))) | ||
| 131 | 192 | ||
| 132 | ;;;###autoload | 193 | ;;;###autoload |
| 133 | (defun date-to-day (date) | 194 | (defun date-to-day (date) |
| @@ -180,7 +241,7 @@ The Gregorian date Sunday, December 31, 1bce is imaginary." | |||
| 180 | (defun time-to-number-of-days (time) | 241 | (defun time-to-number-of-days (time) |
| 181 | "Return the number of days represented by TIME. | 242 | "Return the number of days represented by TIME. |
| 182 | The number of days will be returned as a floating point number." | 243 | The number of days will be returned as a floating point number." |
| 183 | (/ (+ (* 1.0 65536 (car time)) (cadr time)) (* 60 60 24))) | 244 | (/ (time-to-seconds time) (* 60 60 24))) |
| 184 | 245 | ||
| 185 | ;;;###autoload | 246 | ;;;###autoload |
| 186 | (defun safe-date-to-time (date) | 247 | (defun safe-date-to-time (date) |