groupdate 2.2.1 → 2.3.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 +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +5 -1
- data/lib/groupdate/magic.rb +26 -3
- data/lib/groupdate/version.rb +1 -1
- data/lib/groupdate.rb +1 -1
- data/test/test_helper.rb +115 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: daf83ef79d462a5e64a5718a32473030971ac38c
|
4
|
+
data.tar.gz: f7223697deffaeca83fff949081837397da1aaea
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 20e08fd6c4737c5624fbee1bb3651af4b50b30d863ce50d3a3ef6e574bfdc8b3b072149cff799bd62eb7d6a38a4d474b376f0f9caaff5e35fb226abcd0f72b4b
|
7
|
+
data.tar.gz: 7ef016743a24bab4dcc51b69f4a48cdd7670eb86165f4158f0dd3c3f56c8c720e92bbcfce1952cfbb0b72add483ec4492f973953c8acd5942a178808e05cc23a
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -13,7 +13,7 @@ The simplest way to group by:
|
|
13
13
|
|
14
14
|
Works with Rails 3.1+
|
15
15
|
|
16
|
-
Supports PostgreSQL and MySQL, plus
|
16
|
+
Supports PostgreSQL and MySQL, plus arrays and hashes
|
17
17
|
|
18
18
|
[](https://travis-ci.org/ankane/groupdate)
|
19
19
|
|
@@ -47,6 +47,8 @@ and
|
|
47
47
|
|
48
48
|
- hour_of_day
|
49
49
|
- day_of_week (Sunday = 0, Monday = 1, etc)
|
50
|
+
- day_of_month [master]
|
51
|
+
- month_of_year [master]
|
50
52
|
|
51
53
|
Use it anywhere you can use `group`.
|
52
54
|
|
@@ -171,6 +173,8 @@ gem 'groupdate'
|
|
171
173
|
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql
|
172
174
|
```
|
173
175
|
|
176
|
+
or copy and paste [these statements](https://gist.githubusercontent.com/ankane/1d6b0022173186accbf0/raw/time_zone_support.sql) into a SQL console.
|
177
|
+
|
174
178
|
#### For JRuby
|
175
179
|
|
176
180
|
Use the master version of your JDBC adapter. You will get incorrect results for versions before [this commit](https://github.com/jruby/activerecord-jdbc-adapter/commit/c1cdb7cec8d3f06fc54995e8d872d830bd0a4d91).
|
data/lib/groupdate/magic.rb
CHANGED
@@ -20,7 +20,10 @@ module Groupdate
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def relation(column, relation)
|
23
|
-
|
23
|
+
if relation.default_timezone == :local
|
24
|
+
raise "ActiveRecord::Base.default_timezone must be :utc to use Groupdate"
|
25
|
+
end
|
26
|
+
|
24
27
|
time_zone = self.time_zone.tzinfo.name
|
25
28
|
|
26
29
|
adapter_name = relation.connection.adapter_name
|
@@ -33,6 +36,10 @@ module Groupdate
|
|
33
36
|
["DAYOFWEEK(CONVERT_TZ(DATE_SUB(#{column}, INTERVAL #{day_start} HOUR), '+00:00', ?)) - 1", time_zone]
|
34
37
|
when :hour_of_day
|
35
38
|
["(EXTRACT(HOUR from CONVERT_TZ(#{column}, '+00:00', ?)) + 24 - #{day_start}) % 24", time_zone]
|
39
|
+
when :day_of_month
|
40
|
+
["DAYOFMONTH(CONVERT_TZ(DATE_SUB(#{column}, INTERVAL #{day_start} HOUR), '+00:00', ?))", time_zone]
|
41
|
+
when :month_of_year
|
42
|
+
["MONTH(CONVERT_TZ(DATE_SUB(#{column}, INTERVAL #{day_start} HOUR), '+00:00', ?))", time_zone]
|
36
43
|
when :week
|
37
44
|
["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
45
|
else
|
@@ -57,9 +64,13 @@ module Groupdate
|
|
57
64
|
when "PostgreSQL", "PostGIS"
|
58
65
|
case field
|
59
66
|
when :day_of_week
|
60
|
-
["EXTRACT(DOW from
|
67
|
+
["EXTRACT(DOW from #{column}::timestamptz AT TIME ZONE ? - INTERVAL '#{day_start} hour')::integer", time_zone]
|
61
68
|
when :hour_of_day
|
62
69
|
["EXTRACT(HOUR from #{column}::timestamptz AT TIME ZONE ? - INTERVAL '#{day_start} hour')::integer", time_zone]
|
70
|
+
when :day_of_month
|
71
|
+
["EXTRACT(DAY from #{column}::timestamptz AT TIME ZONE ? - INTERVAL '#{day_start} hour')::integer", time_zone]
|
72
|
+
when :month_of_year
|
73
|
+
["EXTRACT(MONTH from #{column}::timestamptz AT TIME ZONE ? - INTERVAL '#{day_start} hour')::integer", time_zone]
|
63
74
|
when :week # start on Sunday, not PostgreSQL default Monday
|
64
75
|
["(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
76
|
else
|
@@ -105,7 +116,7 @@ module Groupdate
|
|
105
116
|
|
106
117
|
cast_method =
|
107
118
|
case field
|
108
|
-
when :day_of_week, :hour_of_day
|
119
|
+
when :day_of_week, :hour_of_day, :day_of_month, :month_of_year
|
109
120
|
lambda{|k| k.to_i }
|
110
121
|
else
|
111
122
|
utc = ActiveSupport::TimeZone["UTC"]
|
@@ -162,6 +173,10 @@ module Groupdate
|
|
162
173
|
0..6
|
163
174
|
when :hour_of_day
|
164
175
|
0..23
|
176
|
+
when :day_of_month
|
177
|
+
1..31
|
178
|
+
when :month_of_year
|
179
|
+
1..12
|
165
180
|
else
|
166
181
|
time_range = self.time_range
|
167
182
|
time_range =
|
@@ -218,6 +233,10 @@ module Groupdate
|
|
218
233
|
key = sunday + key.hours + day_start.hours
|
219
234
|
when :day_of_week
|
220
235
|
key = sunday + key.days
|
236
|
+
when :day_of_month
|
237
|
+
key = Date.new(2014, 1, key).to_time
|
238
|
+
when :month_of_year
|
239
|
+
key = Date.new(2014, key, 1).to_time
|
221
240
|
end
|
222
241
|
key.strftime(options[:format].to_s)
|
223
242
|
end
|
@@ -256,6 +275,10 @@ module Groupdate
|
|
256
275
|
time.hour
|
257
276
|
when :day_of_week
|
258
277
|
(7 - week_start + ((time.wday - 1) % 7) % 7)
|
278
|
+
when :day_of_month
|
279
|
+
time.day
|
280
|
+
when :month_of_year
|
281
|
+
time.month
|
259
282
|
else
|
260
283
|
raise "Invalid field"
|
261
284
|
end
|
data/lib/groupdate/version.rb
CHANGED
data/lib/groupdate.rb
CHANGED
@@ -4,7 +4,7 @@ require "groupdate/version"
|
|
4
4
|
require "groupdate/magic"
|
5
5
|
|
6
6
|
module Groupdate
|
7
|
-
FIELDS = [:second, :minute, :hour, :day, :week, :month, :year, :day_of_week, :hour_of_day]
|
7
|
+
FIELDS = [:second, :minute, :hour, :day, :week, :month, :year, :day_of_week, :hour_of_day, :day_of_month, :month_of_year]
|
8
8
|
METHODS = FIELDS.map{|v| :"group_by_#{v}" }
|
9
9
|
|
10
10
|
mattr_accessor :week_start, :day_start, :time_zone
|
data/test/test_helper.rb
CHANGED
@@ -328,6 +328,82 @@ module TestGroupdate
|
|
328
328
|
assert_result :day_of_week, 3, "2013-01-02 10:00:00", true, :day_start => 2
|
329
329
|
end
|
330
330
|
|
331
|
+
# day of month
|
332
|
+
|
333
|
+
def test_day_of_month_end_of_day
|
334
|
+
assert_result :day_of_month, 31, "2013-01-31 23:59:59"
|
335
|
+
end
|
336
|
+
|
337
|
+
def test_day_of_month_end_of_day_feb_leap_year
|
338
|
+
assert_result :day_of_month, 29, "2012-02-29 23:59:59"
|
339
|
+
end
|
340
|
+
|
341
|
+
def test_day_of_month_start_of_day
|
342
|
+
assert_result :day_of_month, 3, "2013-01-03 00:00:00"
|
343
|
+
end
|
344
|
+
|
345
|
+
def test_day_of_month_end_of_day_with_time_zone
|
346
|
+
assert_result :day_of_month, 31, "2013-02-01 07:59:59", true
|
347
|
+
end
|
348
|
+
|
349
|
+
def test_day_of_month_start_of_day_with_time_zone
|
350
|
+
assert_result :day_of_month, 1, "2013-01-01 08:00:00", true
|
351
|
+
end
|
352
|
+
|
353
|
+
# day of month starts at 2am
|
354
|
+
|
355
|
+
def test_day_of_month_end_of_day_day_start_2am
|
356
|
+
assert_result :day_of_month, 31, "2013-01-01 01:59:59", false, :day_start => 2
|
357
|
+
end
|
358
|
+
|
359
|
+
def test_day_of_month_start_of_day_day_start_2am
|
360
|
+
assert_result :day_of_month, 1, "2013-01-01 02:00:00", false, :day_start => 2
|
361
|
+
end
|
362
|
+
|
363
|
+
def test_day_of_month_end_of_day_with_time_zone_day_start_2am
|
364
|
+
assert_result :day_of_month, 31, "2013-01-01 09:59:59", true, :day_start => 2
|
365
|
+
end
|
366
|
+
|
367
|
+
def test_day_of_month_start_of_day_with_time_zone_day_start_2am
|
368
|
+
assert_result :day_of_month, 1, "2013-01-01 10:00:00", true, :day_start => 2
|
369
|
+
end
|
370
|
+
|
371
|
+
# month of year
|
372
|
+
|
373
|
+
def test_month_of_year_end_of_month
|
374
|
+
assert_result :month_of_year, 1, "2013-01-31 23:59:59"
|
375
|
+
end
|
376
|
+
|
377
|
+
def test_month_of_year_start_of_month
|
378
|
+
assert_result :month_of_year, 1, "2013-01-01 00:00:00"
|
379
|
+
end
|
380
|
+
|
381
|
+
def test_month_of_year_end_of_month_with_time_zone
|
382
|
+
assert_result :month_of_year, 1, "2013-02-01 07:59:59", true
|
383
|
+
end
|
384
|
+
|
385
|
+
def test_month_of_year_start_of_month_with_time_zone
|
386
|
+
assert_result :month_of_year, 1, "2013-01-01 08:00:00", true
|
387
|
+
end
|
388
|
+
|
389
|
+
# month of year starts at 2am
|
390
|
+
|
391
|
+
def test_month_of_year_end_of_month_day_start_2am
|
392
|
+
assert_result :month_of_year, 12, "2013-01-01 01:59:59", false, :day_start => 2
|
393
|
+
end
|
394
|
+
|
395
|
+
def test_month_of_year_start_of_month_day_start_2am
|
396
|
+
assert_result :month_of_year, 1, "2013-01-01 02:00:00", false, :day_start => 2
|
397
|
+
end
|
398
|
+
|
399
|
+
def test_month_of_year_end_of_month_with_time_zone_day_start_2am
|
400
|
+
assert_result :month_of_year, 12, "2013-01-01 09:59:59", true, :day_start => 2
|
401
|
+
end
|
402
|
+
|
403
|
+
def test_month_of_year_start_of_month_with_time_zone_day_start_2am
|
404
|
+
assert_result :month_of_year, 1, "2013-01-01 10:00:00", true, :day_start => 2
|
405
|
+
end
|
406
|
+
|
331
407
|
# zeros
|
332
408
|
|
333
409
|
def test_zeros_second
|
@@ -408,6 +484,24 @@ module TestGroupdate
|
|
408
484
|
assert_equal expected, call_method(:hour_of_day, :created_at, {})
|
409
485
|
end
|
410
486
|
|
487
|
+
def test_zeros_day_of_month
|
488
|
+
create_user "1978-12-18 00:00:00 UTC"
|
489
|
+
expected = {}
|
490
|
+
(1..31).each do |n|
|
491
|
+
expected[n] = n == 18 ? 1 : 0
|
492
|
+
end
|
493
|
+
assert_equal expected, call_method(:day_of_month, :created_at, {})
|
494
|
+
end
|
495
|
+
|
496
|
+
def test_zeros_month_of_year
|
497
|
+
create_user "2013-05-01 00:00:00 UTC"
|
498
|
+
expected = {}
|
499
|
+
(1..12).each do |n|
|
500
|
+
expected[n] = n == 5 ? 1 : 0
|
501
|
+
end
|
502
|
+
assert_equal expected, call_method(:month_of_year, :created_at, {})
|
503
|
+
end
|
504
|
+
|
411
505
|
def test_zeros_excludes_end
|
412
506
|
create_user "2013-05-02 00:00:00 UTC"
|
413
507
|
expected = {
|
@@ -609,6 +703,16 @@ module TestGroupdate
|
|
609
703
|
assert_format :day_of_week, "Sun", "%a", week_start: :sat
|
610
704
|
end
|
611
705
|
|
706
|
+
def test_format_day_of_month
|
707
|
+
create_user "2014-03-01 00:00:00 UTC"
|
708
|
+
assert_format :day_of_month, " 1", "%e"
|
709
|
+
end
|
710
|
+
|
711
|
+
def test_format_month_of_year
|
712
|
+
create_user "2014-01-01 00:00:00 UTC"
|
713
|
+
assert_format :month_of_year, "Jan", "%b"
|
714
|
+
end
|
715
|
+
|
612
716
|
def test_format_multiple_groups
|
613
717
|
create_user "2014-03-01 00:00:00 UTC"
|
614
718
|
assert_equal ({["Sun", 1] => 1}), User.group_by_week(:created_at, format: "%a").group(:score).count
|
@@ -622,6 +726,17 @@ module TestGroupdate
|
|
622
726
|
assert_empty user.posts.group_by_day(:created_at).count
|
623
727
|
end
|
624
728
|
|
729
|
+
# activerecord default_timezone option
|
730
|
+
|
731
|
+
def test_default_timezone_local
|
732
|
+
begin
|
733
|
+
User.default_timezone = :local
|
734
|
+
assert_raises(RuntimeError){ User.group_by_day(:created_at).count }
|
735
|
+
ensure
|
736
|
+
User.default_timezone = :utc
|
737
|
+
end
|
738
|
+
end
|
739
|
+
|
625
740
|
# helpers
|
626
741
|
|
627
742
|
def assert_format(method, expected, format, options = {})
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: groupdate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-08-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -167,3 +167,4 @@ test_files:
|
|
167
167
|
- test/mysql_test.rb
|
168
168
|
- test/postgresql_test.rb
|
169
169
|
- test/test_helper.rb
|
170
|
+
has_rdoc:
|