all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Paul Eggert <eggert@cs.ucla.edu>
To: Stefan Monnier <monnier@iro.umontreal.ca>
Cc: Eli Zaretskii <eliz@gnu.org>,
	andrewjmoreton@gmail.com, larsi@gnus.org, emacs-devel@gnu.org
Subject: Re: encode-time vs decode-time
Date: Fri, 16 Aug 2019 23:47:12 -0700	[thread overview]
Message-ID: <35b2a118-c1d8-7a2b-02f9-6dc446536739@cs.ucla.edu> (raw)
In-Reply-To: <jwvlfw5g0lk.fsf-monnier+emacs@gnu.org>

[-- Attachment #1: Type: text/plain, Size: 2425 bytes --]

>> there's little doubt that some user code somewhere will break because it
>> (mistakenly) assumes that decode-time's result format will never be
>> extended. If this is a real concern, we can go about the change in some
>> other way.
> 
> Actually, while I agree that it's possible it will break something
> somewhere, it's rather unlikely.

Although I initially thought the same way (that's why I installed the patch that 
altered decode-time), I may have been a bit hasty. I searched for "decode-time" 
in all public GitHub source code files with an .el extension, and looked just in 
the first page of results (10 hits) and found one hit that would have a problem:

https://github.com/tjim/nevermore/blob/5a3f29174b3a4b2b2e7a700a862f3b16a942687e/nm-dateparse.el

It contains several instances of code like this:

(defun nm-next-month (&optional dtime)
   "One month from now, or specified dtime"
   (pcase (or dtime (decode-time))
     (`(,SECONDS ,MINUTES ,HOUR ,DAY ,MONTH ,YEAR ,DOW ,DST ,ZONE)
      (nm-noon
       (if (eq MONTH 12)
           `(,SECONDS ,MINUTES ,HOUR ,DAY ,1 ,(1+ YEAR) ,DOW ,DST ,ZONE)
         `(,SECONDS ,MINUTES ,HOUR ,DAY ,(1+ MONTH) ,YEAR ,DOW ,DST ,ZONE))))))

which won't work if decode-time returns a 10-element list.

Although not a systematic study, this example suggests that we might want to be 
cautious about changing decode-time to return a 10-element list.

With that in mind, I installed the attached patch, which causes decode-time to 
behave at it does in Emacs 26 unless you pass it a new optional argument. And 
even with the new argument, it still returns a 9-element list so the above code 
will still work.

Eli Zaretskii wrote:

> Another alternative is to make the SECONDS member be a float, then we
> could return the extra precision there.

Floats suffer from rounding confusion, and won't suffice for 
attosecond-precision timestamps - admittedly not something one runs into every 
day, but they are needed for some physics applications. The experience that I've 
had with floating-point timestamps over the years has been negative, for the 
usual reasons. So the patch I installed uses the (TICKS . HZ) form that can 
handle attoseconds - indeed, it can even handle zeptoseconds, which were first 
needed by experimental physicists in 2016, according to Jason Daley 
<https://www.smithsonianmag.com/smart-news/physicists-record-smallest-slice-time-yet-180961085/>.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-More-compatible-subsecond-calendrical-timestamps.patch --]
[-- Type: text/x-patch; name="0001-More-compatible-subsecond-calendrical-timestamps.patch", Size: 60524 bytes --]

From 37257d6acadff17bd1e52cfa460950bcb684c5c3 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Fri, 16 Aug 2019 22:09:04 -0700
Subject: [PATCH] More-compatible subsecond calendrical timestamps
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Instead of appending a subseconds member to the result of
‘decode-time’, this keeps the format unchanged unless you give
a new optional argument to ‘decode-time’.  Also, the augmented
format now puts the subsecond info in the SECONDS element, so
the total number of elements is unchanged; this is more
compatible with code that expects the traditional 9 elements,
such as ‘(pcase decoded-time (`(,SEC ,MIN ,HOUR ,DAY ,MON
,YEAR ,DOW ,DST ,ZONE) ...) ...)’.
* doc/lispref/os.texi, doc/misc/emacs-mime.texi, etc/NEWS:
* lisp/net/soap-client.el (soap-decode-date-time):
* lisp/simple.el (decoded-time):
Document the new behavior.
* lisp/calendar/icalendar.el (icalendar--decode-isodatetime):
* lisp/calendar/iso8601.el (iso8601-parse)
(iso8601-parse-time, iso8601-parse-duration)
(iso8601--decoded-time):
* lisp/calendar/parse-time.el (parse-time-string):
* lisp/calendar/time-date.el (decoded-time-add)
(decoded-time--alter-second):
* lisp/org/org.el (org-parse-time-string):
* lisp/simple.el (decoded-time):
* src/timefns.c (Fdecode_time, Fencode_time):
* test/lisp/calendar/icalendar-tests.el:
(icalendar--decode-isodatetime):
* test/lisp/calendar/iso8601-tests.el (test-iso8601-date-years)
(test-iso8601-date-dates, test-iso8601-date-obsolete)
(test-iso8601-date-weeks, test-iso8601-date-ordinals)
(test-iso8601-time, test-iso8601-combined)
(test-iso8601-duration, test-iso8601-intervals)
(standard-test-dates, standard-test-time-of-day-fractions)
(standard-test-time-of-day-beginning-of-day)
(standard-test-time-of-day-utc)
(standard-test-time-of-day-zone)
(standard-test-date-and-time-of-day, standard-test-interval):
* test/lisp/calendar/parse-time-tests.el (parse-time-tests):
* test/src/timefns-tests.el (format-time-string-with-zone)
(encode-time-dst-numeric-zone):
Revert recent changes that added a SUBSECS member to
calendrical timestamps, since that component is no longer
present (the info, if any, is now in the SECONDS member).
* lisp/calendar/time-date.el (decoded-time-add)
(decoded-time--alter-second):
Support fractional seconds in the new form.  Simplify.
* src/timefns.c (Fdecode_time): Support new arg FORM.
(Fencode_time): Support subsecond resolution.
* test/src/timefns-tests.el (format-time-string-with-zone)
(decode-then-encode-time): Test subsecond calendrical timestamps.
---
 doc/lispref/os.texi                    |  65 +++++----
 doc/misc/emacs-mime.texi               |   2 +-
 etc/NEWS                               |  22 ++-
 lisp/calendar/icalendar.el             |   2 +-
 lisp/calendar/iso8601.el               |  14 +-
 lisp/calendar/parse-time.el            |   8 +-
 lisp/calendar/time-date.el             |  75 ++++------
 lisp/net/soap-client.el                |   4 +-
 lisp/org/org.el                        |   4 +-
 lisp/simple.el                         |   8 +-
 src/timefns.c                          | 178 +++++++++++++----------
 test/lisp/calendar/icalendar-tests.el  |   8 +-
 test/lisp/calendar/iso8601-tests.el    | 190 ++++++++++++-------------
 test/lisp/calendar/parse-time-tests.el |  18 +--
 test/src/timefns-tests.el              |  46 +++---
 15 files changed, 337 insertions(+), 307 deletions(-)

diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi
index 70ae39e6ab..49c07380c5 100644
--- a/doc/lispref/os.texi
+++ b/doc/lispref/os.texi
@@ -1478,23 +1478,23 @@ Time Conversion
 @end example
 @end defun
 
-@defun decode-time &optional time zone
+@defun decode-time &optional time zone form
 This function converts a time value into calendrical information.  If
 you don't specify @var{time}, it decodes the current time, and similarly
 @var{zone} defaults to the current time zone rule.  @xref{Time Zone Rules}.
-The return value is a list of ten elements, as follows:
+The @var{form} argument controls the form of the returned
+@var{seconds} element, as described below.
+The return value is a list of nine elements, as follows:
 
 @example
-(@var{seconds} @var{minutes} @var{hour} @var{day} @var{month} @var{year}
- @var{dow} @var{dst} @var{utcoff} @var{subsec})
+(@var{seconds} @var{minutes} @var{hour} @var{day} @var{month} @var{year} @var{dow} @var{dst} @var{utcoff})
 @end example
 
 Here is what the elements mean:
 
 @table @var
 @item seconds
-The number of seconds past the minute, as an integer between 0 and 59.
-On some operating systems, this is 60 for leap seconds.
+The number of seconds past the minute, with form described below.
 @item minutes
 The number of minutes past the hour, as an integer between 0 and 59.
 @item hour
@@ -1514,22 +1514,33 @@ Time Conversion
 @item utcoff
 An integer indicating the Universal Time offset in seconds, i.e., the number of
 seconds east of Greenwich.
-@item subsec
-The number of subseconds past the second, as either 0 or a Lisp
-timestamp @code{(@var{ticks} . @var{hz})} representing a nonnegative
-fraction less than 1.
 @end table
 
+The @var{seconds} element is a Lisp timestamp that is nonnegative and
+less than 61; it is less than 60 except during positive leap seconds
+(assuming the operating system supports leap seconds).  If the
+optional @var{form} argument is @code{t}, @var{seconds} uses the same
+precision as @var{time}; if @var{form} is @code{integer},
+@var{seconds} is truncated to an integer.  For example, if @var{time}
+is the timestamp @code{(1566009571321 . 1000)}, which represents
+2019-08-17 02:39:31.321 UTC on typical systems that lack leap seconds,
+then @code{(decode-time @var{time} t t)} returns @code{((31321 . 1000)
+39 2 17 8 2019 6 nil 0)}, whereas @code{(decode-time @var{time} t
+'integer)} returns @code{(31 39 2 17 8 2019 6 nil 0)}.  If @var{form}
+is omitted or @code{nil}, it currently defaults to @code{integer} but
+this default may change in future Emacs releases, so callers requiring
+a particular form should specify @var{form}.
+
 @strong{Common Lisp Note:} Common Lisp has different meanings for
-@var{dow} and @var{utcoff}, and lacks @var{subsec}.
+@var{dow} and @var{utcoff}, and its @var{second} is an integer between
+0 and 59 inclusive.
 
 To access (or alter) the elements in the time value, the
 @code{decoded-time-second}, @code{decoded-time-minute},
 @code{decoded-time-hour}, @code{decoded-time-day},
 @code{decoded-time-month}, @code{decoded-time-year},
-@code{decoded-time-weekday}, @code{decoded-time-dst},
-@code{decoded-time-zone} and @code{decoded-time-subsec}
-accessors can be used.
+@code{decoded-time-weekday}, @code{decoded-time-dst} and
+@code{decoded-time-zone} accessors can be used.
 
 For instance, to increase the year in a decoded time, you could say:
 
@@ -1551,7 +1562,7 @@ Time Conversion
 could say:
 
 @lisp
-(let ((time (decode-time))
+(let ((time (decode-time nil nil t))
       (delta (make-decoded-time :month 2)))
    (encode-time (decoded-time-add time delta)))
 @end lisp
@@ -1585,22 +1596,21 @@ Time Conversion
 
 Ordinarily the first argument is a list
 @code{(@var{second} @var{minute} @var{hour} @var{day} @var{month}
-@var{year} @var{ignored} @var{dst} @var{zone} @var{subsec})} that specifies a
+@var{year} @var{ignored} @var{dst} @var{zone})} that specifies a
 decoded time in the style of @code{decode-time}, so that
 @code{(encode-time (decode-time ...))}  works.  For the meanings of
 these list members, see the table under @code{decode-time}.
 
 As an obsolescent calling convention, this function can be given six
-through ten arguments.  The first six arguments @var{second},
+or more arguments.  The first six arguments @var{second},
 @var{minute}, @var{hour}, @var{day}, @var{month}, and @var{year}
-specify most of the components of a decoded time.  If there are seven
-through nine arguments the @emph{last} argument is used as @var{zone},
-and if there are ten arguments the ninth specifies @var{zone} and the
-tenth specifies @var{subsec}; in either case any other extra arguments
-are ignored, so that @code{(apply #'encode-time (decode-time ...))}
-works.  In this obsolescent convention, @var{zone} defaults to the
-current time zone rule (@pxref{Time Zone Rules}), @var{subsec}
-defaults to 0, and @var{dst} is treated as if it was @minus{}1.
+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.  In this obsolescent
+convention, @var{zone} defaults to the current time zone rule
+(@pxref{Time Zone Rules}), and @var{dst} is treated as if it was
+@minus{}1.
 
 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
@@ -1615,9 +1625,8 @@ Time Conversion
 @end example
 
 You can perform simple date arithmetic by using out-of-range values for
-@var{seconds}, @var{minutes}, @var{hour}, @var{day}, @var{month}, and
-@var{subsec}; for example, day 0 means the day preceding the given
-month.
+@var{seconds}, @var{minutes}, @var{hour}, @var{day}, and @var{month};
+for example, day 0 means the day preceding the given month.
 
 The operating system puts limits on the range of possible time values;
 if the limits are exceeded while encoding the time, an error results.
diff --git a/doc/misc/emacs-mime.texi b/doc/misc/emacs-mime.texi
index c411bf3d68..eb829b0612 100644
--- a/doc/misc/emacs-mime.texi
+++ b/doc/misc/emacs-mime.texi
@@ -1535,7 +1535,7 @@ time-date
 
 @example
 (parse-time-string "Sat Sep 12 12:21:54 1998 +0200")
-@result{} (54 21 12 12 9 1998 6 -1 7200 0)
+@result{} (54 21 12 12 9 1998 6 -1 7200)
 
 (time-convert
   (date-to-time "Sat Sep 12 12:21:54 1998 +0200")
diff --git a/etc/NEWS b/etc/NEWS
index edce7b3e57..53408a871e 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -2116,10 +2116,20 @@ probing the innards of a timestamp directly, or creating a timestamp
 by hand.
 
 +++
-*** Decoded (calendrical) timestamps now have a new subsecond member.
-This affects functions like decode-time and parse-time-string that
-generate these timestamps, and functions like encode-time that accept
-them.
+*** Decoded (calendrical) timestamps now have subsecond resolution.
+This affects decode-time, which generates these timestamps, as well as
+functions like encode-time that accept them.  The subsecond info is
+present as a (TICKS . HZ) value in the seconds element of a decoded
+timestamp, and decode-time has a new optional FORM argument specifying
+the form of the seconds member.  For example, if X is the timestamp
+(1566009571321878186 . 1000000000), which represents 2019-08-17
+02:39:31.321878186 UTC, (decode-time X t t) returns ((31321878186
+. 1000000000) 39 2 17 8 2019 6 nil 0) instead of the traditional (31
+39 2 17 8 2019 6 nil 0) returned by plain (decode-time X t).  Although
+the default FORM is currently 'integer', which truncates the seconds
+to an integer and is the traditional behavior, this default may change
+in future Emacs versions, so callers requiring an integer should
+specify FORM explicitly.
 
 +++
 *** 'encode-time' supports a new API '(encode-time TIME)'.
@@ -2152,8 +2162,8 @@ with POSIX.1-2017.
 *** To access (or alter) the elements a decoded time value, the
 'decoded-time-second', 'decoded-time-minute', 'decoded-time-hour',
 'decoded-time-day', 'decoded-time-month', 'decoded-time-year',
-'decoded-time-weekday', 'decoded-time-dst', 'decoded-time-zone',
-and 'decoded-time-subsec' accessors can be used.
+'decoded-time-weekday', 'decoded-time-dst' and 'decoded-time-zone'
+accessors can be used.
 
 *** The new functions 'date-days-in-month' (which will say how many
 days there are in a month in a specific year), 'date-ordinal-to-time'
diff --git a/lisp/calendar/icalendar.el b/lisp/calendar/icalendar.el
index 84f579ad44..c2688705e3 100644
--- a/lisp/calendar/icalendar.el
+++ b/lisp/calendar/icalendar.el
@@ -644,7 +644,7 @@ icalendar--decode-isodatetime
         ;; create the decoded date-time
         ;; FIXME!?!
 	(let ((decoded-time (list second minute hour day month year
-				  nil -1 zone 0)))
+				  nil -1 zone)))
 	  (condition-case nil
 	      (decode-time (encode-time decoded-time))
 	    (error
diff --git a/lisp/calendar/iso8601.el b/lisp/calendar/iso8601.el
index 51f5dff909..30352c7e75 100644
--- a/lisp/calendar/iso8601.el
+++ b/lisp/calendar/iso8601.el
@@ -129,8 +129,7 @@ iso8601-parse
         (let ((time (iso8601-parse-time time-string)))
           (setf (decoded-time-hour date) (decoded-time-hour time))
           (setf (decoded-time-minute date) (decoded-time-minute time))
-	  (setf (decoded-time-second date) (decoded-time-second time))
-	  (setf (decoded-time-subsec date) (decoded-time-subsec time))))
+          (setf (decoded-time-second date) (decoded-time-second time))))
       ;; The time zone is optional.
       (when zone-string
         (setf (decoded-time-zone date)
@@ -237,8 +236,6 @@ iso8601-parse-time
           (iso8601--decoded-time :hour hour
                                  :minute (or minute 0)
                                  :second (or second 0)
-				 ;; FIXME: Support subsec.
-				 :subsec 0
                                  :zone (and zone
                                             (* 60 (iso8601-parse-zone
                                                    zone)))))))))
@@ -277,9 +274,7 @@ iso8601-parse-duration
                            :day (or (match-string 3 string) 0)
                            :hour (or (match-string 5 string) 0)
                            :minute (or (match-string 6 string) 0)
-			   :second (or (match-string 7 string) 0)
-			   ;; FIXME: Support subsec.
-			   :subsec 0))
+                           :second (or (match-string 7 string) 0)))
    ;; PnW: Weeks.
    ((iso8601--match iso8601--duration-week-match string)
     (let ((weeks (string-to-number (match-string 1 string))))
@@ -341,7 +336,7 @@ iso8601--value
 
 (cl-defun iso8601--decoded-time (&key second minute hour
                                       day month year
-                                      dst zone subsec)
+                                      dst zone)
   (list (iso8601--value second)
         (iso8601--value minute)
         (iso8601--value hour)
@@ -350,8 +345,7 @@ iso8601--value
         (iso8601--value year)
         nil
         dst
-        zone
-	subsec))
+        zone))
 
 (defun iso8601--encode-time (time)
   "Like `encode-time', but fill in nil values in TIME."
diff --git a/lisp/calendar/parse-time.el b/lisp/calendar/parse-time.el
index 9af93b5b1e..b0b277db77 100644
--- a/lisp/calendar/parse-time.el
+++ b/lisp/calendar/parse-time.el
@@ -148,7 +148,7 @@ parse-time-rules
 
 ;;;###autoload
 (defun parse-time-string (string)
-  "Parse the time in STRING into (SEC MIN HOUR DAY MON YEAR DOW DST TZ SUBSEC).
+  "Parse the time in STRING into (SEC MIN HOUR DAY MON YEAR DOW DST TZ).
 STRING should be something resembling an RFC 822 (or later) date-time, e.g.,
 \"Fri, 25 Mar 2016 16:24:56 +0100\", but this function is
 somewhat liberal in what format it accepts, and will attempt to
@@ -156,7 +156,7 @@ parse-time-string
 The values returned are identical to those of `decode-time', but
 any unknown values other than DST are returned as nil, and an
 unknown DST value is returned as -1."
-  (let ((time (list nil nil nil nil nil nil nil -1 nil nil))
+  (let ((time (list nil nil nil nil nil nil nil -1 nil))
 	(temp (parse-time-tokenize (downcase string))))
     (while temp
       (let ((parse-time-elt (pop temp))
@@ -193,10 +193,6 @@ parse-time-string
 				       (funcall this)))
 				 parse-time-val)))
 		  (setf (nth (pop slots) time) new-val))))))))
-    ;; FIXME: Currently parse-time-string does not parse subseconds.
-    ;; So if seconds were found, set subseconds to zero.
-    (when (nth 0 time)
-      (setf (nth 9 time) 0))
     time))
 
 (defun parse-iso8601-time-string (date-string)
diff --git a/lisp/calendar/time-date.el b/lisp/calendar/time-date.el
index fa5e886869..f3d252f03c 100644
--- a/lisp/calendar/time-date.el
+++ b/lisp/calendar/time-date.el
@@ -420,26 +420,13 @@ decoded-time-add
 
     ;; Do the time part, which is pretty simple (except for leap
     ;; seconds, I guess).
-    (setq seconds (+ (* (or (decoded-time-hour delta) 0) 3600)
-                     (* (or (decoded-time-minute delta) 0) 60)
-                     (or (decoded-time-second delta) 0)))
-    (when (decoded-time-subsec delta)
-      (let* ((subsec (time-convert (time-add (decoded-time-subsec time)
-					     (decoded-time-subsec delta))
-				   t))
-	     (s (time-convert subsec 'integer)))
-	(setq seconds (+ seconds s))
-	(setf (decoded-time-subsec time) (time-subtract subsec s))))
-
     ;; Time zone adjustments are basically the same as time adjustments.
-    (setq seconds (+ seconds (or (decoded-time-zone delta) 0)))
-
-    (cond
-     ((> seconds 0)
-      (decoded-time--alter-second time seconds t))
-     ((< seconds 0)
-      (decoded-time--alter-second time (abs seconds) nil)))
+    (setq seconds (time-add (+ (* (or (decoded-time-hour delta) 0) 3600)
+			       (* (or (decoded-time-minute delta) 0) 60)
+			       (or (decoded-time-zone delta) 0))
+			    (or (decoded-time-second delta) 0)))
 
+    (decoded-time--alter-second time seconds)
     time))
 
 (defun decoded-time--alter-month (time increase)
@@ -472,38 +459,31 @@ decoded-time--alter-day
             (date-days-in-month (decoded-time-year time)
                                 (decoded-time-month time))))))
 
-(defun decoded-time--alter-second (time seconds increase)
-  "Increase or decrease the time in TIME by SECONDS."
-  (let ((old (+ (* (or (decoded-time-hour time) 0) 3600)
-                (* (or (decoded-time-minute time) 0) 60)
-                (or (decoded-time-second time) 0))))
-
-    (if increase
-        (progn
-          (setq old (+ old seconds))
-          (setf (decoded-time-second time) (% old 60)
-                (decoded-time-minute time) (% (/ old 60) 60)
-                (decoded-time-hour time) (% (/ old 3600) 24))
-          ;; Hm...  DST...
-          (let ((days (/ old (* 60 60 24))))
-            (while (> days 0)
-              (decoded-time--alter-day time t)
-              (cl-decf days))))
-      (setq old (abs (- old seconds)))
-      (setf (decoded-time-second time) (% old 60)
-            (decoded-time-minute time) (% (/ old 60) 60)
-            (decoded-time-hour time) (% (/ old 3600) 24))
-      ;; Hm...  DST...
-      (let ((days (/ old (* 60 60 24))))
-        (while (> days 0)
-          (decoded-time--alter-day time nil)
-          (cl-decf days))))))
+(defun decoded-time--alter-second (time seconds)
+  "Increase the time in TIME by SECONDS."
+  (let* ((secsperday 86400)
+	 (old (time-add (+ (* 3600 (or (decoded-time-hour time) 0))
+			   (* 60 (or (decoded-time-minute time) 0)))
+			(or (decoded-time-second time) 0)))
+	 (new (time-add old seconds)))
+    ;; Hm...  DST...
+    (while (time-less-p new 0)
+      (decoded-time--alter-day time nil)
+      (setq new (time-add new secsperday)))
+    (while (not (time-less-p new secsperday))
+      (decoded-time--alter-day time t)
+      (setq new (time-subtract new secsperday)))
+    (let ((sec (time-convert new 'integer)))
+      (setf (decoded-time-second time) (time-add (% sec 60)
+						 (time-subtract new sec))
+	    (decoded-time-minute time) (% (/ sec 60) 60)
+	    (decoded-time-hour time) (/ sec 3600)))))
 
 (cl-defun make-decoded-time (&key second minute hour
                                   day month year
-                                  dst zone subsec)
+                                  dst zone)
   "Return a `decoded-time' structure with only the keywords given filled out."
-  (list second minute hour day month year nil dst zone subsec))
+  (list second minute hour day month year nil dst zone))
 
 (defun decoded-time-set-defaults (time &optional default-zone)
   "Set any nil values in `decoded-time' TIME to default values.
@@ -533,9 +513,6 @@ decoded-time-set-defaults
   (when (and (not (decoded-time-zone time))
              default-zone)
     (setf (decoded-time-zone time) 0))
-
-  (unless (decoded-time-subsec time)
-    (setf (decoded-time-subsec time) 0))
   time)
 
 (provide 'time-date)
diff --git a/lisp/net/soap-client.el b/lisp/net/soap-client.el
index eb08511171..7ce7d79c74 100644
--- a/lisp/net/soap-client.el
+++ b/lisp/net/soap-client.el
@@ -561,8 +561,8 @@ soap-decode-date-time
 Return a list in a format (SEC MINUTE HOUR DAY MONTH YEAR
 SEC-FRACTION DATATYPE ZONE).  This format is meant to be similar
 to that returned by `decode-time' (and compatible with
-`encode-time').  The differences are the SUBSEC (fractional
-seconds) field is omitted, the DOW (day-of-week) field
+`encode-time').  The differences are the SEC (seconds)
+field is always an integer, the DOW (day-of-week) field
 is replaced with SEC-FRACTION, a float representing the
 fractional seconds, and the DST (daylight savings time) field is
 replaced with DATATYPE, a symbol representing the XSD primitive
diff --git a/lisp/org/org.el b/lisp/org/org.el
index 336c413c8c..ab29353ae8 100644
--- a/lisp/org/org.el
+++ b/lisp/org/org.el
@@ -17775,12 +17775,14 @@ org-parse-time-string
 	       (string-to-number (match-string 4 s))
 	       (string-to-number (match-string 3 s))
 	       (string-to-number (match-string 2 s))
-	       nil nil nil 0))
+	       nil nil nil))
 	((string-match "^<[^>]+>$" s)
 	 ;; FIXME: `decode-time' needs to be called with ZONE as its
 	 ;; second argument.  However, this requires at least Emacs
 	 ;; 25.1.  We can do it when we switch to this version as our
 	 ;; minimal requirement.
+	 ;; FIXME: decode-time needs to be called with t as its
+	 ;; third argument, but this requires at least Emacs 27.
 	 (decode-time (org-matcher-time s)))
 	(t (error "Not a standard Org time string: %s" s))))
 
diff --git a/lisp/simple.el b/lisp/simple.el
index cb938bb341..fdf7d893cd 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -9082,8 +9082,9 @@ capitalize-dwim
                (:copier nil)
                (:type list))
   (second nil :documentation "\
-This is an integer between 0 and 60 (inclusive).  (60 is a leap
-second, which only some operating systems support.)")
+This is an integer or a Lisp timestamp (TICKS . HZ) representing a nonnegative
+number of seconds less than 61.  (If not less than 60, it is a leap second,
+which only some operating systems support.)")
   (minute nil :documentation "This is an integer between 0 and 59 (inclusive).")
   (hour nil :documentation "This is an integer between 0 and 23 (inclusive).")
   (day nil :documentation "This is an integer between 1 and 31 (inclusive).")
@@ -9099,9 +9100,6 @@ capitalize-dwim
   (zone nil :documentation "\
 This is an integer indicating the UTC offset in seconds, i.e.,
 the number of seconds east of Greenwich.")
-  (subsec nil :documentation "\
-This is 0, or is an integer pair (TICKS . HZ) indicating TICKS/HZ seconds,
-where HZ is positive and TICKS is nonnegative and less than HZ.")
   )
 
 \f
diff --git a/src/timefns.c b/src/timefns.c
index 979550c843..16c39c8349 100644
--- a/src/timefns.c
+++ b/src/timefns.c
@@ -1374,8 +1374,8 @@ usage: (format-time-string FORMAT-STRING &optional TIME ZONE)  */)
 			     t, zone, &tm);
 }
 
-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 SUBSEC).
+DEFUN ("decode-time", Fdecode_time, Sdecode_time, 0, 3, 0,
+       doc: /* Decode a time value as (SEC MINUTE HOUR DAY MONTH YEAR DOW DST UTCOFF).
 The optional TIME is the time value to convert.  See
 `format-time-string' for the various forms of a time value.
 
@@ -1385,29 +1385,33 @@ the TZ environment variable.  It can also be a list (as from
 `current-time-zone') or an integer (the UTC offset in seconds) applied
 without consideration for daylight saving time.
 
+The optional FORM specifies the form of the SEC member.  If `integer',
+SEC is an integer; if t, SEC uses the same resolution as TIME.  An
+omitted or nil FORM is currently treated like `integer', but this may
+change in future Emacs versions.
+
 To access (or alter) the elements in the time value, the
 `decoded-time-second', `decoded-time-minute', `decoded-time-hour',
 `decoded-time-day', `decoded-time-month', `decoded-time-year',
-`decoded-time-weekday', `decoded-time-dst', `decoded-time-zone' and
-`decoded-time-subsec' accessors can be used.
+`decoded-time-weekday', `decoded-time-dst' and `decoded-time-zone'
+accessors can be used.
 
-The list has the following ten members: SEC is an integer between 0
-and 60; SEC is 60 for a leap second, which only some operating systems
-support.  MINUTE is an integer between 0 and 59.  HOUR is an integer
+The list has the following nine members: SEC is an integer or
+Lisp timestamp representing a nonnegative value less than 60
+\(or less than 61 if the operating system supports leap seconds).
+MINUTE is an integer between 0 and 59.  HOUR is an integer
 between 0 and 23.  DAY is an integer between 1 and 31.  MONTH is an
 integer between 1 and 12.  YEAR is an integer indicating the
 four-digit year.  DOW is the day of week, an integer between 0 and 6,
 where 0 is Sunday.  DST is t if daylight saving time is in effect,
 nil if it is not in effect, and -1 if daylight saving information is
 not available.  UTCOFF is an integer indicating the UTC offset in
-seconds, i.e., the number of seconds east of Greenwich.  SUBSEC is
-is either 0 or (TICKS . HZ) where HZ is a positive integer clock
-resolution and TICKS is a nonnegative integer less than HZ.  (Note
-that Common Lisp has different meanings for DOW and UTCOFF, and lacks
-SUBSEC.)
+seconds, i.e., the number of seconds east of Greenwich.  (Note that
+Common Lisp has different meanings for DOW and UTCOFF, and its
+SEC is always an integer between 0 and 59.)
 
-usage: (decode-time &optional TIME ZONE)  */)
-  (Lisp_Object specified_time, Lisp_Object zone)
+usage: (decode-time &optional TIME ZONE FORM)  */)
+  (Lisp_Object specified_time, Lisp_Object zone, Lisp_Object form)
 {
   struct lisp_time lt = lisp_time_struct (specified_time, 0);
   struct timespec ts = lisp_to_timespec (lt);
@@ -1439,8 +1443,35 @@ usage: (decode-time &optional TIME ZONE)  */)
       year = make_integer_mpz ();
     }
 
+  Lisp_Object hz = lt.hz, sec;
+  if (EQ (hz, make_fixnum (1)) || !EQ (form, Qt))
+    sec = make_fixnum (local_tm.tm_sec);
+  else
+    {
+      Lisp_Object ticks; /* hz * tm_sec + mod (lt.ticks, hz) */
+      intmax_t n;
+      if (FASTER_TIMEFNS && FIXNUMP (lt.ticks) && FIXNUMP (hz)
+	  && !INT_MULTIPLY_WRAPV (XFIXNUM (hz), local_tm.tm_sec, &n)
+	  && ! (INT_ADD_WRAPV
+		(n, (XFIXNUM (lt.ticks) % XFIXNUM (hz)
+		     + (XFIXNUM (lt.ticks) % XFIXNUM (hz) < 0
+			? XFIXNUM (hz) : 0)),
+		 &n)))
+	ticks = make_int (n);
+      else
+	{
+	  mpz_fdiv_r (mpz[0],
+		      *bignum_integer (&mpz[0], lt.ticks),
+		      *bignum_integer (&mpz[1], hz));
+	  mpz_addmul_ui (mpz[0], *bignum_integer (&mpz[1], hz),
+			 local_tm.tm_sec);
+	  ticks = make_integer_mpz ();
+	}
+      sec = Fcons (ticks, hz);
+    }
+
   return CALLN (Flist,
-		make_fixnum (local_tm.tm_sec),
+		sec,
 		make_fixnum (local_tm.tm_min),
 		make_fixnum (local_tm.tm_hour),
 		make_fixnum (local_tm.tm_mday),
@@ -1453,10 +1484,7 @@ usage: (decode-time &optional TIME ZONE)  */)
 		 ? make_fixnum (tm_gmtoff (&local_tm))
 		 : gmtime_r (&time_spec, &gmt_tm)
 		 ? make_fixnum (tm_diff (&local_tm, &gmt_tm))
-		 : Qnil),
-		(EQ (lt.hz, make_fixnum (1))
-		 ? make_fixnum (0)
-		 : Fcons (integer_mod (lt.ticks, lt.hz), lt.hz)));
+		 : Qnil));
 }
 
 /* Return OBJ - OFFSET, checking that OBJ is a valid integer and that
@@ -1487,7 +1515,7 @@ check_tm_member (Lisp_Object obj, int offset)
 DEFUN ("encode-time", Fencode_time, Sencode_time, 1, MANY, 0,
        doc: /* Convert TIME to a timestamp.
 
-TIME is a list (SECOND MINUTE HOUR DAY MONTH YEAR IGNORED DST ZONE SUBSEC).
+TIME is a list (SECOND MINUTE HOUR DAY MONTH YEAR IGNORED DST ZONE).
 in the style of `decode-time', so that (encode-time (decode-time ...)) works.
 In this list, ZONE can be nil for Emacs local time, t for Universal
 Time, `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
 without consideration for daylight saving time.  If ZONE specifies a
 time zone with daylight-saving transitions, DST is t for daylight
 saving time, nil for standard time, and -1 to cause the daylight
-saving flag to be guessed.  SUBSEC is either 0 or a Lisp timestamp
-in (TICKS . HZ) form.
+saving flag to be guessed.
 
 As an obsolescent calling convention, if this function is called with
-6 through 10 arguments, the first 6 arguments are SECOND, MINUTE,
-HOUR, DAY, MONTH, and YEAR, and specify the components of a decoded
-time.  If there are 7 through 9 arguments the *last* argument
-specifies ZONE, and if there are 10 arguments the 9th specifies ZONE
-and the 10th specifies SUBSEC; in either case any other extra
-arguments are ignored, so that (apply #\\='encode-time (decode-time
-...)) works.  In this obsolescent convention, DST, ZONE, and SUBSEC
-default to -1, nil and 0 respectively.
-
-Out-of-range values for SECOND, MINUTE, HOUR, DAY, or MONTH are allowed;
-for example, a DAY of 0 means the day preceding the given month.
-Year numbers less than 100 are treated just like other year numbers.
-If you want them to stand for years in this century, you must do that yourself.
+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
+(decode-time ...)) works.  In this obsolescent convention, DST and
+ZONE default to -1 and nil respectively.
 
 Years before 1970 are not guaranteed to work.  On some systems,
 year values as low as 1901 do work.
@@ -1521,27 +1542,27 @@ usage: (encode-time TIME &rest OBSOLESCENT-ARGUMENTS)  */)
   (ptrdiff_t nargs, Lisp_Object *args)
 {
   struct tm tm;
-  Lisp_Object zone = Qnil, subsec = make_fixnum (0);
+  Lisp_Object zone = Qnil;
   Lisp_Object a = args[0];
+  Lisp_Object secarg, minarg, hourarg, mdayarg, monarg, yeararg;
   tm.tm_isdst = -1;
 
   if (nargs == 1)
     {
       Lisp_Object tail = a;
-      for (int i = 0; i < 10; i++, tail = XCDR (tail))
+      for (int i = 0; i < 9; i++, tail = XCDR (tail))
 	CHECK_CONS (tail);
-      tm.tm_sec  = check_tm_member (XCAR (a), 0); a = XCDR (a);
-      tm.tm_min  = check_tm_member (XCAR (a), 0); a = XCDR (a);
-      tm.tm_hour = check_tm_member (XCAR (a), 0); a = XCDR (a);
-      tm.tm_mday = check_tm_member (XCAR (a), 0); a = XCDR (a);
-      tm.tm_mon  = check_tm_member (XCAR (a), 1); a = XCDR (a);
-      tm.tm_year = check_tm_member (XCAR (a), TM_YEAR_BASE); a = XCDR (a);
+      secarg = XCAR (a); a = XCDR (a);
+      minarg = XCAR (a); a = XCDR (a);
+      hourarg = XCAR (a); a = XCDR (a);
+      mdayarg = XCAR (a); a = XCDR (a);
+      monarg = XCAR (a); a = XCDR (a);
+      yeararg = XCAR (a); a = XCDR (a);
       a = XCDR (a);
       Lisp_Object dstflag = XCAR (a); a = XCDR (a);
-      zone = XCAR (a); a = XCDR (a);
+      zone = XCAR (a);
       if (SYMBOLP (dstflag) && !FIXNUMP (zone) && !CONSP (zone))
 	tm.tm_isdst = !NILP (dstflag);
-      subsec = XCAR (a);
     }
   else if (nargs < 6)
     xsignal2 (Qwrong_number_of_arguments, Qencode_time, make_fixnum (nargs));
@@ -1549,18 +1570,37 @@ usage: (encode-time TIME &rest OBSOLESCENT-ARGUMENTS)  */)
     {
       if (6 < nargs)
 	zone = args[nargs - 1];
-      if (9 < nargs)
-	{
-	  zone = args[8];
-	  subsec = args[9];
-	}
-      tm.tm_sec  = check_tm_member (a, 0);
-      tm.tm_min  = check_tm_member (args[1], 0);
-      tm.tm_hour = check_tm_member (args[2], 0);
-      tm.tm_mday = check_tm_member (args[3], 0);
-      tm.tm_mon  = check_tm_member (args[4], 1);
-      tm.tm_year = check_tm_member (args[5], TM_YEAR_BASE);
+      secarg = a;
+      minarg = args[1];
+      hourarg = args[2];
+      mdayarg = args[3];
+      monarg = args[4];
+      yeararg = args[5];
+    }
+
+  struct lisp_time lt;
+  decode_lisp_time (secarg, 0, &lt, 0);
+  Lisp_Object hz = lt.hz, sec, subsecticks;
+  if (FASTER_TIMEFNS && EQ (hz, make_fixnum (1)))
+    {
+      sec = lt.ticks;
+      subsecticks = make_fixnum (0);
+    }
+  else
+    {
+      mpz_fdiv_qr (mpz[0], mpz[1],
+		   *bignum_integer (&mpz[0], lt.ticks),
+		   *bignum_integer (&mpz[1], hz));
+      sec = make_integer_mpz ();
+      mpz_swap (mpz[0], mpz[1]);
+      subsecticks = make_integer_mpz ();
     }
