tempr 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.markdown CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.2 / 2012-02-19
4
+
5
+ - add `within?`, `subsume?`, `intersection_with`, `intersects?`
6
+
3
7
  ## 0.1.1 / 2012-02-18
4
8
 
5
9
  - add `SubRangeIterator#cover?` shortcut
@@ -473,11 +473,61 @@ module Tempr
473
473
  end
474
474
  end
475
475
 
476
+ # ---
477
+
478
+ # Set-like operations on two ranges
479
+
480
+ # true iff self.begin <= other.begin and self.end >= other.end
481
+ # (with accomodations for exclusive-end ranges)
482
+ def within?(other)
483
+ range_within_other?(self,other)
484
+ end
485
+
486
+ # true iff other.begin <= self.begin and other.end >= self.end
487
+ # (with accomodations for exclusive-end ranges)
488
+ def subsume?(other)
489
+ range_within_other?(other,self)
490
+ end
491
+
492
+ # the range intersection of self and other
493
+ # note: returns nil if no intersection
494
+ def intersection_with(other)
495
+ max_begin = [self.begin,other.begin].max
496
+ min_end = [self.end,other.end].min
497
+ excl = ( self.end == min_end &&
498
+ self.respond_to?(:exclude_end?) && self.exclude_end?
499
+ ) ||
500
+ ( other.end == min_end &&
501
+ other.respond_to?(:exclude_end?) && other.exclude_end?
502
+ )
503
+ unless max_begin > min_end
504
+ Range.new(max_begin, min_end, excl).extend(DateTimeRange)
505
+ end
506
+ end
507
+
508
+ # true iff there is a range intersection of self and other
509
+ def intersects?(other)
510
+ !!intersection_with(other)
511
+ end
512
+
513
+ # ---
514
+
476
515
  # convenience wrapper for SubRangeIterator.new(self) { ... }
477
516
  def build_subrange(&builder)
478
517
  SubRangeIterator.new(self, &builder)
479
518
  end
480
519
 
520
+ private
521
+
522
+ def range_within_other?(r1,r2)
523
+ if r2.respond_to?(:exclude_end?) && r2.exclude_end? &&
524
+ !(r1.respond_to?(:exclude_end?) && r1.exclude_end?)
525
+ r1.begin >= r2.begin && r1.end < r2.end
526
+ else
527
+ r1.begin >= r2.begin && r1.end <= r2.end
528
+ end
529
+ end
530
+
481
531
  # ---
482
532
 
483
533
  # Iterators are defined by
data/lib/tempr/version.rb CHANGED
@@ -3,7 +3,7 @@ module Tempr
3
3
  module Version
4
4
  MAJOR = 0
5
5
  MINOR = 1
6
- TINY = 1
6
+ TINY = 2
7
7
  STRING = "#{MAJOR}.#{MINOR}.#{TINY}"
8
8
  end
9
9
  end
