tempr 0.1.1 → 0.1.2

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.
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