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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 61482d521349112fbb247de01da256b7d2559574
4
- data.tar.gz: ef39227bacbce05f6d382f4e7e70c8f3a69eea3d
3
+ metadata.gz: daf83ef79d462a5e64a5718a32473030971ac38c
4
+ data.tar.gz: f7223697deffaeca83fff949081837397da1aaea
5
5
  SHA512:
6
- metadata.gz: 4b054169e094d93790241c3757e3f6171058e2379655394c8060db79417fb6bcafa39f7612f4462fc3ea2d6befd11dcfa700a1bde9073ab37037d2714db1ca8d
7
- data.tar.gz: 478d53080c29fd79b2965c7804a76a16451f239151bb839aa26040d874d05f1c0bf83ba730b3f23ba670c6d8ffb35028e69d9f147328c735efca669422ead0f9
6
+ metadata.gz: 20e08fd6c4737c5624fbee1bb3651af4b50b30d863ce50d3a3ef6e574bfdc8b3b072149cff799bd62eb7d6a38a4d474b376f0f9caaff5e35fb226abcd0f72b4b
7
+ data.tar.gz: 7ef016743a24bab4dcc51b69f4a48cdd7670eb86165f4158f0dd3c3f56c8c720e92bbcfce1952cfbb0b72add483ec4492f973953c8acd5942a178808e05cc23a
data/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## 2.3.0
2
+
3
+ - Raise error when ActiveRecord::Base.default_timezone is not `:utc`
4
+ - Added `day_of_month`
5
+ - Added `month_of_year`
6
+ - Do not quote column name
7
+
1
8
  ## 2.2.1
2
9
 
3
10
  - Fixed ActiveRecord 3 associations
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 Arrays and Hashes
16
+ Supports PostgreSQL and MySQL, plus arrays and hashes
17
17
 
18
18
  [![Build Status](https://travis-ci.org/ankane/groupdate.png)](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).
@@ -20,7 +20,10 @@ module Groupdate
20
20
  end
21
21
 
22
22
  def relation(column, relation)
23
- column = relation.connection.quote_table_name(column)
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 (#{column}::timestamptz AT TIME ZONE ? - INTERVAL '#{day_start} hour'))::integer", time_zone]
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
@@ -1,3 +1,3 @@
1
1
  module Groupdate
2
- VERSION = "2.2.1"
2
+ VERSION = "2.3.0"
3
3
  end
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.2.1
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-06-24 00:00:00.000000000 Z
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: