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

Use exact date spans instead of multi-nine approximations for all_day, all_week, etc. methods #51575

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
Expand Up @@ -87,6 +87,10 @@ def end_of_day
end
alias :at_end_of_day :end_of_day

def end_of_day_threshold
beginning_of_day.advance(days: 1)
end

def plus_with_duration(other) # :nodoc:
if ActiveSupport::Duration === other
other.since(self)
Expand Down
Expand Up @@ -157,6 +157,11 @@ def end_of_quarter
end
alias :at_end_of_quarter :end_of_quarter

def end_of_quarter_threshold
last_quarter_month = month + (12 - month) % 3
beginning_of_month.change(month: last_quarter_month).end_of_month_threshold
end

# Returns the quarter for a date/time.
#
# Date.new(2010, 1, 31).quarter # => 1
Expand Down Expand Up @@ -285,6 +290,10 @@ def end_of_week(start_day = Date.beginning_of_week)
end
alias :at_end_of_week :end_of_week

def end_of_week_threshold(start_day = Date.beginning_of_week)
days_since(6 - days_to_week_start(start_day)).advance(days: 1).beginning_of_day
end

# Returns Sunday of this week assuming that week starts on Monday.
# +DateTime+ objects have their time set to 23:59:59.
def sunday
Expand All @@ -299,37 +308,46 @@ def end_of_month
end
alias :at_end_of_month :end_of_month

def end_of_month_threshold
last_day = ::Time.days_in_month(month, year)
days_since(last_day - day).advance(days: 1).beginning_of_day
end

# Returns a new date/time representing the end of the year.
# DateTime objects will have a time set to 23:59:59.
def end_of_year
change(month: 12).end_of_month
end
alias :at_end_of_year :end_of_year

def end_of_year_threshold
change(month: 12).end_of_month_threshold
end

# Returns a Range representing the whole day of the current date/time.
def all_day
beginning_of_day..end_of_day
beginning_of_day...end_of_day_threshold
end

# Returns a Range representing the whole week of the current date/time.
# Week starts on start_day, default is <tt>Date.beginning_of_week</tt> or <tt>config.beginning_of_week</tt> when set.
def all_week(start_day = Date.beginning_of_week)
beginning_of_week(start_day)..end_of_week(start_day)
beginning_of_week(start_day)...end_of_week_threshold(start_day)
end

# Returns a Range representing the whole month of the current date/time.
def all_month
beginning_of_month..end_of_month
beginning_of_month...end_of_month_threshold
end

# Returns a Range representing the whole quarter of the current date/time.
def all_quarter
beginning_of_quarter..end_of_quarter
beginning_of_quarter...end_of_quarter_threshold
end

# Returns a Range representing the whole year of the current date/time.
def all_year
beginning_of_year..end_of_year
beginning_of_year...end_of_year_threshold
end

# Returns a new date/time representing the next occurrence of the specified day of week.
Expand Down
Expand Up @@ -142,6 +142,10 @@ def end_of_day
end
alias :at_end_of_day :end_of_day

def end_of_day_threshold
change(hour: 0, min: 0, sec: 0, usec: 0).advance(days: 1)
end

# Returns a new DateTime representing the start of the hour (hh:00:00).
def beginning_of_hour
change(min: 0)
Expand Down
Expand Up @@ -251,6 +251,15 @@ def end_of_day
end
alias :at_end_of_day :end_of_day

def end_of_day_threshold
change(
hour: 0,
min: 0,
sec: 0,
usec: 0
).advance(days: 1)
end

# Returns a new Time representing the start of the hour (x:00)
def beginning_of_hour
change(min: 0)
Expand Down
18 changes: 9 additions & 9 deletions activesupport/test/core_ext/date_ext_test.rb
Expand Up @@ -284,36 +284,36 @@ def test_end_of_day_when_zone_is_set

def test_all_day
beginning_of_day = Time.local(2011, 6, 7, 0, 0, 0)
end_of_day = Time.local(2011, 6, 7, 23, 59, 59, Rational(999999999, 1000))
assert_equal beginning_of_day..end_of_day, Date.new(2011, 6, 7).all_day
beginning_of_next_day = Time.local(2011, 6, 8, 0, 0, 0)
assert_equal beginning_of_day...beginning_of_next_day, Date.new(2011, 6, 7).all_day
end

def test_all_day_when_zone_is_set
zone = ActiveSupport::TimeZone["Hawaii"]
with_env_tz "UTC" do
with_tz_default zone do
beginning_of_day = zone.local(2011, 6, 7, 0, 0, 0)
end_of_day = zone.local(2011, 6, 7, 23, 59, 59, Rational(999999999, 1000))
assert_equal beginning_of_day..end_of_day, Date.new(2011, 6, 7).all_day
beginning_of_next_day = zone.local(2011, 6, 8, 0, 0, 0)
assert_equal beginning_of_day...beginning_of_next_day, Date.new(2011, 6, 7).all_day
end
end
end

def test_all_week
assert_equal Date.new(2011, 6, 6)..Date.new(2011, 6, 12), Date.new(2011, 6, 7).all_week
assert_equal Date.new(2011, 6, 5)..Date.new(2011, 6, 11), Date.new(2011, 6, 7).all_week(:sunday)
assert_equal Date.new(2011, 6, 6)...Date.new(2011, 6, 13), Date.new(2011, 6, 7).all_week
assert_equal Date.new(2011, 6, 5)...Date.new(2011, 6, 12), Date.new(2011, 6, 7).all_week(:sunday)
end

def test_all_month
assert_equal Date.new(2011, 6, 1)..Date.new(2011, 6, 30), Date.new(2011, 6, 7).all_month
assert_equal Date.new(2011, 6, 1)...Date.new(2011, 7, 1), Date.new(2011, 6, 7).all_month
end

def test_all_quarter
assert_equal Date.new(2011, 4, 1)..Date.new(2011, 6, 30), Date.new(2011, 6, 7).all_quarter
assert_equal Date.new(2011, 4, 1)...Date.new(2011, 7, 1), Date.new(2011, 6, 7).all_quarter
end

def test_all_year
assert_equal Date.new(2011, 1, 1)..Date.new(2011, 12, 31), Date.new(2011, 6, 7).all_year
assert_equal Date.new(2011, 1, 1)...Date.new(2012, 1, 1), Date.new(2011, 6, 7).all_year
end

def test_xmlschema
Expand Down
16 changes: 8 additions & 8 deletions activesupport/test/core_ext/time_ext_test.rb
Expand Up @@ -1252,32 +1252,32 @@ def test_case_equality
end

def test_all_day
assert_equal Time.local(2011, 6, 7, 0, 0, 0)..Time.local(2011, 6, 7, 23, 59, 59, Rational(999999999, 1000)), Time.local(2011, 6, 7, 10, 10, 10).all_day
assert_equal Time.local(2011, 6, 7, 0, 0, 0)...Time.local(2011, 6, 8, 0, 0, 0), Time.local(2011, 6, 7, 10, 10, 10).all_day
end

def test_all_day_with_timezone
beginning_of_day = ActiveSupport::TimeWithZone.new(nil, ActiveSupport::TimeZone["Hawaii"], Time.local(2011, 6, 7, 0, 0, 0))
end_of_day = ActiveSupport::TimeWithZone.new(nil, ActiveSupport::TimeZone["Hawaii"], Time.local(2011, 6, 7, 23, 59, 59, Rational(999999999, 1000)))
beginning_of_next_day = ActiveSupport::TimeWithZone.new(nil, ActiveSupport::TimeZone["Hawaii"], Time.local(2011, 6, 8, 0, 0, 0))

assert_equal beginning_of_day, ActiveSupport::TimeWithZone.new(Time.local(2011, 6, 7, 10, 10, 10), ActiveSupport::TimeZone["Hawaii"]).all_day.begin
assert_equal end_of_day, ActiveSupport::TimeWithZone.new(Time.local(2011, 6, 7, 10, 10, 10), ActiveSupport::TimeZone["Hawaii"]).all_day.end
assert_equal beginning_of_next_day, ActiveSupport::TimeWithZone.new(Time.local(2011, 6, 7, 10, 10, 10), ActiveSupport::TimeZone["Hawaii"]).all_day.end
end

def test_all_week
assert_equal Time.local(2011, 6, 6, 0, 0, 0)..Time.local(2011, 6, 12, 23, 59, 59, Rational(999999999, 1000)), Time.local(2011, 6, 7, 10, 10, 10).all_week
assert_equal Time.local(2011, 6, 5, 0, 0, 0)..Time.local(2011, 6, 11, 23, 59, 59, Rational(999999999, 1000)), Time.local(2011, 6, 7, 10, 10, 10).all_week(:sunday)
assert_equal Time.local(2011, 6, 6, 0, 0, 0)...Time.local(2011, 6, 13, 0, 0, 0), Time.local(2011, 6, 7, 10, 10, 10).all_week
assert_equal Time.local(2011, 6, 5, 0, 0, 0)...Time.local(2011, 6, 12, 0, 0, 0), Time.local(2011, 6, 7, 10, 10, 10).all_week(:sunday)
end

def test_all_month
assert_equal Time.local(2011, 6, 1, 0, 0, 0)..Time.local(2011, 6, 30, 23, 59, 59, Rational(999999999, 1000)), Time.local(2011, 6, 7, 10, 10, 10).all_month
assert_equal Time.local(2011, 6, 1, 0, 0, 0)...Time.local(2011, 7, 1, 0, 0, 0), Time.local(2011, 6, 7, 10, 10, 10).all_month
end

def test_all_quarter
assert_equal Time.local(2011, 4, 1, 0, 0, 0)..Time.local(2011, 6, 30, 23, 59, 59, Rational(999999999, 1000)), Time.local(2011, 6, 7, 10, 10, 10).all_quarter
assert_equal Time.local(2011, 4, 1, 0, 0, 0)...Time.local(2011, 7, 1, 0, 0, 0), Time.local(2011, 6, 7, 10, 10, 10).all_quarter
end

def test_all_year
assert_equal Time.local(2011, 1, 1, 0, 0, 0)..Time.local(2011, 12, 31, 23, 59, 59, Rational(999999999, 1000)), Time.local(2011, 6, 7, 10, 10, 10).all_year
assert_equal Time.local(2011, 1, 1, 0, 0, 0)...Time.local(2012, 1, 1, 0, 0, 0), Time.local(2011, 6, 7, 10, 10, 10).all_year
end

def test_rfc3339_parse
Expand Down