diff --git a/README.md b/README.md index f728568..6914e85 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ You can also group by: - hour - week - month +- quarter - year and diff --git a/lib/groupdate.rb b/lib/groupdate.rb index 9b5c77a..01f146e 100644 --- a/lib/groupdate.rb +++ b/lib/groupdate.rb @@ -4,7 +4,7 @@ require "groupdate/version" require "groupdate/magic" module Groupdate - FIELDS = [:second, :minute, :hour, :day, :week, :month, :year, :day_of_week, :hour_of_day, :day_of_month, :month_of_year] + FIELDS = [:second, :minute, :hour, :day, :week, :month, :quarter, :year, :day_of_week, :hour_of_day, :day_of_month, :month_of_year] METHODS = FIELDS.map { |v| :"group_by_#{v}" } mattr_accessor :week_start, :day_start, :time_zone diff --git a/lib/groupdate/magic.rb b/lib/groupdate/magic.rb index 939061d..e6baa04 100644 --- a/lib/groupdate/magic.rb +++ b/lib/groupdate/magic.rb @@ -45,6 +45,8 @@ module Groupdate ["MONTH(CONVERT_TZ(DATE_SUB(#{column}, INTERVAL #{day_start} HOUR), '+00:00', ?))", time_zone] when :week ["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] + when :quarter + ["DATE_ADD(CONVERT_TZ(DATE_FORMAT(DATE(CONCAT(EXTRACT(YEAR FROM CONVERT_TZ(DATE_SUB(#{column}, INTERVAL #{day_start} HOUR), '+00:00', ?)), '-', LPAD(1 + 3 * (QUARTER(CONVERT_TZ(DATE_SUB(#{column}, INTERVAL #{day_start} HOUR), '+00:00', ?)) - 1), 2, '00'), '-01')), '%Y-%m-%d %H:%i:%S'), ?, '+00:00'), INTERVAL #{day_start} HOUR)", time_zone, time_zone, time_zone] else format = case field @@ -201,7 +203,11 @@ module Groupdate if time_range.first series = [round_time(time_range.first)] - step = 1.send(field) + if field == :quarter + step = 3.months + else + step = 1.send(field) + end while (next_step = round_time(series.last + step)) && time_range.cover?(next_step) series << next_step @@ -278,6 +284,8 @@ module Groupdate (time - ((7 - week_start + weekday) % 7).days).midnight when :month time.beginning_of_month + when :quarter + time.beginning_of_quarter when :year time.beginning_of_year when :hour_of_day diff --git a/test/test_helper.rb b/test/test_helper.rb index c9aadf9..f08facc 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -230,6 +230,42 @@ module TestGroupdate assert_result_time :month, "2013-03-01 02:00:00 PST", "2013-03-01 10:00:00", true, day_start: 2 end + # quarter + + def test_quarter_end_of_quarter + assert_result_time :quarter, "2013-04-01 00:00:00 UTC", "2013-06-30 23:59:59" + end + + def test_quarter_start_of_quarter + assert_result_time :quarter, "2013-04-01 00:00:00 UTC", "2013-04-01 00:00:00" + end + + def test_quarter_end_of_quarter_with_time_zone + assert_result_time :quarter, "2013-04-01 00:00:00 PDT", "2013-07-01 06:59:59", true + end + + def test_quarter_start_of_quarter_with_time_zone + assert_result_time :quarter, "2013-04-01 00:00:00 PDT", "2013-04-01 07:00:00", true + end + + # quarter starts at 2am + + def test_quarter_end_of_quarter_day_start_2am + assert_result_time :quarter, "2013-04-01 02:00:00 UTC", "2013-07-01 01:59:59", false, day_start: 2 + end + + def test_quarter_start_of_quarter_day_start_2am + assert_result_time :quarter, "2013-04-01 02:00:00 UTC", "2013-04-01 02:00:00", false, day_start: 2 + end + + def test_quarter_end_of_quarter_with_time_zone_day_start_2am + assert_result_time :quarter, "2013-01-01 02:00:00 PST", "2013-04-01 08:59:59", true, day_start: 2 + end + + def test_quarter_start_of_quarter_with_time_zone_day_start_2am + assert_result_time :quarter, "2013-01-01 02:00:00 PST", "2013-01-01 10:00:00", true, day_start: 2 + end + # year def test_year_end_of_year @@ -468,6 +504,14 @@ module TestGroupdate 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 end + def test_zeros_quarter + assert_zeros :quarter, "2013-04-16 20:00:00 UTC", ["2013-01-01 00:00:00 UTC", "2013-04-01 00:00:00 UTC", "2013-07-01 00:00:00 UTC"], "2013-01-01 00:00:00 UTC", "2013-09-30 23:59:59 UTC" + end + + def test_zeros_quarter_time_zone + assert_zeros :quarter, "2013-04-16 20:00:00 PDT", ["2013-01-01 00:00:00 PST", "2013-04-01 00:00:00 PDT", "2013-07-01 00:00:00 PDT"], "2013-01-01 00:00:00 PST", "2013-09-30 23:59:59 PDT", true + end + def test_zeros_year 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" end @@ -721,6 +765,11 @@ module TestGroupdate assert_format :month, "March 2014", "%B %Y" end + def test_format_quarter + create_user "2014-03-05 00:00:00 UTC" + assert_format :quarter, "January 1, 2014", "%B %-e, %Y" + end + def test_format_year create_user "2014-03-01 00:00:00 UTC" assert_format :year, "2014", "%Y" -- libgit2 0.21.0