groupdate 1.0.1 → 1.0.2

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: 9f1468425ce9451398c5c487174224dc971a30d2
4
- data.tar.gz: 5fff75e9b44d6651ca75d634f3bff1ceb68901de
3
+ metadata.gz: 8e473d607f5f1bf038d605fb7bb99c07876d4e20
4
+ data.tar.gz: 33f2c1067c4ac21b2dcb4e9c07402426e7d0abc7
5
5
  SHA512:
6
- metadata.gz: c14ee2daf271500e82db8e221fb8e1dcee97694355e244664c575b9e035c03fd62ba5e4a09189b4555b76f4b685ea9261e58a7101d707b892e2e8e52a051abb1
7
- data.tar.gz: 33c9afbdc4ec5bf3e99329c99c6b41702507762f122acbae0addbac7faeda9c6e87aa147b4f3c53cefceb9b58bb7643d21674958815cdb3974dfaa4df920c36b
6
+ metadata.gz: 957ef7d7bb9ef5ef0857094c9330e5b294a7d4b001a2d83e04e536d0c6cc119fbab6f2c913b005029baba8f117444c181449e464a64258142d85c48734e03cf9
7
+ data.tar.gz: d8e4ac13ab0194543382942698373577fd40b8299f4b81acd220636d0bd505ba3ac92abe0581e28fb9b9a991235f3da7a1b542adb5fa86159717bdaf6ca14093
data/CHANGELOG.md CHANGED
@@ -1,6 +1,10 @@
1
+ ## 1.0.2
2
+
3
+ - Added :start option for custom week start for group_by_week
4
+
1
5
  ## 1.0.1
2
6
 
3
- - Fixed series for Rails < 3.2 and MySQL 2
7
+ - Fixed series for Rails < 3.2 and MySQL
4
8
 
5
9
  ## 1.0.0
6
10
 
data/README.md CHANGED
@@ -61,7 +61,14 @@ time_zone = ActiveSupport::TimeZone["Pacific Time (US & Canada)"]
61
61
  User.group_by_week(:created_at, time_zone).count
62
62
  ```
63
63
 
64
- **Note:** Weeks start on Sunday.
64
+ **Note:** Weeks start on Sunday by default. For other days, use:
65
+
66
+ ```ruby
67
+ User.group_by_week(:created_at, :start => :mon) # first three letters of day
68
+
69
+ # must be the last argument
70
+ User.group_by_week(:created_at, time_zone, :start => :sat)
71
+ ```
65
72
 
66
73
  You can also group by the day of the week or hour of the day.
67
74
 
@@ -35,6 +35,8 @@ module Groupdate
35
35
  (time_fields + number_fields).each do |field|
36
36
  # no define_singleton_method in ruby 1.8
37
37
  (class << self; self end).send :define_method, :"group_by_#{field}" do |*args|
38
+ args = args.dup
39
+ options = args[-1].is_a?(Hash) ? args.pop : {}
38
40
  column = connection.quote_table_name(args[0])
39
41
  time_zone = args[1] || Time.zone || "Etc/UTC"
40
42
  if time_zone.is_a?(ActiveSupport::TimeZone) or time_zone = ActiveSupport::TimeZone[time_zone]
@@ -42,6 +44,13 @@ module Groupdate
42
44
  else
43
45
  raise "Unrecognized time zone"
44
46
  end
47
+
48
+ # for week
49
+ week_start = [:mon, :tue, :wed, :thu, :fri, :sat, :sun].index((options[:start] || :sun).to_sym)
50
+ if field == "week" and !week_start
51
+ raise "Unrecognized :start option"
52
+ end
53
+
45
54
  query =
46
55
  case connection.adapter_name
47
56
  when "MySQL", "Mysql2"
@@ -52,7 +61,7 @@ module Groupdate
52
61
  when "hour_of_day"
53
62
  ["EXTRACT(HOUR from CONVERT_TZ(#{column}, '+00:00', ?))", time_zone]
54
63
  when "week"
55
- ["CONVERT_TZ(DATE_FORMAT(CONVERT_TZ(DATE_SUB(#{column}, INTERVAL (DAYOFWEEK(CONVERT_TZ(#{column}, '+00:00', ?)) - 1) DAY), '+00:00', ?), '%Y-%m-%d 00:00:00'), ?, '+00:00')", time_zone, time_zone, time_zone]
64
+ ["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]
56
65
  else
57
66
  format =
58
67
  case field
@@ -79,7 +88,7 @@ module Groupdate
79
88
  when "hour_of_day"
80
89
  ["EXTRACT(HOUR from #{column}::timestamptz AT TIME ZONE ?)::integer", time_zone]
81
90
  when "week" # start on Sunday, not PostgreSQL default Monday
82
- ["(DATE_TRUNC('#{field}', (#{column}::timestamptz + INTERVAL '1 day') AT TIME ZONE ?) - INTERVAL '1 day') AT TIME ZONE ?", time_zone, time_zone]
91
+ ["(DATE_TRUNC('#{field}', (#{column}::timestamptz - INTERVAL '#{week_start} day') AT TIME ZONE ?) + INTERVAL '#{week_start} day') AT TIME ZONE ?", time_zone, time_zone]
83
92
  else
84
93
  ["DATE_TRUNC('#{field}', #{column}::timestamptz AT TIME ZONE ?) AT TIME ZONE ?", time_zone, time_zone]
85
94
  end
@@ -89,7 +98,7 @@ module Groupdate
89
98
 
90
99
  group = group(Groupdate::OrderHack.new(sanitize_sql_array(query), field, time_zone))
91
100
  if args[2]
92
- Series.new(group, field, column, time_zone, args[2])
101
+ Series.new(group, field, column, time_zone, args[2], week_start)
93
102
  else
94
103
  group
95
104
  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)
4
+ def initialize(relation, field, column, time_zone, time_range, week_start)
5
5
  @relation = relation
6
6
  if time_range.is_a?(Range)
7
7
  @relation = relation.where("#{column} BETWEEN ? AND ?", time_range.first, time_range.last)
@@ -9,6 +9,7 @@ module Groupdate
9
9
  @field = field
10
10
  @time_zone = time_zone
11
11
  @time_range = time_range
12
+ @week_start = week_start
12
13
  end
13
14
 
14
15
  def build_series(count)
@@ -19,7 +20,7 @@ module Groupdate
19
20
  when "day_of_week", "hour_of_day"
20
21
  lambda{|k| k.to_i }
21
22
  else
22
- lambda{|k| (k.is_a?(Time) ? k : utc.parse(k)).utc }
23
+ lambda{|k| (k.is_a?(String) ? utc.parse(k) : k.to_time).utc }
23
24
  end
24
25
 
25
26
  count = Hash[count.map do |k, v|
@@ -55,8 +56,9 @@ module Groupdate
55
56
  when "day"
56
57
  time.beginning_of_day
57
58
  when "week"
58
- # beginning_of_week does not support :sunday argument in activesupport < 3.2
59
- (time - time.wday.days).midnight
59
+ # same logic as MySQL group
60
+ weekday = (time.wday - 1) % 7
61
+ (time - ((7 - @week_start + weekday) % 7).days).midnight
60
62
  when "month"
61
63
  time.beginning_of_month
62
64
  else # year
@@ -1,3 +1,3 @@
1
1
  module Groupdate
2
- VERSION = "1.0.1"
2
+ VERSION = "1.0.2"
3
3
  end
data/test/test_helper.rb CHANGED
@@ -95,6 +95,42 @@ module TestGroupdate
95
95
  assert_result_time :week, "2013-03-17 00:00:00 PDT", "2013-03-17 07:00:00", true
96
96
  end
97
97
 
98
+ # week starting on monday
99
+
100
+ def test_week_end_of_week_mon
101
+ assert_result_time :week, "2013-03-18 00:00:00 UTC", "2013-03-24 23:59:59", false, :start => :mon
102
+ end
103
+
104
+ def test_week_start_of_week_mon
105
+ assert_result_time :week, "2013-03-25 00:00:00 UTC", "2013-03-25 00:00:00", false, :start => :mon
106
+ end
107
+
108
+ def test_week_end_of_week_with_time_zone_mon
109
+ assert_result_time :week, "2013-03-11 00:00:00 PDT", "2013-03-18 06:59:59", true, :start => :mon
110
+ end
111
+
112
+ def test_week_start_of_week_with_time_zone_mon
113
+ assert_result_time :week, "2013-03-18 00:00:00 PDT", "2013-03-18 07:00:00", true, :start => :mon
114
+ end
115
+
116
+ # week starting on saturday
117
+
118
+ def test_week_end_of_week_sat
119
+ assert_result_time :week, "2013-03-16 00:00:00 UTC", "2013-03-22 23:59:59", false, :start => :sat
120
+ end
121
+
122
+ def test_week_start_of_week_sat
123
+ assert_result_time :week, "2013-03-23 00:00:00 UTC", "2013-03-23 00:00:00", false, :start => :sat
124
+ end
125
+
126
+ def test_week_end_of_week_with_time_zone_sat
127
+ assert_result_time :week, "2013-03-09 00:00:00 PST", "2013-03-16 06:59:59", true, :start => :sat
128
+ end
129
+
130
+ def test_week_start_of_week_with_time_zone_sat
131
+ assert_result_time :week, "2013-03-16 00:00:00 PDT", "2013-03-16 07:00:00", true, :start => :sat
132
+ end
133
+
98
134
  # month
99
135
 
100
136
  def test_month_end_of_month
@@ -197,6 +233,22 @@ module TestGroupdate
197
233
  assert_zeros :week, "2013-05-01 20:00:00 PDT", ["2013-04-21 00:00:00 PDT", "2013-04-28 00:00:00 PDT", "2013-05-05 00:00:00 PDT"], "2013-04-27 23:59:59 PDT", "2013-05-11 23:59:59 PDT", true
198
234
  end
199
235
 
236
+ def test_zeros_week_mon
237
+ 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
238
+ end
239
+
240
+ def test_zeros_week_time_zone_mon
241
+ 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
242
+ end
243
+
244
+ def test_zeros_week_sat
245
+ 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
246
+ end
247
+
248
+ def test_zeros_week_time_zone_sat
249
+ 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
250
+ end
251
+
200
252
  def test_zeros_month
201
253
  assert_zeros :month, "2013-04-16 20:00:00 UTC", ["2013-03-01 00:00:00 UTC", "2013-04-01 00:00:00 UTC", "2013-05-01 00:00:00 UTC"], "2013-03-01 00:00:00 UTC", "2013-05-31 23:59:59 UTC"
202
254
  end
@@ -272,23 +324,23 @@ module TestGroupdate
272
324
 
273
325
  # helpers
274
326
 
275
- def assert_result_time(method, expected, time_str, time_zone = false)
276
- assert_result method, Time.parse(expected), time_str, time_zone
327
+ def assert_result_time(method, expected, time_str, time_zone = false, options = {})
328
+ assert_result method, Time.parse(expected), time_str, time_zone, options
277
329
  end
278
330
 
279
- def assert_result(method, expected, time_str, time_zone = false)
331
+ def assert_result(method, expected, time_str, time_zone = false, options = {})
280
332
  create_user time_str
281
333
  expected = expected.is_a?(Time) ? time_key(expected) : number_key(expected)
282
- assert_equal(ordered_hash({expected => 1}), User.send(:"group_by_#{method}", :created_at, time_zone ? "Pacific Time (US & Canada)" : nil).order(method.to_s).count)
334
+ 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)
283
335
  end
284
336
 
285
- def assert_zeros(method, created_at, keys, range_start, range_end, time_zone = nil)
337
+ def assert_zeros(method, created_at, keys, range_start, range_end, time_zone = nil, options = {})
286
338
  create_user created_at
287
339
  expected = {}
288
340
  keys.each_with_index do |key, i|
289
341
  expected[Time.parse(key)] = i == 1 ? 1 : 0
290
342
  end
291
- 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)).count)
343
+ 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)
292
344
  end
293
345
 
294
346
  def ordered_hash(hash)
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: 1.0.1
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-06-04 00:00:00.000000000 Z
11
+ date: 2013-06-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord