groupdate 1.0.0 → 1.0.1
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 +4 -0
- data/Gemfile +2 -0
- data/Rakefile +14 -4
- data/lib/groupdate/scopes.rb +2 -2
- data/lib/groupdate/series.rb +6 -3
- data/lib/groupdate/version.rb +1 -1
- data/test/mysql_test.rb +22 -0
- data/test/postgresql_test.rb +30 -0
- data/test/test_helper.rb +306 -0
- metadata +8 -4
- data/test/groupdate_test.rb +0 -288
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9f1468425ce9451398c5c487174224dc971a30d2
|
4
|
+
data.tar.gz: 5fff75e9b44d6651ca75d634f3bff1ceb68901de
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c14ee2daf271500e82db8e221fb8e1dcee97694355e244664c575b9e035c03fd62ba5e4a09189b4555b76f4b685ea9261e58a7101d707b892e2e8e52a051abb1
|
7
|
+
data.tar.gz: 33c9afbdc4ec5bf3e99329c99c6b41702507762f122acbae0addbac7faeda9c6e87aa147b4f3c53cefceb9b58bb7643d21674958815cdb3974dfaa4df920c36b
|
data/CHANGELOG.md
CHANGED
data/Gemfile
CHANGED
data/Rakefile
CHANGED
@@ -1,9 +1,19 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
2
|
require "rake/testtask"
|
3
3
|
|
4
|
+
task :default => :test
|
4
5
|
Rake::TestTask.new do |t|
|
5
|
-
t.libs
|
6
|
-
t.
|
7
|
-
|
8
|
-
|
6
|
+
t.libs << "test"
|
7
|
+
t.pattern = "test/**/*_test.rb"
|
8
|
+
end
|
9
|
+
|
10
|
+
namespace :test do
|
11
|
+
Rake::TestTask.new(:postgresql) do |t|
|
12
|
+
t.libs << "test"
|
13
|
+
t.pattern = "test/postgresql_test.rb"
|
14
|
+
end
|
15
|
+
Rake::TestTask.new(:mysql) do |t|
|
16
|
+
t.libs << "test"
|
17
|
+
t.pattern = "test/mysql_test.rb"
|
18
|
+
end
|
9
19
|
end
|
data/lib/groupdate/scopes.rb
CHANGED
@@ -75,9 +75,9 @@ module Groupdate
|
|
75
75
|
when "PostgreSQL"
|
76
76
|
case field
|
77
77
|
when "day_of_week"
|
78
|
-
["EXTRACT(DOW from #{column}::timestamptz AT TIME ZONE ?)", time_zone]
|
78
|
+
["EXTRACT(DOW from #{column}::timestamptz AT TIME ZONE ?)::integer", time_zone]
|
79
79
|
when "hour_of_day"
|
80
|
-
["EXTRACT(HOUR from #{column}::timestamptz AT TIME ZONE ?)", time_zone]
|
80
|
+
["EXTRACT(HOUR from #{column}::timestamptz AT TIME ZONE ?)::integer", time_zone]
|
81
81
|
when "week" # start on Sunday, not PostgreSQL default Monday
|
82
82
|
["(DATE_TRUNC('#{field}', (#{column}::timestamptz + INTERVAL '1 day') AT TIME ZONE ?) - INTERVAL '1 day') AT TIME ZONE ?", time_zone, time_zone]
|
83
83
|
else
|
data/lib/groupdate/series.rb
CHANGED
@@ -12,12 +12,14 @@ module Groupdate
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def build_series(count)
|
15
|
+
utc = ActiveSupport::TimeZone["UTC"]
|
16
|
+
|
15
17
|
cast_method =
|
16
18
|
case @field
|
17
19
|
when "day_of_week", "hour_of_day"
|
18
20
|
lambda{|k| k.to_i }
|
19
21
|
else
|
20
|
-
lambda{|k| k.is_a?(Time) ? k :
|
22
|
+
lambda{|k| (k.is_a?(Time) ? k : utc.parse(k)).utc }
|
21
23
|
end
|
22
24
|
|
23
25
|
count = Hash[count.map do |k, v|
|
@@ -53,7 +55,8 @@ module Groupdate
|
|
53
55
|
when "day"
|
54
56
|
time.beginning_of_day
|
55
57
|
when "week"
|
56
|
-
|
58
|
+
# beginning_of_week does not support :sunday argument in activesupport < 3.2
|
59
|
+
(time - time.wday.days).midnight
|
57
60
|
when "month"
|
58
61
|
time.beginning_of_month
|
59
62
|
else # year
|
@@ -68,7 +71,7 @@ module Groupdate
|
|
68
71
|
series << series.last + step
|
69
72
|
end
|
70
73
|
|
71
|
-
series.map{|s| s.to_time }
|
74
|
+
series.map{|s| s.to_time.utc }
|
72
75
|
end
|
73
76
|
|
74
77
|
Hash[series.map do |k|
|
data/lib/groupdate/version.rb
CHANGED
data/test/mysql_test.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class TestMysql < Minitest::Test
|
4
|
+
include TestGroupdate
|
5
|
+
|
6
|
+
def setup
|
7
|
+
User.establish_connection :adapter => "mysql2", :database => "groupdate_test", :username => "root"
|
8
|
+
end
|
9
|
+
|
10
|
+
def time_key(key)
|
11
|
+
if RUBY_PLATFORM == "java"
|
12
|
+
key.utc.strftime("%Y-%m-%d %H:%M:%S").gsub(/ 00\:00\:00\z/, "")
|
13
|
+
else
|
14
|
+
key
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def number_key(key)
|
19
|
+
key
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class TestPostgresql < Minitest::Test
|
4
|
+
include TestGroupdate
|
5
|
+
|
6
|
+
def setup
|
7
|
+
User.establish_connection :adapter => "postgresql", :database => "groupdate_test"
|
8
|
+
end
|
9
|
+
|
10
|
+
def time_key(key)
|
11
|
+
if RUBY_PLATFORM == "java"
|
12
|
+
key.utc.strftime("%Y-%m-%d %H:%M:%S%z")[0..-3]
|
13
|
+
else
|
14
|
+
if ActiveRecord::VERSION::MAJOR == 3
|
15
|
+
key.utc.strftime("%Y-%m-%d %H:%M:%S+00")
|
16
|
+
else
|
17
|
+
key
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def number_key(key)
|
23
|
+
if RUBY_PLATFORM != "java" and ActiveRecord::VERSION::MAJOR == 3
|
24
|
+
key.to_s
|
25
|
+
else
|
26
|
+
key
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,306 @@
|
|
1
|
+
require "bundler/setup"
|
2
|
+
Bundler.require(:default)
|
3
|
+
require "minitest/autorun"
|
4
|
+
require "minitest/pride"
|
5
|
+
require "logger"
|
6
|
+
|
7
|
+
# for debugging
|
8
|
+
# ActiveRecord::Base.logger = Logger.new(STDOUT)
|
9
|
+
|
10
|
+
# rails does this in activerecord/lib/active_record/railtie.rb
|
11
|
+
ActiveRecord::Base.default_timezone = :utc
|
12
|
+
ActiveRecord::Base.time_zone_aware_attributes = true
|
13
|
+
|
14
|
+
class User < ActiveRecord::Base
|
15
|
+
end
|
16
|
+
|
17
|
+
# migrations
|
18
|
+
%w(postgresql mysql2).each do |adapter|
|
19
|
+
ActiveRecord::Base.establish_connection :adapter => adapter, :database => "groupdate_test", :username => adapter == "mysql2" ? "root" : nil
|
20
|
+
|
21
|
+
unless ActiveRecord::Base.connection.table_exists? "users"
|
22
|
+
ActiveRecord::Migration.create_table :users do |t|
|
23
|
+
t.string :name
|
24
|
+
t.integer :score
|
25
|
+
t.timestamps
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
module TestGroupdate
|
31
|
+
|
32
|
+
# second
|
33
|
+
|
34
|
+
def test_second_end_of_second
|
35
|
+
assert_result_time :second, "2013-05-03 00:00:00 UTC", "2013-05-03 00:00:00.999"
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_second_start_of_second
|
39
|
+
assert_result_time :second, "2013-05-03 00:00:01 UTC", "2013-05-03 00:00:01.000"
|
40
|
+
end
|
41
|
+
|
42
|
+
# minute
|
43
|
+
|
44
|
+
def test_minute_end_of_minute
|
45
|
+
assert_result_time :minute, "2013-05-03 00:00:00 UTC", "2013-05-03 00:00:59"
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_minute_start_of_minute
|
49
|
+
assert_result_time :minute, "2013-05-03 00:01:00 UTC", "2013-05-03 00:01:00"
|
50
|
+
end
|
51
|
+
|
52
|
+
# hour
|
53
|
+
|
54
|
+
def test_hour_end_of_hour
|
55
|
+
assert_result_time :hour, "2013-05-03 00:00:00 UTC", "2013-05-03 00:59:59"
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_hour_start_of_hour
|
59
|
+
assert_result_time :hour, "2013-05-03 01:00:00 UTC", "2013-05-03 01:00:00"
|
60
|
+
end
|
61
|
+
|
62
|
+
# day
|
63
|
+
|
64
|
+
def test_day_end_of_day
|
65
|
+
assert_result_time :day, "2013-05-03 00:00:00 UTC", "2013-05-03 23:59:59"
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_day_start_of_day
|
69
|
+
assert_result_time :day, "2013-05-04 00:00:00 UTC", "2013-05-04 00:00:00"
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_day_end_of_day_with_time_zone
|
73
|
+
assert_result_time :day, "2013-05-02 00:00:00 PDT", "2013-05-03 06:59:59", true
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_day_start_of_day_with_time_zone
|
77
|
+
assert_result_time :day, "2013-05-03 00:00:00 PDT", "2013-05-03 07:00:00", true
|
78
|
+
end
|
79
|
+
|
80
|
+
# week
|
81
|
+
|
82
|
+
def test_week_end_of_week
|
83
|
+
assert_result_time :week, "2013-03-17 00:00:00 UTC", "2013-03-23 23:59:59"
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_week_start_of_week
|
87
|
+
assert_result_time :week, "2013-03-24 00:00:00 UTC", "2013-03-24 00:00:00"
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_week_end_of_week_with_time_zone
|
91
|
+
assert_result_time :week, "2013-03-10 00:00:00 PST", "2013-03-17 06:59:59", true
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_week_start_of_week_with_time_zone
|
95
|
+
assert_result_time :week, "2013-03-17 00:00:00 PDT", "2013-03-17 07:00:00", true
|
96
|
+
end
|
97
|
+
|
98
|
+
# month
|
99
|
+
|
100
|
+
def test_month_end_of_month
|
101
|
+
assert_result_time :month, "2013-05-01 00:00:00 UTC", "2013-05-31 23:59:59"
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_month_start_of_month
|
105
|
+
assert_result_time :month, "2013-06-01 00:00:00 UTC", "2013-06-01 00:00:00"
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_month_end_of_month_with_time_zone
|
109
|
+
assert_result_time :month, "2013-05-01 00:00:00 PDT", "2013-06-01 06:59:59", true
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_month_start_of_month_with_time_zone
|
113
|
+
assert_result_time :month, "2013-06-01 00:00:00 PDT", "2013-06-01 07:00:00", true
|
114
|
+
end
|
115
|
+
|
116
|
+
# year
|
117
|
+
|
118
|
+
def test_year_end_of_year
|
119
|
+
assert_result_time :year, "2013-01-01 00:00:00 UTC", "2013-12-31 23:59:59"
|
120
|
+
end
|
121
|
+
|
122
|
+
def test_year_start_of_year
|
123
|
+
assert_result_time :year, "2014-01-01 00:00:00 UTC", "2014-01-01 00:00:00"
|
124
|
+
end
|
125
|
+
|
126
|
+
def test_year_end_of_year_with_time_zone
|
127
|
+
assert_result_time :year, "2013-01-01 00:00:00 PST", "2014-01-01 07:59:59", true
|
128
|
+
end
|
129
|
+
|
130
|
+
def test_year_start_of_year_with_time_zone
|
131
|
+
assert_result_time :year, "2014-01-01 00:00:00 PST", "2014-01-01 08:00:00", true
|
132
|
+
end
|
133
|
+
|
134
|
+
# hour of day
|
135
|
+
|
136
|
+
def test_hour_of_day_end_of_hour
|
137
|
+
assert_result :hour_of_day, 0, "2013-01-01 00:59:59"
|
138
|
+
end
|
139
|
+
|
140
|
+
def test_hour_of_day_start_of_hour
|
141
|
+
assert_result :hour_of_day, 1, "2013-01-01 01:00:00"
|
142
|
+
end
|
143
|
+
|
144
|
+
def test_hour_of_day_end_of_hour_with_time_zone
|
145
|
+
assert_result :hour_of_day, 0, "2013-01-01 08:59:59", true
|
146
|
+
end
|
147
|
+
|
148
|
+
def test_hour_of_day_start_of_hour_with_time_zone
|
149
|
+
assert_result :hour_of_day, 1, "2013-01-01 09:00:00", true
|
150
|
+
end
|
151
|
+
|
152
|
+
# day of week
|
153
|
+
|
154
|
+
def test_day_of_week_end_of_day
|
155
|
+
assert_result :day_of_week, 2, "2013-01-01 23:59:59"
|
156
|
+
end
|
157
|
+
|
158
|
+
def test_day_of_week_start_of_day
|
159
|
+
assert_result :day_of_week, 3, "2013-01-02 00:00:00"
|
160
|
+
end
|
161
|
+
|
162
|
+
def test_day_of_week_end_of_week_with_time_zone
|
163
|
+
assert_result :day_of_week, 2, "2013-01-02 07:59:59", true
|
164
|
+
end
|
165
|
+
|
166
|
+
def test_day_of_week_start_of_week_with_time_zone
|
167
|
+
assert_result :day_of_week, 3, "2013-01-02 08:00:00", true
|
168
|
+
end
|
169
|
+
|
170
|
+
# zeros
|
171
|
+
|
172
|
+
def test_zeros_second
|
173
|
+
assert_zeros :second, "2013-05-01 00:00:01 UTC", ["2013-05-01 00:00:00 UTC", "2013-05-01 00:00:01 UTC", "2013-05-01 00:00:02 UTC"], "2013-05-01 00:00:00.999 UTC", "2013-05-01 00:00:02 UTC"
|
174
|
+
end
|
175
|
+
|
176
|
+
def test_zeros_minute
|
177
|
+
assert_zeros :minute, "2013-05-01 00:01:00 UTC", ["2013-05-01 00:00:00 UTC", "2013-05-01 00:01:00 UTC", "2013-05-01 00:02:00 UTC"], "2013-05-01 00:00:59 UTC", "2013-05-01 00:02:00 UTC"
|
178
|
+
end
|
179
|
+
|
180
|
+
def test_zeros_hour
|
181
|
+
assert_zeros :hour, "2013-05-01 04:01:01 UTC", ["2013-05-01 03:00:00 UTC", "2013-05-01 04:00:00 UTC", "2013-05-01 05:00:00 UTC"], "2013-05-01 03:59:59 UTC", "2013-05-01 05:00:00 UTC"
|
182
|
+
end
|
183
|
+
|
184
|
+
def test_zeros_day
|
185
|
+
assert_zeros :day, "2013-05-01 20:00:00 UTC", ["2013-04-30 00:00:00 UTC", "2013-05-01 00:00:00 UTC", "2013-05-02 00:00:00 UTC"], "2013-04-30 00:00:00 UTC", "2013-05-02 23:59:59 UTC"
|
186
|
+
end
|
187
|
+
|
188
|
+
def test_zeros_day_time_zone
|
189
|
+
assert_zeros :day, "2013-05-01 20:00:00 PDT", ["2013-04-30 00:00:00 PDT", "2013-05-01 00:00:00 PDT", "2013-05-02 00:00:00 PDT"], "2013-04-30 00:00:00 PDT", "2013-05-02 23:59:59 PDT", true
|
190
|
+
end
|
191
|
+
|
192
|
+
def test_zeros_week
|
193
|
+
assert_zeros :week, "2013-05-01 20:00:00 UTC", ["2013-04-21 00:00:00 UTC", "2013-04-28 00:00:00 UTC", "2013-05-05 00:00:00 UTC"], "2013-04-27 23:59:59 UTC", "2013-05-11 23:59:59 UTC"
|
194
|
+
end
|
195
|
+
|
196
|
+
def test_zeros_week_time_zone
|
197
|
+
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
|
+
end
|
199
|
+
|
200
|
+
def test_zeros_month
|
201
|
+
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
|
+
end
|
203
|
+
|
204
|
+
def test_zeros_month_time_zone
|
205
|
+
assert_zeros :month, "2013-04-16 20:00:00 PDT", ["2013-03-01 00:00:00 PST", "2013-04-01 00:00:00 PDT", "2013-05-01 00:00:00 PDT"], "2013-03-01 00:00:00 PST", "2013-05-31 23:59:59 PDT", true
|
206
|
+
end
|
207
|
+
|
208
|
+
def test_zeros_year
|
209
|
+
assert_zeros :year, "2013-04-16 20:00:00 UTC", ["2012-01-01 00:00:00 UTC", "2013-01-01 00:00:00 UTC", "2014-01-01 00:00:00 UTC"], "2012-01-01 00:00:00 UTC", "2014-12-31 23:59:59 UTC"
|
210
|
+
end
|
211
|
+
|
212
|
+
def test_zeros_year_time_zone
|
213
|
+
assert_zeros :year, "2013-04-16 20:00:00 PDT", ["2012-01-01 00:00:00 PST", "2013-01-01 00:00:00 PST", "2014-01-01 00:00:00 PST"], "2012-01-01 00:00:00 PST", "2014-12-31 23:59:59 PST", true
|
214
|
+
end
|
215
|
+
|
216
|
+
def test_zeros_day_of_week
|
217
|
+
create_user "2013-05-01 00:00:00 UTC"
|
218
|
+
expected = {}
|
219
|
+
7.times do |n|
|
220
|
+
expected[n] = n == 3 ? 1 : 0
|
221
|
+
end
|
222
|
+
assert_equal(expected, User.group_by_day_of_week(:created_at, Time.zone, true).count(:created_at))
|
223
|
+
end
|
224
|
+
|
225
|
+
def test_zeros_hour_of_day
|
226
|
+
create_user "2013-05-01 20:00:00 UTC"
|
227
|
+
expected = {}
|
228
|
+
24.times do |n|
|
229
|
+
expected[n] = n == 20 ? 1 : 0
|
230
|
+
end
|
231
|
+
assert_equal(expected, User.group_by_hour_of_day(:created_at, Time.zone, true).count(:created_at))
|
232
|
+
end
|
233
|
+
|
234
|
+
def test_zeros_excludes_end
|
235
|
+
create_user "2013-05-02 00:00:00 UTC"
|
236
|
+
expected = {
|
237
|
+
Time.parse("2013-05-01 00:00:00 UTC") => 0
|
238
|
+
}
|
239
|
+
assert_equal(expected, User.group_by_day(:created_at, Time.zone, Time.parse("2013-05-01 00:00:00 UTC")...Time.parse("2013-05-02 00:00:00 UTC")).count)
|
240
|
+
end
|
241
|
+
|
242
|
+
def test_zeros_previous_scope
|
243
|
+
create_user "2013-05-01 00:00:00 UTC"
|
244
|
+
expected = {
|
245
|
+
Time.parse("2013-05-01 00:00:00 UTC") => 0
|
246
|
+
}
|
247
|
+
assert_equal(expected, User.where("id = 0").group_by_day(:created_at, Time.zone, Time.parse("2013-05-01 00:00:00 UTC")..Time.parse("2013-05-01 23:59:59 UTC")).count)
|
248
|
+
end
|
249
|
+
|
250
|
+
# misc
|
251
|
+
|
252
|
+
def test_order_day
|
253
|
+
assert_equal({}, User.group_by_day(:created_at).order("day desc").limit(20).count)
|
254
|
+
end
|
255
|
+
|
256
|
+
def test_order_week
|
257
|
+
assert_equal({}, User.group_by_week(:created_at).order("week asc").count)
|
258
|
+
end
|
259
|
+
|
260
|
+
def test_order_hour_of_day
|
261
|
+
assert_equal({}, User.group_by_hour_of_day(:created_at).order("hour_of_day desc").count)
|
262
|
+
end
|
263
|
+
|
264
|
+
def test_table_name
|
265
|
+
assert_equal({}, User.group_by_day("users.created_at").count)
|
266
|
+
end
|
267
|
+
|
268
|
+
def test_previous_scopes
|
269
|
+
create_user "2013-05-01 00:00:00 UTC"
|
270
|
+
assert_equal({}, User.where("id = 0").group_by_day(:created_at).count)
|
271
|
+
end
|
272
|
+
|
273
|
+
# helpers
|
274
|
+
|
275
|
+
def assert_result_time(method, expected, time_str, time_zone = false)
|
276
|
+
assert_result method, Time.parse(expected), time_str, time_zone
|
277
|
+
end
|
278
|
+
|
279
|
+
def assert_result(method, expected, time_str, time_zone = false)
|
280
|
+
create_user time_str
|
281
|
+
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)
|
283
|
+
end
|
284
|
+
|
285
|
+
def assert_zeros(method, created_at, keys, range_start, range_end, time_zone = nil)
|
286
|
+
create_user created_at
|
287
|
+
expected = {}
|
288
|
+
keys.each_with_index do |key, i|
|
289
|
+
expected[Time.parse(key)] = i == 1 ? 1 : 0
|
290
|
+
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)
|
292
|
+
end
|
293
|
+
|
294
|
+
def ordered_hash(hash)
|
295
|
+
RUBY_VERSION =~ /1\.8/ ? hash.inject(ActiveSupport::OrderedHash.new){|h, (k, v)| h[k] = v; h } : hash
|
296
|
+
end
|
297
|
+
|
298
|
+
def create_user(created_at)
|
299
|
+
User.create!(:name => "Andrew", :score => 1, :created_at => ActiveSupport::TimeZone["UTC"].parse(created_at))
|
300
|
+
end
|
301
|
+
|
302
|
+
def teardown
|
303
|
+
User.delete_all
|
304
|
+
end
|
305
|
+
|
306
|
+
end
|
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.
|
4
|
+
version: 1.0.1
|
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-
|
11
|
+
date: 2013-06-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -114,7 +114,9 @@ files:
|
|
114
114
|
- lib/groupdate/scopes.rb
|
115
115
|
- lib/groupdate/series.rb
|
116
116
|
- lib/groupdate/version.rb
|
117
|
-
- test/
|
117
|
+
- test/mysql_test.rb
|
118
|
+
- test/postgresql_test.rb
|
119
|
+
- test/test_helper.rb
|
118
120
|
homepage: ''
|
119
121
|
licenses:
|
120
122
|
- MIT
|
@@ -140,4 +142,6 @@ signing_key:
|
|
140
142
|
specification_version: 4
|
141
143
|
summary: The simplest way to group temporal data
|
142
144
|
test_files:
|
143
|
-
- test/
|
145
|
+
- test/mysql_test.rb
|
146
|
+
- test/postgresql_test.rb
|
147
|
+
- test/test_helper.rb
|
data/test/groupdate_test.rb
DELETED
@@ -1,288 +0,0 @@
|
|
1
|
-
require "bundler/setup"
|
2
|
-
Bundler.require(:default)
|
3
|
-
require "minitest/autorun"
|
4
|
-
require "minitest/pride"
|
5
|
-
require "logger"
|
6
|
-
|
7
|
-
# for debugging
|
8
|
-
# ActiveRecord::Base.logger = Logger.new(STDOUT)
|
9
|
-
|
10
|
-
# rails does this in activerecord/lib/active_record/railtie.rb
|
11
|
-
ActiveRecord::Base.default_timezone = :utc
|
12
|
-
ActiveRecord::Base.time_zone_aware_attributes = true
|
13
|
-
|
14
|
-
class User < ActiveRecord::Base
|
15
|
-
end
|
16
|
-
|
17
|
-
# migrations
|
18
|
-
%w(postgresql mysql2).each do |adapter|
|
19
|
-
ActiveRecord::Base.establish_connection :adapter => adapter, :database => "groupdate_test", :username => adapter == "mysql2" ? "root" : nil
|
20
|
-
|
21
|
-
unless ActiveRecord::Base.connection.table_exists? "users"
|
22
|
-
ActiveRecord::Migration.create_table :users do |t|
|
23
|
-
t.string :name
|
24
|
-
t.integer :score
|
25
|
-
t.timestamps
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
describe Groupdate do
|
31
|
-
%w(postgresql mysql2).each do |adapter|
|
32
|
-
describe adapter do
|
33
|
-
|
34
|
-
before do
|
35
|
-
User.establish_connection :adapter => adapter, :database => "groupdate_test", :username => adapter == "mysql2" ? "root" : nil
|
36
|
-
User.delete_all
|
37
|
-
end
|
38
|
-
|
39
|
-
it "works!" do
|
40
|
-
[
|
41
|
-
{:name => "Andrew", :score => 1, :created_at => Time.parse("2013-04-01 00:00:00 UTC")},
|
42
|
-
{:name => "Jordan", :score => 2, :created_at => Time.parse("2013-04-01 00:00:00 UTC")},
|
43
|
-
{:name => "Nick", :score => 3, :created_at => Time.parse("2013-04-02 00:00:00 UTC")}
|
44
|
-
].each{|u| User.create!(u) }
|
45
|
-
|
46
|
-
assert_equal(
|
47
|
-
ordered_hash({
|
48
|
-
time_key("2013-04-01 00:00:00 UTC") => 1,
|
49
|
-
time_key("2013-04-02 00:00:00 UTC") => 1
|
50
|
-
}),
|
51
|
-
User.where("score > 1").group_by_day(:created_at).count
|
52
|
-
)
|
53
|
-
end
|
54
|
-
|
55
|
-
it "doesn't throw exception with order" do
|
56
|
-
assert_equal({}, User.group_by_day(:created_at).order("day desc").limit(20).count)
|
57
|
-
assert_equal({}, User.group_by_week(:created_at).order("week asc").count)
|
58
|
-
assert_equal({}, User.group_by_hour_of_day(:created_at).order("hour_of_day desc").count)
|
59
|
-
end
|
60
|
-
|
61
|
-
it "allows for table name" do
|
62
|
-
assert_equal({}, User.group_by_day("users.created_at").count)
|
63
|
-
end
|
64
|
-
|
65
|
-
it "group_by_second" do
|
66
|
-
assert_group :second, "2013-04-01 00:00:01 UTC", "2013-04-01 00:00:01 UTC"
|
67
|
-
end
|
68
|
-
|
69
|
-
it "group_by_minute" do
|
70
|
-
assert_group :minute, "2013-04-01 00:01:01 UTC", "2013-04-01 00:01:00 UTC"
|
71
|
-
end
|
72
|
-
|
73
|
-
it "group_by_hour" do
|
74
|
-
assert_group :hour, "2013-04-01 01:01:01 UTC", "2013-04-01 01:00:00 UTC"
|
75
|
-
end
|
76
|
-
|
77
|
-
it "group_by_day" do
|
78
|
-
assert_group :day, "2013-04-01 01:01:01 UTC", "2013-04-01 00:00:00 UTC"
|
79
|
-
end
|
80
|
-
|
81
|
-
it "group_by_day with time zone" do
|
82
|
-
assert_group_tz :day, "2013-04-01 01:01:01 UTC", "2013-03-31 07:00:00 UTC"
|
83
|
-
end
|
84
|
-
|
85
|
-
it "group_by_week" do
|
86
|
-
assert_group :week, "2013-03-17 01:01:01 UTC", "2013-03-17 00:00:00 UTC"
|
87
|
-
end
|
88
|
-
|
89
|
-
it "group_by_week with time zone" do # day of DST
|
90
|
-
assert_group_tz :week, "2013-03-17 01:01:01 UTC", "2013-03-10 08:00:00 UTC"
|
91
|
-
end
|
92
|
-
|
93
|
-
it "group_by_month" do
|
94
|
-
assert_group :month, "2013-04-01 01:01:01 UTC", "2013-04-01 00:00:00 UTC"
|
95
|
-
end
|
96
|
-
|
97
|
-
it "group_by_month with time zone" do
|
98
|
-
assert_group_tz :month, "2013-04-01 01:01:01 UTC", "2013-03-01 08:00:00 UTC"
|
99
|
-
end
|
100
|
-
|
101
|
-
it "group_by_year" do
|
102
|
-
assert_group :year, "2013-01-01 01:01:01 UTC", "2013-01-01 00:00:00 UTC"
|
103
|
-
end
|
104
|
-
|
105
|
-
it "group_by_year with time zone" do
|
106
|
-
assert_group_tz :year, "2013-01-01 01:01:01 UTC", "2012-01-01 08:00:00 UTC"
|
107
|
-
end
|
108
|
-
|
109
|
-
it "group_by_hour_of_day" do
|
110
|
-
assert_group_number :hour_of_day, "2013-01-01 11:00:00 UTC", 11
|
111
|
-
end
|
112
|
-
|
113
|
-
it "group_by_hour_of_day with time zone" do
|
114
|
-
assert_group_number_tz :hour_of_day, "2013-01-01 11:00:00 UTC", 3
|
115
|
-
end
|
116
|
-
|
117
|
-
it "group_by_day_of_week" do
|
118
|
-
assert_group_number :day_of_week, "2013-03-03 00:00:00 UTC", 0
|
119
|
-
end
|
120
|
-
|
121
|
-
it "group_by_day_of_week with time zone" do
|
122
|
-
assert_group_number_tz :day_of_week, "2013-03-03 00:00:00 UTC", 6
|
123
|
-
end
|
124
|
-
|
125
|
-
it "works with previous scopes" do
|
126
|
-
create_user "2013-05-01 00:00:00 UTC"
|
127
|
-
assert_equal({}, User.where("id = 0").group_by_day(:created_at).count)
|
128
|
-
end
|
129
|
-
|
130
|
-
describe "returns zeros" do
|
131
|
-
|
132
|
-
it "group_by_second" do
|
133
|
-
assert_zeros :second, "2013-05-01 00:00:01 UTC", ["2013-05-01 00:00:00 UTC", "2013-05-01 00:00:01 UTC", "2013-05-01 00:00:02 UTC"], "2013-05-01 00:00:00.999 UTC", "2013-05-01 00:00:02 UTC"
|
134
|
-
end
|
135
|
-
|
136
|
-
it "group_by_minute" do
|
137
|
-
assert_zeros :minute, "2013-05-01 00:01:00 UTC", ["2013-05-01 00:00:00 UTC", "2013-05-01 00:01:00 UTC", "2013-05-01 00:02:00 UTC"], "2013-05-01 00:00:59 UTC", "2013-05-01 00:02:00 UTC"
|
138
|
-
end
|
139
|
-
|
140
|
-
it "group_by_hour" do
|
141
|
-
assert_zeros :hour, "2013-05-01 04:01:01 UTC", ["2013-05-01 03:00:00 UTC", "2013-05-01 04:00:00 UTC", "2013-05-01 05:00:00 UTC"], "2013-05-01 03:59:59 UTC", "2013-05-01 05:00:00 UTC"
|
142
|
-
end
|
143
|
-
|
144
|
-
it "group_by_day" do
|
145
|
-
assert_zeros :day, "2013-05-01 20:00:00 UTC", ["2013-04-30 00:00:00 UTC", "2013-05-01 00:00:00 UTC", "2013-05-02 00:00:00 UTC"], "2013-04-30 00:00:00 UTC", "2013-05-02 23:59:59 UTC"
|
146
|
-
end
|
147
|
-
|
148
|
-
it "group_by_day with time zone" do
|
149
|
-
assert_zeros_tz :day, "2013-05-01 20:00:00 PDT", ["2013-04-30 00:00:00 PDT", "2013-05-01 00:00:00 PDT", "2013-05-02 00:00:00 PDT"], "2013-04-30 00:00:00 PDT", "2013-05-02 23:59:59 PDT"
|
150
|
-
end
|
151
|
-
|
152
|
-
it "group_by_week" do
|
153
|
-
assert_zeros :week, "2013-05-01 20:00:00 UTC", ["2013-04-21 00:00:00 UTC", "2013-04-28 00:00:00 UTC", "2013-05-05 00:00:00 UTC"], "2013-04-27 23:59:59 UTC", "2013-05-11 23:59:59 UTC"
|
154
|
-
end
|
155
|
-
|
156
|
-
it "group_by_week with time zone" do
|
157
|
-
assert_zeros_tz :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"
|
158
|
-
end
|
159
|
-
|
160
|
-
it "group_by_month" do
|
161
|
-
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"
|
162
|
-
end
|
163
|
-
|
164
|
-
it "group_by_month with time zone" do
|
165
|
-
assert_zeros_tz :month, "2013-04-16 20:00:00 PDT", ["2013-03-01 00:00:00 PST", "2013-04-01 00:00:00 PDT", "2013-05-01 00:00:00 PDT"], "2013-03-01 00:00:00 PST", "2013-05-31 23:59:59 PDT"
|
166
|
-
end
|
167
|
-
|
168
|
-
it "group_by_year" do
|
169
|
-
assert_zeros :year, "2013-04-16 20:00:00 UTC", ["2012-01-01 00:00:00 UTC", "2013-01-01 00:00:00 UTC", "2014-01-01 00:00:00 UTC"], "2012-01-01 00:00:00 UTC", "2014-12-31 23:59:59 UTC"
|
170
|
-
end
|
171
|
-
|
172
|
-
it "group_by_year with time zone" do
|
173
|
-
assert_zeros_tz :year, "2013-04-16 20:00:00 PDT", ["2012-01-01 00:00:00 PST", "2013-01-01 00:00:00 PST", "2014-01-01 00:00:00 PST"], "2012-01-01 00:00:00 PST", "2014-12-31 23:59:59 PST"
|
174
|
-
end
|
175
|
-
|
176
|
-
it "group_by_day_of_week" do
|
177
|
-
create_user "2013-05-01 00:00:00 UTC"
|
178
|
-
expected = {}
|
179
|
-
7.times do |n|
|
180
|
-
expected[n] = n == 3 ? 1 : 0
|
181
|
-
end
|
182
|
-
assert_equal(expected, User.group_by_day_of_week(:created_at, Time.zone, true).count(:created_at))
|
183
|
-
end
|
184
|
-
|
185
|
-
it "group_by_hour_of_day" do
|
186
|
-
create_user "2013-05-01 20:00:00 UTC"
|
187
|
-
expected = {}
|
188
|
-
24.times do |n|
|
189
|
-
expected[n] = n == 20 ? 1 : 0
|
190
|
-
end
|
191
|
-
assert_equal(expected, User.group_by_hour_of_day(:created_at, Time.zone, true).count(:created_at))
|
192
|
-
end
|
193
|
-
|
194
|
-
it "excludes end" do
|
195
|
-
create_user "2013-05-02 00:00:00 UTC"
|
196
|
-
expected = {
|
197
|
-
Time.parse("2013-05-01 00:00:00 UTC") => 0
|
198
|
-
}
|
199
|
-
assert_equal(expected, User.group_by_day(:created_at, Time.zone, Time.parse("2013-05-01 00:00:00 UTC")...Time.parse("2013-05-02 00:00:00 UTC")).count)
|
200
|
-
end
|
201
|
-
|
202
|
-
it "works with previous scopes" do
|
203
|
-
create_user "2013-05-01 00:00:00 UTC"
|
204
|
-
expected = {
|
205
|
-
Time.parse("2013-05-01 00:00:00 UTC") => 0
|
206
|
-
}
|
207
|
-
assert_equal(expected, User.where("id = 0").group_by_day(:created_at, Time.zone, Time.parse("2013-05-01 00:00:00 UTC")..Time.parse("2013-05-01 23:59:59 UTC")).count)
|
208
|
-
end
|
209
|
-
|
210
|
-
end
|
211
|
-
|
212
|
-
end
|
213
|
-
end
|
214
|
-
|
215
|
-
# helper methods
|
216
|
-
|
217
|
-
def assert_group(method, created_at, key, time_zone = nil)
|
218
|
-
create_user created_at
|
219
|
-
assert_equal(ordered_hash({time_key(key) => 1}), User.send(:"group_by_#{method}", :created_at, time_zone).order(method.to_s).count)
|
220
|
-
end
|
221
|
-
|
222
|
-
def assert_group_tz(method, created_at, key)
|
223
|
-
assert_group method, created_at, key, "Pacific Time (US & Canada)"
|
224
|
-
end
|
225
|
-
|
226
|
-
def assert_group_number(method, created_at, key, time_zone = nil)
|
227
|
-
create_user created_at
|
228
|
-
assert_equal(ordered_hash({number_key(key) => 1}), User.send(:"group_by_#{method}", :created_at, time_zone).order(method.to_s).count)
|
229
|
-
end
|
230
|
-
|
231
|
-
def assert_group_number_tz(method, created_at, key)
|
232
|
-
assert_group_number method, created_at, key, "Pacific Time (US & Canada)"
|
233
|
-
end
|
234
|
-
|
235
|
-
def assert_zeros(method, created_at, keys, range_start, range_end, time_zone = nil, java_hack = false)
|
236
|
-
create_user created_at
|
237
|
-
expected = {}
|
238
|
-
keys.each_with_index do |key, i|
|
239
|
-
expected[Time.parse(key)] = i == 1 ? 1 : 0
|
240
|
-
end
|
241
|
-
assert_equal(expected, User.send(:"group_by_#{method}", :created_at, time_zone, Time.parse(range_start)..Time.parse(range_end)).count)
|
242
|
-
end
|
243
|
-
|
244
|
-
def assert_zeros_tz(method, created_at, keys, range_start, range_end)
|
245
|
-
assert_zeros method, created_at, keys, range_start, range_end, "Pacific Time (US & Canada)", true
|
246
|
-
end
|
247
|
-
|
248
|
-
def time_key(key)
|
249
|
-
if RUBY_PLATFORM == "java"
|
250
|
-
if User.connection.adapter_name == "PostgreSQL"
|
251
|
-
Time.parse(key).utc.strftime("%Y-%m-%d %H:%M:%S%z")[0..-3]
|
252
|
-
else
|
253
|
-
Time.parse(key).strftime("%Y-%m-%d %H:%M:%S").gsub(/ 00\:00\:00\z/, "")
|
254
|
-
end
|
255
|
-
else
|
256
|
-
if User.connection.adapter_name == "PostgreSQL" and ActiveRecord::VERSION::MAJOR == 3
|
257
|
-
Time.parse(key).utc.strftime("%Y-%m-%d %H:%M:%S+00")
|
258
|
-
else
|
259
|
-
Time.parse(key)
|
260
|
-
end
|
261
|
-
end
|
262
|
-
end
|
263
|
-
|
264
|
-
def number_key(key)
|
265
|
-
if RUBY_PLATFORM == "java"
|
266
|
-
if User.connection.adapter_name == "PostgreSQL"
|
267
|
-
key.to_f
|
268
|
-
else
|
269
|
-
key
|
270
|
-
end
|
271
|
-
else
|
272
|
-
if User.connection.adapter_name == "PostgreSQL"
|
273
|
-
ActiveRecord::VERSION::MAJOR == 3 ? key.to_s : key.to_f
|
274
|
-
else
|
275
|
-
key
|
276
|
-
end
|
277
|
-
end
|
278
|
-
end
|
279
|
-
|
280
|
-
def ordered_hash(hash)
|
281
|
-
RUBY_VERSION =~ /1\.8/ ? hash.inject(ActiveSupport::OrderedHash.new){|h, (k, v)| h[k] = v; h } : hash
|
282
|
-
end
|
283
|
-
|
284
|
-
def create_user(created_at)
|
285
|
-
User.create!(:name => "Andrew", :score => 1, :created_at => Time.parse(created_at))
|
286
|
-
end
|
287
|
-
|
288
|
-
end
|