aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Eggert2014-11-16 20:38:15 -0800
committerPaul Eggert2014-11-16 20:41:22 -0800
commit0921dbc3ab4dcc6b291ef45e46a24b322bbcb885 (patch)
tree0e320978c7d30af415bb7de6e0b8f6735a3ca3d1
parent058f56d24f776bdc25bcac86fe1f8969a78374e9 (diff)
downloademacs-0921dbc3ab4dcc6b291ef45e46a24b322bbcb885.tar.gz
emacs-0921dbc3ab4dcc6b291ef45e46a24b322bbcb885.zip
Improve time stamp handling, and be more consistent about it.
This implements a suggestion made in: http://lists.gnu.org/archive/html/emacs-devel/2014-10/msg00587.html Among other things, this means timer.el no longer needs to autoload the time-date module. * doc/lispref/os.texi (Time of Day, Time Conversion, Time Parsing) (Processor Run Time, Time Calculations): Document the new behavior, plus be clearer about the old behavior. (Idle Timers): Take advantage of new functionality. * etc/NEWS: Document the changes. * lisp/allout-widgets.el (allout-elapsed-time-seconds): Doc fix. * lisp/arc-mode.el (archive-ar-summarize): * lisp/calendar/time-date.el (seconds-to-time, days-to-time, time-since): * lisp/emacs-lisp/timer.el (timer-relative-time, timer-event-handler) (run-at-time, with-timeout-suspend, with-timeout-unsuspend): * lisp/net/tramp.el (tramp-time-less-p, tramp-time-subtract): * lisp/proced.el (proced-time-lessp): * lisp/timezone.el (timezone-time-from-absolute): * lisp/type-break.el (type-break-schedule, type-break-time-sum): Simplify by using new functionality. * lisp/calendar/cal-dst.el (calendar-next-time-zone-transition): Do not return time values in obsolete and undocumented (HI . LO) format; use (HI LO) instead. * lisp/calendar/time-date.el (with-decoded-time-value): Treat 'nil' as current time. This is mostly for XEmacs. (encode-time-value, with-decoded-time-value): Obsolete. (time-add, time-subtract, time-less-p): Use no-op autoloads, for XEmacs. Define only if XEmacs, as they're now C builtins in Emacs. * lisp/ldefs-boot.el: Update to match new time-date.el * lisp/proced.el: Do not require time-date. * src/editfns.c (invalid_time): New function. Use it instead of 'error ("Invalid time specification")'. (time_add, time_subtract, time_arith, Ftime_add, Ftime_less_p) (decode_float_time, lisp_to_timespec, lisp_time_struct): New functions. (make_time_tail, make_time): Remove. All uses changed to use new functions or plain list4i. (disassemble_lisp_time): Return effective length if successful. Check that LOW is an integer, if it's combined with other components. (decode_time_components): Decode into struct lisp_time, not struct timespec, so that we can support a wide set of times regardless of whether time_t is signed. Decode plain numbers as seconds since the Epoch, and nil as the current time. (lisp_time_argument, lisp_seconds_argument, Ffloat_time): Reimplement in terms of new functions. (Fencode_time): Just use list2i. (syms_of_editfns): Add time-add, time-subtract, time-less-p. * src/keyboard.c (decode_timer): Don't allow the new formats (floating point or nil) in timers. * src/systime.h (LO_TIME_BITS): New constant. Use it everywhere in place of the magic number '16'. (struct lisp_time): New type. (decode_time_components): Use it. (lisp_to_timespec): New decl.
-rw-r--r--doc/lispref/ChangeLog8
-rw-r--r--doc/lispref/os.texi133
-rw-r--r--etc/ChangeLog5
-rw-r--r--etc/NEWS19
-rw-r--r--lisp/ChangeLog28
-rw-r--r--lisp/allout-widgets.el4
-rw-r--r--lisp/arc-mode.el6
-rw-r--r--lisp/calendar/cal-dst.el1
-rw-r--r--lisp/calendar/time-date.el158
-rw-r--r--lisp/emacs-lisp/timer.el16
-rw-r--r--lisp/ldefs-boot.el21
-rw-r--r--lisp/net/tramp.el14
-rw-r--r--lisp/proced.el15
-rw-r--r--lisp/timezone.el10
-rw-r--r--lisp/type-break.el17
-rw-r--r--src/ChangeLog28
-rw-r--r--src/editfns.c364
-rw-r--r--src/keyboard.c13
-rw-r--r--src/systime.h15
19 files changed, 548 insertions, 327 deletions
diff --git a/doc/lispref/ChangeLog b/doc/lispref/ChangeLog
index b7423af07ba..0a8a0a88cce 100644
--- a/doc/lispref/ChangeLog
+++ b/doc/lispref/ChangeLog
@@ -1,3 +1,11 @@
12014-11-17 Paul Eggert <eggert@cs.ucla.edu>
2
3 Improve time stamp handling, and be more consistent about it.
4 * os.texi (Time of Day, Time Conversion, Time Parsing)
5 (Processor Run Time, Time Calculations):
6 Document the new behavior, plus be clearer about the old behavior.
7 (Idle Timers): Take advantage of new functionality.
8
12014-11-16 Lars Magne Ingebrigtsen <larsi@gnus.org> 92014-11-16 Lars Magne Ingebrigtsen <larsi@gnus.org>
2 10
3 * text.texi (Special Properties): Mention `inhibit-read-only'. 11 * text.texi (Special Properties): Mention `inhibit-read-only'.
diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi
index 167ecb372b5..b7094479db2 100644
--- a/doc/lispref/os.texi
+++ b/doc/lispref/os.texi
@@ -1213,37 +1213,34 @@ return value is @code{nil}.
1213zone. 1213zone.
1214 1214
1215@cindex epoch 1215@cindex epoch
1216 Most of these functions represent time as a list of either four 1216 Most of these functions represent time as a list of four integers
1217integers, @code{(@var{sec-high} @var{sec-low} @var{microsec} 1217@code{(@var{sec-high} @var{sec-low} @var{microsec} @var{picosec})}.
1218@var{picosec})}, or of three 1218This represents the number of seconds from the @dfn{epoch} (January
1219integers, @code{(@var{sec-high} @var{sec-low} @var{microsec})}, or of 12191, 1970 at 00:00 UTC), using the formula:
1220two integers, @code{(@var{sec-high} @var{sec-low})}. The integers
1221@var{sec-high} and @var{sec-low} give the high and low bits of an
1222integer number of seconds. This integer,
1223@ifnottex 1220@ifnottex
1224@var{high} * 2**16 + @var{low}, 1221@var{high} * 2**16 + @var{low} + @var{micro} * 10**@minus{}6 +
1222@var{pico} * 10**@minus{}12.
1225@end ifnottex 1223@end ifnottex
1226@tex 1224@tex
1227$high*2^{16}+low$, 1225$high*2^{16} + low + micro*10^{-6} + pico*10^{-12}$.
1228@end tex 1226@end tex
1229is the number of seconds from the @dfn{epoch} (January 1, 1970 at 00:00 1227The return value of @code{current-time} represents time using this
1230UTC) to the specified time. The third list element @var{microsec}, if 1228form, as do the timestamps in the return values of other functions
1231present, gives the number of microseconds from the start of that 1229such as @code{file-attributes} (@pxref{Definition of
1232second to the specified time. 1230file-attributes}). In some cases, functions may return two- or
1233Similarly, the fourth list element @var{picosec}, if present, gives 1231three-element lists, with omitted @var{microsec} and @var{picosec}
1234the number of picoseconds from the start of that microsecond to the 1232components defaulting to zero.
1235specified time. 1233
1236 1234@cindex time value
1237 The return value of @code{current-time} represents time using four 1235 Function arguments, e.g., the @var{time-value} argument to
1238integers, as do the timestamps in the return value of 1236@code{current-time-string}, accept a more-general @dfn{time value}
1239@code{file-attributes} (@pxref{Definition of 1237format, which can be a list of integers as above, or a single number
1240file-attributes}). In function arguments, e.g., the @var{time-value} 1238for seconds since the epoch, or @code{nil} for the current time. You
1241argument to @code{current-time-string}, two-, three-, and four-integer 1239can convert a time value into a human-readable string using
1242lists are accepted. You can convert times from the list 1240@code{current-time-string} and @code{format-time-string}, into a list
1243representation into standard human-readable strings using 1241of integers using @code{seconds-to-time}, and into other forms using
1244@code{current-time-string}, or to other forms using the 1242@code{decode-time} and @code{float-time}. These functions are
1245@code{decode-time} and @code{format-time-string} functions documented 1243described in the following sections.
1246in the following sections.
1247 1244
1248@defun current-time-string &optional time-value 1245@defun current-time-string &optional time-value
1249This function returns the current time and date as a human-readable 1246This function returns the current time and date as a human-readable
@@ -1256,8 +1253,8 @@ characters from the beginning of the string rather than from the end,
1256as the year might not have exactly four digits, and additional 1253as the year might not have exactly four digits, and additional
1257information may some day be added at the end. 1254information may some day be added at the end.
1258 1255
1259The argument @var{time-value}, if given, specifies a time to format 1256The argument @var{time-value}, if given, specifies a time to format,
1260(represented as a list of integers), instead of the current time. 1257instead of the current time.
1261 1258
1262@example 1259@example
1263@group 1260@group
@@ -1279,11 +1276,19 @@ become available.
1279@defun float-time &optional time-value 1276@defun float-time &optional time-value
1280This function returns the current time as a floating-point number of 1277This function returns the current time as a floating-point number of
1281seconds since the epoch. The optional argument @var{time-value}, if 1278seconds since the epoch. The optional argument @var{time-value}, if
1282given, specifies a time (represented as a list of integers) to convert 1279given, specifies a time to convert instead of the current time.
1283instead of the current time.
1284 1280
1285@emph{Warning}: Since the result is floating point, it may not be 1281@emph{Warning}: Since the result is floating point, it may not be
1286exact. Do not use this function if precise time stamps are required. 1282exact. Do not use this function if precise time stamps are required.
1283
1284@code{time-to-seconds} is an alias for this function.
1285@end defun
1286
1287@defun seconds-to-time time-value
1288This function converts a time value to list-of-integer form.
1289For example, if @var{time-value} is a number, @code{(time-to-seconds
1290(seconds-to-time @var{time-value}))} equals the number unless overflow
1291or rounding errors occur.
1287@end defun 1292@end defun
1288 1293
1289@defun current-time-zone &optional time-value 1294@defun current-time-zone &optional time-value
@@ -1302,8 +1307,8 @@ adjustment, then the value is constant through time.
1302If the operating system doesn't supply all the information necessary to 1307If the operating system doesn't supply all the information necessary to
1303compute the value, the unknown elements of the list are @code{nil}. 1308compute the value, the unknown elements of the list are @code{nil}.
1304 1309
1305The argument @var{time-value}, if given, specifies a time (represented 1310The argument @var{time-value}, if given, specifies a time value to
1306as a list of integers) to analyze instead of the current time. 1311analyze instead of the current time.
1307@end defun 1312@end defun
1308 1313
1309The current time zone is determined by the @env{TZ} environment 1314The current time zone is determined by the @env{TZ} environment
@@ -1316,15 +1321,15 @@ time zone.
1316@section Time Conversion 1321@section Time Conversion
1317@cindex calendrical information 1322@cindex calendrical information
1318 1323
1319 These functions convert time values (lists of two to four integers, 1324 These functions convert time values (@pxref{Time of Day}) into
1320as explained in the previous section) into calendrical information and 1325calendrical information and vice versa.
1321vice versa.
1322 1326
1323 Many 32-bit operating systems are limited to time values containing 1327 Many 32-bit operating systems are limited to system times containing
132432 bits of information; these systems typically handle only the times 132832 bits of information in their seconds component; these systems
1325from 1901-12-13 20:45:52 UTC through 2038-01-19 03:14:07 UTC@. 1329typically handle only the times from 1901-12-13 20:45:52 UTC through
1326However, 64-bit and some 32-bit operating systems have larger time 13302038-01-19 03:14:07 UTC@. However, 64-bit and some 32-bit operating
1327values, and can represent times far in the past or future. 1331systems have larger seconds components, and can represent times far in
1332the past or future.
1328 1333
1329 Time conversion functions always use the Gregorian calendar, even 1334 Time conversion functions always use the Gregorian calendar, even
1330for dates before the Gregorian calendar was introduced. Year numbers 1335for dates before the Gregorian calendar was introduced. Year numbers
@@ -1332,9 +1337,9 @@ count the number of years since the year 1 B.C., and do not skip zero
1332as traditional Gregorian years do; for example, the year number 1337as traditional Gregorian years do; for example, the year number
1333@minus{}37 represents the Gregorian year 38 B.C@. 1338@minus{}37 represents the Gregorian year 38 B.C@.
1334 1339
1335@defun decode-time &optional time 1340@defun decode-time &optional time-value
1336This function converts a time value into calendrical information. If 1341This function converts a time value into calendrical information. If
1337you don't specify @var{time}, it decodes the current time. The return 1342you don't specify @var{time-value}, it decodes the current time. The return
1338value is a list of nine elements, as follows: 1343value is a list of nine elements, as follows:
1339 1344
1340@example 1345@example
@@ -1373,8 +1378,9 @@ Greenwich.
1373 1378
1374@defun encode-time seconds minutes hour day month year &optional zone 1379@defun encode-time seconds minutes hour day month year &optional zone
1375This function is the inverse of @code{decode-time}. It converts seven 1380This function is the inverse of @code{decode-time}. It converts seven
1376items of calendrical data into a time value. For the meanings of the 1381items of calendrical data into a list-of-integer time value. For the
1377arguments, see the table above under @code{decode-time}. 1382meanings of the arguments, see the table above under
1383@code{decode-time}.
1378 1384
1379Year numbers less than 100 are not treated specially. If you want them 1385Year numbers less than 100 are not treated specially. If you want them
1380to stand for years above 1900, or years above 2000, you must alter them 1386to stand for years above 1900, or years above 2000, you must alter them
@@ -1418,9 +1424,11 @@ This function parses the time-string @var{string} and returns the
1418corresponding time value. 1424corresponding time value.
1419@end defun 1425@end defun
1420 1426
1421@defun format-time-string format-string &optional time universal 1427@defun format-time-string format-string &optional time-value universal
1422This function converts @var{time} (or the current time, if @var{time} is 1428
1423omitted) to a string according to @var{format-string}. The argument 1429This function converts @var{time-value} (or the current time, if
1430@var{time-value} is omitted) to a string according to
1431@var{format-string}. The argument
1424@var{format-string} may contain @samp{%}-sequences which say to 1432@var{format-string} may contain @samp{%}-sequences which say to
1425substitute parts of the time. Here is a table of what the 1433substitute parts of the time. Here is a table of what the
1426@samp{%}-sequences mean: 1434@samp{%}-sequences mean:
@@ -1540,12 +1548,6 @@ specified by @code{locale-coding-system} (@pxref{Locales}); after
1540system. 1548system.
1541@end defun 1549@end defun
1542 1550
1543@defun seconds-to-time seconds
1544This function converts @var{seconds}, the number of seconds since the
1545epoch, to a time value and returns that. To convert back, use
1546@code{float-time} (@pxref{Time of Day}).
1547@end defun
1548
1549@defun format-seconds format-string seconds 1551@defun format-seconds format-string seconds
1550This function converts its argument @var{seconds} into a string of 1552This function converts its argument @var{seconds} into a string of
1551years, days, hours, etc., according to @var{format-string}. The 1553years, days, hours, etc., according to @var{format-string}. The
@@ -1619,7 +1621,7 @@ When called interactively, it prints the uptime in the echo area.
1619 1621
1620@defun get-internal-run-time 1622@defun get-internal-run-time
1621This function returns the processor run time used by Emacs as a list 1623This function returns the processor run time used by Emacs as a list
1622of four integers: @code{(@var{high} @var{low} @var{microsec} 1624of four integers: @code{(@var{sec-high} @var{sec-low} @var{microsec}
1623@var{picosec})}, using the same format as @code{current-time} 1625@var{picosec})}, using the same format as @code{current-time}
1624(@pxref{Time of Day}). 1626(@pxref{Time of Day}).
1625 1627
@@ -1643,7 +1645,7 @@ interactively, it prints the duration in the echo area.
1643@section Time Calculations 1645@section Time Calculations
1644 1646
1645 These functions perform calendrical computations using time values 1647 These functions perform calendrical computations using time values
1646(the kind of list that @code{current-time} returns). 1648(@pxref{Time of Day}).
1647 1649
1648@defun time-less-p t1 t2 1650@defun time-less-p t1 t2
1649This returns @code{t} if time value @var{t1} is less than time value 1651This returns @code{t} if time value @var{t1} is less than time value
@@ -1652,26 +1654,26 @@ This returns @code{t} if time value @var{t1} is less than time value
1652 1654
1653@defun time-subtract t1 t2 1655@defun time-subtract t1 t2
1654This returns the time difference @var{t1} @minus{} @var{t2} between 1656This returns the time difference @var{t1} @minus{} @var{t2} between
1655two time values, in the same format as a time value. 1657two time values, as a time value.
1656@end defun 1658@end defun
1657 1659
1658@defun time-add t1 t2 1660@defun time-add t1 t2
1659This returns the sum of two time values, one of which ought to 1661This returns the sum of two time values, as a time value.
1660represent a time difference rather than a point in time. 1662One argument should represent a time difference rather than a point in time.
1661Here is how to add a number of seconds to a time value: 1663Here is how to add a number of seconds to a time value:
1662 1664
1663@example 1665@example
1664(time-add @var{time} (seconds-to-time @var{seconds})) 1666(time-add @var{time} @var{seconds})
1665@end example 1667@end example
1666@end defun 1668@end defun
1667 1669
1668@defun time-to-days time 1670@defun time-to-days time-value
1669This function returns the number of days between the beginning of year 1671This function returns the number of days between the beginning of year
16701 and @var{time}. 16721 and @var{time-value}.
1671@end defun 1673@end defun
1672 1674
1673@defun time-to-day-in-year time 1675@defun time-to-day-in-year time-value
1674This returns the day number within the year corresponding to @var{time}. 1676This returns the day number within the year corresponding to @var{time-value}.
1675@end defun 1677@end defun
1676 1678
1677@defun date-leap-year-p year 1679@defun date-leap-year-p year
@@ -1915,8 +1917,7 @@ idleness. Here's an example:
1915 (run-with-idle-timer 1917 (run-with-idle-timer
1916 ;; Compute an idle time @var{break-length} 1918 ;; Compute an idle time @var{break-length}
1917 ;; more than the current value. 1919 ;; more than the current value.
1918 (time-add (current-idle-time) 1920 (time-add (current-idle-time) @var{break-length})
1919 (seconds-to-time @var{break-length}))
1920 nil 1921 nil
1921 'my-timer-function)))) 1922 'my-timer-function))))
1922@end example 1923@end example
diff --git a/etc/ChangeLog b/etc/ChangeLog
index 983fcaa28eb..ed8c345eef5 100644
--- a/etc/ChangeLog
+++ b/etc/ChangeLog
@@ -1,3 +1,8 @@
12014-11-17 Paul Eggert <eggert@cs.ucla.edu>
2
3 Improve time stamp handling, and be more consistent about it.
4 * NEWS: Document the changes.
5
12014-11-14 Lars Magne Ingebrigtsen <larsi@gnus.org> 62014-11-14 Lars Magne Ingebrigtsen <larsi@gnus.org>
2 7
3 * NEWS: Mention the new `M-s M-s' keystroke. 8 * NEWS: Mention the new `M-s M-s' keystroke.
diff --git a/etc/NEWS b/etc/NEWS
index b0e08d46819..cb34e9b4613 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -377,6 +377,25 @@ optional repeat-count argument.
377*** New macros `thread-first' and `thread-last' allow threading a form 377*** New macros `thread-first' and `thread-last' allow threading a form
378 as the first or last argument of subsequent forms. 378 as the first or last argument of subsequent forms.
379 379
380+++
381** Time-related changes:
382
383*** Time-related functions now consistently accept numbers
384(representing seconds since the epoch) and nil (representing the
385current time) as well as the usual list-of-integer representation.
386Affected functions include `current-time-string', `current-time-zone',
387`decode-time', `float-time', `format-time-string', `seconds-to-time',
388`time-add', `time-less-p', `time-subtract', `time-to-day-in-year',
389`time-to-days', and `time-to-seconds'.
390
391*** The `encode-time-value' and `with-decoded-time-value' macros have
392been obsoleted.
393
394*** `calendar-next-time-zone-transition', `time-add', and
395`time-subtract' no longer return time values in the obsolete and
396undocumented integer-pair format. Instead, they return a list of two
397integers.
398
380 399
381* Changes in Frames and Windows Code in Emacs 25.1 400* Changes in Frames and Windows Code in Emacs 25.1
382 401
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 7659d3c2235..7e516b95c61 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,31 @@
12014-11-17 Paul Eggert <eggert@cs.ucla.edu>
2
3 Improve time stamp handling, and be more consistent about it.
4 This implements a suggestion made in:
5 http://lists.gnu.org/archive/html/emacs-devel/2014-10/msg00587.html
6 Among other things, this means timer.el no longer needs to
7 autoload the time-date module.
8 * allout-widgets.el (allout-elapsed-time-seconds): Doc fix.
9 * arc-mode.el (archive-ar-summarize):
10 * calendar/time-date.el (seconds-to-time, days-to-time, time-since):
11 * emacs-lisp/timer.el (timer-relative-time, timer-event-handler)
12 (run-at-time, with-timeout-suspend, with-timeout-unsuspend):
13 * net/tramp.el (tramp-time-less-p, tramp-time-subtract):
14 * proced.el (proced-time-lessp):
15 * timezone.el (timezone-time-from-absolute):
16 * type-break.el (type-break-schedule, type-break-time-sum):
17 Simplify by using new functionality.
18 * calendar/cal-dst.el (calendar-next-time-zone-transition):
19 Do not return time values in obsolete and undocumented (HI . LO)
20 format; use (HI LO) instead.
21 * calendar/time-date.el (with-decoded-time-value):
22 Treat 'nil' as current time. This is mostly for XEmacs.
23 (encode-time-value, with-decoded-time-value): Obsolete.
24 (time-add, time-subtract, time-less-p): Use no-op autoloads, for
25 XEmacs. Define only if XEmacs, as they're now C builtins in Emacs.
26 * ldefs-boot.el: Update to match new time-date.el
27 * proced.el: Do not require time-date.
28
12014-11-16 Lars Magne Ingebrigtsen <larsi@gnus.org> 292014-11-16 Lars Magne Ingebrigtsen <larsi@gnus.org>
2 30
3 * net/eww.el (eww-mode): Make the buffer read-only. 31 * net/eww.el (eww-mode): Make the buffer read-only.
diff --git a/lisp/allout-widgets.el b/lisp/allout-widgets.el
index f2dcdb40425..25abf3f9252 100644
--- a/lisp/allout-widgets.el
+++ b/lisp/allout-widgets.el
@@ -2342,9 +2342,9 @@ We use a caching strategy, so the caller doesn't need to do so."
2342 got))) 2342 got)))
2343 2343
2344;;;_ : Miscellaneous 2344;;;_ : Miscellaneous
2345;;;_ > allout-elapsed-time-seconds (triple) 2345;;;_ > allout-elapsed-time-seconds (time-value time-value)
2346(defun allout-elapsed-time-seconds (end start) 2346(defun allout-elapsed-time-seconds (end start)
2347 "Return seconds between `current-time' style time START/END triples." 2347 "Return seconds between START/END time values."
2348 (let ((elapsed (time-subtract end start))) 2348 (let ((elapsed (time-subtract end start)))
2349 (float-time elapsed))) 2349 (float-time elapsed)))
2350;;;_ > allout-frame-property (frame property) 2350;;;_ > allout-frame-property (frame property)
diff --git a/lisp/arc-mode.el b/lisp/arc-mode.el
index ef155ee2b99..a9f0ec71b51 100644
--- a/lisp/arc-mode.el
+++ b/lisp/arc-mode.el
@@ -2181,11 +2181,7 @@ This doesn't recover lost files, it just undoes changes in the buffer itself."
2181 (size (string-to-number (match-string 6)))) 2181 (size (string-to-number (match-string 6))))
2182 ;; Move to the beginning of the data. 2182 ;; Move to the beginning of the data.
2183 (goto-char (match-end 0)) 2183 (goto-char (match-end 0))
2184 (setq time 2184 (setq time (format-time-string "%Y-%m-%d %H:%M" time))
2185 (format-time-string
2186 "%Y-%m-%d %H:%M"
2187 (let ((high (truncate (/ time 65536))))
2188 (list high (truncate (- time (* 65536.0 high)))))))
2189 (setq extname 2185 (setq extname
2190 (cond ((equal name "// ") 2186 (cond ((equal name "// ")
2191 (propertize ".<ExtNamesTable>." 'face 'italic)) 2187 (propertize ".<ExtNamesTable>." 'face 'italic))
diff --git a/lisp/calendar/cal-dst.el b/lisp/calendar/cal-dst.el
index e3cb690306e..2a9cdee301d 100644
--- a/lisp/calendar/cal-dst.el
+++ b/lisp/calendar/cal-dst.el
@@ -179,6 +179,7 @@ Return nil if no such transition can be found."
179 (if (eq (car (current-time-zone probe)) hi-utc-diff) 179 (if (eq (car (current-time-zone probe)) hi-utc-diff)
180 (setq hi probe) 180 (setq hi probe)
181 (setq lo probe))) 181 (setq lo probe)))
182 (setcdr hi (list (cdr hi)))
182 hi)))) 183 hi))))
183 184
184(autoload 'calendar-persian-to-absolute "cal-persia") 185(autoload 'calendar-persian-to-absolute "cal-persia")
diff --git a/lisp/calendar/time-date.el b/lisp/calendar/time-date.el
index 82bc05f299f..100e856469a 100644
--- a/lisp/calendar/time-date.el
+++ b/lisp/calendar/time-date.el
@@ -30,10 +30,9 @@
30;; value equal to HIGH * 2^16 + LOW + USEC * 10^-6 + PSEC * 10^-12 30;; value equal to HIGH * 2^16 + LOW + USEC * 10^-6 + PSEC * 10^-12
31;; seconds, where missing components are treated as zero. HIGH can be 31;; seconds, where missing components are treated as zero. HIGH can be
32;; negative, either because the value is a time difference, or because 32;; negative, either because the value is a time difference, or because
33;; the machine supports negative time stamps that fall before the epoch. 33;; it represents a time stamp before the epoch. Typically, there are
34;; The macro `with-decoded-time-value' and the function 34;; more time values than the underlying system time type supports,
35;; `encode-time-value' make it easier to deal with these formats. 35;; but the reverse can also be true.
36;; See `time-subtract' for an example of how to use them.
37 36
38;;; Code: 37;;; Code:
39 38
@@ -71,6 +70,7 @@ list (HIGH LOW MICRO PICO)."
71 ,low ,micro) 70 ,low ,micro)
72 (when pico `(,pico)) 71 (when pico `(,pico))
73 (when type `(,type))) 72 (when type `(,type)))
73 (or ,gensym (setq ,gensym (current-time)))
74 (if (consp ,gensym) 74 (if (consp ,gensym)
75 (progn 75 (progn
76 (setq ,low (pop ,gensym)) 76 (setq ,low (pop ,gensym))
@@ -108,6 +108,10 @@ it is assumed that PICO was omitted and should be treated as zero."
108 ((eq type 3) (list high low micro pico)) 108 ((eq type 3) (list high low micro pico))
109 ((null type) (encode-time-value high low micro 0 pico)))) 109 ((null type) (encode-time-value high low micro 0 pico))))
110 110
111(when (featurep 'emacs)
112 (make-obsolete 'encode-time-value nil "25.1")
113 (make-obsolete 'with-decoded-time-value nil "25.1"))
114
111(autoload 'parse-time-string "parse-time") 115(autoload 'parse-time-string "parse-time")
112(autoload 'timezone-make-date-arpa-standard "timezone") 116(autoload 'timezone-make-date-arpa-standard "timezone")
113 117
@@ -158,47 +162,17 @@ TIME defaults to the current time."
158 162
159;;;###autoload 163;;;###autoload
160(defun seconds-to-time (seconds) 164(defun seconds-to-time (seconds)
161 "Convert SECONDS (a floating point number) to a time value." 165 "Convert SECONDS to a time value."
162 (let* ((usec (* 1000000 (mod seconds 1))) 166 (time-add 0 seconds))
163 (ps (round (* 1000000 (mod usec 1))))
164 (us (floor usec))
165 (lo (floor (mod seconds 65536)))
166 (hi (floor seconds 65536)))
167 (if (eq ps 1000000)
168 (progn
169 (setq ps 0)
170 (setq us (1+ us))
171 (if (eq us 1000000)
172 (progn
173 (setq us 0)
174 (setq lo (1+ lo))
175 (if (eq lo 65536)
176 (progn
177 (setq lo 0)
178 (setq hi (1+ hi))))))))
179 (list hi lo us ps)))
180
181;;;###autoload
182(defun time-less-p (t1 t2)
183 "Return non-nil if time value T1 is earlier than time value T2."
184 (with-decoded-time-value ((high1 low1 micro1 pico1 type1 t1)
185 (high2 low2 micro2 pico2 type2 t2))
186 (or (< high1 high2)
187 (and (= high1 high2)
188 (or (< low1 low2)
189 (and (= low1 low2)
190 (or (< micro1 micro2)
191 (and (= micro1 micro2)
192 (< pico1 pico2)))))))))
193 167
194;;;###autoload 168;;;###autoload
195(defun days-to-time (days) 169(defun days-to-time (days)
196 "Convert DAYS into a time value." 170 "Convert DAYS into a time value."
197 (let* ((seconds (* 1.0 days 60 60 24)) 171 (let ((time (condition-case nil (seconds-to-time (* 86400.0 days))
198 (high (condition-case nil (floor (/ seconds 65536)) 172 (range-error (list most-positive-fixnum 65535)))))
199 (range-error most-positive-fixnum)))) 173 (if (integerp days)
200 (list high (condition-case nil (floor (- seconds (* 1.0 high 65536))) 174 (setcdr (cdr time) nil))
201 (range-error 65535))))) 175 time))
202 176
203;;;###autoload 177;;;###autoload
204(defun time-since (time) 178(defun time-since (time)
@@ -207,53 +181,71 @@ TIME should be either a time value or a date-time string."
207 (when (stringp time) 181 (when (stringp time)
208 ;; Convert date strings to internal time. 182 ;; Convert date strings to internal time.
209 (setq time (date-to-time time))) 183 (setq time (date-to-time time)))
210 (time-subtract (current-time) time)) 184 (time-subtract nil time))
211 185
212;;;###autoload 186;;;###autoload
213(defalias 'subtract-time 'time-subtract) 187(defalias 'subtract-time 'time-subtract)
214 188
215;;;###autoload 189;; These autoloads do nothing in Emacs 25, where the functions are builtin.
216(defun time-subtract (t1 t2) 190;;;###autoload(autoload 'time-add "time-date")
217 "Subtract two time values, T1 minus T2. 191;;;###autoload(autoload 'time-subtract "time-date")
218Return the difference in the format of a time value." 192;;;###autoload(autoload 'time-less-p "time-date")
219 (with-decoded-time-value ((high low micro pico type t1)
220 (high2 low2 micro2 pico2 type2 t2))
221 (setq high (- high high2)
222 low (- low low2)
223 micro (- micro micro2)
224 pico (- pico pico2)
225 type (max type type2))
226 (when (< pico 0)
227 (setq micro (1- micro)
228 pico (+ pico 1000000)))
229 (when (< micro 0)
230 (setq low (1- low)
231 micro (+ micro 1000000)))
232 (when (< low 0)
233 (setq high (1- high)
234 low (+ low 65536)))
235 (encode-time-value high low micro pico type)))
236 193
237;;;###autoload 194(eval-when-compile
238(defun time-add (t1 t2) 195 (when (not (featurep 'emacs))
239 "Add two time values T1 and T2. One should represent a time difference." 196
240 (with-decoded-time-value ((high low micro pico type t1) 197 (defun time-add (t1 t2)
241 (high2 low2 micro2 pico2 type2 t2)) 198 "Add two time values T1 and T2. One should represent a time difference."
242 (setq high (+ high high2) 199 (with-decoded-time-value ((high low micro pico type t1)
243 low (+ low low2) 200 (high2 low2 micro2 pico2 type2 t2))
244 micro (+ micro micro2) 201 (setq high (+ high high2)
245 pico (+ pico pico2) 202 low (+ low low2)
246 type (max type type2)) 203 micro (+ micro micro2)
247 (when (>= pico 1000000) 204 pico (+ pico pico2)
248 (setq micro (1+ micro) 205 type (max type type2))
249 pico (- pico 1000000))) 206 (when (>= pico 1000000)
250 (when (>= micro 1000000) 207 (setq micro (1+ micro)
251 (setq low (1+ low) 208 pico (- pico 1000000)))
252 micro (- micro 1000000))) 209 (when (>= micro 1000000)
253 (when (>= low 65536) 210 (setq low (1+ low)
254 (setq high (1+ high) 211 micro (- micro 1000000)))
255 low (- low 65536))) 212 (when (>= low 65536)
256 (encode-time-value high low micro pico type))) 213 (setq high (1+ high)
214 low (- low 65536)))
215 (encode-time-value high low micro pico type)))
216
217 (defun time-subtract (t1 t2)
218 "Subtract two time values, T1 minus T2.
219Return the difference in the format of a time value."
220 (with-decoded-time-value ((high low micro pico type t1)
221 (high2 low2 micro2 pico2 type2 t2))
222 (setq high (- high high2)
223 low (- low low2)
224 micro (- micro micro2)
225 pico (- pico pico2)
226 type (max type type2))
227 (when (< pico 0)
228 (setq micro (1- micro)
229 pico (+ pico 1000000)))
230 (when (< micro 0)
231 (setq low (1- low)
232 micro (+ micro 1000000)))
233 (when (< low 0)
234 (setq high (1- high)
235 low (+ low 65536)))
236 (encode-time-value high low micro pico type)))
237
238 (defun time-less-p (t1 t2)
239 "Return non-nil if time value T1 is earlier than time value T2."
240 (with-decoded-time-value ((high1 low1 micro1 pico1 type1 t1)
241 (high2 low2 micro2 pico2 type2 t2))
242 (or (< high1 high2)
243 (and (= high1 high2)
244 (or (< low1 low2)
245 (and (= low1 low2)
246 (or (< micro1 micro2)
247 (and (= micro1 micro2)
248 (< pico1 pico2)))))))))))
257 249
258;;;###autoload 250;;;###autoload
259(defun date-to-day (date) 251(defun date-to-day (date)
diff --git a/lisp/emacs-lisp/timer.el b/lisp/emacs-lisp/timer.el
index 7fc6bf7b920..a189d242ac4 100644
--- a/lisp/emacs-lisp/timer.el
+++ b/lisp/emacs-lisp/timer.el
@@ -125,9 +125,7 @@ of SECS seconds since the epoch. SECS may be a fraction."
125 "Advance TIME by SECS seconds and optionally USECS microseconds 125 "Advance TIME by SECS seconds and optionally USECS microseconds
126and PSECS picoseconds. SECS may be either an integer or a 126and PSECS picoseconds. SECS may be either an integer or a
127floating point number." 127floating point number."
128 (let ((delta (if (floatp secs) 128 (let ((delta secs))
129 (seconds-to-time secs)
130 (list (floor secs 65536) (mod secs 65536)))))
131 (if (or usecs psecs) 129 (if (or usecs psecs)
132 (setq delta (time-add delta (list 0 0 (or usecs 0) (or psecs 0))))) 130 (setq delta (time-add delta (list 0 0 (or usecs 0) (or psecs 0)))))
133 (time-add time delta))) 131 (time-add time delta)))
@@ -307,8 +305,8 @@ This function is called, by name, directly by the C code."
307 ;; perhaps because Emacs was suspended for a long time, 305 ;; perhaps because Emacs was suspended for a long time,
308 ;; limit how many times things get repeated. 306 ;; limit how many times things get repeated.
309 (if (and (numberp timer-max-repeats) 307 (if (and (numberp timer-max-repeats)
310 (< 0 (timer-until timer (current-time)))) 308 (< 0 (timer-until timer nil)))
311 (let ((repeats (/ (timer-until timer (current-time)) 309 (let ((repeats (/ (timer-until timer nil)
312 (timer--repeat-delay timer)))) 310 (timer--repeat-delay timer))))
313 (if (> repeats timer-max-repeats) 311 (if (> repeats timer-max-repeats)
314 (timer-inc-time timer (* (timer--repeat-delay timer) 312 (timer-inc-time timer (* (timer--repeat-delay timer)
@@ -374,13 +372,13 @@ This function returns a timer object which you can use in `cancel-timer'."
374 372
375 ;; Handle numbers as relative times in seconds. 373 ;; Handle numbers as relative times in seconds.
376 (if (numberp time) 374 (if (numberp time)
377 (setq time (timer-relative-time (current-time) time))) 375 (setq time (timer-relative-time nil time)))
378 376
379 ;; Handle relative times like "2 hours 35 minutes" 377 ;; Handle relative times like "2 hours 35 minutes"
380 (if (stringp time) 378 (if (stringp time)
381 (let ((secs (timer-duration time))) 379 (let ((secs (timer-duration time)))
382 (if secs 380 (if secs
383 (setq time (timer-relative-time (current-time) secs))))) 381 (setq time (timer-relative-time nil secs)))))
384 382
385 ;; Handle "11:23pm" and the like. Interpret it as meaning today 383 ;; Handle "11:23pm" and the like. Interpret it as meaning today
386 ;; which admittedly is rather stupid if we have passed that time 384 ;; which admittedly is rather stupid if we have passed that time
@@ -486,7 +484,7 @@ The value is a list that the debugger can pass to `with-timeout-unsuspend'
486when it exits, to make these timers start counting again." 484when it exits, to make these timers start counting again."
487 (mapcar (lambda (timer) 485 (mapcar (lambda (timer)
488 (cancel-timer timer) 486 (cancel-timer timer)
489 (list timer (time-subtract (timer--time timer) (current-time)))) 487 (list timer (time-subtract (timer--time timer) nil)))
490 with-timeout-timers)) 488 with-timeout-timers))
491 489
492(defun with-timeout-unsuspend (timer-spec-list) 490(defun with-timeout-unsuspend (timer-spec-list)
@@ -495,7 +493,7 @@ The argument should be a value previously returned by `with-timeout-suspend'."
495 (dolist (elt timer-spec-list) 493 (dolist (elt timer-spec-list)
496 (let ((timer (car elt)) 494 (let ((timer (car elt))
497 (delay (cadr elt))) 495 (delay (cadr elt)))
498 (timer-set-time timer (time-add (current-time) delay)) 496 (timer-set-time timer (time-add nil delay))
499 (timer-activate timer)))) 497 (timer-activate timer))))
500 498
501(defun y-or-n-p-with-timeout (prompt seconds default-value) 499(defun y-or-n-p-with-timeout (prompt seconds default-value)
diff --git a/lisp/ldefs-boot.el b/lisp/ldefs-boot.el
index b78c906b450..f60d6608f7e 100644
--- a/lisp/ldefs-boot.el
+++ b/lisp/ldefs-boot.el
@@ -27478,15 +27478,10 @@ If DATE lacks timezone information, GMT is assumed.
27478 (autoload 'time-to-seconds "time-date")) 27478 (autoload 'time-to-seconds "time-date"))
27479 27479
27480(autoload 'seconds-to-time "time-date" "\ 27480(autoload 'seconds-to-time "time-date" "\
27481Convert SECONDS (a floating point number) to a time value. 27481Convert SECONDS to a time value.
27482 27482
27483\(fn SECONDS)" nil nil) 27483\(fn SECONDS)" nil nil)
27484 27484
27485(autoload 'time-less-p "time-date" "\
27486Return non-nil if time value T1 is earlier than time value T2.
27487
27488\(fn T1 T2)" nil nil)
27489
27490(autoload 'days-to-time "time-date" "\ 27485(autoload 'days-to-time "time-date" "\
27491Convert DAYS into a time value. 27486Convert DAYS into a time value.
27492 27487
@@ -27499,17 +27494,9 @@ TIME should be either a time value or a date-time string.
27499\(fn TIME)" nil nil) 27494\(fn TIME)" nil nil)
27500 27495
27501(defalias 'subtract-time 'time-subtract) 27496(defalias 'subtract-time 'time-subtract)
27502 27497(autoload 'time-add "time-date")
27503(autoload 'time-subtract "time-date" "\ 27498(autoload 'time-subtract "time-date")
27504Subtract two time values, T1 minus T2. 27499(autoload 'time-less-p "time-date")
27505Return the difference in the format of a time value.
27506
27507\(fn T1 T2)" nil nil)
27508
27509(autoload 'time-add "time-date" "\
27510Add two time values T1 and T2. One should represent a time difference.
27511
27512\(fn T1 T2)" nil nil)
27513 27500
27514(autoload 'date-to-day "time-date" "\ 27501(autoload 'date-to-day "time-date" "\
27515Return the number of days between year 1 and DATE. 27502Return the number of days between year 1 and DATE.
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index 5889743e28b..01cd8191169 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -4236,25 +4236,15 @@ Invokes `password-read' if available, `read-passwd' else."
4236 ("oct" . 10) ("nov" . 11) ("dec" . 12)) 4236 ("oct" . 10) ("nov" . 11) ("dec" . 12))
4237 "Alist mapping month names to integers.") 4237 "Alist mapping month names to integers.")
4238 4238
4239;; FIXME: Shouldn't this also look at any subseconds parts of T1 and T2?
4240;;;###tramp-autoload 4239;;;###tramp-autoload
4241(defun tramp-time-less-p (t1 t2) 4240(defun tramp-time-less-p (t1 t2)
4242 "Say whether time value T1 is less than time value T2." 4241 "Say whether time value T1 is less than time value T2."
4243 (unless t1 (setq t1 '(0 0))) 4242 (time-less-p (or t1 0) (or t2 0)))
4244 (unless t2 (setq t2 '(0 0)))
4245 (or (< (car t1) (car t2))
4246 (and (= (car t1) (car t2))
4247 (< (nth 1 t1) (nth 1 t2)))))
4248 4243
4249;; FIXME: Shouldn't this also look at any subseconds parts of T1 and T2?
4250(defun tramp-time-subtract (t1 t2) 4244(defun tramp-time-subtract (t1 t2)
4251 "Subtract two time values. 4245 "Subtract two time values.
4252Return the difference in the format of a time value." 4246Return the difference in the format of a time value."
4253 (unless t1 (setq t1 '(0 0))) 4247 (time-subtract (or t1 0) (or t2 0)))
4254 (unless t2 (setq t2 '(0 0)))
4255 (let ((borrow (< (cadr t1) (cadr t2))))
4256 (list (- (car t1) (car t2) (if borrow 1 0))
4257 (- (+ (if borrow 65536 0) (cadr t1)) (cadr t2)))))
4258 4248
4259;;;###tramp-autoload 4249;;;###tramp-autoload
4260(defun tramp-time-diff (t1 t2) 4250(defun tramp-time-diff (t1 t2)
diff --git a/lisp/proced.el b/lisp/proced.el
index 592c0d066c7..188b8c354c6 100644
--- a/lisp/proced.el
+++ b/lisp/proced.el
@@ -49,8 +49,6 @@
49 49
50;;; Code: 50;;; Code:
51 51
52(require 'time-date) ; for `with-decoded-time-value'
53
54(defgroup proced nil 52(defgroup proced nil
55 "Proced mode." 53 "Proced mode."
56 :group 'processes 54 :group 'processes
@@ -1186,17 +1184,8 @@ Return nil otherwise."
1186(defun proced-time-lessp (t1 t2) 1184(defun proced-time-lessp (t1 t2)
1187 "Return t if time value T1 is less than time value T2. 1185 "Return t if time value T1 is less than time value T2.
1188Return `equal' if T1 equals T2. Return nil otherwise." 1186Return `equal' if T1 equals T2. Return nil otherwise."
1189 (with-decoded-time-value ((high1 low1 micro1 pico1 type1 t1) 1187 (or (time-less-p t1 t2)
1190 (high2 low2 micro2 pico2 type2 t2)) 1188 (if (not (time-less-p t2 t1)) 'equal)))
1191 (cond ((< high1 high2))
1192 ((< high2 high1) nil)
1193 ((< low1 low2))
1194 ((< low2 low1) nil)
1195 ((< micro1 micro2))
1196 ((< micro2 micro1) nil)
1197 ((< pico1 pico2))
1198 ((< pico2 pico1) nil)
1199 (t 'equal))))
1200 1189
1201;;; Sorting 1190;;; Sorting
1202 1191
diff --git a/lisp/timezone.el b/lisp/timezone.el
index 1135092b039..8ff43966f69 100644
--- a/lisp/timezone.el
+++ b/lisp/timezone.el
@@ -295,13 +295,9 @@ Gregorian date Sunday, December 31, 1 BC."
295 ;; (timezone-absolute-from-gregorian 1 1 1970) 295 ;; (timezone-absolute-from-gregorian 1 1 1970)
296 (days (- date current-time-origin)) 296 (days (- date current-time-origin))
297 (seconds-per-day (float 86400)) 297 (seconds-per-day (float 86400))
298 (seconds (+ seconds (* days seconds-per-day))) 298 (day-seconds (* days seconds-per-day)))
299 (current-time-arithmetic-base (float 65536)) 299 (condition-case nil (time-add day-seconds seconds)
300 (hi (floor (/ seconds current-time-arithmetic-base))) 300 (range-error))))
301 (hibase (* hi current-time-arithmetic-base))
302 (lo (floor (- seconds hibase))))
303 (and (< (abs (- seconds (+ hibase lo))) 2) ;; Check for integer overflow.
304 (cons hi lo))))
305 301
306(defun timezone-time-zone-from-absolute (date seconds) 302(defun timezone-time-zone-from-absolute (date seconds)
307 "Compute the local time zone for DATE at time SECONDS after midnight. 303 "Compute the local time zone for DATE at time SECONDS after midnight.
diff --git a/lisp/type-break.el b/lisp/type-break.el
index f954e5d1c26..a3af407bf17 100644
--- a/lisp/type-break.el
+++ b/lisp/type-break.el
@@ -604,8 +604,7 @@ INTERVAL is the full length of an interval (defaults to TIME)."
604 (type-break-time-warning-schedule time 'reset) 604 (type-break-time-warning-schedule time 'reset)
605 (type-break-run-at-time (max 1 time) nil 'type-break-alarm) 605 (type-break-run-at-time (max 1 time) nil 'type-break-alarm)
606 (setq type-break-time-next-break 606 (setq type-break-time-next-break
607 (type-break-time-sum (or start (current-time)) 607 (type-break-time-sum start (or interval time))))
608 (or interval time))))
609 608
610(defun type-break-cancel-schedule () 609(defun type-break-cancel-schedule ()
611 (type-break-cancel-time-warning-schedule) 610 (type-break-cancel-time-warning-schedule)
@@ -961,19 +960,11 @@ FRAC should be the inverse of the fractional value; for example, a value of
961(defun type-break-time-difference (a b) 960(defun type-break-time-difference (a b)
962 (round (float-time (time-subtract b a)))) 961 (round (float-time (time-subtract b a))))
963 962
964;; Return (in a new list the same in structure to that returned by 963;; Return a time value that is the sum of the time-value arguments.
965;; `current-time') the sum of the arguments. Each argument may be a time
966;; list or a single integer, a number of seconds.
967;; This function keeps the high and low 16 bits of the seconds properly
968;; balanced so that the lower value never exceeds 16 bits. Otherwise, when
969;; the result is passed to `current-time-string' it will toss some of the
970;; "low" bits and format the time incorrectly.
971(defun type-break-time-sum (&rest tmlist) 964(defun type-break-time-sum (&rest tmlist)
972 (let ((sum '(0 0 0))) 965 (let ((sum '(0 0)))
973 (dolist (tem tmlist) 966 (dolist (tem tmlist)
974 (setq sum (time-add sum (if (integerp tem) 967 (setq sum (time-add sum tem)))
975 (list (floor tem 65536) (mod tem 65536))
976 tem))))
977 sum)) 968 sum))
978 969
979(defun type-break-time-stamp (&optional when) 970(defun type-break-time-stamp (&optional when)
diff --git a/src/ChangeLog b/src/ChangeLog
index d1888987dbc..b169479a274 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,31 @@
12014-11-17 Paul Eggert <eggert@cs.ucla.edu>
2
3 Improve time stamp handling, and be more consistent about it.
4 * editfns.c (invalid_time): New function.
5 Use it instead of 'error ("Invalid time specification")'.
6 (time_add, time_subtract, time_arith, Ftime_add, Ftime_less_p)
7 (decode_float_time, lisp_to_timespec, lisp_time_struct):
8 New functions.
9 (make_time_tail, make_time): Remove. All uses changed to use
10 new functions or plain list4i.
11 (disassemble_lisp_time): Return effective length if successful.
12 Check that LOW is an integer, if it's combined with other components.
13 (decode_time_components): Decode into struct lisp_time, not
14 struct timespec, so that we can support a wide set of times
15 regardless of whether time_t is signed. Decode plain numbers
16 as seconds since the Epoch, and nil as the current time.
17 (lisp_time_argument, lisp_seconds_argument, Ffloat_time):
18 Reimplement in terms of new functions.
19 (Fencode_time): Just use list2i.
20 (syms_of_editfns): Add time-add, time-subtract, time-less-p.
21 * keyboard.c (decode_timer): Don't allow the new formats (floating
22 point or nil) in timers.
23 * systime.h (LO_TIME_BITS): New constant. Use it everywhere in
24 place of the magic number '16'.
25 (struct lisp_time): New type.
26 (decode_time_components): Use it.
27 (lisp_to_timespec): New decl.
28
12014-11-16 Lars Magne Ingebrigtsen <larsi@gnus.org> 292014-11-16 Lars Magne Ingebrigtsen <larsi@gnus.org>
2 30
3 * intervals.h (INTERVAL_WRITABLE_P): Check the `inhibit-read-only' 31 * intervals.h (INTERVAL_WRITABLE_P): Check the `inhibit-read-only'
diff --git a/src/editfns.c b/src/editfns.c
index 376d8e3a0ea..0a07886934c 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -64,6 +64,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
64extern Lisp_Object w32_get_internal_run_time (void); 64extern Lisp_Object w32_get_internal_run_time (void);
65#endif 65#endif
66 66
67static struct lisp_time lisp_time_struct (Lisp_Object, int *);
67static void set_time_zone_rule (char const *); 68static void set_time_zone_rule (char const *);
68static Lisp_Object format_time_string (char const *, ptrdiff_t, struct timespec, 69static Lisp_Object format_time_string (char const *, ptrdiff_t, struct timespec,
69 bool, struct tm *); 70 bool, struct tm *);
@@ -1392,6 +1393,12 @@ time_overflow (void)
1392 error ("Specified time is not representable"); 1393 error ("Specified time is not representable");
1393} 1394}
1394 1395
1396static void
1397invalid_time (void)
1398{
1399 error ("Invalid time specification");
1400}
1401
1395/* A substitute for mktime_z on platforms that lack it. It's not 1402/* A substitute for mktime_z on platforms that lack it. It's not
1396 thread-safe, but should be good enough for Emacs in typical use. */ 1403 thread-safe, but should be good enough for Emacs in typical use. */
1397#ifndef HAVE_TZALLOC 1404#ifndef HAVE_TZALLOC
@@ -1420,26 +1427,26 @@ mktime_z (timezone_t tz, struct tm *tm)
1420static EMACS_INT 1427static EMACS_INT
1421hi_time (time_t t) 1428hi_time (time_t t)
1422{ 1429{
1423 time_t hi = t >> 16; 1430 time_t hi = t >> LO_TIME_BITS;
1424 1431
1425 /* Check for overflow, helping the compiler for common cases where 1432 /* Check for overflow, helping the compiler for common cases where
1426 no runtime check is needed, and taking care not to convert 1433 no runtime check is needed, and taking care not to convert
1427 negative numbers to unsigned before comparing them. */ 1434 negative numbers to unsigned before comparing them. */
1428 if (! ((! TYPE_SIGNED (time_t) 1435 if (! ((! TYPE_SIGNED (time_t)
1429 || MOST_NEGATIVE_FIXNUM <= TIME_T_MIN >> 16 1436 || MOST_NEGATIVE_FIXNUM <= TIME_T_MIN >> LO_TIME_BITS
1430 || MOST_NEGATIVE_FIXNUM <= hi) 1437 || MOST_NEGATIVE_FIXNUM <= hi)
1431 && (TIME_T_MAX >> 16 <= MOST_POSITIVE_FIXNUM 1438 && (TIME_T_MAX >> LO_TIME_BITS <= MOST_POSITIVE_FIXNUM
1432 || hi <= MOST_POSITIVE_FIXNUM))) 1439 || hi <= MOST_POSITIVE_FIXNUM)))
1433 time_overflow (); 1440 time_overflow ();
1434 1441
1435 return hi; 1442 return hi;
1436} 1443}
1437 1444
1438/* Return the bottom 16 bits of the time T. */ 1445/* Return the bottom bits of the time T. */
1439static int 1446static int
1440lo_time (time_t t) 1447lo_time (time_t t)
1441{ 1448{
1442 return t & ((1 << 16) - 1); 1449 return t & ((1 << LO_TIME_BITS) - 1);
1443} 1450}
1444 1451
1445DEFUN ("current-time", Fcurrent_time, Scurrent_time, 0, 0, 0, 1452DEFUN ("current-time", Fcurrent_time, Scurrent_time, 0, 0, 0,
@@ -1453,6 +1460,96 @@ picosecond counts. */)
1453 return make_lisp_time (current_timespec ()); 1460 return make_lisp_time (current_timespec ());
1454} 1461}
1455 1462
1463static struct lisp_time
1464time_add (struct lisp_time ta, struct lisp_time tb)
1465{
1466 EMACS_INT hi = ta.hi + tb.hi;
1467 int lo = ta.lo + tb.lo;
1468 int us = ta.us + tb.us;
1469 int ps = ta.ps + tb.ps;
1470 us += (1000000 <= ps);
1471 ps -= (1000000 <= ps) * 1000000;
1472 lo += (1000000 <= us);
1473 us -= (1000000 <= us) * 1000000;
1474 hi += (1 << LO_TIME_BITS <= lo);
1475 lo -= (1 << LO_TIME_BITS <= lo) << LO_TIME_BITS;
1476 return (struct lisp_time) { hi, lo, us, ps };
1477}
1478
1479static struct lisp_time
1480time_subtract (struct lisp_time ta, struct lisp_time tb)
1481{
1482 EMACS_INT hi = ta.hi - tb.hi;
1483 int lo = ta.lo - tb.lo;
1484 int us = ta.us - tb.us;
1485 int ps = ta.ps - tb.ps;
1486 us -= (ps < 0);
1487 ps += (ps < 0) * 1000000;
1488 lo -= (us < 0);
1489 us += (us < 0) * 1000000;
1490 hi -= (lo < 0);
1491 lo += (lo < 0) << LO_TIME_BITS;
1492 return (struct lisp_time) { hi, lo, us, ps };
1493}
1494
1495static Lisp_Object
1496time_arith (Lisp_Object a, Lisp_Object b,
1497 struct lisp_time (*op) (struct lisp_time, struct lisp_time))
1498{
1499 int alen, blen;
1500 struct lisp_time ta = lisp_time_struct (a, &alen);
1501 struct lisp_time tb = lisp_time_struct (b, &blen);
1502 struct lisp_time t = op (ta, tb);
1503 if (! (MOST_NEGATIVE_FIXNUM <= t.hi && t.hi <= MOST_POSITIVE_FIXNUM))
1504 time_overflow ();
1505 Lisp_Object val = Qnil;
1506
1507 switch (max (alen, blen))
1508 {
1509 default:
1510 val = Fcons (make_number (t.ps), val);
1511 /* Fall through. */
1512 case 3:
1513 val = Fcons (make_number (t.us), val);
1514 /* Fall through. */
1515 case 2:
1516 val = Fcons (make_number (t.lo), val);
1517 val = Fcons (make_number (t.hi), val);
1518 break;
1519 }
1520
1521 return val;
1522}
1523
1524DEFUN ("time-add", Ftime_add, Stime_add, 2, 2, 0,
1525 doc: /* Return the sum of two time values A and B, as a time value. */)
1526 (Lisp_Object a, Lisp_Object b)
1527{
1528 return time_arith (a, b, time_add);
1529}
1530
1531DEFUN ("time-subtract", Ftime_subtract, Stime_subtract, 2, 2, 0,
1532 doc: /* Return the difference between two time values A and B, as a time value. */)
1533 (Lisp_Object a, Lisp_Object b)
1534{
1535 return time_arith (a, b, time_subtract);
1536}
1537
1538DEFUN ("time-less-p", Ftime_less_p, Stime_less_p, 2, 2, 0,
1539 doc: /* Return non-nil if time value T1 is earlier than time value T2. */)
1540 (Lisp_Object t1, Lisp_Object t2)
1541{
1542 int t1len, t2len;
1543 struct lisp_time a = lisp_time_struct (t1, &t1len);
1544 struct lisp_time b = lisp_time_struct (t2, &t2len);
1545 return ((a.hi != b.hi ? a.hi < b.hi
1546 : a.lo != b.lo ? a.lo < b.lo
1547 : a.us != b.us ? a.us < b.us
1548 : a.ps < b.ps)
1549 ? Qt : Qnil);
1550}
1551
1552
1456DEFUN ("get-internal-run-time", Fget_internal_run_time, Sget_internal_run_time, 1553DEFUN ("get-internal-run-time", Fget_internal_run_time, Sget_internal_run_time,
1457 0, 0, 0, 1554 0, 0, 0,
1458 doc: /* Return the current run time used by Emacs. 1555 doc: /* Return the current run time used by Emacs.
@@ -1491,21 +1588,6 @@ does the same thing as `current-time'. */)
1491} 1588}
1492 1589
1493 1590
1494/* Make a Lisp list that represents the time T with fraction TAIL. */
1495static Lisp_Object
1496make_time_tail (time_t t, Lisp_Object tail)
1497{
1498 return Fcons (make_number (hi_time (t)),
1499 Fcons (make_number (lo_time (t)), tail));
1500}
1501
1502/* Make a Lisp list that represents the system time T. */
1503static Lisp_Object
1504make_time (time_t t)
1505{
1506 return make_time_tail (t, Qnil);
1507}
1508
1509/* Make a Lisp list that represents the Emacs time T. T may be an 1591/* Make a Lisp list that represents the Emacs time T. T may be an
1510 invalid time, with a slightly negative tv_nsec value such as 1592 invalid time, with a slightly negative tv_nsec value such as
1511 UNKNOWN_MODTIME_NSECS; in that case, the Lisp list contains a 1593 UNKNOWN_MODTIME_NSECS; in that case, the Lisp list contains a
@@ -1513,23 +1595,30 @@ make_time (time_t t)
1513Lisp_Object 1595Lisp_Object
1514make_lisp_time (struct timespec t) 1596make_lisp_time (struct timespec t)
1515{ 1597{
1598 time_t s = t.tv_sec;
1516 int ns = t.tv_nsec; 1599 int ns = t.tv_nsec;
1517 return make_time_tail (t.tv_sec, list2i (ns / 1000, ns % 1000 * 1000)); 1600 return list4i (hi_time (s), lo_time (s), ns / 1000, ns % 1000 * 1000);
1518} 1601}
1519 1602
1520/* Decode a Lisp list SPECIFIED_TIME that represents a time. 1603/* Decode a Lisp list SPECIFIED_TIME that represents a time.
1521 Set *PHIGH, *PLOW, *PUSEC, *PPSEC to its parts; do not check their values. 1604 Set *PHIGH, *PLOW, *PUSEC, *PPSEC to its parts; do not check their values.
1522 Return true if successful. */ 1605 Return 2, 3, or 4 to indicate the effective length of SPECIFIED_TIME
1523static bool 1606 if successful, 0 if unsuccessful. */
1607static int
1524disassemble_lisp_time (Lisp_Object specified_time, Lisp_Object *phigh, 1608disassemble_lisp_time (Lisp_Object specified_time, Lisp_Object *phigh,
1525 Lisp_Object *plow, Lisp_Object *pusec, 1609 Lisp_Object *plow, Lisp_Object *pusec,
1526 Lisp_Object *ppsec) 1610 Lisp_Object *ppsec)
1527{ 1611{
1612 Lisp_Object high = make_number (0);
1613 Lisp_Object low = specified_time;
1614 Lisp_Object usec = make_number (0);
1615 Lisp_Object psec = make_number (0);
1616 int len = 4;
1617
1528 if (CONSP (specified_time)) 1618 if (CONSP (specified_time))
1529 { 1619 {
1530 Lisp_Object low = XCDR (specified_time); 1620 high = XCAR (specified_time);
1531 Lisp_Object usec = make_number (0); 1621 low = XCDR (specified_time);
1532 Lisp_Object psec = make_number (0);
1533 if (CONSP (low)) 1622 if (CONSP (low))
1534 { 1623 {
1535 Lisp_Object low_tail = XCDR (low); 1624 Lisp_Object low_tail = XCDR (low);
@@ -1540,40 +1629,119 @@ disassemble_lisp_time (Lisp_Object specified_time, Lisp_Object *phigh,
1540 low_tail = XCDR (low_tail); 1629 low_tail = XCDR (low_tail);
1541 if (CONSP (low_tail)) 1630 if (CONSP (low_tail))
1542 psec = XCAR (low_tail); 1631 psec = XCAR (low_tail);
1632 else
1633 len = 3;
1543 } 1634 }
1544 else if (!NILP (low_tail)) 1635 else if (!NILP (low_tail))
1545 usec = low_tail; 1636 {
1637 usec = low_tail;
1638 len = 3;
1639 }
1640 else
1641 len = 2;
1546 } 1642 }
1643 else
1644 len = 2;
1547 1645
1548 *phigh = XCAR (specified_time); 1646 /* When combining components, require LOW to be an integer,
1549 *plow = low; 1647 as otherwise it would be a pain to add up times. */
1550 *pusec = usec; 1648 if (! INTEGERP (low))
1551 *ppsec = psec; 1649 return 0;
1552 return 1;
1553 } 1650 }
1651 else if (INTEGERP (specified_time))
1652 len = 2;
1653
1654 *phigh = high;
1655 *plow = low;
1656 *pusec = usec;
1657 *ppsec = psec;
1658 return len;
1659}
1554 1660
1555 return 0; 1661/* Convert T into an Emacs time *RESULT, truncating toward minus infinity.
1662 Return true if T is in range, false otherwise. */
1663static bool
1664decode_float_time (double t, struct lisp_time *result)
1665{
1666 double lo_multiplier = 1 << LO_TIME_BITS;
1667 double emacs_time_min = MOST_NEGATIVE_FIXNUM * lo_multiplier;
1668 if (! (emacs_time_min <= t && t < -emacs_time_min))
1669 return false;
1670
1671 double small_t = t / lo_multiplier;
1672 EMACS_INT hi = small_t;
1673 double t_sans_hi = t - hi * lo_multiplier;
1674 int lo = t_sans_hi;
1675 long double fracps = (t_sans_hi - lo) * 1e12L;
1676#ifdef INT_FAST64_MAX
1677 int_fast64_t ifracps = fracps;
1678 int us = ifracps / 1000000;
1679 int ps = ifracps % 1000000;
1680#else
1681 int us = fracps / 1e6L;
1682 int ps = fracps - us * 1e6L;
1683#endif
1684 us -= (ps < 0);
1685 ps += (ps < 0) * 1000000;
1686 lo -= (us < 0);
1687 us += (us < 0) * 1000000;
1688 hi -= (lo < 0);
1689 lo += (lo < 0) << LO_TIME_BITS;
1690 result->hi = hi;
1691 result->lo = lo;
1692 result->us = us;
1693 result->ps = ps;
1694 return true;
1556} 1695}
1557 1696
1558/* From the time components HIGH, LOW, USEC and PSEC taken from a Lisp 1697/* From the time components HIGH, LOW, USEC and PSEC taken from a Lisp
1559 list, generate the corresponding time value. 1698 list, generate the corresponding time value.
1699 If LOW is floating point, the other components should be zero.
1560 1700
1561 If RESULT is not null, store into *RESULT the converted time; 1701 If RESULT is not null, store into *RESULT the converted time.
1562 if the converted time does not fit into struct timespec,
1563 store an invalid timespec to indicate the overflow.
1564 If *DRESULT is not null, store into *DRESULT the number of 1702 If *DRESULT is not null, store into *DRESULT the number of
1565 seconds since the start of the POSIX Epoch. 1703 seconds since the start of the POSIX Epoch.
1566 1704
1567 Return true if successful. */ 1705 Return true if successful, false if the components are of the
1706 wrong type or represent a time out of range. */
1568bool 1707bool
1569decode_time_components (Lisp_Object high, Lisp_Object low, Lisp_Object usec, 1708decode_time_components (Lisp_Object high, Lisp_Object low, Lisp_Object usec,
1570 Lisp_Object psec, 1709 Lisp_Object psec,
1571 struct timespec *result, double *dresult) 1710 struct lisp_time *result, double *dresult)
1572{ 1711{
1573 EMACS_INT hi, lo, us, ps; 1712 EMACS_INT hi, lo, us, ps;
1574 if (! (INTEGERP (high) && INTEGERP (low) 1713 if (! (INTEGERP (high)
1575 && INTEGERP (usec) && INTEGERP (psec))) 1714 && INTEGERP (usec) && INTEGERP (psec)))
1576 return false; 1715 return false;
1716 if (! INTEGERP (low))
1717 {
1718 if (FLOATP (low))
1719 {
1720 double t = XFLOAT_DATA (low);
1721 if (result && ! decode_float_time (t, result))
1722 return false;
1723 if (dresult)
1724 *dresult = t;
1725 return true;
1726 }
1727 else if (NILP (low))
1728 {
1729 struct timespec now = current_timespec ();
1730 if (result)
1731 {
1732 result->hi = hi_time (now.tv_sec);
1733 result->lo = lo_time (now.tv_sec);
1734 result->us = now.tv_nsec / 1000;
1735 result->ps = now.tv_nsec % 1000 * 1000;
1736 }
1737 if (dresult)
1738 *dresult = now.tv_sec + now.tv_nsec / 1e9;
1739 return true;
1740 }
1741 else
1742 return false;
1743 }
1744
1577 hi = XINT (high); 1745 hi = XINT (high);
1578 lo = XINT (low); 1746 lo = XINT (low);
1579 us = XINT (usec); 1747 us = XINT (usec);
@@ -1583,53 +1751,68 @@ decode_time_components (Lisp_Object high, Lisp_Object low, Lisp_Object usec,
1583 each overflow into the next higher-order component. */ 1751 each overflow into the next higher-order component. */
1584 us += ps / 1000000 - (ps % 1000000 < 0); 1752 us += ps / 1000000 - (ps % 1000000 < 0);
1585 lo += us / 1000000 - (us % 1000000 < 0); 1753 lo += us / 1000000 - (us % 1000000 < 0);
1586 hi += lo >> 16; 1754 hi += lo >> LO_TIME_BITS;
1587 ps = ps % 1000000 + 1000000 * (ps % 1000000 < 0); 1755 ps = ps % 1000000 + 1000000 * (ps % 1000000 < 0);
1588 us = us % 1000000 + 1000000 * (us % 1000000 < 0); 1756 us = us % 1000000 + 1000000 * (us % 1000000 < 0);
1589 lo &= (1 << 16) - 1; 1757 lo &= (1 << LO_TIME_BITS) - 1;
1590 1758
1591 if (result) 1759 if (result)
1592 { 1760 {
1593 if ((TYPE_SIGNED (time_t) ? TIME_T_MIN >> 16 <= hi : 0 <= hi) 1761 if (! (MOST_NEGATIVE_FIXNUM <= hi && hi <= MOST_POSITIVE_FIXNUM))
1594 && hi <= TIME_T_MAX >> 16) 1762 return false;
1595 { 1763 result->hi = hi;
1596 /* Return the greatest representable time that is not greater 1764 result->lo = lo;
1597 than the requested time. */ 1765 result->us = us;
1598 time_t sec = hi; 1766 result->ps = ps;
1599 *result = make_timespec ((sec << 16) + lo, us * 1000 + ps / 1000);
1600 }
1601 else
1602 *result = invalid_timespec ();
1603 } 1767 }
1604 1768
1605 if (dresult) 1769 if (dresult)
1606 *dresult = (us * 1e6 + ps) / 1e12 + lo + hi * 65536.0; 1770 {
1771 double dhi = hi;
1772 *dresult = (us * 1e6 + ps) / 1e12 + lo + dhi * (1 << LO_TIME_BITS);
1773 }
1607 1774
1608 return true; 1775 return true;
1609} 1776}
1610 1777
1778struct timespec
1779lisp_to_timespec (struct lisp_time t)
1780{
1781 if (! ((TYPE_SIGNED (time_t) ? TIME_T_MIN >> LO_TIME_BITS <= t.hi : 0 <= t.hi)
1782 && t.hi <= TIME_T_MAX >> LO_TIME_BITS))
1783 return invalid_timespec ();
1784 time_t s = (t.hi << LO_TIME_BITS) + t.lo;
1785 int ns = t.us * 1000 + t.ps / 1000;
1786 return make_timespec (s, ns);
1787}
1788
1611/* Decode a Lisp list SPECIFIED_TIME that represents a time. 1789/* Decode a Lisp list SPECIFIED_TIME that represents a time.
1790 Store its effective length into *PLEN.
1612 If SPECIFIED_TIME is nil, use the current time. 1791 If SPECIFIED_TIME is nil, use the current time.
1792 Signal an error if SPECIFIED_TIME does not represent a time. */
1793static struct lisp_time
1794lisp_time_struct (Lisp_Object specified_time, int *plen)
1795{
1796 Lisp_Object high, low, usec, psec;
1797 struct lisp_time t;
1798 int len = disassemble_lisp_time (specified_time, &high, &low, &usec, &psec);
1799 if (! (len && decode_time_components (high, low, usec, psec, &t, 0)))
1800 invalid_time ();
1801 *plen = len;
1802 return t;
1803}
1613 1804
1614 Round the time down to the nearest struct timespec value. 1805/* Like lisp_time_struct, except return a struct timespec.
1615 Return seconds since the Epoch. 1806 Discard any low-order digits. */
1616 Signal an error if unsuccessful. */
1617struct timespec 1807struct timespec
1618lisp_time_argument (Lisp_Object specified_time) 1808lisp_time_argument (Lisp_Object specified_time)
1619{ 1809{
1620 if (NILP (specified_time)) 1810 int len;
1621 return current_timespec (); 1811 struct lisp_time lt = lisp_time_struct (specified_time, &len);
1622 else 1812 struct timespec t = lisp_to_timespec (lt);
1623 { 1813 if (! timespec_valid_p (t))
1624 Lisp_Object high, low, usec, psec; 1814 time_overflow ();
1625 struct timespec t; 1815 return t;
1626 if (! (disassemble_lisp_time (specified_time, &high, &low, &usec, &psec)
1627 && decode_time_components (high, low, usec, psec, &t, 0)))
1628 error ("Invalid time specification");
1629 if (! timespec_valid_p (t))
1630 time_overflow ();
1631 return t;
1632 }
1633} 1816}
1634 1817
1635/* Like lisp_time_argument, except decode only the seconds part, 1818/* Like lisp_time_argument, except decode only the seconds part,
@@ -1637,20 +1820,16 @@ lisp_time_argument (Lisp_Object specified_time)
1637static time_t 1820static time_t
1638lisp_seconds_argument (Lisp_Object specified_time) 1821lisp_seconds_argument (Lisp_Object specified_time)
1639{ 1822{
1640 if (NILP (specified_time)) 1823 Lisp_Object high, low, usec, psec;
1641 return time (NULL); 1824 struct lisp_time t;
1642 else 1825 if (! (disassemble_lisp_time (specified_time, &high, &low, &usec, &psec)
1643 { 1826 && decode_time_components (high, low, make_number (0),
1644 Lisp_Object high, low, usec, psec; 1827 make_number (0), &t, 0)))
1645 struct timespec t; 1828 invalid_time ();
1646 if (! (disassemble_lisp_time (specified_time, &high, &low, &usec, &psec) 1829 if (! ((TYPE_SIGNED (time_t) ? TIME_T_MIN >> LO_TIME_BITS <= t.hi : 0 <= t.hi)
1647 && decode_time_components (high, low, make_number (0), 1830 && t.hi <= TIME_T_MAX >> LO_TIME_BITS))
1648 make_number (0), &t, 0))) 1831 time_overflow ();
1649 error ("Invalid time specification"); 1832 return (t.hi << LO_TIME_BITS) + t.lo;
1650 if (! timespec_valid_p (t))
1651 time_overflow ();
1652 return t.tv_sec;
1653 }
1654} 1833}
1655 1834
1656DEFUN ("float-time", Ffloat_time, Sfloat_time, 0, 1, 0, 1835DEFUN ("float-time", Ffloat_time, Sfloat_time, 0, 1, 0,
@@ -1668,18 +1847,10 @@ or (if you need time as a string) `format-time-string'. */)
1668 (Lisp_Object specified_time) 1847 (Lisp_Object specified_time)
1669{ 1848{
1670 double t; 1849 double t;
1671 if (NILP (specified_time)) 1850 Lisp_Object high, low, usec, psec;
1672 { 1851 if (! (disassemble_lisp_time (specified_time, &high, &low, &usec, &psec)
1673 struct timespec now = current_timespec (); 1852 && decode_time_components (high, low, usec, psec, 0, &t)))
1674 t = now.tv_sec + now.tv_nsec / 1e9; 1853 invalid_time ();
1675 }
1676 else
1677 {
1678 Lisp_Object high, low, usec, psec;
1679 if (! (disassemble_lisp_time (specified_time, &high, &low, &usec, &psec)
1680 && decode_time_components (high, low, usec, psec, 0, &t)))
1681 error ("Invalid time specification");
1682 }
1683 return make_float (t); 1854 return make_float (t);
1684} 1855}
1685 1856
@@ -1969,7 +2140,7 @@ usage: (encode-time SECOND MINUTE HOUR DAY MONTH YEAR &optional ZONE) */)
1969 if (value == (time_t) -1) 2140 if (value == (time_t) -1)
1970 time_overflow (); 2141 time_overflow ();
1971 2142
1972 return make_time (value); 2143 return list2i (hi_time (value), lo_time (value));
1973} 2144}
1974 2145
1975DEFUN ("current-time-string", Fcurrent_time_string, Scurrent_time_string, 0, 1, 0, 2146DEFUN ("current-time-string", Fcurrent_time_string, Scurrent_time_string, 0, 1, 0,
@@ -4874,6 +5045,9 @@ functions if all the text being accessed has this property. */);
4874 defsubr (&Suser_full_name); 5045 defsubr (&Suser_full_name);
4875 defsubr (&Semacs_pid); 5046 defsubr (&Semacs_pid);
4876 defsubr (&Scurrent_time); 5047 defsubr (&Scurrent_time);
5048 defsubr (&Stime_add);
5049 defsubr (&Stime_subtract);
5050 defsubr (&Stime_less_p);
4877 defsubr (&Sget_internal_run_time); 5051 defsubr (&Sget_internal_run_time);
4878 defsubr (&Sformat_time_string); 5052 defsubr (&Sformat_time_string);
4879 defsubr (&Sfloat_time); 5053 defsubr (&Sfloat_time);
diff --git a/src/keyboard.c b/src/keyboard.c
index 060784cf0af..908eb59ff9c 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -4429,10 +4429,15 @@ decode_timer (Lisp_Object timer, struct timespec *result)
4429 vector = XVECTOR (timer)->contents; 4429 vector = XVECTOR (timer)->contents;
4430 if (! NILP (vector[0])) 4430 if (! NILP (vector[0]))
4431 return 0; 4431 return 0;
4432 4432 if (! INTEGERP (vector[2]))
4433 return (decode_time_components (vector[1], vector[2], vector[3], vector[8], 4433 return false;
4434 result, 0) 4434
4435 && timespec_valid_p (*result)); 4435 struct lisp_time t;
4436 if (! decode_time_components (vector[1], vector[2], vector[3], vector[8],
4437 &t, 0))
4438 return false;
4439 *result = lisp_to_timespec (t);
4440 return timespec_valid_p (*result);
4436} 4441}
4437 4442
4438 4443
diff --git a/src/systime.h b/src/systime.h
index 8f018044660..e0f7eec7977 100644
--- a/src/systime.h
+++ b/src/systime.h
@@ -86,10 +86,23 @@ extern void set_waiting_for_input (struct timespec *);
86 happen when this files is used outside the src directory). 86 happen when this files is used outside the src directory).
87 Use GCPRO1 to determine if lisp.h was included. */ 87 Use GCPRO1 to determine if lisp.h was included. */
88#ifdef GCPRO1 88#ifdef GCPRO1
89
90/* Emacs uses the integer list (HI LO US PS) to represent the time
91 (HI << LO_TIME_BITS) + LO + US / 1e6 + PS / 1e12. */
92enum { LO_TIME_BITS = 16 };
93
94/* A Lisp time (HI LO US PS), sans the cons cells. */
95struct lisp_time
96{
97 EMACS_INT hi;
98 int lo, us, ps;
99};
100
89/* defined in editfns.c */ 101/* defined in editfns.c */
90extern Lisp_Object make_lisp_time (struct timespec); 102extern Lisp_Object make_lisp_time (struct timespec);
91extern bool decode_time_components (Lisp_Object, Lisp_Object, Lisp_Object, 103extern bool decode_time_components (Lisp_Object, Lisp_Object, Lisp_Object,
92 Lisp_Object, struct timespec *, double *); 104 Lisp_Object, struct lisp_time *, double *);
105extern struct timespec lisp_to_timespec (struct lisp_time);
93extern struct timespec lisp_time_argument (Lisp_Object); 106extern struct timespec lisp_time_argument (Lisp_Object);
94#endif 107#endif
95 108