groupdate 1.0.5 → 2.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.
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