timeframe 0.2.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f5c448bfd96b67234ea8986d23f6c9f668ffacb9
4
+ data.tar.gz: 0b348d4217d82035a8247f6a23546ce223af3e3f
5
+ SHA512:
6
+ metadata.gz: c9fca9bff28ef6ea8cf6de692f79509a7200fe85efedc9c871f538c4e72402a329fc4e69d6737aa45064744b1bad35933c401920b3094a2de865c6d820fc4445
7
+ data.tar.gz: e65458296129a65a665f0cfd4357cd9fa34ee023613d4414887f951cc1199153542bf77c2d0c0ba1aa97c0c98006b19026efc71f3891a00d8450f4b86bdc4120
data/CHANGELOG CHANGED
@@ -1,3 +1,14 @@
1
+ 1.0.0 / 2017-06-22
2
+
3
+ * Breaking changes
4
+
5
+ * No more Array#multiple_timeframes_gaps_left_by (who knows what that was for)
6
+
7
+ * Enhancements
8
+
9
+ * Only uses active_support/core_ext/date
10
+ * Convert to rspec, modernize
11
+
1
12
  0.2.1 / 2012-04-24
2
13
 
3
14
  * Bug fixes
data/Gemfile CHANGED
@@ -1,9 +1,3 @@
1
1
  source :rubygems
2
2
 
3
3
  gemspec
4
-
5
- # development dependencies
6
- gem 'yard'
7
- gem 'rake'
8
- gem 'minitest'
9
- gem 'minitest-reporters'
data/Rakefile CHANGED
@@ -1,15 +1,6 @@
1
- #!/usr/bin/env rake
2
1
  require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
3
 
4
- require 'rake'
5
- require 'rake/testtask'
6
- Rake::TestTask.new(:test) do |test|
7
- test.libs << 'lib' << 'test'
8
- test.pattern = 'test/**/test_*.rb'
9
- test.verbose = true
10
- end
4
+ RSpec::Core::RakeTask.new(:spec)
11
5
 
12
- task :default => :test
13
-
14
- require 'yard'
15
- YARD::Rake::YardocTask.new
6
+ task :default => :spec
@@ -1,7 +1,7 @@
1
1
  require 'date'
2
2
  require 'multi_json'
3
- require 'active_support/version'
4
- require 'active_support/core_ext' if ActiveSupport::VERSION::MAJOR >= 3
3
+ require 'active_support'
4
+ require 'active_support/core_ext/date'
5
5
 
6
6
  require 'timeframe/iso_8601'
7
7
 
@@ -94,10 +94,23 @@ class Timeframe
94
94
  new *args
95
95
  end
96
96
 
97
+ def to_date(v)
98
+ case v
99
+ when NilClass
100
+ nil
101
+ when Date
102
+ v
103
+ when Time
104
+ v.to_date
105
+ else
106
+ Date.parse v
107
+ end
108
+ end
109
+
97
110
  private
98
111
 
99
112
  def make_dates(start_date, end_date)
100
- [start_date.to_date, end_date.to_date]
113
+ [to_date(start_date), to_date(end_date)]
101
114
  end
102
115
  end
103
116
 
@@ -131,8 +144,8 @@ class Timeframe
131
144
  end_date = Date.new(year+1, 1, 1)
132
145
  end
133
146
 
134
- start_date = args.shift.to_date if start_date.nil? and args.any?
135
- end_date = args.shift.to_date if end_date.nil? and args.any?
147
+ start_date ||= Timeframe.to_date(args[0])
148
+ end_date ||= Timeframe.to_date(args[1])
136
149
 
137
150
  raise ArgumentError, "Please supply a start and end date, `#{args.map(&:inspect).to_sentence}' is not enough" if start_date.nil? or end_date.nil?
138
151
  raise ArgumentError, "Start date #{start_date} should be earlier than end date #{end_date}" if start_date > end_date
@@ -160,7 +173,7 @@ class Timeframe
160
173
  when Date
161
174
  (start_date...end_date).include?(obj)
162
175
  when Time
163
- # (start_date...end_date).include?(obj.to_date)
176
+ # (start_date...end_date).include?(Date.parse(obj))
164
177
  raise "this wasn't previously supported, but it could be"
165
178
  when Timeframe
166
179
  start_date <= obj.start_date and end_date >= obj.end_date
@@ -275,7 +288,10 @@ class Timeframe
275
288
 
276
289
  # Returns the same Timeframe, only a year earlier
277
290
  def last_year
278
- self.class.new((start_date - 1.year), (end_date - 1.year))
291
+ self.class.new(
292
+ Date.new(start_date.year - 1, start_date.month, start_date.day),
293
+ Date.new(end_date.year - 1, end_date.month, end_date.day)
294
+ )
279
295
  end
280
296
 
281
297
  def as_json(*)
@@ -1,3 +1,3 @@
1
1
  class Timeframe
2
- VERSION = '0.2.1'
2
+ VERSION = '1.0.0'
3
3
  end
@@ -0,0 +1,4 @@
1
+ require 'timeframe'
2
+
3
+ RSpec.configure do |config|
4
+ end
@@ -0,0 +1,332 @@
1
+ require_relative 'spec_helper'
2
+
3
+ describe Timeframe do
4
+ describe 'initialization' do
5
+ it 'should create a timeframe using date strings' do
6
+ tf = Timeframe.new('2008-02-14', '2008-05-10')
7
+ expect(tf.from).to eq(Date.parse('2008-02-14'))
8
+ expect(tf.to).to eq(Date.parse('2008-05-10'))
9
+ end
10
+ it 'should create a timeframe using date objects' do
11
+ start = Date.parse('2008-02-14')
12
+ finish = Date.parse('2008-05-10')
13
+ tf = Timeframe.new(start, finish)
14
+ expect(tf.from).to eq(start)
15
+ expect(tf.to).to eq(finish)
16
+ end
17
+ it "should accept months" do
18
+ timeframe = Timeframe.new(:month => 1)
19
+ expect(timeframe.from).to eq(Date.today.change(:month => 1, :day => 1))
20
+ expect(timeframe.to).to eq(Date.today.change(:month => 2, :day => 1))
21
+ end
22
+ it "should accept month names" do
23
+ timeframe = Timeframe.new(:month => 'february')
24
+ expect(timeframe.from).to eq(Date.today.change(:month => 2, :day => 1))
25
+ expect(timeframe.to).to eq(Date.today.change(:month => 3, :day => 1))
26
+ end
27
+ it "should accept years" do
28
+ timeframe = Timeframe.new(:year => 2004)
29
+ expect(timeframe.from).to eq(Date.new(2004, 1, 1))
30
+ expect(timeframe.to).to eq(Date.new(2005, 1, 1))
31
+ end
32
+ it "should accept years and months" do
33
+ timeframe = Timeframe.new(:year => 2005, :month => 5)
34
+ expect(timeframe.from).to eq(Date.new(2005, 5, 1))
35
+ expect(timeframe.to).to eq(Date.new(2005, 6, 1))
36
+ end
37
+ it "should not accept just one date argument" do
38
+ expect {
39
+ Timeframe.new Date.new(2007, 2, 1)
40
+ }.to raise_error(ArgumentError, /supply/)
41
+ end
42
+ it "should not accept end date that is earlier than start date" do
43
+ expect {
44
+ timeframe = Timeframe.new Date.new(2008, 1, 1), Date.new(2007, 1, 1)
45
+ }.to raise_error(ArgumentError, /earlier/)
46
+ end
47
+ it "should always accept timeframes that cross year boundaries" do
48
+ timeframe = Timeframe.new Date.new(2007, 1, 1), Date.new(2008, 1, 2)
49
+ expect(timeframe.start_date).to eq(Date.new(2007, 1, 1))
50
+ end
51
+ end
52
+
53
+ describe '#inspect' do
54
+ it 'should return the time frame in readable text' do
55
+ start = Date.parse('2008-02-14')
56
+ finish = Date.parse('2008-05-10')
57
+ tf = Timeframe.new(start, finish)
58
+ expect(tf.inspect).to match(%r{<Timeframe\(-?\d+\) 86 days starting 2008-02-14 ending 2008-05-10>})
59
+ end
60
+ end
61
+
62
+ describe :constrained_new do
63
+ let(:start) { Date.parse('2008-02-14') }
64
+ let(:finish) { Date.parse('2008-05-10') }
65
+ let(:constraint_start) { Date.parse('2008-01-01') }
66
+ let(:constraint_finish) { Date.parse('2008-12-01') }
67
+ let(:constraint) { Timeframe.new(constraint_start, constraint_finish) }
68
+
69
+ it "should allow for constrained creation" do
70
+ constraint = Timeframe.new :year => 2008
71
+ may = Timeframe.new Date.new(2008,5,1), Date.new(2008,6,1)
72
+ january = Timeframe.new Date.new(2008,1,1), Date.new(2008,2,1)
73
+ expect(Timeframe.constrained_new(may.from, may.to, constraint)).to eq(may)
74
+ expect(Timeframe.constrained_new(Date.new(2007,1,1), Date.new(2010,1,1), constraint)).to eq(constraint)
75
+ expect(Timeframe.constrained_new(Date.new(2007,11,1), Date.new(2008,2,1), constraint)).to eq(january)
76
+ end
77
+ it 'should return a timeframe spanning start and end date if within constraint' do
78
+ tf = Timeframe.constrained_new(start, finish, constraint)
79
+ expect(tf.from).to eq(start)
80
+ expect(tf.to).to eq(finish)
81
+ end
82
+ it 'should return a timeframe spanning constraint start and end date if outside constraint' do
83
+ constraint = Timeframe.new(start, finish)
84
+ tf = Timeframe.constrained_new(constraint_start, constraint_finish, constraint)
85
+ expect(tf.from).to eq(start)
86
+ expect(tf.to).to eq(finish)
87
+ end
88
+ it 'should return a timeframe starting at constraint start' do
89
+ start = Date.parse('2008-01-01')
90
+ constraint_start = Date.parse('2008-01-14')
91
+ constraint = Timeframe.new(constraint_start, constraint_finish)
92
+ tf = Timeframe.constrained_new(start, finish, constraint)
93
+ expect(tf.from).to eq(constraint_start)
94
+ expect(tf.to).to eq(finish)
95
+ end
96
+ it 'should return a timeframe ending at constraint end' do
97
+ constraint_finish = Date.parse('2008-04-14')
98
+ constraint = Timeframe.new(constraint_start, constraint_finish)
99
+ tf = Timeframe.constrained_new(start, finish, constraint)
100
+ expect(tf.from).to eq(start)
101
+ expect(tf.to).to eq(constraint_finish)
102
+ end
103
+ it "should return a 0-length timeframe when constraining a timeframe by a disjoint timeframe" do
104
+ constraint = Timeframe.new :year => 2010
105
+ timeframe = Timeframe.constrained_new(
106
+ Date.new(2009,1,1), Date.new(2010,1,1), constraint)
107
+ expect(timeframe.days).to eq(0)
108
+ end
109
+ end
110
+
111
+ describe :this_year do
112
+ it "should return the current year" do
113
+ expect(Timeframe.this_year).to eq(Timeframe.new(:year => Time.now.year))
114
+ end
115
+ end
116
+
117
+ describe '#days' do
118
+ it "should return them number of days included" do
119
+ #TODO: make these separate "it" blocks, per best practices
120
+ expect(Timeframe.new(Date.new(2007, 1, 1), Date.new(2008, 1, 1)).days).to eq(365)
121
+ expect(Timeframe.new(Date.new(2008, 1, 1), Date.new(2009, 1, 1)).days).to eq(366) # leap year
122
+ expect(Timeframe.new(Date.new(2007, 11, 1), Date.new(2007, 12, 1)).days).to eq(30)
123
+ expect(Timeframe.new(Date.new(2007, 11, 1), Date.new(2008, 1, 1)).days).to eq(61)
124
+ expect(Timeframe.new(Date.new(2007, 2, 1), Date.new(2007, 3, 1)).days).to eq(28)
125
+ expect(Timeframe.new(Date.new(2008, 2, 1), Date.new(2008, 3, 1)).days).to eq(29)
126
+ expect(Timeframe.new(Date.new(2008, 2, 1), Date.new(2008, 2, 1)).days).to eq(0)
127
+ end
128
+ end
129
+
130
+ describe '#include?' do
131
+ it "should know if a certain date is included in the Timeframe" do
132
+ #TODO: make these separate "it" blocks, per best practices
133
+ timeframe = Timeframe.new :year => 2008, :month => 2
134
+ [
135
+ Date.new(2008, 2, 1),
136
+ Date.new(2008, 2, 5),
137
+ Date.new(2008, 2, 29)
138
+ ].each do |date|
139
+ expect(timeframe.include?(date)).to eq(true)
140
+ end
141
+ [
142
+ Date.new(2008, 1, 1),
143
+ Date.new(2007, 2, 1),
144
+ Date.new(2008, 3, 1)
145
+ ].each do |date|
146
+ expect(timeframe.include?(date)).to eq(false)
147
+ end
148
+ end
149
+ end
150
+
151
+ describe '#==' do
152
+ it "should be able to know if it's equal to another Timeframe object" do
153
+ expect(Timeframe.new(:year => 2007)).to eq(Timeframe.new(:year => 2007))
154
+ expect(Timeframe.new(:year => 2004, :month => 1)).to eq(Timeframe.new(:year => 2004, :month => 1))
155
+ end
156
+
157
+ it "should hash equal hash values when the timeframe is equal" do
158
+ expect(Timeframe.new(:year => 2007).hash).to eq(Timeframe.new(:year => 2007).hash)
159
+ expect(Timeframe.new(:year => 2004, :month => 1).hash).to eq(Timeframe.new(:year => 2004, :month => 1).hash)
160
+ end
161
+ end
162
+
163
+ describe '#months' do
164
+ it "should return an array of month-long subtimeframes" do
165
+ expect(Timeframe.new(:year => 2009).months.length).to eq(12)
166
+ end
167
+ end
168
+
169
+ describe '#year' do
170
+ it "should return the relevant year of a timeframe" do
171
+ expect(Timeframe.new(Date.new(2009, 2, 1), Date.new(2009, 4, 1)).year).to eq(Timeframe.new(:year => 2009))
172
+ end
173
+ it "should not return the relevant year of a timeframe if provided an inappropriate range" do
174
+ expect {
175
+ Timeframe.new(Date.new(2009, 1, 1), Date.new(2012, 1, 1)).year
176
+ }.to raise_error(ArgumentError, /dangerous during/)
177
+ end
178
+ end
179
+
180
+ describe '#&' do
181
+ it "should return its intersection with another timeframe" do
182
+ #TODO: make these separate "it" blocks, per best practices
183
+ expect(Timeframe.new(:month => 4) & Timeframe.new(:month => 6)).to be_nil
184
+ expect(Timeframe.new(:month => 4) & Timeframe.new(:month => 5)).to be_nil
185
+ expect((Timeframe.new(:month => 4) & Timeframe.new(:month => 4))).to eq(Timeframe.new(:month => 4))
186
+ expect((Timeframe.new(:year => Time.now.year) & Timeframe.new(:month => 4))).to eq(Timeframe.new(:month => 4))
187
+ expect((Timeframe.new(Date.new(2009, 2, 1), Date.new(2009, 6, 1)) & Timeframe.new(Date.new(2009, 4, 1), Date.new(2009, 8, 1)))).to eq(Timeframe.new(Date.new(2009, 4, 1), Date.new(2009, 6, 1)))
188
+ end
189
+ end
190
+
191
+ describe '#/' do
192
+ it "should return a fraction of another timeframe" do
193
+ expect(Timeframe.new(:month => 4, :year => 2009) / Timeframe.new(:year => 2009)).to eq(30.0 / 365.0)
194
+ end
195
+ end
196
+
197
+ describe '#gaps_left_by' do
198
+ it "should be able to ascertain gaps left by a list of other Timeframes" do
199
+ expect(Timeframe.new(:year => 2009).gaps_left_by(
200
+ Timeframe.new(:year => 2009, :month => 3),
201
+ Timeframe.new(:year => 2009, :month => 5),
202
+ Timeframe.new(Date.new(2009, 8, 1), Date.new(2009, 11, 1)),
203
+ Timeframe.new(Date.new(2009, 9, 1), Date.new(2009, 10, 1))
204
+ )).to eq(
205
+ [ Timeframe.new(Date.new(2009, 1, 1), Date.new(2009, 3, 1)),
206
+ Timeframe.new(Date.new(2009, 4, 1), Date.new(2009, 5, 1)),
207
+ Timeframe.new(Date.new(2009, 6, 1), Date.new(2009, 8, 1)),
208
+ Timeframe.new(Date.new(2009, 11, 1), Date.new(2010, 1, 1)) ])
209
+ end
210
+ end
211
+
212
+ describe '#covered_by?' do
213
+ it "should be able to ascertain gaps left by a list of other Timeframes" do
214
+ expect(Timeframe.new(:year => 2009).covered_by?(
215
+ Timeframe.new(:month => 1, :year => 2009),
216
+ Timeframe.new(Date.new(2009, 2, 1), Date.new(2010, 1, 1))
217
+ )).to eq(true)
218
+ end
219
+ end
220
+
221
+ describe '#last_year' do
222
+ it "should return its predecessor in a previous year" do
223
+ expect(Timeframe.this_year.last_year).to eq(Timeframe.new(Date.new(Date.today.year - 1, 1, 1), Date.new(Date.today.year, 1, 1)))
224
+ end
225
+ end
226
+
227
+ describe :parse do
228
+ describe 'ISO 8601 <start>/<end>' do
229
+ it 'works without time' do
230
+ expect(Timeframe.parse('2007-03-01/2008-05-11')).to eq(Timeframe.new(Date.new(2007, 3, 1), Date.new(2008, 5, 11)))
231
+ expect(Timeframe.parse('2007-03-01--2008-05-11')).to eq(Timeframe.new(Date.new(2007, 3, 1), Date.new(2008, 5, 11)))
232
+ end
233
+ it 'works with time' do
234
+ expect(Timeframe.parse('2007-03-01T13:00:00Z/2008-05-11T15:30:00Z')).to eq(Timeframe.new(Date.new(2007, 3, 1), Date.new(2008, 5, 11)))
235
+ expect(Timeframe.parse('2007-03-01T13:00:00Z--2008-05-11T15:30:00Z')).to eq(Timeframe.new(Date.new(2007, 3, 1), Date.new(2008, 5, 11)))
236
+ end
237
+ it 'takes shorthand' do
238
+ expect(Timeframe.parse('2007-11-13/15')).to eq(Timeframe.new(Date.new(2007, 11, 13), Date.new(2007, 11, 15))) # "2007-11-13/15", i.e. from any time on 2007-11-13 to any time on 2007-11-15
239
+ expect(Timeframe.parse("2008-02-15/03-14")).to eq(Timeframe.new(Date.new(2008, 2, 15), Date.new(2008, 3, 14))) # "2008-02-15/2008-03-14"
240
+ expect(Timeframe.parse("2007-12-14T13:30/15:30")).to eq(Timeframe.new(Date.new(2007, 12, 14), Date.new(2007, 12, 14))) # "2007-12-14T13:30/2007-12-14T15:30".. imprecise!
241
+ end
242
+ end
243
+
244
+ describe 'ISO 8601 <start>/<duration>' do
245
+ it 'works without time' do
246
+ expect(Timeframe.parse('2007-03-01/P1Y2M10DT2H30M')).to eq(Timeframe.new(Date.new(2007, 3, 1), Date.new(2008, 5, 11)))
247
+ expect(Timeframe.parse('2007-03-01--P1Y2M10DT2H30M')).to eq(Timeframe.new(Date.new(2007, 3, 1), Date.new(2008, 5, 11)))
248
+ end
249
+ it 'works with time' do
250
+ expect(Timeframe.parse('2007-03-01T13:00:00Z/P1Y2M10DT2H30M')).to eq(Timeframe.new(Date.new(2007, 3, 1), Date.new(2008, 5, 11)))
251
+ expect(Timeframe.parse('2007-03-01T13:00:00Z--P1Y2M10DT2H30M')).to eq(Timeframe.new(Date.new(2007, 3, 1), Date.new(2008, 5, 11)))
252
+ end
253
+ end
254
+
255
+ # note that 2008 was a leap year
256
+ describe 'ISO 8601 <duration>/<end>' do
257
+ it 'works with leap years' do
258
+ expect(Timeframe.parse('2007-02-28--P1Y')).to eq(Timeframe.new(Date.new(2007, 2, 28), Date.new(2008, 2, 29)))
259
+ expect(Timeframe.parse('P1Y--2008-02-29')).to eq(Timeframe.new(Date.new(2007, 3, 1), Date.new(2008, 2, 29)))
260
+ end
261
+ it 'works without time' do
262
+ expect(Timeframe.parse('P1Y2M10DT2H30M/2008-05-11')).to eq(Timeframe.new(Date.new(2007, 3, 2), Date.new(2008, 5, 11)))
263
+ expect(Timeframe.parse('P1Y2M10DT2H30M--2008-05-11')).to eq(Timeframe.new(Date.new(2007, 3, 2), Date.new(2008, 5, 11)))
264
+ end
265
+ it 'works with time' do
266
+ expect(Timeframe.parse('P1Y2M10DT2H30M/2008-05-11T15:30:00Z')).to eq(Timeframe.new(Date.new(2007, 3, 3), Date.new(2008, 5, 11)))
267
+ expect(Timeframe.parse('P1Y2M10DT2H30M--2008-05-11T15:30:00Z')).to eq(Timeframe.new(Date.new(2007, 3, 3), Date.new(2008, 5, 11)))
268
+ end
269
+ end
270
+
271
+ it 'understands plain year' do
272
+ plain_year = 2009
273
+ expect(Timeframe.parse(plain_year)).to eq(Timeframe.new(:year => plain_year))
274
+ expect(Timeframe.parse(plain_year.to_s)).to eq(Timeframe.new(:year => plain_year))
275
+ end
276
+ it 'understands JSON' do
277
+ json =<<-EOS
278
+ "2009-05-01/2009-06-01"
279
+ EOS
280
+ expect(Timeframe.parse(json)).to eq(Timeframe.new(:year => 2009, :month => 5))
281
+ end
282
+ it 'understands a particular style of Ruby hash we used to emit (deprecated)' do
283
+ hsh = { :startDate => '2009-05-01', :endDate => '2009-06-01' }
284
+ expect(Timeframe.parse(hsh)).to eq(Timeframe.new(:year => 2009, :month => 5))
285
+ expect(Timeframe.parse(hsh.stringify_keys)).to eq(Timeframe.new(:year => 2009, :month => 5))
286
+ end
287
+ end
288
+
289
+ describe '#as_json' do
290
+ it 'should generate JSON (test fails on ruby 1.8)' do
291
+ expect(Timeframe.new(:year => 2009).as_json).to eq(%{2009-01-01/2010-01-01})
292
+ expect(MultiJson.dump(Timeframe.new(:year => 2009))).to eq(Timeframe.new(:year => 2009).as_json.inspect)
293
+ end
294
+ it 'understands its own JSON' do
295
+ t = Timeframe.new(:year => 2009, :month => 5)
296
+ expect(Timeframe.from_json(MultiJson.dump(t))).to eq(t)
297
+ end
298
+ end
299
+
300
+ describe '#to_param' do
301
+ it 'should generate a URL-friendly parameter' do
302
+ expect(Timeframe.new(:year => 2009).to_param).to eq("2009-01-01/2010-01-01")
303
+ end
304
+ it 'understands its own #to_param' do
305
+ t = Timeframe.new(:year => 2009, :month => 5)
306
+ expect(Timeframe.parse(t.to_param)).to eq(t)
307
+ end
308
+ end
309
+
310
+ describe '#to_s' do
311
+ it 'should not only look at month numbers when describing multi-year timeframes' do
312
+ expect(Timeframe.new(Date.parse('2008-01-01'), Date.parse('2010-01-01')).to_s).to eq("2008-01-01/2010-01-01")
313
+ end
314
+ end
315
+
316
+ describe '#dates' do
317
+ it "should enumerate all dates between start and end" do
318
+ dates = Timeframe.new(:year => 2008).dates
319
+ expect(dates.min).to eq(Date.new(2008,1,1))
320
+ expect(dates.max).to eq(Date.new(2008,12,31))
321
+ expect(dates.uniq.length).to eq(366)
322
+ expect(dates.select { |d| d.month == 2 }.length).to eq(29)
323
+ end
324
+ end
325
+
326
+ describe '#first_days_of_months' do
327
+ it "should enumerate all the first days of included months" do
328
+ dates = Timeframe.parse('2011-05-01/2012-02-01').first_days_of_months
329
+ expect(dates).to eq([Date.new(2011,5,1), Date.new(2011,6,1), Date.new(2011,7,1), Date.new(2011,8,1), Date.new(2011,9,1), Date.new(2011,10,1), Date.new(2011,11,1), Date.new(2011,12,1), Date.new(2012,1,1)])
330
+ end
331
+ end
332
+ end
@@ -21,5 +21,8 @@ Gem::Specification.new do |s|
21
21
 
