diff options
| author | Paul Eggert | 2014-11-16 20:38:15 -0800 |
|---|---|---|
| committer | Paul Eggert | 2014-11-16 20:41:22 -0800 |
| commit | 0921dbc3ab4dcc6b291ef45e46a24b322bbcb885 (patch) | |
| tree | 0e320978c7d30af415bb7de6e0b8f6735a3ca3d1 | |
| parent | 058f56d24f776bdc25bcac86fe1f8969a78374e9 (diff) | |
| download | emacs-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/ChangeLog | 8 | ||||
| -rw-r--r-- | doc/lispref/os.texi | 133 | ||||
| -rw-r--r-- | etc/ChangeLog | 5 | ||||
| -rw-r--r-- | etc/NEWS | 19 | ||||
| -rw-r--r-- | lisp/ChangeLog | 28 | ||||
| -rw-r--r-- | lisp/allout-widgets.el | 4 | ||||
| -rw-r--r-- | lisp/arc-mode.el | 6 | ||||
| -rw-r--r-- | lisp/calendar/cal-dst.el | 1 | ||||
| -rw-r--r-- | lisp/calendar/time-date.el | 158 | ||||
| -rw-r--r-- | lisp/emacs-lisp/timer.el | 16 | ||||
| -rw-r--r-- | lisp/ldefs-boot.el | 21 | ||||
| -rw-r--r-- | lisp/net/tramp.el | 14 | ||||
| -rw-r--r-- | lisp/proced.el | 15 | ||||
| -rw-r--r-- | lisp/timezone.el | 10 | ||||
| -rw-r--r-- | lisp/type-break.el | 17 | ||||
| -rw-r--r-- | src/ChangeLog | 28 | ||||
| -rw-r--r-- | src/editfns.c | 364 | ||||
| -rw-r--r-- | src/keyboard.c | 13 | ||||
| -rw-r--r-- | src/systime.h | 15 |
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 @@ | |||
| 1 | 2014-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 | |||
| 1 | 2014-11-16 Lars Magne Ingebrigtsen <larsi@gnus.org> | 9 | 2014-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}. | |||
| 1213 | zone. | 1213 | zone. |
| 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 |
| 1217 | integers, @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 | 1218 | This represents the number of seconds from the @dfn{epoch} (January |
| 1219 | integers, @code{(@var{sec-high} @var{sec-low} @var{microsec})}, or of | 1219 | 1, 1970 at 00:00 UTC), using the formula: |
| 1220 | two 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 | ||
| 1222 | integer 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 |
| 1229 | is the number of seconds from the @dfn{epoch} (January 1, 1970 at 00:00 | 1227 | The return value of @code{current-time} represents time using this |
| 1230 | UTC) to the specified time. The third list element @var{microsec}, if | 1228 | form, as do the timestamps in the return values of other functions |
| 1231 | present, gives the number of microseconds from the start of that | 1229 | such as @code{file-attributes} (@pxref{Definition of |
| 1232 | second to the specified time. | 1230 | file-attributes}). In some cases, functions may return two- or |
| 1233 | Similarly, the fourth list element @var{picosec}, if present, gives | 1231 | three-element lists, with omitted @var{microsec} and @var{picosec} |
| 1234 | the number of picoseconds from the start of that microsecond to the | 1232 | components defaulting to zero. |
| 1235 | specified 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 |
| 1238 | integers, 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 | 1237 | format, which can be a list of integers as above, or a single number |
| 1240 | file-attributes}). In function arguments, e.g., the @var{time-value} | 1238 | for seconds since the epoch, or @code{nil} for the current time. You |
| 1241 | argument to @code{current-time-string}, two-, three-, and four-integer | 1239 | can convert a time value into a human-readable string using |
| 1242 | lists are accepted. You can convert times from the list | 1240 | @code{current-time-string} and @code{format-time-string}, into a list |
| 1243 | representation into standard human-readable strings using | 1241 | of 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 | 1243 | described in the following sections. |
| 1246 | in the following sections. | ||
| 1247 | 1244 | ||
| 1248 | @defun current-time-string &optional time-value | 1245 | @defun current-time-string &optional time-value |
| 1249 | This function returns the current time and date as a human-readable | 1246 | This 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, | |||
| 1256 | as the year might not have exactly four digits, and additional | 1253 | as the year might not have exactly four digits, and additional |
| 1257 | information may some day be added at the end. | 1254 | information may some day be added at the end. |
| 1258 | 1255 | ||
| 1259 | The argument @var{time-value}, if given, specifies a time to format | 1256 | The argument @var{time-value}, if given, specifies a time to format, |
| 1260 | (represented as a list of integers), instead of the current time. | 1257 | instead 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 |
| 1280 | This function returns the current time as a floating-point number of | 1277 | This function returns the current time as a floating-point number of |
| 1281 | seconds since the epoch. The optional argument @var{time-value}, if | 1278 | seconds since the epoch. The optional argument @var{time-value}, if |
| 1282 | given, specifies a time (represented as a list of integers) to convert | 1279 | given, specifies a time to convert instead of the current time. |
| 1283 | instead 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 |
| 1286 | exact. Do not use this function if precise time stamps are required. | 1282 | exact. 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 | ||
| 1288 | This function converts a time value to list-of-integer form. | ||
| 1289 | For example, if @var{time-value} is a number, @code{(time-to-seconds | ||
| 1290 | (seconds-to-time @var{time-value}))} equals the number unless overflow | ||
| 1291 | or 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. | |||
| 1302 | If the operating system doesn't supply all the information necessary to | 1307 | If the operating system doesn't supply all the information necessary to |
| 1303 | compute the value, the unknown elements of the list are @code{nil}. | 1308 | compute the value, the unknown elements of the list are @code{nil}. |
| 1304 | 1309 | ||
| 1305 | The argument @var{time-value}, if given, specifies a time (represented | 1310 | The argument @var{time-value}, if given, specifies a time value to |
| 1306 | as a list of integers) to analyze instead of the current time. | 1311 | analyze instead of the current time. |
| 1307 | @end defun | 1312 | @end defun |
| 1308 | 1313 | ||
| 1309 | The current time zone is determined by the @env{TZ} environment | 1314 | The 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 |
| 1320 | as explained in the previous section) into calendrical information and | 1325 | calendrical information and vice versa. |
| 1321 | vice 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 |
| 1324 | 32 bits of information; these systems typically handle only the times | 1328 | 32 bits of information in their seconds component; these systems |
| 1325 | from 1901-12-13 20:45:52 UTC through 2038-01-19 03:14:07 UTC@. | 1329 | typically handle only the times from 1901-12-13 20:45:52 UTC through |
| 1326 | However, 64-bit and some 32-bit operating systems have larger time | 1330 | 2038-01-19 03:14:07 UTC@. However, 64-bit and some 32-bit operating |
| 1327 | values, and can represent times far in the past or future. | 1331 | systems have larger seconds components, and can represent times far in |
| 1332 | the 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 |
| 1330 | for dates before the Gregorian calendar was introduced. Year numbers | 1335 | for 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 | |||
| 1332 | as traditional Gregorian years do; for example, the year number | 1337 | as 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 |
| 1336 | This function converts a time value into calendrical information. If | 1341 | This function converts a time value into calendrical information. If |
| 1337 | you don't specify @var{time}, it decodes the current time. The return | 1342 | you don't specify @var{time-value}, it decodes the current time. The return |
| 1338 | value is a list of nine elements, as follows: | 1343 | value 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 |
| 1375 | This function is the inverse of @code{decode-time}. It converts seven | 1380 | This function is the inverse of @code{decode-time}. It converts seven |
| 1376 | items of calendrical data into a time value. For the meanings of the | 1381 | items of calendrical data into a list-of-integer time value. For the |
| 1377 | arguments, see the table above under @code{decode-time}. | 1382 | meanings of the arguments, see the table above under |
| 1383 | @code{decode-time}. | ||
| 1378 | 1384 | ||
| 1379 | Year numbers less than 100 are not treated specially. If you want them | 1385 | Year numbers less than 100 are not treated specially. If you want them |
| 1380 | to stand for years above 1900, or years above 2000, you must alter them | 1386 | to 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 | |||
| 1418 | corresponding time value. | 1424 | corresponding 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 |
| 1422 | This function converts @var{time} (or the current time, if @var{time} is | 1428 | |
| 1423 | omitted) to a string according to @var{format-string}. The argument | 1429 | This 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 |
| 1425 | substitute parts of the time. Here is a table of what the | 1433 | substitute 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 | |||
| 1540 | system. | 1548 | system. |
| 1541 | @end defun | 1549 | @end defun |
| 1542 | 1550 | ||
| 1543 | @defun seconds-to-time seconds | ||
| 1544 | This function converts @var{seconds}, the number of seconds since the | ||
| 1545 | epoch, 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 |
| 1550 | This function converts its argument @var{seconds} into a string of | 1552 | This function converts its argument @var{seconds} into a string of |
| 1551 | years, days, hours, etc., according to @var{format-string}. The | 1553 | years, 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 |
| 1621 | This function returns the processor run time used by Emacs as a list | 1623 | This function returns the processor run time used by Emacs as a list |
| 1622 | of four integers: @code{(@var{high} @var{low} @var{microsec} | 1624 | of 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 |
| 1649 | This returns @code{t} if time value @var{t1} is less than time value | 1651 | This 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 |
| 1654 | This returns the time difference @var{t1} @minus{} @var{t2} between | 1656 | This returns the time difference @var{t1} @minus{} @var{t2} between |
| 1655 | two time values, in the same format as a time value. | 1657 | two 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 |
| 1659 | This returns the sum of two time values, one of which ought to | 1661 | This returns the sum of two time values, as a time value. |
| 1660 | represent a time difference rather than a point in time. | 1662 | One argument should represent a time difference rather than a point in time. |
| 1661 | Here is how to add a number of seconds to a time value: | 1663 | Here 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 |
| 1669 | This function returns the number of days between the beginning of year | 1671 | This function returns the number of days between the beginning of year |
| 1670 | 1 and @var{time}. | 1672 | 1 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 |
| 1674 | This returns the day number within the year corresponding to @var{time}. | 1676 | This 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 @@ | |||
| 1 | 2014-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 | |||
| 1 | 2014-11-14 Lars Magne Ingebrigtsen <larsi@gnus.org> | 6 | 2014-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. |
| @@ -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 | ||
| 385 | current time) as well as the usual list-of-integer representation. | ||
| 386 | Affected 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 | ||
| 392 | been obsoleted. | ||
| 393 | |||
| 394 | *** `calendar-next-time-zone-transition', `time-add', and | ||
| 395 | `time-subtract' no longer return time values in the obsolete and | ||
| 396 | undocumented integer-pair format. Instead, they return a list of two | ||
| 397 | integers. | ||
| 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 @@ | |||
| 1 | 2014-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 | |||
| 1 | 2014-11-16 Lars Magne Ingebrigtsen <larsi@gnus.org> | 29 | 2014-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") |
| 218 | Return 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. | ||
| 219 | Return 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 |
| 126 | and PSECS picoseconds. SECS may be either an integer or a | 126 | and PSECS picoseconds. SECS may be either an integer or a |
| 127 | floating point number." | 127 | floating 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' | |||
| 486 | when it exits, to make these timers start counting again." | 484 | when 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" "\ |
| 27481 | Convert SECONDS (a floating point number) to a time value. | 27481 | Convert 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" "\ | ||
| 27486 | Return 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" "\ |
| 27491 | Convert DAYS into a time value. | 27486 | Convert 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") |
| 27504 | Subtract two time values, T1 minus T2. | 27499 | (autoload 'time-less-p "time-date") |
| 27505 | Return the difference in the format of a time value. | ||
| 27506 | |||
| 27507 | \(fn T1 T2)" nil nil) | ||
| 27508 | |||
| 27509 | (autoload 'time-add "time-date" "\ | ||
| 27510 | Add 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" "\ |
| 27515 | Return the number of days between year 1 and DATE. | 27502 | Return 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. |
| 4252 | Return the difference in the format of a time value." | 4246 | Return 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. |
| 1188 | Return `equal' if T1 equals T2. Return nil otherwise." | 1186 | Return `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 @@ | |||
| 1 | 2014-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 | |||
| 1 | 2014-11-16 Lars Magne Ingebrigtsen <larsi@gnus.org> | 29 | 2014-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/>. */ | |||
| 64 | extern Lisp_Object w32_get_internal_run_time (void); | 64 | extern Lisp_Object w32_get_internal_run_time (void); |
| 65 | #endif | 65 | #endif |
| 66 | 66 | ||
| 67 | static struct lisp_time lisp_time_struct (Lisp_Object, int *); | ||
| 67 | static void set_time_zone_rule (char const *); | 68 | static void set_time_zone_rule (char const *); |
| 68 | static Lisp_Object format_time_string (char const *, ptrdiff_t, struct timespec, | 69 | static 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 | ||
| 1396 | static void | ||
| 1397 | invalid_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) | |||
| 1420 | static EMACS_INT | 1427 | static EMACS_INT |
| 1421 | hi_time (time_t t) | 1428 | hi_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. */ |
| 1439 | static int | 1446 | static int |
| 1440 | lo_time (time_t t) | 1447 | lo_time (time_t t) |
| 1441 | { | 1448 | { |
| 1442 | return t & ((1 << 16) - 1); | 1449 | return t & ((1 << LO_TIME_BITS) - 1); |
| 1443 | } | 1450 | } |
| 1444 | 1451 | ||
| 1445 | DEFUN ("current-time", Fcurrent_time, Scurrent_time, 0, 0, 0, | 1452 | DEFUN ("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 | ||
| 1463 | static struct lisp_time | ||
| 1464 | time_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 | |||
| 1479 | static struct lisp_time | ||
| 1480 | time_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 | |||
| 1495 | static Lisp_Object | ||
| 1496 | time_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 | |||
| 1524 | DEFUN ("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 | |||
| 1531 | DEFUN ("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 | |||
| 1538 | DEFUN ("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 | |||
| 1456 | DEFUN ("get-internal-run-time", Fget_internal_run_time, Sget_internal_run_time, | 1553 | DEFUN ("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. */ | ||
| 1495 | static Lisp_Object | ||
| 1496 | make_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. */ | ||
| 1503 | static Lisp_Object | ||
| 1504 | make_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) | |||
| 1513 | Lisp_Object | 1595 | Lisp_Object |
| 1514 | make_lisp_time (struct timespec t) | 1596 | make_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 |
| 1523 | static bool | 1606 | if successful, 0 if unsuccessful. */ |
| 1607 | static int | ||
| 1524 | disassemble_lisp_time (Lisp_Object specified_time, Lisp_Object *phigh, | 1608 | disassemble_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. */ | ||
| 1663 | static bool | ||
| 1664 | decode_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. */ | ||
| 1568 | bool | 1707 | bool |
| 1569 | decode_time_components (Lisp_Object high, Lisp_Object low, Lisp_Object usec, | 1708 | decode_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 | ||
| 1778 | struct timespec | ||
| 1779 | lisp_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. */ | ||
| 1793 | static struct lisp_time | ||
| 1794 | lisp_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. */ | ||
| 1617 | struct timespec | 1807 | struct timespec |
| 1618 | lisp_time_argument (Lisp_Object specified_time) | 1808 | lisp_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) | |||
| 1637 | static time_t | 1820 | static time_t |
| 1638 | lisp_seconds_argument (Lisp_Object specified_time) | 1821 | lisp_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 | ||
| 1656 | DEFUN ("float-time", Ffloat_time, Sfloat_time, 0, 1, 0, | 1835 | DEFUN ("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 | ||
| 1975 | DEFUN ("current-time-string", Fcurrent_time_string, Scurrent_time_string, 0, 1, 0, | 2146 | DEFUN ("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. */ | ||
| 92 | enum { LO_TIME_BITS = 16 }; | ||
| 93 | |||
| 94 | /* A Lisp time (HI LO US PS), sans the cons cells. */ | ||
| 95 | struct lisp_time | ||
| 96 | { | ||
| 97 | EMACS_INT hi; | ||
| 98 | int lo, us, ps; | ||
| 99 | }; | ||
| 100 | |||
| 89 | /* defined in editfns.c */ | 101 | /* defined in editfns.c */ |
| 90 | extern Lisp_Object make_lisp_time (struct timespec); | 102 | extern Lisp_Object make_lisp_time (struct timespec); |
| 91 | extern bool decode_time_components (Lisp_Object, Lisp_Object, Lisp_Object, | 103 | extern bool decode_time_components (Lisp_Object, Lisp_Object, Lisp_Object, |
| 92 | Lisp_Object, struct timespec *, double *); | 104 | Lisp_Object, struct lisp_time *, double *); |
| 105 | extern struct timespec lisp_to_timespec (struct lisp_time); | ||
| 93 | extern struct timespec lisp_time_argument (Lisp_Object); | 106 | extern struct timespec lisp_time_argument (Lisp_Object); |
| 94 | #endif | 107 | #endif |
| 95 | 108 | ||