timeframe 0.2.1 → 1.0.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.
@@ -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