groupdate 6.6.0 → 6.7.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
  SHA256:
3
- metadata.gz: e81c8d8bce77a4b40a6e612c9dac7017561e3083cbe3f232ca7326d4cbc45941
4
- data.tar.gz: 993879fa7e1fd657e3362dd2e8edcda080c5c808cb5265ae9e14f46d5704a870
3
+ metadata.gz: 07ae05090ff5047136472fd30bc78ff078350c4fab330f73d84c36316dbbfbcf
4
+ data.tar.gz: 824c766fa826aeb15bcd0e21ed85b264a6d2f1a45c9e3f06d408b0df3c773e64
5
5
  SHA512:
6
- metadata.gz: 867a01e2efd77e36617edcc345a1503194a32518115afcd6f952f0eecf1fb03a26c1e4abbbb8acf82255db650408403c4c6744008e17d0c6355375a37b4cc10f
7
- data.tar.gz: d28f72bb69616b0389107d902758b41e1268c5785edb442406f9b213e8a1790185f3b61e91c7496edd992a6599b7bfd967721d861be79d78d3e28c3753b15cac
6
+ metadata.gz: 5716c00f5cfd9ef21a4500b8936cdc42cbe476ea1acaf8cf72df82ea69d9595284300cdeb4aac43af434dfe3ab192b021fc247910b6f294bb4dcc6cd72807fb1
7
+ data.tar.gz: 845d022ae8bba825fa3f6ee6ba91cb5939a60c5a2933a942a2aa8b0802cb4de7507226570dc648c597b5d8e7dc46211e8d57ea93c32d5fa63247a2a7262f6712
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## 6.7.0 (2025-06-02)
2
+
3
+ - Added time zone support for SQLite
4
+ - Added `day_start` support for SQLite
5
+ - Added `group_by_quarter` support for SQLite
6
+
1
7
  ## 6.6.0 (2025-05-04)
2
8
 
3
9
  - Dropped support for Ruby < 3.2 and Active Record < 7.1
data/README.md CHANGED
@@ -11,7 +11,7 @@ The simplest way to group by:
11
11
 
12
12
  :cake: Get the entire series - **the other best part**
13
13
 
