1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2025-01-05 11:45:45 +00:00

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.
This commit is contained in:
Paul Eggert 2018-10-03 09:10:01 -07:00
parent 84f39d3389
commit 93fe420942
20 changed files with 1040 additions and 570 deletions

View File

@ -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

View File

@ -1233,11 +1233,44 @@ return value is @code{nil}.
This section explains how to determine the current time and time
zone.
@cindex Lisp timestamp
@cindex timestamp, Lisp
Many functions like @code{current-time} and @code{file-attributes}
return @dfn{Lisp timestamp} values that count seconds, and that can
represent absolute time by counting seconds since the @dfn{epoch} of
1970-01-01 00:00:00 UTC.
Although traditionally Lisp timestamps were integer pairs, their
form has evolved and programs ordinarily should not depend on the
current default form. If your program needs a particular timestamp
form, you can use the @code{encode-time} function to convert it to the
needed form. @xref{Time Conversion}.
@cindex epoch
Most of these functions represent time as a list of four integers
@code{(@var{sec-high} @var{sec-low} @var{microsec} @var{picosec})}.
This represents the number of seconds from the @dfn{epoch} (January
1, 1970 at 00:00 UTC), using the formula:
There are currently three forms of Lisp timestamps, each of
which represents a number of seconds:
@itemize @bullet
@item
An integer. Although this is the simplest form, it cannot represent
subsecond timestamps.
@item
A pair of integers @code{(@var{ticks} . @var{hz})}, where @var{hz} is
positive. This represents @var{ticks}/@var{hz} seconds, which is the
same time as plain @var{ticks} if @var{hz} is 1. A common value for
@var{hz} is 1000000000, for a nanosecond-resolution
clock.@footnote{Currently @var{hz} should be at least 65536 to avoid
compatibility warnings when the timestamp is passed to standard
functions, as previous versions of Emacs would interpret such a
timestamps differently due to backward-compatibility concerns. These
warnings are intended to be removed in a future Emacs version.}
@item
A list of four integers @code{(@var{high} @var{low} @var{micro}
@var{pico})}, where 0 @leq{} @var{low} < 65536, 0 @leq{} @var{micro} <
1000000, and 0 @leq{} @var{pico} < 1000000.
This represents the number of seconds using the formula:
@ifnottex
@var{high} * 2**16 + @var{low} + @var{micro} * 10**@minus{}6 +
@var{pico} * 10**@minus{}12.
@ -1245,21 +1278,23 @@ This represents the number of seconds from the @dfn{epoch} (January
@tex
$high*2^{16} + low + micro*10^{-6} + pico*10^{-12}$.
@end tex
The return value of @code{current-time} represents time using this
form, as do the timestamps in the return values of other functions
such as @code{file-attributes} (@pxref{Definition of
file-attributes}). In some cases, functions may return two- or
In some cases, functions may default to returning two- or
three-element lists, with omitted @var{microsec} and @var{picosec}
components defaulting to zero.
On all current machines @var{picosec} is a multiple of 1000, but this
may change as higher-resolution clocks become available.
@end itemize
@cindex time value
Function arguments, e.g., the @var{time} argument to
@code{current-time-string}, accept a more-general @dfn{time value}
format, which can be a list of integers as above, or a single number
for seconds since the epoch, or @code{nil} for the current time. You
can convert a time value into a human-readable string using
@code{current-time-string} and @code{format-time-string}, into a list
of integers using @code{seconds-to-time}, and into other forms using
format, which can be a Lisp timestamp, @code{nil} for the current
time, a single floating-point number for seconds, or a list
@code{(@var{high} @var{low} @var{micro})} or @code{(@var{high}
@var{low})} that is a truncated list timestamp with missing elements
taken to be zero. You can convert a time value into
a human-readable string using @code{format-time-string}, into a Lisp
timestamp using @code{encode-time}, and into other forms using
@code{decode-time} and @code{float-time}. These functions are
described in the following sections.
@ -1287,12 +1322,7 @@ defaults to the current time zone rule. @xref{Time Zone Rules}.
@end defun
@defun current-time
This function returns the current time, represented as a list of four
integers @code{(@var{sec-high} @var{sec-low} @var{microsec} @var{picosec})}.
These integers have trailing zeros on systems that return time with
lower resolutions. On all current machines @var{picosec} is a
multiple of 1000, but this may change as higher-resolution clocks
become available.
This function returns the current time as a Lisp timestamp.
@end defun
@defun float-time &optional time
@ -1306,13 +1336,6 @@ exact. Do not use this function if precise time stamps are required.
@code{time-to-seconds} is an alias for this function.
@end defun
@defun seconds-to-time time
This function converts a time value to list-of-integer form.
For example, if @var{time} is a number, @code{(time-to-seconds
(seconds-to-time @var{time}))} equals the number unless overflow
or rounding errors occur.
@end defun
@node Time Zone Rules
@section Time Zone Rules
@cindex time zone rules
@ -1434,32 +1457,63 @@ seconds east of Greenwich.
@var{dow} and @var{utcoff}.
@end defun
@defun encode-time seconds minutes hour day month year &optional zone
This function is the inverse of @code{decode-time}. It converts seven
items of calendrical data into a list-of-integer time value. For the
meanings of the arguments, see the table above under
@code{decode-time}.
@defun encode-time time &optional form
This function converts @var{time} to a Lisp timestamp.
It can act as the inverse of @code{decode-time}.
The first argument can be a Lisp time value such as @code{nil} for the
current time, a number of seconds, a pair @code{(@var{ticks}
. @var{hz})}, or a list @code{(@var{high} @var{low} @var{micro}
@var{pico})} (@pxref{Time of Day}). It can also be a list
@code{(@var{second} @var{minute} @var{hour} @var{day} @var{month}
@var{year} @var{ignored} @var{dst} @var{zone})} that specifies a
decoded time in the style of @code{decode-time}, so that
@code{(encode-time (decode-time ...))} works. For the meanings of
these list members, see the table under @code{decode-time}.
The optional @var{form} argument specifies the desired timestamp form
to be returned. If @var{form} is the symbol @code{integer}, this
function returns an integer count of seconds. If @var{form} is a
positive integer, it specifies a clock frequency and this function
returns an integer-pair timestamp @code{(@var{ticks}
. @var{form})}.@footnote{Currently a positive integer @var{form}
should be at least 65536 if the returned value is intended to be given
to standard functions expecting Lisp timestamps.} If @var{form} is
@code{t}, this function treats it as a positive integer suitable for
representing the timestamp; for example, it is treated as 1000000000
if the platform timestamp has nanosecond resolution. If @var{form} is
@code{list}, this function returns an integer list @code{(@var{high}
@var{low} @var{micro} @var{pico})}. Although an omitted or @code{nil}
@var{form} currently acts like @code{list}, this is planned to change
in a future Emacs version, so callers requiring list timestamps should
pass @code{list} explicitly.
As an obsolescent calling convention, this function can be given six
or more arguments. The first six arguments @var{second},
@var{minute}, @var{hour}, @var{day}, @var{month}, and @var{year}
specify most of the components of a decoded time. If there are more
than six arguments the @emph{last} argument is used as @var{zone} and
any other extra arguments are ignored, so that @code{(apply
'encode-time (decode-time ...))} works; otherwise @var{zone} defaults
to the current time zone rule (@pxref{Time Zone Rules}). The decoded
time's @var{dst} component is treated as if it was @minus{}1, and
@var{form} so it takes its default value.
Year numbers less than 100 are not treated specially. If you want them
to stand for years above 1900, or years above 2000, you must alter them
yourself before you call @code{encode-time}.
The optional argument @var{zone} defaults to the current time zone rule.
@xref{Time Zone Rules}.
If you pass more than seven arguments to @code{encode-time}, the first
six are used as @var{seconds} through @var{year}, the last argument is
used as @var{zone}, and the arguments in between are ignored. This
feature makes it possible to use the elements of a list returned by
@code{decode-time} as the arguments to @code{encode-time}, like this:
The @code{encode-time} function acts as a rough inverse to
@code{decode-time}. For example, you can pass the output of
the latter to the former as follows:
@example
(apply 'encode-time (decode-time @dots{}))
(encode-time (decode-time @dots{}))
@end example
You can perform simple date arithmetic by using out-of-range values for
the @var{seconds}, @var{minutes}, @var{hour}, @var{day}, and @var{month}
arguments; for example, day 0 means the day preceding the given month.
@var{seconds}, @var{minutes}, @var{hour}, @var{day}, and @var{month};
for example, day 0 means the day preceding the given month.
The operating system puts limits on the range of possible time values;
if you try to encode a time that is out of range, an error results.
@ -1474,12 +1528,12 @@ on others, years as early as 1901 do work.
@cindex formatting time values
These functions convert time values to text in a string, and vice versa.
Time values include @code{nil}, numbers, and lists of two to four
integers (@pxref{Time of Day}).
Time values include @code{nil}, numbers, and Lisp timestamps
(@pxref{Time of Day}).
@defun date-to-time string
This function parses the time-string @var{string} and returns the
corresponding time value.
corresponding Lisp timestamp.
@end defun
@defun format-time-string format-string &optional time zone
@ -1701,10 +1755,8 @@ When called interactively, it prints the uptime in the echo area.
@end deffn
@defun get-internal-run-time
This function returns the processor run time used by Emacs as a list
of four integers: @code{(@var{sec-high} @var{sec-low} @var{microsec}
@var{picosec})}, using the same format as @code{current-time}
(@pxref{Time of Day}).
This function returns the processor run time used by Emacs, as a Lisp
timestamp (@pxref{Time of Day}).
Note that the time returned by this function excludes the time Emacs
was not using the processor, and if the Emacs process has several
@ -1729,9 +1781,10 @@ interactively, it prints the duration in the echo area.
@cindex calendrical computations
These functions perform calendrical computations using time values
(@pxref{Time of Day}). A value of @code{nil} for any of their
(@pxref{Time of Day}). As with any time value, a value of
@code{nil} for any of their
time-value arguments stands for the current system time, and a single
integer number stands for the number of seconds since the epoch.
number stands for the number of seconds since the epoch.
@defun time-less-p t1 t2
This returns @code{t} if time value @var{t1} is less than time value
@ -1757,7 +1810,7 @@ float-time}) to convert the result into seconds.
This returns the sum of two time values, as a time value.
However, the result is a float if either argument is a float infinity or NaN@.
One argument should represent a time difference rather than a point in time,
either as a list or as a single number of elapsed seconds.
as a time value that is often just a single number of elapsed seconds.
Here is how to add a number of seconds to a time value:
@example

View File

@ -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.

View File

@ -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;

View 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

View File

@ -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

View File

@ -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")

View File

@ -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)

View File

@ -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))

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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))))

View File

@ -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)))

View File

@ -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.

View File

@ -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];

View File

@ -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;
return false;
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)
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);
}

View File

@ -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);

File diff suppressed because it is too large Load Diff

View File

@ -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)))