提交 bc1bcdde 编写于 作者: R Rob Zolkos & Xavier Noria 提交者: Xavier Noria

implements weeks_ago and prev_week for Date/DateTime/Time [#5122 state:committed]

上级 4bfe30ca
*Rails 3.1.0 (unreleased)*
* Added weeks_ago and prev_week to Date/DateTime/Time. [Rob Zolkos, fxn]
* Added before_remove_const callback to ActiveSupport::Dependencies.remove_unloadable_constants! [Andrew White]
......
......@@ -5,6 +5,8 @@
require 'active_support/core_ext/time/zones'
class Date
DAYS_INTO_WEEK = { :monday => 0, :tuesday => 1, :wednesday => 2, :thursday => 3, :friday => 4, :saturday => 5, :sunday => 6 }
if RUBY_VERSION < '1.9'
undef :>>
......@@ -127,6 +129,11 @@ def change(options)
)
end
# Returns a new Date/DateTime representing the time a number of specified weeks ago.
def weeks_ago(weeks)
advance(:weeks => -weeks)
end
# Returns a new Date/DateTime representing the time a number of specified months ago.
def months_ago(months)
advance(:months => -months)
......@@ -185,10 +192,15 @@ def end_of_week
alias :sunday :end_of_week
alias :at_end_of_week :end_of_week
# Returns a new Date/DateTime representing the start of the given day in the previous week (default is Monday).
def prev_week(day = :monday)
result = (self - 7).beginning_of_week + DAYS_INTO_WEEK[day]
self.acts_like?(:time) ? result.change(:hour => 0) : result
end
# Returns a new Date/DateTime representing the start of the given day in next week (default is Monday).
def next_week(day = :monday)
days_into_week = { :monday => 0, :tuesday => 1, :wednesday => 2, :thursday => 3, :friday => 4, :saturday => 5, :sunday => 6}
result = (self + 7).beginning_of_week + days_into_week[day]
result = (self + 7).beginning_of_week + DAYS_INTO_WEEK[day]
self.acts_like?(:time) ? result.change(:hour => 0) : result
end
......
......@@ -22,7 +22,7 @@ def days_in_month(month, year = now.year)
# Returns a new Time if requested year can be accommodated by Ruby's Time class
# (i.e., if year is within either 1970..2038 or 1902..2038, depending on system architecture);
# otherwise returns a DateTime
# otherwise returns a DateTime.
def time_with_datetime_fallback(utc_or_local, year, month=1, day=1, hour=0, min=0, sec=0, usec=0)
time = ::Time.send(utc_or_local, year, month, day, hour, min, sec, usec)
# This check is needed because Time.utc(y) returns a time object in the 2000s for 0 <= y <= 138.
......@@ -117,6 +117,11 @@ def since(seconds)
end
alias :in :since
# Returns a new Time representing the time a number of specified weeks ago.
def weeks_ago(weeks)
advance(:weeks => -weeks)
end
# Returns a new Time representing the time a number of specified months ago
def months_ago(months)
advance(:months => -months)
......@@ -172,6 +177,11 @@ def end_of_week
end
alias :at_end_of_week :end_of_week
# Returns a new Time representing the start of the given day in the previous week (default is Monday).
def prev_week(day = :monday)
ago(1.week).beginning_of_week.since(DAYS_INTO_WEEK[day].day).change(:hour => 0)
end
# Returns a new Time representing the start of the given day in next week (default is Monday).
def next_week(day = :monday)
since(1.week).beginning_of_week.since(DAYS_INTO_WEEK[day].day).change(:hour => 0)
......
......@@ -110,6 +110,14 @@ def test_beginning_of_year
assert_equal Date.new(2005,1,1).to_s, Date.new(2005,2,22).beginning_of_year.to_s
end
def test_weeks_ago
assert_equal Date.new(2005,5,10), Date.new(2005,5,17).weeks_ago(1)
assert_equal Date.new(2005,5,10), Date.new(2005,5,24).weeks_ago(2)
assert_equal Date.new(2005,5,10), Date.new(2005,5,31).weeks_ago(3)
assert_equal Date.new(2005,5,10), Date.new(2005,6,7).weeks_ago(4)
assert_equal Date.new(2006,12,31), Date.new(2007,2,4).weeks_ago(5)
end
def test_months_ago
assert_equal Date.new(2005,5,5), Date.new(2005,6,5).months_ago(1)
assert_equal Date.new(2004,11,5), Date.new(2005,6,5).months_ago(7)
......@@ -219,6 +227,14 @@ def test_advance_in_calendar_reform
end
end
def test_prev_week
assert_equal Date.new(2005,5,9), Date.new(2005,5,17).prev_week
assert_equal Date.new(2006,12,25), Date.new(2007,1,7).prev_week
assert_equal Date.new(2010,2,12), Date.new(2010,2,19).prev_week(:friday)
assert_equal Date.new(2010,2,13), Date.new(2010,2,19).prev_week(:saturday)
assert_equal Date.new(2010,2,27), Date.new(2010,3,4).prev_week(:saturday)
end
def test_next_week
assert_equal Date.new(2005,2,28), Date.new(2005,2,22).next_week
assert_equal Date.new(2005,3,4), Date.new(2005,2,22).next_week(:friday)
......
......@@ -92,6 +92,14 @@ def test_beginning_of_year
assert_equal DateTime.civil(2005,1,1,0,0,0), DateTime.civil(2005,2,22,10,10,10).beginning_of_year
end
def test_weeks_ago
assert_equal DateTime.civil(2005,5,29,10), DateTime.civil(2005,6,5,10,0,0).weeks_ago(1)
assert_equal DateTime.civil(2005,5,1,10), DateTime.civil(2005,6,5,10,0,0).weeks_ago(5)
assert_equal DateTime.civil(2005,4,24,10), DateTime.civil(2005,6,5,10,0,0).weeks_ago(6)
assert_equal DateTime.civil(2005,2,27,10), DateTime.civil(2005,6,5,10,0,0).weeks_ago(14)
assert_equal DateTime.civil(2004,12,25,10), DateTime.civil(2005,1,1,10,0,0).weeks_ago(1)
end
def test_months_ago
assert_equal DateTime.civil(2005,5,5,10), DateTime.civil(2005,6,5,10,0,0).months_ago(1)
assert_equal DateTime.civil(2004,11,5,10), DateTime.civil(2005,6,5,10,0,0).months_ago(7)
......@@ -196,6 +204,14 @@ def test_advanced_processes_first_the_date_deltas_and_then_the_time_deltas
assert_equal DateTime.civil(2010, 3, 29), DateTime.civil(2010, 2, 28, 22, 58, 59).advance(:months => 1, :hours => 1, :minutes => 1, :seconds => 1)
end
def test_prev_week
assert_equal DateTime.civil(2005,2,21), DateTime.civil(2005,3,1,15,15,10).prev_week
assert_equal DateTime.civil(2005,2,22), DateTime.civil(2005,3,1,15,15,10).prev_week(:tuesday)
assert_equal DateTime.civil(2005,2,25), DateTime.civil(2005,3,1,15,15,10).prev_week(:friday)
assert_equal DateTime.civil(2006,10,30), DateTime.civil(2006,11,6,0,0,0).prev_week
assert_equal DateTime.civil(2006,11,15), DateTime.civil(2006,11,23,0,0,0).prev_week(:wednesday)
end
def test_next_week
assert_equal DateTime.civil(2005,2,28), DateTime.civil(2005,2,22,15,15,10).next_week
assert_equal DateTime.civil(2005,3,4), DateTime.civil(2005,2,22,15,15,10).next_week(:friday)
......
......@@ -130,6 +130,14 @@ def test_beginning_of_year
assert_equal Time.local(2005,1,1,0,0,0), Time.local(2005,2,22,10,10,10).beginning_of_year
end
def test_weeks_ago
assert_equal Time.local(2005,5,29,10), Time.local(2005,6,5,10,0,0).weeks_ago(1)
assert_equal Time.local(2005,5,1,10), Time.local(2005,6,5,10,0,0).weeks_ago(5)
assert_equal Time.local(2005,4,24,10), Time.local(2005,6,5,10,0,0).weeks_ago(6)
assert_equal Time.local(2005,2,27,10), Time.local(2005,6,5,10,0,0).weeks_ago(14)
assert_equal Time.local(2004,12,25,10), Time.local(2005,1,1,10,0,0).weeks_ago(1)
end
def test_months_ago
assert_equal Time.local(2005,5,5,10), Time.local(2005,6,5,10,0,0).months_ago(1)
assert_equal Time.local(2004,11,5,10), Time.local(2005,6,5,10,0,0).months_ago(7)
......@@ -463,6 +471,16 @@ def test_utc_advance
assert_equal Time.utc(2013,10,17,20,22,19), Time.utc(2005,2,28,15,15,10).advance(:years => 7, :months => 19, :weeks => 2, :days => 5, :hours => 5, :minutes => 7, :seconds => 9)
end
def test_prev_week
with_env_tz 'US/Eastern' do
assert_equal Time.local(2005,2,21), Time.local(2005,3,1,15,15,10).prev_week
assert_equal Time.local(2005,2,22), Time.local(2005,3,1,15,15,10).prev_week(:tuesday)
assert_equal Time.local(2005,2,25), Time.local(2005,3,1,15,15,10).prev_week(:friday)
assert_equal Time.local(2006,10,30), Time.local(2006,11,6,0,0,0).prev_week
assert_equal Time.local(2006,11,15), Time.local(2006,11,23,0,0,0).prev_week(:wednesday)
end
end
def test_next_week
with_env_tz 'US/Eastern' do
assert_equal Time.local(2005,2,28), Time.local(2005,2,22,15,15,10).next_week
......
......@@ -2859,9 +2859,9 @@ d.end_of_week # => Sun, 09 May 2010
+beginning_of_week+ is aliased to +monday+ and +at_beginning_of_week+. +end_of_week+ is aliased to +sunday+ and +at_end_of_week+.
h6. +next_week+
h6. +prev_week+, +next_week+
+next_week+ receives a symbol with a day name in English (in lowercase, default is +:monday+) and it returns the date corresponding to that day in the next week:
The method +next_week+ receives a symbol with a day name in English (in lowercase, default is +:monday+) and it returns the date corresponding to that day:
<ruby>
d = Date.new(2010, 5, 9) # => Sun, 09 May 2010
......@@ -2869,6 +2869,14 @@ d.next_week # => Mon, 10 May 2010
d.next_week(:saturday) # => Sat, 15 May 2010
</ruby>
The method +prev_week+ is analogous:
<ruby>
d.prev_week # => Mon, 26 Apr 2010
d.prev_week(:saturday) # => Sat, 01 May 2010
d.prev_week(:friday) # => Fri, 30 Apr 2010
</ruby>
h6. +beginning_of_month+, +end_of_month+
The methods +beginning_of_month+ and +end_of_month+ return the dates for the beginning and end of the month:
......@@ -2946,6 +2954,15 @@ Date.new(2010, 4, 30).months_ago(2) # => Sun, 28 Feb 2010
Date.new(2009, 12, 31).months_since(2) # => Sun, 28 Feb 2010
</ruby>
h6. +weeks_ago+
The method +weeks_ago+ works analogously for weeks:
<ruby>
Date.new(2010, 5, 24).weeks_ago(1) # => Mon, 17 May 2010
Date.new(2010, 5, 24).weeks_ago(2) # => Mon, 10 May 2010
</ruby>
h6. +advance+
The most generic way to jump to other days is +advance+. This method receives a hash with keys +:years+, +:months+, +:weeks+, +:days+, and returns a date advanced as much as the present keys indicate:
......@@ -3067,6 +3084,8 @@ yesterday
tomorrow
beginning_of_week (monday, at_beginning_of_week)
end_on_week (at_end_of_week)
weeks_ago
prev_week
next_week
months_ago
months_since
......@@ -3239,6 +3258,8 @@ beginning_of_day (midnight, at_midnight, at_beginning_of_day)
end_of_day
beginning_of_week (monday, at_beginning_of_week)
end_on_week (at_end_of_week)
weeks_ago
prev_week
next_week
months_ago
months_since
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册