123456789_123456789_123456789_123456789_123456789_

Class: TZInfo::DataSources::TransitionsDataTimezoneInfo

Relationships & Source Files
Super Chains via Extension / Inclusion / Inheritance
Class Chain:
Instance Chain:
Inherits: TZInfo::DataSources::DataTimezoneInfo
Defined in: lib/tzinfo/data_sources/transitions_data_timezone_info.rb

Overview

Represents a data time zone defined by a list of transitions that change the locally observed time.

Class Method Summary

TimezoneInfo - Inherited

.new

Initializes a new TimezoneInfo.

Instance Attribute Summary

Instance Method Summary

DataTimezoneInfo - Inherited

#create_timezone, #period_for,
#periods_for_local

Returns an Array containing the TimezonePeriods that could be observed at the local time specified by local_timestamp.

#transitions_up_to

Returns an Array of ::TZInfo::TimezoneTransition instances representing the times where the UTC offset of the time zone changes.

#raise_not_implemented

Raises a NotImplementedError to indicate that the base class is incorrectly being used directly.

TimezoneInfo - Inherited

#create_timezone, #inspect,
#raise_not_implemented

Raises a NotImplementedError.

Constructor Details

.new(identifier, transitions) ⇒ TransitionsDataTimezoneInfo

Initializes a new TransitionsDataTimezoneInfo.

The passed in identifier instance will be frozen. A reference to the passed in Array will be retained.

The #transitions Array must be sorted in order of ascending timestamp. Each transition must have a timestamp_value that is greater than the timestamp_value of the prior transition.

Parameters:

  • identifier (String)

    the identifier of the time zone.

  • transitions (Array<TimezoneTransitions>)

    an Array of transitions that each indicate when a change occurs in the locally observed time.

Raises:

  • (ArgumentError)

    if identifier is nil.

  • (ArgumentError)

    if #transitions is nil.

  • (ArgumentError)

    if #transitions is an empty Array.

[ GitHub ]

  
# File 'lib/tzinfo/data_sources/transitions_data_timezone_info.rb', line 31

def initialize(identifier, transitions)
  super(identifier)
  raise ArgumentError, 'transitions must be specified' unless transitions
  raise ArgumentError, 'transitions must not be an empty Array' if transitions.empty?
  @transitions = transitions.freeze
end

Instance Attribute Details

#transitionsArray<TimezoneTransition> (readonly)

Returns:

  • (Array<TimezoneTransition>)

    the transitions that define this time zone in order of ascending timestamp.

[ GitHub ]

  
# File 'lib/tzinfo/data_sources/transitions_data_timezone_info.rb', line 11

attr_reader :transitions

Instance Method Details

#find_minimum_transition {|transition| ... } ⇒ Integer (private)

Performs a binary search on #transitions to find the index of the earliest transition satisfying a condition.

:nocov_array_bsearch_index:

See additional method definition at line 159.

Yields:

  • (transition)

    the caller will be yielded to to test the search condition.

Yield Parameters:

Yield Returns:

  • (Boolean)

    true for the earliest transition that satisfies the condition and return true for all subsequent transitions. In all other cases, the result of the block must be false.

Returns:

  • (Integer)

    the index of the earliest transition safisfying the condition or nil if there are no such transitions.

[ GitHub ]

  
# File 'lib/tzinfo/data_sources/transitions_data_timezone_info.rb', line 179

def find_minimum_transition(&block)
  @transitions.bsearch_index(&block)
end

#period_for(timestamp) ⇒ TimezonePeriod

Parameters:

Returns:

Raises:

  • (ArgumentError)

    may be raised if timestamp is nil or does not have a specified utc_offset.

[ GitHub ]

  
# File 'lib/tzinfo/data_sources/transitions_data_timezone_info.rb', line 39

def period_for(timestamp)
  raise ArgumentError, 'timestamp must be specified' unless timestamp
  raise ArgumentError, 'timestamp must have a specified utc_offset' unless timestamp.utc_offset

  timestamp_value = timestamp.value

  index = find_minimum_transition {|t| t.timestamp_value >= timestamp_value }

  if index
    transition = @transitions[index]

    if transition.timestamp_value == timestamp_value
      # timestamp occurs within the second of the found transition, so is
      # the transition that starts the period.
      start_transition = transition
      end_transition = @transitions[index + 1]
    else
      # timestamp occurs before the second of the found transition, so is
      # the transition that ends the period.
      start_transition = index == 0 ? nil : @transitions[index - 1]
      end_transition = transition
    end
  else
    start_transition = @transitions.last
    end_transition = nil
  end

  TransitionsTimezonePeriod.new(start_transition, end_transition)
end

#periods_for_local(local_timestamp) ⇒ Array<TimezonePeriod>

Returns an Array containing the TimezonePeriods that could be observed at the local time specified by local_timestamp. The results are are ordered by increasing UTC start date. An empty Array is returned if no periods are found for the given local time.

