timeframe 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/.document CHANGED
@@ -1,5 +1,5 @@
1
- README.rdoc
2
- lib/**/*.rb
3
- bin/*
4
- features/**/*.feature
5
- LICENSE
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore CHANGED
@@ -1,21 +1,21 @@
1
- ## MAC OS
2
- .DS_Store
3
-
4
- ## TEXTMATE
5
- *.tmproj
6
- tmtags
7
-
8
- ## EMACS
9
- *~
10
- \#*
11
- .\#*
12
-
13
- ## VIM
14
- *.swp
15
-
16
- ## PROJECT::GENERAL
17
- coverage
18
- rdoc
19
- pkg
20
-
21
- ## PROJECT::SPECIFIC
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE CHANGED
@@ -1,20 +1,20 @@
1
- Copyright (c) 2009 Andy Rossmeissl
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining
4
- a copy of this software and associated documentation files (the
5
- "Software"), to deal in the Software without restriction, including
6
- without limitation the rights to use, copy, modify, merge, publish,
7
- distribute, sublicense, and/or sell copies of the Software, and to
8
- permit persons to whom the Software is furnished to do so, subject to
9
- the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be
12
- included in all copies or substantial portions of the Software.
13
-
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1
+ Copyright (c) 2009 Andy Rossmeissl
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc CHANGED
@@ -1,13 +1,15 @@
1
- = timeframe
2
-
3
- A Ruby class for describing and interacting with timeframes.
4
-
5
- == Documentation
6
-
7
- == Acknoweldgements
8
-
9
- The good parts of Timeframe all came from the gentlemen at Fingertips[http://fngtps.com].
10
-
11
- == Copyright
12
-
13
- Copyright (c) 2010 Andy Rossmeissl.
1
+ = timeframe
2
+
3
+ A Ruby class for describing and interacting with timeframes.
4
+
5
+ == Documentation
6
+
7
+ http://rdoc.info/projects/rossmeissl/timeframe
8
+
9
+ == Acknowledgements
10
+
11
+ The good parts of Timeframe all came from the gentlemen at Fingertips[http://fngtps.com].
12
+
13
+ == Copyright
14
+
15
+ Copyright (c) 2010 Andy Rossmeissl.
data/Rakefile CHANGED
@@ -1,46 +1,46 @@
1
- require 'rubygems'
2
- require 'rake'
3
-
4
- begin
5
- require 'jeweler'
6
- Jeweler::Tasks.new do |gem|
7
- gem.name = "timeframe"
8
- gem.summary = %Q{Date intervals}
9
- gem.description = %Q{A Ruby class for describing and interacting with timeframes.}
10
- gem.email = "andy@rossmeissl.net"
11
- gem.homepage = "http://github.com/rossmeissl/timeframe"
12
- gem.authors = ["Andy Rossmeissl"]
13
- gem.add_development_dependency "rspec", ">= 1.2.9"
14
- gem.add_dependency 'activesupport', '= 3.0.0.beta4'
15
- gem.add_dependency 'andand'
16
- end
17
- Jeweler::GemcutterTasks.new
18
- rescue LoadError
19
- puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
20
- end
21
-
22
- require 'spec/rake/spectask'
23
- Spec::Rake::SpecTask.new(:spec) do |spec|
24
- spec.libs << 'lib' << 'spec'
25
- spec.spec_files = FileList['spec/**/*_spec.rb']
26
- end
27
-
28
- Spec::Rake::SpecTask.new(:rcov) do |spec|
29
- spec.libs << 'lib' << 'spec'
30
- spec.pattern = 'spec/**/*_spec.rb'
31
- spec.rcov = true
32
- end
33
-
34
- task :spec => :check_dependencies
35
-
36
- task :default => :spec
37
-
38
- require 'rake/rdoctask'
39
- Rake::RDocTask.new do |rdoc|
40
- version = File.exist?('VERSION') ? File.read('VERSION') : ""
41
-
42
- rdoc.rdoc_dir = 'rdoc'
43
- rdoc.title = "timeframe #{version}"
44
- rdoc.rdoc_files.include('README*')
45
- rdoc.rdoc_files.include('lib/**/*.rb')
46
- end
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "timeframe"
8
+ gem.summary = %Q{Date intervals}
9
+ gem.description = %Q{A Ruby class for describing and interacting with timeframes.}
10
+ gem.email = "andy@rossmeissl.net"
11
+ gem.homepage = "http://github.com/rossmeissl/timeframe"
12
+ gem.authors = ["Andy Rossmeissl", "Seamus Abshere", "Derek Kastner"]
13
+ gem.add_development_dependency "rspec", ">= 1.2.9"
14
+ gem.add_dependency 'activesupport', '= 3.0.0.beta4'
15
+ gem.add_dependency 'andand'
16
+ end
17
+ Jeweler::GemcutterTasks.new
18
+ rescue LoadError
19
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
20
+ end
21
+
22
+ require 'spec/rake/spectask'
23
+ Spec::Rake::SpecTask.new(:spec) do |spec|
24
+ spec.libs << 'lib' << 'spec'
25
+ spec.spec_files = FileList['spec/**/*_spec.rb']
26
+ end
27
+
28
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
29
+ spec.libs << 'lib' << 'spec'
30
+ spec.pattern = 'spec/**/*_spec.rb'
31
+ spec.rcov = true
32
+ end
33
+
34
+ task :spec => :check_dependencies
35
+
36
+ task :default => :spec
37
+
38
+ require 'rake/rdoctask'
39
+ Rake::RDocTask.new do |rdoc|
40
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
41
+
42
+ rdoc.rdoc_dir = 'rdoc'
43
+ rdoc.title = "timeframe #{version}"
44
+ rdoc.rdoc_files.include('README*')
45
+ rdoc.rdoc_files.include('lib/**/*.rb')
46
+ end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.0.2
@@ -0,0 +1,5 @@
1
+ class Date
2
+ def to_json(*)
3
+ super nil
4
+ end
5
+ end
data/lib/timeframe/ykk.rb CHANGED
@@ -1,4 +1,4 @@
1
- module Ykk
1
+ module Ykk # :nodoc: all
2
2
  def ykk(*arys, &blk) # YKK: a better zipper
3
3
  return zip(*arys) unless block_given?
4
4
  zip(*arys).collect { |a| yield a }
data/lib/timeframe.rb CHANGED
@@ -6,11 +6,13 @@ require 'active_support/version'
6
6
  active_support/core_ext/date/conversions
7
7
  active_support/core_ext/integer/time
8
8
  active_support/core_ext/numeric/time
9
+ active_support/json/encoding
9
10
  }.each do |active_support_3_requirement|
10
11
  require active_support_3_requirement
11
12
  end if ActiveSupport::VERSION::MAJOR == 3
12
13
  require 'andand'
13
14
  require 'timeframe/ykk'
15
+ require 'timeframe/date_to_json'
14
16
 
15
17
  # Encapsulates a timeframe between two dates. The dates provided to the class are always until the last date. That means
16
18
  # that the last date is excluded.
@@ -77,9 +79,9 @@ class Timeframe
77
79
 
78
80
  # Returns a string representation of the timeframe
79
81
  def to_s
80
- if [from.day, from.month, to.day, to.month].uniq == [1]
82
+ if (from.year == to.year - 1) and [from.day, from.month, to.day, to.month].uniq == [1]
81
83
  from.year.to_s
82
- elsif from.day == 1 and to.day == 1 and to.month - from.month == 1
84
+ elsif from.year == to.year and from.day == 1 and to.day == 1 and to.month - from.month == 1
83
85
  "#{Date::MONTHNAMES[from.month]} #{from.year}"
84
86
  else
85
87
  "the period from #{from.strftime('%d %B')} to #{to.yesterday.strftime('%d %B %Y')}"
@@ -120,7 +122,6 @@ class Timeframe
120
122
  def hash
121
123
  from.hash + to.hash
122
124
  end
123
- alias :to_param :hash
124
125
 
125
126
  # Returns an array of month-long subtimeframes
126
127
  #--
@@ -250,6 +251,11 @@ class Timeframe
250
251
  { :from => from, :to => to }.to_json
251
252
  end
252
253
 
254
+ # URL-friendly like "2008-10-25/2009-11-12"
255
+ def to_param
256
+ "#{from}/#{to}"
257
+ end
258
+
253
259
  class << self
254
260
  # Shortcut method to return the Timeframe representing the current year (as defined by Time.now)
255
261
  def this_year
data/spec/spec.opts CHANGED
@@ -1 +1 @@
1
- --color
1
+ --color
data/spec/spec_helper.rb CHANGED
@@ -1,10 +1,10 @@
1
- $LOAD_PATH.unshift(File.dirname(__FILE__))
2
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
- require 'timeframe'
4
- require 'spec'
5
- require 'spec/autorun'
6
- require 'date'
7
-
8
- Spec::Runner.configure do |config|
9
-
10
- end
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'timeframe'
4
+ require 'spec'
5
+ require 'spec/autorun'
6
+ require 'date'
7
+
8
+ Spec::Runner.configure do |config|
9
+
10
+ end
@@ -1,248 +1,270 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
- require 'date'
3
-
4
- describe Timeframe do
5
- describe 'initialization' do
6
- it 'should create a timeframe using date strings' do
7
- tf = Timeframe.new('2008-02-14', '2008-05-10')
8
- tf.from.should == Date.parse('2008-02-14')
9
- tf.to.should == Date.parse('2008-05-10')
10
- end
11
- it 'should create a timeframe using date objects' do
12
- start = Date.parse('2008-02-14')
13
- finish = Date.parse('2008-05-10')
14
- tf = Timeframe.new(start, finish)
15
- tf.from.should == start
16
- tf.to.should == finish
17
- end
18
- it "should accept months" do
19
- timeframe = Timeframe.new(:month => 1)
20
- timeframe.from.should == Date.today.change(:month => 1, :day => 1)
21
- timeframe.to.should == Date.today.change(:month => 2, :day => 1)
22
- end
23
- it "should accept month names" do
24
- timeframe = Timeframe.new(:month => 'february')
25
- timeframe.from.should == Date.today.change(:month => 2, :day => 1)
26
- timeframe.to.should == Date.today.change(:month => 3, :day => 1)
27
- end
28
- it "should accept years" do
29
- timeframe = Timeframe.new(:year => 2004)
30
- timeframe.from.should == Date.new(2004, 1, 1)
31
- timeframe.to.should == Date.new(2005, 1, 1)
32
- end
33
- it "should accept years and months" do
34
- timeframe = Timeframe.new(:year => 2005, :month => 5)
35
- timeframe.from.should == Date.new(2005, 5, 1)
36
- timeframe.to.should == Date.new(2005, 6, 1)
37
- end
38
- it "should not accept just one date argument" do
39
- lambda {
40
- Timeframe.new Date.new(2007, 2, 1)
41
- }.should raise_error(ArgumentError, /supply/)
42
- end
43
- it "should not accept end date that is earlier than start date" do
44
- lambda {
45
- timeframe = Timeframe.new Date.new(2008, 1, 1), Date.new(2007, 1, 1)
46
- }.should raise_error(ArgumentError, /earlier/)
47
- end
48
- it "should not accept timeframes that cross year boundaries" do
49
- lambda {
50
- timeframe = Timeframe.new Date.new(2007, 1, 1), Date.new(2008, 1, 2)
51
- }.should raise_error(ArgumentError, /cross/)
52
- end
53
- it "should optionally accept timeframes that cross year boundaries" do
54
- lambda {
55
- timeframe = Timeframe.new Date.new(2007, 1, 1), Date.new(2008, 1, 2), :skip_year_boundary_crossing_check => true
56
- }.should_not raise_error
57
- end
58
- end
59
-
60
- describe '#inspect' do
61
- it 'should return the time frame in readable text' do
62
- start = Date.parse('2008-02-14')
63
- finish = Date.parse('2008-05-10')
64
- tf = Timeframe.new(start, finish)
65
- tf.inspect.should =~ /<Timeframe\(-?\d+\) 86 days starting 2008-02-14 ending 2008-05-10>/
66
- end
67
- end
68
-
69
- describe '.constrained_new' do
70
- let(:start) { Date.parse('2008-02-14') }
71
- let(:finish) { Date.parse('2008-05-10') }
72
- let(:constraint_start) { Date.parse('2008-01-01') }
73
- let(:constraint_finish) { Date.parse('2008-12-01') }
74
- let(:constraint) { Timeframe.new(constraint_start, constraint_finish) }
75
-
76
- it "should allow for constrained creation" do
77
- constraint = Timeframe.new :year => 2008
78
- may = Timeframe.new Date.new(2008,5,1), Date.new(2008,6,1)
79
- january = Timeframe.new Date.new(2008,1,1), Date.new(2008,2,1)
80
- Timeframe.constrained_new(may.from, may.to, constraint).should == may
81
- Timeframe.constrained_new(Date.new(2007,1,1), Date.new(2010,1,1), constraint).should == constraint
82
- Timeframe.constrained_new(Date.new(2007,11,1), Date.new(2008,2,1), constraint).should == january
83
- end
84
- it 'should return a timeframe spanning start and end date if within constraint' do
85
- tf = Timeframe.constrained_new(start, finish, constraint)
86
- tf.from.should == start
87
- tf.to.should == finish
88
- end
89
- it 'should return a timeframe spanning constraint start and end date if outside constraint' do
90
- constraint = Timeframe.new(start, finish)
91
- tf = Timeframe.constrained_new(constraint_start, constraint_finish, constraint)
92
- tf.from.should == start
93
- tf.to.should == finish
94
- end
95
- it 'should return a timeframe starting at constraint start' do
96
- start = Date.parse('2008-01-01')
97
- constraint_start = Date.parse('2008-01-14')
98
- constraint = Timeframe.new(constraint_start, constraint_finish)
99
- tf = Timeframe.constrained_new(start, finish, constraint)
100
- tf.from.should == constraint_start
101
- tf.to.should == finish
102
- end
103
- it 'should return a timeframe ending at constraint end' do
104
- constraint_finish = Date.parse('2008-04-14')
105
- constraint = Timeframe.new(constraint_start, constraint_finish)
106
- tf = Timeframe.constrained_new(start, finish, constraint)
107
- tf.from.should == start
108
- tf.to.should == constraint_finish
109
- end
110
- it "should return a 0-length timeframe when constraining a timeframe by a disjoint timeframe" do
111
- constraint = Timeframe.new :year => 2010
112
- timeframe = Timeframe.constrained_new(
113
- Date.new(2009,1,1), Date.new(2010,1,1), constraint)
114
- timeframe.days.should == 0
115
- end
116
- end
117
-
118
- describe '.this_year' do
119
- it "should return the current year" do
120
- Timeframe.this_year.should == Timeframe.new(:year => Time.now.year)
121
- end
122
- end
123
-
124
- describe '#days' do
125
- it "should return them number of days included" do
126
- #TODO: make these separate "it" blocks, per best practices
127
- Timeframe.new(Date.new(2007, 1, 1), Date.new(2008, 1, 1)).days.should == 365
128
- Timeframe.new(Date.new(2008, 1, 1), Date.new(2009, 1, 1)).days.should == 366 #leap year
129
- Timeframe.new(Date.new(2007, 11, 1), Date.new(2007, 12, 1)).days.should == 30
130
- Timeframe.new(Date.new(2007, 11, 1), Date.new(2008, 1, 1)).days.should == 61
131
- Timeframe.new(Date.new(2007, 2, 1), Date.new(2007, 3, 1)).days.should == 28
132
- Timeframe.new(Date.new(2008, 2, 1), Date.new(2008, 3, 1)).days.should == 29
133
- Timeframe.new(Date.new(2008, 2, 1), Date.new(2008, 2, 1)).days.should == 0
134
- end
135
- end
136
-
137
- describe '#include?' do
138
- it "should know if a certain date is included in the Timeframe" do
139
- #TODO: make these separate "it" blocks, per best practices
140
- timeframe = Timeframe.new :year => 2008, :month => 2
141
- [
142
- Date.new(2008, 2, 1),
143
- Date.new(2008, 2, 5),
144
- Date.new(2008, 2, 29)
145
- ].each do |date|
146
- timeframe.include?(date).should == true
147
- end
148
- [
149
- Date.new(2008, 1, 1),
150
- Date.new(2007, 2, 1),
151
- Date.new(2008, 3, 1)
152
- ].each do |date|
153
- timeframe.include?(date).should == false
154
- end
155
- end
156
- end
157
-
158
- describe '#==' do
159
- it "should be able to know if it's equal to another Timeframe object" do
160
- Timeframe.new(:year => 2007).should == Timeframe.new(:year => 2007)
161
- Timeframe.new(:year => 2004, :month => 1).should == Timeframe.new(:year => 2004, :month => 1)
162
- end
163
-
164
- it "should hash equal hash values when the timeframe is equal" do
165
- Timeframe.new(:year => 2007).hash.should == Timeframe.new(:year => 2007).hash
166
- Timeframe.new(:year => 2004, :month => 1).hash.should == Timeframe.new(:year => 2004, :month => 1).hash
167
- end
168
- end
169
-
170
- describe '#months' do
171
- it "should return an array of month-long subtimeframes" do
172
- Timeframe.new(:year => 2009).months.length.should == 12
173
- end
174
- it "should not return an array of month-long subtimeframes if provided an inappropriate range" do
175
- lambda {
176
- Timeframe.new(Date.new(2009, 3, 2), Date.new(2009, 3, 5)).months
177
- }.should raise_error(ArgumentError, /whole/)
178
- lambda {
179
- Timeframe.new(Date.new(2009, 1, 1), Date.new(2012, 1, 1), :skip_year_boundary_crossing_check => true).months
180
- }.should raise_error(ArgumentError, /dangerous during/)
181
- end
182
- end
183
-
184
- describe '#year' do
185
- it "should return the relevant year of a timeframe" do
186
- Timeframe.new(Date.new(2009, 2, 1), Date.new(2009, 4, 1)).year.should == Timeframe.new(:year => 2009)
187
- end
188
- it "should not return the relevant year of a timeframe if provided an inappropriate range" do
189
- lambda {
190
- Timeframe.new(Date.new(2009, 1, 1), Date.new(2012, 1, 1), :skip_year_boundary_crossing_check => true).year
191
- }.should raise_error(ArgumentError, /dangerous during/)
192
- end
193
- end
194
-
195
- describe '#&' do
196
- it "should return its intersection with another timeframe" do
197
- #TODO: make these separate "it" blocks, per best practices
198
- (Timeframe.new(:month => 4) & Timeframe.new(:month => 6)).should be_nil
199
- (Timeframe.new(:month => 4) & Timeframe.new(:month => 5)).should be_nil
200
- (Timeframe.new(:month => 4) & Timeframe.new(:month => 4)).should == Timeframe.new(:month => 4)
201
- (Timeframe.new(:year => Time.now.year) & Timeframe.new(:month => 4)).should == Timeframe.new(:month => 4)
202
- (Timeframe.new(Date.new(2009, 2, 1), Date.new(2009, 6, 1)) & Timeframe.new(Date.new(2009, 4, 1), Date.new(2009, 8, 1))).should == Timeframe.new(Date.new(2009, 4, 1), Date.new(2009, 6, 1))
203
- end
204
- end
205
-
206
- describe '#/' do
207
- it "should return a fraction of another timeframe" do
208
- (Timeframe.new(:month => 4, :year => 2009) / Timeframe.new(:year => 2009)).should == (30.0 / 365.0)
209
- end
210
- end
211
-
212
- describe '#gaps_left_by' do
213
- it "should be able to ascertain gaps left by a list of other Timeframes" do
214
- Timeframe.new(:year => 2009).gaps_left_by(
215
- Timeframe.new(:year => 2009, :month => 3),
216
- Timeframe.new(:year => 2009, :month => 5),
217
- Timeframe.new(Date.new(2009, 8, 1), Date.new(2009, 11, 1)),
218
- Timeframe.new(Date.new(2009, 9, 1), Date.new(2009, 10, 1))
219
- ).should ==
220
- [ Timeframe.new(Date.new(2009, 1, 1), Date.new(2009, 3, 1)),
221
- Timeframe.new(Date.new(2009, 4, 1), Date.new(2009, 5, 1)),
222
- Timeframe.new(Date.new(2009, 6, 1), Date.new(2009, 8, 1)),
223
- Timeframe.new(Date.new(2009, 11, 1), Date.new(2010, 1, 1)) ]
224
- end
225
- end
226
-
227
- describe '#covered_by?' do
228
- it "should be able to ascertain gaps left by a list of other Timeframes" do
229
- Timeframe.new(:year => 2009).covered_by?(
230
- Timeframe.new(:month => 1, :year => 2009),
231
- Timeframe.new(Date.new(2009, 2, 1), Date.new(2010, 1, 1))
232
- ).should be_true
233
- end
234
- end
235
-
236
- describe '#last_year' do
237
- it "should return its predecessor in a previous year" do
238
- Timeframe.this_year.last_year.should ==
239
- Timeframe.new(Date.new(Date.today.year - 1, 1, 1), Date.new(Date.today.year, 1, 1))
240
- end
241
- end
242
-
243
- describe 'Timeframe:class#interval' do
244
- it 'should parse ISO 8601 interval format' do
245
- Timeframe.interval('2009-01-01/2010-01-01').should == Timeframe.new(:year => 2009)
246
- end
247
- end
248
- end
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ require 'date'
3
+
4
+ describe Timeframe do
5
+ describe 'initialization' do
6
+ it 'should create a timeframe using date strings' do
7
+ tf = Timeframe.new('2008-02-14', '2008-05-10')
8
+ tf.from.should == Date.parse('2008-02-14')
9
+ tf.to.should == Date.parse('2008-05-10')
10
+ end
11
+ it 'should create a timeframe using date objects' do
12
+ start = Date.parse('2008-02-14')
13
+ finish = Date.parse('2008-05-10')
14
+ tf = Timeframe.new(start, finish)
15
+ tf.from.should == start
16
+ tf.to.should == finish
17
+ end
18
+ it "should accept months" do
19
+ timeframe = Timeframe.new(:month => 1)
20
+ timeframe.from.should == Date.today.change(:month => 1, :day => 1)
21
+ timeframe.to.should == Date.today.change(:month => 2, :day => 1)
22
+ end
23
+ it "should accept month names" do
24
+ timeframe = Timeframe.new(:month => 'february')
25
+ timeframe.from.should == Date.today.change(:month => 2, :day => 1)
26
+ timeframe.to.should == Date.today.change(:month => 3, :day => 1)
27
+ end
28
+ it "should accept years" do
29
+ timeframe = Timeframe.new(:year => 2004)
30
+ timeframe.from.should == Date.new(2004, 1, 1)
31
+ timeframe.to.should == Date.new(2005, 1, 1)
32
+ end
33
+ it "should accept years and months" do
34
+ timeframe = Timeframe.new(:year => 2005, :month => 5)
35
+ timeframe.from.should == Date.new(2005, 5, 1)
36
+ timeframe.to.should == Date.new(2005, 6, 1)
37
+ end
38
+ it "should not accept just one date argument" do
39
+ lambda {
40
+ Timeframe.new Date.new(2007, 2, 1)
41
+ }.should raise_error(ArgumentError, /supply/)
42
+ end
43
+ it "should not accept end date that is earlier than start date" do
44
+ lambda {
45
+ timeframe = Timeframe.new Date.new(2008, 1, 1), Date.new(2007, 1, 1)
46
+ }.should raise_error(ArgumentError, /earlier/)
47
+ end
48
+ it "should not accept timeframes that cross year boundaries" do
49
+ lambda {
50
+ timeframe = Timeframe.new Date.new(2007, 1, 1), Date.new(2008, 1, 2)
51
+ }.should raise_error(ArgumentError, /cross/)
52
+ end
53
+ it "should optionally accept timeframes that cross year boundaries" do
54
+ lambda {
55
+ timeframe = Timeframe.new Date.new(2007, 1, 1), Date.new(2008, 1, 2), :skip_year_boundary_crossing_check => true
56
+ }.should_not raise_error
57
+ end
58
+ end
59
+
60
+ describe '#inspect' do
61
+ it 'should return the time frame in readable text' do
62
+ start = Date.parse('2008-02-14')
63
+ finish = Date.parse('2008-05-10')
64
+ tf = Timeframe.new(start, finish)
65
+ tf.inspect.should =~ /<Timeframe\(-?\d+\) 86 days starting 2008-02-14 ending 2008-05-10>/
66
+ end
67
+ end
68
+
69
+ describe '.constrained_new' do
70
+ let(:start) { Date.parse('2008-02-14') }
71
+ let(:finish) { Date.parse('2008-05-10') }
72
+ let(:constraint_start) { Date.parse('2008-01-01') }
73
+ let(:constraint_finish) { Date.parse('2008-12-01') }
74
+ let(:constraint) { Timeframe.new(constraint_start, constraint_finish) }
75
+
76
+ it "should allow for constrained creation" do
77
+ constraint = Timeframe.new :year => 2008
78
+ may = Timeframe.new Date.new(2008,5,1), Date.new(2008,6,1)
79
+ january = Timeframe.new Date.new(2008,1,1), Date.new(2008,2,1)
80
+ Timeframe.constrained_new(may.from, may.to, constraint).should == may
81
+ Timeframe.constrained_new(Date.new(2007,1,1), Date.new(2010,1,1), constraint).should == constraint
82
+ Timeframe.constrained_new(Date.new(2007,11,1), Date.new(2008,2,1), constraint).should == january
83
+ end
84
+ it 'should return a timeframe spanning start and end date if within constraint' do
85
+ tf = Timeframe.constrained_new(start, finish, constraint)
86
+ tf.from.should == start
87
+ tf.to.should == finish
88
+ end
89
+ it 'should return a timeframe spanning constraint start and end date if outside constraint' do
90
+ constraint = Timeframe.new(start, finish)
91
+ tf = Timeframe.constrained_new(constraint_start, constraint_finish, constraint)
92
+ tf.from.should == start
93
+ tf.to.should == finish
94
+ end
95
+ it 'should return a timeframe starting at constraint start' do
96
+ start = Date.parse('2008-01-01')
97
+ constraint_start = Date.parse('2008-01-14')
98
+ constraint = Timeframe.new(constraint_start, constraint_finish)
99
+ tf = Timeframe.constrained_new(start, finish, constraint)
100
+ tf.from.should == constraint_start
101
+ tf.to.should == finish
102
+ end
103
+ it 'should return a timeframe ending at constraint end' do
104
+ constraint_finish = Date.parse('2008-04-14')
105
+ constraint = Timeframe.new(constraint_start, constraint_finish)
106
+ tf = Timeframe.constrained_new(start, finish, constraint)
107
+ tf.from.should == start
108
+ tf.to.should == constraint_finish
109
+ end
110
+ it "should return a 0-length timeframe when constraining a timeframe by a disjoint timeframe" do
111
+ constraint = Timeframe.new :year => 2010
112
+ timeframe = Timeframe.constrained_new(
113
+ Date.new(2009,1,1), Date.new(2010,1,1), constraint)
114
+ timeframe.days.should == 0
115
+ end
116
+ end
117
+
118
+ describe '.this_year' do
119
+ it "should return the current year" do
120
+ Timeframe.this_year.should == Timeframe.new(:year => Time.now.year)
121
+ end
122
+ end
123
+
124
+ describe '#days' do
125
+ it "should return them number of days included" do
126
+ #TODO: make these separate "it" blocks, per best practices
127
+ Timeframe.new(Date.new(2007, 1, 1), Date.new(2008, 1, 1)).days.should == 365
128
+ Timeframe.new(Date.new(2008, 1, 1), Date.new(2009, 1, 1)).days.should == 366 #leap year
129
+ Timeframe.new(Date.new(2007, 11, 1), Date.new(2007, 12, 1)).days.should == 30
130
+ Timeframe.new(Date.new(2007, 11, 1), Date.new(2008, 1, 1)).days.should == 61
131
+ Timeframe.new(Date.new(2007, 2, 1), Date.new(2007, 3, 1)).days.should == 28
132
+ Timeframe.new(Date.new(2008, 2, 1), Date.new(2008, 3, 1)).days.should == 29
133
+ Timeframe.new(Date.new(2008, 2, 1), Date.new(2008, 2, 1)).days.should == 0
134
+ end
135
+ end
136
+
137
+ describe '#include?' do
138
+ it "should know if a certain date is included in the Timeframe" do
139
+ #TODO: make these separate "it" blocks, per best practices
140
+ timeframe = Timeframe.new :year => 2008, :month => 2
141
+ [
142
+ Date.new(2008, 2, 1),
143
+ Date.new(2008, 2, 5),
144
+ Date.new(2008, 2, 29)
145
+ ].each do |date|
146
+ timeframe.include?(date).should == true
147
+ end
148
+ [
149
+ Date.new(2008, 1, 1),
150
+ Date.new(2007, 2, 1),
151
+ Date.new(2008, 3, 1)
152
+ ].each do |date|
153
+ timeframe.include?(date).should == false
154
+ end
155
+ end
156
+ end
157
+
158
+ describe '#==' do
159
+ it "should be able to know if it's equal to another Timeframe object" do
160
+ Timeframe.new(:year => 2007).should == Timeframe.new(:year => 2007)
161
+ Timeframe.new(:year => 2004, :month => 1).should == Timeframe.new(:year => 2004, :month => 1)
162
+ end
163
+
164
+ it "should hash equal hash values when the timeframe is equal" do
165
+ Timeframe.new(:year => 2007).hash.should == Timeframe.new(:year => 2007).hash
166
+ Timeframe.new(:year => 2004, :month => 1).hash.should == Timeframe.new(:year => 2004, :month => 1).hash
167
+ end
168
+ end
169
+
170
+ describe '#months' do
171
+ it "should return an array of month-long subtimeframes" do
172
+ Timeframe.new(:year => 2009).months.length.should == 12
173
+ end
174
+ it "should not return an array of month-long subtimeframes if provided an inappropriate range" do
175
+ lambda {
176
+ Timeframe.new(Date.new(2009, 3, 2), Date.new(2009, 3, 5)).months
177
+ }.should raise_error(ArgumentError, /whole/)
178
+ lambda {
179
+ Timeframe.new(Date.new(2009, 1, 1), Date.new(2012, 1, 1), :skip_year_boundary_crossing_check => true).months
180
+ }.should raise_error(ArgumentError, /dangerous during/)
181
+ end
182
+ end
183
+
184
+ describe '#year' do
185
+ it "should return the relevant year of a timeframe" do
186
+ Timeframe.new(Date.new(2009, 2, 1), Date.new(2009, 4, 1)).year.should == Timeframe.new(:year => 2009)
187
+ end
188
+ it "should not return the relevant year of a timeframe if provided an inappropriate range" do
189
+ lambda {
190
+ Timeframe.new(Date.new(2009, 1, 1), Date.new(2012, 1, 1), :skip_year_boundary_crossing_check => true).year
191
+ }.should raise_error(ArgumentError, /dangerous during/)
192
+ end
193
+ end
194
+
195
+ describe '#&' do
196
+ it "should return its intersection with another timeframe" do
197
+ #TODO: make these separate "it" blocks, per best practices
198
+ (Timeframe.new(:month => 4) & Timeframe.new(:month => 6)).should be_nil
199
+ (Timeframe.new(:month => 4) & Timeframe.new(:month => 5)).should be_nil
200
+ (Timeframe.new(:month => 4) & Timeframe.new(:month => 4)).should == Timeframe.new(:month => 4)
201
+ (Timeframe.new(:year => Time.now.year) & Timeframe.new(:month => 4)).should == Timeframe.new(:month => 4)
202
+ (Timeframe.new(Date.new(2009, 2, 1), Date.new(2009, 6, 1)) & Timeframe.new(Date.new(2009, 4, 1), Date.new(2009, 8, 1))).should == Timeframe.new(Date.new(2009, 4, 1), Date.new(2009, 6, 1))
203
+ end
204
+ end
205
+
206
+ describe '#/' do
207
+ it "should return a fraction of another timeframe" do
208
+ (Timeframe.new(:month => 4, :year => 2009) / Timeframe.new(:year => 2009)).should == (30.0 / 365.0)
209
+ end
210
+ end
211
+
212
+ describe '#gaps_left_by' do
213
+ it "should be able to ascertain gaps left by a list of other Timeframes" do
214
+ Timeframe.new(:year => 2009).gaps_left_by(
215
+ Timeframe.new(:year => 2009, :month => 3),
216
+ Timeframe.new(:year => 2009, :month => 5),
217
+ Timeframe.new(Date.new(2009, 8, 1), Date.new(2009, 11, 1)),
218
+ Timeframe.new(Date.new(2009, 9, 1), Date.new(2009, 10, 1))
219
+ ).should ==
220
+ [ Timeframe.new(Date.new(2009, 1, 1), Date.new(2009, 3, 1)),
221
+ Timeframe.new(Date.new(2009, 4, 1), Date.new(2009, 5, 1)),
222
+ Timeframe.new(Date.new(2009, 6, 1), Date.new(2009, 8, 1)),
223
+ Timeframe.new(Date.new(2009, 11, 1), Date.new(2010, 1, 1)) ]
224
+ end
225
+ end
226
+
227
+ describe '#covered_by?' do
228
+ it "should be able to ascertain gaps left by a list of other Timeframes" do
229
+ Timeframe.new(:year => 2009).covered_by?(
230
+ Timeframe.new(:month => 1, :year => 2009),
231
+ Timeframe.new(Date.new(2009, 2, 1), Date.new(2010, 1, 1))
232
+ ).should be_true
233
+ end
234
+ end
235
+
236
+ describe '#last_year' do
237
+ it "should return its predecessor in a previous year" do
238
+ Timeframe.this_year.last_year.should ==
239
+ Timeframe.new(Date.new(Date.today.year - 1, 1, 1), Date.new(Date.today.year, 1, 1))
240
+ end
241
+ end
242
+
243
+ describe 'Timeframe:class#interval' do
244
+ it 'should parse ISO 8601 interval format' do
245
+ Timeframe.interval('2009-01-01/2010-01-01').should == Timeframe.new(:year => 2009)
246
+ end
247
+ it 'should understand its own #to_param' do
248
+ t = Timeframe.new(:year => 2009)
249
+ Timeframe.interval(t.to_param).should == t
250
+ end
251
+ end
252
+
253
+ describe '#to_json' do
254
+ it 'should generate JSON' do
255
+ Timeframe.new(:year => 2009).to_json.should == "{\"from\":\"2009-01-01\",\"to\":\"2010-01-01\"}"
256
+ end
257
+ end
258
+
259
+ describe '#to_param' do
260
+ it 'should generate a URL-friendly parameter' do
261
+ Timeframe.new(:year => 2009).to_param.should == "2009-01-01/2010-01-01"
262
+ end
263
+ end
264
+
265
+ describe '#to_s' do
266
+ it 'should not only look at month numbers when describing multi-year timeframes' do
267
+ Timeframe.multiyear(Date.parse('2008-01-01'), Date.parse('2010-01-01')).to_s.should == "the period from 01 January to 31 December 2009"
268
+ end
269
+ end
270
+ end
data/timeframe.gemspec ADDED
@@ -0,0 +1,63 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{timeframe}
8
+ s.version = "0.0.2"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Andy Rossmeissl", "Seamus Abshere", "Derek Kastner"]
12
+ s.date = %q{2010-07-16}
13
+ s.description = %q{A Ruby class for describing and interacting with timeframes.}
14
+ s.email = %q{andy@rossmeissl.net}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "LICENSE",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "lib/timeframe.rb",
27
+ "lib/timeframe/date_to_json.rb",
28
+ "lib/timeframe/ykk.rb",
29
+ "spec/spec.opts",
30
+ "spec/spec_helper.rb",
31
+ "spec/timeframe_spec.rb",
32
+ "timeframe.gemspec"
33
+ ]
34
+ s.homepage = %q{http://github.com/rossmeissl/timeframe}
35
+ s.rdoc_options = ["--charset=UTF-8"]
36
+ s.require_paths = ["lib"]
37
+ s.rubygems_version = %q{1.3.7}
38
+ s.summary = %q{Date intervals}
39
+ s.test_files = [
40
+ "spec/spec_helper.rb",
41
+ "spec/timeframe_spec.rb"
42
+ ]
43
+
44
+ if s.respond_to? :specification_version then
45
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
46
+ s.specification_version = 3
47
+
48
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
49
+ s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
50
+ s.add_runtime_dependency(%q<activesupport>, ["= 3.0.0.beta4"])
51
+ s.add_runtime_dependency(%q<andand>, [">= 0"])
52
+ else
53
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
54
+ s.add_dependency(%q<activesupport>, ["= 3.0.0.beta4"])
55
+ s.add_dependency(%q<andand>, [">= 0"])
56
+ end
57
+ else
58
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
59
+ s.add_dependency(%q<activesupport>, ["= 3.0.0.beta4"])
60
+ s.add_dependency(%q<andand>, [">= 0"])
61
+ end
62
+ end
63
+
metadata CHANGED
@@ -1,29 +1,34 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: timeframe
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 27
4
5
  prerelease: false
5
6
  segments:
6
7
  - 0
7
8
  - 0
8
- - 1
9
- version: 0.0.1
9
+ - 2
10
+ version: 0.0.2
10
11
  platform: ruby
11
12
  authors:
12
13
  - Andy Rossmeissl
14
+ - Seamus Abshere
15
+ - Derek Kastner
13
16
  autorequire:
14
17
  bindir: bin
15
18
  cert_chain: []
16
19
 
17
- date: 2010-07-15 00:00:00 -04:00
20
+ date: 2010-07-16 00:00:00 -05:00
18
21
  default_executable:
19
22
  dependencies:
20
23
  - !ruby/object:Gem::Dependency
21
24
  name: rspec
22
25
  prerelease: false
23
26
  requirement: &id001 !ruby/object:Gem::Requirement
27
+ none: false
24
28
  requirements:
25
29
  - - ">="
26
30
  - !ruby/object:Gem::Version
31
+ hash: 13
27
32
  segments:
28
33
  - 1
29
34
  - 2
@@ -35,9 +40,11 @@ dependencies:
35
40
  name: activesupport
36
41
  prerelease: false
37
42
  requirement: &id002 !ruby/object:Gem::Requirement
43
+ none: false
38
44
  requirements:
39
45
  - - "="
40
46
  - !ruby/object:Gem::Version
47
+ hash: 299253624
41
48
  segments:
42
49
  - 3
43
50
  - 0
@@ -50,9 +57,11 @@ dependencies:
50
57
  name: andand
51
58
  prerelease: false
52
59
  requirement: &id003 !ruby/object:Gem::Requirement
60
+ none: false
53
61
  requirements:
54
62
  - - ">="
55
63
  - !ruby/object:Gem::Version
64
+ hash: 3
56
65
  segments:
57
66
  - 0
58
67
  version: "0"
@@ -75,10 +84,12 @@ files:
75
84
  - Rakefile
76
85
  - VERSION
77
86
  - lib/timeframe.rb
87
+ - lib/timeframe/date_to_json.rb
78
88
  - lib/timeframe/ykk.rb
79
89
  - spec/spec.opts
80
90
  - spec/spec_helper.rb
81
91
  - spec/timeframe_spec.rb
92
+ - timeframe.gemspec
82
93
  has_rdoc: true
83
94
  homepage: http://github.com/rossmeissl/timeframe
84
95
  licenses: []
@@ -89,23 +100,27 @@ rdoc_options:
89
100
  require_paths:
90
101
  - lib
91
102
  required_ruby_version: !ruby/object:Gem::Requirement
103
+ none: false
92
104
  requirements:
93
105
  - - ">="
94
106
  - !ruby/object:Gem::Version
107
+ hash: 3
95
108
  segments:
96
109
  - 0
97
110
  version: "0"
98
111
  required_rubygems_version: !ruby/object:Gem::Requirement
112
+ none: false
99
113
  requirements:
100
114
  - - ">="
101
115
  - !ruby/object:Gem::Version
116
+ hash: 3
102
117
  segments:
103
118
  - 0
104
119
  version: "0"
105
120
  requirements: []
106
121
 
107
122
  rubyforge_project:
108
- rubygems_version: 1.3.6
123
+ rubygems_version: 1.3.7
109
124
  signing_key:
110
125
  specification_version: 3
111
126
  summary: Date intervals