Commit 93fe4209 authored by Paul Eggert's avatar Paul Eggert

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.
parent 84f39d33
......@@ -648,10 +648,7 @@ file should not be done.
@defun visited-file-modtime
This function returns the current buffer's recorded last file
modification time, as a list of the form @code{(@var{high} @var{low}
@var{microsec} @var{picosec})}. (This is the same format that
@code{file-attributes} uses to return time values; @pxref{File
Attributes}.)
modification time, as a Lisp timestamp (@pxref{Time of Day}).
If the buffer has no recorded last modification time, this function
returns zero. This case occurs, for instance, if the buffer is not
......@@ -671,9 +668,8 @@ is not @code{nil}, and otherwise to the last modification time of the
visited file.
If @var{time} is neither @code{nil} nor an integer flag returned
by @code{visited-file-modtime}, it should have the form
@code{(@var{high} @var{low} @var{microsec} @var{picosec})},
the format used by @code{current-time} (@pxref{Time of Day}).
by @code{visited-file-modtime}, it should be a Lisp time value
(@pxref{Time of Day}).
This function is useful if the buffer was not read from the file
normally, or if the file itself has been changed for some known benign
......
This diff is collapsed.
......@@ -2158,19 +2158,17 @@ faults for all the child processes of the given process.
@item utime
Time spent by the process in the user context, for running the
application's code. The corresponding @var{value} is in the
@w{@code{(@var{high} @var{low} @var{microsec} @var{picosec})}} format, the same
format used by functions @code{current-time} (@pxref{Time of Day,
current-time}) and @code{file-attributes} (@pxref{File Attributes}).
application's code. The corresponding @var{value} is a Lisp
timestamp (@pxref{Time of Day}).
@item stime
Time spent by the process in the system (kernel) context, for
processing system calls. The corresponding @var{value} is in the same
format as for @code{utime}.
processing system calls. The corresponding @var{value} is a Lisp
timestamp.
@item time
The sum of @code{utime} and @code{stime}. The corresponding
@var{value} is in the same format as for @code{utime}.
@var{value} is a Lisp timestamp.
@item cutime
@itemx cstime
......@@ -2189,13 +2187,10 @@ nice values get scheduled more favorably.)
The number of threads in the process.
@item start
The time when the process was started, in the same
@code{(@var{high} @var{low} @var{microsec} @var{picosec})} format used by
@code{file-attributes} and @code{current-time}.
The time when the process was started, as a Lisp timestamp.
@item etime
The time elapsed since the process started, in the format @code{(@var{high}
@var{low} @var{microsec} @var{picosec})}.
The time elapsed since the process started, as a Lisp timestamp.
@item vsize
The virtual memory size of the process, measured in kilobytes.
......
......@@ -1327,9 +1327,8 @@ elements follow immediately after this element.
@item (t . @var{time-flag})
This kind of element indicates that an unmodified buffer became
modified. A @var{time-flag} of the form
@code{(@var{sec-high} @var{sec-low} @var{microsec}
@var{picosec})} represents the visited file's modification time as of
modified. A @var{time-flag} that is a non-integer Lisp timestamp
represents the visited file's modification time as of
when it was previously visited or saved, using the same format as
@code{current-time}; see @ref{Time of Day}.
A @var{time-flag} of 0 means the buffer does not correspond to any file;
......
......@@ -1524,12 +1524,12 @@ many mailers don't support it. @xref{rfc2231}.
@section time-date
While not really a part of the @acronym{MIME} library, it is convenient to
document this library here. It deals with parsing @code{Date} headers
document time conversion functions often used when parsing @code{Date} headers
and manipulating time. (Not by using tesseracts, though, I'm sorry to
say.)
These functions convert between five formats: A date string, an Emacs
time structure, a decoded time list, a second number, and a day number.
These functions convert between five formats: A date string, a Lisp
timestamp, a decoded time list, a second number, and a day number.
Here's a bunch of time/date/second/day examples:
......@@ -1537,35 +1537,41 @@ Here's a bunch of time/date/second/day examples:
(parse-time-string "Sat Sep 12 12:21:54 1998 +0200")
@result{} (54 21 12 12 9 1998 6 -1 7200)
(date-to-time "Sat Sep 12 12:21:54 1998 +0200")
@result{} (13818 19266)
(encode-time (date-to-time "Sat Sep 12 12:21:54 1998 +0200")
1000000)
@result{} (905595714000000 . 1000000)
(parse-iso8601-time-string "1998-09-12T12:21:54+0200")
@result{} (13818 19266)
(encode-time (parse-iso8601-time-string "1998-09-12T12:21:54+0200")
1000000)
@result{} (905595714000000 . 1000000)
(float-time '(13818 19266))
(float-time '(905595714000000 . 1000000))
@result{} 905595714.0
(seconds-to-time 905595714.0)
@result{} (13818 19266 0 0)
(encode-time 905595714.0 1000000)
@result{} (905595714000000 . 1000000)
(time-to-days '(13818 19266))
(time-to-days '(905595714000000 . 1000000))
@result{} 729644
(days-to-time 729644)
@result{} (961933 512)
(encode-time (days-to-time 729644) 1000000)
@result{} (63041241600000000 . 1000000)
(time-since '(13818 19266))
@result{} (6797 9607 984839 247000)
(encode-time (time-since '(905595714000000 . 1000000))
1000000)
@result{} (631963244775642171 . 1000000000)
(time-less-p '(13818 19266) '(13818 19145))
(time-less-p '(905595714000000 . 1000000)
'(905595593000000000 . 1000000000))
@result{} nil
(time-equal-p '(13818 19266) '(13818 19145))
@result{} nil
(time-equal-p '(905595593000000000 . 1000000000)
'(905595593000000 . 1000000 ))
@result{} t
(time-subtract '(13818 19266) '(13818 19145))
@result{} (0 121)
(time-subtract '(905595714000000 . 1000000)
'(905595593000000000 . 1000000000))
@result{} (121000000000 . 1000000000)
(days-between "Sat Sep 12 12:21:54 1998 +0200"
"Sat Sep 07 12:21:54 1998 +0200")
......@@ -1574,13 +1580,13 @@ Here's a bunch of time/date/second/day examples:
(date-leap-year-p 2000)
@result{} t
(time-to-day-in-year '(13818 19266))
(time-to-day-in-year '(905595714000000 . 1000000))
@result{} 255
(time-to-number-of-days
(time-since
(date-to-time "Mon, 01 Jan 2001 02:22:26 GMT")))
@result{} 4314.095589286675
@result{} 6472.722661506652
@end example
And finally, we have @code{safe-date-to-time}, which does the same as
......@@ -1595,22 +1601,24 @@ An RFC822 (or similar) date string. For instance: @code{"Sat Sep 12
12:21:54 1998 +0200"}.
@item time
An internal Emacs time. For instance: @code{(13818 26466 0 0)}.
A Lisp timestamp.
For instance: @code{(905595714000000 . 1000000)}.
@item seconds
A floating point representation of the internal Emacs time. For
instance: @code{905595714.0}.
An integer or floating point count of seconds. For instance:
@code{905595714.0}, @code{905595714}.
@item days
An integer number representing the number of days since 00000101. For
instance: @code{729644}.
@item decoded time
A list of decoded time. For instance: @code{(54 21 12 12 9 1998 6 t
A list of decoded time. For instance: @code{(54 21 12 12 9 1998 6 nil
7200)}.
@end table
All the examples above represent the same moment.
All the examples above represent the same moment, except that
@var{days} represents the day containing the moment.
These are the functions available:
......@@ -1621,8 +1629,9 @@ Take a date and return a time.
@item float-time
Take a time and return seconds. (This is a built-in function.)
@item seconds-to-time
Take seconds and return a time.
@item encode-time
Take seconds (and other ways to represent time, notably decoded time
lists), and return a time.
@item time-to-days
Take a time and return days.
......@@ -1645,7 +1654,7 @@ Take two times and say whether the first time is less (i.e., earlier)
than the second time. (This is a built-in function.)
@item time-equal-p
Check, whether two time values are equal. The time values must not be
Check whether two time values are equal. The time values need not be
in the same format. (This is a built-in function.)
@item time-since
......
......@@ -995,6 +995,21 @@ like file-attributes that compute file sizes and other attributes,
functions like process-id that compute process IDs, and functions like
user-uid and group-gid that compute user and group IDs.
+++
** Although the default timestamp format is still (HI LO US PS),
it is planned to change in a future Emacs version, to exploit bignums.
The documentation has been updated to mention that the timestamp
format may change and that programs should use functions like
format-time-string, decode-time, and encode-time rather than probing
the innards of a timestamp directly, or creating a timestamp by hand.
+++
** encode-time supports a new API (encode-time TIME &optional FORM).
This can convert decoded times and Lisp time values to Lisp timestamps
of various forms, including a new timestamp form (TICKS . HZ), where
TICKS is an integer and HZ is a positive integer denoting a clock
frequency. The old encode-time API is still supported.
+++
** 'time-add', 'time-subtract', and 'time-less-p' now accept
infinities and NaNs too, and propagate them or return nil like
......
......@@ -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")
......
......@@ -227,7 +227,7 @@ If DATE-STRING cannot be parsed, it falls back to
(tz-re (nth 2 parse-time-iso8601-regexp))
re-start
time seconds minute hour
day month year day-of-week dst tz)
day month year day-of-week (dst -1) tz)
;; We need to populate 'time' with
;; (SEC MIN HOUR DAY MON YEAR DOW DST TZ)
......@@ -243,6 +243,7 @@ If DATE-STRING cannot be parsed, it falls back to
seconds (string-to-number (match-string 3 date-string))
re-start (match-end 0))
(when (string-match tz-re date-string re-start)
(setq dst nil)
(if (string= "Z" (match-string 1 date-string))
(setq tz 0) ;; UTC timezone indicated by Z
(setq tz (+
......@@ -260,7 +261,7 @@ If DATE-STRING cannot be parsed, it falls back to
(setq time (parse-time-string date-string)))
(and time
(apply 'encode-time time))))
(encode-time time))))
(provide 'parse-time)
......
......@@ -168,15 +168,15 @@ If DATE lacks timezone information, GMT is assumed."
(defalias 'time-to-seconds 'float-time)
;;;###autoload
(defun seconds-to-time (seconds)
"Convert SECONDS to a time value."
(time-add 0 seconds))
(defalias 'seconds-to-time 'encode-time)
;;;###autoload
(defun days-to-time (days)
"Convert DAYS into a time value."
(let ((time (seconds-to-time (* 86400 days))))
(if (integerp days)
(let ((time (encode-time (* 86400 days))))
;; Traditionally, this returned a two-element list if DAYS was an integer.
;; Keep that tradition if encode-time outputs timestamps in list form.
(if (and (integerp days) (consp (cdr time)))
(setcdr (cdr time) nil))
time))
......
......@@ -534,8 +534,7 @@ non-nil, the amount returned will be relative to past time worked."
string)))
(define-obsolete-function-alias 'timeclock-time-to-seconds 'float-time "26.1")
(define-obsolete-function-alias 'timeclock-seconds-to-time 'seconds-to-time
"26.1")
(define-obsolete-function-alias 'timeclock-seconds-to-time 'encode-time "26.1")
;; Should today-only be removed in favor of timeclock-relative? - gm
(defsubst timeclock-when-to-leave (&optional today-only)
......
......@@ -57,17 +57,11 @@
(defun timer--time-setter (timer time)
(timer--check timer)
(setf (timer--high-seconds timer) (pop time))
(let ((low time) (usecs 0) (psecs 0))
(when (consp time)
(setq low (pop time))
(when time
(setq usecs (pop time))
(when time
(setq psecs (car time)))))
(setf (timer--low-seconds timer) low)
(setf (timer--usecs timer) usecs)
(setf (timer--psecs timer) psecs)
(let ((lt (encode-time time 'list)))
(setf (timer--high-seconds timer) (nth 0 lt))
(setf (timer--low-seconds timer) (nth 1 lt))
(setf (timer--usecs timer) (nth 2 lt))
(setf (timer--psecs timer) (nth 3 lt))
time))
;; Pseudo field `time'.
......@@ -102,24 +96,14 @@ fire each time Emacs is idle for that many seconds."
"Yield the next value after TIME that is an integral multiple of SECS.
More precisely, the next value, after TIME, that is an integral multiple
of SECS seconds since the epoch. SECS may be a fraction."
(let* ((trillion 1000000000000)
(time-sec (+ (nth 1 time)
(* 65536 (nth 0 time))))
(delta-sec (mod (- time-sec) secs))
(next-sec (+ time-sec (floor delta-sec)))
(next-sec-psec (floor (* trillion (mod delta-sec 1))))
(sub-time-psec (+ (or (nth 3 time) 0)
(* 1000000 (nth 2 time))))
(psec-diff (- sub-time-psec next-sec-psec)))
(if (and (<= next-sec time-sec) (< 0 psec-diff))
(setq next-sec-psec (+ sub-time-psec
(mod (- psec-diff) (* trillion secs)))))
(setq next-sec (+ next-sec (floor next-sec-psec trillion)))
(setq next-sec-psec (mod next-sec-psec trillion))
(list (floor next-sec 65536)
(floor (mod next-sec 65536))
(floor next-sec-psec 1000000)
(floor (mod next-sec-psec 1000000)))))
(let* ((ticks-hz (if (and (consp time) (integerp (car time))
(integerp (cdr time)) (< 0 (cdr time)))
time
(encode-time time 1000000000000)))
(hz (cdr ticks-hz))
(s-ticks (* secs hz))
(more-ticks (+ (car ticks-hz) s-ticks)))
(encode-time (cons (- more-ticks (% more-ticks s-ticks)) hz))))
(defun timer-relative-time (time secs &optional usecs psecs)
"Advance TIME by SECS seconds and optionally USECS microseconds
......
......@@ -155,8 +155,7 @@ signed integer."
;; tenths of microseconds between
;; 1601-01-01 and 1970-01-01
"116444736000000000)")
;; add trailing zeros to support old current-time formats
'rawnum (append (current-time) '(0 0))))
'rawnum (encode-time nil 'list)))
result-bytes)
(dotimes (byte 8)
(push (calc-eval "and($1,16#FF)" 'rawnum tenths-of-us-since-jan-1-1601)
......
......@@ -133,7 +133,8 @@ If nil, use the value of `vc-diff-switches'. If t, use no switches."
(file-error (insert (format "%s <%s> %s"
(current-time-string)
user-mail-address
(+ (nth 2 (current-time))
(+ (% (car (encode-time nil 1000000))
1000000)
(buffer-size)))))))
(comment-region beg (point))))
......
......@@ -357,7 +357,7 @@ So a typical ID could look like \"Org:4nd91V40HI\"."
"Return string with random (version 4) UUID."
(let ((rnd (md5 (format "%s%s%s%s%s%s%s"
(random)
(current-time)
(encode-time nil 'list)
(user-uid)
(emacs-pid)
(user-full-name)
......@@ -416,7 +416,7 @@ The input I may be a character, or a single-letter string."
"Encode TIME as a 10-digit string.
This string holds the time to micro-second accuracy, and can be decoded
using `org-id-decode'."
(setq time (or time (current-time)))
(setq time (encode-time time 'list))
(concat (org-id-int-to-b36 (nth 0 time) 4)
(org-id-int-to-b36 (nth 1 time) 4)
(org-id-int-to-b36 (or (nth 2 time) 0) 4)))
......
......@@ -304,7 +304,7 @@ write-date, checksum, link-type, and link-name."
(tar-parse-octal-integer string tar-uid-offset tar-gid-offset)
(tar-parse-octal-integer string tar-gid-offset tar-size-offset)
(tar-parse-octal-integer string tar-size-offset tar-time-offset)
(tar-parse-octal-long-integer string tar-time-offset tar-chk-offset)
(tar-parse-octal-integer string tar-time-offset tar-chk-offset)
(tar-parse-octal-integer string tar-chk-offset tar-linkp-offset)
link-p
linkname
......@@ -342,20 +342,8 @@ write-date, checksum, link-type, and link-name."
start (1+ start)))
n)))
(defun tar-parse-octal-long-integer (string &optional start end)
(if (null start) (setq start 0))
(if (null end) (setq end (length string)))
(if (= (aref string start) 0)
(list 0 0)
(let ((lo 0)
(hi 0))
(while (< start end)
(if (>= (aref string start) ?0)
(setq lo (+ (* lo 8) (- (aref string start) ?0))
hi (+ (* hi 8) (ash lo -16))
lo (logand lo 65535)))
(setq start (1+ start)))
(list hi lo))))
(define-obsolete-function-alias 'tar-parse-octal-long-integer
'tar-parse-octal-integer "27.1")
(defun tar-parse-octal-integer-safe (string)
(if (zerop (length string)) (error "empty string"))
......@@ -1276,14 +1264,8 @@ for this to be permanent."
(defun tar-octal-time (timeval)
;; Format a timestamp as 11 octal digits. Ghod, I hope this works...
(let ((hibits (car timeval)) (lobits (car (cdr timeval))))
(format "%05o%01o%05o"
(ash hibits -2)
(logior (ash (logand 3 hibits) 1)
(if (> (logand lobits 32768) 0) 1 0))
(logand 32767 lobits)
)))
;; Format a timestamp as 11 octal digits.
(format "%011o" (encode-time timeval 'integer)))
(defun tar-subfile-save-buffer ()
"In tar subfile mode, save this buffer into its parent tar-file buffer.
......
......@@ -31,7 +31,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
storage is exhausted. Admittedly this is not ideal. An mpz value
in a temporary is made permanent by mpz_swapping it with a bignum's
value. Although typically at most two temporaries are needed,
rounding_driver and rounddiv_q need four altogther. */
time_arith, rounddiv_q and rounding_driver each need four. */
mpz_t mpz[4];
......
......@@ -4163,18 +4163,13 @@ decode_timer (Lisp_Object timer, struct timespec *result)
Lisp_Object *vec;
if (! (VECTORP (timer) && ASIZE (timer) == 9))
return 0;
return false;
vec = XVECTOR (timer)->contents;
if (! NILP (vec[0]))
return 0;
if (! FIXNUMP (vec[2]))
return false;
struct lisp_time t;
if (decode_time_components (vec[1], vec[2], vec[3], vec[8], &t, 0) <= 0)
if (! FIXNUMP (vec[2]))
return false;
*result = lisp_to_timespec (t);
return timespec_valid_p (*result);
return list4_to_timespec (vec[1], vec[2], vec[3], vec[8], result);
}
......
......@@ -75,19 +75,22 @@ extern void set_waiting_for_input (struct timespec *);
(HI << LO_TIME_BITS) + LO + US / 1e6 + PS / 1e12. */
enum { LO_TIME_BITS = 16 };
/* A Lisp time (HI LO US PS), sans the cons cells. */
/* Components of a new-format Lisp timestamp. */
struct lisp_time
{
EMACS_INT hi;
int lo, us, ps;
/* Clock count as a Lisp integer. */
Lisp_Object ticks;
/* Clock frequency (ticks per second) as a positive Lisp integer.
(TICKS . HZ) is a valid Lisp timestamp unless HZ < 65536. */
Lisp_Object hz;
};
/* defined in timefns.c */
extern struct timeval make_timeval (struct timespec) ATTRIBUTE_CONST;
extern Lisp_Object make_lisp_time (struct timespec);
extern int decode_time_components (Lisp_Object, Lisp_Object, Lisp_Object,
Lisp_Object, struct lisp_time *, double *);
extern struct timespec lisp_to_timespec (struct lisp_time);
extern bool list4_to_timespec (Lisp_Object, Lisp_Object, Lisp_Object,
Lisp_Object, struct timespec *);
extern struct timespec lisp_time_argument (Lisp_Object);
extern _Noreturn void time_overflow (void);
extern void init_timefns (bool);
......
This diff is collapsed.
......@@ -77,3 +77,6 @@
(format-time-string "%Y-%m-%d %H:%M:%S" (- (ash 1 31) 3600) t)
"2038-01-19 02:14:08")
(timefns-tests--have-leap-seconds))))
(ert-deftest time-equal-p-nil-nil ()
(should (time-equal-p nil nil)))
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment