-
Notifications
You must be signed in to change notification settings - Fork 153
/
bounds.go
120 lines (99 loc) · 2.67 KB
/
bounds.go
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
package plan
import (
"github.com/influxdata/flux"
"github.com/influxdata/flux/values"
)
// EmptyBounds is a time range containing only a single point
var EmptyBounds = &Bounds{
Start: values.Time(0),
Stop: values.Time(0),
}
// Bounds is a range of time
type Bounds struct {
Start values.Time
Stop values.Time
}
// BoundsAwareProcedureSpec is any procedure
// that modifies the time bounds of its data.
type BoundsAwareProcedureSpec interface {
TimeBounds(predecessorBounds *Bounds) *Bounds
}
// ComputeBounds computes the time bounds for a
// plan node from the bounds of its predecessors.
func ComputeBounds(node Node) error {
var bounds *Bounds
for _, pred := range node.Predecessors() {
if pred.Bounds() != nil && bounds == nil {
bounds = pred.Bounds()
}
if pred.Bounds() != nil && bounds != nil {
bounds = bounds.Union(pred.Bounds())
}
}
if s, ok := node.ProcedureSpec().(BoundsAwareProcedureSpec); ok {
bounds = s.TimeBounds(bounds)
}
node.SetBounds(bounds)
return nil
}
// IsEmpty reports whether the given bounds contain at most a single point
func (b *Bounds) IsEmpty() bool {
return b.Start >= b.Stop
}
// Contains reports whether a given time is contained within the time range
func (b *Bounds) Contains(t values.Time) bool {
return t >= b.Start && t < b.Stop
}
// Overlaps reports whether two given bounds have overlapping time ranges
func (b *Bounds) Overlaps(o *Bounds) bool {
return b.Contains(o.Start) ||
(b.Contains(o.Stop) && o.Stop > b.Start) ||
o.Contains(b.Start)
}
// Union returns the smallest bounds which contain both input bounds.
// It returns empty bounds if one of the input bounds are empty.
func (b *Bounds) Union(o *Bounds) *Bounds {
if b.IsEmpty() || o.IsEmpty() {
return EmptyBounds
}
u := new(Bounds)
u.Start = b.Start
if o.Start < b.Start {
u.Start = o.Start
}
u.Stop = b.Stop
if o.Stop > b.Stop {
u.Stop = o.Stop
}
return u
}
// Intersect returns the intersection of two bounds.
// It returns empty bounds if one of the input bounds are empty.
func (b *Bounds) Intersect(o *Bounds) *Bounds {
if b.IsEmpty() || o.IsEmpty() || !b.Overlaps(o) {
return EmptyBounds
}
i := new(Bounds)
i.Start = b.Start
if o.Start > b.Start {
i.Start = o.Start
}
i.Stop = b.Stop
if o.Stop < b.Stop {
i.Stop = o.Stop
}
return i
}
// Shift moves the start and stop values of a time range by a specified duration
func (b *Bounds) Shift(d values.Duration) *Bounds {
return &Bounds{
Start: b.Start.Add(d),
Stop: b.Stop.Add(d),
}
}
func FromFluxBounds(bounds flux.Bounds) Bounds {
return Bounds{
Start: values.ConvertTime(bounds.Start.Time(bounds.Now)),
Stop: values.ConvertTime(bounds.Stop.Time(bounds.Now)),
}
}