класс ActiveSupport::TimeWithZone
Класс, похожий на Time, который может представлять время в любой часовой зоне. Необходим, потому что стандартные экземпляры Ruby Time ограничены UTC и системной ENV['TZ'] зоной.
Вам, скорее всего, не придётся создавать экземпляр TimeWithZone напрямую с помощью new. Вместо этого используйте методы local, parse, at и now для экземпляров TimeZone, а также in_time_zone для экземпляров Time и DateTime.
Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
Time.zone.local(2007, 2, 10, 15, 30, 45) # => Sat, 10 Feb 2007 15:30:45 EST -05:00
Time.zone.parse('2007-02-10 15:30:45') # => Sat, 10 Feb 2007 15:30:45 EST -05:00
Time.zone.at(1171139445) # => Sat, 10 Feb 2007 15:30:45 EST -05:00
Time.zone.now # => Sun, 18 May 2008 13:07:55 EDT -04:00
Time.utc(2007, 2, 10, 20, 30, 45).in_time_zone # => Sat, 10 Feb 2007 15:30:45 EST -05:00
См. Time и TimeZone для более подробной документации по этим методам.
Экземпляры TimeWithZone реализуют тот же API, что и экземпляры Ruby Time, так что экземпляры Time и TimeWithZone взаимозаменяемы.
t = Time.zone.now # => Sun, 18 May 2008 13:27:25 EDT -04:00 t.hour # => 13 t.dst? # => true t.utc_offset # => -14400 t.zone # => "EDT" t.to_s(:rfc822) # => "Sun, 18 May 2008 13:27:25 -0400" t + 1.day # => Mon, 19 May 2008 13:27:25 EDT -04:00 t.beginning_of_year # => Tue, 01 Jan 2008 00:00:00 EST -05:00 t > Time.utc(1999) # => true t.is_a?(Time) # => true t.is_a?(ActiveSupport::TimeWithZone) # => true
Константы
- PRECISIONS
Атрибуты
Публичные методы класса
# File activesupport/lib/active_support/time_with_zone.rb, line 42 def self.name "Time" end
Отчёт о имени класса как 'Time', чтобы обойти проверку типа.
# File activesupport/lib/active_support/time_with_zone.rb, line 52 def initialize(utc_time, time_zone, local_time = nil, period = nil) @utc = utc_time ? transfer_time_values_to_utc_constructor(utc_time) : nil @time_zone, @time = time_zone, local_time @period = @utc ? period : get_period_and_ensure_valid_local_time(period) end
Публичные методы экземпляра
# File activesupport/lib/active_support/time_with_zone.rb, line 276
def +(other)
if duration_of_variable_length?(other)
method_missing(:+, other)
else
result = utc.acts_like?(:date) ? utc.since(other) : utc + other rescue utc.since(other)
result.in_time_zone(time_zone)
end
end Добавляет интервал времени к текущему времени объекта и возвращает это значение в виде нового объекта TimeWithZone.
Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)' now = Time.zone.now # => Sun, 02 Nov 2014 01:26:28 EDT -04:00 now + 1000 # => Sun, 02 Nov 2014 01:43:08 EDT -04:00
Если мы добавляем Duration переменной длины (т.е. годы, месяцы, дни), двигаемся вперед от time, иначе двигаемся вперед от utc для точности при переходе через границы летнего времени.
Например, время + 24.hours продвинется ровно на 24 часа, в то время как время + 1.day продвинется на 23-25 часов в зависимости от дня.
now + 24.hours # => Mon, 03 Nov 2014 00:26:28 EST -05:00 now + 1.day # => Mon, 03 Nov 2014 01:26:28 EST -05:00
# File activesupport/lib/active_support/time_with_zone.rb, line 303
def -(other)
if other.acts_like?(:time)
to_time - other.to_time
elsif duration_of_variable_length?(other)
method_missing(:-, other)
else
result = utc.acts_like?(:date) ? utc.ago(other) : utc - other rescue utc.ago(other)
result.in_time_zone(time_zone)
end
end Возвращает новый объект TimeWithZone, который представляет собой разницу между текущим временем объекта и временем other.
Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)' now = Time.zone.now # => Mon, 03 Nov 2014 00:26:28 EST -05:00 now - 1000 # => Mon, 03 Nov 2014 00:09:48 EST -05:00
При вычитании Duration переменной длины (т.е. годы, месяцы, дни), двигаемся назад от time, иначе двигаемся назад от utc для точности при переходе через границы летнего времени.
Например, время - 24.hours вычтет ровно 24 часа, в то время как время - 1.day вычтет 23-25 часов в зависимости от дня.
now - 24.hours # => Sun, 02 Nov 2014 01:26:28 EDT -04:00 now - 1.day # => Sun, 02 Nov 2014 00:26:28 EDT -04:00
# File activesupport/lib/active_support/time_with_zone.rb, line 225 def <=>(other) utc <=> other end
Используйте время в UTC для сравнений.
# File activesupport/lib/active_support/time_with_zone.rb, line 464 def acts_like_time? true end
Так что self acts_like?(:time).
# File activesupport/lib/active_support/time_with_zone.rb, line 392
def advance(options)
# If we're advancing a value of variable length (i.e., years, weeks, months, days), advance from #time,
# otherwise advance from #utc, for accuracy when moving across DST boundaries
if options.values_at(:years, :weeks, :months, :days).any?
method_missing(:advance, options)
else
utc.advance(options).in_time_zone(time_zone)
end
end Использует Date для обеспечения точных вычислений Time для лет, месяцев и дней в соответствии с пролептическим григорианским календарем. Результат возвращается как новый объект TimeWithZone.
Параметр options принимает хэш с любыми из этих ключей: :years, :months, :weeks, :days, :hours, :minutes, :seconds.
При продвижении на значение переменной длины (т.е. годы, недели, месяцы, дни), двигайтесь вперед от time, иначе двигайтесь вперед от utc для точности при переходе через границы летнего времени.
Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)' now = Time.zone.now # => Sun, 02 Nov 2014 01:26:28 EDT -04:00 now.advance(seconds: 1) # => Sun, 02 Nov 2014 01:26:29 EDT -04:00 now.advance(minutes: 1) # => Sun, 02 Nov 2014 01:27:28 EDT -04:00 now.advance(hours: 1) # => Sun, 02 Nov 2014 01:26:28 EST -05:00 now.advance(days: 1) # => Mon, 03 Nov 2014 01:26:28 EST -05:00 now.advance(weeks: 1) # => Sun, 09 Nov 2014 01:26:28 EST -05:00 now.advance(months: 1) # => Tue, 02 Dec 2014 01:26:28 EST -05:00 now.advance(years: 1) # => Mon, 02 Nov 2015 01:26:28 EST -05:00
# File activesupport/lib/active_support/time_with_zone.rb, line 331 def ago(other) since(-other) end
Вычитает интервал времени из текущего времени объекта и возвращает результат в виде нового объекта TimeWithZone.
Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)' now = Time.zone.now # => Mon, 03 Nov 2014 00:26:28 EST -05:00 now.ago(1000) # => Mon, 03 Nov 2014 00:09:48 EST -05:00
Если мы вычитаем Duration переменной длины (т.е. годы, месяцы, дни), двигаемся назад от time, иначе двигаемся назад от utc для точности при переходе через границы летнего времени.
Например, time.ago(24.hours) переместится назад ровно на 24 часа, в то время как time.ago(1.day) переместится назад на 23-25 часов в зависимости от дня.
now.ago(24.hours) # => Sun, 02 Nov 2014 01:26:28 EDT -04:00 now.ago(1.day) # => Sun, 02 Nov 2014 00:26:28 EDT -04:00
# File activesupport/lib/active_support/time_with_zone.rb, line 167
def as_json(options = nil)
if ActiveSupport::JSON::Encoding.use_standard_json_time_format
xmlschema(ActiveSupport::JSON::Encoding.time_precision)
else
%(#{time.strftime("%Y/%m/%d %H:%M:%S")} #{formatted_offset(false)})
end
end Приводит время к строке для кодирования JSON. Формат по умолчанию - ISO 8601. Вы можете получить стиль %Y/%m/%d %H:%M:%S +offset, установив ActiveSupport::JSON::Encoding.use_standard_json_time_format в false.
# With ActiveSupport::JSON::Encoding.use_standard_json_time_format = true
Time.utc(2005,2,1,15,15,10).in_time_zone("Hawaii").to_json
# => "2005-02-01T05:15:10.000-10:00"
# With ActiveSupport::JSON::Encoding.use_standard_json_time_format = false
Time.utc(2005,2,1,15,15,10).in_time_zone("Hawaii").to_json
# => "2005/02/01 05:15:10 -1000"
# File activesupport/lib/active_support/time_with_zone.rb, line 231 def between?(min, max) utc.between?(min, max) end
Возвращает true, если текущее время объекта находится в указанном диапазоне времени min и max.
# File activesupport/lib/active_support/time_with_zone.rb, line 475 def blank? false end
Экземпляр ActiveSupport::TimeWithZone никогда не является пустым
# File activesupport/lib/active_support/time_with_zone.rb, line 352
def change(options)
if options[:zone] && options[:offset]
raise ArgumentError, "Can't change both :offset and :zone at the same time: #{options.inspect}"
end
new_time = time.change(options)
if options[:zone]
new_zone = ::Time.find_zone(options[:zone])
elsif options[:offset]
new_zone = ::Time.find_zone(new_time.utc_offset)
end
new_zone ||= time_zone
periods = new_zone.periods_for_local(new_time)
self.class.new(nil, new_zone, new_time, periods.include?(period) ? period : nil)
end Возвращает новый ActiveSupport::TimeWithZone, в котором один или несколько элементов были изменены в соответствии с параметром options. Параметры времени (:hour, :min, :sec, :usec, :nsec) сбрасываются каскадно, поэтому, если передается только час, то минута, секунда, микросекунда и наносекунда устанавливаются в 0. Если передаются час и минута, то секунда, микросекунда и наносекунда устанавливаются в 0. Параметр options принимает хэш с любыми из этих ключей: :year, :month, :day, :hour, :min, :sec, :usec, :nsec, :offset, :zone. Передайте либо :usec, либо :nsec, но не оба. Аналогично, передайте либо :zone, либо :offset, но не оба.
t = Time.zone.now # => Fri, 14 Apr 2017 11:45:15 EST -05:00 t.change(year: 2020) # => Tue, 14 Apr 2020 11:45:15 EST -05:00 t.change(hour: 12) # => Fri, 14 Apr 2017 12:00:00 EST -05:00 t.change(min: 30) # => Fri, 14 Apr 2017 11:30:00 EST -05:00 t.change(offset: "-10:00") # => Fri, 14 Apr 2017 11:45:15 HST -10:00 t.change(zone: "Hawaii") # => Fri, 14 Apr 2017 11:45:15 HST -10:00
# File activesupport/lib/active_support/time_with_zone.rb, line 95 def dst? period.dst? end
Возвращает true, если текущее время находится в летнее время для указанного часового пояса.
Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
Time.zone.parse("2012-5-30").dst? # => true
Time.zone.parse("2012-11-30").dst? # => false
# File activesupport/lib/active_support/time_with_zone.rb, line 252 def eql?(other) other.eql?(utc) end
Возвращает true, если other равен текущему объекту.
# File activesupport/lib/active_support/time_with_zone.rb, line 126 def formatted_offset(colon = true, alternate_utc_string = nil) utc? && alternate_utc_string || TimeZone.seconds_to_utc_offset(utc_offset, colon) end
Возвращает отформатированную строку смещения от UTC или альтернативную строку, если часовой пояс уже UTC.
Time.zone = 'Eastern Time (US & Canada)' # => "Eastern Time (US & Canada)" Time.zone.now.formatted_offset(true) # => "-05:00" Time.zone.now.formatted_offset(false) # => "-0500" Time.zone = 'UTC' # => "UTC" Time.zone.now.formatted_offset(true, "0") # => "0"
# File activesupport/lib/active_support/time_with_zone.rb, line 479 def freeze # preload instance variables before freezing period; utc; time; to_datetime; to_time super end
# File activesupport/lib/active_support/time_with_zone.rb, line 247 def future? utc.future? end
Возвращает true, если текущее время объекта находится в будущем.
# File activesupport/lib/active_support/time_with_zone.rb, line 256 def hash utc.hash end
# File activesupport/lib/active_support/time_with_zone.rb, line 188 def httpdate utc.httpdate end
Возвращает строку с датой и временем объекта в формате, используемом в HTTP-запросах.
Time.zone.now.httpdate # => "Tue, 01 Jan 2013 04:39:43 GMT"
# File activesupport/lib/active_support/time_with_zone.rb, line 78 def in_time_zone(new_zone = ::Time.zone) return self if time_zone == new_zone utc.in_time_zone(new_zone) end
Возвращает одновременное время в Time.zone, или в указанной зоне.
# File activesupport/lib/active_support/time_with_zone.rb, line 141
def inspect
"#{time.strftime('%a, %d %b %Y %H:%M:%S')} #{zone} #{formatted_offset}"
end Возвращает строку с датой, временем, зоной и смещением от UTC объекта.
Time.zone.now.inspect # => "Thu, 04 Dec 2014 11:00:25 EST -05:00"
# File activesupport/lib/active_support/time_with_zone.rb, line 469 def is_a?(klass) klass == ::Time || super end
Предположим, что мы – Time, чтобы обойти проверку типов.
# File activesupport/lib/active_support/time_with_zone.rb, line 84 def localtime(utc_offset = nil) utc.getlocal(utc_offset) end
Возвращает экземпляр Time одновременного времени в часовом поясе системы.
# File activesupport/lib/active_support/time_with_zone.rb, line 485 def marshal_dump [utc, time_zone.name, time] end
# File activesupport/lib/active_support/time_with_zone.rb, line 489 def marshal_load(variables) initialize(variables[0].utc, ::Time.find_zone(variables[1]), variables[2].utc) end
# File activesupport/lib/active_support/time_with_zone.rb, line 510 def method_missing(sym, *args, &block) wrap_with_time_zone time.__send__(sym, *args, &block) rescue NoMethodError => e raise e, e.message.sub(time.inspect, inspect), e.backtrace end
Отправляет отсутствующий метод экземпляру time, и оборачивает результат в новый TimeWithZone с существующим time_zone.
# File activesupport/lib/active_support/time_with_zone.rb, line 236 def past? utc.past? end
Возвращает true, если текущее время объекта находится в прошлом.
# File activesupport/lib/active_support/time_with_zone.rb, line 73 def period @period ||= time_zone.period_for_utc(@utc) end
Возвращает базовый TZInfo::TimezonePeriod.
# File activesupport/lib/active_support/time_with_zone.rb, line 495 def respond_to?(sym, include_priv = false) # ensure that we're not going to throw and rescue from NoMethodError in method_missing which is slow return false if sym.to_sym == :to_str super end
respond_to_missing? не вызывается в некоторых случаях, например, при преобразовании типов с помощью Kernel#String
# File activesupport/lib/active_support/time_with_zone.rb, line 503 def respond_to_missing?(sym, include_priv) return false if sym.to_sym == :acts_like_date? time.respond_to?(sym, include_priv) end
Убедиться, что прокси-класс отвечает на все методы, к которым отвечает базовый экземпляр времени.
# File activesupport/lib/active_support/time_with_zone.rb, line 196 def rfc2822 to_s(:rfc822) end
Возвращает строку с датой и временем объекта в формате стандарта RFC 2822.
Time.zone.now.rfc2822 # => "Tue, 01 Jan 2013 04:51:39 +0000"
# File activesupport/lib/active_support/time_with_zone.rb, line 219
def strftime(format)
format = format.gsub(/((?:\A|[^%])(?:%%)*)%Z/, "\\1#{zone}")
getlocal(utc_offset).strftime(format)
end Заменяет директиву %Z на +zone перед передачей в Time#strftime, чтобы информация о часовом поясе была корректной.
# File activesupport/lib/active_support/time_with_zone.rb, line 59 def time @time ||= period.to_local(@utc) end
Возвращает экземпляр Time, который представляет время в time_zone.
# File activesupport/lib/active_support/time_with_zone.rb, line 415 def to_a [time.sec, time.min, time.hour, time.day, time.mon, time.year, time.wday, time.yday, dst?, zone] end
Возвращает массив Array частей Time в последовательности [секунды, минуты, часы, день, месяц, год, день недели, день года, DST?, зона].
now = Time.zone.now # => Tue, 18 Aug 2015 02:29:27 UTC +00:00 now.to_a # => [27, 29, 2, 18, 8, 2015, 2, 230, false, "UTC"]
# File activesupport/lib/active_support/time_with_zone.rb, line 448 def to_datetime @to_datetime ||= utc.to_datetime.new_offset(Rational(utc_offset, 86_400)) end
Возвращает экземпляр DateTime со смещением часового пояса от UTC.
Time.zone.now.to_datetime # => Tue, 18 Aug 2015 02:32:20 +0000
Time.current.in_time_zone('Hawaii').to_datetime # => Mon, 17 Aug 2015 16:32:20 -1000
# File activesupport/lib/active_support/time_with_zone.rb, line 423 def to_f utc.to_f end
Возвращает дату и время объекта как число с плавающей точкой, представляющее количество секунд с эпохи (1 января 1970 года 00:00 UTC).
Time.zone.now.to_f # => 1417709320.285418
# File activesupport/lib/active_support/time_with_zone.rb, line 431 def to_i utc.to_i end
Возвращает дату и время объекта как целое число секунд с момента эпохи (1 января 1970 года 00:00 UTC).
Time.zone.now.to_i # => 1417709320
# File activesupport/lib/active_support/time_with_zone.rb, line 440 def to_r utc.to_r end
Возвращает дату и время объекта как рациональное число секунд с момента эпохи (1 января 1970 года 00:00 UTC).
Time.zone.now.to_r # => (708854548642709/500000)
# File activesupport/lib/active_support/time_with_zone.rb, line 206
def to_s(format = :default)
if format == :db
utc.to_s(format)
elsif formatter = ::Time::DATE_FORMATS[format]
formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
else
"#{time.strftime("%Y-%m-%d %H:%M:%S")} #{formatted_offset(false, 'UTC')}" # mimicking Ruby Time#to_s format
end
end Возвращает строку даты и времени объекта. Принимает необязательный format:
-
:default- значение по умолчанию, имитирует формат Ruby Time#to_s. -
:db- формат вывода времени в UTC :db time. См. Time#to_formatted_s(:db). -
Любой ключ в
Time::DATE_FORMATSможет быть использован. См. active_support/core_ext/time/conversions.rb.
# File activesupport/lib/active_support/time_with_zone.rb, line 455
def to_time
if preserve_timezone
@to_time_with_instance_offset ||= getlocal(utc_offset)
else
@to_time_with_system_offset ||= getlocal
end
end Возвращает экземпляр Time, либо с тем же смещением UTC, что и self, либо в часовом поясе системы в зависимости от настроек ActiveSupport.to_time_preserves_timezone.
# File activesupport/lib/active_support/time_with_zone.rb, line 242 def today? time.today? end
Возвращает true, если текущее время объекта попадает в текущий день.
# File activesupport/lib/active_support/time_with_zone.rb, line 64 def utc @utc ||= period.to_utc(@time) end
Возвращает экземпляр Time с одновременным временем в часовом поясе UTC.
# File activesupport/lib/active_support/time_with_zone.rb, line 106 def utc? period.offset.abbreviation == :UTC || period.offset.abbreviation == :UCT end
Возвращает true, если текущий часовой пояс установлен на UTC.
Time.zone = 'UTC' # => 'UTC' Time.zone.now.utc? # => true Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)' Time.zone.now.utc? # => false
# File activesupport/lib/active_support/time_with_zone.rb, line 112 def utc_offset period.utc_total_offset end
Возвращает смещение от текущего времени до UTC времени в секундах.
# File activesupport/lib/active_support/time_with_zone.rb, line 149
def xmlschema(fraction_digits = 0)
"#{time.strftime(PRECISIONS[fraction_digits.to_i])}#{formatted_offset(true, 'Z'.freeze)}"
end Возвращает строку даты и времени объекта в формате ISO 8601.
Time.zone.now.xmlschema # => "2014-12-04T11:02:37-05:00"
# File activesupport/lib/active_support/time_with_zone.rb, line 134 def zone period.zone_identifier.to_s end
Возвращает сокращение часового пояса.
Time.zone = 'Eastern Time (US & Canada)' # => "Eastern Time (US & Canada)" Time.zone.now.zone # => "EST"
© 2004–2018 David Heinemeier Hansson
Licensed under the MIT License.