forked from dm3/clojure.java-time
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinterval.clj
More file actions
148 lines (118 loc) · 5.03 KB
/
interval.clj
File metadata and controls
148 lines (118 loc) · 5.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
(ns java-time.interval
(:refer-clojure :exclude [contains?])
(:require [clojure.string :as string]
[java-time.util :as jt.u]
[java-time.core :as jt.c]
[java-time.temporal :as jt.t]
[java-time.amount :as jt.a])
(:import [java.time Instant Duration]))
(defprotocol ^:private AnyInterval
(seq-move-start-by [i os]
"Use `move-start-by` with vararags")
(seq-move-end-by [i os]
"Use `move-end-by` with vararags")
(move-start-to [i new-start]
"Moves the start instant of the interval to the given instant (or something
convertible to an instant):
(move-start-to (interval 0 10000) (instant 5000))
=> #<Interval ...:05Z/...:10Z>
Fails if the new start instant falls after the end instant:
(move-start-to (interval 0 10000) (millis 15000))
=> DateTimeException...")
(move-end-to [i new-end]
"Moves the end of the interval to the given instant (or something
convertible to an instant):
(move-end-to (interval 0 10000) (instant 15000))
=> #<Interval ...:00Z/...:15Z>
Fails if the new end instant falls before the start instant:
(move-end-to (interval 0 10000) (millis -1))
=> DateTimeException...")
(start [i] "Gets the start instant of the interval")
(end [i] "Gets the end instant of the interval")
(contains? [i o] "True if the interval contains the given instant or interval")
(overlaps? [i oi] "True if this interval overlaps the other one")
(abuts? [i oi] "True if this interval abut with the other one")
(overlap [i oi] "Gets the overlap between this interval and the other one or `nil`")
(gap [i oi] "Gets the gap between this interval and the other one or `nil`"))
;;;;;;;;;;;;; ReadableInterval
(jt.u/when-threeten-extra
(import [org.threeten.extra Interval])
(defn interval?
"True if `Interval`"
[o] (instance? Interval o))
(defn ^Interval interval
"Constructs an interval out of a string, start and end instants or a start
+ duration:
(j/interval \"2010-01-01T00:00:00Z/2013-01-01T00:00:00Z\")
=> #<Interval 2010-01-01T00:00:00Z/2013-01-01T00:00:00Z>
(j/interval (j/instant 100000) (j/instant 1000000))
=> #<Interval 1970-01-01T00:01:40Z/1970-01-01T00:16:40Z>
(j/interval (j/instant 100000) (j/duration 15 :minutes))
=> #<Interval 1970-01-01T00:01:40Z/1970-01-01T00:16:40Z>"
([^String o] (Interval/parse o))
([a b]
(cond (and (jt.t/instant? a) (jt.t/instant? b))
(Interval/of ^Instant a ^Instant b)
(jt.a/duration? b)
(Interval/of (jt.t/instant a) ^Duration b)
:else (Interval/of (jt.t/instant a) (jt.t/instant b)))))
(defn- with-start [^Interval i ^Instant s]
(.withStart i s))
(defn- with-end [^Interval i ^Instant e]
(.withEnd i e))
(extend-type Interval
AnyInterval
(seq-move-start-by [i os]
(let [^Instant s (jt.c/seq-plus (.getStart i) os)]
(with-start i s)))
(seq-move-end-by [i os]
(let [^Instant e (jt.c/seq-plus (.getEnd i) os)]
(with-end i e)))
(move-start-to [i new-start]
(with-start i (jt.t/instant new-start)))
(move-end-to [i new-end]
(with-end i (jt.t/instant new-end)))
(start [i] (.getStart i))
(end [i] (.getEnd i))
(contains? [i o] (if (interval? o)
(.encloses i ^Interval o)
(.contains i (jt.t/instant o))))
(overlaps? [i oi] (.overlaps i oi))
(abuts? [i oi] (.abuts i oi))
(overlap [self ^Interval i]
(when (overlaps? self i)
(interval (jt.c/max (start self) (start i))
(jt.c/min (end self) (end i)))))
(gap [self ^Interval i]
(cond (.isAfter (.getStart self) (.getEnd i))
(interval (.getEnd i) (.getStart self))
(.isBefore (.getEnd self) (.getStart i))
(interval (.getEnd self) (.getStart i))))
jt.c/Ordered
(single-before? [i o] (if (jt.t/instant? o)
(.isBefore (.getEnd i) o)
(.isBefore (.getEnd i) (.getStart ^Interval o))))
(single-after? [i o] (if (jt.t/instant? o)
(.isAfter (.getStart i) o)
(.isAfter (.getStart i) (.getEnd ^Interval o))))
jt.c/As
(as* [o k]
(jt.c/as (.toDuration o) k))))
(defn move-start-by
"Moves the start instant of the interval by the sum of given
periods/durations/numbers of milliseconds:
(move-start-by (interval 0 10000) (millis 1000) (seconds 1))
=> #<Interval ...:02Z/...:10Z>
Fails if the new start instant falls after the end instant.
(move-start-by (interval 0 10000) (millis 11000))
; => DateTimeException..."
[i & os] (seq-move-start-by i os))
(defn move-end-by
"Moves the end instant of the interval by the sum of given
periods/durations/numbers of milliseconds.
(move-start-by (interval 0 10000) (millis 1000) (seconds 1))
=> #<Interval ...:00Z/...:12Z>
Fails if the new end instant falls before the start instant.
(move-end-by (interval 0 10000) (millis -11000))
=> DateTimeException..."
[i & os] (seq-move-end-by i os))