diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2018-10-03 09:10:01 -0700 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2018-10-06 23:31:04 -0700 |
commit | 93fe420942c08111a6048af7c4d7807c61d80a09 (patch) | |
tree | 9ec406b06d09cde9573e757574e9e626e86d7a77 /lisp/calendar/cal-dst.el | |
parent | 84f39d3389209e566dde9acbdd78f5572f0c6751 (diff) | |
download | emacs-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.el | 55 |
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") |