22
22
  s.add_runtime_dependency 'activesupport', '>=2.3.5'
23
23
  s.add_runtime_dependency 'i18n'
24
- s.add_runtime_dependency 'multi_json'
24
+
25
+ s.add_development_dependency "bundler"
26
+ s.add_development_dependency "rake"
27
+ s.add_development_dependency "rspec"
25
28
  end
metadata CHANGED
@@ -1,8 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: timeframe
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
5
- prerelease:
4
+ version: 1.0.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Andy Rossmeissl
@@ -11,54 +10,76 @@ authors:
11
10
  autorequire:
12
11
  bindir: bin
13
12
  cert_chain: []
14
- date: 2012-04-24 00:00:00.000000000 Z
13
+ date: 2017-06-22 00:00:00.000000000 Z
15
14
  dependencies:
16
15
  - !ruby/object:Gem::Dependency
17
16
  name: activesupport
18
17
  requirement: !ruby/object:Gem::Requirement
19
- none: false
20
18
  requirements:
21
- - - ! '>='
19
+ - - ">="
22
20
  - !ruby/object:Gem::Version
23
21
  version: 2.3.5
24
22
  type: :runtime
25
23
  prerelease: false
26
24
  version_requirements: !ruby/object:Gem::Requirement
27
- none: false
28
25
  requirements:
