Class: TZInfo::TimezonePeriodList

Inherits:
Object
  • Object
show all
Defined in:
lib/tzinfo/timezone_period_list.rb

Overview

A list of TimezonePeriod instances defining a Timezone.

Instance Method Summary collapse

Constructor Details

#initializeTimezonePeriodList

Initializes a new TimezonePeriodList



34
35
36
37
38
39
40
41
# File 'lib/tzinfo/timezone_period_list.rb', line 34

def initialize
  @list = nil
  @last_year = nil
  @last_month = nil
  @start_year = nil
  @start_month = nil
  @unbounded_start = nil
end

Instance Method Details

#add(utc_start_year, utc_start_month, &block) ⇒ Object

Adds a new TimezonePeriod to the list. utc_start_year and utc_start_month are the year and month in which the period starts in UTC. A block must be passed in that will return the TimezonePeriod when called with no arguments.

If the start year and month are less than the previously encountered year and month ArgumentError will be thrown.

Blocks must be added in order of increasing UTC start date.



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/tzinfo/timezone_period_list.rb', line 63

def add(utc_start_year, utc_start_month, &block)                 
  if @list.nil?
    @list = [block]
    @start_year = utc_start_year
    @start_month = utc_start_month
  else
    if utc_start_year < @last_year || (utc_start_year == @last_year && utc_start_month < @last_month)
      raise ArgumentError, 'Calls to add must be in increasing start date order'
    end
                     
    index = index_for_utc(utc_start_year, utc_start_month)
    if @list[index].nil?
      @list[index] = block
    elsif @list[index].is_a?(Array)
      @list[index] << block
    else
      @list[index] = [@list[index], block]
    end
  end
    
  @last_year = utc_start_year
  @last_month = utc_start_month        
end

#add_unbounded_start(&block) ⇒ Object

One unbounded start period can be defined. This must be set before any calls to add.

ArgumentError will be thrown if add or add_unbounded_start has already been called.

Raises:

  • (ArgumentError)


48
49
50
51
52
# File 'lib/tzinfo/timezone_period_list.rb', line 48

def add_unbounded_start(&block)
  raise ArgumentError, 'add_unbounded_start has already been called' if !@unbounded_start.nil?
  raise ArgumentError, 'add has already been called' if !@list.nil?
  @unbounded_start = block
end

#period_for_utc(utc) ⇒ Object

Returns the period for the given utc time. If no period is found for the given time, PeriodNotFound is thrown.



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/tzinfo/timezone_period_list.rb', line 89

def period_for_utc(utc)
  utc = TimeOrDateTime.wrap(utc)
  
  if @list.nil?
    result = nil
  else
    index = index_for_utc(utc.year, utc.mon)
    index = 0 if index < 0
    index = @list.length - 1 if index >= @list.length
    
    result = nil
    index.downto(0) {|i|
      contents = get_contents(i)
      
      if contents.is_a?(Array)
        (contents.length - 1).downto(0) {|j|
          if contents[j].valid_for_utc?(utc)
            result = contents[j]
            break
          end
        }
        break unless result.nil?
      elsif !contents.nil? && contents.valid_for_utc?(utc)
        result = contents
        break        
      end
    }
  end
  
  if result.nil?
    unbounded_start = get_unbounded_start
    if !unbounded_start.nil? && unbounded_start.valid_for_utc?(utc)          
      unbounded_start
    else
      raise PeriodNotFound, "No period found for utc: #{utc}"
    end
  else
    result
  end
end

#periods_for_local(local) ⇒ Object

Returns the set of periods for the given local time as an array. If no period is found for the given time, PeriodNotFound is thrown. Results returned are ordered by increasing UTC start date.



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/tzinfo/timezone_period_list.rb', line 133

def periods_for_local(local)
  local = TimeOrDateTime.wrap(local)
  
  # found_first is used to avoid searching back to far
  # the search will be limited at the next half year block after discovering
  # the first match
  found_first = nil
  
  result = []
  
  if !@list.nil?      
    # add one to the index because the periods are indexed by UTC start
    # and the period we are looking for could therefore be in the next
    # half of the year
    index = index_for_utc(local.year, local.mon) + 1
    index = 0 if index < 0
    index = @list.length - 1 if index >= @list.length
    
    index.downto(0) {|i|
      contents = get_contents(i)
      
      if contents.is_a?(Array)
        (contents.length - 1).downto(0) {|j|
          if contents[j].valid_for_local?(local)
            result << contents[j]
            found_first = i if found_first.nil?
          end
        }                        
      elsif !contents.nil? && contents.valid_for_local?(local)
        result << contents
        found_first = i if found_first.nil?
      end
      
      if !contents.nil? && !found_first.nil? && i < found_first
        # searched far enough
        break
      end
    }
  end
    
  if result.empty? || found_first == 0
    unbounded_start = get_unbounded_start
    result << unbounded_start if !unbounded_start.nil? && unbounded_start.valid_for_local?(local)
  end
  
  if result.empty?        
    raise PeriodNotFound, "No period found for utc: #{local}"
  else
    result.reverse!
    result
  end
end