groupdate 1.0.1 → 1.0.2

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: 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