From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Paul Eggert Newsgroups: gmane.emacs.bugs Subject: bug#32902: Add support for (TIMESTAMP . RESOLUTION) Lisp timestamps Date: Wed, 3 Oct 2018 11:45:12 -0700 Organization: UCLA Computer Science Department Message-ID: <13abcc70-0e5b-0d5f-fffc-9b146743a565@cs.ucla.edu> References: <83y3bh2gns.fsf@gnu.org> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------CB6262307A5A40D8B733BD47" X-Trace: blaine.gmane.org 1538592445 2276 195.159.176.226 (3 Oct 2018 18:47:25 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Wed, 3 Oct 2018 18:47:25 +0000 (UTC) User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.0 Cc: 32902@debbugs.gnu.org To: Eli Zaretskii Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Wed Oct 03 20:47:20 2018 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1g7mB5-0000UD-KM for geb-bug-gnu-emacs@m.gmane.org; Wed, 03 Oct 2018 20:47:19 +0200 Original-Received: from localhost ([::1]:52365 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g7mDC-0001Wq-Bp for geb-bug-gnu-emacs@m.gmane.org; Wed, 03 Oct 2018 14:49:30 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:41819) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g7m9t-0005Uq-3R for bug-gnu-emacs@gnu.org; Wed, 03 Oct 2018 14:46:07 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1g7m9q-0001nM-9I for bug-gnu-emacs@gnu.org; Wed, 03 Oct 2018 14:46:04 -0400 Original-Received: from debbugs.gnu.org ([208.118.235.43]:59988) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1g7m9q-0001n3-0y for bug-gnu-emacs@gnu.org; Wed, 03 Oct 2018 14:46:02 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1g7m9p-0001Mj-UC for bug-gnu-emacs@gnu.org; Wed, 03 Oct 2018 14:46:01 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Paul Eggert Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Wed, 03 Oct 2018 18:46:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 32902 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch Original-Received: via spool by 32902-submit@debbugs.gnu.org id=B32902.15385923275205 (code B ref 32902); Wed, 03 Oct 2018 18:46:01 +0000 Original-Received: (at 32902) by debbugs.gnu.org; 3 Oct 2018 18:45:27 +0000 Original-Received: from localhost ([127.0.0.1]:36013 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1g7m9G-0001Ls-Tt for submit@debbugs.gnu.org; Wed, 03 Oct 2018 14:45:27 -0400 Original-Received: from zimbra.cs.ucla.edu ([131.179.128.68]:38132) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1g7m9D-0001Ld-Jk for 32902@debbugs.gnu.org; Wed, 03 Oct 2018 14:45:25 -0400 Original-Received: from localhost (localhost [127.0.0.1]) by zimbra.cs.ucla.edu (Postfix) with ESMTP id A4165161624; Wed, 3 Oct 2018 11:45:17 -0700 (PDT) Original-Received: from zimbra.cs.ucla.edu ([127.0.0.1]) by localhost (zimbra.cs.ucla.edu [127.0.0.1]) (amavisd-new, port 10032) with ESMTP id I9Fb8p4PPArj; Wed, 3 Oct 2018 11:45:13 -0700 (PDT) Original-Received: from localhost (localhost [127.0.0.1]) by zimbra.cs.ucla.edu (Postfix) with ESMTP id 317C81616BB; Wed, 3 Oct 2018 11:45:13 -0700 (PDT) X-Virus-Scanned: amavisd-new at zimbra.cs.ucla.edu Original-Received: from zimbra.cs.ucla.edu ([127.0.0.1]) by localhost (zimbra.cs.ucla.edu [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id ZOM2DylQA7IT; Wed, 3 Oct 2018 11:45:13 -0700 (PDT) Original-Received: from Penguin.CS.UCLA.EDU (Penguin.CS.UCLA.EDU [131.179.64.200]) by zimbra.cs.ucla.edu (Postfix) with ESMTPSA id 0E926161624; Wed, 3 Oct 2018 11:45:13 -0700 (PDT) Openpgp: preference=signencrypt Autocrypt: addr=eggert@cs.ucla.edu; prefer-encrypt=mutual; keydata= xsFNBEyAcmQBEADAAyH2xoTu7ppG5D3a8FMZEon74dCvc4+q1XA2J2tBy2pwaTqfhpxxdGA9 Jj50UJ3PD4bSUEgN8tLZ0san47l5XTAFLi2456ciSl5m8sKaHlGdt9XmAAtmXqeZVIYX/UFS 96fDzf4xhEmm/y7LbYEPQdUdxu47xA5KhTYp5bltF3WYDz1Ygd7gx07Auwp7iw7eNvnoDTAl KAl8KYDZzbDNCQGEbpY3efZIvPdeI+FWQN4W+kghy+P6au6PrIIhYraeua7XDdb2LS1en3Ss mE3QjqfRqI/A2ue8JMwsvXe/WK38Ezs6x74iTaqI3AFH6ilAhDqpMnd/msSESNFt76DiO1ZK QMr9amVPknjfPmJISqdhgB1DlEdw34sROf6V8mZw0xfqT6PKE46LcFefzs0kbg4GORf8vjG2 Sf1tk5eU8MBiyN/bZ03bKNjNYMpODDQQwuP84kYLkX2wBxxMAhBxwbDVZudzxDZJ1C2VXujC OJVxq2kljBM9ETYuUGqd75AW2LXrLw6+MuIsHFAYAgRr7+KcwDgBAfwhPBYX34nSSiHlmLC+ KaHLeCLF5ZI2vKm3HEeCTtlOg7xZEONgwzL+fdKo+D6SoC8RRxJKs8a3sVfI4t6CnrQzvJbB n6gxdgCu5i29J1QCYrCYvql2UyFPAK+do99/1jOXT4m2836j1wARAQABzSBQYXVsIEVnZ2Vy dCA8ZWdnZXJ0QGNzLnVjbGEuZWR1PsLBfgQTAQIAKAUCTIByZAIbAwUJEswDAAYLCQgHAwIG FQgCCQoLBBYCAwECH In-Reply-To: <83y3bh2gns.fsf@gnu.org> Content-Language: en-US X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 208.118.235.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.org gmane.emacs.bugs:150917 Archived-At: This is a multi-part message in MIME format. --------------CB6262307A5A40D8B733BD47 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit On 10/1/18 8:04 PM, Eli Zaretskii wrote: > Doc strings only send to > the manuals for additional details and explanations, not for the basic > facts such as these. The attached proposed additional patch fixes this by referring to format-time-string, and by adding the description of time values to format-time-string's doc string. (This is better than the old practice of referring to current-time-string, which does not deal with subsecond info.) It also fixes some minor doc nits I noticed in additional reading. > This makes an impression the function doesn't support more than 2 > arguments, which is incorrect. Can we provide a more accurate 'usage' form? Yes, and I gave that a shot in the attached patch. > I think it would be good to add tests for the functions being > modified, otherwise we might be breaking something without paying > attention. Good point, and done in the attached. > Is it feasible to leave the time-related code in editfns.c? It's feasible, and I could prepare a patch along those lines. However, the time code has has nothing to do with edit functions and is growing significantly: the proposed src/systime.c is 56 KiB, which is above the median size for src/*.c files. Also, this patch changes the time code so much that moving it to a new file won't be that much more of a forensics annoyance than leaving it in editfns.c. To my mind the clarity in having the time code in its own module outweighs the forensics annoyance. --------------CB6262307A5A40D8B733BD47 Content-Type: text/x-patch; name="0001-Improvements-on-TICKS-.-HZ.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="0001-Improvements-on-TICKS-.-HZ.patch" >From ebf996b716f99434abe217dafccb950124303adc Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Wed, 3 Oct 2018 09:10:01 -0700 Subject: [PATCH] Improvements on (TICKS . HZ) This patch is in response to Eli's review (Bug#32902#10). * src/systime.c: Doc strings of affected functions now refer to format-time-string instead of to Lisp manual, and format-time-string's doc string covers time values. * test/src/systime-tests.el (format-time-string-with-zone): Check decode-time too. (decode-then-encode-time, time-arith-tests): New tests. --- doc/lispref/os.texi | 14 ++--- src/systime.c | 79 ++++++++++++++------------ test/src/systime-tests.el | 116 +++++++++++++++++++++++++++++--------- 3 files changed, 139 insertions(+), 70 deletions(-) diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi index ea6915350e..64c327c380 100644 --- a/doc/lispref/os.texi +++ b/doc/lispref/os.texi @@ -1457,14 +1457,14 @@ Time Conversion @var{dow} and @var{utcoff}. @end defun -@defun encode-time time &optional form +@defun encode-time &optional time form &rest obsolescent-arguments This function converts @var{time} to a Lisp timestamp. It can act as the inverse of @code{decode-time}. -The first argument can be a Lisp time value such as @code{nil} for the -current time, a number of seconds, a pair @code{(@var{ticks} -. @var{hz})}, or a list @code{(@var{high} @var{low} @var{micro} -@var{pico})} (@pxref{Time of Day}). It can also be a list +The first argument can be a time value such as a number of seconds, a +pair @code{(@var{ticks} . @var{hz})}, a list @code{(@var{high} +@var{low} @var{micro} @var{pico})}, or @code{nil} (the default) for +the current time (@pxref{Time of Day}). It can also be a list @code{(@var{second} @var{minute} @var{hour} @var{day} @var{month} @var{year} @var{ignored} @var{dst} @var{zone})} that specifies a decoded time in the style of @code{decode-time}, so that @@ -1494,10 +1494,10 @@ Time Conversion specify most of the components of a decoded time. If there are more than six arguments the @emph{last} argument is used as @var{zone} and any other extra arguments are ignored, so that @code{(apply -'encode-time (decode-time ...))} works; otherwise @var{zone} defaults +#\\='encode-time (decode-time ...))} works; otherwise @var{zone} defaults to the current time zone rule (@pxref{Time Zone Rules}). The decoded time's @var{dst} component is treated as if it was @minus{}1, and -@var{form} so it takes its default value. +@var{form} takes its default value. Year numbers less than 100 are not treated specially. If you want them to stand for years above 1900, or years above 2000, you must alter them diff --git a/src/systime.c b/src/systime.c index c01b5a6d33..ae1ac04aad 100644 --- a/src/systime.c +++ b/src/systime.c @@ -1035,8 +1035,8 @@ time_arith (Lisp_Object a, Lisp_Object b, bool subtract) } DEFUN ("time-add", Ftime_add, Stime_add, 2, 2, 0, - doc: /* Return the sum of two time values A and B, as a timestamp. -See Info node `(elisp)Time of Day' for time value formats. + doc: /* Return the sum of two time values A and B, as a time value. +See `format-time-string' for the various forms of a time value. For example, nil stands for the current time. */) (Lisp_Object a, Lisp_Object b) { @@ -1044,9 +1044,9 @@ For example, nil stands for the current time. */) } DEFUN ("time-subtract", Ftime_subtract, Stime_subtract, 2, 2, 0, - doc: /* Return the difference between two time values A and B, as a timestamp. + doc: /* Return the difference between two time values A and B, as a time value. You can use `float-time' to convert the difference into elapsed seconds. -See Info node `(elisp)Time of Day' for time value formats. +See `format-time-string' for the various forms of a time value. For example, nil stands for the current time. */) (Lisp_Object a, Lisp_Object b) { @@ -1092,7 +1092,7 @@ time_cmp (Lisp_Object a, Lisp_Object b) DEFUN ("time-less-p", Ftime_less_p, Stime_less_p, 2, 2, 0, doc: /* Return non-nil if time value A is less than time value B. -See Info node `(elisp)Time of Day' for time value formats. +See `format-time-string' for the various forms of a time value. For example, nil stands for the current time. */) (Lisp_Object a, Lisp_Object b) { @@ -1101,7 +1101,7 @@ For example, nil stands for the current time. */) DEFUN ("time-equal-p", Ftime_equal_p, Stime_equal_p, 2, 2, 0, doc: /* Return non-nil if A and B are equal time values. -See Info node `(elisp)Time of Day' for time value formats. */) +See `format-time-string' for the various forms of a time value. */) (Lisp_Object a, Lisp_Object b) { return time_cmp (a, b) == 0 ? Qt : Qnil; @@ -1110,12 +1110,12 @@ See Info node `(elisp)Time of Day' for time value formats. */) DEFUN ("float-time", Ffloat_time, Sfloat_time, 0, 1, 0, doc: /* Return the current time, as a float number of seconds since the epoch. -If SPECIFIED-TIME is given, it is a Lisp time value to convert to -float instead of the current time. See Info node `(elisp)Time of Day' -for time value formats. +If SPECIFIED-TIME is given, it is a time value to convert to float +instead of the current time. See `format-time-string' for the various +forms of a time value. WARNING: Since the result is floating point, it may not be exact. -If precise time stamps are required, use either `current-time', +If precise time stamps are required, use either `encode-time', or (if you need time as a string) `format-time-string'. */) (Lisp_Object specified_time) { @@ -1226,8 +1226,12 @@ format_time_string (char const *format, ptrdiff_t formatlen, } DEFUN ("format-time-string", Fformat_time_string, Sformat_time_string, 1, 3, 0, - doc: /* Use FORMAT-STRING to format the time TIME, or now if omitted or nil. -TIME is a Lisp time value; see Info node `(elisp)Time of Day'. + doc: /* Use FORMAT-STRING to format the time value TIME. +A time value that is omitted or nil stands for the current time, +a number stands for that many seconds, an integer pair (TICKS . HZ) +stands for TICKS/HZ seconds, and an integer list (HI LO US PS) stands +for HI*2**16 + LO + US/10**6 + PS/10**12 seconds. This function +treats seconds as time since the epoch of 1970-01-01 00:00:00 UTC. The optional ZONE is omitted or nil for Emacs local time, t for Universal Time, `wall' for system wall clock time, or a string as in @@ -1300,8 +1304,8 @@ usage: (format-time-string FORMAT-STRING &optional TIME ZONE) */) DEFUN ("decode-time", Fdecode_time, Sdecode_time, 0, 2, 0, doc: /* Decode a time value as (SEC MINUTE HOUR DAY MONTH YEAR DOW DST UTCOFF). -The optional TIME is the Lisp time value to convert. See Info node -`(elisp)Time of Day' for time value formats. +The optional TIME is the time value to convert. See +`format-time-string' for the various forms of a time value. The optional ZONE is omitted or nil for Emacs local time, t for Universal Time, `wall' for system wall clock time, or a string as in @@ -1381,22 +1385,23 @@ check_tm_member (Lisp_Object obj, int offset) } DEFUN ("encode-time", Fencode_time, Sencode_time, 1, MANY, 0, - doc: /* Convert TIME to a timestamp. + doc: /* Convert optional TIME to a timestamp. Optional FORM specifies how the returned value should be encoded. This can act as the reverse operation of `decode-time', which see. If TIME is a list (SECOND MINUTE HOUR DAY MONTH YEAR IGNORED DST ZONE) -it a decoded time in the style of `decode-time', so that (encode-time -(decode-time ...)) works. TIME can also be a Lisp time value; see -Info node `(elisp)Time of Day'. +it is a decoded time in the style of `decode-time', so that (encode-time +(decode-time ...)) works. TIME can also be a time value. +See `format-time-string' for the various forms of a time value. +For example, an omitted TIME stands for the current time. If FORM is a positive integer, the time is returned as a pair of integers (TICKS . FORM), where TICKS is the number of clock ticks and FORM is the clock frequency in ticks per second. (Currently the positive integer should be at least 65536 if the returned value is expected to be given to standard functions expecting Lisp timestamps.) If FORM is -t, the time is returned as (TICKS . PHZ), where PHZ is a -platform-dependent clock frequency. If FORM is `integer', the time is +t, the time is returned as (TICKS . PHZ), where PHZ is a platform dependent +clock frequency in ticks per second. If FORM is `integer', the time is returned as an integer count of seconds. If FORM is `list', the time is returned as an integer list (HIGH LOW USEC PSEC), where HIGH has the most significant bits of the seconds, LOW has the least significant 16 @@ -1405,11 +1410,12 @@ Returned values are rounded toward minus infinity. Although an omitted or nil FORM currently acts like `list', this is planned to change, so callers requiring list timestamps should specify `list'. -As an obsolescent calling convention, the first 6 arguments SECOND, -MINUTE, HOUR, DAY, MONTH, and YEAR specify the components of a decoded -time, where DST assumed to be -1 and FORM is omitted. If there are more +As an obsolescent calling convention, if this function is called with +6 or more arguments, the first 6 arguments are SECOND, MINUTE, HOUR, +DAY, MONTH, and YEAR, and specify the components of a decoded time, +where DST assumed to be -1 and FORM is omitted. If there are more than 6 arguments the *last* argument is used as ZONE and any other -extra arguments are ignored, so that (apply \\='encode-time +extra arguments are ignored, so that (apply #\\='encode-time (decode-time ...)) works; otherwise ZONE is assumed to be nil. If the input is a decoded time, ZONE is nil for Emacs local time, t @@ -1430,7 +1436,7 @@ If you want them to stand for years in this century, you must do that yourself. Years before 1970 are not guaranteed to work. On some systems, year values as low as 1901 do work. -usage: (encode-time TIME &optional FORM) */) +usage: (encode-time &optional TIME FORM &rest OBSOLESCENT-ARGUMENTS) */) (ptrdiff_t nargs, Lisp_Object *args) { time_t value; @@ -1490,13 +1496,13 @@ usage: (encode-time TIME &optional FORM) */) } DEFUN ("current-time", Fcurrent_time, Scurrent_time, 0, 0, 0, - doc: /* Return the current time, counting the number of seconds since the epoch. - -See Info node `(elisp)Time of Day' for the format of the returned -timestamp. Although this is currently list format, it may change in -future versions of Emacs. Use `encode-time' if you need a particular -form; for example, (encode-time nil \\='list) returns the current time -in list form. */) + doc: /* Return the current time, as the number of seconds since 1970-01-01 00:00:00. +The time is returned as a list of integers (HIGH LOW USEC PSEC). +HIGH has the most significant bits of the seconds, while LOW has the +least significant 16 bits. USEC and PSEC are the microsecond and +picosecond counts. Use `encode-time' if you need a particular +timestamp form; for example, (encode-time nil \\='integer) returns the +current time in seconds. */) (void) { return make_lisp_time (current_timespec ()); @@ -1512,9 +1518,9 @@ The format is `Sun Sep 16 01:03:52 1973'. However, see also the functions `decode-time' and `format-time-string' which provide a much more powerful and general facility. -If SPECIFIED-TIME is given, it is the Lisp time value to format -instead of the current time. See Info node `(elisp)Time of Day' for -time value formats. +If SPECIFIED-TIME is given, it is the time value to format instead of +the current time. See `format-time-string' for the various forms of a +time value. The optional ZONE is omitted or nil for Emacs local time, t for Universal Time, `wall' for system wall clock time, or a string as in @@ -1559,7 +1565,8 @@ OFFSET is an integer number of seconds ahead of UTC (east of Greenwich). NAME is a string giving the name of the time zone. If SPECIFIED-TIME is given, the time zone offset is determined from it instead of using the current time. The argument should be a Lisp -time value; see Info node `(elisp)Time of Day'. +time value; see `format-time-string' for the various forms of a time +value. The optional ZONE is omitted or nil for Emacs local time, t for Universal Time, `wall' for system wall clock time, or a string as in diff --git a/test/src/systime-tests.el b/test/src/systime-tests.el index 485d379cfe..3036c44992 100644 --- a/test/src/systime-tests.el +++ b/test/src/systime-tests.el @@ -19,7 +19,7 @@ (require 'ert) -;;; Check format-time-string with various TZ settings. +;;; Check format-time-string and decode-time with various TZ settings. ;;; Use only POSIX-compatible TZ values, since the tests should work ;;; even if tzdb is not in use. (ert-deftest format-time-string-with-zone () @@ -35,32 +35,61 @@ ;; Similarly, stick to the limited set of time zones that are ;; supported by both POSIX and MS-Windows: exactly 3 ASCII letters ;; in the abbreviation, and no DST. - (let ((look '(1202 22527 999999 999999)) - (format "%Y-%m-%d %H:%M:%S.%3N %z (%Z)")) - ;; UTC. - (should (string-equal - (format-time-string "%Y-%m-%d %H:%M:%S.%3N %z" look t) - "1972-06-30 23:59:59.999 +0000")) - ;; "UTC0". - (should (string-equal - (format-time-string format look "UTC0") - "1972-06-30 23:59:59.999 +0000 (UTC)")) - ;; Negative UTC offset, as a Lisp list. - (should (string-equal - (format-time-string format look '(-28800 "PST")) - "1972-06-30 15:59:59.999 -0800 (PST)")) - ;; Negative UTC offset, as a Lisp integer. - (should (string-equal - (format-time-string format look -28800) - ;; MS-Windows build replaces unrecognizable TZ values, - ;; such as "-08", with "ZZZ". - (if (eq system-type 'windows-nt) - "1972-06-30 15:59:59.999 -0800 (ZZZ)" - "1972-06-30 15:59:59.999 -0800 (-08)"))) - ;; Positive UTC offset that is not an hour multiple, as a string. - (should (string-equal - (format-time-string format look "IST-5:30") - "1972-07-01 05:29:59.999 +0530 (IST)")))) + (let ((format "%Y-%m-%d %H:%M:%S.%3N %z (%Z)")) + (dolist (look '((1202 22527 999999 999999) + (7879679999900 . 100000) + (78796799999999999999 . 1000000000000))) + ;; UTC. + (should (string-equal + (format-time-string "%Y-%m-%d %H:%M:%S.%3N %z" look t) + "1972-06-30 23:59:59.999 +0000")) + (should (equal (decode-time look t) + '(59 59 23 30 6 1972 5 nil 0))) + ;; "UTC0". + (should (string-equal + (format-time-string format look "UTC0") + "1972-06-30 23:59:59.999 +0000 (UTC)")) + (should (equal (decode-time look "UTC0") + '(59 59 23 30 6 1972 5 nil 0))) + ;; Negative UTC offset, as a Lisp list. + (should (string-equal + (format-time-string format look '(-28800 "PST")) + "1972-06-30 15:59:59.999 -0800 (PST)")) + (should (equal (decode-time look '(-28800 "PST")) + '(59 59 15 30 6 1972 5 nil -28800))) + ;; Negative UTC offset, as a Lisp integer. + (should (string-equal + (format-time-string format look -28800) + ;; MS-Windows build replaces unrecognizable TZ values, + ;; such as "-08", with "ZZZ". + (if (eq system-type 'windows-nt) + "1972-06-30 15:59:59.999 -0800 (ZZZ)" + "1972-06-30 15:59:59.999 -0800 (-08)"))) + (should (equal (decode-time look -28800) + '(59 59 15 30 6 1972 5 nil -28800))) + ;; Positive UTC offset that is not an hour multiple, as a string. + (should (string-equal + (format-time-string format look "IST-5:30") + "1972-07-01 05:29:59.999 +0530 (IST)")) + (should (equal (decode-time look "IST-5:30") + '(59 29 5 1 7 1972 6 nil 19800)))))) + +(ert-deftest decode-then-encode-time () + (let ((time-values (list 0 -2 1 0.0 -0.0 -2.0 1.0 + most-negative-fixnum most-positive-fixnum + (1- most-negative-fixnum) + (1+ most-positive-fixnum) + 1e+INF -1e+INF 1e+NaN -1e+NaN + '(0 1 0 0) '(1 0 0 0) '(-1 0 0 0) + '(123456789000000 . 1000000) + (cons (1+ most-positive-fixnum) 1000000000000) + (cons 1000000000000 (1+ most-positive-fixnum))))) + (dolist (a time-values) + (let* ((d (ignore-errors (decode-time a t))) + (e (encode-time d)) + (diff (float-time (time-subtract a e)))) + (should (or (not d) + (and (<= 0 diff) (< diff 1)))))))) ;;; This should not dump core. (ert-deftest format-time-string-with-outlandish-zone () @@ -80,3 +109,36 @@ systime-tests--have-leap-seconds (ert-deftest time-equal-p-nil-nil () (should (time-equal-p nil nil))) + +(ert-deftest time-arith-tests () + (let ((time-values (list 0 -1 1 0.0 -0.0 -1.0 1.0 + most-negative-fixnum most-positive-fixnum + (1- most-negative-fixnum) + (1+ most-positive-fixnum) + 1e+INF -1e+INF 1e+NaN -1e+NaN + '(0 0 0 1) '(0 0 1 0) '(0 1 0 0) '(1 0 0 0) + '(-1 0 0 0) '(1 2 3 4) '(-1 2 3 4) + '(-123456789 . 100000) '(123456789 . 1000000) + (cons (1+ most-positive-fixnum) 1000000000000) + (cons 1000000000000 (1+ most-positive-fixnum))))) + (dolist (a time-values) + (dolist (b time-values) + (let ((aa (time-subtract (time-add a b) b))) + (should (or (time-equal-p a aa) (and (floatp aa) (isnan aa))))) + (should (= 1 (+ (if (time-less-p a b) 1 0) + (if (time-equal-p a b) 1 0) + (if (time-less-p b a) 1 0) + (if (or (and (floatp a) (isnan a)) + (and (floatp b) (isnan b))) + 1 0)))) + (should (or (not (time-less-p 0 b)) + (time-less-p a (time-add a b)) + (time-equal-p a (time-add a b)) + (and (floatp (time-add a b)) (isnan (time-add a b))))) + (let ((x (float-time (time-add a b))) + (y (+ (float-time a) (float-time b)))) + (should (or (and (isnan x) (isnan y)) + (= x y) + (< 0.99 (/ x y) 1.01) + (< 0.99 (/ (- (float-time a)) (float-time b)) + 1.01)))))))) -- 2.17.1 --------------CB6262307A5A40D8B733BD47--