29
- - - ! '>='
26
+ - - ">="
30
27
  - !ruby/object:Gem::Version
31
28
  version: 2.3.5
32
29
  - !ruby/object:Gem::Dependency
33
30
  name: i18n
34
31
  requirement: !ruby/object:Gem::Requirement
35
- none: false
36
32
  requirements:
37
- - - ! '>='
33
+ - - ">="
38
34
  - !ruby/object:Gem::Version
39
35
  version: '0'
40
36
  type: :runtime
41
37
  prerelease: false
42
38
  version_requirements: !ruby/object:Gem::Requirement
43
- none: false
44
39
  requirements:
45
- - - ! '>='
40
+ - - ">="
46
41
  - !ruby/object:Gem::Version
47
42
  version: '0'
48
43
  - !ruby/object:Gem::Dependency
49
- name: multi_json
44
+ name: bundler
50
45
  requirement: !ruby/object:Gem::Requirement
51
- none: false
52
46
  requirements:
53
- - - ! '>='
47
+ - - ">="
54
48
  - !ruby/object:Gem::Version
55
49
  version: '0'
56
- type: :runtime
50
+ type: :development
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ - !ruby/object:Gem::Dependency
58
+ name: rake
59
+ requirement: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ type: :development
65
+ prerelease: false
66
+ version_requirements: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ - !ruby/object:Gem::Dependency
72
+ name: rspec
73
+ requirement: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ type: :development
57
79
  prerelease: false