14
- Supports PostgreSQL, MySQL, MariaDB, and Redshift, plus arrays and hashes (and limited support for [SQLite](#for-sqlite))
14
+ Supports PostgreSQL, MySQL, MariaDB, SQLite, and Redshift, plus arrays and hashes
15
15
 
16
16
  :cupid: Goes hand in hand with [Chartkick](https://www.chartkick.com)
17
17
 
@@ -25,7 +25,7 @@ Add this line to your application’s Gemfile:
25
25
  gem "groupdate"
26
26
  ```
27
27
 
28
- For MySQL, MariaDB, and SQLite, also follow [these instructions](#additional-instructions).
28
+ For MySQL and MariaDB, also follow [these instructions](#additional-instructions).
29
29
 
30
30
  ## Getting Started
31
31
 
@@ -268,20 +268,6 @@ SELECT CONVERT_TZ(NOW(), '+00:00', 'Pacific/Honolulu');
268
268
 
269
269
  It should return the time instead of `NULL`.
270
270
 
271
- ### For SQLite
272
-
273
- Groupdate has limited support for SQLite.
274
-
275
- - No time zone support
276
- - No `day_start` option
277
- - No `group_by_quarter` method
278
-
279
- If your application’s time zone is set to something other than `Etc/UTC` (the default), create an initializer with:
280
-
281
- ```ruby
282
- Groupdate.time_zone = false
283
- ```
284
-
285
271
  ## History
286
272
 
287
273
  View the [changelog](https://github.com/ankane/groupdate/blob/master/CHANGELOG.md)
@@ -2,9 +2,6 @@ module Groupdate
2
2
  module Adapters
3
3
  class SQLiteAdapter < BaseAdapter
4
4
  def group_clause
5
- raise Groupdate::Error, "Time zones not supported for SQLite" unless @time_zone.utc_offset.zero?
6
- raise Groupdate::Error, "day_start not supported for SQLite" unless day_start.zero?
7
-
8
5
  query =
9
6
  if period == :week
10
7
  ["strftime('%Y-%m-%d', #{column}, '-6 days', ?)", "weekday #{(week_start + 1) % 7}"]
@@ -36,7 +33,7 @@ module Groupdate
36
33
  when :month
37
34
  "%Y-%m-01"
38
35
  when :quarter
39
- raise Groupdate::Error, "Quarter not supported for SQLite"
36
+ nil
40
37
  else # year
41
38
  "%Y-01-01"
42
39
  end
@@ -44,8 +41,46 @@ module Groupdate
44
41
  ["strftime(?, #{column})", format]
45
42
  end
46
43
 
44
+ if period != :custom && (@time_zone != SeriesBuilder.utc || day_start != 0 || period == :quarter)
45
+ setup_function
46
+ week_start = period == :week ? Groupdate::Magic::DAYS[self.week_start].to_s : nil
47
+ query = ["groupdate_internal(?, #{column}, ?, ?, ?)", period, @time_zone.tzinfo.name, day_start, week_start]
48
+ end
49
+
47
50
  @relation.send(:sanitize_sql_array, query)
48
51
  end
52
+
53
+ private
54
+
55
+ def setup_function
56
+ @relation.connection_pool.with_connection do |connection|
57
+ raw_connection = connection.raw_connection
58
+ return if raw_connection.instance_variable_defined?(:@groupdate_function)
59
+
60
+ utc = SeriesBuilder.utc
61
+ date_periods = %i[day week month quarter year]
62
+
63
+ # note: this function is part of the internal API and may change between releases
64
+ # TODO improve performance
65
+ raw_connection.create_function("groupdate_internal", 4) do |func, period, value, time_zone, day_start, week_start|
66
+ if value.nil?
67
+ func.result = nil
68
+ else
69
+ period = period.to_sym
70
+ # cast_result handles week_start for day_of_week
71
+ week_start = :sunday if period == :day_of_week
72
+ result = SeriesBuilder.round_time(utc.parse(value), period, ActiveSupport::TimeZone[time_zone], day_start.to_i, week_start&.to_sym)
73
+ if date_periods.include?(period)
74
+ result = result.strftime("%Y-%m-%d")
75
+ elsif result.is_a?(Time)
76
+ result = result.in_time_zone(utc).strftime("%Y-%m-%d %H:%M:%S")
77
+ end
78
+ func.result = result
79
+ end
80
+ end
81
+ raw_connection.instance_variable_set(:@groupdate_function, true)
82
+ end
83
+ end
49
84
  end
50
85
  end
51
86
  end
@@ -46,7 +46,12 @@ module Groupdate
46
46
  return time_zone.at((time.to_time.to_i / n_seconds) * n_seconds)
47
47
  end
48
48
 
49
- time = time.to_time.in_time_zone(time_zone)
49
+ # TODO avoid calling to_time on dates
50
+ self.class.round_time(time.to_time, period, time_zone, day_start, @week_start_key)
51
+ end
52
+
53
+ def self.round_time(time, period, time_zone, day_start, week_start_key)
54
+ time = time.in_time_zone(time_zone)
50
55
 
51
56
  if day_start != 0
52
57
  # apply day_start to a time object that's not affected by DST
@@ -65,7 +70,7 @@ module Groupdate
65
70
  when :day
66
71
  time.beginning_of_day
67
72
  when :week
68
- time.beginning_of_week(@week_start_key)
73
+ time.beginning_of_week(week_start_key)
69
74
  when :month
70
75
  time.beginning_of_month
71
76
  when :quarter
@@ -77,7 +82,7 @@ module Groupdate
77
82
  when :minute_of_hour
78
83
  time.min
79
84
  when :day_of_week
80
- time.days_to_week_start(@week_start_key)
85
+ time.days_to_week_start(week_start_key)
81
86
  when :day_of_month
82
87
  time.day
83
88
  when :month_of_year
@@ -297,7 +302,7 @@ module Groupdate
297
302
  options.key?(:series) ? options[:series] : series_default
298
303
  end
299
304
 
300
- def utc
305
+ def self.utc
301
306
  @utc ||= ActiveSupport::TimeZone["Etc/UTC"]
302
307
  end
303
308
  end
@@ -1,3 +1,3 @@
1
1
  module Groupdate
2
- VERSION = "6.6.0"
2
+ VERSION = "6.7.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: groupdate
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.6.0
4
+ version: 6.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane