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:
parent
84f39d3389
commit
93fe420942
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
15
etc/NEWS
15
etc/NEWS
@ -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;
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
1151
src/timefns.c
1151
src/timefns.c
File diff suppressed because it is too large
Load Diff
@ -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)))
|
||||
|
Loading…
Reference in New Issue
Block a user