58
80
  version_requirements: !ruby/object:Gem::Requirement
59
- none: false
60
81
  requirements:
61
- - - ! '>='
82
+ - - ">="
62
83
  - !ruby/object:Gem::Version
63
84
  version: '0'
64
85
  description: A Ruby class for describing and interacting with timeframes.
@@ -68,44 +89,41 @@ executables: []
68
89
  extensions: []
69
90
  extra_rdoc_files: []
70
91
  files:
71
- - .gitignore
92
+ - ".gitignore"
72
93
  - CHANGELOG
73
94
  - Gemfile
74
95
  - LICENSE
75
96
  - README.markdown
76
97
  - Rakefile
77
98
  - lib/timeframe.rb
78
- - lib/timeframe/core_ext/array.rb
79
99
  - lib/timeframe/iso_8601.rb
80
100
  - lib/timeframe/version.rb
81
- - test/helper.rb
82
- - test/test_timeframe.rb
101
+ - spec/spec_helper.rb
102
+ - spec/timeframe_spec.rb
83
103
  - timeframe.gemspec
84
104
  homepage: http://github.com/rossmeissl/timeframe
85
105
  licenses: []
106
+ metadata: {}
86
107
  post_install_message:
87
108
  rdoc_options: []
88
109
  require_paths:
89
110
  - lib
90
111
  required_ruby_version: !ruby/object:Gem::Requirement
91
- none: false
92
112
  requirements:
93
- - - ! '>='
113
+ - - ">="
94
114
  - !ruby/object:Gem::Version
95
115
  version: '0'
96
116
  required_rubygems_version: !ruby/object:Gem::Requirement
97
- none: false
98
117
  requirements:
99
- - - ! '>='
118
+ - - ">="
100
119
  - !ruby/object:Gem::Version
101
120
  version: '0'
102
121
  requirements: []
103
122
  rubyforge_project: timeframe
104
- rubygems_version: 1.8.21
123
+ rubygems_version: 2.6.8
105
124
  signing_key:
106
- specification_version: 3
125
+ specification_version: 4
107
126
  summary: Date intervals
108
127
  test_files:
109
- - test/helper.rb
110
- - test/test_timeframe.rb
111
- has_rdoc:
128
+ - spec/spec_helper.rb
129
+ - spec/timeframe_spec.rb
@@ -1,9 +0,0 @@
1
- class Array
2
- # Constructs an array of timeframes representing the "gaps" left by the given array of timeframes.
3
- #
4
- # To use this feature, you must explicitly require 'timeframe/core_ext/array'
5
- def multiple_timeframes_gaps_left_by(*time_frames)
6
- raise ArgumentError.new 'You can only use timeframe for this operation' unless [self + time_frames].flatten.all?{|el| el.is_a?(Timeframe)}
7
- self.inject([]){|a,b| a << b.gaps_left_by(*time_frames)}.flatten
8
- end
9
- end
@@ -1,11 +0,0 @@
1
- require 'rubygems'
2
- require 'bundler/setup'
3
-
4
- require 'minitest/spec'
5
- require 'minitest/autorun'
6
- require 'minitest/reporters'
7
- MiniTest::Unit.runner = MiniTest::SuiteRunner.new
8
- MiniTest::Unit.runner.reporters << MiniTest::Reporters::SpecReporter.new
9
-
10
- require 'timeframe'
11
- require 'timeframe/core_ext/array'
@@ -1,354 +0,0 @@
1
- require 'helper'
2
-
3
- describe Timeframe do
4
- describe 'initialization' do
5
- it 'should create a timeframe using date strings' do
6
- tf = Timeframe.new('2008-02-14', '2008-05-10')
7
- tf.from.must_equal Date.parse('2008-02-14')
8
- tf.to.must_equal Date.parse('2008-05-10')
9
- end
10
- it 'should create a timeframe using date objects' do
11
- start = Date.parse('2008-02-14')
12
- finish = Date.parse('2008-05-10')
13
- tf = Timeframe.new(start, finish)
14
- tf.from.must_equal start
15
- tf.to.must_equal finish
16
- end
17
- it "should accept months" do
18
- timeframe = Timeframe.new(:month => 1)
19
- timeframe.from.must_equal Date.today.change(:month => 1, :day => 1)
20
- timeframe.to.must_equal Date.today.change(:month => 2, :day => 1)
21
- end
22
- it "should accept month names" do
23
- timeframe = Timeframe.new(:month => 'february')
24
- timeframe.from.must_equal Date.today.change(:month => 2, :day => 1)
25
- timeframe.to.must_equal Date.today.change(:month => 3, :day => 1)
26
- end
27
- it "should accept years" do
28
- timeframe = Timeframe.new(:year => 2004)
29
- timeframe.from.must_equal Date.new(2004, 1, 1)
30
- timeframe.to.must_equal Date.new(2005, 1, 1)
31
- end
32
- it "should accept years and months" do
33
- timeframe = Timeframe.new(:year => 2005, :month => 5)
34
- timeframe.from.must_equal Date.new(2005, 5, 1)
35
- timeframe.to.must_equal Date.new(2005, 6, 1)
36
- end
37
- it "should not accept just one date argument" do
38
- lambda {
39
- Timeframe.new Date.new(2007, 2, 1)
40
- }.must_raise(ArgumentError, /supply/)
41
- end
42
- it "should not accept end date that is earlier than start date" do
43
- lambda {
44
- timeframe = Timeframe.new Date.new(2008, 1, 1), Date.new(2007, 1, 1)
45
- }.must_raise(ArgumentError, /earlier/)
46
- end
47
- it "should always accept timeframes that cross year boundaries" do
48
- timeframe = Timeframe.new Date.new(2007, 1, 1), Date.new(2008, 1, 2)
49
- timeframe.start_date.must_equal Date.new(2007, 1, 1)
50
- end
51
- end
52
-
53
- describe '#inspect' do
54
- it 'should return the time frame in readable text' do
55
- start = Date.parse('2008-02-14')
56
- finish = Date.parse('2008-05-10')
57
- tf = Timeframe.new(start, finish)
58
- tf.inspect.must_match %r{<Timeframe\(-?\d+\) 86 days starting 2008-02-14 ending 2008-05-10>}
59
- end
60
- end
61
-
62
- describe :constrained_new do
63
- let(:start) { Date.parse('2008-02-14') }
64
- let(:finish) { Date.parse('2008-05-10') }
65
- let(:constraint_start) { Date.parse('2008-01-01') }
66
- let(:constraint_finish) { Date.parse('2008-12-01') }
67
- let(:constraint) { Timeframe.new(constraint_start, constraint_finish) }
68
-
69
- it "should allow for constrained creation" do
70
- constraint = Timeframe.new :year => 2008
71
- may = Timeframe.new Date.new(2008,5,1), Date.new(2008,6,1)
72
- january = Timeframe.new Date.new(2008,1,1), Date.new(2008,2,1)
73
- Timeframe.constrained_new(may.from, may.to, constraint).must_equal may
74
- Timeframe.constrained_new(Date.new(2007,1,1), Date.new(2010,1,1), constraint).must_equal constraint
75
- Timeframe.constrained_new(Date.new(2007,11,1), Date.new(2008,2,1), constraint).must_equal january
76
- end
77
- it 'should return a timeframe spanning start and end date if within constraint' do
78
- tf = Timeframe.constrained_new(start, finish, constraint)
79
- tf.from.must_equal start
80
- tf.to.must_equal finish
81
- end
82
- it 'should return a timeframe spanning constraint start and end date if outside constraint' do
83
- constraint = Timeframe.new(start, finish)
84
- tf = Timeframe.constrained_new(constraint_start, constraint_finish, constraint)
85
- tf.from.must_equal start
86
- tf.to.must_equal finish
87
- end
88
- it 'should return a timeframe starting at constraint start' do
89
- start = Date.parse('2008-01-01')
90
- constraint_start = Date.parse('2008-01-14')
91
- constraint = Timeframe.new(constraint_start, constraint_finish)
92
- tf = Timeframe.constrained_new(start, finish, constraint)
93
- tf.from.must_equal constraint_start
94
- tf.to.must_equal finish
95
- end
96
- it 'should return a timeframe ending at constraint end' do
97
- constraint_finish = Date.parse('2008-04-14')
98
- constraint = Timeframe.new(constraint_start, constraint_finish)
99
- tf = Timeframe.constrained_new(start, finish, constraint)
100
- tf.from.must_equal start
101
- tf.to.must_equal constraint_finish
102
- end
103
- it "should return a 0-length timeframe when constraining a timeframe by a disjoint timeframe" do
104
- constraint = Timeframe.new :year => 2010
105
- timeframe = Timeframe.constrained_new(
106
- Date.new(2009,1,1), Date.new(2010,1,1), constraint)
107
- timeframe.days.must_equal 0
108
- end
109
- end
110
-
111
- describe :this_year do
112
- it "should return the current year" do
113
- Timeframe.this_year.must_equal Timeframe.new(:year => Time.now.year)
114
- end
115
- end
116
-
117
- describe '#days' do
118
- it "should return them number of days included" do
119
- #TODO: make these separate "it" blocks, per best practices
120
- Timeframe.new(Date.new(2007, 1, 1), Date.new(2008, 1, 1)).days.must_equal 365
121
- Timeframe.new(Date.new(2008, 1, 1), Date.new(2009, 1, 1)).days.must_equal 366 #leap year
122
- Timeframe.new(Date.new(2007, 11, 1), Date.new(2007, 12, 1)).days.must_equal 30
123
- Timeframe.new(Date.new(2007, 11, 1), Date.new(2008, 1, 1)).days.must_equal 61
124
- Timeframe.new(Date.new(2007, 2, 1), Date.new(2007, 3, 1)).days.must_equal 28
125
- Timeframe.new(Date.new(2008, 2, 1), Date.new(2008, 3, 1)).days.must_equal 29
126
- Timeframe.new(Date.new(2008, 2, 1), Date.new(2008, 2, 1)).days.must_equal 0
127
- end
128
- end
129
-
130
- describe '#include?' do
131
- it "should know if a certain date is included in the Timeframe" do
132
- #TODO: make these separate "it" blocks, per best practices
133
- timeframe = Timeframe.new :year => 2008, :month => 2
134
- [
135
- Date.new(2008, 2, 1),
136
- Date.new(2008, 2, 5),
137
- Date.new(2008, 2, 29)
138
- ].each do |date|
139
- timeframe.include?(date).must_equal true
140
- end
141
- [
142
- Date.new(2008, 1, 1),
143
- Date.new(2007, 2, 1),
144
- Date.new(2008, 3, 1)
145
- ].each do |date|
146
- timeframe.include?(date).must_equal false
147
- end
148
- end
149
- end
150
-
151
- describe '#==' do
152
- it "should be able to know if it's equal to another Timeframe object" do
153
- Timeframe.new(:year => 2007).must_equal Timeframe.new(:year => 2007)
154
- Timeframe.new(:year => 2004, :month => 1).must_equal Timeframe.new(:year => 2004, :month => 1)
155
- end
156
-
157
- it "should hash equal hash values when the timeframe is equal" do
158
- Timeframe.new(:year => 2007).hash.must_equal Timeframe.new(:year => 2007).hash
159
- Timeframe.new(:year => 2004, :month => 1).hash.must_equal Timeframe.new(:year => 2004, :month => 1).hash
160
- end
161
- end
162
-
163
- describe '#months' do
164
- it "should return an array of month-long subtimeframes" do
165
- Timeframe.new(:year => 2009).months.length.must_equal 12
166
- end
167
- end
168
-
169
- describe '#year' do
170
- it "should return the relevant year of a timeframe" do
171
- Timeframe.new(Date.new(2009, 2, 1), Date.new(2009, 4, 1)).year.must_equal Timeframe.new(:year => 2009)
172
- end
173
- it "should not return the relevant year of a timeframe if provided an inappropriate range" do
174
- lambda {
175
- Timeframe.new(Date.new(2009, 1, 1), Date.new(2012, 1, 1)).year
176
- }.must_raise(ArgumentError, /dangerous during/)
177
- end
178
- end
179
-
180
- describe '#&' do
181
- it "should return its intersection with another timeframe" do
182
- #TODO: make these separate "it" blocks, per best practices
183
- (Timeframe.new(:month => 4) & Timeframe.new(:month => 6)).must_be_nil
184
- (Timeframe.new(:month => 4) & Timeframe.new(:month => 5)).must_be_nil
185
- (Timeframe.new(:month => 4) & Timeframe.new(:month => 4)).must_equal Timeframe.new(:month => 4)
186
- (Timeframe.new(:year => Time.now.year) & Timeframe.new(:month => 4)).must_equal Timeframe.new(:month => 4)
187
- (Timeframe.new(Date.new(2009, 2, 1), Date.new(2009, 6, 1)) & Timeframe.new(Date.new(2009, 4, 1), Date.new(2009, 8, 1))).must_equal Timeframe.new(Date.new(2009, 4, 1), Date.new(2009, 6, 1))
188
- end
189
- end
190
-
191
- describe '#/' do
192
- it "should return a fraction of another timeframe" do
193
- (Timeframe.new(:month => 4, :year => 2009) / Timeframe.new(:year => 2009)).must_equal(30.0 / 365.0)
194
- end
195
- end
196
-
197
- describe '#gaps_left_by' do
198
- it "should be able to ascertain gaps left by a list of other Timeframes" do
199
- Timeframe.new(:year => 2009).gaps_left_by(
200
- Timeframe.new(:year => 2009, :month => 3),
201
- Timeframe.new(:year => 2009, :month => 5),
202
- Timeframe.new(Date.new(2009, 8, 1), Date.new(2009, 11, 1)),
203
- Timeframe.new(Date.new(2009, 9, 1), Date.new(2009, 10, 1))
204
- ).must_equal(
205
- [ Timeframe.new(Date.new(2009, 1, 1), Date.new(2009, 3, 1)),
206
- Timeframe.new(Date.new(2009, 4, 1), Date.new(2009, 5, 1)),
207
- Timeframe.new(Date.new(2009, 6, 1), Date.new(2009, 8, 1)),
208
- Timeframe.new(Date.new(2009, 11, 1), Date.new(2010, 1, 1)) ])
209
- end
210
- end
211
-
212
- describe '#covered_by?' do
213
- it "should be able to ascertain gaps left by a list of other Timeframes" do
214
- Timeframe.new(:year => 2009).covered_by?(
215
- Timeframe.new(:month => 1, :year => 2009),
216
- Timeframe.new(Date.new(2009, 2, 1), Date.new(2010, 1, 1))
217
- ).must_equal(true)
218
- end
219
- end
220
-
221
- describe '#last_year' do
222
- it "should return its predecessor in a previous year" do
223
- Timeframe.this_year.last_year.must_equal Timeframe.new(Date.new(Date.today.year - 1, 1, 1), Date.new(Date.today.year, 1, 1))
224
- end
225
- end
226
-
227
- describe :parse do
228
- describe 'ISO 8601 <start>/<end>' do
229
- it 'works without time' do
230
- Timeframe.parse('2007-03-01/2008-05-11').must_equal Timeframe.new(Date.new(2007, 3, 1), Date.new(2008, 5, 11))
231
- Timeframe.parse('2007-03-01--2008-05-11').must_equal Timeframe.new(Date.new(2007, 3, 1), Date.new(2008, 5, 11))
232
- end
233
- it 'works with time' do
234
- Timeframe.parse('2007-03-01T13:00:00Z/2008-05-11T15:30:00Z').must_equal Timeframe.new(Date.new(2007, 3, 1), Date.new(2008, 5, 11))
235
- Timeframe.parse('2007-03-01T13:00:00Z--2008-05-11T15:30:00Z').must_equal Timeframe.new(Date.new(2007, 3, 1), Date.new(2008, 5, 11))
236
- end
237
- it 'takes shorthand' do
238
- Timeframe.parse('2007-11-13/15').must_equal Timeframe.new(Date.new(2007, 11, 13), Date.new(2007, 11, 15)) # "2007-11-13/15", i.e. from any time on 2007-11-13 to any time on 2007-11-15
239
- Timeframe.parse("2008-02-15/03-14").must_equal Timeframe.new(Date.new(2008, 2, 15), Date.new(2008, 3, 14)) # "2008-02-15/2008-03-14"
240
- Timeframe.parse("2007-12-14T13:30/15:30").must_equal Timeframe.new(Date.new(2007, 12, 14), Date.new(2007, 12, 14)) # "2007-12-14T13:30/2007-12-14T15:30".. imprecise!
241
- end
242
- end
243
-
244
- describe 'ISO 8601 <start>/<duration>' do
245
- it 'works without time' do
246
- Timeframe.parse('2007-03-01/P1Y2M10DT2H30M').must_equal Timeframe.new(Date.new(2007, 3, 1), Date.new(2008, 5, 11))
247
- Timeframe.parse('2007-03-01--P1Y2M10DT2H30M').must_equal Timeframe.new(Date.new(2007, 3, 1), Date.new(2008, 5, 11))
248
- end
249
- it 'works with time' do
250
- Timeframe.parse('2007-03-01T13:00:00Z/P1Y2M10DT2H30M').must_equal Timeframe.new(Date.new(2007, 3, 1), Date.new(2008, 5, 11))
251
- Timeframe.parse('2007-03-01T13:00:00Z--P1Y2M10DT2H30M').must_equal Timeframe.new(Date.new(2007, 3, 1), Date.new(2008, 5, 11))
252
- end
253
- end
254
-
255
- # note that 2008 was a leap year
256
- describe 'ISO 8601 <duration>/<end>' do
257
- it 'works with leap years' do
258
- Timeframe.parse('2007-02-28--P1Y').must_equal Timeframe.new(Date.new(2007, 2, 28), Date.new(2008, 2, 29))
259
- Timeframe.parse('P1Y--2008-02-29').must_equal Timeframe.new(Date.new(2007, 3, 1), Date.new(2008, 2, 29))
260
- end
261
- it 'works without time' do
262
- Timeframe.parse('P1Y2M10DT2H30M/2008-05-11').must_equal Timeframe.new(Date.new(2007, 3, 2), Date.new(2008, 5, 11))
263
- Timeframe.parse('P1Y2M10DT2H30M--2008-05-11').must_equal Timeframe.new(Date.new(2007, 3, 2), Date.new(2008, 5, 11))
264
- end
265
- it 'works with time' do
266
- Timeframe.parse('P1Y2M10DT2H30M/2008-05-11T15:30:00Z').must_equal Timeframe.new(Date.new(2007, 3, 3), Date.new(2008, 5, 11))
267
- Timeframe.parse('P1Y2M10DT2H30M--2008-05-11T15:30:00Z').must_equal Timeframe.new(Date.new(2007, 3, 3), Date.new(2008, 5, 11))
268
- end
269
- end
270
-
271
- it 'understands plain year' do
272
- plain_year = 2009
273
- Timeframe.parse(plain_year).must_equal Timeframe.new(:year => plain_year)
274
- Timeframe.parse(plain_year.to_s).must_equal Timeframe.new(:year => plain_year)
275
- end
276
- it 'understands JSON' do
277
- json =<<-EOS
278
- "2009-05-01/2009-06-01"
279
- EOS
280
- Timeframe.parse(json).must_equal Timeframe.new(:year => 2009, :month => 5)
281
- end
282
- it 'understands a particular style of Ruby hash we used to emit (deprecated)' do
283
- hsh = { :startDate => '2009-05-01', :endDate => '2009-06-01' }
284
- Timeframe.parse(hsh).must_equal Timeframe.new(:year => 2009, :month => 5)
285
- Timeframe.parse(hsh.stringify_keys).must_equal Timeframe.new(:year => 2009, :month => 5)
286
- end
287
- end
288
-
289
- describe '#as_json' do
290
- it 'should generate JSON (test fails on ruby 1.8)' do
291
- Timeframe.new(:year => 2009).as_json.must_equal %{2009-01-01/2010-01-01}
292
- MultiJson.dump(Timeframe.new(:year => 2009)).must_equal Timeframe.new(:year => 2009).as_json.inspect
293
- end
294
- it 'understands its own JSON' do
295
- t = Timeframe.new(:year => 2009, :month => 5)
296
- Timeframe.from_json(MultiJson.dump(t)).must_equal t
297
- end
298
- end
299
-
300
- describe '#to_param' do
301
- it 'should generate a URL-friendly parameter' do
302
- Timeframe.new(:year => 2009).to_param.must_equal "2009-01-01/2010-01-01"
303
- end
304
- it 'understands its own #to_param' do
305
- t = Timeframe.new(:year => 2009, :month => 5)
306
- Timeframe.parse(t.to_param).must_equal t
307
- end
308
- end
309
-
310
- describe '#to_s' do
311
- it 'should not only look at month numbers when describing multi-year timeframes' do
312
- Timeframe.new(Date.parse('2008-01-01'), Date.parse('2010-01-01')).to_s.must_equal "2008-01-01/2010-01-01"
313
- end
314
- end
315
-
316
- describe '#dates' do
317
- it "should enumerate all dates between start and end" do
318
- dates = Timeframe.new(:year => 2008).dates
319
- dates.min.must_equal Date.new(2008,1,1)
320
- dates.max.must_equal Date.new(2008,12,31)
321
- dates.uniq.length.must_equal 366
322
- dates.select { |d| d.month == 2 }.length.must_equal 29
323
- end
324
- end
325
-
326
- describe '#first_days_of_months' do
327
- it "should enumerate all the first days of included months" do
328
- dates = Timeframe.parse('2011-05-01/2012-02-01').first_days_of_months
329
- dates.must_equal [Date.new(2011,5,1), Date.new(2011,6,1), Date.new(2011,7,1), Date.new(2011,8,1), Date.new(2011,9,1), Date.new(2011,10,1), Date.new(2011,11,1), Date.new(2011,12,1), Date.new(2012,1,1)]
330
- end
331
- end
332
-
333
- describe "Array#multiple_timeframes_gaps_left_by" do
334
- it "should raise error if not a Timeframes are going to be merged" do
335
- lambda {
336
- [Timeframe.new(Date.parse('2011-10-10'), Date.parse('2011-10-28'))].multiple_timeframes_gaps_left_by(1,2)
337
- }.must_raise(ArgumentError, /only use timeframe/)
338
- end
339
-
340
- it "should properly work with multiple timeframes" do
341
- t1 = Timeframe.new(Date.parse('2011-10-10'), Date.parse('2011-10-28'))
342
- t2 = Timeframe.new(Date.parse('2011-11-01'), Date.parse('2011-11-12'))
343
-
344
- t3 = Timeframe.new(Date.parse('2011-10-11'), Date.parse('2011-10-15'))
345
- t4 = Timeframe.new(Date.parse('2011-11-01'), Date.parse('2011-11-08'))
346
-
347
- [t1, t2].multiple_timeframes_gaps_left_by(t3, t4).must_equal(
348
- [ Timeframe.new(Date.parse('2011-10-10'), Date.parse('2011-10-11')),
349
- Timeframe.new(Date.parse('2011-10-15'), Date.parse('2011-10-28')),
350
- Timeframe.new(Date.parse('2011-11-08'), Date.parse('2011-11-12'))
351
- ])
352
- end
353
- end
354
- end