Parameters:

Returns:

Raises:

  • (ArgumentError)

    may be raised if local_timestamp is nil, or has a specified utc_offset.

[ GitHub ]

  
# File 'lib/tzinfo/data_sources/transitions_data_timezone_info.rb', line 70

def periods_for_local(local_timestamp)
  raise ArgumentError, 'local_timestamp must be specified' unless local_timestamp
  raise ArgumentError, 'local_timestamp must have an unspecified utc_offset' if local_timestamp.utc_offset

  local_timestamp_value = local_timestamp.value
  latest_possible_utc_value = local_timestamp_value + 86400
  earliest_possible_utc_value = local_timestamp_value - 86400

  # Find the index of the first transition that occurs after a latest
  # possible UTC representation of the local timestamp and then search
  # backwards until an earliest possible UTC representation.

  index = find_minimum_transition {|t| t.timestamp_value >= latest_possible_utc_value }

  # No transitions after latest_possible_utc_value, set to max index + 1
  # to search backwards including the period after the last transition
  index = @transitions.length unless index

  result = []

  index.downto(0) do |i|
    start_transition = i > 0 ? @transitions[i - 1] : nil
    end_transition = @transitions[i]
    offset = start_transition ? start_transition.offset : end_transition.previous_offset
    utc_timestamp_value = local_timestamp_value - offset.observed_utc_offset

    # It is not necessary to compare the sub-seconds because a timestamp
    # is in the period if is >= the start transition (sub-seconds would
    # make == become >) and if it is < the end transition (which
    # sub-seconds cannot affect).
    if (!start_transition || utc_timestamp_value >= start_transition.timestamp_value) && (!end_transition || utc_timestamp_value < end_transition.timestamp_value)
      result << TransitionsTimezonePeriod.new(start_transition, end_transition)
    elsif end_transition && end_transition.timestamp_value < earliest_possible_utc_value
      break
    end
  end

  result.reverse!
end

#transition_on_or_after_timestamp?(transition, timestamp) ⇒ Boolean (private)

Determines if a transition occurs at or after a given ::TZInfo::Timestamp, taking the sub_second into consideration.

Parameters:

Returns:

  • (Boolean)

    true if transition occurs at or after timestamp, otherwise false.

[ GitHub ]

  
# File 'lib/tzinfo/data_sources/transitions_data_timezone_info.rb', line 207

def transition_on_or_after_timestamp?(transition, timestamp)
  transition_timestamp_value = transition.timestamp_value
  timestamp_value = timestamp.value
  transition_timestamp_value > timestamp_value || transition_timestamp_value == timestamp_value && timestamp.sub_second == 0
end

#transitions_up_to(to_timestamp, from_timestamp = nil) ⇒ Array<TimezoneTransition>

Returns an Array of ::TZInfo::TimezoneTransition instances representing the times where the UTC offset of the time zone changes.

Transitions are returned up to a given ::TZInfo::Timestamp (to_timestamp).

A from ::TZInfo::Timestamp may also be supplied using the from_timestamp parameter. If from_timestamp is specified, only transitions from that time onwards will be returned.

Comparisons with to_timestamp are exclusive. Comparisons with from_timestamp are inclusive. If a transition falls precisely on to_timestamp, it will be excluded. If a transition falls on from_timestamp, it will be included.

Transitions returned are ordered by when they occur, from earliest to latest.

Parameters:

Returns:

Raises:

  • (ArgumentError)

    may be raised if to_timestamp is nil or does not have a specified utc_offset.

  • (ArgumentError)

    may be raised if from_timestamp is specified but does not have a specified utc_offset.

  • (ArgumentError)

    may be raised if from_timestamp is specified but is not earlier than or at the same time as to_timestamp.

[ GitHub ]

  
# File 'lib/tzinfo/data_sources/transitions_data_timezone_info.rb', line 111

def transitions_up_to(to_timestamp, from_timestamp = nil)
  raise ArgumentError, 'to_timestamp must be specified' unless to_timestamp
  raise ArgumentError, 'to_timestamp must have a specified utc_offset' unless to_timestamp.utc_offset

  if from_timestamp
    raise ArgumentError, 'from_timestamp must have a specified utc_offset' unless from_timestamp.utc_offset
    raise ArgumentError, 'to_timestamp must be greater than from_timestamp' if to_timestamp <= from_timestamp
  end

  if from_timestamp
    from_index = find_minimum_transition {|t| transition_on_or_after_timestamp?(t, from_timestamp) }
    return [] unless from_index
  else
    from_index = 0
  end

  to_index = find_minimum_transition {|t| transition_on_or_after_timestamp?(t, to_timestamp) }

  if to_index
    return [] if to_index < 1
    to_index -= 1
  else
    to_index = -1
  end

  @transitions[from_index..to_index]
end