diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/timefns.c | 187 |
1 files changed, 111 insertions, 76 deletions
diff --git a/src/timefns.c b/src/timefns.c index 979550c8431..bf49843aae7 100644 --- a/src/timefns.c +++ b/src/timefns.c | |||
| @@ -1090,11 +1090,14 @@ time_arith (Lisp_Object a, Lisp_Object b, bool subtract) | |||
| 1090 | } | 1090 | } |
| 1091 | 1091 | ||
| 1092 | /* Return an integer if the timestamp resolution is 1, | 1092 | /* Return an integer if the timestamp resolution is 1, |
| 1093 | otherwise the (TICKS . HZ) form if either argument is that way, | 1093 | otherwise the (TICKS . HZ) form if !CURRENT_TIME_LIST or if |
| 1094 | otherwise the (HI LO US PS) form for backward compatibility. */ | 1094 | either input form supports timestamps that cannot be expressed |
| 1095 | exactly in (HI LO US PS) form, otherwise the (HI LO US PS) form | ||
| 1096 | for backward compatibility. */ | ||
| 1095 | return (EQ (hz, make_fixnum (1)) | 1097 | return (EQ (hz, make_fixnum (1)) |
| 1096 | ? ticks | 1098 | ? ticks |
| 1097 | : timeform_sub_ps_p (aform) || timeform_sub_ps_p (bform) | 1099 | : (!CURRENT_TIME_LIST |
| 1100 | || timeform_sub_ps_p (aform) || timeform_sub_ps_p (bform)) | ||
| 1098 | ? Fcons (ticks, hz) | 1101 | ? Fcons (ticks, hz) |
| 1099 | : ticks_hz_list4 (ticks, hz)); | 1102 | : ticks_hz_list4 (ticks, hz)); |
| 1100 | } | 1103 | } |
| @@ -1374,8 +1377,8 @@ usage: (format-time-string FORMAT-STRING &optional TIME ZONE) */) | |||
| 1374 | t, zone, &tm); | 1377 | t, zone, &tm); |
| 1375 | } | 1378 | } |
| 1376 | 1379 | ||
| 1377 | DEFUN ("decode-time", Fdecode_time, Sdecode_time, 0, 2, 0, | 1380 | DEFUN ("decode-time", Fdecode_time, Sdecode_time, 0, 3, 0, |
| 1378 | doc: /* Decode a time value as (SEC MINUTE HOUR DAY MONTH YEAR DOW DST UTCOFF SUBSEC). | 1381 | doc: /* Decode a time value as (SEC MINUTE HOUR DAY MONTH YEAR DOW DST UTCOFF). |
| 1379 | The optional TIME is the time value to convert. See | 1382 | The optional TIME is the time value to convert. See |
| 1380 | `format-time-string' for the various forms of a time value. | 1383 | `format-time-string' for the various forms of a time value. |
| 1381 | 1384 | ||
| @@ -1385,29 +1388,33 @@ the TZ environment variable. It can also be a list (as from | |||
| 1385 | `current-time-zone') or an integer (the UTC offset in seconds) applied | 1388 | `current-time-zone') or an integer (the UTC offset in seconds) applied |
| 1386 | without consideration for daylight saving time. | 1389 | without consideration for daylight saving time. |
| 1387 | 1390 | ||
| 1391 | The optional FORM specifies the form of the SEC member. If `integer', | ||
| 1392 | SEC is an integer; if t, SEC uses the same resolution as TIME. An | ||
| 1393 | omitted or nil FORM is currently treated like `integer', but this may | ||
| 1394 | change in future Emacs versions. | ||
| 1395 | |||
| 1388 | To access (or alter) the elements in the time value, the | 1396 | To access (or alter) the elements in the time value, the |
| 1389 | `decoded-time-second', `decoded-time-minute', `decoded-time-hour', | 1397 | `decoded-time-second', `decoded-time-minute', `decoded-time-hour', |
| 1390 | `decoded-time-day', `decoded-time-month', `decoded-time-year', | 1398 | `decoded-time-day', `decoded-time-month', `decoded-time-year', |
| 1391 | `decoded-time-weekday', `decoded-time-dst', `decoded-time-zone' and | 1399 | `decoded-time-weekday', `decoded-time-dst' and `decoded-time-zone' |
| 1392 | `decoded-time-subsec' accessors can be used. | 1400 | accessors can be used. |
| 1393 | 1401 | ||
| 1394 | The list has the following ten members: SEC is an integer between 0 | 1402 | The list has the following nine members: SEC is an integer or |
| 1395 | and 60; SEC is 60 for a leap second, which only some operating systems | 1403 | Lisp timestamp representing a nonnegative value less than 60 |
| 1396 | support. MINUTE is an integer between 0 and 59. HOUR is an integer | 1404 | \(or less than 61 if the operating system supports leap seconds). |
| 1405 | MINUTE is an integer between 0 and 59. HOUR is an integer | ||
| 1397 | between 0 and 23. DAY is an integer between 1 and 31. MONTH is an | 1406 | between 0 and 23. DAY is an integer between 1 and 31. MONTH is an |
| 1398 | integer between 1 and 12. YEAR is an integer indicating the | 1407 | integer between 1 and 12. YEAR is an integer indicating the |
| 1399 | four-digit year. DOW is the day of week, an integer between 0 and 6, | 1408 | four-digit year. DOW is the day of week, an integer between 0 and 6, |
| 1400 | where 0 is Sunday. DST is t if daylight saving time is in effect, | 1409 | where 0 is Sunday. DST is t if daylight saving time is in effect, |
| 1401 | nil if it is not in effect, and -1 if daylight saving information is | 1410 | nil if it is not in effect, and -1 if daylight saving information is |
| 1402 | not available. UTCOFF is an integer indicating the UTC offset in | 1411 | not available. UTCOFF is an integer indicating the UTC offset in |
| 1403 | seconds, i.e., the number of seconds east of Greenwich. SUBSEC is | 1412 | seconds, i.e., the number of seconds east of Greenwich. (Note that |
| 1404 | is either 0 or (TICKS . HZ) where HZ is a positive integer clock | 1413 | Common Lisp has different meanings for DOW and UTCOFF, and its |
| 1405 | resolution and TICKS is a nonnegative integer less than HZ. (Note | 1414 | SEC is always an integer between 0 and 59.) |
| 1406 | that Common Lisp has different meanings for DOW and UTCOFF, and lacks | ||
| 1407 | SUBSEC.) | ||
| 1408 | 1415 | ||
| 1409 | usage: (decode-time &optional TIME ZONE) */) | 1416 | usage: (decode-time &optional TIME ZONE FORM) */) |
| 1410 | (Lisp_Object specified_time, Lisp_Object zone) | 1417 | (Lisp_Object specified_time, Lisp_Object zone, Lisp_Object form) |
| 1411 | { | 1418 | { |
| 1412 | struct lisp_time lt = lisp_time_struct (specified_time, 0); | 1419 | struct lisp_time lt = lisp_time_struct (specified_time, 0); |
| 1413 | struct timespec ts = lisp_to_timespec (lt); | 1420 | struct timespec ts = lisp_to_timespec (lt); |
| @@ -1439,8 +1446,35 @@ usage: (decode-time &optional TIME ZONE) */) | |||
| 1439 | year = make_integer_mpz (); | 1446 | year = make_integer_mpz (); |
| 1440 | } | 1447 | } |
| 1441 | 1448 | ||
| 1449 | Lisp_Object hz = lt.hz, sec; | ||
| 1450 | if (EQ (hz, make_fixnum (1)) || !EQ (form, Qt)) | ||
| 1451 | sec = make_fixnum (local_tm.tm_sec); | ||
| 1452 | else | ||
| 1453 | { | ||
| 1454 | Lisp_Object ticks; /* hz * tm_sec + mod (lt.ticks, hz) */ | ||
| 1455 | intmax_t n; | ||
| 1456 | if (FASTER_TIMEFNS && FIXNUMP (lt.ticks) && FIXNUMP (hz) | ||
| 1457 | && !INT_MULTIPLY_WRAPV (XFIXNUM (hz), local_tm.tm_sec, &n) | ||
| 1458 | && ! (INT_ADD_WRAPV | ||
| 1459 | (n, (XFIXNUM (lt.ticks) % XFIXNUM (hz) | ||
| 1460 | + (XFIXNUM (lt.ticks) % XFIXNUM (hz) < 0 | ||
| 1461 | ? XFIXNUM (hz) : 0)), | ||
| 1462 | &n))) | ||
| 1463 | ticks = make_int (n); | ||
| 1464 | else | ||
| 1465 | { | ||
| 1466 | mpz_fdiv_r (mpz[0], | ||
| 1467 | *bignum_integer (&mpz[0], lt.ticks), | ||
| 1468 | *bignum_integer (&mpz[1], hz)); | ||
| 1469 | mpz_addmul_ui (mpz[0], *bignum_integer (&mpz[1], hz), | ||
| 1470 | local_tm.tm_sec); | ||
| 1471 | ticks = make_integer_mpz (); | ||
| 1472 | } | ||
| 1473 | sec = Fcons (ticks, hz); | ||
| 1474 | } | ||
| 1475 | |||
| 1442 | return CALLN (Flist, | 1476 | return CALLN (Flist, |
| 1443 | make_fixnum (local_tm.tm_sec), | 1477 | sec, |
| 1444 | make_fixnum (local_tm.tm_min), | 1478 | make_fixnum (local_tm.tm_min), |
| 1445 | make_fixnum (local_tm.tm_hour), | 1479 | make_fixnum (local_tm.tm_hour), |
| 1446 | make_fixnum (local_tm.tm_mday), | 1480 | make_fixnum (local_tm.tm_mday), |
| @@ -1453,10 +1487,7 @@ usage: (decode-time &optional TIME ZONE) */) | |||
| 1453 | ? make_fixnum (tm_gmtoff (&local_tm)) | 1487 | ? make_fixnum (tm_gmtoff (&local_tm)) |
| 1454 | : gmtime_r (&time_spec, &gmt_tm) | 1488 | : gmtime_r (&time_spec, &gmt_tm) |
| 1455 | ? make_fixnum (tm_diff (&local_tm, &gmt_tm)) | 1489 | ? make_fixnum (tm_diff (&local_tm, &gmt_tm)) |
| 1456 | : Qnil), | 1490 | : Qnil)); |
| 1457 | (EQ (lt.hz, make_fixnum (1)) | ||
| 1458 | ? make_fixnum (0) | ||
| 1459 | : Fcons (integer_mod (lt.ticks, lt.hz), lt.hz))); | ||
| 1460 | } | 1491 | } |
| 1461 | 1492 | ||
| 1462 | /* Return OBJ - OFFSET, checking that OBJ is a valid integer and that | 1493 | /* Return OBJ - OFFSET, checking that OBJ is a valid integer and that |
| @@ -1487,7 +1518,7 @@ check_tm_member (Lisp_Object obj, int offset) | |||
| 1487 | DEFUN ("encode-time", Fencode_time, Sencode_time, 1, MANY, 0, | 1518 | DEFUN ("encode-time", Fencode_time, Sencode_time, 1, MANY, 0, |
| 1488 | doc: /* Convert TIME to a timestamp. | 1519 | doc: /* Convert TIME to a timestamp. |
| 1489 | 1520 | ||
| 1490 | TIME is a list (SECOND MINUTE HOUR DAY MONTH YEAR IGNORED DST ZONE SUBSEC). | 1521 | TIME is a list (SECOND MINUTE HOUR DAY MONTH YEAR IGNORED DST ZONE). |
| 1491 | in the style of `decode-time', so that (encode-time (decode-time ...)) works. | 1522 | in the style of `decode-time', so that (encode-time (decode-time ...)) works. |
| 1492 | In this list, ZONE can be nil for Emacs local time, t for Universal | 1523 | In this list, ZONE can be nil for Emacs local time, t for Universal |
| 1493 | Time, `wall' for system wall clock time, or a string as in the TZ | 1524 | Time, `wall' for system wall clock time, or a string as in the TZ |
| @@ -1496,23 +1527,16 @@ environment variable. It can also be a list (as from | |||
| 1496 | without consideration for daylight saving time. If ZONE specifies a | 1527 | without consideration for daylight saving time. If ZONE specifies a |
| 1497 | time zone with daylight-saving transitions, DST is t for daylight | 1528 | time zone with daylight-saving transitions, DST is t for daylight |
| 1498 | saving time, nil for standard time, and -1 to cause the daylight | 1529 | saving time, nil for standard time, and -1 to cause the daylight |
| 1499 | saving flag to be guessed. SUBSEC is either 0 or a Lisp timestamp | 1530 | saving flag to be guessed. |
| 1500 | in (TICKS . HZ) form. | ||
| 1501 | 1531 | ||
| 1502 | As an obsolescent calling convention, if this function is called with | 1532 | As an obsolescent calling convention, if this function is called with |
| 1503 | 6 through 10 arguments, the first 6 arguments are SECOND, MINUTE, | 1533 | 6 or more arguments, the first 6 arguments are SECOND, MINUTE, HOUR, |
| 1504 | HOUR, DAY, MONTH, and YEAR, and specify the components of a decoded | 1534 | DAY, MONTH, and YEAR, and specify the components of a decoded time, |
| 1505 | time. If there are 7 through 9 arguments the *last* argument | 1535 | where DST assumed to be -1 and FORM is omitted. If there are more |
| 1506 | specifies ZONE, and if there are 10 arguments the 9th specifies ZONE | 1536 | than 6 arguments the *last* argument is used as ZONE and any other |
| 1507 | and the 10th specifies SUBSEC; in either case any other extra | 1537 | extra arguments are ignored, so that (apply #\\='encode-time |
| 1508 | arguments are ignored, so that (apply #\\='encode-time (decode-time | 1538 | (decode-time ...)) works. In this obsolescent convention, DST and |
| 1509 | ...)) works. In this obsolescent convention, DST, ZONE, and SUBSEC | 1539 | ZONE default to -1 and nil respectively. |
| 1510 | default to -1, nil and 0 respectively. | ||
| 1511 | |||
| 1512 | Out-of-range values for SECOND, MINUTE, HOUR, DAY, or MONTH are allowed; | ||
| 1513 | for example, a DAY of 0 means the day preceding the given month. | ||
| 1514 | Year numbers less than 100 are treated just like other year numbers. | ||
| 1515 | If you want them to stand for years in this century, you must do that yourself. | ||
| 1516 | 1540 | ||
| 1517 | Years before 1970 are not guaranteed to work. On some systems, | 1541 | Years before 1970 are not guaranteed to work. On some systems, |
| 1518 | year values as low as 1901 do work. | 1542 | year values as low as 1901 do work. |
| @@ -1521,27 +1545,27 @@ usage: (encode-time TIME &rest OBSOLESCENT-ARGUMENTS) */) | |||
| 1521 | (ptrdiff_t nargs, Lisp_Object *args) | 1545 | (ptrdiff_t nargs, Lisp_Object *args) |
| 1522 | { | 1546 | { |
| 1523 | struct tm tm; | 1547 | struct tm tm; |
| 1524 | Lisp_Object zone = Qnil, subsec = make_fixnum (0); | 1548 | Lisp_Object zone = Qnil; |
| 1525 | Lisp_Object a = args[0]; | 1549 | Lisp_Object a = args[0]; |
| 1550 | Lisp_Object secarg, minarg, hourarg, mdayarg, monarg, yeararg; | ||
| 1526 | tm.tm_isdst = -1; | 1551 | tm.tm_isdst = -1; |
| 1527 | 1552 | ||
| 1528 | if (nargs == 1) | 1553 | if (nargs == 1) |
| 1529 | { | 1554 | { |
| 1530 | Lisp_Object tail = a; | 1555 | Lisp_Object tail = a; |
| 1531 | for (int i = 0; i < 10; i++, tail = XCDR (tail)) | 1556 | for (int i = 0; i < 9; i++, tail = XCDR (tail)) |
| 1532 | CHECK_CONS (tail); | 1557 | CHECK_CONS (tail); |
| 1533 | tm.tm_sec = check_tm_member (XCAR (a), 0); a = XCDR (a); | 1558 | secarg = XCAR (a); a = XCDR (a); |
| 1534 | tm.tm_min = check_tm_member (XCAR (a), 0); a = XCDR (a); | 1559 | minarg = XCAR (a); a = XCDR (a); |
| 1535 | tm.tm_hour = check_tm_member (XCAR (a), 0); a = XCDR (a); | 1560 | hourarg = XCAR (a); a = XCDR (a); |
| 1536 | tm.tm_mday = check_tm_member (XCAR (a), 0); a = XCDR (a); | 1561 | mdayarg = XCAR (a); a = XCDR (a); |
| 1537 | tm.tm_mon = check_tm_member (XCAR (a), 1); a = XCDR (a); | 1562 | monarg = XCAR (a); a = XCDR (a); |
| 1538 | tm.tm_year = check_tm_member (XCAR (a), TM_YEAR_BASE); a = XCDR (a); | 1563 | yeararg = XCAR (a); a = XCDR (a); |
| 1539 | a = XCDR (a); | 1564 | a = XCDR (a); |
| 1540 | Lisp_Object dstflag = XCAR (a); a = XCDR (a); | 1565 | Lisp_Object dstflag = XCAR (a); a = XCDR (a); |
| 1541 | zone = XCAR (a); a = XCDR (a); | 1566 | zone = XCAR (a); |
| 1542 | if (SYMBOLP (dstflag) && !FIXNUMP (zone) && !CONSP (zone)) | 1567 | if (SYMBOLP (dstflag) && !FIXNUMP (zone) && !CONSP (zone)) |
| 1543 | tm.tm_isdst = !NILP (dstflag); | 1568 | tm.tm_isdst = !NILP (dstflag); |
| 1544 | subsec = XCAR (a); | ||
| 1545 | } | 1569 | } |
| 1546 | else if (nargs < 6) | 1570 | else if (nargs < 6) |
| 1547 | xsignal2 (Qwrong_number_of_arguments, Qencode_time, make_fixnum (nargs)); | 1571 | xsignal2 (Qwrong_number_of_arguments, Qencode_time, make_fixnum (nargs)); |
| @@ -1549,18 +1573,37 @@ usage: (encode-time TIME &rest OBSOLESCENT-ARGUMENTS) */) | |||
| 1549 | { | 1573 | { |
| 1550 | if (6 < nargs) | 1574 | if (6 < nargs) |
| 1551 | zone = args[nargs - 1]; | 1575 | zone = args[nargs - 1]; |
| 1552 | if (9 < nargs) | 1576 | secarg = a; |
| 1553 | { | 1577 | minarg = args[1]; |
| 1554 | zone = args[8]; | 1578 | hourarg = args[2]; |
| 1555 | subsec = args[9]; | 1579 | mdayarg = args[3]; |
| 1556 | } | 1580 | monarg = args[4]; |
| 1557 | tm.tm_sec = check_tm_member (a, 0); | 1581 | yeararg = args[5]; |
| 1558 | tm.tm_min = check_tm_member (args[1], 0); | 1582 | } |
| 1559 | tm.tm_hour = check_tm_member (args[2], 0); | 1583 | |
| 1560 | tm.tm_mday = check_tm_member (args[3], 0); | 1584 | struct lisp_time lt; |
| 1561 | tm.tm_mon = check_tm_member (args[4], 1); | 1585 | decode_lisp_time (secarg, 0, <, 0); |
| 1562 | tm.tm_year = check_tm_member (args[5], TM_YEAR_BASE); | 1586 | Lisp_Object hz = lt.hz, sec, subsecticks; |
| 1587 | if (FASTER_TIMEFNS && EQ (hz, make_fixnum (1))) | ||
| 1588 | { | ||
| 1589 | sec = lt.ticks; | ||
| 1590 | subsecticks = make_fixnum (0); | ||
| 1591 | } | ||
| 1592 | else | ||
| 1593 | { | ||
| 1594 | mpz_fdiv_qr (mpz[0], mpz[1], | ||
| 1595 | *bignum_integer (&mpz[0], lt.ticks), | ||
| 1596 | *bignum_integer (&mpz[1], hz)); | ||
| 1597 | sec = make_integer_mpz (); | ||
| 1598 | mpz_swap (mpz[0], mpz[1]); | ||
| 1599 | subsecticks = make_integer_mpz (); | ||
| 1563 | } | 1600 | } |
| 1601 | tm.tm_sec = check_tm_member (sec, 0); | ||
| 1602 | tm.tm_min = check_tm_member (minarg, 0); | ||
| 1603 | tm.tm_hour = check_tm_member (hourarg, 0); | ||
| 1604 | tm.tm_mday = check_tm_member (mdayarg, 0); | ||
| 1605 | tm.tm_mon = check_tm_member (monarg, 1); | ||
| 1606 | tm.tm_year = check_tm_member (yeararg, TM_YEAR_BASE); | ||
| 1564 | 1607 | ||
| 1565 | timezone_t tz = tzlookup (zone, false); | 1608 | timezone_t tz = tzlookup (zone, false); |
| 1566 | tm.tm_wday = -1; | 1609 | tm.tm_wday = -1; |
| @@ -1571,25 +1614,17 @@ usage: (encode-time TIME &rest OBSOLESCENT-ARGUMENTS) */) | |||
| 1571 | if (tm.tm_wday < 0) | 1614 | if (tm.tm_wday < 0) |
| 1572 | time_error (mktime_errno); | 1615 | time_error (mktime_errno); |
| 1573 | 1616 | ||
| 1574 | if (CONSP (subsec)) | 1617 | if (EQ (hz, make_fixnum (1))) |
| 1618 | return (CURRENT_TIME_LIST | ||
| 1619 | ? list2 (hi_time (value), lo_time (value)) | ||
| 1620 | : INT_TO_INTEGER (value)); | ||
| 1621 | else | ||
| 1575 | { | 1622 | { |
| 1576 | Lisp_Object subsecticks = XCAR (subsec); | 1623 | struct lisp_time val1 = { INT_TO_INTEGER (value), make_fixnum (1) }; |
| 1577 | if (INTEGERP (subsecticks)) | 1624 | Lisp_Object secticks = lisp_time_hz_ticks (val1, hz); |
| 1578 | { | 1625 | Lisp_Object ticks = lispint_arith (secticks, subsecticks, false); |
| 1579 | struct lisp_time val1 = { INT_TO_INTEGER (value), make_fixnum (1) }; | 1626 | return Fcons (ticks, hz); |
| 1580 | Lisp_Object | ||
| 1581 | hz = XCDR (subsec), | ||
| 1582 | secticks = lisp_time_hz_ticks (val1, hz), | ||
| 1583 | ticks = lispint_arith (secticks, subsecticks, false); | ||
| 1584 | return Fcons (ticks, hz); | ||
| 1585 | } | ||
| 1586 | } | 1627 | } |
| 1587 | else if (INTEGERP (subsec)) | ||
| 1588 | return (CURRENT_TIME_LIST && EQ (subsec, make_fixnum (0)) | ||
| 1589 | ? list2 (hi_time (value), lo_time (value)) | ||
| 1590 | : lispint_arith (INT_TO_INTEGER (value), subsec, false)); | ||
| 1591 | |||
| 1592 | xsignal2 (Qerror, build_string ("Invalid subsec"), subsec); | ||
| 1593 | } | 1628 | } |
| 1594 | 1629 | ||
| 1595 | DEFUN ("time-convert", Ftime_convert, Stime_convert, 1, 2, 0, | 1630 | DEFUN ("time-convert", Ftime_convert, Stime_convert, 1, 2, 0, |