@@ -0,0 +1,125 @@
1
+ require File.expand_path('test_helper', File.dirname(__FILE__))
2
+
3
+ module RangeIntersectionTests
4
+
5
+ Fixtures = [
6
+ {
7
+ :case => "inclusive ranges, other equals self",
8
+ :subject => (Date.civil(2012,2,13)..
9
+ Date.civil(2012,2,17)).extend(Tempr::DateTimeRange),
10
+ :other => Date.civil(2012,2,13)..Date.civil(2012,2,17),
11
+ :expected => Date.civil(2012,2,13)..Date.civil(2012,2,17)
12
+ },
13
+ {
14
+ :case => "inclusive ranges, other within self",
15
+ :subject => (Date.civil(2012,2,13)..
16
+ Date.civil(2012,2,17)).extend(Tempr::DateTimeRange),
17
+ :other => Date.civil(2012,2,13)..Date.civil(2012,2,16),
18
+ :expected => Date.civil(2012,2,13)..Date.civil(2012,2,16)
19
+ },
20
+ {
21
+ :case => "inclusive ranges, self within other",
22
+ :subject => (Date.civil(2012,2,13)..
23
+ Date.civil(2012,2,17)).extend(Tempr::DateTimeRange),
24
+ :other => Date.civil(2012,2,13)..Date.civil(2012,2,18),
25
+ :expected => Date.civil(2012,2,13)..Date.civil(2012,2,17)
26
+ },
27
+ {
28
+ :case => "inclusive ranges, self intersects but not within other",
29
+ :subject => (Date.civil(2012,2,13)..
30
+ Date.civil(2012,2,17)).extend(Tempr::DateTimeRange),
31
+ :other => Date.civil(2012,2,14)..Date.civil(2012,2,18),
32
+ :expected => Date.civil(2012,2,14)..Date.civil(2012,2,17)
33
+ },
34
+ {
35
+ :case => "inclusive ranges, self does not intersect other",
36
+ :subject => (Date.civil(2012,2,13)..
37
+ Date.civil(2012,2,17)).extend(Tempr::DateTimeRange),
38
+ :other => Date.civil(2012,2,18)..Date.civil(2012,2,19),
39
+ :expected => nil
40
+ },
41
+ {
42
+ :case => "exclusive ranges, same endpoint, both exclusive",
43
+ :subject => (Date.civil(2012,2,13)...
44
+ Date.civil(2012,2,17)).extend(Tempr::DateTimeRange),
45
+ :other => Date.civil(2012,2,13)...Date.civil(2012,2,17),
46
+ :expected => Date.civil(2012,2,13)...Date.civil(2012,2,17),
47
+ :exclusive => true
48
+ },
49
+ {
50
+ :case => "exclusive ranges, same endpoint, other is non-exclusive, self is exclusive",
51
+ :subject => (Date.civil(2012,2,13)...
52
+ Date.civil(2012,2,17)).extend(Tempr::DateTimeRange),
53
+ :other => Date.civil(2012,2,13)..Date.civil(2012,2,17),
54
+ :expected => Date.civil(2012,2,13)...Date.civil(2012,2,17),
55
+ :exclusive => true
56
+ },
57
+ {
58
+ :case => "exclusive ranges, same endpoint, other is exclusive, self is non-exclusive",
59
+ :subject => (Date.civil(2012,2,13)..
60
+ Date.civil(2012,2,17)).extend(Tempr::DateTimeRange),
61
+ :other => Date.civil(2012,2,13)...Date.civil(2012,2,17),
62
+ :expected => Date.civil(2012,2,13)...Date.civil(2012,2,17),
63
+ :exclusive => true
64
+ },
65
+ {
66
+ :case => "exclusive ranges, different endpoint, both exclusive",
67
+ :subject => (Date.civil(2012,2,13)...
68
+ Date.civil(2012,2,17)).extend(Tempr::DateTimeRange),
69
+ :other => Date.civil(2012,2,14)...Date.civil(2012,2,18),
70
+ :expected => Date.civil(2012,2,14)...Date.civil(2012,2,17),
71
+ :exclusive => true
72
+ },
73
+ {
74
+ :case => "exclusive ranges, different endpoint, other is non-exclusive, self is exclusive",
75
+ :subject => (Date.civil(2012,2,13)...
76
+ Date.civil(2012,2,17)).extend(Tempr::DateTimeRange),
77
+ :other => Date.civil(2012,2,12)..Date.civil(2012,2,16),
78
+ :expected => Date.civil(2012,2,13)..Date.civil(2012,2,16),
79
+ :exclusive => true
80
+ },
81
+ {
82
+ :case => "exclusive ranges, different endpoint, other is exclusive, self is non-exclusive",
83
+ :subject => (Date.civil(2012,2,13)..
84
+ Date.civil(2012,2,17)).extend(Tempr::DateTimeRange),
85
+ :other => Date.civil(2012,2,11)...Date.civil(2012,2,15),
86
+ :expected => Date.civil(2012,2,13)...Date.civil(2012,2,15),
87
+ :exclusive => true
88
+ }
89
+ ]
90
+
91
+
92
+
93
+ describe "DateTimeRange#intersection_with, date ranges" do
94
+
95
+ Fixtures.each do |fixture|
96
+
97
+ describe fixture[:case] do
98
+ let(:subject) { fixture[:subject] }
99
+ let(:other) { fixture[:other] }
100
+ let(:expected) { fixture[:expected] }
101
+
102
+ it 'should return expected range' do
103
+ actual = subject.intersection_with(other)
104
+ if expected.nil?
105
+ assert_nil actual
106
+ else
107
+ assert_equal expected.begin, actual.begin
108
+ assert_equal expected.end, actual.end
109
+ end
110
+ end
111
+
112
+ if fixture[:exclusive]
113
+ it 'should return expected exclusivity' do
114
+ actual = subject.intersection_with(other)
115
+ assert_equal expected.exclude_end?, actual.exclude_end?
116
+ end
117
+ end
118
+
119
+ end
120
+
121
+ end
122
+
123
+ end
124
+
125
+ end
@@ -0,0 +1,141 @@
1
+ require File.expand_path('test_helper', File.dirname(__FILE__))
2
+
3
+ module RangeWithinOtherTests
4
+
5
+ describe "DateTimeRange#within, non-exclusive date ranges" do
6
+
7
+ describe "other equals self" do
8
+ let(:subject) { (Date.civil(2012,2,13)..
9
+ Date.civil(2012,2,17)).extend(Tempr::DateTimeRange)
10
+ }
11
+ let(:other) { Date.civil(2012,2,13)..Date.civil(2012,2,17) }
12
+
13
+ it "within should return true" do
14
+ assert_equal true, subject.within?(other)
15
+ end
16
+
17
+ it "subsume should return true" do
18
+ assert_equal true, subject.subsume?(other)
19
+ end
20
+
21
+ end
22
+
23
+ describe "other within self" do
24
+ let(:subject) { (Date.civil(2012,2,13)..
25
+ Date.civil(2012,2,17)).extend(Tempr::DateTimeRange)
26
+ }
27
+ let(:other) { Date.civil(2012,2,13)..Date.civil(2012,2,16) }
28
+
29
+ it "within should return false" do
30
+ assert_equal false, subject.within?(other)
31
+ end
32
+
33
+ it "subsume should return true" do
34
+ assert_equal true, subject.subsume?(other)
35
+ end
36
+
37
+ end
38
+
39
+ describe "self within other" do
40
+ let(:subject) { (Date.civil(2012,2,13)..
41
+ Date.civil(2012,2,17)).extend(Tempr::DateTimeRange)
42
+ }
43
+ let(:other) { Date.civil(2012,2,13)..Date.civil(2012,2,18) }
44
+
45
+ it "within should return true" do
46
+ assert_equal true, subject.within?(other)
47
+ end
48
+
49
+ it "subsume should return false" do
50
+ assert_equal false, subject.subsume?(other)
51
+ end
52
+
53
+ end
54
+
55
+ describe "self intersects but not within other" do
56
+ let(:subject) { (Date.civil(2012,2,13)..
57
+ Date.civil(2012,2,17)).extend(Tempr::DateTimeRange)
58
+ }
59
+ let(:other) { Date.civil(2012,2,14)..Date.civil(2012,2,18) }
60
+
61
+ it "within should return false" do
62
+ assert_equal false, subject.within?(other)
63
+ end
64
+
65
+ it "subsume should return false" do
66
+ assert_equal false, subject.subsume?(other)
67
+ end
68
+
69
+ end
70
+
71
+ describe "self does not intersect other" do
72
+ let(:subject) { (Date.civil(2012,2,13)..
73
+ Date.civil(2012,2,17)).extend(Tempr::DateTimeRange)
74
+ }
75
+ let(:other) { Date.civil(2012,2,18)..Date.civil(2012,2,19) }
76
+
77
+ it "within should return false" do
78
+ assert_equal false, subject.within?(other)
79
+ end
80
+
81
+ it "subsume should return false" do
82
+ assert_equal false, subject.subsume?(other)
83
+ end
84
+
85
+ end
86
+
87
+ end
88
+
89
+ describe "DateTimeRange#within, exclusive date ranges" do
90
+
91
+ describe "same endpoint, both exclusive" do
92
+ let(:subject) { (Date.civil(2012,2,13)...
93
+ Date.civil(2012,2,17)).extend(Tempr::DateTimeRange)
94
+ }
95
+ let(:other) { Date.civil(2012,2,13)...Date.civil(2012,2,17) }
96
+
97
+ it "within should return true" do
98
+ assert_equal true, subject.within?(other)
99
+ end
100
+
101
+ it "subsume should return true" do
102
+ assert_equal true, subject.subsume?(other)
103
+ end
104
+
105
+ end
106
+
107
+ describe "same endpoint, other is non-exclusive, self is exclusive" do
108
+ let(:subject) { (Date.civil(2012,2,13)...
109
+ Date.civil(2012,2,17)).extend(Tempr::DateTimeRange)
110
+ }
111
+ let(:other) { Date.civil(2012,2,13)..Date.civil(2012,2,17) }
112
+
113
+ it "within should return true" do
114
+ assert_equal true, subject.within?(other)
115
+ end
116
+
117
+ it "subsume should return false" do
118
+ assert_equal false, subject.subsume?(other)
119
+ end
120
+
121
+ end
122
+
123
+ describe "same endpoint, other is exclusive, self is non-exclusive" do
124
+ let(:subject) { (Date.civil(2012,2,13)..
125
+ Date.civil(2012,2,17)).extend(Tempr::DateTimeRange)
126
+ }
127
+ let(:other) { Date.civil(2012,2,13)...Date.civil(2012,2,17) }
128
+
129
+ it "within should return false" do
130
+ assert_equal false, subject.within?(other)
131
+ end
132
+
133
+ it "subsume should return true" do
134
+ assert_equal true, subject.subsume?(other)
135
+ end
136
+
137
+ end
138
+
139
+ end
140
+
141
+ end
data/test/suite.rb CHANGED
@@ -1,3 +1,7 @@
1
- %w[ time_subrange each_time_of_day ].each do |test|
2
- require File.expand_path(test,File.dirname(__FILE__))
3
- end
1
+ %w[ time_subrange
2
+ each_time_of_day
3
+ range_within_other
4
+ range_intersection
5
+ ].each do |test|
6
+ require File.expand_path(test,File.dirname(__FILE__))
7
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tempr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2012-02-19 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: minitest
16
- requirement: &10703460 !ruby/object:Gem::Requirement
16
+ requirement: &9985020 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,7 +21,7 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *10703460
24
+ version_requirements: *9985020
25
25
  description: ''
26
26
  email:
27
27
  - ericgj72@gmail.com
@@ -37,6 +37,8 @@ files:
37
37
  - lib/tempr/date_time_range.rb
38
38
  - lib/tempr/version.rb
39
39
  - test/each_time_of_day.rb
40
+ - test/range_intersection.rb
41
+ - test/range_within_other.rb
40
42
  - test/suite.rb
41
43
  - test/test_helper.rb
42
44
  - test/time_subrange.rb