класс Time
Константы
- COMMON_YEAR_DAYS_IN_MONTH
- DATE_FORMATS
Атрибуты
Публичные методы класса
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 15 def ===(other) super || (self == Time && other.is_a?(ActiveSupport::TimeWithZone)) end
Переопределение метода сравнения на равенство по значению, чтобы оно возвращало true для экземпляров ActiveSupport::TimeWithZone.
# File activesupport/lib/active_support/core_ext/time/marshal.rb, line 8
def _load(marshaled_time)
time = _load_without_zone(marshaled_time)
time.instance_eval do
if zone = defined?(@_zone) && remove_instance_variable('@_zone')
ary = to_a
ary[0] += subsec if ary[0] == sec
ary[-1] = zone
utc? ? Time.utc(*ary) : Time.local(*ary)
else
self
end
end
end # File activesupport/lib/active_support/core_ext/time/calculations.rb, line 36
def at_with_coercion(*args)
return at_without_coercion(*args) if args.size != 1
# Time.at can be called with a time or numerical value
time_or_number = args.first
if time_or_number.is_a?(ActiveSupport::TimeWithZone) || time_or_number.is_a?(DateTime)
at_without_coercion(time_or_number.to_f).getlocal
else
at_without_coercion(time_or_number)
end
end Добавляет дополнительное поведение к ::at, чтобы экземпляры ActiveSupport::TimeWithZone и DateTime можно было использовать, когда вызывается с одним аргументом.
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 30 def current ::Time.zone ? ::Time.zone.now : ::Time.now end
Возвращает Time.zone.now, когда Time.zone или config.time_zone установлены, в противном случае возвращает Time.now.
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 21
def days_in_month(month, year = now.year)
if month == 2 && ::Date.gregorian_leap?(year)
29
else
COMMON_YEAR_DAYS_IN_MONTH[month]
end
end Возвращает количество дней в данном месяце. Если год не указан, используется текущий год.
# File activesupport/lib/active_support/core_ext/time/zones.rb, line 75 def find_zone(time_zone) find_zone!(time_zone) rescue nil end
# File activesupport/lib/active_support/core_ext/time/zones.rb, line 55
def find_zone!(time_zone)
if !time_zone || time_zone.is_a?(ActiveSupport::TimeZone)
time_zone
else
# lookup timezone based on identifier (unless we've been passed a TZInfo::Timezone)
unless time_zone.respond_to?(:period_for_local)
time_zone = ActiveSupport::TimeZone[time_zone] || TZInfo::Timezone.get(time_zone)
end
# Return if a TimeZone instance, or wrap in a TimeZone instance if a TZInfo::Timezone
if time_zone.is_a?(ActiveSupport::TimeZone)
time_zone
else
ActiveSupport::TimeZone.create(time_zone.name, nil, time_zone)
end
end
rescue TZInfo::InvalidTimezoneIdentifier
raise ArgumentError, "Invalid Timezone: #{time_zone}"
end Возвращает экземпляр TimeZone или null, или генерирует ArgumentError для неверных часовых поясов.
# File activesupport/lib/active_support/core_ext/time/zones.rb, line 44
def use_zone(time_zone)
new_zone = find_zone!(time_zone)
begin
old_zone, ::Time.zone = ::Time.zone, new_zone
yield
ensure
::Time.zone = old_zone
end
end Позволяет локально переопределить Time.zone, внутри предоставленного блока; при завершении восстанавливает Time.zone до предыдущего значения.
# File activesupport/lib/active_support/core_ext/time/zones.rb, line 12 def zone Thread.current[:time_zone] || zone_default end
Возвращает часовой пояс для текущего запроса, если он был установлен (через ::zone=). Если Time.zone не был установлен для текущего запроса, возвращает часовой пояс, указанный в config.time_zone.
# File activesupport/lib/active_support/core_ext/time/zones.rb, line 39 def zone=(time_zone) Thread.current[:time_zone] = find_zone!(time_zone) end
Устанавливает Time.zone на объект часового пояса для текущего запроса/потока.
Этот метод принимает следующие значения:
-
Объект часового пояса Rails.
-
Идентификатор объекта часового пояса Rails (например, «Восточное время (США и Канада)»,
-5.hours). -
Объект TZInfo::Timezone.
-
Идентификатор объекта TZInfo::Timezone (например, «America/New_York»).
Вот пример того, как можно установить Time.zone на основе каждого запроса и сбросить его по завершении запроса. current_user.time_zone просто должен возвращать строку, идентифицирующую предпочтительный часовой пояс пользователя:
class ApplicationController < ActionController::Base
around_filter :set_time_zone
def set_time_zone
if logged_in?
Time.use_zone(current_user.time_zone) { yield }
else
yield
end
end
end
Публичные методы экземпляра
# File activesupport/lib/active_support/core_ext/time/marshal.rb, line 24
def _dump(*args)
obj = dup
obj.instance_variable_set('@_zone', zone)
obj.send :_dump_without_zone, *args
end # File activesupport/lib/active_support/core_ext/time/acts_like.rb, line 5 def acts_like_time? true end
Утиная типизация как класс, подобный Time. См. Object#acts_like?.
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 121
def advance(options)
unless options[:weeks].nil?
options[:weeks], partial_weeks = options[:weeks].divmod(1)
options[:days] = options.fetch(:days, 0) + 7 * partial_weeks
end
unless options[:days].nil?
options[:days], partial_days = options[:days].divmod(1)
options[:hours] = options.fetch(:hours, 0) + 24 * partial_days
end
d = to_date.advance(options)
d = d.gregorian if d.julian?
time_advanced_by_date = change(:year => d.year, :month => d.month, :day => d.day)
seconds_to_advance = options.fetch(:seconds, 0) +
options.fetch(:minutes, 0) * 60 +
options.fetch(:hours, 0) * 3600
if seconds_to_advance.zero?
time_advanced_by_date
else
time_advanced_by_date.since(seconds_to_advance)
end
end Использует Date для обеспечения точных вычислений Time для лет, месяцев и дней в соответствии с пролептическим григорианским календарём. Параметр options принимает хэш с любыми из этих ключей: :years, :months, :weeks, :days, :hours, :minutes, :seconds.
Time.new(2015, 8, 1, 14, 35, 0).advance(seconds: 1) # => 2015-08-01 14:35:01 -0700 Time.new(2015, 8, 1, 14, 35, 0).advance(minutes: 1) # => 2015-08-01 14:36:00 -0700 Time.new(2015, 8, 1, 14, 35, 0).advance(hours: 1) # => 2015-08-01 15:35:00 -0700 Time.new(2015, 8, 1, 14, 35, 0).advance(days: 1) # => 2015-08-02 14:35:00 -0700 Time.new(2015, 8, 1, 14, 35, 0).advance(weeks: 1) # => 2015-08-08 14:35:00 -0700
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 222 def all_day beginning_of_day..end_of_day end
Возвращает Range, представляющий весь день текущего времени.
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 161 def beginning_of_day #(self - seconds_since_midnight).change(usec: 0) change(:hour => 0) end
Возвращает новый Time, представляющий начало дня (0:00)
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 191 def beginning_of_hour change(:min => 0) end
Возвращает новый Time, представляющий начало часа (x:00)
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 207 def beginning_of_minute change(:sec => 0) end
Возвращает новый Time, представляющий начало минуты (x:xx:00)
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 85
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)
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
if utc?
::Time.utc(new_year, new_month, new_day, new_hour, new_min, new_sec, new_usec)
elsif zone
::Time.local(new_year, new_month, new_day, new_hour, new_min, new_sec, new_usec)
else
raise ArgumentError, 'argument out of range' if new_usec >= 1000000
::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec + (new_usec.to_r / 1000000), utc_offset)
end
end Возвращает новый Time, в котором один или несколько элементов были изменены в соответствии с параметром options. Параметры времени (:hour, :min, :sec, :usec, :nsec) сбрасываются каскадно, поэтому, если передан только час, то минута, секунда, микросекунда и наносекунда устанавливаются в 0. Если переданы час и минута, то секунда, микросекунда и наносекунда устанавливаются в 0. Параметр options принимает хэш с любыми из этих ключей: :year, :month, :day, :hour, :min, :sec, :usec :nsec. Укажите либо :usec, либо :nsec, но не оба.
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)
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 258
def compare_with_coercion(other)
# we're avoiding Time#to_datetime cause it's expensive
if other.class == Time
compare_without_coercion(other)
elsif other.is_a?(Time)
compare_without_coercion(other.to_time)
else
to_datetime <=> other
end
end Добавляет дополнительное поведение к Time#<=>, чтобы экземпляры DateTime и ActiveSupport::TimeWithZone можно было сравнивать хронологически с Time
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 180
def end_of_day
change(
:hour => 23,
:min => 59,
:sec => 59,
:usec => Rational(999999999, 1000)
)
end Возвращает новый Time, представляющий конец дня, 23:59:59.999999 (.999999999 в ruby1.9)
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 197
def end_of_hour
change(
:min => 59,
:sec => 59,
:usec => Rational(999999999, 1000)
)
end Возвращает новое значение Time, представляющее конец часа, x:59:59.999999 (.999999999 в ruby1.9)
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 213
def end_of_minute
change(
:sec => 59,
:usec => Rational(999999999, 1000)
)
end Возвращает новое значение Time, представляющее конец минуты, x:xx:59.999999 (.999999999 в ruby1.9)
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 273 def eql_with_coercion(other) # if other is an ActiveSupport::TimeWithZone, coerce a Time instance from it so we can do eql? comparison other = other.comparable_time if other.respond_to?(:comparable_time) eql_without_coercion(other) end
Добавляет дополнительное поведение к #eql?, чтобы экземпляры ActiveSupport::TimeWithZone могли быть eql? эквивалентному значению Time
# File activesupport/lib/active_support/core_ext/time/conversions.rb, line 62 def formatted_offset(colon = true, alternate_utc_string = nil) utc? && alternate_utc_string || ActiveSupport::TimeZone.seconds_to_utc_offset(utc_offset, colon) end
Возвращает смещение UTC в формате +HH:MM.
Time.local(2000).formatted_offset # => "-06:00" Time.local(2000).formatted_offset(false) # => "-0600"
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 170 def middle_of_day change(:hour => 12) end
Возвращает новое значение Time, представляющее середину дня (12:00)
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 249 def minus_with_coercion(other) other = other.comparable_time if other.respond_to?(:comparable_time) other.is_a?(DateTime) ? to_f - other.to_f : minus_without_coercion(other) end
Time#- также можно использовать для определения количества секунд между двумя экземплярами Time. Мы добавляем дополнительное поведение, чтобы экземпляры ActiveSupport::TimeWithZone были приведены к типам, которые Time#- распознает
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 69 def sec_fraction subsec end
Возвращает дробную часть секунды как Rational
Time.new(2012, 8, 29, 0, 0, 0.5).sec_fraction # => (1/2)
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 53 def seconds_since_midnight to_i - change(:hour => 0).to_i + (usec / 1.0e+6) end
Секунды с полуночи: Time.now.seconds_since_midnight
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 62 def seconds_until_end_of_day end_of_day.to_i - to_i end
Возвращает количество секунд до 23:59:59.
Time.new(2012, 8, 29, 0, 0, 0).seconds_until_end_of_day # => 86399 Time.new(2012, 8, 29, 12, 34, 56).seconds_until_end_of_day # => 41103 Time.new(2012, 8, 29, 23, 59, 59).seconds_until_end_of_day # => 0
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 153 def since(seconds) self + seconds rescue to_datetime.since(seconds) end
Возвращает новое значение Time, представляющее время через заданное количество секунд после времени экземпляра.
# File activesupport/lib/active_support/core_ext/time/conversions.rb, line 48
def to_formatted_s(format = :default)
if formatter = DATE_FORMATS[format]
formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
else
to_default_s
end
end Преобразует в строку с форматом. Смотрите DATE_FORMATS для встроенных форматов.
Этот метод алиасирован к to_s.
time = Time.now # => Thu Jan 18 06:10:17 CST 2007 time.to_formatted_s(:time) # => "06:10" time.to_s(:time) # => "06:10" time.to_formatted_s(:db) # => "2007-01-18 06:10:17" time.to_formatted_s(:number) # => "20070118061017" time.to_formatted_s(:short) # => "18 Jan 06:10" time.to_formatted_s(:long) # => "January 18, 2007 06:10" time.to_formatted_s(:long_ordinal) # => "January 18th, 2007 06:10" time.to_formatted_s(:rfc822) # => "Thu, 18 Jan 2007 06:10:17 -0600" time.to_formatted_s(:iso8601) # => "2007-01-18T06:10:17-06:00"
Добавление собственных форматов времени в to_formatted_s
Вы можете добавить свои собственные форматы в хэш Time::DATE_FORMATS. Используйте имя формата в качестве ключа хэша и строку strftime или экземпляр Proc, принимающий время, в качестве значения.
# config/initializers/time_formats.rb
Time::DATE_FORMATS[:month_and_year] = '%B %Y'
Time::DATE_FORMATS[:short_ordinal] = ->(time) { time.strftime("%B #{time.day.ordinalize}") }
# File activesupport/lib/active_support/core_ext/time/compatibility.rb, line 11 def to_time preserve_timezone ? self : getlocal end
Возвращает либо self, либо время в местном часовом поясе системы, в зависимости от настройки ActiveSupport.to_time_preserves_timezone.
© 2004–2018 David Heinemeier Hansson
Licensed under the MIT License.