Add Date and Time `#yesterday?` and `#tomorrow?` (#37625)

Add Date and Time `#yesterday?` and `#tomorrow?` alongside `#today?`.

Aliased to `#prev_day?` and `#next_day?` to match the existing `#prev/next_day` methods.
This commit is contained in:
Jatin Dhankhar 2020-03-20 09:00:14 +05:30 committed by GitHub
parent e91b3b2c58
commit 5df9b4584c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 215 additions and 3 deletions

View File

@ -1,3 +1,9 @@
* Add Date and Time `#yesterday?` and `#tomorrow?` alongside `#today?`.
Aliased to `#prev_day?` and `#next_day?` to match the existing `#prev/next_day` methods.
*Jatin Dhankhar*
* Add `Enumerable#pick` to complement `ActiveRecord::Relation#pick`.
*Eugene Kenny*

View File

@ -31,6 +31,18 @@ module DateAndTime
to_date == ::Date.current
end
# Returns true if the date/time is tomorrow.
def tomorrow?
to_date == ::Date.current.tomorrow
end
alias :next_day? :tomorrow?
# Returns true if the date/time is yesterday.
def yesterday?
to_date == ::Date.current.yesterday
end
alias :prev_day? :yesterday?
# Returns true if the date/time is in the past.
def past?
self < self.class.current

View File

@ -245,6 +245,20 @@ module ActiveSupport
time.today?
end
# Returns true if the current object's time falls within
# the next day (tomorrow).
def tomorrow?
time.tomorrow?
end
alias :next_day? :tomorrow?
# Returns true if the current object's time falls within
# the previous day (yesterday).
def yesterday?
time.yesterday?
end
alias :prev_day? :yesterday?
# Returns true if the current object's time is in the future.
def future?
utc.future?

View File

@ -253,9 +253,81 @@ class DateTimeExtCalculationsTest < ActiveSupport::TestCase
end
end
def test_yesterday_with_offset
Date.stub(:current, Date.new(2000, 1, 1)) do
assert_equal true, DateTime.civil(1999, 12, 31, 23, 59, 59, Rational(-18000, 86400)).yesterday?
assert_equal false, DateTime.civil(2000, 1, 1, 0, 0, 0, Rational(-18000, 86400)).yesterday?
assert_equal false, DateTime.civil(2000, 1, 1, 23, 59, 59, Rational(-18000, 86400)).yesterday?
assert_equal true, DateTime.civil(1999, 12, 31, 0, 0, 0, Rational(-18000, 86400)).yesterday?
end
end
def test_yesterday_without_offset
Date.stub(:current, Date.new(2000, 1, 1)) do
assert_equal true, DateTime.civil(1999, 12, 31, 23, 59, 59).yesterday?
assert_equal false, DateTime.civil(2000, 1, 1, 0).yesterday?
assert_equal false, DateTime.civil(2000, 1, 1, 23, 59, 59).yesterday?
assert_equal false, DateTime.civil(2000, 1, 2, 0).yesterday?
end
end
def test_prev_day_with_offset
Date.stub(:current, Date.new(2000, 1, 1)) do
assert_equal true, DateTime.civil(1999, 12, 31, 23, 59, 59, Rational(-18000, 86400)).prev_day?
assert_equal false, DateTime.civil(2000, 1, 1, 0, 0, 0, Rational(-18000, 86400)).prev_day?
assert_equal false, DateTime.civil(2000, 1, 1, 23, 59, 59, Rational(-18000, 86400)).prev_day?
assert_equal true, DateTime.civil(1999, 12, 31, 0, 0, 0, Rational(-18000, 86400)).prev_day?
end
end
def test_prev_day_without_offset
Date.stub(:current, Date.new(2000, 1, 1)) do
assert_equal true, DateTime.civil(1999, 12, 31, 23, 59, 59).prev_day?
assert_equal false, DateTime.civil(2000, 1, 1, 0).prev_day?
assert_equal false, DateTime.civil(2000, 1, 1, 23, 59, 59).prev_day?
assert_equal false, DateTime.civil(2000, 1, 2, 0).prev_day?
end
end
def test_tomorrow_with_offset
Date.stub(:current, Date.new(2000, 1, 1)) do
assert_equal false, DateTime.civil(1999, 12, 31, 23, 59, 59, Rational(-18000, 86400)).tomorrow?
assert_equal true, DateTime.civil(2000, 1, 2, 0, 0, 0, Rational(-18000, 86400)).tomorrow?
assert_equal false, DateTime.civil(2000, 1, 1, 23, 59, 59, Rational(-18000, 86400)).tomorrow?
assert_equal true, DateTime.civil(2000, 1, 2, 23, 59, 59, Rational(-18000, 86400)).tomorrow?
end
end
def test_tomorrow_without_offset
Date.stub(:current, Date.new(2000, 1, 1)) do
assert_equal false, DateTime.civil(1999, 12, 31, 23, 59, 59).tomorrow?
assert_equal true, DateTime.civil(2000, 1, 2, 0).tomorrow?
assert_equal false, DateTime.civil(2000, 1, 1, 23, 59, 59).tomorrow?
assert_equal false, DateTime.civil(2000, 1, 3, 0).tomorrow?
end
end
def test_next_day_with_offset
Date.stub(:current, Date.new(2000, 1, 1)) do
assert_equal false, DateTime.civil(1999, 12, 31, 23, 59, 59, Rational(-18000, 86400)).next_day?
assert_equal true, DateTime.civil(2000, 1, 2, 0, 0, 0, Rational(-18000, 86400)).next_day?
assert_equal false, DateTime.civil(2000, 1, 1, 23, 59, 59, Rational(-18000, 86400)).next_day?
assert_equal true, DateTime.civil(2000, 1, 2, 23, 59, 59, Rational(-18000, 86400)).next_day?
end
end
def test_next_day_without_offset
Date.stub(:current, Date.new(2000, 1, 1)) do
assert_equal false, DateTime.civil(1999, 12, 31, 23, 59, 59).next_day?
assert_equal true, DateTime.civil(2000, 1, 2, 0).next_day?
assert_equal false, DateTime.civil(2000, 1, 1, 23, 59, 59).next_day?
assert_equal false, DateTime.civil(2000, 1, 3, 0).next_day?
end
end
def test_past_with_offset
DateTime.stub(:current, DateTime.civil(2005, 2, 10, 15, 30, 45, Rational(-18000, 86400))) do
assert_equal true, DateTime.civil(2005, 2, 10, 15, 30, 44, Rational(-18000, 86400)).past?
assert_equal true, DateTime.civil(2005, 2, 10, 15, 30, 44, Rational(-18000, 86400)).past?
assert_equal false, DateTime.civil(2005, 2, 10, 15, 30, 45, Rational(-18000, 86400)).past?
assert_equal false, DateTime.civil(2005, 2, 10, 15, 30, 46, Rational(-18000, 86400)).past?
end

View File

@ -686,6 +686,78 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase
end
end
def test_yesterday_with_time_local
Date.stub(:current, Date.new(2000, 1, 1)) do
assert_equal true, Time.local(1999, 12, 31, 23, 59, 59).yesterday?
assert_equal false, Time.local(2000, 1, 1, 0).yesterday?
assert_equal true, Time.local(1999, 12, 31).yesterday?
assert_equal false, Time.local(2000, 1, 2, 0).yesterday?
end
end
def test_yesterday_with_time_utc
Date.stub(:current, Date.new(2000, 1, 1)) do
assert_equal true, Time.utc(1999, 12, 31, 23, 59, 59).yesterday?
assert_equal false, Time.utc(2000, 1, 1, 0).yesterday?
assert_equal true, Time.utc(1999, 12, 31).yesterday?
assert_equal false, Time.utc(2000, 1, 2, 0).yesterday?
end
end
def test_prev_day_with_time_local
Date.stub(:current, Date.new(2000, 1, 1)) do
assert_equal true, Time.local(1999, 12, 31, 23, 59, 59).prev_day?
assert_equal false, Time.local(2000, 1, 1, 0).prev_day?
assert_equal true, Time.local(1999, 12, 31).prev_day?
assert_equal false, Time.local(2000, 1, 2, 0).prev_day?
end
end
def test_prev_day_with_time_utc
Date.stub(:current, Date.new(2000, 1, 1)) do
assert_equal true, Time.utc(1999, 12, 31, 23, 59, 59).prev_day?
assert_equal false, Time.utc(2000, 1, 1, 0).prev_day?
assert_equal true, Time.utc(1999, 12, 31).prev_day?
assert_equal false, Time.utc(2000, 1, 2, 0).prev_day?
end
end
def test_tomorrow_with_time_local
Date.stub(:current, Date.new(2000, 1, 1)) do
assert_equal false, Time.local(1999, 12, 31, 23, 59, 59).tomorrow?
assert_equal true, Time.local(2000, 1, 2, 0).tomorrow?
assert_equal true, Time.local(2000, 1, 2, 23, 59, 59).tomorrow?
assert_equal false, Time.local(2000, 1, 1, 0).tomorrow?
end
end
def test_tomorrow_with_time_utc
Date.stub(:current, Date.new(2000, 1, 1)) do
assert_equal false, Time.utc(1999, 12, 31, 23, 59, 59).tomorrow?
assert_equal true, Time.utc(2000, 1, 2, 0).tomorrow?
assert_equal true, Time.utc(2000, 1, 2, 23, 59, 59).tomorrow?
assert_equal false, Time.utc(2000, 1, 1, 0).tomorrow?
end
end
def test_next_day_with_time_local
Date.stub(:current, Date.new(2000, 1, 1)) do
assert_equal false, Time.local(1999, 12, 31, 23, 59, 59).next_day?
assert_equal true, Time.local(2000, 1, 2, 0).next_day?
assert_equal true, Time.local(2000, 1, 2, 23, 59, 59).next_day?
assert_equal false, Time.local(2000, 1, 1, 0).next_day?
end
end
def test_next_day_with_time_utc
Date.stub(:current, Date.new(2000, 1, 1)) do
assert_equal false, Time.utc(1999, 12, 31, 23, 59, 59).next_day?
assert_equal true, Time.utc(2000, 1, 2, 0).next_day?
assert_equal true, Time.utc(2000, 1, 2, 23, 59, 59).next_day?
assert_equal false, Time.utc(2000, 1, 1, 0).next_day?
end
end
def test_past_with_time_current_as_time_local
with_env_tz "US/Eastern" do
Time.stub(:current, Time.local(2005, 2, 10, 15, 30, 45)) do

View File

@ -251,6 +251,42 @@ class TimeWithZoneTest < ActiveSupport::TestCase
end
end
def test_yesterday?
Date.stub(:current, Date.new(2000, 1, 1)) do
assert_equal true, ActiveSupport::TimeWithZone.new(nil, @time_zone, Time.utc(1999, 12, 31, 23, 59, 59)).yesterday?
assert_equal false, ActiveSupport::TimeWithZone.new(nil, @time_zone, Time.utc(2000, 1, 1, 0)).yesterday?
assert_equal true, ActiveSupport::TimeWithZone.new(nil, @time_zone, Time.utc(1999, 12, 31)).yesterday?
assert_equal false, ActiveSupport::TimeWithZone.new(nil, @time_zone, Time.utc(2000, 1, 2, 0)).yesterday?
end
end
def test_prev_day?
Date.stub(:current, Date.new(2000, 1, 1)) do
assert_equal true, ActiveSupport::TimeWithZone.new(nil, @time_zone, Time.utc(1999, 12, 31, 23, 59, 59)).prev_day?
assert_equal false, ActiveSupport::TimeWithZone.new(nil, @time_zone, Time.utc(2000, 1, 1, 0)).prev_day?
assert_equal true, ActiveSupport::TimeWithZone.new(nil, @time_zone, Time.utc(1999, 12, 31)).prev_day?
assert_equal false, ActiveSupport::TimeWithZone.new(nil, @time_zone, Time.utc(2000, 1, 2, 0)).prev_day?
end
end
def test_tomorrow?
Date.stub(:current, Date.new(2000, 1, 1)) do
assert_equal false, ActiveSupport::TimeWithZone.new(nil, @time_zone, Time.utc(1999, 12, 31, 23, 59, 59)).tomorrow?
assert_equal true, ActiveSupport::TimeWithZone.new(nil, @time_zone, Time.utc(2000, 1, 2, 0)).tomorrow?
assert_equal false, ActiveSupport::TimeWithZone.new(nil, @time_zone, Time.utc(2000, 1, 1, 23, 59, 59)).tomorrow?
assert_equal false, ActiveSupport::TimeWithZone.new(nil, @time_zone, Time.utc(1999, 12, 31, 0)).tomorrow?
end
end
def test_next_day?
Date.stub(:current, Date.new(2000, 1, 1)) do
assert_equal false, ActiveSupport::TimeWithZone.new(nil, @time_zone, Time.utc(1999, 12, 31, 23, 59, 59)).next_day?
assert_equal true, ActiveSupport::TimeWithZone.new(nil, @time_zone, Time.utc(2000, 1, 2, 0)).next_day?
assert_equal false, ActiveSupport::TimeWithZone.new(nil, @time_zone, Time.utc(2000, 1, 1, 23, 59, 59)).next_day?
assert_equal false, ActiveSupport::TimeWithZone.new(nil, @time_zone, Time.utc(1999, 12, 31, 0)).next_day?
end
end
def test_past_with_time_current_as_time_local
with_env_tz "US/Eastern" do
Time.stub(:current, Time.local(2005, 2, 10, 15, 30, 45)) do

View File

@ -2928,7 +2928,7 @@ INFO: The following calculation methods have edge cases in October 1582, since d
#### `Date.current`
Active Support defines `Date.current` to be today in the current time zone. That's like `Date.today`, except that it honors the user time zone, if defined. It also defines `Date.yesterday` and `Date.tomorrow`, and the instance predicates `past?`, `today?`, `future?`, `on_weekday?` and `on_weekend?`, all of them relative to `Date.current`.
Active Support defines `Date.current` to be today in the current time zone. That's like `Date.today`, except that it honors the user time zone, if defined. It also defines `Date.yesterday` and `Date.tomorrow`, and the instance predicates `past?`, `today?`, `tomorrow?`, `next_day?`, `yesterday?`, `prev_day?`, `future?`, `on_weekday?` and `on_weekend?`, all of them relative to `Date.current`.
When making Date comparisons using methods which honor the user time zone, make sure to use `Date.current` and not `Date.today`. There are cases where the user time zone might be in the future compared to the system time zone, which `Date.today` uses by default. This means `Date.today` may equal `Date.yesterday`.
@ -3441,7 +3441,7 @@ t.advance(seconds: 1)
#### `Time.current`
Active Support defines `Time.current` to be today in the current time zone. That's like `Time.now`, except that it honors the user time zone, if defined. It also defines the instance predicates `past?`, `today?`, and `future?`, all of them relative to `Time.current`.
Active Support defines `Time.current` to be today in the current time zone. That's like `Time.now`, except that it honors the user time zone, if defined. It also defines the instance predicates `past?`, `today?`, `tomorrow?`, `next_day?`, `yesterday?`, `prev_day?` and `future?`, all of them relative to `Time.current`.
When making Time comparisons using methods which honor the user time zone, make sure to use `Time.current` instead of `Time.now`. There are cases where the user time zone might be in the future compared to the system time zone, which `Time.now` uses by default. This means `Time.now.to_date` may equal `Date.yesterday`.