aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb
diff options
context:
space:
mode:
Diffstat (limited to 'activesupport/lib/active_support/core_ext/date_and_time/calculations.rb')
-rw-r--r--activesupport/lib/active_support/core_ext/date_and_time/calculations.rb74
1 files changed, 57 insertions, 17 deletions
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 b85e49aca5..9525c10112 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
@@ -9,15 +9,26 @@ module DateAndTime
:saturday => 5,
:sunday => 6
}
+ WEEKEND_DAYS = [ 6, 0 ]
# Returns a new date/time representing yesterday.
def yesterday
- advance(:days => -1)
+ advance(days: -1)
+ end
+
+ # Returns a new date/time representing the previous day.
+ def prev_day
+ advance(days: -1)
end
# Returns a new date/time representing tomorrow.
def tomorrow
- advance(:days => 1)
+ advance(days: 1)
+ end
+
+ # Returns a new date/time representing the next day.
+ def next_day
+ advance(days: 1)
end
# Returns true if the date/time is today.
@@ -35,6 +46,11 @@ module DateAndTime
self > self.class.current
end
+ # Returns true if the date/time falls on a Saturday or Sunday.
+ def on_weekend?
+ WEEKEND_DAYS.include?(wday)
+ end
+
# Returns a new date/time the specified number of days ago.
def days_ago(days)
advance(:days => -days)
@@ -111,9 +127,19 @@ module DateAndTime
# Returns a new date/time representing the given day in the next week.
# The +given_day_in_next_week+ defaults to the beginning of the week
# which is determined by +Date.beginning_of_week+ or +config.beginning_of_week+
- # when set. +DateTime+ objects have their time set to 0:00.
- def next_week(given_day_in_next_week = Date.beginning_of_week)
- first_hour(weeks_since(1).beginning_of_week.days_since(days_span(given_day_in_next_week)))
+ # when set. +DateTime+ objects have their time set to 0:00 unless +same_time+ is true.
+ def next_week(given_day_in_next_week = Date.beginning_of_week, same_time: false)
+ result = first_hour(weeks_since(1).beginning_of_week.days_since(days_span(given_day_in_next_week)))
+ same_time ? copy_time_to(result) : result
+ end
+
+ # Returns a new date/time representing the next weekday.
+ def next_weekday
+ if next_day.on_weekend?
+ next_week(:monday, same_time: true)
+ else
+ next_day
+ end
end
# Short-hand for months_since(1).
@@ -134,12 +160,23 @@ module DateAndTime
# Returns a new date/time representing the given day in the previous week.
# 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(start_day = Date.beginning_of_week)
- first_hour(weeks_ago(1).beginning_of_week.days_since(days_span(start_day)))
+ # DateTime objects have their time set to 0:00 unless +same_time+ is true.
+ def prev_week(start_day = Date.beginning_of_week, same_time: false)
+ result = first_hour(weeks_ago(1).beginning_of_week.days_since(days_span(start_day)))
+ same_time ? copy_time_to(result) : result
end
alias_method :last_week, :prev_week
+ # Returns a new date/time representing the previous weekday.
+ def prev_weekday
+ if prev_day.on_weekend?
+ copy_time_to(beginning_of_week(:friday))
+ else
+ prev_day
+ end
+ end
+ alias_method :last_weekday, :prev_weekday
+
# Short-hand for months_ago(1).
def prev_month
months_ago(1)
@@ -235,17 +272,20 @@ module DateAndTime
end
private
+ def first_hour(date_or_time)
+ date_or_time.acts_like?(:time) ? date_or_time.beginning_of_day : date_or_time
+ end
- def first_hour(date_or_time)
- date_or_time.acts_like?(:time) ? date_or_time.beginning_of_day : date_or_time
- end
+ def last_hour(date_or_time)
+ date_or_time.acts_like?(:time) ? date_or_time.end_of_day : date_or_time
+ end
- def last_hour(date_or_time)
- date_or_time.acts_like?(:time) ? date_or_time.end_of_day : date_or_time
- end
+ def days_span(day)
+ (DAYS_INTO_WEEK[day] - DAYS_INTO_WEEK[Date.beginning_of_week]) % 7
+ end
- def days_span(day)
- (DAYS_INTO_WEEK[day] - DAYS_INTO_WEEK[Date.beginning_of_week]) % 7
- end
+ def copy_time_to(other)
+ other.change(hour: hour, min: min, sec: sec, usec: try(:usec))
+ end
end
end