groupdate 1.0.5 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b79c5fbce92b20167a5d590b155aa54a5f9a7719
4
- data.tar.gz: 8fc3b7483fbb78e6dd28b1aa993eb6f7554aea49
3
+ metadata.gz: 00f2a25fe5b1a02e4b8a6e2b483e407ed4d5d76e
4
+ data.tar.gz: 5f6c81ee95f601a8ad189d706c53b5e57cf6d483
5
5
  SHA512:
6
- metadata.gz: 23fb19dd4593f11e762e9728c9e637831aa00e64a466e8a3def9ccc0e51817c14150f387c27461d457cb27a6c310c76975f0383b4c24bc635d5fe06d04963554
7
- data.tar.gz: d53817d4a0825181dafd79532107184aaab0ae473f3e697b26e6a44baa00674be21532b7757e8f119cc03aa26c1ae49bc6710eb180614133eb2b0e6e913cae2a
6
+ metadata.gz: e3f980694ad4a61ae5a3915720f8e90a4d01fd62e865aa5db751f06c3fb4bc87b3b91f0681cf0d49ba39287b08aeb1ba7bbfe78b86d1fe3d8554b3f4754e6113
7
+ data.tar.gz: 6700771e7de2ad8e0153e58efaa417fcbc73e5fd8f55beaa5af5314fc54d46425ea2d9ecacbed8a28a71f49931fa64f717f657b51da26e9203c2ed2b3f99fae9
data/.gitignore CHANGED
@@ -15,3 +15,5 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
+ .ruby-version
19
+ .ruby-gemset
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ # 2.0.0
2
+
3
+ - Returns entire series by default
4
+ - Added day_start option
5
+ - Better interface
6
+
1
7
  # 1.0.5
2
8
 
3
9
  - Added global time_zone option
data/README.md CHANGED
@@ -4,10 +4,8 @@ The simplest way to group by:
4
4
 
5
5
  - day
6
6
  - week
7
- - month
8
- - day of the week
9
7
  - hour of the day
10
- - and more (complete list at bottom)
8
+ - and more (complete list below)
11
9
 
12
10
  :tada: Time zones supported!! **the best part**
13
11
 
@@ -21,7 +19,9 @@ Supports PostgreSQL and MySQL
21
19
 