+  tm.tm_sec  = check_tm_member (sec, 0);
+  tm.tm_min  = check_tm_member (minarg, 0);
+  tm.tm_hour = check_tm_member (hourarg, 0);
+  tm.tm_mday = check_tm_member (mdayarg, 0);
+  tm.tm_mon  = check_tm_member (monarg, 1);
+  tm.tm_year = check_tm_member (yeararg, TM_YEAR_BASE);
 
   timezone_t tz = tzlookup (zone, false);
   tm.tm_wday = -1;
@@ -1571,25 +1611,17 @@ usage: (encode-time TIME &rest OBSOLESCENT-ARGUMENTS)  */)
   if (tm.tm_wday < 0)
     time_error (mktime_errno);
 
-  if (CONSP (subsec))
+  if (EQ (hz, make_fixnum (1)))
+    return (CURRENT_TIME_LIST
+	    ? list2 (hi_time (value), lo_time (value))
+	    : INT_TO_INTEGER (value));
+  else
     {
-      Lisp_Object subsecticks = XCAR (subsec);
-      if (INTEGERP (subsecticks))
-	{
-	  struct lisp_time val1 = { INT_TO_INTEGER (value), make_fixnum (1) };
-	  Lisp_Object
-	    hz = XCDR (subsec),
-	    secticks = lisp_time_hz_ticks (val1, hz),
-	    ticks = lispint_arith (secticks, subsecticks, false);
-	  return Fcons (ticks, hz);
-	}
+      struct lisp_time val1 = { INT_TO_INTEGER (value), make_fixnum (1) };
+      Lisp_Object secticks = lisp_time_hz_ticks (val1, hz);
+      Lisp_Object ticks = lispint_arith (secticks, subsecticks, false);
+      return Fcons (ticks, hz);
     }
-  else if (INTEGERP (subsec))
-    return (CURRENT_TIME_LIST && EQ (subsec, make_fixnum (0))
-	    ? list2 (hi_time (value), lo_time (value))
-	    : lispint_arith (INT_TO_INTEGER (value), subsec, false));
-
-  xsignal2 (Qerror, build_string ("Invalid subsec"), subsec);
 }
 
 DEFUN ("time-convert", Ftime_convert, Stime_convert, 1, 2, 0,
diff --git a/test/lisp/calendar/icalendar-tests.el b/test/lisp/calendar/icalendar-tests.el
index 060cd8c909..baea480404 100644
--- a/test/lisp/calendar/icalendar-tests.el
+++ b/test/lisp/calendar/icalendar-tests.el
@@ -477,18 +477,18 @@ icalendar-tests--trim
 
           ;; testcase: no time zone in input -> keep time as is
           ;; 1 Jan 2013 10:00
-          (should (equal '(0 0 10 1 1 2013 2 nil 7200 0)
+          (should (equal '(0 0 10 1 1 2013 2 nil 7200)
                          (icalendar--decode-isodatetime "20130101T100000")))
           ;; 1 Aug 2013 10:00 (DST)
-          (should (equal '(0 0 10 1 8 2013 4 t 10800 0)
+          (should (equal '(0 0 10 1 8 2013 4 t 10800)
                          (icalendar--decode-isodatetime "20130801T100000")))
 
           ;; testcase: UTC time zone specifier in input -> convert to local time
           ;; 31 Dec 2013 23:00 UTC -> 1 Jan 2013 01:00 EET
-          (should (equal '(0 0 1 1 1 2014 3 nil 7200 0)
+          (should (equal '(0 0 1 1 1 2014 3 nil 7200)
                          (icalendar--decode-isodatetime "20131231T230000Z")))
           ;; 1 Aug 2013 10:00 UTC -> 1 Aug 2013 13:00 EEST
-          (should (equal '(0 0 13 1 8 2013 4 t 10800 0)
+          (should (equal '(0 0 13 1 8 2013 4 t 10800)
                          (icalendar--decode-isodatetime "20130801T100000Z")))
 
           )
diff --git a/test/lisp/calendar/iso8601-tests.el b/test/lisp/calendar/iso8601-tests.el
index 3f1149c864..35c319ed03 100644
--- a/test/lisp/calendar/iso8601-tests.el
+++ b/test/lisp/calendar/iso8601-tests.el
@@ -24,65 +24,65 @@
 
 (ert-deftest test-iso8601-date-years ()
   (should (equal (iso8601-parse-date "1985")
-                 '(nil nil nil nil nil 1985 nil nil nil nil)))
+                 '(nil nil nil nil nil 1985 nil nil nil)))
   (should (equal (iso8601-parse-date "-0003")
-                 '(nil nil nil nil nil -4 nil nil nil nil)))
+                 '(nil nil nil nil nil -4 nil nil nil)))
   (should (equal (iso8601-parse-date "+1985")
-                 '(nil nil nil nil nil 1985 nil nil nil nil))))
+                 '(nil nil nil nil nil 1985 nil nil nil))))
 
 (ert-deftest test-iso8601-date-dates ()
   (should (equal (iso8601-parse-date "1985-03-14")
-                 '(nil nil nil 14 3 1985 nil nil nil nil)))
+                 '(nil nil nil 14 3 1985 nil nil nil)))
   (should (equal (iso8601-parse-date "19850314")
-                 '(nil nil nil 14 3 1985 nil nil nil nil)))
+                 '(nil nil nil 14 3 1985 nil nil nil)))
   (should (equal (iso8601-parse-date "1985-02")
-                 '(nil nil nil nil 2 1985 nil nil nil nil))))
+                 '(nil nil nil nil 2 1985 nil nil nil))))
 
 (ert-deftest test-iso8601-date-obsolete ()
   (should (equal (iso8601-parse-date "--02-01")
-                 '(nil nil nil 1 2 nil nil nil nil nil)))
+                 '(nil nil nil 1 2 nil nil nil nil)))
   (should (equal (iso8601-parse-date "--0201")
-                 '(nil nil nil 1 2 nil nil nil nil nil))))
+                 '(nil nil nil 1 2 nil nil nil nil))))
 
 (ert-deftest test-iso8601-date-weeks ()
   (should (equal (iso8601-parse-date "2008W39-6")
-                 '(nil nil nil 27 9 2008 nil nil nil nil)))
+                 '(nil nil nil 27 9 2008 nil nil nil)))
   (should (equal (iso8601-parse-date "2009W01-1")
-                 '(nil nil nil 29 12 2008 nil nil nil nil)))
+                 '(nil nil nil 29 12 2008 nil nil nil)))
   (should (equal (iso8601-parse-date "2009W53-7")
-                 '(nil nil nil 3 1 2010 nil nil nil nil))))
+                 '(nil nil nil 3 1 2010 nil nil nil))))
 
 (ert-deftest test-iso8601-date-ordinals ()
   (should (equal (iso8601-parse-date "1981-095")
-                 '(nil nil nil 5 4 1981 nil nil nil nil))))
+                 '(nil nil nil 5 4 1981 nil nil nil))))
 
 (ert-deftest test-iso8601-time ()
   (should (equal (iso8601-parse-time "13:47:30")
-                 '(30 47 13 nil nil nil nil nil nil 0)))
+                 '(30 47 13 nil nil nil nil nil nil)))
   (should (equal (iso8601-parse-time "134730")
-                 '(30 47 13 nil nil nil nil nil nil 0)))
+                 '(30 47 13 nil nil nil nil nil nil)))
   (should (equal (iso8601-parse-time "1347")
-                 '(0 47 13 nil nil nil nil nil nil 0))))
+                 '(0 47 13 nil nil nil nil nil nil))))
 
 (ert-deftest test-iso8601-combined ()
   (should (equal (iso8601-parse "2008-03-02T13:47:30")
-                 '(30 47 13 2 3 2008 nil nil nil 0)))
+                 '(30 47 13 2 3 2008 nil nil nil)))
   (should (equal (iso8601-parse "2008-03-02T13:47:30Z")
-                 '(30 47 13 2 3 2008 nil nil 0 0)))
+                 '(30 47 13 2 3 2008 nil nil 0)))
   (should (equal (iso8601-parse "2008-03-02T13:47:30+01:00")
-                 '(30 47 13 2 3 2008 nil nil 3600 0)))
+                 '(30 47 13 2 3 2008 nil nil 3600)))
   (should (equal (iso8601-parse "2008-03-02T13:47:30-01")
-                 '(30 47 13 2 3 2008 nil nil -3600 0))))
+                 '(30 47 13 2 3 2008 nil nil -3600))))
 
 (ert-deftest test-iso8601-duration ()
   (should (equal (iso8601-parse-duration "P3Y6M4DT12H30M5S")
-                 '(5 30 12 4 6 3 nil nil nil 0)))
+                 '(5 30 12 4 6 3 nil nil nil)))
   (should (equal (iso8601-parse-duration "P1M")
-                 '(0 0 0 0 1 0 nil nil nil 0)))
+                 '(0 0 0 0 1 0 nil nil nil)))
   (should (equal (iso8601-parse-duration "PT1M")
-                 '(0 1 0 0 0 0 nil nil nil 0)))
+                 '(0 1 0 0 0 0 nil nil nil)))
   (should (equal (iso8601-parse-duration "P0003-06-04T12:30:05")
-                 '(5 30 12 4 6 3 nil nil nil 0))))
+                 '(5 30 12 4 6 3 nil nil nil))))
 
 (ert-deftest test-iso8601-invalid ()
   (should-not (iso8601-valid-p " 2008-03-02T13:47:30-01"))
@@ -94,149 +94,149 @@
 (ert-deftest test-iso8601-intervals ()
   (should (equal
            (iso8601-parse-interval "2007-03-01T13:00:00Z/2008-05-11T15:30:00Z")
-           '((0 0 13 1 3 2007 nil nil 0 0)
-             (0 30 15 11 5 2008 nil nil 0 0)
+           '((0 0 13 1 3 2007 nil nil 0)
+             (0 30 15 11 5 2008 nil nil 0)
              ;; Hm...  can't really use decode-time for time differences...
-             (0 30 2 14 3 1971 0 nil 0 0))))
+             (0 30 2 14 3 1971 0 nil 0))))
   (should (equal (iso8601-parse-interval "2007-03-01T13:00:00Z/P1Y2M10DT2H30M")
-                 '((0 0 13 1 3 2007 nil nil 0 0)
-                   (0 30 15 11 5 2008 nil nil 0 0)
-                   (0 30 2 10 2 1 nil nil nil 0))))
+                 '((0 0 13 1 3 2007 nil nil 0)
+                   (0 30 15 11 5 2008 nil nil 0)
+                   (0 30 2 10 2 1 nil nil nil))))
   (should (equal (iso8601-parse-interval "P1Y2M10DT2H30M/2008-05-11T15:30:00Z")
-                 '((0 0 13 1 3 2007 nil nil 0 0)
-                   (0 30 15 11 5 2008 nil nil 0 0)
-                   (0 30 2 10 2 1 nil nil nil 0)))))
+                 '((0 0 13 1 3 2007 nil nil 0)
+                   (0 30 15 11 5 2008 nil nil 0)
+                   (0 30 2 10 2 1 nil nil nil)))))
 
 (ert-deftest standard-test-dates ()
   (should (equal (iso8601-parse-date "19850412")
-                 '(nil nil nil 12 4 1985 nil nil nil nil)))
+                 '(nil nil nil 12 4 1985 nil nil nil)))
   (should (equal (iso8601-parse-date "1985-04-12")
-                 '(nil nil nil 12 4 1985 nil nil nil nil)))
+                 '(nil nil nil 12 4 1985 nil nil nil)))
 
   (should (equal (iso8601-parse-date "1985102")
-                 '(nil nil nil 12 4 1985 nil nil nil nil)))
+                 '(nil nil nil 12 4 1985 nil nil nil)))
   (should (equal (iso8601-parse-date "1985-102")
-                 '(nil nil nil 12 4 1985 nil nil nil nil)))
+                 '(nil nil nil 12 4 1985 nil nil nil)))
 
   (should (equal (iso8601-parse-date "1985W155")
-                 '(nil nil nil 12 4 1985 nil nil nil nil)))
+                 '(nil nil nil 12 4 1985 nil nil nil)))
   (should (equal (iso8601-parse-date "1985-W15-5")
-                 '(nil nil nil 12 4 1985 nil nil nil nil)))
+                 '(nil nil nil 12 4 1985 nil nil nil)))
 
   (should (equal (iso8601-parse-date "1985W15")
-                 '(nil nil nil 7 4 1985 nil nil nil nil)))
+                 '(nil nil nil 7 4 1985 nil nil nil)))
   (should (equal (iso8601-parse-date "1985-W15")
-                 '(nil nil nil 7 4 1985 nil nil nil nil)))
+                 '(nil nil nil 7 4 1985 nil nil nil)))
 
   (should (equal (iso8601-parse-date "1985-04")
-                 '(nil nil nil nil 4 1985 nil nil nil nil)))
+                 '(nil nil nil nil 4 1985 nil nil nil)))
 
   (should (equal (iso8601-parse-date "1985")
-                 '(nil nil nil nil nil 1985 nil nil nil nil)))
+                 '(nil nil nil nil nil 1985 nil nil nil)))
 
   (should (equal (iso8601-parse-date "+1985-04-12")
-                 '(nil nil nil 12 4 1985 nil nil nil nil)))
+                 '(nil nil nil 12 4 1985 nil nil nil)))
   (should (equal (iso8601-parse-date "+19850412")
-                 '(nil nil nil 12 4 1985 nil nil nil nil))))
+                 '(nil nil nil 12 4 1985 nil nil nil))))
 
 (ert-deftest standard-test-time-of-day-local-time ()
   (should (equal (iso8601-parse-time "152746")
-                 '(46 27 15 nil nil nil nil nil nil 0)))
+                 '(46 27 15 nil nil nil nil nil nil)))
   (should (equal (iso8601-parse-time "15:27:46")
-                 '(46 27 15 nil nil nil nil nil nil 0)))
+                 '(46 27 15 nil nil nil nil nil nil)))
 
   (should (equal (iso8601-parse-time "1528")
-                 '(0 28 15 nil nil nil nil nil nil 0)))
+                 '(0 28 15 nil nil nil nil nil nil)))
   (should (equal (iso8601-parse-time "15:28")
-                 '(0 28 15 nil nil nil nil nil nil 0)))
+                 '(0 28 15 nil nil nil nil nil nil)))
 
   (should (equal (iso8601-parse-time "15")
-                 '(0 0 15 nil nil nil nil nil nil 0))))
+                 '(0 0 15 nil nil nil nil nil nil))))
 
 (ert-deftest standard-test-time-of-day-fractions ()
   ;; decoded-time doesn't support sub-second times.
   ;; (should (equal (iso8601-parse-time "152735,5")
-  ;;                '(46 27 15 nil nil nil nil nil nil (5 . 10))))
+  ;;                '(46 27 15 nil nil nil nil nil nil)))
   ;; (should (equal (iso8601-parse-time "15:27:35,5")
-  ;;                '(46 27 15 nil nil nil nil nil nil (5 . 10))))
+  ;;                '(46 27 15 nil nil nil nil nil nil)))
   )
 
 (ert-deftest standard-test-time-of-day-beginning-of-day ()
   (should (equal (iso8601-parse-time "000000")
-                 '(0 0 0 nil nil nil nil nil nil 0)))
+                 '(0 0 0 nil nil nil nil nil nil)))
   (should (equal (iso8601-parse-time "00:00:00")
-                 '(0 0 0 nil nil nil nil nil nil 0)))
+                 '(0 0 0 nil nil nil nil nil nil)))
 
   (should (equal (iso8601-parse-time "0000")
-                 '(0 0 0 nil nil nil nil nil nil 0)))
+                 '(0 0 0 nil nil nil nil nil nil)))
   (should (equal (iso8601-parse-time "00:00")
-                 '(0 0 0 nil nil nil nil nil nil 0))))
+                 '(0 0 0 nil nil nil nil nil nil))))
 
 (ert-deftest standard-test-time-of-day-utc ()
   (should (equal (iso8601-parse-time "232030Z")
-                 '(30 20 23 nil nil nil nil nil 0 0)))
+                 '(30 20 23 nil nil nil nil nil 0)))
   (should (equal (iso8601-parse-time "23:20:30Z")
-                 '(30 20 23 nil nil nil nil nil 0 0)))
+                 '(30 20 23 nil nil nil nil nil 0)))
 
   (should (equal (iso8601-parse-time "2320Z")
-                 '(0 20 23 nil nil nil nil nil 0 0)))
+                 '(0 20 23 nil nil nil nil nil 0)))
   (should (equal (iso8601-parse-time "23:20Z")
-                 '(0 20 23 nil nil nil nil nil 0 0)))
+                 '(0 20 23 nil nil nil nil nil 0)))
 
   (should (equal (iso8601-parse-time "23Z")
-                 '(0 0 23 nil nil nil nil nil 0 0))))
+                 '(0 0 23 nil nil nil nil nil 0))))
 
 
 (ert-deftest standard-test-time-of-day-zone ()
   (should (equal (iso8601-parse-time "152746+0100")
-                 '(46 27 15 nil nil nil nil nil 3600 0)))
+                 '(46 27 15 nil nil nil nil nil 3600)))
   (should (equal (iso8601-parse-time "15:27:46+0100")
-                 '(46 27 15 nil nil nil nil nil 3600 0)))
+                 '(46 27 15 nil nil nil nil nil 3600)))
 
   (should (equal (iso8601-parse-time "152746+01")
-                 '(46 27 15 nil nil nil nil nil 3600 0)))
+                 '(46 27 15 nil nil nil nil nil 3600)))
   (should (equal (iso8601-parse-time "15:27:46+01")
-                 '(46 27 15 nil nil nil nil nil 3600 0)))
+                 '(46 27 15 nil nil nil nil nil 3600)))
 
   (should (equal (iso8601-parse-time "152746-0500")
-                 '(46 27 15 nil nil nil nil nil -18000 0)))
+                 '(46 27 15 nil nil nil nil nil -18000)))
   (should (equal (iso8601-parse-time "15:27:46-0500")
-                 '(46 27 15 nil nil nil nil nil -18000 0)))
+                 '(46 27 15 nil nil nil nil nil -18000)))
 
   (should (equal (iso8601-parse-time "152746-05")
-                 '(46 27 15 nil nil nil nil nil -18000 0)))
+                 '(46 27 15 nil nil nil nil nil -18000)))
   (should (equal (iso8601-parse-time "15:27:46-05")
-                 '(46 27 15 nil nil nil nil nil -18000 0))))
+                 '(46 27 15 nil nil nil nil nil -18000))))
 
 (ert-deftest standard-test-date-and-time-of-day ()
   (should (equal (iso8601-parse "19850412T101530")
-                 '(30 15 10 12 4 1985 nil nil nil 0)))
+                 '(30 15 10 12 4 1985 nil nil nil)))
   (should (equal (iso8601-parse "1985-04-12T10:15:30")
-                 '(30 15 10 12 4 1985 nil nil nil 0)))
+                 '(30 15 10 12 4 1985 nil nil nil)))
 
   (should (equal (iso8601-parse "1985102T235030Z")
-                 '(30 50 23 12 4 1985 nil nil 0 0)))
+                 '(30 50 23 12 4 1985 nil nil 0)))
   (should (equal (iso8601-parse "1985-102T23:50:30Z")
-                 '(30 50 23 12 4 1985 nil nil 0 0)))
+                 '(30 50 23 12 4 1985 nil nil 0)))
 
   (should (equal (iso8601-parse "1985W155T235030")
-                 '(30 50 23 12 4 1985 nil nil nil 0)))
+                 '(30 50 23 12 4 1985 nil nil nil)))
   (should (equal (iso8601-parse "1985-W155T23:50:30")
-                 '(30 50 23 12 4 1985 nil nil nil 0))))
+                 '(30 50 23 12 4 1985 nil nil nil))))
 
 (ert-deftest standard-test-interval ()
   ;; A time interval starting at 20 minutes and 50 seconds past 23
   ;; hours on 12 April 1985 and ending at 30 minutes past 10 hours on
   ;; 25 June 1985.
   (should (equal (iso8601-parse-interval "19850412T232050Z/19850625T103000Z")
-                 '((50 20 23 12 4 1985 nil nil 0 0)
-                   (0 30 10 25 6 1985 nil nil 0 0)
-                   (10 9 11 15 3 1970 0 nil 0 0))))
+                 '((50 20 23 12 4 1985 nil nil 0)
+                   (0 30 10 25 6 1985 nil nil 0)
+                   (10 9 11 15 3 1970 0 nil 0))))
   (should (equal (iso8601-parse-interval
                   "1985-04-12T23:20:50Z/1985-06-25T10:30:00Z")
-                 '((50 20 23 12 4 1985 nil nil 0 0)
-                   (0 30 10 25 6 1985 nil nil 0 0)
-                   (10 9 11 15 3 1970 0 nil 0 0))))
+                 '((50 20 23 12 4 1985 nil nil 0)
+                   (0 30 10 25 6 1985 nil nil 0)
+                   (10 9 11 15 3 1970 0 nil 0))))
 
   ;; A time interval starting at 12 April 1985 and ending on 25 June
   ;; 1985.
@@ -251,41 +251,41 @@
   ;; A time interval of 2 years, 10 months, 15 days, 10 hours, 20
   ;; minutes and 30 seconds.
   (should (equal (iso8601-parse-duration "P2Y10M15DT10H20M30S")
-                 '(30 20 10 15 10 2 nil nil nil 0)))
+                 '(30 20 10 15 10 2 nil nil nil)))
 
   (should (equal (iso8601-parse-duration "P00021015T102030")
-                 '(30 20 10 15 10 2 nil nil nil 0)))
+                 '(30 20 10 15 10 2 nil nil nil)))
   (should (equal (iso8601-parse-duration "P0002-10-15T10:20:30")
-                 '(30 20 10 15 10 2 nil nil nil 0)))
+                 '(30 20 10 15 10 2 nil nil nil)))
 
   ;; A time interval of 1 year and 6 months.
   (should (equal (iso8601-parse-duration "P1Y6M")
-                 '(0 0 0 0 6 1 nil nil nil 0)))
+                 '(0 0 0 0 6 1 nil nil nil)))
   (should (equal (iso8601-parse-duration "P0001-06")
-                 '(nil nil nil nil 6 1 nil nil nil nil)))
+                 '(nil nil nil nil 6 1 nil nil nil)))
 
   ;; A time interval of seventy-two hours.
   (should (equal (iso8601-parse-duration "PT72H")
-                 '(0 0 72 0 0 0 nil nil nil 0)))
+                 '(0 0 72 0 0 0 nil nil nil)))
 
   ;; Defined by start and duration
   ;; A time interval of 1 year, 2 months, 15 days and 12 hours,
   ;; beginning on 12 April 1985 at 20 minutes past 23 hours.
   (should (equal (iso8601-parse-interval "19850412T232000/P1Y2M15DT12H")
-                 '((0 20 23 12 4 1985 nil nil nil 0)
-                   (0 20 11 28 6 1986 nil nil nil 0)
-                   (0 0 12 15 2 1 nil nil nil 0))))
+                 '((0 20 23 12 4 1985 nil nil nil)
+                   (0 20 11 28 6 1986 nil nil nil)
+                   (0 0 12 15 2 1 nil nil nil))))
   (should (equal (iso8601-parse-interval "1985-04-12T23:20:00/P1Y2M15DT12H")
-                 '((0 20 23 12 4 1985 nil nil nil 0)
-                   (0 20 11 28 6 1986 nil nil nil 0)
-                   (0 0 12 15 2 1 nil nil nil 0))))
+                 '((0 20 23 12 4 1985 nil nil nil)
+                   (0 20 11 28 6 1986 nil nil nil)
+                   (0 0 12 15 2 1 nil nil nil))))
 
   ;; Defined by duration and end
   ;; A time interval of 1 year, 2 months, 15 days and 12 hours, ending
   ;; on 12 April 1985 at 20 minutes past 23 hour.
   (should (equal (iso8601-parse-interval "P1Y2M15DT12H/19850412T232000")
-                 '((0 20 11 28 1 1984 nil nil nil 0)
-                   (0 20 23 12 4 1985 nil nil nil 0)
-                   (0 0 12 15 2 1 nil nil nil 0)))))
+                 '((0 20 11 28 1 1984 nil nil nil)
+                   (0 20 23 12 4 1985 nil nil nil)
+                   (0 0 12 15 2 1 nil nil nil)))))
 
 ;;; iso8601-tests.el ends here
diff --git a/test/lisp/calendar/parse-time-tests.el b/test/lisp/calendar/parse-time-tests.el
index 61a3838a52..7435620b71 100644
--- a/test/lisp/calendar/parse-time-tests.el
+++ b/test/lisp/calendar/parse-time-tests.el
@@ -28,23 +28,23 @@
 
 (ert-deftest parse-time-tests ()
   (should (equal (parse-time-string "Mon, 22 Feb 2016 19:35:42 +0100")
-                 '(42 35 19 22 2 2016 1 -1 3600 0)))
+                 '(42 35 19 22 2 2016 1 -1 3600)))
   (should (equal (parse-time-string "22 Feb 2016 19:35:42 +0100")
-                 '(42 35 19 22 2 2016 nil -1 3600 0)))
+                 '(42 35 19 22 2 2016 nil -1 3600)))
   (should (equal (parse-time-string "22 Feb 2016 +0100")
-                 '(nil nil nil 22 2 2016 nil -1 3600 nil)))
+                 '(nil nil nil 22 2 2016 nil -1 3600)))
   (should (equal (parse-time-string "Mon, 22 Feb 16 19:35:42 +0100")
-                 '(42 35 19 22 2 2016 1 -1 3600 0)))
+                 '(42 35 19 22 2 2016 1 -1 3600)))
   (should (equal (parse-time-string "Mon, 22 February 2016 19:35:42 +0100")
-                 '(42 35 19 22 2 2016 1 -1 3600 0)))
+                 '(42 35 19 22 2 2016 1 -1 3600)))
   (should (equal (parse-time-string "Mon, 22 feb 2016 19:35:42 +0100")
-                 '(42 35 19 22 2 2016 1 -1 3600 0)))
+                 '(42 35 19 22 2 2016 1 -1 3600)))
   (should (equal (parse-time-string "Monday, 22 february 2016 19:35:42 +0100")
-                 '(42 35 19 22 2 2016 1 -1 3600 0)))
+                 '(42 35 19 22 2 2016 1 -1 3600)))
   (should (equal (parse-time-string "Monday, 22 february 2016 19:35:42 PST")
-                 '(42 35 19 22 2 2016 1 nil -28800 0)))
+                 '(42 35 19 22 2 2016 1 nil -28800)))
   (should (equal (parse-time-string "Friday, 21 Sep 2018 13:47:58 PDT")
-                 '(58 47 13 21 9 2018 5 t -25200 0)))
+                 '(58 47 13 21 9 2018 5 t -25200)))
   (should (equal (format-time-string
 		  "%Y-%m-%d %H:%M:%S"
 		  (parse-iso8601-time-string "1998-09-12T12:21:54-0200") t)
diff --git a/test/src/timefns-tests.el b/test/src/timefns-tests.el
index 362e7655a9..13ab7d83c3 100644
--- a/test/src/timefns-tests.el
+++ b/test/src/timefns-tests.el
@@ -40,25 +40,31 @@
 		    (7879679999900 . 100000)
 		    (78796799999999999999 . 1000000000000)))
       ;; UTC.
-     (let ((subsec (time-subtract (time-convert look t)
-				  (time-convert look 'integer))))
+     (let ((sec (time-add 59 (time-subtract (time-convert look t)
+                                            (time-convert look 'integer)))))
       (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)
-		     (list 59 59 23 30 6 1972 5 nil 0 subsec)))
+      (should (equal (decode-time look t 'integer)
+		     '(59 59 23 30 6 1972 5 nil 0)))
+      (should (equal (decode-time look t t)
+		     (list sec 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")
-		     (list 59 59 23 30 6 1972 5 nil 0 subsec)))
+      (should (equal (decode-time look "UTC0" 'integer)
+		     '(59 59 23 30 6 1972 5 nil 0)))
+      (should (equal (decode-time look "UTC0" t)
+		     (list sec 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"))
-		     (list 59 59 15 30 6 1972 5 nil -28800 subsec)))
+      (should (equal (decode-time look '(-28800 "PST") 'integer)
+		     '(59 59 15 30 6 1972 5 nil -28800)))
+      (should (equal (decode-time look '(-28800 "PST") t)
+		     (list sec 59 15 30 6 1972 5 nil -28800)))
       ;; Negative UTC offset, as a Lisp integer.
       (should (string-equal
 	       (format-time-string format look -28800)
@@ -67,14 +73,18 @@
 	       (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)
-		     (list 59 59 15 30 6 1972 5 nil -28800 subsec)))
+      (should (equal (decode-time look -28800 'integer)
+		     '(59 59 15 30 6 1972 5 nil -28800)))
+      (should (equal (decode-time look -28800 t)
+		     (list sec 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")
-		     (list 59 29 5 1 7 1972 6 nil 19800 subsec)))))))
+      (should (equal (decode-time look "IST-5:30" 'integer)
+		     '(59 29 5 1 7 1972 6 nil 19800)))
+      (should (equal (decode-time look "IST-5:30" t)
+		     (list sec 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
@@ -87,11 +97,13 @@
 			   (cons (1+ most-positive-fixnum) 1000000000000)
 			   (cons 1000000000000 (1+ most-positive-fixnum)))))
     (dolist (a time-values)
-      (let* ((d (ignore-errors (decode-time a t)))
+      (let* ((d (ignore-errors (decode-time a t t)))
+             (d-integer (ignore-errors (decode-time a t 'integer)))
 	     (e (if d (encode-time d)))
-	     (diff (float-time (time-subtract a e))))
-	(should (or (not d)
-		    (and (<= 0 diff) (< diff 1))))))))
+	     (e-integer (if d-integer (encode-time d-integer))))
+	(should (or (not d) (time-equal-p a e)))
+	(should (or (not d-integer) (time-equal-p (time-convert a 'integer)
+                                                  e-integer)))))))
 
 ;;; This should not dump core.
 (ert-deftest format-time-string-with-outlandish-zone ()
@@ -151,7 +163,7 @@ timefns-tests--have-leap-seconds
 (ert-deftest encode-time-dst-numeric-zone ()
     "Check for Bug#35502."
     (should (time-equal-p
-             (encode-time '(29 31 17 30 4 2019 2 t 7200 0))
+             (encode-time '(29 31 17 30 4 2019 2 t 7200))
              '(23752 27217))))
 
 (ert-deftest float-time-precision ()
-- 
2.17.1


  parent reply	other threads:[~2019-08-17  6:47 UTC|newest]

Thread overview: 45+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-07-29  9:48 Support for sub-second time in decoded time Lars Ingebrigtsen
2019-07-29 14:03 ` Stefan Monnier
2019-07-29 14:12   ` Lars Ingebrigtsen
2019-07-29 14:43     ` Stefan Monnier
2019-07-29 15:00       ` Lars Ingebrigtsen
2019-07-29 17:50         ` Stefan Monnier
2019-07-30 11:33           ` Lars Ingebrigtsen
2019-07-29 16:08     ` encode-time vs decode-time Stefan Monnier
2019-07-30 10:32       ` Lars Ingebrigtsen
2019-07-30 11:34         ` Andy Moreton
2019-07-30 11:37           ` Lars Ingebrigtsen
2019-07-30 17:54             ` Paul Eggert
2019-07-30 22:50               ` Paul Eggert
2019-07-31 19:03               ` Lars Ingebrigtsen
2019-07-31 19:31                 ` Stefan Monnier
2019-08-06  1:48                 ` Paul Eggert
2019-08-06 14:21                   ` Eli Zaretskii
2019-08-06 15:59                     ` Paul Eggert
2019-08-06 18:23                       ` Eli Zaretskii
2019-08-07  1:02                         ` Paul Eggert
2019-08-07  2:41                           ` Stefan Monnier
2019-08-07 14:47                             ` Eli Zaretskii
2019-08-11 23:39                               ` Lars Ingebrigtsen
2019-08-17  6:47                             ` Paul Eggert [this message]
2019-08-07 11:33                           ` Lars Ingebrigtsen
2019-08-17  7:54                             ` Paul Eggert
2019-08-17  8:16                               ` Eli Zaretskii
2019-08-17  9:33                                 ` Paul Eggert
2019-08-17 20:46                               ` Lars Ingebrigtsen
2019-08-17 20:56                                 ` Paul Eggert
2019-08-17 21:42                                   ` Stefan Monnier
2019-08-17 22:53                                     ` Paul Eggert
2019-08-19 21:12                                       ` Stefan Monnier
2019-08-21 10:55                                         ` Adam Porter
2019-08-21 20:20                                           ` Paul Eggert
2019-08-26 10:59                                             ` Adam Porter
2019-08-26 21:35                                               ` Paul Eggert
2019-08-07 14:44                           ` Eli Zaretskii
2019-08-07 11:41                   ` Lars Ingebrigtsen
2019-08-17  9:25                     ` Paul Eggert
2019-08-17 20:51                       ` Lars Ingebrigtsen
2019-07-29 14:23 ` Support for sub-second time in decoded time Eli Zaretskii
2019-07-29 14:59   ` Lars Ingebrigtsen
2019-07-29 16:46 ` Paul Eggert
2019-07-30 11:43   ` Lars Ingebrigtsen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=35b2a118-c1d8-7a2b-02f9-6dc446536739@cs.ucla.edu \
    --to=eggert@cs.ucla.edu \
    --cc=andrewjmoreton@gmail.com \
    --cc=eliz@gnu.org \
    --cc=emacs-devel@gnu.org \
    --cc=larsi@gnus.org \
    --cc=monnier@iro.umontreal.ca \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.