time_frame 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +34 -18
- data/lib/time_frame/time_frame.rb +28 -28
- data/lib/time_frame/version.rb +1 -1
- data/spec/spec_helper.rb +2 -0
- data/spec/time_frame_spec.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f106979451ecad285f797d3da950839ab3f06af0
|
4
|
+
data.tar.gz: b1140e0f5bc73bbcf1ec5a8dd467057f7094b57c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d632b2b40b133b92c70c259def3d414980ffdf548bfdbf96ed1c767ef73097df4794273268c3455076d3e358ca97641826a6b6b7efd39e04b2f0ce4c3c5d049b
|
7
|
+
data.tar.gz: 088b62f79eb26489a6dfdd9d57bc39479f7cbc96e6b54f9b44012a501ef60f97246d695f52d2db7c66d9add7ee84bdb2abbd3f0ea9b20dc30af806c617f0689b
|
data/README.md
CHANGED
@@ -23,66 +23,82 @@ or just by specifying a `min` and `duration`
|
|
23
23
|
time_frame = TimeFrame.new(min: Time.now, duration: 1.day)
|
24
24
|
```
|
25
25
|
|
26
|
-
|
26
|
+
###Important:
|
27
|
+
TimeFrame doesn't support Date class.
|
27
28
|
|
28
|
-
|
29
|
-
# Using pp in some samples to beautify output:
|
30
|
-
require 'pp'
|
31
|
-
# => true
|
29
|
+
## Let's play around a bit...
|
32
30
|
|
33
|
-
|
31
|
+
Create a time frame instance from today with duration of 1 day
|
32
|
+
```ruby
|
34
33
|
time_frame = TimeFrame.new(min: Time.now, duration: 1.day)
|
35
34
|
# => 2014-05-07 14:58:47 +0200..2014-05-08 14:58:47 +0200
|
35
|
+
```
|
36
36
|
|
37
|
-
|
37
|
+
Get the duration
|
38
|
+
```ruby
|
38
39
|
time_frame.duration
|
39
40
|
# => 86400.0 seconds
|
41
|
+
```
|
40
42
|
|
41
|
-
|
43
|
+
Shift the whole time frame by... let's say... 2 days!
|
44
|
+
```ruby
|
42
45
|
later = time_frame.shift_by(2.days)
|
43
46
|
# => 2014-05-09 14:58:47 +0200..2014-05-10 14:58:47 +0200
|
47
|
+
```
|
44
48
|
|
45
|
-
|
49
|
+
Shifting can also be done in the other direction...
|
50
|
+
```ruby
|
46
51
|
earlier = time_frame.shift_by(-2.days)
|
47
52
|
# => 2014-05-05 14:58:47 +0200..2014-05-06 14:58:47 +0200
|
53
|
+
```
|
48
54
|
|
49
|
-
|
55
|
+
Is another time covered by our time frame?
|
56
|
+
```ruby
|
50
57
|
my_time = Time.new(2014, 5, 7, 16)
|
51
58
|
time_frame.cover?(my_time)
|
52
59
|
# => true
|
60
|
+
```
|
53
61
|
|
54
|
-
|
62
|
+
Shifting to another time... duration remains:
|
63
|
+
```ruby
|
55
64
|
time_frame.shift_to(Time.new(2016, 1, 1))
|
56
65
|
# => 2016-01-01 00:00:00 +0100..2016-01-02 00:00:00 +0100
|
66
|
+
```
|
57
67
|
|
58
|
-
|
68
|
+
Checking whether another time frame overlaps:
|
69
|
+
```ruby
|
59
70
|
other_frame = TimeFrame.new(
|
60
71
|
min: time_frame.min - 3.days,
|
61
72
|
max: time_frame.min + 40.minutes
|
62
73
|
)
|
63
74
|
time_frame.overlaps?(other_frame)
|
64
75
|
# => true
|
76
|
+
```
|
65
77
|
|
66
|
-
|
78
|
+
Time frame without another time frame:
|
79
|
+
```ruby
|
67
80
|
time_frame = TimeFrame.new(min: Time.new(2014, 5, 12), duration: 1.day)
|
68
81
|
other = TimeFrame.new(min: Time.new(2014, 5, 12, 19), duration: 10.minutes)
|
69
|
-
|
82
|
+
time_frame.without(other)
|
70
83
|
# [2014-05-12 00:00:00 +0200..2014-05-12 19:00:00 +0200,
|
71
84
|
# 2014-05-12 19:10:00 +0200..2014-05-13 00:00:00 +0200]
|
85
|
+
```
|
72
86
|
|
73
|
-
|
87
|
+
You can also use without with many TimeFrame's:
|
88
|
+
```ruby
|
74
89
|
another = other.shift_by(15.minutes)
|
75
|
-
|
90
|
+
time_frame.without(other, another)
|
76
91
|
# [2014-05-12 00:00:00 +0200..2014-05-12 19:00:00 +0200,
|
77
92
|
# 2014-05-12 19:10:00 +0200..2014-05-12 19:15:00 +0200,
|
78
93
|
# 2014-05-12 19:25:00 +0200..2014-05-13 00:00:00 +0200]
|
94
|
+
```
|
79
95
|
|
80
|
-
|
96
|
+
Use of the mathematical &. The intersection is returned:
|
97
|
+
```ruby
|
81
98
|
time_frame = TimeFrame.new(min: Time.new(2014), duration: 1.day)
|
82
99
|
other_time_frame = time_frame.shift_by(12.hours)
|
83
100
|
time_frame & other_time_frame
|
84
101
|
# => 2014-01-01 12:00:00 +0100..2014-01-02 00:00:00 +0100
|
85
|
-
|
86
102
|
```
|
87
103
|
|
88
104
|
These are the most common functionalities of the `TimeFrame` class, but there is quite more to discover. If you have an array of time frames, you can compute their union and pairwise intersection using `TimeFrame.union` and `TimeFrame.intersection`. For two sorted arrays of time frames, you can traverse all overlaps of time frames in the first array with time frames in the second array in **linear time** using `TimeFrame.each_overlap`.
|
@@ -11,20 +11,20 @@ class TimeFrame
|
|
11
11
|
EMPTY = Empty.instance
|
12
12
|
|
13
13
|
def initialize(args)
|
14
|
-
min = args.fetch(:min)
|
15
|
-
max = args.fetch(:max) { min + args.fetch(:duration) }
|
16
|
-
check_bounds
|
17
|
-
@
|
18
|
-
@
|
14
|
+
@min = args.fetch(:min)
|
15
|
+
@max = args.fetch(:max) { @min + args.fetch(:duration) }
|
16
|
+
check_bounds
|
17
|
+
@max_float = @max.to_f
|
18
|
+
@min_float = @min.to_f
|
19
19
|
end
|
20
20
|
|
21
21
|
def duration
|
22
|
-
(
|
22
|
+
@duration ||= (@max_float - @min_float)
|
23
23
|
end
|
24
24
|
|
25
25
|
def ==(other)
|
26
|
-
|
27
|
-
|
26
|
+
@min_float == other.min_float &&
|
27
|
+
@max_float == other.max_float
|
28
28
|
end
|
29
29
|
|
30
30
|
alias_method :eql?, :==
|
@@ -34,42 +34,44 @@ class TimeFrame
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def cover?(element)
|
37
|
-
if
|
38
|
-
element.empty? ||
|
37
|
+
if element.is_a?(TimeFrame)
|
38
|
+
element.empty? ||
|
39
|
+
@min_float <= element.min_float && element.max_float <= max_float
|
39
40
|
else
|
40
|
-
|
41
|
+
min_float <= element.to_f && element.to_f <= max_float
|
41
42
|
end
|
42
43
|
end
|
43
44
|
|
44
45
|
def before?(item)
|
45
46
|
case
|
46
|
-
when
|
47
|
+
when item.is_a?(TimeFrame)
|
47
48
|
fail_if_empty item
|
48
|
-
item.min >
|
49
|
+
item.min.to_f > max_float
|
49
50
|
else
|
50
|
-
item >
|
51
|
+
item.to_f > max_float
|
51
52
|
end
|
52
53
|
end
|
53
54
|
|
54
55
|
def after?(item)
|
55
56
|
case
|
56
|
-
when
|
57
|
+
when item.is_a?(TimeFrame)
|
57
58
|
fail_if_empty item
|
58
|
-
item.max <
|
59
|
+
item.max.to_f < min_float
|
59
60
|
else
|
60
|
-
item <
|
61
|
+
item.to_f < min_float
|
61
62
|
end
|
62
63
|
end
|
63
64
|
|
64
65
|
def time_between(item)
|
65
66
|
case
|
66
|
-
when
|
67
|
+
when item.is_a?(TimeFrame)
|
67
68
|
fail_if_empty item
|
68
69
|
[time_between(item.min), time_between(item.max)].min_by(&:abs)
|
69
70
|
when cover?(item)
|
70
71
|
0
|
71
72
|
else
|
72
|
-
|
73
|
+
float_value = item.to_f
|
74
|
+
[(float_value - min_float).abs, (float_value - max_float).abs].min
|
73
75
|
end
|
74
76
|
end
|
75
77
|
|
@@ -90,7 +92,7 @@ class TimeFrame
|
|
90
92
|
# Returns true if the interior intersect.
|
91
93
|
def overlaps?(other)
|
92
94
|
return false if other.duration == 0
|
93
|
-
other.
|
95
|
+
other.max_float > min_float && other.min_float < max_float
|
94
96
|
end
|
95
97
|
|
96
98
|
def &(other)
|
@@ -142,27 +144,25 @@ class TimeFrame
|
|
142
144
|
intersection = self & other
|
143
145
|
|
144
146
|
result = []
|
145
|
-
if intersection.
|
147
|
+
if intersection.min_float > min_float
|
146
148
|
result << TimeFrame.new(min: min, max: intersection.min)
|
147
149
|
end
|
148
|
-
if intersection.
|
150
|
+
if intersection.max_float < max_float
|
149
151
|
result << TimeFrame.new(min: intersection.max, max: max)
|
150
152
|
end
|
151
153
|
result
|
152
154
|
end
|
153
155
|
|
156
|
+
attr_reader :min_float, :max_float
|
157
|
+
|
154
158
|
private
|
155
159
|
|
156
160
|
def fail_if_empty(item)
|
157
|
-
fail ArgumentError, 'time frame is empty' if item.respond_to?(:empty) &&
|
161
|
+
fail ArgumentError, 'time frame is empty' if item.respond_to?(:empty?) &&
|
158
162
|
item.empty?
|
159
163
|
end
|
160
164
|
|
161
|
-
def
|
162
|
-
item.respond_to?(:min) && item.respond_to?(:max)
|
163
|
-
end
|
164
|
-
|
165
|
-
def check_bounds(max, min)
|
165
|
+
def check_bounds
|
166
166
|
fail ArgumentError, 'min is greater than max.' if min > max
|
167
167
|
end
|
168
168
|
end
|
data/lib/time_frame/version.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
data/spec/time_frame_spec.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: time_frame
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Patrick Derichs
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2014-10-
|
13
|
+
date: 2014-10-29 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rake
|