class ActiveSupport::TimeZone

Experimental RBS support (using type sampling data from the type_fusion project).

# sig/active_support/values/time_zone.rbs

class ActiveSupport::TimeZone
  def []: (ActiveSupport::TimeZone arg) -> untyped
end

Time.zone.now # => Sun, 18 May 2008 14:30:44 EDT -04:00
Time.zone.name # => “Eastern Time (US & Canada)”
Time.zone # => #<ActiveSupport::TimeZone:0x514834…>
end
config.time_zone = ‘Eastern Time (US & Canada)’
class Application < Rails::Application
# application.rb:
access this TimeZone object via Time.zone:
If you set config.time_zone in the Rails Application, you can
parse, at, and now methods.
* Create ActiveSupport::TimeWithZone instances via TimeZone’s local,
* Lazily load TZInfo::Timezone instances only when they’re needed.
(e.g., “Eastern Time (US & Canada)” instead of “America/New_York”).
* Retrieve and display zones with a friendlier name
zones.
* Limit the set of zones provided by TZInfo to a meaningful subset of 134
It allows us to do the following:
The TimeZone class serves as a wrapper around TZInfo::Timezone instances.

def <=>(zone)

their offsets, and then by name.
Compare this time zone to the parameter. The two are compared first on
def <=>(zone)
  return unless zone.respond_to? :utc_offset
  result = (utc_offset <=> zone.utc_offset)
  result = (name <=> zone.name) if result == 0
  result
end

def =~(re)

if a match is found.
Compare #name and TZInfo identifier to a supplied regexp, returning +true+
def =~(re)
  re === name || re === MAPPING[name]
end

def [](arg)

Experimental RBS support (using type sampling data from the type_fusion project).

def []: (ActiveSupport::TimeZone arg) -> untyped

This signature was generated using 1 sample from 1 application.

Returns +nil+ if no such time zone is known to the system.
timezone to find. (The first one with that offset will be returned.)
numeric value it is either the hour offset, or the second offset, of the
is interpreted to mean the name of the timezone to locate. If it is a
Locate a specific time zone object. If the argument is a string, it
def [](arg)
  case arg
  when self
    arg
  when String
    begin
      @lazy_zones_map[arg] ||= create(arg)
    rescue TZInfo::InvalidTimezoneIdentifier
      nil
    end
  when TZInfo::Timezone
    @lazy_zones_map[arg.name] ||= create(arg.name, nil, arg)
  when Numeric, ActiveSupport::Duration
    arg *= 3600 if arg.abs <= 13
    all.find { |z| z.utc_offset == arg.to_i }
  else
    raise ArgumentError, "invalid argument to TimeZone[]: #{arg.inspect}"
  end
end

def all

for users to find their own time zone.
TimeZone objects per time zone, in many cases, to make it easier
Returns an array of all TimeZone objects. There are multiple
def all
  @zones ||= zones_map.values.sort
end

def at(*args)

Time.at(946684800, 123456.789).nsec # => 123456789
Time.zone = 'Hawaii' # => "Hawaii"

A second argument can be supplied to specify sub-second precision.

Time.zone.at(946684800.0) # => Fri, 31 Dec 1999 14:00:00 HST -10:00
Time.utc(2000).to_f # => 946684800.0
Time.zone = 'Hawaii' # => "Hawaii"

of +self+ from number of seconds since the Unix epoch.
Method for creating new ActiveSupport::TimeWithZone instance in time zone
def at(*args)
  Time.at(*args).utc.in_time_zone(self)
end

def clear # :nodoc:

:nodoc:
def clear # :nodoc:
  @lazy_zones_map = Concurrent::Map.new
  @country_zones  = Concurrent::Map.new
  @zones = nil
  @zones_map = nil
end

def country_zones(country_code)

for time zones in the country specified by its ISO 3166-1 Alpha2 code.
A convenience method for returning a collection of TimeZone objects
def country_zones(country_code)
  code = country_code.to_s.upcase
  @country_zones[code] ||= load_country_zones(code)
end

def encode_with(coder) # :nodoc:

