aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/timefns.c187
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
1377DEFUN ("decode-time", Fdecode_time, Sdecode_time, 0, 2, 0, 1380DEFUN ("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).
1379The optional TIME is the time value to convert. See 1382The 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
1386without consideration for daylight saving time. 1389without consideration for daylight saving time.
1387 1390
1391The optional FORM specifies the form of the SEC member. If `integer',
1392SEC is an integer; if t, SEC uses the same resolution as TIME. An
1393omitted or nil FORM is currently treated like `integer', but this may
1394change in future Emacs versions.
1395
1388To access (or alter) the elements in the time value, the 1396To 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. 1400accessors can be used.
1393 1401
1394The list has the following ten members: SEC is an integer between 0 1402The list has the following nine members: SEC is an integer or
1395and 60; SEC is 60 for a leap second, which only some operating systems 1403Lisp timestamp representing a nonnegative value less than 60
1396support. MINUTE is an integer between 0 and 59. HOUR is an integer 1404\(or less than 61 if the operating system supports leap seconds).
1405MINUTE is an integer between 0 and 59. HOUR is an integer
1397between 0 and 23. DAY is an integer between 1 and 31. MONTH is an 1406between 0 and 23. DAY is an integer between 1 and 31. MONTH is an
1398integer between 1 and 12. YEAR is an integer indicating the 1407integer between 1 and 12. YEAR is an integer indicating the
1399four-digit year. DOW is the day of week, an integer between 0 and 6, 1408four-digit year. DOW is the day of week, an integer between 0 and 6,
1400where 0 is Sunday. DST is t if daylight saving time is in effect, 1409where 0 is Sunday. DST is t if daylight saving time is in effect,
1401nil if it is not in effect, and -1 if daylight saving information is 1410nil if it is not in effect, and -1 if daylight saving information is
1402not available. UTCOFF is an integer indicating the UTC offset in 1411not available. UTCOFF is an integer indicating the UTC offset in
1403seconds, i.e., the number of seconds east of Greenwich. SUBSEC is 1412seconds, i.e., the number of seconds east of Greenwich. (Note that
1404is either 0 or (TICKS . HZ) where HZ is a positive integer clock 1413Common Lisp has different meanings for DOW and UTCOFF, and its
1405resolution and TICKS is a nonnegative integer less than HZ. (Note 1414SEC is always an integer between 0 and 59.)
1406that Common Lisp has different meanings for DOW and UTCOFF, and lacks
1407SUBSEC.)
1408 1415
1409usage: (decode-time &optional TIME ZONE) */) 1416usage: (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)
1487DEFUN ("encode-time", Fencode_time, Sencode_time, 1, MANY, 0, 1518DEFUN ("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
1490TIME is a list (SECOND MINUTE HOUR DAY MONTH YEAR IGNORED DST ZONE SUBSEC). 1521TIME is a list (SECOND MINUTE HOUR DAY MONTH YEAR IGNORED DST ZONE).
1491in the style of `decode-time', so that (encode-time (decode-time ...)) works. 1522in the style of `decode-time', so that (encode-time (decode-time ...)) works.
1492In this list, ZONE can be nil for Emacs local time, t for Universal 1523In this list, ZONE can be nil for Emacs local time, t for Universal
1493Time, `wall' for system wall clock time, or a string as in the TZ 1524Time, `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
1496without consideration for daylight saving time. If ZONE specifies a 1527without consideration for daylight saving time. If ZONE specifies a
1497time zone with daylight-saving transitions, DST is t for daylight 1528time zone with daylight-saving transitions, DST is t for daylight
1498saving time, nil for standard time, and -1 to cause the daylight 1529saving time, nil for standard time, and -1 to cause the daylight
1499saving flag to be guessed. SUBSEC is either 0 or a Lisp timestamp 1530saving flag to be guessed.
1500in (TICKS . HZ) form.
1501 1531
1502As an obsolescent calling convention, if this function is called with 1532As an obsolescent calling convention, if this function is called with
15036 through 10 arguments, the first 6 arguments are SECOND, MINUTE, 15336 or more arguments, the first 6 arguments are SECOND, MINUTE, HOUR,
1504HOUR, DAY, MONTH, and YEAR, and specify the components of a decoded 1534DAY, MONTH, and YEAR, and specify the components of a decoded time,
1505time. If there are 7 through 9 arguments the *last* argument 1535where DST assumed to be -1 and FORM is omitted. If there are more
1506specifies ZONE, and if there are 10 arguments the 9th specifies ZONE 1536than 6 arguments the *last* argument is used as ZONE and any other
1507and the 10th specifies SUBSEC; in either case any other extra 1537extra arguments are ignored, so that (apply #\\='encode-time
1508arguments 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 1539ZONE default to -1 and nil respectively.
1510default to -1, nil and 0 respectively.
1511
1512Out-of-range values for SECOND, MINUTE, HOUR, DAY, or MONTH are allowed;
1513for example, a DAY of 0 means the day preceding the given month.
1514Year numbers less than 100 are treated just like other year numbers.
1515If you want them to stand for years in this century, you must do that yourself.
1516 1540
1517Years before 1970 are not guaranteed to work. On some systems, 1541Years before 1970 are not guaranteed to work. On some systems,
1518year values as low as 1901 do work. 1542year 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, &lt, 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
1595DEFUN ("time-convert", Ftime_convert, Stime_convert, 1, 2, 0, 1630DEFUN ("time-convert", Ftime_convert, Stime_convert, 1, 2, 0,