File: //usr/local/rvm/gems/ruby-2.5.9/gems/tzinfo-2.0.4/lib/tzinfo/time_with_offset.rb
# encoding: UTF-8
# frozen_string_literal: true
module TZInfo
# A subclass of `Time` used to represent local times. {TimeWithOffset} holds a
# reference to the related {TimezoneOffset} and overrides various methods to
# return results appropriate for the {TimezoneOffset}. Certain operations will
# clear the associated {TimezoneOffset} (if the {TimezoneOffset} would not
# necessarily be valid for the result). Once the {TimezoneOffset} has been
# cleared, {TimeWithOffset} behaves identically to `Time`.
#
# Arithmetic performed on {TimeWithOffset} instances is _not_ time zone-aware.
# Regardless of whether transitions in the time zone are crossed, results of
# arithmetic operations will always maintain the same offset from UTC
# (`utc_offset`). The associated {TimezoneOffset} will aways be cleared.
class TimeWithOffset < Time
include WithOffset
# @return [TimezoneOffset] the {TimezoneOffset} associated with this
# instance.
attr_reader :timezone_offset
# Marks this {TimeWithOffset} as a local time with the UTC offset of a given
# {TimezoneOffset} and sets the associated {TimezoneOffset}.
#
# @param timezone_offset [TimezoneOffset] the {TimezoneOffset} to use to set
# the offset of this {TimeWithOffset}.
# @return [TimeWithOffset] `self`.
# @raise [ArgumentError] if `timezone_offset` is `nil`.
def set_timezone_offset(timezone_offset)
raise ArgumentError, 'timezone_offset must be specified' unless timezone_offset
localtime(timezone_offset.observed_utc_offset)
@timezone_offset = timezone_offset
self
end
# An overridden version of `Time#dst?` that, if there is an associated
# {TimezoneOffset}, returns the result of calling {TimezoneOffset#dst? dst?}
# on that offset.
#
# @return [Boolean] `true` if daylight savings time is being observed,
# otherwise `false`.
def dst?
to = timezone_offset
to ? to.dst? : super
end
alias isdst dst?
# An overridden version of `Time#getlocal` that clears the associated
# {TimezoneOffset} if the base implementation of `getlocal` returns a
# {TimeWithOffset}.
#
# @return [Time] a representation of the {TimeWithOffset} using either the
# local time zone or the given offset.
def getlocal(*args)
# JRuby < 9.3 returns a Time in all cases.
# JRuby >= 9.3 returns a Time when called with no arguments and a
# TimeWithOffset with a timezone_offset assigned when called with an
# offset argument.
result = super
result.clear_timezone_offset if result.kind_of?(TimeWithOffset)
result
end
# An overridden version of `Time#gmtime` that clears the associated
# {TimezoneOffset}.
#
# @return [TimeWithOffset] `self`.
def gmtime
super
@timezone_offset = nil
self
end
# An overridden version of `Time#localtime` that clears the associated
# {TimezoneOffset}.
#
# @return [TimeWithOffset] `self`.
def localtime(*args)
super
@timezone_offset = nil
self
end
# An overridden version of `Time#round` that, if there is an associated
# {TimezoneOffset}, returns a {TimeWithOffset} preserving that offset.
#
# @return [Time] the rounded time.
def round(ndigits = 0)
if_timezone_offset(super) {|o,t| self.class.at(t.to_i, t.subsec * 1_000_000).set_timezone_offset(o) }
end
# An overridden version of `Time#to_a`. The `isdst` (index 8) and `zone`
# (index 9) elements of the array are set according to the associated
# {TimezoneOffset}.
#
# @return [Array] an `Array` representation of the {TimeWithOffset}.
def to_a
if_timezone_offset(super) do |o,a|
a[8] = o.dst?
a[9] = o.abbreviation
a
end
end
# An overridden version of `Time#utc` that clears the associated
# {TimezoneOffset}.
#
# @return [TimeWithOffset] `self`.
def utc
super
@timezone_offset = nil
self
end
# An overridden version of `Time#zone` that, if there is an associated
# {TimezoneOffset}, returns the {TimezoneOffset#abbreviation abbreviation}
# of that offset.
#
# @return [String] the {TimezoneOffset#abbreviation abbreviation} of the
# associated {TimezoneOffset}, or the result from `Time#zone` if there is
# no such offset.
def zone
to = timezone_offset
to ? to.abbreviation : super
end
# An overridden version of `Time#to_datetime` that, if there is an
# associated {TimezoneOffset}, returns a {DateTimeWithOffset} with that
# offset.
#
# @return [DateTime] if there is an associated {TimezoneOffset}, a
# {DateTimeWithOffset} representation of this {TimeWithOffset}, otherwise
# a `Time` representation.
def to_datetime
if_timezone_offset(super) do |o,dt|
offset = dt.offset
result = DateTimeWithOffset.jd(dt.jd + dt.day_fraction - offset)
result = result.new_offset(offset) unless offset == 0
result.set_timezone_offset(o)
end
end
protected
# Clears the associated {TimezoneOffset}.
#
# @return [TimeWithOffset] `self`.
def clear_timezone_offset
@timezone_offset = nil
self
end
end
end