(defun timezone-time-from-absolute (date seconds)
"Compute the UTC time equivalent to DATE at time SECONDS after midnight.
-Return a list suitable as an argument to `current-time-zone',
+Return a Lisp timestamp suitable as an argument to `current-time-zone',
or nil if the date cannot be thus represented.
DATE is the number of days elapsed since the (imaginary)
Gregorian date Sunday, December 31, 1 BC."
(let* ((current-time-origin 719163)
;; (timezone-absolute-from-gregorian 1 1 1970)
(days (- date current-time-origin))
- (seconds-per-day (float 86400))
+ (seconds-per-day 86400)
(day-seconds (* days seconds-per-day)))
(condition-case nil (time-add day-seconds seconds)
(range-error))))
TIMEFORM_HI_LO_US, /* seconds plus microseconds (HI LO US) */
TIMEFORM_NIL, /* current time in nanoseconds */
TIMEFORM_HI_LO_US_PS, /* seconds plus micro and picoseconds (HI LO US PS) */
+ /* These two should be last; see timeform_sub_ps_p. */
TIMEFORM_FLOAT, /* time as a float */
TIMEFORM_TICKS_HZ /* fractional time: HI is ticks, LO is ticks per second */
};
+/* True if Lisp times of form FORM can express sub-picosecond timestamps. */
+static bool
+timeform_sub_ps_p (enum timeform form)
+{
+ return TIMEFORM_FLOAT <= form;
+}
+
/* From the valid form FORM and the time components HIGH, LOW, USEC
and PSEC, generate the corresponding time value. If LOW is
floating point, the other components should be zero and FORM should
/* Given Lisp operands A and B, add their values, and return the
result as a Lisp timestamp that is in (TICKS . HZ) form if either A
- or B are in that form, (HI LO US PS) form otherwise. Subtract
- instead of adding if SUBTRACT. */
+ or B are in that form or are floats, (HI LO US PS) form otherwise.
+ Subtract instead of adding if SUBTRACT. */
static Lisp_Object
time_arith (Lisp_Object a, Lisp_Object b, bool subtract)
{
otherwise the (HI LO US PS) form for backward compatibility. */
return (EQ (hz, make_fixnum (1))
? ticks
- : aform == TIMEFORM_TICKS_HZ || bform == TIMEFORM_TICKS_HZ
+ : timeform_sub_ps_p (aform) || timeform_sub_ps_p (bform)
? Fcons (ticks, hz)
: ticks_hz_list4 (ticks, hz));
}
(should (equal (timezone-zone-to-minute "*invalid*") 0)))
(ert-deftest timezone-tests-time-from-absolute ()
- (should (equal (timezone-time-from-absolute (* 2020 365) ; Jan 1 2020
- (* 12 60 60)) ; 12:00
- '(23911 48704 0 0))))
+ (should (time-equal-p
+ (timezone-time-from-absolute (* 2020 365) ; Jan 1 2020
+ (* 12 60 60)) ; 12:00
+ '(23911 48704 0 0))))
;; TODO: Write tests for timezone-tests-time-zone-from-absolute, which is a
;; bit tricky since the results depend on `current-time-zone'.
;; New (TICKS . HZ) format.
'(123456789 . 1000000000)))
(ert-info ((format "input: %s" input))
- (let ((result (mod-test-add-nanosecond input)))
+ (let ((result (mod-test-add-nanosecond input))
+ (desired-result
+ (let ((hz 1000000000))
+ (time-add (time-convert input hz) (cons 1 hz)))))
(should (consp result))
(should (integerp (car result)))
(should (integerp (cdr result)))
(should (cl-plusp (cdr result)))
- (should (time-equal-p result (time-add input '(0 0 0 1000))))))))
+ (should (time-equal-p result desired-result))))))
(ert-deftest mod-test-add-nanosecond/nil ()
(should (<= (float-time (mod-test-add-nanosecond nil))
(< 0.99 (/ (- (float-time a)) (float-time b))
1.01))))))))
+(ert-deftest time-rounding-tests ()
+ (should (time-equal-p 1e-13 (time-add 0 1e-13))))
+
(ert-deftest encode-time-dst-numeric-zone ()
"Check for Bug#35502."
(should (time-equal-p