instance method
change
Ruby on Rails 7.2.3
Since v3.0.20Signature
change(options)
Returns a new Time where one or more of the elements have been changed according to the options parameter. The time options (:hour, :min, :sec, :usec, :nsec) reset cascadingly, so if only the hour is passed, then minute, sec, usec, and nsec is set to 0. If the hour and minute is passed, then sec, usec, and nsec is set to 0. The options parameter takes a hash with any of these keys: :year, :month, :day, :hour, :min, :sec, :usec, :nsec, :offset. Pass either :usec or :nsec, not both.
Time.new(2012, 8, 29, 22, 35, 0).change(day: 1) # => Time.new(2012, 8, 1, 22, 35, 0) Time.new(2012, 8, 29, 22, 35, 0).change(year: 1981, day: 1) # => Time.new(1981, 8, 1, 22, 35, 0) Time.new(2012, 8, 29, 22, 35, 0).change(year: 1981, hour: 0) # => Time.new(1981, 8, 29, 0, 0, 0)
Parameters
-
optionsreq
Source
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 123
def change(options)
new_year = options.fetch(:year, year)
new_month = options.fetch(:month, month)
new_day = options.fetch(:day, day)
new_hour = options.fetch(:hour, hour)
new_min = options.fetch(:min, options[:hour] ? 0 : min)
new_sec = options.fetch(:sec, (options[:hour] || options[:min]) ? 0 : sec)
new_offset = options.fetch(:offset, nil)
if new_nsec = options[:nsec]
raise ArgumentError, "Can't change both :nsec and :usec at the same time: #{options.inspect}" if options[:usec]
new_usec = Rational(new_nsec, 1000)
else
new_usec = options.fetch(:usec, (options[:hour] || options[:min] || options[:sec]) ? 0 : Rational(nsec, 1000))
end
raise ArgumentError, "argument out of range" if new_usec >= 1000000
new_sec += Rational(new_usec, 1000000)
if new_offset
::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec, new_offset)
elsif utc?
::Time.utc(new_year, new_month, new_day, new_hour, new_min, new_sec)
elsif zone.respond_to?(:utc_to_local)
new_time = ::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec, zone)
# When there are two occurrences of a nominal time due to DST ending,
# `Time.new` chooses the first chronological occurrence (the one with a
# larger UTC offset). However, for `change`, we want to choose the
# occurrence that matches this time's UTC offset.
#
# If the new time's UTC offset is larger than this time's UTC offset, the
# new time might be a first chronological occurrence. So we add the offset
# difference to fast-forward the new time, and check if the result has the
# desired UTC offset (i.e. is the second chronological occurrence).
offset_difference = new_time.utc_offset - utc_offset
if offset_difference > 0 && (new_time_2 = new_time + offset_difference).utc_offset == utc_offset
new_time_2
else
new_time
end
elsif zone
::Time.local(new_sec, new_min, new_hour, new_day, new_month, new_year, nil, nil, isdst, nil)
else
::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec, utc_offset)
end
end
Defined in activesupport/lib/active_support/core_ext/time/calculations.rb line 123
· View on GitHub
· Improve this page
· Find usages on GitHub
Defined in Time