summaryrefslogtreecommitdiff
path: root/lisp/calendar/cal-dst.el
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2018-10-03 09:10:01 -0700
committerPaul Eggert <eggert@cs.ucla.edu>2018-10-06 23:31:04 -0700
commit93fe420942c08111a6048af7c4d7807c61d80a09 (patch)
tree9ec406b06d09cde9573e757574e9e626e86d7a77 /lisp/calendar/cal-dst.el
parent84f39d3389209e566dde9acbdd78f5572f0c6751 (diff)
downloademacs-93fe420942c08111a6048af7c4d7807c61d80a09.tar.gz
New (TICKS . HZ) timestamp format
This follows on a suggestion by Stefan Monnier in: https://lists.gnu.org/r/emacs-devel/2018-08/msg00991.html (Bug#32902). * doc/lispref/buffers.texi (Modification Time): * doc/lispref/os.texi (Processor Run Time, Time Calculations) * doc/lispref/processes.texi (System Processes): * doc/lispref/text.texi (Undo): Let the "Time of Day" section cover timestamp format details. * doc/lispref/os.texi (Time of Day): Say that timestamp internal format should not be assumed. Document new (ticks . hz) format. Omit mention of seconds-to-time since it is now just an alias for encode-time. (Time Conversion): Document encode-time extension. * etc/NEWS: Mention changes. * lisp/calendar/cal-dst.el (calendar-system-time-basis): Now const. * lisp/calendar/cal-dst.el (calendar-absolute-from-time) (calendar-time-from-absolute) (calendar-next-time-zone-transition): * lisp/emacs-lisp/timer.el (timer-next-integral-multiple-of-time): Simplify by using bignums, (TICKS . HZ), and new encode-time. * lisp/emacs-lisp/timer.el (timer-next-integral-multiple-of-time): Simplify by using bignums and new encode-time. * lisp/calendar/parse-time.el (parse-iso8601-time-string): Handle DST more accurately, by using new encode-time. * lisp/calendar/time-date.el (seconds-to-time): * lisp/calendar/timeclock.el (timeclock-seconds-to-time): Now just an alias for encode-time. * lisp/calendar/time-date.el (days-to-time): * lisp/emacs-lisp/timer.el (timer--time-setter): * lisp/net/ntlm.el (ntlm-compute-timestamp): * lisp/obsolete/vc-arch.el (vc-arch-add-tagline): * lisp/org/org-id.el (org-id-uuid, org-id-time-to-b36): * lisp/tar-mode (tar-octal-time): Don't assume timestamps default to list form. * lisp/tar-mode.el (tar-parse-octal-long-integer): Now an obsolete alias for tar-parse-octal-integer. * src/keyboard.c (decode_timer): Adjust to changes to time decoding functions elsewhere. * src/timefns.c: Include bignum.h, limits.h. (FASTER_TIMEFNS): New macro. (WARN_OBSOLETE_TIMESTAMPS, CURRENT_TIME_LIST) (timespec_hz, trillion, ztrillion): New constants. (make_timeval): Use TIME_T_MAX instead of its definiens. (check_time_validity, time_add, time_subtract): Remove. All uses removed. (disassemble_lisp_time): Remove; old code now folded into decode_lisp_time. All callers changed. (invalid_hz, s_ns_to_double, ticks_hz_list4, mpz_set_time) (timespec_mpz, timespec_ticks, time_hz_ticks) (lisp_time_hz_ticks, lisp_time_seconds) (time_form_stamp, lisp_time_form_stamp, decode_ticks_hz) (decode_lisp_time, mpz_time, list4_to_timespec): New functions. (decode_float_time, decode_time_components, lisp_to_timespec): Adjust to new struct lisp_time, which does not lose information like the old one did. (enum timeform): New enum. (decode_time_components): New arg FORM. All callers changed. RESULT and DRESULT are now mutually exclusive; no callers need to change because of this. (decode_time_components, lisp_time_struct) (lisp_seconds_argument, time_arith, make_lisp_time, Ffloat_time) (Fencode_time): Add support for (TICKS . HZ) form. (DECODE_SECS_ONLY): New constant. (lisp_time_struct): 2nd arg is now enum timeform, not int. All callers changed. (check_tm_member): Support bignums.m (Fencode_time): Add new two-arg functionality. * src/systime.h (struct lisp_time): Now ticks+hz rather than hi+lo+us+ps, since ticks+hz does not lose info. * test/src/systime-tests.el (time-equal-p-nil-nil): New test.
Diffstat (limited to 'lisp/calendar/cal-dst.el')
-rw-r--r--lisp/calendar/cal-dst.el55
1 files changed, 17 insertions, 38 deletions
diff --git a/lisp/calendar/cal-dst.el b/lisp/calendar/cal-dst.el
index 00a8e7498af..25264bda097 100644
--- a/lisp/calendar/cal-dst.el
+++ b/lisp/calendar/cal-dst.el
@@ -97,62 +97,48 @@ If the locale never uses daylight saving time, set this to nil."
;;;###autoload
(put 'calendar-current-time-zone-cache 'risky-local-variable t)
-(defvar calendar-system-time-basis
+(defconst calendar-system-time-basis
(calendar-absolute-from-gregorian '(1 1 1970))
"Absolute date of starting date of system clock.")
(defun calendar-absolute-from-time (x utc-diff)
"Absolute local date of time X; local time is UTC-DIFF seconds from UTC.
-X is (HIGH . LOW) or (HIGH LOW . IGNORED) where HIGH and LOW are the
-high and low 16 bits, respectively, of the number of seconds since
-1970-01-01 00:00:00 UTC, ignoring leap seconds.
+X is the number of seconds since 1970-01-01 00:00:00 UTC,
+ignoring leap seconds.
Returns the pair (ABS-DATE . SECONDS) where SECONDS after local midnight on
absolute date ABS-DATE is the equivalent moment to X."
- (let* ((h (car x))
- (xtail (cdr x))
- (l (+ utc-diff (if (numberp xtail) xtail (car xtail))))
- (u (+ (* 512 (mod h 675)) (floor l 128))))
- ;; Overflow is a terrible thing!
- (cons (+ calendar-system-time-basis
- ;; floor((2^16 h +l) / (60*60*24))
- (* 512 (floor h 675)) (floor u 675))
- ;; (2^16 h +l) mod (60*60*24)
- (+ (* (mod u 675) 128) (mod l 128)))))
+ (let ((secsperday 86400)
+ (local (+ x utc-diff)))
+ (cons (+ calendar-system-time-basis (floor local secsperday))
+ (mod local secsperday))))
(defun calendar-time-from-absolute (abs-date s)
"Time of absolute date ABS-DATE, S seconds after midnight.
-Returns the list (HIGH LOW) where HIGH and LOW are the high and low
-16 bits, respectively, of the number of seconds 1970-01-01 00:00:00 UTC,
-ignoring leap seconds, that is the equivalent moment to S seconds after
-midnight UTC on absolute date ABS-DATE."
- (let* ((a (- abs-date calendar-system-time-basis))
- (u (+ (* 163 (mod a 512)) (floor s 128))))
- ;; Overflow is a terrible thing!
- (list
- ;; floor((60*60*24*a + s) / 2^16)
- (+ a (* 163 (floor a 512)) (floor u 512))
- ;; (60*60*24*a + s) mod 2^16
- (+ (* 128 (mod u 512)) (mod s 128)))))
+Return the number of seconds since 1970-01-01 00:00:00 UTC,
+ignoring leap seconds, that is the equivalent moment to S seconds
+after midnight UTC on absolute date ABS-DATE."
+ (let ((secsperday 86400))
+ (+ s (* secsperday (- abs-date calendar-system-time-basis)))))
(defun calendar-next-time-zone-transition (time)
"Return the time of the next time zone transition after TIME.
Both TIME and the result are acceptable arguments to `current-time-zone'.
Return nil if no such transition can be found."
- (let* ((base 65536) ; 2^16 = base of current-time output
- (quarter-multiple 120) ; approx = (seconds per quarter year) / base
+ (let* ((time (encode-time time 'integer))
(time-zone (current-time-zone time))
(time-utc-diff (car time-zone))
hi
hi-zone
(hi-utc-diff time-utc-diff)
+ (quarter-seconds 7889238) ; Average seconds per 1/4 Gregorian year.
(quarters '(2 1 3)))
;; Heuristic: probe the time zone offset in the next three calendar
;; quarters, looking for a time zone offset different from TIME.
(while (and quarters (eq time-utc-diff hi-utc-diff))
- (setq hi (cons (+ (car time) (* (car quarters) quarter-multiple)) 0)
+ (setq hi (+ time (* (car quarters) quarter-seconds))
hi-zone (current-time-zone hi)
hi-utc-diff (car hi-zone)
quarters (cdr quarters)))
@@ -163,23 +149,16 @@ Return nil if no such transition can be found."
;; Now HI is after the next time zone transition.
;; Set LO to TIME, and then binary search to increase LO and decrease HI
;; until LO is just before and HI is just after the time zone transition.
- (let* ((tail (cdr time))
- (lo (cons (car time) (if (numberp tail) tail (car tail))))
+ (let* ((lo time)
probe)
(while
;; Set PROBE to halfway between LO and HI, rounding down.
;; If PROBE equals LO, we are done.
- (let* ((lsum (+ (cdr lo) (cdr hi)))
- (hsum (+ (car lo) (car hi) (/ lsum base)))
- (hsumodd (logand 1 hsum)))
- (setq probe (cons (/ (- hsum hsumodd) 2)
- (/ (+ (* hsumodd base) (% lsum base)) 2)))
- (not (equal lo probe)))
+ (not (= lo (setq probe (/ (+ lo hi) 2))))
;; Set either LO or HI to PROBE, depending on probe results.
(if (eq (car (current-time-zone probe)) hi-utc-diff)
(setq hi probe)
(setq lo probe)))
- (setcdr hi (list (cdr hi)))
hi))))
(autoload 'calendar-persian-to-absolute "cal-persia")