diff options
author | gregolsen <anotheroneman@yahoo.com> | 2012-09-18 17:18:19 +0300 |
---|---|---|
committer | gregolsen <anotheroneman@yahoo.com> | 2012-09-18 17:18:19 +0300 |
commit | da26dfbefdccac4ab1f3195ae747685d2b11be13 (patch) | |
tree | b70490470cd80389bdaf19ab96af2948544507a9 /activesupport | |
parent | 9f2d1a146c3883c2ea9d16d4fa5a7ad65ca55db8 (diff) | |
download | rails-da26dfbefdccac4ab1f3195ae747685d2b11be13.tar.gz rails-da26dfbefdccac4ab1f3195ae747685d2b11be13.tar.bz2 rails-da26dfbefdccac4ab1f3195ae747685d2b11be13.zip |
Date.beginning_of_week thread local and beginning_of_week application config option added (default is Monday)
Diffstat (limited to 'activesupport')
6 files changed, 121 insertions, 17 deletions
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 59e112e3f9..47f1c8458e 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,5 +1,7 @@ ## Rails 4.0.0 (unreleased) ## +* `Date.beginning_of_week` thread local and `beginning_of_week` application config option added (default is Monday). *Innokenty Mikhailov* + * An optional block can be passed to `config_accessor` to set its default value class User diff --git a/activesupport/lib/active_support/core_ext/date/calculations.rb b/activesupport/lib/active_support/core_ext/date/calculations.rb index 86badf4d29..ee23bc578c 100644 --- a/activesupport/lib/active_support/core_ext/date/calculations.rb +++ b/activesupport/lib/active_support/core_ext/date/calculations.rb @@ -9,6 +9,29 @@ class Date include DateAndTime::Calculations class << self + attr_accessor :beginning_of_week_default + + # Returns the week start (e.g. :monday) for the current request, if this has been set (via Date.beginning_of_week=). + # If <tt>Date.beginning_of_week</tt> has not been set for the current request, returns the week start specified in <tt>config.beginning_of_week</tt>. + # If no config.beginning_of_week was specified, returns :monday. + def beginning_of_week + Thread.current[:beginning_of_week] || beginning_of_week_default || :monday + end + + # Sets <tt>Date.beginning_of_week</tt> to a week start (e.g. :monday) for current request/thread. + # + # This method accepts any of the following day symbols: + # :monday, :tuesday, :wednesday, :thursday, :friday, :saturday, :sunday + def beginning_of_week=(week_start) + Thread.current[:beginning_of_week] = find_beginning_of_week!(week_start) + end + + # Returns week start day symbol (e.g. :monday), or raises an ArgumentError for invalid day symbol. + def find_beginning_of_week!(week_start) + raise ArgumentError, "Invalid beginning of week: #{week_start}" unless ::Date::DAYS_INTO_WEEK.keys.include?(week_start) + week_start + end + # Returns a new Date representing the date 1 day ago (i.e. yesterday's date). def yesterday ::Date.current.yesterday 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 e703fca7a7..1f78b9eb5a 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 @@ -109,10 +109,11 @@ module DateAndTime alias :at_beginning_of_year :beginning_of_year # Returns a new date/time representing the given day in the next week. - # Default is :monday. + # Week is assumed to start on +start_day+, default is + # +Date.beginning_of_week+ or +config.beginning_of_week+ when set. # DateTime objects have their time set to 0:00. - def next_week(day = :monday) - first_hour{ weeks_since(1).beginning_of_week.days_since(DAYS_INTO_WEEK[day]) } + def next_week(start_day = Date.beginning_of_week) + first_hour{ weeks_since(1).beginning_of_week.days_since(days_span(start_day)) } end # Short-hand for months_since(1). @@ -131,10 +132,11 @@ module DateAndTime end # Returns a new date/time representing the given day in the previous week. - # Default is :monday. + # Week is assumed to start on +start_day+, default is + # +Date.beginning_of_week+ or +config.beginning_of_week+ when set. # DateTime objects have their time set to 0:00. - def prev_week(day = :monday) - first_hour{ weeks_ago(1).beginning_of_week.days_since(DAYS_INTO_WEEK[day]) } + def prev_week(start_day = Date.beginning_of_week) + first_hour{ weeks_ago(1).beginning_of_week.days_since(days_span(start_day)) } end alias_method :last_week, :prev_week @@ -157,31 +159,44 @@ module DateAndTime alias_method :last_year, :prev_year # Returns the number of days to the start of the week on the given day. - # Default is :monday. - def days_to_week_start(start_day = :monday) + # Week is assumed to start on +start_day+, default is + # +Date.beginning_of_week+ or +config.beginning_of_week+ when set. + def days_to_week_start(start_day = Date.beginning_of_week) start_day_number = DAYS_INTO_WEEK[start_day] current_day_number = wday != 0 ? wday - 1 : 6 (current_day_number - start_day_number) % 7 end # Returns a new date/time representing the start of this week on the given day. - # Default is :monday. - # DateTime objects have their time set to 0:00. - def beginning_of_week(start_day = :monday) + # Week is assumed to start on +start_day+, default is + # +Date.beginning_of_week+ or +config.beginning_of_week+ when set. + # +DateTime+ objects have their time set to 0:00. + def beginning_of_week(start_day = Date.beginning_of_week) result = days_ago(days_to_week_start(start_day)) acts_like?(:time) ? result.midnight : result end alias :at_beginning_of_week :beginning_of_week - alias :monday :beginning_of_week + + # Returns Monday of this week assuming that week starts on Monday. + # +DateTime+ objects have their time set to 0:00. + def monday + beginning_of_week(:monday) + end # Returns a new date/time representing the end of this week on the given day. - # Default is :monday (i.e end of Sunday). + # Week is assumed to start on +start_day+, default is + # +Date.beginning_of_week+ or +config.beginning_of_week+ when set. # DateTime objects have their time set to 23:59:59. - def end_of_week(start_day = :monday) + def end_of_week(start_day = Date.beginning_of_week) last_hour{ days_since(6 - days_to_week_start(start_day)) } end alias :at_end_of_week :end_of_week - alias :sunday :end_of_week + + # Returns Sunday of this week assuming that week starts on Monday. + # +DateTime+ objects have their time set to 23:59:59. + def sunday + end_of_week(:monday) + end # Returns a new date/time representing the end of the month. # DateTime objects will have a time set to 23:59:59. @@ -209,5 +224,9 @@ module DateAndTime result = yield acts_like?(:time) ? result.end_of_day : result end + + def days_span(day) + (DAYS_INTO_WEEK[day] - DAYS_INTO_WEEK[Date.beginning_of_week]) % 7 + end end end diff --git a/activesupport/lib/active_support/core_ext/time/calculations.rb b/activesupport/lib/active_support/core_ext/time/calculations.rb index 148f2c27f1..78baa80ccd 100644 --- a/activesupport/lib/active_support/core_ext/time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/time/calculations.rb @@ -169,8 +169,9 @@ class Time beginning_of_day..end_of_day end - # Returns a Range representing the whole week of the current time. Week starts on start_day (default is :monday, i.e. end of Sunday). - def all_week(start_day = :monday) + # Returns a Range representing the whole week of the current time. + # Week starts on start_day, default is <tt>Date.week_start</tt> or <tt>config.week_start</tt> when set. + def all_week(start_day = Date.beginning_of_week) beginning_of_week(start_day)..end_of_week(start_day) end diff --git a/activesupport/lib/active_support/railtie.rb b/activesupport/lib/active_support/railtie.rb index aa8d408da9..29351db742 100644 --- a/activesupport/lib/active_support/railtie.rb +++ b/activesupport/lib/active_support/railtie.rb @@ -27,6 +27,15 @@ module ActiveSupport Time.zone_default = zone_default end + # Sets the default week start + # If assigned value is not a valid day symbol (e.g. :sunday, :monday, ...), an exception will be raised. + initializer "active_support.initialize_beginning_of_week" do |app| + require 'active_support/core_ext/date/calculations' + beginning_of_week_default = Date.find_beginning_of_week!(app.config.beginning_of_week) + + Date.beginning_of_week_default = beginning_of_week_default + end + initializer "active_support.set_configs" do |app| app.config.active_support.each do |k, v| k = "#{k}=" diff --git a/activesupport/test/core_ext/date_and_time_behavior.rb b/activesupport/test/core_ext/date_and_time_behavior.rb index 014935b0c0..9927856aa2 100644 --- a/activesupport/test/core_ext/date_and_time_behavior.rb +++ b/activesupport/test/core_ext/date_and_time_behavior.rb @@ -101,6 +101,15 @@ module DateAndTimeBehavior assert_equal date_time_init(2006,11,1,0,0,0), date_time_init(2006,10,23,0,0,0).next_week(:wednesday) end + def test_next_week_with_default_beginning_of_week_set + with_bw_default(:tuesday) do + assert_equal Time.local(2012, 3, 28), Time.local(2012, 3, 21).next_week(:wednesday) + assert_equal Time.local(2012, 3, 31), Time.local(2012, 3, 21).next_week(:saturday) + assert_equal Time.local(2012, 3, 27), Time.local(2012, 3, 21).next_week(:tuesday) + assert_equal Time.local(2012, 4, 02), Time.local(2012, 3, 21).next_week(:monday) + end + end + def test_next_month_on_31st assert_equal date_time_init(2005,9,30,15,15,10), date_time_init(2005,8,31,15,15,10).next_month end @@ -121,6 +130,15 @@ module DateAndTimeBehavior assert_equal date_time_init(2006,11,15,0,0,0), date_time_init(2006,11,23,0,0,0).prev_week(:wednesday) end + def test_prev_week_with_default_beginning_of_week + with_bw_default(:tuesday) do + assert_equal Time.local(2012, 3, 14), Time.local(2012, 3, 21).prev_week(:wednesday) + assert_equal Time.local(2012, 3, 17), Time.local(2012, 3, 21).prev_week(:saturday) + assert_equal Time.local(2012, 3, 13), Time.local(2012, 3, 21).prev_week(:tuesday) + assert_equal Time.local(2012, 3, 19), Time.local(2012, 3, 21).prev_week(:monday) + end + end + def test_prev_month_on_31st assert_equal date_time_init(2004,2,29,10,10,10), date_time_init(2004,3,31,10,10,10).prev_month end @@ -151,6 +169,18 @@ module DateAndTimeBehavior assert_equal 3, date_time_init(2011,11,9,0,0,0).days_to_week_start(:sunday) end + def test_days_to_week_start_with_default_set + with_bw_default(:friday) do + assert_equal 6, Time.local(2012,03,8,0,0,0).days_to_week_start + assert_equal 5, Time.local(2012,03,7,0,0,0).days_to_week_start + assert_equal 4, Time.local(2012,03,6,0,0,0).days_to_week_start + assert_equal 3, Time.local(2012,03,5,0,0,0).days_to_week_start + assert_equal 2, Time.local(2012,03,4,0,0,0).days_to_week_start + assert_equal 1, Time.local(2012,03,3,0,0,0).days_to_week_start + assert_equal 0, Time.local(2012,03,2,0,0,0).days_to_week_start + end + end + def test_beginning_of_week assert_equal date_time_init(2005,1,31,0,0,0), date_time_init(2005,2,4,10,10,10).beginning_of_week assert_equal date_time_init(2005,11,28,0,0,0), date_time_init(2005,11,28,0,0,0).beginning_of_week #monday @@ -183,4 +213,24 @@ module DateAndTimeBehavior assert_equal date_time_init(2007,12,31,23,59,59,Rational(999999999, 1000)), date_time_init(2007,2,22,10,10,10).end_of_year assert_equal date_time_init(2007,12,31,23,59,59,Rational(999999999, 1000)), date_time_init(2007,12,31,10,10,10).end_of_year end + + def test_monday_with_default_beginning_of_week_set + with_bw_default(:saturday) do + assert_equal date_time_init(2012,9,17,0,0,0), date_time_init(2012,9,18,0,0,0).monday + end + end + + def test_sunday_with_default_beginning_of_week_set + with_bw_default(:wednesday) do + assert_equal date_time_init(2012,9,23,23,59,59, Rational(999999999, 1000)), date_time_init(2012,9,19,0,0,0).sunday + end + end + + def with_bw_default(bw = :monday) + old_bw = Date.beginning_of_week + Date.beginning_of_week = bw + yield + ensure + Date.beginning_of_week = old_bw + end end |