|
706 | 706 | ;; Bound by given interval, last will become a remainder. |
707 | 707 | (map (juxt identity #(t/min (p/forward-duration % period) (t/end ival)))))) |
708 | 708 |
|
709 | | -(defn divide-by-divisor [ival divisor] |
710 | | - (divide-by-duration ival (cljc.java-time.duration/divided-by (t/duration ival) divisor))) |
| 709 | +(defn divide-by-divisor |
| 710 | + "Divides the interval specified by `ival` into `divisor` spaced |
| 711 | + intervals. The `divisor` must be a positive integer. The calculated |
| 712 | + subintervals are exact down to the nearest nanosecond." |
| 713 | + [ival divisor] |
| 714 | + (assert (pos? divisor)) |
| 715 | + (assert (integer? divisor)) |
| 716 | + (let [total-nanos (t/nanos (t/duration ival)) |
| 717 | + original-beginning (:tick/beginning ival)] |
| 718 | + ;; Note the algorithm here. We do not calculate a constant |
| 719 | + ;; duration for each sub-interval. That ends up truncating |
| 720 | + ;; fractional nanoseconds which can cause us problems with the |
| 721 | + ;; last interval if we just add the durations togther n |
| 722 | + ;; times. Instead, we calculate the total duration of the original |
| 723 | + ;; interval in nanoseconds and compute the ending point of each |
| 724 | + ;; subinterval as i/n * total duration. The duration of each |
| 725 | + ;; sub-interval may differ by plus/minus one nanosecond, but the |
| 726 | + ;; ending point is exactly the end of the original interval (i.e., |
| 727 | + ;; n/n * total duration = 1 * total duration = total duration). |
| 728 | + (loop [i 1 |
| 729 | + sub-intervals [] |
| 730 | + beginning original-beginning] |
| 731 | + (let [duration-to-end (t/new-duration (/ (* i total-nanos) divisor) :nanos) |
| 732 | + end (t/>> original-beginning duration-to-end)] |
| 733 | + (if (= i divisor) |
| 734 | + (clojure.core/conj sub-intervals [beginning end]) |
| 735 | + (recur (inc i) |
| 736 | + (clojure.core/conj sub-intervals [beginning end]) |
| 737 | + end)))))) |
711 | 738 |
|
712 | 739 | (defprotocol IDivisibleInterval |
713 | 740 | (divide-interval [divisor ival] "Divide an interval by a given divisor")) |
|
0 commit comments