22
20
  :cupid: Goes hand in hand with [Chartkick](http://ankane.github.io/chartkick/)
23
21
 
24
- ## Usage
22
+ ## Get Started
23
+
24
+ Group by day
25
25
 
26
26
  ```ruby
27
27
  User.group_by_day(:created_at).count
@@ -30,141 +30,76 @@ User.group_by_day(:created_at).count
30
30
  # 2013-04-17 00:00:00 UTC => 100,
31
31
  # 2013-04-18 00:00:00 UTC => 34
32
32
  # }
33
-
34
- Task.group_by_month(:updated_at).count
35
- # {
36
- # 2013-02-01 00:00:00 UTC => 84,
37
- # 2013-03-01 00:00:00 UTC => 23,
38
- # 2013-04-01 00:00:00 UTC => 44
39
- # }
40
-
41
- Goal.group_by_year(:accomplished_at).count
42
- # {
43
- # 2011-01-01 00:00:00 UTC => 7,
44
- # 2012-01-01 00:00:00 UTC => 11,
45
- # 2013-01-01 00:00:00 UTC => 3
46
- # }
47
33
  ```
48
34
 
49
- The default time zone is `Time.zone`. Pass a time zone as the second argument.
35
+ Results are returned in ascending order, so no need to sort.
50
36
 
51
- ```ruby
52
- User.group_by_week(:created_at, "Pacific Time (US & Canada)").count
53
- # {
54
- # 2013-03-03 08:00:00 UTC => 80,
55
- # 2013-03-10 08:00:00 UTC => 70,
56
- # 2013-03-17 07:00:00 UTC => 54
57
- # }
37
+ You can also group by:
58
38
 
59
- # equivalently
60
- time_zone = ActiveSupport::TimeZone["Pacific Time (US & Canada)"]
61
- User.group_by_week(:created_at, time_zone).count
62
- ```
39
+ - second
40
+ - minute
41
+ - hour
42
+ - week
43
+ - month
44
+ - year
63
45
 
64
- **Note:** Weeks start on Sunday by default. For other days, use:
46
+ and
65
47
 
66
- ```ruby
67
- User.group_by_week(:created_at, :start => :mon) # first three letters of day
48
+ - hour_of_day
49
+ - day_of_week (Sunday = 0, Monday = 1, etc)
50
+
51
+ ### Time Zones
68
52
 
69
- # must be the last argument
70
- User.group_by_week(:created_at, time_zone, :start => :sat)
53
+ The default time zone is `Time.zone`. Change this with:
71
54
 
72
- # change globally
73
- Groupdate.week_start = :mon
55
+ ```ruby
56
+ Groupdate.time_zone = "Pacific Time (US & Canada)"
74
57
  ```
75
58
 
76
- You can also group by the day of the week or hour of the day.
59
+ or
77
60
 
78
61
  ```ruby
79
- # day of the week
80
- User.group_by_day_of_week(:created_at).count
62
+ User.group_by_week(:created_at, time_zone: "Pacific Time (US & Canada)").count
81
63
  # {
82
- # 0 => 54, # Sunday
83
- # 1 => 2, # Monday
84
- # ...
85
- # 6 => 3 # Saturday
86
- # }
87
-
88
- # hour of the day
89
- User.group_by_hour_of_day(:created_at, "Pacific Time (US & Canada)").count
90
- # {
91
- # 0 => 34,
92
- # 1 => 61,
93
- # ...
94
- # 23 => 12
64
+ # 2013-03-03 08:00:00 UTC => 80,
65
+ # 2013-03-10 08:00:00 UTC => 70,
66
+ # 2013-03-17 07:00:00 UTC => 54
95
67
  # }
96
68
  ```
97
69
 
98
- You can order results with:
99
-
100
- ```ruby
101
- User.group_by_day(:created_at).order("day asc").count
102
-
103
- User.group_by_week(:created_at).order("week desc").count
70
+ Time zone objects also work.
104
71
 
105
- User.group_by_hour_of_day(:created_at).order("hour_of_day asc").count
106
- ```
72
+ ### Week Start
107
73
 
108
- Use it with anywhere you can use `group`.
74
+ Weeks start on Sunday by default. Change this with:
109
75
 
110
76
  ```ruby
111
- Task.completed.group_by_hour(:completed_at).average(:priority)
77
+ Groupdate.week_start = :mon # first three letters of day
112
78
  ```
113
79
 
114
- Go nuts!
80
+ or
115
81
 
116
82
  ```ruby
117
- Request.where(page: "/home").group_by_minute(:started_at).maximum(:request_time)
83
+ User.group_by_week(:created_at, week_start: :mon).count
118
84
  ```
119
85
 
120
- ### Show me the series :moneybag:
86
+ ### Day Start
121
87
 
122
- You have two users - one created on May 2 and one on May 5.
88
+ You can change the hour days start with:
123
89
 
124
90
  ```ruby
125
- User.group_by_day(:created_at).count
126
- # {
127
- # 2013-05-02 00:00:00 UTC => 1,
128
- # 2013-05-05 00:00:00 UTC => 1
129
- # }
91
+ Groupdate.day_start = 2 # 2 am - 2 am
130
92
  ```
131
93
 
132
- Awesome, but you want to see the first week of May. Pass a range as the third argument.
94
+ or
133
95
 
134
96
  ```ruby
135
- # pretend today is May 7
136
- time_range = 6.days.ago..Time.now
137
-
138
- User.group_by_day(:created_at, Time.zone, time_range).count
139
- # {
140
- # 2013-05-01 00:00:00 UTC => 0,
141
- # 2013-05-02 00:00:00 UTC => 1,
142
- # 2013-05-03 00:00:00 UTC => 0,
143
- # 2013-05-04 00:00:00 UTC => 0,
144
- # 2013-05-05 00:00:00 UTC => 1,
145
- # 2013-05-06 00:00:00 UTC => 0,
146
- # 2013-05-07 00:00:00 UTC => 0
147
- # }
148
-
149
- User.group_by_day_of_week(:created_at, Time.zone, time_range).count
150
- # {
151
- # 0 => 0,
152
- # 1 => 1,
153
- # 2 => 0,
154
- # 3 => 0,
155
- # 4 => 1,
156
- # 5 => 0,
157
- # 6 => 0
158
- # }
97
+ User.group_by_day(:created_at, day_start: 2).count
159
98
  ```
160
99
 
161
- Results are returned in ascending order, so no need to sort.
162
-
163
- Also, this form of the method returns a Groupdate::Series instead of an ActiveRecord::Relation. ActiveRecord::Relation method calls (like `where` and `joins`) should come before this.
164
-
165
100
  ## Installation
166
101
 
167
- Add this line to your application's Gemfile:
102
+ Add this line to your applications Gemfile:
168
103
 
169
104
  ```ruby
170
105
  gem 'groupdate'
@@ -190,60 +125,31 @@ gem "activerecord-jdbcpostgresql-adapter", :github => "jruby/activerecord-jdbc-a
190
125
  gem "activerecord-jdbcmysql-adapter", :github => "jruby/activerecord-jdbc-adapter"
191
126
  ```
192
127
 
193
- ## Reference
194
-
195
- The default time zone is `Time.zone`. To change this, use:
196
-
197
- ```ruby
198
- Groupdate.time_zone = "Pacific Time (US & Canada)"
199
- ```
200
-
201
- ## Complete list
202
-
203
- group_by_?
204
-
205
- - second
206
- - minute
207
- - hour
208
- - day
209
- - week
210
- - month
211
- - year
212
- - hour_of_day
213
- - day_of_week
214
-
215
- ## Note
128
+ ## Upgrading to 2.0
216
129
 
217
- activerecord <= 4.0.0.beta1 and the pg gem returns String objects instead of Time objects.
218
- [This is fixed on activerecord master](https://github.com/rails/rails/commit/2cc09441c2de57b024b11ba666ba1e72c2b20cfe)
130
+ Groupdate 2.0 brings a number a great improvements.
219
131
 
220
- ```ruby
221
- User.group_by_day(:created_at).count
132
+ - the entire series is returned by default
133
+ - the `day_start` option
134
+ - an improved interface
222
135
 
223
- # mysql2
224
- # pg and activerecord master
225
- {2013-04-22 00:00:00 UTC => 1} # Time object
136
+ However, there are a few things to be aware of when upgrading.
226
137
 
227
- # pg and activerecord <= 4.0.0.beta1
228
- {"2013-04-22 00:00:00+00" => 1} # String
229
- ```
230
-
231
- Another data type inconsistency
138
+ 1. Groupdate methods must come after any `where`, `joins`, or `includes`.
232
139
 
233
- ```ruby
234
- User.group_by_day_of_week(:created_at).count
140
+ Throws error
235
141
 
236
- # mysql2
237
- {0 => 1, 4 => 1} # Integer
142
+ ```ruby
143
+ User.group_by_day(:created_at).where(company_id: 1).count
144
+ ```
238
145
 
239
- # pg and activerecord <= 4.0.0.beta1
240
- {"0" => 1, "4" => 1} # String
146
+ :moneybag:
241
147
 
242
- # pg and activerecord master
243
- {0.0 => 1, 4.0 => 1} # Float
244
- ```
148
+ ```ruby
149
+ User.where(company_id: 1).group_by_day(:created_at).count
150
+ ```
245
151
 
246
- These are *not* a result of groupdate (and unfortunately cannot be fixed by groupdate)
152
+ 2. `Time` keys are now returned for every database adapter. Some older adapters previously returned `String` keys.
247
153
 
248
154
  ## History
249
155
 
data/lib/groupdate.rb CHANGED
@@ -23,7 +23,7 @@ module ActiveRecord
23
23
  end
24
24
 
25
25
  module Groupdate
26
- mattr_accessor :week_start
27
- mattr_accessor :time_zone
26
+ mattr_accessor :week_start, :day_start, :time_zone
28
27
  self.week_start = :sun
28
+ self.day_start = 0
29
29
  end
@@ -11,7 +11,7 @@ module Groupdate
11
11
  args = args.dup
12
12
  options = args[-1].is_a?(Hash) ? args.pop : {}
13
13
  column = connection.quote_table_name(args[0])
14
- time_zone = args[1] || Groupdate.time_zone || Time.zone || "Etc/UTC"
14
+ time_zone = args[1] || options[:time_zone] || Groupdate.time_zone || Time.zone || "Etc/UTC"
15
15
  if time_zone.is_a?(ActiveSupport::TimeZone) or time_zone = ActiveSupport::TimeZone[time_zone]
16
16
  time_zone = time_zone.tzinfo.name
17
17
  else
@@ -19,22 +19,25 @@ module Groupdate
19
19
  end
20
20
 
21
21
  # for week
22
- week_start = [:mon, :tue, :wed, :thu, :fri, :sat, :sun].index((options[:start] || Groupdate.week_start).to_sym)
22
+ week_start = [:mon, :tue, :wed, :thu, :fri, :sat, :sun].index((options[:week_start] || options[:start] || Groupdate.week_start).to_sym)
23
23
  if field == "week" and !week_start
24
24
  raise "Unrecognized :start option"
25
25
  end
26
26
 
27
+ # for day
28
+ day_start = (options[:day_start] || Groupdate.day_start).to_i
29
+
27
30
  query =
28
31
  case connection.adapter_name
29
32
  when "MySQL", "Mysql2"
30
33
  case field
31
34
  when "day_of_week" # Sunday = 0, Monday = 1, etc
32
35
  # use CONCAT for consistent return type (String)
33
- ["DAYOFWEEK(CONVERT_TZ(#{column}, '+00:00', ?)) - 1", time_zone]
36
+ ["DAYOFWEEK(CONVERT_TZ(DATE_SUB(#{column}, INTERVAL #{day_start} HOUR), '+00:00', ?)) - 1", time_zone]
34
37
  when "hour_of_day"
35
- ["EXTRACT(HOUR from CONVERT_TZ(#{column}, '+00:00', ?))", time_zone]
38
+ ["(EXTRACT(HOUR from CONVERT_TZ(#{column}, '+00:00', ?)) + 24 - #{day_start}) % 24", time_zone]
36
39
  when "week"
37
- ["CONVERT_TZ(DATE_FORMAT(CONVERT_TZ(DATE_SUB(#{column}, INTERVAL ((#{7 - week_start} + WEEKDAY(CONVERT_TZ(#{column}, '+00:00', ?))) % 7) DAY), '+00:00', ?), '%Y-%m-%d 00:00:00'), ?, '+00:00')", time_zone, time_zone, time_zone]
40
+ ["CONVERT_TZ(DATE_FORMAT(CONVERT_TZ(DATE_SUB(#{column}, INTERVAL ((#{7 - week_start} + WEEKDAY(CONVERT_TZ(#{column}, '+00:00', ?) - INTERVAL #{day_start} HOUR)) % 7) DAY) - INTERVAL #{day_start} HOUR, '+00:00', ?), '%Y-%m-%d 00:00:00') + INTERVAL #{day_start} HOUR, ?, '+00:00')", time_zone, time_zone, time_zone]
38
41
  else
39
42
  format =
40
43
  case field
@@ -50,28 +53,29 @@ module Groupdate
50
53
  "%Y-%m-01 00:00:00"
51
54
  else # year
52
55
  "%Y-01-01 00:00:00"
53
- end
56
+ end
54
57
 
55
- ["CONVERT_TZ(DATE_FORMAT(CONVERT_TZ(#{column}, '+00:00', ?), '#{format}'), ?, '+00:00')", time_zone, time_zone]
58
+ ["DATE_ADD(CONVERT_TZ(DATE_FORMAT(CONVERT_TZ(DATE_SUB(#{column}, INTERVAL #{day_start} HOUR), '+00:00', ?), '#{format}'), ?, '+00:00'), INTERVAL #{day_start} HOUR)", time_zone, time_zone]
56
59
  end
57
60
  when "PostgreSQL", "PostGIS"
58
61
  case field
59
62
  when "day_of_week"
60
- ["EXTRACT(DOW from #{column}::timestamptz AT TIME ZONE ?)::integer", time_zone]
63
+ ["EXTRACT(DOW from (#{column}::timestamptz AT TIME ZONE ? - INTERVAL '#{day_start} hour'))::integer", time_zone]
61
64
  when "hour_of_day"
62
- ["EXTRACT(HOUR from #{column}::timestamptz AT TIME ZONE ?)::integer", time_zone]
65
+ ["EXTRACT(HOUR from #{column}::timestamptz AT TIME ZONE ? - INTERVAL '#{day_start} hour')::integer", time_zone]
63
66
  when "week" # start on Sunday, not PostgreSQL default Monday
64
- ["(DATE_TRUNC('#{field}', (#{column}::timestamptz - INTERVAL '#{week_start} day') AT TIME ZONE ?) + INTERVAL '#{week_start} day') AT TIME ZONE ?", time_zone, time_zone]
67
+ ["(DATE_TRUNC('#{field}', (#{column}::timestamptz - INTERVAL '#{week_start} day' - INTERVAL '#{day_start}' hour) AT TIME ZONE ?) + INTERVAL '#{week_start} day' + INTERVAL '#{day_start}' hour) AT TIME ZONE ?", time_zone, time_zone]
65
68
  else
66
- ["DATE_TRUNC('#{field}', #{column}::timestamptz AT TIME ZONE ?) AT TIME ZONE ?", time_zone, time_zone]
69
+ ["(DATE_TRUNC('#{field}', (#{column}::timestamptz - INTERVAL '#{day_start} hour') AT TIME ZONE ?) + INTERVAL '#{day_start} hour') AT TIME ZONE ?", time_zone, time_zone]
67
70
  end
68
71
  else
69
72
  raise "Connection adapter not supported: #{connection.adapter_name}"
70
73
  end
71
74
 
72
75
  group = group(Groupdate::OrderHack.new(sanitize_sql_array(query), field, time_zone))
73
- if args[2]
74
- Series.new(group, field, column, time_zone, args[2], week_start)
76
+ range = args[2] || options[:range] || true
77
+ unless options[:series] == false
78
+ Series.new(group, field, column, time_zone, range, week_start, day_start)
75
79
  else
76
80
  group
77
81
  end
@@ -1,7 +1,7 @@
1
1
  module Groupdate
2
2
  class Series
3
3
 
4
- def initialize(relation, field, column, time_zone, time_range, week_start)
4
+ def initialize(relation, field, column, time_zone, time_range, week_start, day_start)
5
5
  if time_range.is_a?(Range)
6
6
  # doesn't matter whether we include the end of a ... range - it will be excluded later
7
7
  @relation = relation.where("#{column} >= ? AND #{column} <= ?", time_range.first, time_range.last)
@@ -12,6 +12,7 @@ module Groupdate
12
12
  @time_zone = time_zone
13
13
  @time_range = time_range
14
14
  @week_start = week_start
15
+ @day_start = day_start
15
16
  end
16
17
 
17
18
  def build_series(count)
@@ -43,37 +44,42 @@ module Groupdate
43
44
  sorted_keys.first..sorted_keys.last
44
45
  end
45
46
 
46
- # determine start time
47
- time = time_range.first.to_time.in_time_zone(@time_zone)
48
- starts_at =
49
- case @field
50
- when "second"
51
- time.change(:usec => 0)
52
- when "minute"
53
- time.change(:sec => 0)
54
- when "hour"
55
- time.change(:min => 0)
56
- when "day"
57
- time.beginning_of_day
58
- when "week"
59
- # same logic as MySQL group
60
- weekday = (time.wday - 1) % 7
61
- (time - ((7 - @week_start + weekday) % 7).days).midnight
62
- when "month"
63
- time.beginning_of_month
64
- else # year
65
- time.beginning_of_year
66
- end
47
+ if time_range.first
48
+ # determine start time
49
+ time = time_range.first.to_time.in_time_zone(@time_zone) - @day_start.hours
50
+ starts_at =
51
+ case @field
52
+ when "second"
53
+ time.change(:usec => 0)
54
+ when "minute"
55
+ time.change(:sec => 0)
56
+ when "hour"
57
+ time.change(:min => 0)
58
+ when "day"
59
+ time.beginning_of_day
60
+ when "week"
61
+ # same logic as MySQL group
62
+ weekday = (time.wday - 1) % 7
63
+ (time - ((7 - @week_start + weekday) % 7).days).midnight
64
+ when "month"
65
+ time.beginning_of_month
66
+ else # year
67
+ time.beginning_of_year
68
+ end
67
69
 
68
- series = [starts_at]
70
+ starts_at += @day_start.hours
71
+ series = [starts_at]
69
72
 
70
- step = 1.send(@field)
73
+ step = 1.send(@field)
71
74
 
72
- while time_range.cover?(series.last + step)
73
- series << series.last + step
74
- end
75
+ while time_range.cover?(series.last + step)
76
+ series << series.last + step
77
+ end
75
78
 
76
- series.map{|s| s.to_time.utc }
79
+ series.map{|s| s.to_time.utc }
80
+ else
81
+ []
82
+ end
77
83
  end
78
84
 
79
85
  Hash[series.map do |k|
@@ -85,6 +91,8 @@ module Groupdate
85
91
  # https://github.com/rails/rails/blob/master/activerecord/lib/active_record/relation/calculations.rb
86
92
  if ActiveRecord::Calculations.method_defined?(method)
87
93
  build_series(@relation.send(method, *args, &block))
94
+ elsif [:joins, :includes, :where].include?(method)
95
+ raise NoMethodError, "#{method} must come before the group_by_#{@field} method"
88
96
  else
89
97
  raise NoMethodError, "valid methods are: #{ActiveRecord::Calculations.instance_methods.join(", ")}"
90
98
  end
@@ -1,3 +1,3 @@
1
1
  module Groupdate
2
- VERSION = "1.0.5"
2
+ VERSION = "2.0.0"
3
3
  end
data/test/mysql_test.rb CHANGED
@@ -1,4 +1,4 @@
1
- require "test_helper"
1
+ require_relative "test_helper"
2
2
 
3
3
  class TestMysql < Minitest::Unit::TestCase
4
4
  include TestGroupdate
@@ -1,4 +1,4 @@
1
- require "test_helper"
1
+ require_relative "test_helper"
2
2
 
3
3
  class TestPostgresql < Minitest::Unit::TestCase
4
4
  include TestGroupdate
data/test/test_helper.rb CHANGED
@@ -84,6 +84,24 @@ module TestGroupdate
84
84
  assert_result_time :day, "2013-05-03 00:00:00 PDT", "2013-05-03 07:00:00", true
85
85
  end
86
86
 
87
+ # day hour starts at 2 am
88
+
89
+ def test_test_day_end_of_day_day_start_2am
90
+ assert_result_time :day, "2013-05-03 02:00:00 UTC", "2013-05-04 01:59:59", false, :day_start => 2
91
+ end
92
+
93
+ def test_test_day_start_of_day_day_start_2am
94
+ assert_result_time :day, "2013-05-03 02:00:00 UTC", "2013-05-03 02:00:00", false, :day_start => 2
95
+ end
96
+
97
+ def test_test_day_end_of_day_with_time_zone_day_start_2am
98
+ assert_result_time :day, "2013-05-03 02:00:00 PDT", "2013-05-04 07:59:59", true, :day_start => 2
99
+ end
100
+
101
+ def test_test_day_start_of_day_with_time_zone_day_start_2am
102
+ assert_result_time :day, "2013-05-03 02:00:00 PDT", "2013-05-03 09:00:00", true, :day_start => 2
103
+ end
104
+
87
105
  # week
88
106
 
89
107
  def test_week_end_of_week
@@ -105,37 +123,55 @@ module TestGroupdate
105
123
  # week starting on monday
106
124
 
107
125
  def test_week_end_of_week_mon
108
- assert_result_time :week, "2013-03-18 00:00:00 UTC", "2013-03-24 23:59:59", false, :start => :mon
126
+ assert_result_time :week, "2013-03-18 00:00:00 UTC", "2013-03-24 23:59:59", false, week_start: :mon
109
127
  end
110
128
 
111
129
  def test_week_start_of_week_mon
112
- assert_result_time :week, "2013-03-25 00:00:00 UTC", "2013-03-25 00:00:00", false, :start => :mon
130
+ assert_result_time :week, "2013-03-25 00:00:00 UTC", "2013-03-25 00:00:00", false, week_start: :mon
113
131
  end
114
132
 
115
133
  def test_week_end_of_week_with_time_zone_mon
116
- assert_result_time :week, "2013-03-11 00:00:00 PDT", "2013-03-18 06:59:59", true, :start => :mon
134
+ assert_result_time :week, "2013-03-11 00:00:00 PDT", "2013-03-18 06:59:59", true, week_start: :mon
117
135
  end
118
136
 
119
137
  def test_week_start_of_week_with_time_zone_mon
120
- assert_result_time :week, "2013-03-18 00:00:00 PDT", "2013-03-18 07:00:00", true, :start => :mon
138
+ assert_result_time :week, "2013-03-18 00:00:00 PDT", "2013-03-18 07:00:00", true, week_start: :mon
121
139
  end
122
140
 
123
141
  # week starting on saturday
124
142
 
125
143
  def test_week_end_of_week_sat
126
- assert_result_time :week, "2013-03-16 00:00:00 UTC", "2013-03-22 23:59:59", false, :start => :sat
144
+ assert_result_time :week, "2013-03-16 00:00:00 UTC", "2013-03-22 23:59:59", false, week_start: :sat
127
145
  end
128
146
 
129
147
  def test_week_start_of_week_sat
130
- assert_result_time :week, "2013-03-23 00:00:00 UTC", "2013-03-23 00:00:00", false, :start => :sat
148
+ assert_result_time :week, "2013-03-23 00:00:00 UTC", "2013-03-23 00:00:00", false, week_start: :sat
131
149
  end
132
150
 
133
151
  def test_week_end_of_week_with_time_zone_sat
134
- assert_result_time :week, "2013-03-09 00:00:00 PST", "2013-03-16 06:59:59", true, :start => :sat
152
+ assert_result_time :week, "2013-03-09 00:00:00 PST", "2013-03-16 06:59:59", true, week_start: :sat
135
153
  end
136
154
 
137
155
  def test_week_start_of_week_with_time_zone_sat
138
- assert_result_time :week, "2013-03-16 00:00:00 PDT", "2013-03-16 07:00:00", true, :start => :sat
156
+ assert_result_time :week, "2013-03-16 00:00:00 PDT", "2013-03-16 07:00:00", true, week_start: :sat
157
+ end
158
+
159
+ # week starting at 2am
160
+
161
+ def test_week_end_of_week_day_start_2am
162
+ assert_result_time :week, "2013-03-17 02:00:00 UTC", "2013-03-24 01:59:59", false, :day_start => 2
163
+ end
164
+
165
+ def test_week_start_of_week_day_start_2am
166
+ assert_result_time :week, "2013-03-17 02:00:00 UTC", "2013-03-17 02:00:00", false, :day_start => 2
167
+ end
168
+
169
+ def test_week_end_of_week_day_with_time_zone_start_2am
170
+ assert_result_time :week, "2013-03-17 02:00:00 PDT", "2013-03-24 08:59:59", true, :day_start => 2
171
+ end
172
+
173
+ def test_week_start_of_week_day_with_time_zone_start_2am
174
+ assert_result_time :week, "2013-03-17 02:00:00 PDT", "2013-03-17 09:00:00", true, :day_start => 2
139
175
  end
140
176
 
141
177
  # month
@@ -156,6 +192,24 @@ module TestGroupdate
156
192
  assert_result_time :month, "2013-06-01 00:00:00 PDT", "2013-06-01 07:00:00", true
157
193
  end
158
194
 
195
+ # month starts at 2am
196
+
197
+ def test_month_end_of_month_day_start_2am
198
+ assert_result_time :month, "2013-03-01 02:00:00 UTC", "2013-04-01 01:59:59", false, :day_start => 2
199
+ end
200
+
201
+ def test_month_start_of_month_day_start_2am
202
+ assert_result_time :month, "2013-03-01 02:00:00 UTC", "2013-03-01 02:00:00", false, :day_start => 2
203
+ end
204
+
205
+ def test_month_end_of_month_with_time_zone_day_start_2am
206
+ assert_result_time :month, "2013-03-01 02:00:00 PST", "2013-04-01 08:59:59", true, :day_start => 2
207
+ end
208
+
209
+ def test_month_start_of_month_with_time_zone_day_start_2am
210
+ assert_result_time :month, "2013-03-01 02:00:00 PST", "2013-03-01 10:00:00", true, :day_start => 2
211
+ end
212
+
159
213
  # year
160
214
 
161
215
  def test_year_end_of_year
@@ -174,6 +228,24 @@ module TestGroupdate
174
228
  assert_result_time :year, "2014-01-01 00:00:00 PST", "2014-01-01 08:00:00", true
175
229
  end
176
230
 
231
+ # year starts at 2am
232
+
233
+ def test_year_end_of_year_day_start_2am
234
+ assert_result_time :year, "2013-01-01 02:00:00 UTC", "2014-01-01 01:59:59", false, :day_start => 2
235
+ end
236
+
237
+ def test_year_start_of_year_day_start_2am
238
+ assert_result_time :year, "2013-01-01 02:00:00 UTC", "2013-01-01 02:00:00", false, :day_start => 2
239
+ end
240
+
241
+ def test_year_end_of_year_with_time_zone_day_start_2am
242
+ assert_result_time :year, "2013-01-01 02:00:00 PST", "2014-01-01 09:59:59", true, :day_start => 2
243
+ end
244
+
245
+ def test_year_start_of_year_with_time_zone_day_start_2am
246
+ assert_result_time :year, "2013-01-01 02:00:00 PST", "2013-01-01 10:00:00", true, :day_start => 2
247
+ end
248
+
177
249
  # hour of day
178
250
 
179
251
  def test_hour_of_day_end_of_hour
@@ -192,6 +264,24 @@ module TestGroupdate
192
264
  assert_result :hour_of_day, 1, "2013-01-01 09:00:00", true
193
265
  end
194
266
 
267
+ # hour of day starts at 2am
268
+
269
+ def test_hour_of_day_end_of_day_day_start_2am
270
+ assert_result :hour_of_day, 23, "2013-01-01 01:59:59", false, :day_start => 2
271
+ end
272
+
273
+ def test_hour_of_day_start_of_day_day_start_2am
274
+ assert_result :hour_of_day, 0, "2013-01-01 02:00:00", false, :day_start => 2
275
+ end
276
+
277
+ def test_hour_of_day_end_of_day_with_time_zone_day_start_2am
278
+ assert_result :hour_of_day, 23, "2013-01-01 09:59:59", true, :day_start => 2
279
+ end
280
+
281
+ def test_hour_of_day_start_of_day_with_time_zone_day_start_2am
282
+ assert_result :hour_of_day, 0, "2013-01-01 10:00:00", true, :day_start => 2
283
+ end
284
+
195
285
  # day of week
196
286
 
197
287
  def test_day_of_week_end_of_day
@@ -210,6 +300,24 @@ module TestGroupdate
210
300
  assert_result :day_of_week, 3, "2013-01-02 08:00:00", true
211
301
  end
212
302
 
303
+ # day of week starts at 2am
304
+
305
+ def test_day_of_week_end_of_day_day_start_2am
306
+ assert_result :day_of_week, 3, "2013-01-03 01:59:59", false, :day_start => 2
307
+ end
308
+
309
+ def test_day_of_week_start_of_day_day_start_2am
310
+ assert_result :day_of_week, 3, "2013-01-02 02:00:00", false, :day_start => 2
311
+ end
312
+
313
+ def test_day_of_week_end_of_day_with_time_zone_day_start_2am
314
+ assert_result :day_of_week, 3, "2013-01-03 09:59:59", true, :day_start => 2
315
+ end
316
+
317
+ def test_day_of_week_start_of_day_with_time_zone_day_start_2am
318
+ assert_result :day_of_week, 3, "2013-01-02 10:00:00", true, :day_start => 2
319
+ end
320
+
213
321
  # zeros
214
322
 
215
323
  def test_zeros_second
@@ -241,19 +349,19 @@ module TestGroupdate
241
349
  end
242
350
 
243
351
  def test_zeros_week_mon
244
- assert_zeros :week, "2013-05-01 20:00:00 UTC", ["2013-04-22 00:00:00 UTC", "2013-04-29 00:00:00 UTC", "2013-05-06 00:00:00 UTC"], "2013-04-27 23:59:59 UTC", "2013-05-11 23:59:59 UTC", false, :start => :mon
352
+ assert_zeros :week, "2013-05-01 20:00:00 UTC", ["2013-04-22 00:00:00 UTC", "2013-04-29 00:00:00 UTC", "2013-05-06 00:00:00 UTC"], "2013-04-27 23:59:59 UTC", "2013-05-11 23:59:59 UTC", false, week_start: :mon
245
353
  end
246
354
 
247
355
  def test_zeros_week_time_zone_mon
248
- assert_zeros :week, "2013-05-01 20:00:00 PDT", ["2013-04-22 00:00:00 PDT", "2013-04-29 00:00:00 PDT", "2013-05-06 00:00:00 PDT"], "2013-04-27 23:59:59 PDT", "2013-05-11 23:59:59 PDT", true, :start => :mon
356
+ assert_zeros :week, "2013-05-01 20:00:00 PDT", ["2013-04-22 00:00:00 PDT", "2013-04-29 00:00:00 PDT", "2013-05-06 00:00:00 PDT"], "2013-04-27 23:59:59 PDT", "2013-05-11 23:59:59 PDT", true, week_start: :mon
249
357
  end
250
358
 
251
359
  def test_zeros_week_sat
252
- assert_zeros :week, "2013-05-01 20:00:00 UTC", ["2013-04-20 00:00:00 UTC", "2013-04-27 00:00:00 UTC", "2013-05-04 00:00:00 UTC"], "2013-04-26 23:59:59 UTC", "2013-05-10 23:59:59 UTC", false, :start => :sat
360
+ assert_zeros :week, "2013-05-01 20:00:00 UTC", ["2013-04-20 00:00:00 UTC", "2013-04-27 00:00:00 UTC", "2013-05-04 00:00:00 UTC"], "2013-04-26 23:59:59 UTC", "2013-05-10 23:59:59 UTC", false, week_start: :sat
253
361
  end
254
362
 
255
363
  def test_zeros_week_time_zone_sat
256
- assert_zeros :week, "2013-05-01 20:00:00 PDT", ["2013-04-20 00:00:00 PDT", "2013-04-27 00:00:00 PDT", "2013-05-04 00:00:00 PDT"], "2013-04-26 23:59:59 PDT", "2013-05-10 23:59:59 PDT", true, :start => :sat
364
+ assert_zeros :week, "2013-05-01 20:00:00 PDT", ["2013-04-20 00:00:00 PDT", "2013-04-27 00:00:00 PDT", "2013-05-04 00:00:00 PDT"], "2013-04-26 23:59:59 PDT", "2013-05-10 23:59:59 PDT", true, week_start: :sat
257
365
  end
258
366
 
259
367
  def test_zeros_month
@@ -278,7 +386,7 @@ module TestGroupdate
278
386
  7.times do |n|
279
387
  expected[n] = n == 3 ? 1 : 0
280
388
  end
281
- assert_equal expected, User.group_by_day_of_week(:created_at, Time.zone, true).count(:created_at)
389
+ assert_equal expected, User.group_by_day_of_week(:created_at, range: true).count(:created_at)
282
390
  end
283
391
 
284
392
  def test_zeros_hour_of_day
@@ -287,7 +395,7 @@ module TestGroupdate
287
395
  24.times do |n|
288
396
  expected[n] = n == 20 ? 1 : 0
289
397
  end
290
- assert_equal expected, User.group_by_hour_of_day(:created_at, Time.zone, true).count(:created_at)
398
+ assert_equal expected, User.group_by_hour_of_day(:created_at, range: true).count(:created_at)
291
399
  end
292
400
 
293
401
  def test_zeros_excludes_end
@@ -295,7 +403,7 @@ module TestGroupdate
295
403
  expected = {
296
404
  Time.parse("2013-05-01 00:00:00 UTC") => 0
297
405
  }
298
- assert_equal expected, User.group_by_day(:created_at, Time.zone, Time.parse("2013-05-01 00:00:00 UTC")...Time.parse("2013-05-02 00:00:00 UTC")).count
406
+ assert_equal expected, User.group_by_day(:created_at, range: Time.parse("2013-05-01 00:00:00 UTC")...Time.parse("2013-05-02 00:00:00 UTC")).count
299
407
  end
300
408
 
301
409
  def test_zeros_previous_scope
@@ -303,7 +411,7 @@ module TestGroupdate
303
411
  expected = {
304
412
  Time.parse("2013-05-01 00:00:00 UTC") => 0
305
413
  }
306
- assert_equal expected, User.where("id = 0").group_by_day(:created_at, Time.zone, Time.parse("2013-05-01 00:00:00 UTC")..Time.parse("2013-05-01 23:59:59 UTC")).count
414
+ assert_equal expected, User.where("id = 0").group_by_day(:created_at, range: Time.parse("2013-05-01 00:00:00 UTC")..Time.parse("2013-05-01 23:59:59 UTC")).count
307
415
  end
308
416
 
309
417
  def test_zeros_datetime
@@ -311,13 +419,13 @@ module TestGroupdate
311
419
  expected = {
312
420
  Time.parse("2013-05-01 00:00:00 UTC") => 1
313
421
  }
314
- assert_equal expected, User.group_by_day(:created_at, Time.zone, DateTime.parse("2013-05-01 00:00:00 UTC")..DateTime.parse("2013-05-01 00:00:00 UTC")).count
422
+ assert_equal expected, User.group_by_day(:created_at, range: DateTime.parse("2013-05-01 00:00:00 UTC")..DateTime.parse("2013-05-01 00:00:00 UTC")).count
315
423
  end
316
424
 
317
425
  def test_zeros_null_value
318
426
  user = User.create!(name: "Andrew")
319
427
  user.update_column :created_at, nil
320
- assert_equal 0, User.group_by_hour_of_day(:created_at, Time.zone, true).count[0]
428
+ assert_equal 0, User.group_by_hour_of_day(:created_at, range: true).count[0]
321
429
  end
322
430
 
323
431
  def test_zeroes_range_true
@@ -328,7 +436,7 @@ module TestGroupdate
328
436
  Time.parse("2013-05-02 00:00:00 UTC") => 0,
329
437
  Time.parse("2013-05-03 00:00:00 UTC") => 1
330
438
  }
331
- assert_equal expected, User.group_by_day(:created_at, Time.zone, true).count
439
+ assert_equal expected, User.group_by_day(:created_at, range: true).count
332
440
  end
333
441
 
334
442
  # week_start
@@ -340,21 +448,21 @@ module TestGroupdate
340
448
 
341
449
  def test_week_start_and_start_option
342
450
  Groupdate.week_start = :mon
343
- assert_result_time :week, "2013-03-16 00:00:00 UTC", "2013-03-22 23:59:59", false, :start => :sat
451
+ assert_result_time :week, "2013-03-16 00:00:00 UTC", "2013-03-22 23:59:59", false, week_start: :sat
344
452
  end
345
453
 
346
454
  # misc
347
455
 
348
456
  def test_order_day
349
- assert_empty User.group_by_day(:created_at).order("day desc").limit(20).count
457
+ assert_empty User.group_by_day(:created_at, series: false).order("day desc").limit(20).count
350
458
  end
351
459
 
352
460
  def test_order_week
353
- assert_empty User.group_by_week(:created_at).order("week asc").count
461
+ assert_empty User.group_by_week(:created_at, series: false).order("week asc").count
354
462
  end
355
463
 
356
464
  def test_order_hour_of_day
357
- assert_empty User.group_by_hour_of_day(:created_at).order("hour_of_day desc").count
465
+ assert_empty User.group_by_hour_of_day(:created_at, series: false).order("hour_of_day desc").count
358
466
  end
359
467
 
360
468
  def test_table_name
@@ -375,8 +483,8 @@ module TestGroupdate
375
483
  def assert_result(method, expected, time_str, time_zone = false, options = {})
376
484
  create_user time_str
377
485
  expected = expected.is_a?(Time) ? time_key(expected) : number_key(expected)
378
- assert_equal ordered_hash({expected => 1}), User.send(:"group_by_#{method}", :created_at, time_zone ? "Pacific Time (US & Canada)" : nil, options).order(method.to_s).count
379
- assert_equal 1, User.send(:"group_by_#{method}", :created_at, time_zone ? "Pacific Time (US & Canada)" : nil, true, options).count[expected]
486
+ assert_equal ordered_hash({expected => 1}), User.send(:"group_by_#{method}", :created_at, options.merge(series: false, time_zone: time_zone ? "Pacific Time (US & Canada)" : nil)).order(method.to_s).count
487
+ assert_equal 1, User.send(:"group_by_#{method}", :created_at, options.merge(time_zone: time_zone ? "Pacific Time (US & Canada)" : nil)).count[expected]
380
488
  end
381
489
 
382
490
  def assert_zeros(method, created_at, keys, range_start, range_end, time_zone = nil, options = {})
@@ -385,7 +493,7 @@ module TestGroupdate
385
493
  keys.each_with_index do |key, i|
386
494
  expected[Time.parse(key)] = i == 1 ? 1 : 0
387
495
  end
388
- assert_equal expected, User.send(:"group_by_#{method}", :created_at, time_zone ? "Pacific Time (US & Canada)" : nil, Time.parse(range_start)..Time.parse(range_end), options).count
496
+ assert_equal expected, User.send(:"group_by_#{method}", :created_at, options.merge(time_zone: time_zone ? "Pacific Time (US & Canada)" : nil, range: Time.parse(range_start)..Time.parse(range_end))).count
389
497
  end
390
498
 
391
499
  def ordered_hash(hash)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: groupdate
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.5
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane