Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add methods [days, weeks, months, years]_between #27966

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions activesupport/CHANGELOG.md
@@ -1,3 +1,9 @@
* Add methods calculation: `#days_between`, `#weeks_between`,`#months_between`, `#years_between`
for "date" and "time" objects, that return the number of days, weeks, months, years
to given date, default to `Date.current`

*bogdanvlviv*

* Deprecate `.halt_callback_chains_on_return_false`.

*Rafael Mendonça França*
Expand Down
Expand Up @@ -2,6 +2,9 @@

module DateAndTime
module Calculations
AMOUNT_DAYS_PER_YEAR = 365
AMOUNT_WEEKS_PER_YEAR = 52
AMOUNT_MONTHS_PER_YEAR = 12
DAYS_INTO_WEEK = {
monday: 0,
tuesday: 1,
Expand Down Expand Up @@ -68,6 +71,13 @@ def days_since(days)
advance(days: days)
end

# Returns the number of days to given date, default to +Date.current+.
def days_between(date = ::Date.current)
date1, date2 = self.to_date, date.to_date

((date2.yday - date1.yday) + AMOUNT_DAYS_PER_YEAR * (date2.year - date1.year)).abs
end

# Returns a new date/time the specified number of weeks ago.
def weeks_ago(weeks)
advance(weeks: -weeks)
Expand All @@ -78,6 +88,13 @@ def weeks_since(weeks)
advance(weeks: weeks)
end

# Returns the number of weeks to given date, default to +Date.current+.
def weeks_between(date = ::Date.current)
date1, date2 = self.to_date, date.to_date

((date2.cweek - date1.cweek) + AMOUNT_WEEKS_PER_YEAR * (date2.year - date1.year)).abs
end

# Returns a new date/time the specified number of months ago.
def months_ago(months)
advance(months: -months)
Expand All @@ -88,6 +105,13 @@ def months_since(months)
advance(months: months)
end

# Returns the number of months to given date, default to +Date.current+.
def months_between(date = ::Date.current)
date1, date2 = self.to_date, date.to_date

((date2.month - date1.month) + AMOUNT_MONTHS_PER_YEAR * (date2.year - date1.year)).abs
end

# Returns a new date/time the specified number of years ago.
def years_ago(years)
advance(years: -years)
Expand All @@ -98,6 +122,13 @@ def years_since(years)
advance(years: years)
end

# Returns the number of years to given date, default to +Date.current+.
def years_between(date = ::Date.current)
date1, date2 = self.to_date, date.to_date

(date2.year - date1.year).abs
end

# Returns a new date/time at the start of the month.
#
# today = Date.today # => Thu, 18 Jun 2015
Expand Down
54 changes: 54 additions & 0 deletions activesupport/test/core_ext/date_and_time_behavior.rb
Expand Up @@ -31,6 +31,20 @@ def test_days_since
assert_equal date_time_init(2005, 1, 1, 10, 10, 10), date_time_init(2004, 12, 31, 10, 10, 10).days_since(1)
end

def test_days_between
assert_equal 0, date_time_init(2017, 2, 10, 10, 10, 10).days_between(date_time_init(2017, 2, 10, 10, 10, 10))

assert_equal 0, date_time_init(2017, 2, 10, 9, 10, 10).days_between(date_time_init(2017, 2, 10, 10, 10, 10))
assert_equal 0, date_time_init(2017, 2, 10, 10, 10, 10).days_between(date_time_init(2017, 2, 10, 9, 10, 10))

assert_equal 1, date_time_init(2017, 2, 9, 10, 10, 10).days_between(date_time_init(2017, 2, 10, 10, 10, 10))
assert_equal 1, date_time_init(2017, 2, 10, 10, 10, 10).days_between(date_time_init(2017, 2, 9, 10, 10, 10))
assert_equal 9, date_time_init(2017, 2, 1, 10, 10, 10).days_between(date_time_init(2017, 2, 10, 10, 10, 10))
assert_equal 9, date_time_init(2017, 2, 10, 10, 10, 10).days_between(date_time_init(2017, 2, 1, 10, 10, 10))
assert_equal 365, date_time_init(2016, 2, 10, 10, 10, 10).days_between(date_time_init(2017, 2, 10, 10, 10, 10))
assert_equal 365, date_time_init(2017, 2, 10, 10, 10, 10).days_between(date_time_init(2016, 2, 10, 10, 10, 10))
end

def test_weeks_ago
assert_equal date_time_init(2005, 5, 29, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).weeks_ago(1)
assert_equal date_time_init(2005, 5, 1, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).weeks_ago(5)
Expand All @@ -46,6 +60,20 @@ def test_weeks_since
assert_equal date_time_init(2005, 1, 4, 10, 10, 10), date_time_init(2004, 12, 28, 10, 10, 10).weeks_since(1)
end

def test_weeks_between
assert_equal 0, date_time_init(2017, 2, 10, 10, 10, 10).weeks_between(date_time_init(2017, 2, 10, 10, 10, 10))

assert_equal 0, date_time_init(2017, 2, 10, 9, 10, 10).weeks_between(date_time_init(2017, 2, 10, 10, 10, 10))
assert_equal 0, date_time_init(2017, 2, 10, 10, 10, 10).weeks_between(date_time_init(2017, 2, 10, 9, 10, 10))

assert_equal 1, date_time_init(2017, 2, 3, 10, 10, 10).weeks_between(date_time_init(2017, 2, 10, 10, 10, 10))
assert_equal 1, date_time_init(2017, 2, 10, 10, 10, 10).weeks_between(date_time_init(2017, 2, 3, 10, 10, 10))
assert_equal 9, date_time_init(2016, 12, 9, 10, 10, 10).weeks_between(date_time_init(2017, 2, 10, 10, 10, 10))
assert_equal 9, date_time_init(2017, 2, 10, 10, 10, 10).weeks_between(date_time_init(2016, 12, 9, 10, 10, 10))
assert_equal 52, date_time_init(2016, 2, 10, 10, 10, 10).weeks_between(date_time_init(2017, 2, 10, 10, 10, 10))
assert_equal 52, date_time_init(2017, 2, 10, 10, 10, 10).weeks_between(date_time_init(2016, 2, 10, 10, 10, 10))
end

def test_months_ago
assert_equal date_time_init(2005, 5, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).months_ago(1)
assert_equal date_time_init(2004, 11, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).months_ago(7)
Expand All @@ -68,6 +96,20 @@ def test_months_since
assert_equal date_time_init(2005, 2, 28, 10, 10, 10), date_time_init(2005, 1, 31, 10, 10, 10).months_since(1)
end

def test_months_between
assert_equal 0, date_time_init(2017, 2, 10, 10, 10, 10).months_between(date_time_init(2017, 2, 10, 10, 10, 10))

assert_equal 0, date_time_init(2017, 2, 9, 10, 10, 10).months_between(date_time_init(2017, 2, 10, 10, 10, 10))
assert_equal 0, date_time_init(2017, 2, 10, 10, 10, 10).months_between(date_time_init(2017, 2, 9, 10, 10, 10))

assert_equal 1, date_time_init(2017, 1, 10, 10, 10, 10).months_between(date_time_init(2017, 2, 10, 10, 10, 10))
assert_equal 1, date_time_init(2017, 2, 10, 10, 10, 10).months_between(date_time_init(2017, 1, 10, 10, 10, 10))
assert_equal 9, date_time_init(2016, 5, 10, 10, 10, 10).months_between(date_time_init(2017, 2, 10, 10, 10, 10))
assert_equal 9, date_time_init(2017, 2, 10, 10, 10, 10).months_between(date_time_init(2016, 5, 1, 10, 10, 10))
assert_equal 12, date_time_init(2016, 2, 10, 10, 10, 10).months_between(date_time_init(2017, 2, 10, 10, 10, 10))
assert_equal 12, date_time_init(2017, 2, 10, 10, 10, 10).months_between(date_time_init(2016, 2, 10, 10, 10, 10))
end

def test_years_ago
assert_equal date_time_init(2004, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).years_ago(1)
assert_equal date_time_init(1998, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).years_ago(7)
Expand All @@ -81,6 +123,18 @@ def test_years_since
assert_equal date_time_init(2182, 6, 5, 10, 10, 10), date_time_init(2005, 6, 5, 10, 10, 10).years_since(177)
end

def test_years_between
assert_equal 0, date_time_init(2017, 2, 10, 10, 10, 10).years_between(date_time_init(2017, 2, 10, 10, 10, 10))

assert_equal 0, date_time_init(2017, 1, 10, 10, 10, 10).years_between(date_time_init(2017, 2, 10, 10, 10, 10))
assert_equal 0, date_time_init(2017, 2, 10, 10, 10, 10).years_between(date_time_init(2017, 1, 10, 10, 10, 10))

assert_equal 1, date_time_init(2016, 2, 10, 10, 10, 10).years_between(date_time_init(2017, 2, 10, 10, 10, 10))
assert_equal 1, date_time_init(2017, 2, 10, 10, 10, 10).years_between(date_time_init(2016, 2, 10, 10, 10, 10))
assert_equal 9, date_time_init(2008, 2, 10, 10, 10, 10).years_between(date_time_init(2017, 2, 10, 10, 10, 10))
assert_equal 9, date_time_init(2017, 2, 10, 10, 10, 10).years_between(date_time_init(2008, 2, 10, 10, 10, 10))
end

def test_beginning_of_month
assert_equal date_time_init(2005, 2, 1, 0, 0, 0), date_time_init(2005, 2, 22, 10, 10, 10).beginning_of_month
end
Expand Down