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