:nodoc:
def encode_with(coder) # :nodoc:
  coder.tag = "!ruby/object:#{self.class}"
  coder.map = { "name" => tzinfo.name }
end

def find_tzinfo(name)

def find_tzinfo(name)
  TZInfo::Timezone.get(MAPPING[name] || name)
end

def formatted_offset(colon = true, alternate_utc_string = nil)

zone.formatted_offset(false) # => "-0600"
zone.formatted_offset # => "-06:00"
zone = ActiveSupport::TimeZone['Central Time (US & Canada)']

string if the time zone is already UTC.
Returns a formatted string of the offset from UTC, or an alternative
def formatted_offset(colon = true, alternate_utc_string = nil)
  utc_offset == 0 && alternate_utc_string || self.class.seconds_to_utc_offset(utc_offset, colon)
end

def init_with(coder) # :nodoc:

:nodoc:
def init_with(coder) # :nodoc:
  initialize(coder["name"])
end

def initialize(name, utc_offset = nil, tzinfo = nil)

that Ruby uses to represent time zone offsets (see Time#utc_offset).
(GMT). Seconds were chosen as the offset unit because that is the unit
offset is the number of seconds that this time zone is offset from UTC
Create a new TimeZone object with the given name and offset. The
def initialize(name, utc_offset = nil, tzinfo = nil)
  @name = name
  @utc_offset = utc_offset
  @tzinfo = tzinfo || TimeZone.find_tzinfo(name)
end

def iso8601(str)

which usually returns +nil+ when given an invalid date string.
If the string is invalid then an +ArgumentError+ will be raised unlike +parse+

Time.zone.iso8601('1999-12-31') # => Fri, 31 Dec 1999 00:00:00 HST -10:00
Time.zone = 'Hawaii' # => "Hawaii"

If the time components are missing then they will be set to zero.

Time.zone.iso8601('1999-12-31T14:00:00') # => Fri, 31 Dec 1999 14:00:00 HST -10:00
Time.zone = 'Hawaii' # => "Hawaii"

of +self+ from an ISO 8601 string.
Method for creating new ActiveSupport::TimeWithZone instance in time zone
def iso8601(str)
  # Historically `Date._iso8601(nil)` returns `{}`, but in the `date` gem versions `3.2.1`, `3.1.2`, `3.0.2`,
  # and `2.0.1`, `Date._iso8601(nil)` raises `TypeError` https://github.com/ruby/date/issues/39
  # Future `date` releases are expected to revert back to the original behavior.
  raise ArgumentError, "invalid date" if str.nil?
  parts = Date._iso8601(str)
  year = parts.fetch(:year)
  if parts.key?(:yday)
    ordinal_date = Date.ordinal(year, parts.fetch(:yday))
    month = ordinal_date.month
    day = ordinal_date.day
  else
    month = parts.fetch(:mon)
    day = parts.fetch(:mday)
  end
  time = Time.new(
    year,
    month,
    day,
    parts.fetch(:hour, 0),
    parts.fetch(:min, 0),
    parts.fetch(:sec, 0) + parts.fetch(:sec_fraction, 0),
    parts.fetch(:offset, 0)
  )
  if parts[:offset]
    TimeWithZone.new(time.utc, self)
  else
    TimeWithZone.new(nil, self, time)
  end
rescue Date::Error, KeyError
  raise ArgumentError, "invalid date"
end

def load_country_zones(code)

def load_country_zones(code)
  country = TZInfo::Country.get(code)
  country.zone_identifiers.flat_map do |tz_id|
    if MAPPING.value?(tz_id)
      MAPPING.inject([]) do |memo, (key, value)|
        memo << self[key] if value == tz_id
        memo
      end
    else
      create(tz_id, nil, TZInfo::Timezone.get(tz_id))
    end
  end.sort!
end

def local(*args)

Time.zone.local(2007, 2, 1, 15, 30, 45) # => Thu, 01 Feb 2007 15:30:45 HST -10:00
Time.zone = 'Hawaii' # => "Hawaii"

of +self+ from given values.
Method for creating new ActiveSupport::TimeWithZone instance in time zone
def local(*args)
  time = Time.utc(*args)
  ActiveSupport::TimeWithZone.new(nil, self, time)
end

def local_to_utc(time, dst = true)

Time.utc() instance.
Adjust the given time to the simultaneous time in UTC. Returns a
def local_to_utc(time, dst = true)
  tzinfo.local_to_utc(time, dst)
end

def match?(re)

if a match is found.
Compare #name and TZInfo identifier to a supplied regexp, returning +true+
def match?(re)
  (re == name) || (re == MAPPING[name]) ||
    ((Regexp === re) && (re.match?(name) || re.match?(MAPPING[name])))
end

def new(name)

this class with the +composed_of+ macro.)
such TimeZone instance exists. (This exists to support the use of
Returns a TimeZone instance with the given name, or +nil+ if no
def new(name)
  self[name]
end

def now

Time.zone.now # => Wed, 23 Jan 2008 20:24:27 HST -10:00
Time.zone = 'Hawaii' # => "Hawaii"

time in the time zone represented by +self+.
Returns an ActiveSupport::TimeWithZone instance representing the current
def now
  time_now.utc.in_time_zone(self)
end

def parse(str, now = now())

If the string is invalid then an +ArgumentError+ could be raised.

Time.zone.parse('Mar 2000') # => Wed, 01 Mar 2000 00:00:00 HST -10:00

components are supplied, then the day of the month defaults to 1:
However, if the date component is not provided, but any other upper

Time.zone.parse('22:30:00') # => Fri, 31 Dec 1999 22:30:00 HST -10:00
Time.zone.now # => Fri, 31 Dec 1999 14:00:00 HST -10:00

TimeZone#now:
If upper components are missing from the string, they are supplied from

Time.zone.parse('1999-12-31 14:00:00') # => Fri, 31 Dec 1999 14:00:00 HST -10:00
Time.zone = 'Hawaii' # => "Hawaii"

of +self+ from parsed string.
Method for creating new ActiveSupport::TimeWithZone instance in time zone
def parse(str, now = now())
  parts_to_time(Date._parse(str, false), now)
end

def parts_to_time(parts, now)

def parts_to_time(parts, now)
  raise ArgumentError, "invalid date" if parts.nil?
  return if parts.empty?
  if parts[:seconds]
    time = Time.at(parts[:seconds])
  else
    time = Time.new(
      parts.fetch(:year, now.year),
      parts.fetch(:mon, now.month),
      parts.fetch(:mday, parts[:year] || parts[:mon] ? 1 : now.day),
      parts.fetch(:hour, 0),
      parts.fetch(:min, 0),
      parts.fetch(:sec, 0) + parts.fetch(:sec_fraction, 0),
      parts.fetch(:offset, 0)
    )
  end
  if parts[:offset] || parts[:seconds]
    TimeWithZone.new(time.utc, self)
  else
    TimeWithZone.new(nil, self, time)
  end
end

def period_for_local(time, dst = true)

instances.
Available so that TimeZone instances respond like TZInfo::Timezone
def period_for_local(time, dst = true)
  tzinfo.period_for_local(time, dst) { |periods| periods.last }
end

def period_for_utc(time)

instances.
Available so that TimeZone instances respond like TZInfo::Timezone
def period_for_utc(time)
  tzinfo.period_for_utc(time)
end

def periods_for_local(time) # :nodoc:

:nodoc:
def periods_for_local(time) # :nodoc:
  tzinfo.periods_for_local(time)
end

def rfc3339(str)

Time.zone.rfc3339('1999-12-31') # => ArgumentError: invalid date
Time.zone = 'Hawaii' # => "Hawaii"

allow for missing components.
be raised. This is much stricter than either +parse+ or +iso8601+ which
If the time or zone components are missing then an +ArgumentError+ will

Time.zone.rfc3339('2000-01-01T00:00:00Z') # => Fri, 31 Dec 1999 14:00:00 HST -10:00
Time.zone = 'Hawaii' # => "Hawaii"

of +self+ from an RFC 3339 string.
Method for creating new ActiveSupport::TimeWithZone instance in time zone
def rfc3339(str)
  parts = Date._rfc3339(str)
  raise ArgumentError, "invalid date" if parts.empty?
  time = Time.new(
    parts.fetch(:year),
    parts.fetch(:mon),
    parts.fetch(:mday),
    parts.fetch(:hour),
    parts.fetch(:min),
    parts.fetch(:sec) + parts.fetch(:sec_fraction, 0),
    parts.fetch(:offset)
  )
  TimeWithZone.new(time.utc, self)
end

def seconds_to_utc_offset(seconds, colon = true)

ActiveSupport::TimeZone.seconds_to_utc_offset(-21_600) # => "-06:00"

Time#utc_offset) and turns this into an +HH:MM formatted string.
Assumes self represents an offset from UTC in seconds (as returned from
def seconds_to_utc_offset(seconds, colon = true)
  format = colon ? UTC_OFFSET_WITH_COLON : UTC_OFFSET_WITHOUT_COLON
  sign = (seconds < 0 ? "-" : "+")
  hours = seconds.abs / 3600
  minutes = (seconds.abs % 3600) / 60
  format % [sign, hours, minutes]
end

def strptime(str, format, now = now())

Time.zone.strptime('Mar 2000', '%b %Y') # => Wed, 01 Mar 2000 00:00:00 HST -10:00

components are supplied, then the day of the month defaults to 1:
However, if the date component is not provided, but any other upper

Time.zone.strptime('22:30:00', '%H:%M:%S') # => Fri, 31 Dec 1999 22:30:00 HST -10:00
Time.zone.now # => Fri, 31 Dec 1999 14:00:00 HST -10:00

TimeZone#now:
If upper components are missing from the string, they are supplied from

Time.zone.strptime('1999-12-31 14:00:00', '%Y-%m-%d %H:%M:%S') # => Fri, 31 Dec 1999 14:00:00 HST -10:00
Time.zone = 'Hawaii' # => "Hawaii"

In either case, the returned TimeWithZone has the timezone of +self+.
(This is the same behavior as +parse+.)
unless +format+ includes an explicit time zone.
Assumes that +str+ is a time in the time zone +self+,

Parses +str+ according to +format+ and returns an ActiveSupport::TimeWithZone.
def strptime(str, format, now = now())
  parts_to_time(DateTime._strptime(str, format), now)
end

def time_now

def time_now
  Time.now
end

def to_s

Returns a textual representation of this time zone.
def to_s
  "(GMT#{formatted_offset}) #{name}"
end

def today

Returns the current date in this time zone.
def today
  tzinfo.now.to_date
end

def tomorrow

Returns the next date in this time zone.
def tomorrow
  today + 1
end

def us_zones

for time zones in the USA.
A convenience method for returning a collection of TimeZone objects
def us_zones
  country_zones(:us)
end

def utc_offset

Returns the offset of this time zone from UTC in seconds.
def utc_offset
  @utc_offset || tzinfo&.current_period&.base_utc_offset
end

def utc_to_local(time)

See the +utc_to_local_returns_utc_offset_times+ config for more info.
As of tzinfo 2, utc_to_local returns a Time with a non-zero utc_offset.

Time#in_time_zone() instead.
-- if you want an ActiveSupport::TimeWithZone instance, use
represented by +self+. Returns a local time with the appropriate offset
Adjust the given time to the simultaneous time in the time zone
def utc_to_local(time)
  tzinfo.utc_to_local(time).yield_self do |t|
    ActiveSupport.utc_to_local_returns_utc_offset_times ?
      t : Time.utc(t.year, t.month, t.day, t.hour, t.min, t.sec, t.sec_fraction * 1_000_000)
  end
end

def yesterday

Returns the previous date in this time zone.
def yesterday
  today - 1
end

def zones_map

def zones_map
  @zones_map ||= MAPPING.each_with_object({}) do |(name, _), zones|
    timezone = self[name]
    zones[name] = timezone if timezone
  end
end