From c1bf9f51d9592f4eee4c6e48cd01fef78068ded4 Mon Sep 17 00:00:00 2001 From: Shota Iguchi Date: Sat, 24 Sep 2016 00:22:59 +0900 Subject: [PATCH] Add next occur and previous occurred day of week API --- activesupport/CHANGELOG.md | 4 ++++ .../core_ext/date_and_time/calculations.rb | 16 ++++++++++++++ .../test/core_ext/date_time_ext_test.rb | 22 +++++++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index bb578d81dc917..63061302426ad 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,7 @@ +* Add `Date#prev_occurring` and `Date#next_occurring` to return specified next/previous occurring day of week. + + *Shota Iguchi* + * Add default option to class_attribute. Before: class_attribute :settings diff --git a/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb b/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb index f2ba7fdda51a0..e2e1d3e359147 100644 --- a/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb @@ -320,6 +320,22 @@ def all_year beginning_of_year..end_of_year end + # Returns specific next occurring day of week + def next_occurring(day_of_week) + current_day_number = wday != 0 ? wday - 1 : 6 + from_now = DAYS_INTO_WEEK.fetch(day_of_week) - current_day_number + from_now += 7 unless from_now > 0 + since(from_now.days) + end + + # Returns specific previous occurring day of week + def prev_occurring(day_of_week) + current_day_number = wday != 0 ? wday - 1 : 6 + ago = current_day_number - DAYS_INTO_WEEK.fetch(day_of_week) + ago += 7 unless ago > 0 + ago(ago.days) + end + private def first_hour(date_or_time) date_or_time.acts_like?(:time) ? date_or_time.beginning_of_day : date_or_time diff --git a/activesupport/test/core_ext/date_time_ext_test.rb b/activesupport/test/core_ext/date_time_ext_test.rb index be7c14e9b4ffb..276fa2bfd3aac 100644 --- a/activesupport/test/core_ext/date_time_ext_test.rb +++ b/activesupport/test/core_ext/date_time_ext_test.rb @@ -28,6 +28,28 @@ def test_to_s end end + def test_next_occur + datetime = DateTime.new(2016, 9, 24, 0, 0) # saturday + assert_equal datetime.next_occurring(:monday), datetime.since(2.days) + assert_equal datetime.next_occurring(:tuesday), datetime.since(3.days) + assert_equal datetime.next_occurring(:wednesday), datetime.since(4.days) + assert_equal datetime.next_occurring(:thursday), datetime.since(5.days) + assert_equal datetime.next_occurring(:friday), datetime.since(6.days) + assert_equal datetime.next_occurring(:saturday), datetime.since(1.week) + assert_equal datetime.next_occurring(:sunday), datetime.since(1.day) + end + + def test_prev_occur + datetime = DateTime.new(2016, 9, 24, 0, 0) # saturday + assert_equal datetime.prev_occurring(:monday), datetime.ago(5.days) + assert_equal datetime.prev_occurring(:tuesday), datetime.ago(4.days) + assert_equal datetime.prev_occurring(:wednesday), datetime.ago(3.days) + assert_equal datetime.prev_occurring(:thursday), datetime.ago(2.days) + assert_equal datetime.prev_occurring(:friday), datetime.ago(1.day) + assert_equal datetime.prev_occurring(:saturday), datetime.ago(1.week) + assert_equal datetime.prev_occurring(:sunday), datetime.ago(6.days) + end + def test_readable_inspect datetime = DateTime.new(2005, 2, 21, 14, 30, 0) assert_equal "Mon, 21 Feb 2005 14:30:00 +0000", datetime.readable_inspect