by_star 1.0.1 → 2.0.0.beta1

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,10 @@
1
+ require 'spec_helper'
2
+ describe Time do
3
+ it "should work out the beginning of a weekend (Friday 3pm)" do
4
+ Time.now.beginning_of_weekend.strftime("%A %I:%M%p").should eql("Friday 03:00PM")
5
+ end
6
+
7
+ it "should work out the end of a weekend (Monday 3am)" do
8
+ Time.now.end_of_weekend.strftime("%A %I:%M%p").should eql("Monday 03:00AM")
9
+ end
10
+ end
metadata CHANGED
@@ -1,61 +1,113 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: by_star
3
- version: !ruby/object:Gem::Version
4
- prerelease:
5
- version: 1.0.1
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.0.beta1
5
+ prerelease: 6
6
6
  platform: ruby
7
- authors:
7
+ authors:
8
8
  - Ryan Bigg
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
-
13
- date: 2011-08-29 00:00:00 Z
14
- dependencies:
15
- - !ruby/object:Gem::Dependency
12
+ date: 2012-02-20 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
16
15
  name: bundler
17
- prerelease: false
18
- requirement: &id001 !ruby/object:Gem::Requirement
16
+ requirement: &70234733397300 !ruby/object:Gem::Requirement
19
17
  none: false
20
- requirements:
21
- - - ">="
22
- - !ruby/object:Gem::Version
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
23
21
  version: 1.0.0
24
22
  type: :development
25
- version_requirements: *id001
26
- - !ruby/object:Gem::Dependency
27
- name: activerecord
28
23
  prerelease: false
29
- requirement: &id002 !ruby/object:Gem::Requirement
24
+ version_requirements: *70234733397300
25
+ - !ruby/object:Gem::Dependency
26
+ name: sqlite3
27
+ requirement: &70234733396920 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *70234733396920
36
+ - !ruby/object:Gem::Dependency
37
+ name: pg
38
+ requirement: &70234733396460 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70234733396460
47
+ - !ruby/object:Gem::Dependency
48
+ name: mysql2
49
+ requirement: &70234733396040 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *70234733396040
58
+ - !ruby/object:Gem::Dependency
59
+ name: rspec-rails
60
+ requirement: &70234733395540 !ruby/object:Gem::Requirement
30
61
  none: false
31
- requirements:
32
- - - ">="
33
- - !ruby/object:Gem::Version
62
+ requirements:
63
+ - - ~>
64
+ - !ruby/object:Gem::Version
65
+ version: '2.8'
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *70234733395540
69
+ - !ruby/object:Gem::Dependency
70
+ name: timecop
71
+ requirement: &70234733395040 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ~>
75
+ - !ruby/object:Gem::Version
76
+ version: '0.3'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: *70234733395040
80
+ - !ruby/object:Gem::Dependency
81
+ name: activerecord
82
+ requirement: &70234733394580 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
34
87
  version: 2.0.0
35
88
  type: :runtime
36
- version_requirements: *id002
37
- - !ruby/object:Gem::Dependency
38
- name: chronic
39
89
  prerelease: false
40
- requirement: &id003 !ruby/object:Gem::Requirement
90
+ version_requirements: *70234733394580
91
+ - !ruby/object:Gem::Dependency
92
+ name: chronic
93
+ requirement: &70234733394200 !ruby/object:Gem::Requirement
41
94
  none: false
42
- requirements:
43
- - - ">="
44
- - !ruby/object:Gem::Version
45
- version: "0"
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
46
99
  type: :runtime
47
- version_requirements: *id003
100
+ prerelease: false
101
+ version_requirements: *70234733394200
48
102
  description: ActiveRecord extension for easier date scopes and time ranges
49
- email:
103
+ email:
50
104
  - radarlistener@gmail.com
51
105
  executables: []
52
-
53
106
  extensions: []
54
-
55
107
  extra_rdoc_files: []
56
-
57
- files:
108
+ files:
58
109
  - .gitignore
110
+ - .travis.yml
59
111
  - Gemfile
60
112
  - Gemfile.lock
61
113
  - MIT-LICENSE
@@ -63,49 +115,52 @@ files:
63
115
  - Rakefile
64
116
  - by_star.gemspec
65
117
  - cleaner.rb
66
- - init.rb
67
118
  - lib/by_star.rb
68
- - lib/by_star/calculations.rb
69
- - lib/by_star/calculations/count.rb
70
- - lib/by_star/calculations/sum.rb
71
- - lib/by_star/neighbours.rb
72
- - lib/by_star/range_calculations.rb
73
- - lib/by_star/shared.rb
119
+ - lib/by_star/by_day.rb
120
+ - lib/by_star/by_direction.rb
121
+ - lib/by_star/by_fortnight.rb
122
+ - lib/by_star/by_month.rb
123
+ - lib/by_star/by_week.rb
124
+ - lib/by_star/by_weekend.rb
125
+ - lib/by_star/by_year.rb
126
+ - lib/by_star/instance_methods.rb
74
127
  - lib/by_star/time_ext.rb
75
- - lib/by_star/vanilla.rb
76
128
  - lib/by_star/version.rb
77
- - spec/by_star_spec.rb
129
+ - spec/by_star/by_day_spec.rb
130
+ - spec/by_star/by_direction_spec.rb
131
+ - spec/by_star/by_fortnight_spec.rb
132
+ - spec/by_star/by_month_spec.rb
133
+ - spec/by_star/by_week_spec.rb
134
+ - spec/by_star/by_weekend_spec.rb
135
+ - spec/by_star/by_year_spec.rb
78
136
  - spec/database.yml
79
137
  - spec/fixtures/models.rb
80
138
  - spec/fixtures/schema.rb
81
139
  - spec/spec_helper.rb
140
+ - spec/time_ext_spec.rb
82
141
  - tmp/.gitignore
83
142
  homepage: http://rubygems.org/gems/by_star
84
143
  licenses: []
85
-
86
144
  post_install_message:
87
145
  rdoc_options: []
88
-
89
- require_paths:
146
+ require_paths:
90
147
  - lib
91
- required_ruby_version: !ruby/object:Gem::Requirement
148
+ required_ruby_version: !ruby/object:Gem::Requirement
92
149
  none: false
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: "0"
97
- required_rubygems_version: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - ! '>='
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
154
+ required_rubygems_version: !ruby/object:Gem::Requirement
98
155
  none: false
99
- requirements:
100
- - - ">="
101
- - !ruby/object:Gem::Version
156
+ requirements:
157
+ - - ! '>='
158
+ - !ruby/object:Gem::Version
102
159
  version: 1.3.6
103
160
  requirements: []
104
-
105
161
  rubyforge_project: by_star
106
- rubygems_version: 1.8.8
162
+ rubygems_version: 1.8.15
107
163
  signing_key:
108
164
  specification_version: 3
109
165
  summary: ActiveRecord extension for easier date scopes and time ranges
110
166
  test_files: []
111
-
data/init.rb DELETED
@@ -1,2 +0,0 @@
1
- require 'by_star'
2
- ActiveRecord::Base.send :include, ByStar
@@ -1,23 +0,0 @@
1
- module ByStar
2
- module Calculations
3
- include Count
4
- include Sum
5
-
6
- private
7
- def work_out_month(time, year=Time.zone.now.year)
8
- year ||= Time.zone.now.year
9
- # Work out what actual month is.
10
- month = if time.is_a?(Numeric) && (1..12).include?(time)
11
- time
12
- elsif valid_time_or_date?(time)
13
- year = time.year
14
- time.month
15
- elsif time.is_a?(String) && Date::MONTHNAMES.include?(time)
16
- Date::MONTHNAMES.index(time)
17
- else
18
- raise ParseError, "Value is not an integer (between 1 and 12), time object or string (make sure you typed the name right)."
19
- end
20
- [year, month]
21
- end
22
- end
23
- end
@@ -1,20 +0,0 @@
1
- module ByStar
2
- module Calculations
3
- module Count
4
- def count_by_year(field=nil, year=Time.zone.now.year, options={}, &block)
5
- db_field = options.delete(:field)
6
- scoped_by(block) do
7
- count(field, { :conditions => conditions_for_range(start_of_year(year), end_of_year(year), db_field) }.reverse_merge!(options))
8
- end
9
- end
10
-
11
- def count_by_month(field=nil, month=Time.now.month, options={}, &block)
12
- db_field = options.delete(:field)
13
- year, month = work_out_month(month, options.delete(:year))
14
- scoped_by(block) do
15
- count(field, { :conditions => conditions_for_range(start_of_month(month, year), end_of_month(month, year), db_field) }.reverse_merge!(options))
16
- end
17
- end
18
- end
19
- end
20
- end
@@ -1,25 +0,0 @@
1
- module ByStar
2
- module Calculations
3
- module Sum
4
- def sum_by_year(field, year=Time.zone.now.year, options={}, &block)
5
- scoped_by(block) do
6
- sum(field, { :conditions => conditions_for_range(start_of_year(year), end_of_year(year), options.delete(:field)) }.reverse_merge!(options))
7
- end
8
- end
9
-
10
- def sum_by_month(field, month=Time.zone.now.month, options={}, &block)
11
- year, month = work_out_month(month, options.delete(:year))
12
- scoped_by(block) do
13
- sum(field, { :conditions => conditions_for_range(start_of_month(month, year), end_of_month(month, year), options.delete(:field)) }.reverse_merge!(options))
14
- end
15
- end
16
-
17
- def sum_by_day(field, day=Time.zone.now, options={}, &block)
18
- scoped_by(block) do
19
- day = parse(day)
20
- sum(field, { :conditions => conditions_for_range(day.beginning_of_day, day.end_of_day, options.delete(:field)) }.reverse_merge!(options))
21
- end
22
- end
23
- end
24
- end
25
- end
@@ -1,15 +0,0 @@
1
- module ByStar
2
- module Neighbours
3
- # Find the previous record to this.
4
- def previous(field=nil)
5
- field = field || self.class.by_star_field
6
- self.class.past(self.send(field.to_s.split(".").last)) { { :order => "#{field} DESC" }}.first
7
- end
8
-
9
- # Find the next record to this.
10
- def next(field=nil)
11
- field = field || self.class.by_star_field
12
- self.class.future(self.send(field.to_s.split(".").last)) { { :order => "#{field} ASC" }}.first
13
- end
14
- end
15
- end
@@ -1,23 +0,0 @@
1
- module ByStar
2
- module RangeCalculations
3
-
4
- private
5
-
6
- def start_of_year(year=Time.zone.now.year)
7
- Time.utc(year, 1, 1)
8
- end
9
-
10
- def end_of_year(year=Time.zone.now.year)
11
- start_of_year(year).end_of_year
12
- end
13
-
14
- def start_of_month(month, year=Timeow.year)
15
- Time.utc(year, month, 1)
16
- end
17
-
18
- def end_of_month(month, year=Time.now.year)
19
- start_of_month(month, year).end_of_month
20
- end
21
- end
22
-
23
- end
@@ -1,18 +0,0 @@
1
- module Shared
2
- def conditions_for_range(start_time, end_time, field=nil)
3
- field = "#{table_name}.#{field}" if field
4
- field ||= by_star_field
5
- ["#{field} >= ? AND #{field} <= ?", start_time.utc, end_time.utc]
6
- end
7
-
8
- private
9
- def scoped_by(options=nil, &block)
10
- if options && scope = options.call
11
- with_scope(:find => scope) do
12
- block.call
13
- end
14
- else
15
- block.call
16
- end
17
- end
18
- end
@@ -1,276 +0,0 @@
1
- module ByStar
2
- module Vanilla
3
- # Examples:
4
- # by_year(2010)
5
- # # 2-digit year:
6
- # by_year(10)
7
- # # Time or Date object:
8
- # by_year(time)
9
- # # String:
10
- # by_year("2010")
11
- def by_year(time=Time.zone.now.year, options={}, &block)
12
- year = work_out_year(time)
13
- start_time = start_of_year(year)
14
- end_time = start_time.end_of_year
15
- by_star(start_time, end_time, options, &block)
16
- rescue ArgumentError
17
- raise ParseError, "Invalid arguments detected, year may possibly be outside of valid range (1902-2039). This is no longer a problem on Ruby versions >= 1.8.7, so we recommend you upgrade to at least 1.8.7."
18
- end
19
-
20
- # Examples:
21
- # by_month(1)
22
- # by_month("January")
23
- # by_month("January", :year => 2008)
24
- # by_month(time)
25
- def by_month(time=Time.zone.now.month, options={}, &block)
26
- time = Time.zone.now.month if time.nil?
27
- year, month = work_out_month(time, options.delete(:year))
28
-
29
- start_time = start_of_month(month, year)
30
- end_time = start_time.end_of_month
31
-
32
- by_star(start_time, end_time, options, &block)
33
- end
34
-
35
- # Examples:
36
- # # 18th fortnight of 2004
37
- # Post.by_fortnight(18, :year => 2004)
38
- def by_fortnight(time=Time.zone.now, options = {}, &block)
39
- time = parse(time)
40
-
41
- # If options[:year] is passed in, use that year regardless.
42
- year = work_out_year(options[:year]) if options[:year]
43
- # If the first argument is a date or time, ask it for the year
44
- year ||= time.year unless time.is_a?(Numeric)
45
- # If the first argument is a fixnum, assume this year.
46
- year ||= Time.zone.now.year
47
-
48
- # Dodgy!
49
- # Surely there's a method in Rails to do this.
50
- start_time = if valid_time_or_date?(time)
51
- time.beginning_of_year + (time.strftime("%U").to_i).weeks
52
- elsif time.is_a?(Numeric) && time <= 26
53
- Time.utc(year, 1, 1) + ((time.to_i) * 2).weeks
54
- else
55
- raise ParseError, "by_fortnight takes only a Time or Date object, a Fixnum (less than or equal to 26) or a Chronicable string."
56
- end
57
- start_time = start_time.beginning_of_week
58
- end_time = start_time + 2.weeks
59
- by_star(start_time, end_time, options, &block)
60
- end
61
-
62
- # Examples:
63
- # # 36th week
64
- # Post.by_week(36)
65
- # Post.by_week(36.54)
66
- # Post.by_week(36, :year => 2004)
67
- # Post.by_week(<Time object>)
68
- # Post.by_week(<Date object>)
69
- # Post.by_week("next tuesday")
70
- def by_week(time=Time.zone.now, options = {}, &block)
71
- time = parse(time)
72
-
73
- # If options[:year] is passed in, use that year regardless.
74
- year = work_out_year(options.delete(:year)) if options[:year]
75
- # If the first argument is a date or time, ask it for the year
76
- year ||= time.year unless time.is_a?(Numeric)
77
- # If the first argument is a fixnum, assume this year.
78
- year ||= Time.zone.now.year
79
-
80
- # Dodgy!
81
- # Surely there's a method in Rails to do this.
82
- start_time = if valid_time_or_date?(time)
83
- weeks = time.strftime("%U").to_i
84
- Time.zone.now.beginning_of_year
85
- elsif time.is_a?(Numeric) && time < 53
86
- weeks = time.to_i
87
- Time.utc(year, 1, 1)
88
- else
89
- raise ParseError, "by_week takes only a Time or Date object, a Fixnum (less than or equal to 53) or a Chronicable string."
90
- end
91
- # Make the start of the week predictably Sunday.
92
- start_time.strftime("%w").to_i != 0 ? start_time - (7 - start_time.strftime("%w").to_i).days : start_time
93
- start_time += weeks.weeks
94
- end_time = start_time + 1.week
95
- by_star(start_time, end_time, options, &block)
96
- end
97
-
98
-
99
- # Examples:
100
- # Post.by_weekend
101
- # Post.by_weekend(Time.now + 5.days)
102
- # Post.by_weekend(Date.today + 5)
103
- # Post.by_weekend("next tuesday")
104
- def by_weekend(time=Time.now, options = {}, &block)
105
- time = parse(time)
106
- start_time = time.beginning_of_weekend
107
- end_time = (start_time + 1.day).end_of_day
108
- by_star(start_time, end_time, options, &block)
109
- end
110
-
111
-
112
- # Examples:
113
- # Post.by_current_weekend
114
- def by_current_weekend(options = {}, &block)
115
- time = Time.zone.now
116
- # Friday, 3pm
117
- start_time = time.beginning_of_weekend
118
- # Monday, 3am
119
- end_time = time.end_of_weekend
120
- by_star(start_time, end_time, options, &block)
121
- end
122
-
123
- # Examples:
124
- # Post.by_current_work_week
125
- def by_current_work_week(options = {}, &block)
126
- time = Time.zone.now
127
- # Monday, 3am
128
- time = time + 1.week if time.wday == 6 || time.wday == 0
129
- start_time = time.beginning_of_week + 3.hours
130
- # Friday, 3pm
131
- end_time = time.beginning_of_weekend
132
- by_star(start_time, end_time, options, &block)
133
- end
134
-
135
-
136
- # Examples:
137
- # Post.by_day
138
- # Post.by_day(Time.yesterday)
139
- # Post.by_day("next tuesday")
140
- def by_day(time = Time.zone.now, options = {}, &block)
141
- time = parse(time)
142
- by_star(time.beginning_of_day, time.end_of_day, options, &block)
143
- end
144
- alias_method :today, :by_day
145
-
146
- # Examples:
147
- # Post.yesterday
148
- # # 2 days ago:
149
- # Post.yesterday(Time.yesterday)
150
- # # day before next tuesday
151
- # Post.yesterday("next tuesday")
152
- def yesterday(time = Time.zone.now, options = {}, &block)
153
- time = parse(time)
154
- by_day(time.advance(:days => -1), options, &block)
155
- end
156
-
157
- # Examples:
158
- # Post.tomorrow
159
- # # 2 days from now:
160
- # Post.tomorrow(Time.tomorrow)
161
- # # day after next tuesday
162
- # Post.tomorrow("next tuesday")
163
- def tomorrow(time = Time.zone.now, options = {}, &block)
164
- time = parse(time)
165
- by_day(time.advance(:days => 1), options, &block)
166
- end
167
-
168
- # Scopes to records older than current or given time
169
- # Post.past
170
- # Post.past()
171
- def past(time = Time.zone.now, options = {}, &block)
172
- time = parse(time)
173
- by_direction("<", time, options, &block)
174
- end
175
-
176
- # Scopes to records newer than current or given time
177
- def future(time = Time.zone.now, options = {}, &block)
178
- time = parse(time)
179
- by_direction(">", time, options, &block)
180
- end
181
-
182
- private
183
-
184
- def by_direction(condition, time, options = {}, &block)
185
- field = options.delete(:field) || by_star_field
186
- ensure_valid_options(options)
187
- result = scoped({ :conditions => ["#{field} #{condition} ?", time.utc] }.merge(options))
188
- result = result.scoped(block.call) if block_given?
189
- result
190
- end
191
-
192
- # scopes results between start_time and end_time
193
- def by_star(start_time, end_time, options = {}, &block)
194
- start_time = parse(start_time)
195
- end_time = parse(end_time)
196
-
197
-
198
- raise ParseError, "End time is before start time, searching like this will return no results." if end_time < start_time
199
- field = options.delete(:field)
200
- ensure_valid_options(options)
201
-
202
- scoping = { :conditions => conditions_for_range(start_time, end_time, field) }.merge(options)
203
- result = scoped(scoping)
204
- result = result.scoped(block.call) if block_given?
205
- result
206
- end
207
-
208
- def ensure_valid_options(options)
209
- if respond_to?(:validate_find_options)
210
- validate_find_options(options)
211
- else
212
- options.assert_valid_keys(ActiveRecord::SpawnMethods::VALID_FIND_OPTIONS)
213
- end
214
- end
215
-
216
- alias :between :by_star
217
- public :between
218
-
219
- # This will work for the next 30 years (written in 2009)
220
- def work_out_year(value)
221
- case value
222
- when 0..39
223
- 2000 + value
224
- when 40..99
225
- 1900 + value
226
- when nil
227
- Time.zone.now.year
228
- else
229
- # We may be passed something that's not a straight out integer
230
- # These things include: BigDecimals, Floats and Strings.
231
- value.to_i
232
- end
233
- end
234
-
235
- # Checks if the object is a Time, Date or TimeWithZone object.
236
- def valid_time_or_date?(value)
237
- value.is_a?(Time) || value.is_a?(Date) || value.is_a?(ActiveSupport::TimeWithZone)
238
- end
239
-
240
- def parse(object)
241
- object = case object.class.to_s
242
- when "NilClass"
243
- o = Time.zone.now
244
- when "String"
245
- o = object
246
- Chronic.parse(object, :now => Time.zone.now)
247
- when "Date"
248
- object.to_time(:utc)
249
- else
250
- object
251
- end
252
- raise ParseError, "Chronic couldn't work out #{o.inspect}; please be more precise." if object.nil?
253
- object
254
- end
255
-
256
- def method_missing(method, *args)
257
- if method.to_s =~ /^(as_of|up_to)_(.+)$/
258
- method = $1
259
- expr = $2.humanize
260
- unless time = parse(expr)
261
- raise ParseError, "Chronic couldn't work out #{expr.inspect}; please be more precise."
262
- end
263
-
264
- reference = args.first || Time.now
265
-
266
- if "as_of" == method
267
- between(time, reference)
268
- else
269
- between(reference, time)
270
- end
271
- else
272
- super
273
- end
274
- end
275
- end
276
- end