groupdate 2.2.1 → 2.3.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: 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: