tzinfo 1.2.11 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.yardopts +3 -0
  4. data/CHANGES.md +469 -431
  5. data/LICENSE +13 -13
  6. data/README.md +368 -114
  7. data/lib/tzinfo/country.rb +131 -129
  8. data/lib/tzinfo/country_timezone.rb +70 -112
  9. data/lib/tzinfo/data_source.rb +389 -144
  10. data/lib/tzinfo/data_sources/constant_offset_data_timezone_info.rb +56 -0
  11. data/lib/tzinfo/data_sources/country_info.rb +42 -0
  12. data/lib/tzinfo/data_sources/data_timezone_info.rb +91 -0
  13. data/lib/tzinfo/data_sources/linked_timezone_info.rb +33 -0
  14. data/lib/tzinfo/data_sources/ruby_data_source.rb +141 -0
  15. data/lib/tzinfo/data_sources/timezone_info.rb +47 -0
  16. data/lib/tzinfo/data_sources/transitions_data_timezone_info.rb +214 -0
  17. data/lib/tzinfo/data_sources/zoneinfo_data_source.rb +573 -0
  18. data/lib/tzinfo/data_sources/zoneinfo_reader.rb +284 -0
  19. data/lib/tzinfo/data_sources.rb +8 -0
  20. data/lib/tzinfo/data_timezone.rb +33 -47
  21. data/lib/tzinfo/datetime_with_offset.rb +153 -0
  22. data/lib/tzinfo/format1/country_definer.rb +17 -0
  23. data/lib/tzinfo/format1/country_index_definition.rb +64 -0
  24. data/lib/tzinfo/format1/timezone_definer.rb +64 -0
  25. data/lib/tzinfo/format1/timezone_definition.rb +39 -0
  26. data/lib/tzinfo/format1/timezone_index_definition.rb +77 -0
  27. data/lib/tzinfo/format1.rb +10 -0
  28. data/lib/tzinfo/format2/country_definer.rb +68 -0
  29. data/lib/tzinfo/format2/country_index_definer.rb +68 -0
  30. data/lib/tzinfo/format2/country_index_definition.rb +46 -0
  31. data/lib/tzinfo/format2/timezone_definer.rb +94 -0
  32. data/lib/tzinfo/format2/timezone_definition.rb +73 -0
  33. data/lib/tzinfo/format2/timezone_index_definer.rb +45 -0
  34. data/lib/tzinfo/format2/timezone_index_definition.rb +55 -0
  35. data/lib/tzinfo/format2.rb +10 -0
  36. data/lib/tzinfo/info_timezone.rb +26 -21
  37. data/lib/tzinfo/linked_timezone.rb +33 -52
  38. data/lib/tzinfo/offset_timezone_period.rb +42 -0
  39. data/lib/tzinfo/string_deduper.rb +118 -0
  40. data/lib/tzinfo/time_with_offset.rb +128 -0
  41. data/lib/tzinfo/timestamp.rb +548 -0
  42. data/lib/tzinfo/timestamp_with_offset.rb +85 -0
  43. data/lib/tzinfo/timezone.rb +979 -502
  44. data/lib/tzinfo/timezone_offset.rb +84 -74
  45. data/lib/tzinfo/timezone_period.rb +151 -217
  46. data/lib/tzinfo/timezone_proxy.rb +70 -79
  47. data/lib/tzinfo/timezone_transition.rb +77 -109
  48. data/lib/tzinfo/transitions_timezone_period.rb +63 -0
  49. data/lib/tzinfo/version.rb +7 -0
  50. data/lib/tzinfo/with_offset.rb +61 -0
  51. data/lib/tzinfo.rb +60 -40
  52. data.tar.gz.sig +0 -0
  53. metadata +51 -115
  54. metadata.gz.sig +2 -3
  55. data/Rakefile +0 -107
  56. data/lib/tzinfo/annual_rules.rb +0 -51
  57. data/lib/tzinfo/country_index_definition.rb +0 -31
  58. data/lib/tzinfo/country_info.rb +0 -42
  59. data/lib/tzinfo/data_timezone_info.rb +0 -55
  60. data/lib/tzinfo/linked_timezone_info.rb +0 -26
  61. data/lib/tzinfo/offset_rationals.rb +0 -77
  62. data/lib/tzinfo/posix_time_zone_parser.rb +0 -136
  63. data/lib/tzinfo/ruby_core_support.rb +0 -176
  64. data/lib/tzinfo/ruby_country_info.rb +0 -74
  65. data/lib/tzinfo/ruby_data_source.rb +0 -136
  66. data/lib/tzinfo/time_or_datetime.rb +0 -351
  67. data/lib/tzinfo/timezone_definition.rb +0 -36
  68. data/lib/tzinfo/timezone_index_definition.rb +0 -54
  69. data/lib/tzinfo/timezone_info.rb +0 -30
  70. data/lib/tzinfo/timezone_transition_definition.rb +0 -104
  71. data/lib/tzinfo/transition_data_timezone_info.rb +0 -274
  72. data/lib/tzinfo/transition_rule.rb +0 -325
  73. data/lib/tzinfo/zoneinfo_country_info.rb +0 -37
  74. data/lib/tzinfo/zoneinfo_data_source.rb +0 -504
  75. data/lib/tzinfo/zoneinfo_timezone_info.rb +0 -516
  76. data/test/assets/payload.rb +0 -1
  77. data/test/tc_annual_rules.rb +0 -95
  78. data/test/tc_country.rb +0 -240
  79. data/test/tc_country_index_definition.rb +0 -69
  80. data/test/tc_country_info.rb +0 -16
  81. data/test/tc_country_timezone.rb +0 -173
  82. data/test/tc_data_source.rb +0 -218
  83. data/test/tc_data_timezone.rb +0 -99
  84. data/test/tc_data_timezone_info.rb +0 -18
  85. data/test/tc_info_timezone.rb +0 -34
  86. data/test/tc_linked_timezone.rb +0 -155
  87. data/test/tc_linked_timezone_info.rb +0 -23
  88. data/test/tc_offset_rationals.rb +0 -23
  89. data/test/tc_posix_time_zone_parser.rb +0 -261
  90. data/test/tc_ruby_core_support.rb +0 -168
  91. data/test/tc_ruby_country_info.rb +0 -110
  92. data/test/tc_ruby_data_source.rb +0 -175
  93. data/test/tc_time_or_datetime.rb +0 -674
  94. data/test/tc_timezone.rb +0 -1361
  95. data/test/tc_timezone_definition.rb +0 -113
  96. data/test/tc_timezone_index_definition.rb +0 -73
  97. data/test/tc_timezone_info.rb +0 -11
  98. data/test/tc_timezone_london.rb +0 -143
  99. data/test/tc_timezone_melbourne.rb +0 -142
  100. data/test/tc_timezone_new_york.rb +0 -142
  101. data/test/tc_timezone_offset.rb +0 -126
  102. data/test/tc_timezone_period.rb +0 -555
  103. data/test/tc_timezone_proxy.rb +0 -136
  104. data/test/tc_timezone_transition.rb +0 -366
  105. data/test/tc_timezone_transition_definition.rb +0 -295
  106. data/test/tc_timezone_utc.rb +0 -27
  107. data/test/tc_transition_data_timezone_info.rb +0 -433
  108. data/test/tc_transition_rule.rb +0 -663
  109. data/test/tc_zoneinfo_country_info.rb +0 -78
  110. data/test/tc_zoneinfo_data_source.rb +0 -1226
  111. data/test/tc_zoneinfo_timezone_info.rb +0 -2149
  112. data/test/test_utils.rb +0 -214
  113. data/test/ts_all.rb +0 -7
  114. data/test/ts_all_ruby.rb +0 -5
  115. data/test/ts_all_zoneinfo.rb +0 -9
  116. data/test/tzinfo-data/tzinfo/data/definitions/America/Argentina/Buenos_Aires.rb +0 -89
  117. data/test/tzinfo-data/tzinfo/data/definitions/America/New_York.rb +0 -327
  118. data/test/tzinfo-data/tzinfo/data/definitions/Australia/Melbourne.rb +0 -230
  119. data/test/tzinfo-data/tzinfo/data/definitions/EST.rb +0 -19
  120. data/test/tzinfo-data/tzinfo/data/definitions/Etc/GMT__m__1.rb +0 -21
  121. data/test/tzinfo-data/tzinfo/data/definitions/Etc/GMT__p__1.rb +0 -21
  122. data/test/tzinfo-data/tzinfo/data/definitions/Etc/UTC.rb +0 -21
  123. data/test/tzinfo-data/tzinfo/data/definitions/Europe/Amsterdam.rb +0 -273
  124. data/test/tzinfo-data/tzinfo/data/definitions/Europe/Andorra.rb +0 -198
  125. data/test/tzinfo-data/tzinfo/data/definitions/Europe/London.rb +0 -333
  126. data/test/tzinfo-data/tzinfo/data/definitions/Europe/Paris.rb +0 -277
  127. data/test/tzinfo-data/tzinfo/data/definitions/Europe/Prague.rb +0 -235
  128. data/test/tzinfo-data/tzinfo/data/definitions/UTC.rb +0 -16
  129. data/test/tzinfo-data/tzinfo/data/indexes/countries.rb +0 -940
  130. data/test/tzinfo-data/tzinfo/data/indexes/timezones.rb +0 -609
  131. data/test/tzinfo-data/tzinfo/data/version.rb +0 -20
  132. data/test/tzinfo-data/tzinfo/data.rb +0 -8
  133. data/test/zoneinfo/America/Argentina/Buenos_Aires +0 -0
  134. data/test/zoneinfo/America/New_York +0 -0
  135. data/test/zoneinfo/Australia/Melbourne +0 -0
  136. data/test/zoneinfo/EST +0 -0
  137. data/test/zoneinfo/Etc/UTC +0 -0
  138. data/test/zoneinfo/Europe/Amsterdam +0 -0
  139. data/test/zoneinfo/Europe/Andorra +0 -0
  140. data/test/zoneinfo/Europe/London +0 -0
  141. data/test/zoneinfo/Europe/Paris +0 -0
  142. data/test/zoneinfo/Europe/Prague +0 -0
  143. data/test/zoneinfo/Factory +0 -0
  144. data/test/zoneinfo/iso3166.tab +0 -274
  145. data/test/zoneinfo/leapseconds +0 -78
  146. data/test/zoneinfo/posix/Europe/London +0 -0
  147. data/test/zoneinfo/posixrules +0 -0
  148. data/test/zoneinfo/right/Europe/London +0 -0
  149. data/test/zoneinfo/zone.tab +0 -452
  150. data/test/zoneinfo/zone1970.tab +0 -384
  151. data/tzinfo.gemspec +0 -21
@@ -1,274 +0,0 @@
1
- module TZInfo
2
- # Raised if no offsets have been defined when calling period_for_utc or
3
- # periods_for_local. Indicates an error in the timezone data.
4
- class NoOffsetsDefined < StandardError
5
- end
6
-
7
- # Represents a data timezone defined by a set of offsets and a set
8
- # of transitions.
9
- #
10
- # @private
11
- class TransitionDataTimezoneInfo < DataTimezoneInfo #:nodoc:
12
-
13
- # Constructs a new TransitionDataTimezoneInfo with its identifier.
14
- def initialize(identifier)
15
- super(identifier)
16
- @offsets = {}
17
- @transitions = []
18
- @previous_offset = nil
19
- @transitions_index = nil
20
- end
21
-
22
- # Defines a offset. The id uniquely identifies this offset within the
23
- # timezone. utc_offset and std_offset define the offset in seconds of
24
- # standard time from UTC and daylight savings from standard time
25
- # respectively. abbreviation describes the timezone offset (e.g. GMT, BST,
26
- # EST or EDT).
27
- #
28
- # The first offset to be defined is treated as the offset that applies
29
- # until the first transition. This will usually be in Local Mean Time (LMT).
30
- #
31
- # ArgumentError will be raised if the id is already defined.
32
- def offset(id, utc_offset, std_offset, abbreviation)
33
- raise ArgumentError, 'Offset already defined' if @offsets.has_key?(id)
34
-
35
- offset = TimezoneOffset.new(utc_offset, std_offset, abbreviation)
36
- @offsets[id] = offset
37
- @previous_offset = offset unless @previous_offset
38
- end
39
-
40
- # Defines a transition. Transitions must be defined in chronological order.
41
- # ArgumentError will be raised if a transition is added out of order.
42
- # offset_id refers to an id defined with offset. ArgumentError will be
43
- # raised if the offset_id cannot be found. numerator_or_time and
44
- # denomiator specify the time the transition occurs as. See
45
- # TimezoneTransition for more detail about specifying times.
46
- def transition(year, month, offset_id, numerator_or_timestamp, denominator_or_numerator = nil, denominator = nil)
47
- offset = @offsets[offset_id]
48
- raise ArgumentError, 'Offset not found' unless offset
49
-
50
- if @transitions_index
51
- if year < @last_year || (year == @last_year && month < @last_month)
52
- raise ArgumentError, 'Transitions must be increasing date order'
53
- end
54
-
55
- # Record the position of the first transition with this index.
56
- index = transition_index(year, month)
57
- @transitions_index[index] ||= @transitions.length
58
-
59
- # Fill in any gaps
60
- (index - 1).downto(0) do |i|
61
- break if @transitions_index[i]
62
- @transitions_index[i] = @transitions.length
63
- end
64
- else
65
- @transitions_index = [@transitions.length]
66
- @start_year = year
67
- @start_month = month
68
- end
69
-
70
- @transitions << TimezoneTransitionDefinition.new(offset, @previous_offset,
71
- numerator_or_timestamp, denominator_or_numerator, denominator)
72
- @last_year = year
73
- @last_month = month
74
- @previous_offset = offset
75
- end
76
-
77
- # Returns the TimezonePeriod for the given UTC time.
78
- # Raises NoOffsetsDefined if no offsets have been defined.
79
- def period_for_utc(utc)
80
- unless @transitions.empty?
81
- utc = TimeOrDateTime.wrap(utc)
82
- index = transition_index(utc.year, utc.mon)
83
-
84
- start_transition = nil
85
- start = transition_before_end(index)
86
- if start
87
- start.downto(0) do |i|
88
- if @transitions[i].at <= utc
89
- start_transition = @transitions[i]
90
- break
91
- end
92
- end
93
- end
94
-
95
- end_transition = nil
96
- start = transition_after_start(index)
97
- if start
98
- start.upto(@transitions.length - 1) do |i|
99
- if @transitions[i].at > utc
100
- end_transition = @transitions[i]
101
- break
102
- end
103
- end
104
- end
105
-
106
- if start_transition || end_transition
107
- TimezonePeriod.new(start_transition, end_transition)
108
- else
109
- # Won't happen since there are transitions. Must always find one
110
- # transition that is either >= or < the specified time.
111
- raise 'No transitions found in search'
112
- end
113
- else
114
- raise NoOffsetsDefined, 'No offsets have been defined' unless @previous_offset
115
- TimezonePeriod.new(nil, nil, @previous_offset)
116
- end
117
- end
118
-
119
- # Returns the set of TimezonePeriods for the given local time as an array.
120
- # Results returned are ordered by increasing UTC start date.
121
- # Returns an empty array if no periods are found for the given time.
122
- # Raises NoOffsetsDefined if no offsets have been defined.
123
- def periods_for_local(local)
124
- unless @transitions.empty?
125
- local = TimeOrDateTime.wrap(local)
126
- index = transition_index(local.year, local.mon)
127
-
128
- result = []
129
-
130
- start_index = transition_after_start(index - 1)
131
- if start_index && @transitions[start_index].local_end_at > local
132
- if start_index > 0
133
- if @transitions[start_index - 1].local_start_at <= local
134
- result << TimezonePeriod.new(@transitions[start_index - 1], @transitions[start_index])
135
- end
136
- else
137
- result << TimezonePeriod.new(nil, @transitions[start_index])
138
- end
139
- end
140
-
141
- end_index = transition_before_end(index + 1)
142
-
143
- if end_index
144
- start_index = end_index unless start_index
145
-
146
- start_index.upto(transition_before_end(index + 1)) do |i|
147
- if @transitions[i].local_start_at <= local
148
- if i + 1 < @transitions.length
149
- if @transitions[i + 1].local_end_at > local
150
- result << TimezonePeriod.new(@transitions[i], @transitions[i + 1])
151
- end
152
- else
153
- result << TimezonePeriod.new(@transitions[i], nil)
154
- end
155
- end
156
- end
157
- end
158
-
159
- result
160
- else
161
- raise NoOffsetsDefined, 'No offsets have been defined' unless @previous_offset
162
- [TimezonePeriod.new(nil, nil, @previous_offset)]
163
- end
164
- end
165
-
166
- # Returns an Array of TimezoneTransition instances representing the times
167
- # where the UTC offset of the timezone changes.
168
- #
169
- # Transitions are returned up to a given date and time up to a given date
170
- # and time, specified in UTC (utc_to).
171
- #
172
- # A from date and time may also be supplied using the utc_from parameter
173
- # (also specified in UTC). If utc_from is not nil, only transitions from
174
- # that date and time onwards will be returned.
175
- #
176
- # Comparisons with utc_to are exclusive. Comparisons with utc_from are
177
- # inclusive. If a transition falls precisely on utc_to, it will be excluded.
178
- # If a transition falls on utc_from, it will be included.
179
- #
180
- # Transitions returned are ordered by when they occur, from earliest to
181
- # latest.
182
- #
183
- # utc_to and utc_from can be specified using either DateTime, Time or
184
- # integer timestamps (Time.to_i).
185
- #
186
- # If utc_from is specified and utc_to is not greater than utc_from, then
187
- # transitions_up_to raises an ArgumentError exception.
188
- def transitions_up_to(utc_to, utc_from = nil)
189
- utc_to = TimeOrDateTime.wrap(utc_to)
190
- utc_from = utc_from ? TimeOrDateTime.wrap(utc_from) : nil
191
-
192
- if utc_from && utc_to <= utc_from
193
- raise ArgumentError, 'utc_to must be greater than utc_from'
194
- end
195
-
196
- unless @transitions.empty?
197
- if utc_from
198
- from = transition_after_start(transition_index(utc_from.year, utc_from.mon))
199
-
200
- if from
201
- while from < @transitions.length && @transitions[from].at < utc_from
202
- from += 1
203
- end
204
-
205
- if from >= @transitions.length
206
- return []
207
- end
208
- else
209
- # utc_from is later than last transition.
210
- return []
211
- end
212
- else
213
- from = 0
214
- end
215
-
216
- to = transition_before_end(transition_index(utc_to.year, utc_to.mon))
217
-
218
- if to
219
- while to >= 0 && @transitions[to].at >= utc_to
220
- to -= 1
221
- end
222
-
223
- if to < 0
224
- return []
225
- end
226
- else
227
- # utc_to is earlier than first transition.
228
- return []
229
- end
230
-
231
- @transitions[from..to]
232
- else
233
- []
234
- end
235
- end
236
-
237
- private
238
- # Returns the index into the @transitions_index array for a given year
239
- # and month.
240
- def transition_index(year, month)
241
- index = (year - @start_year) * 2
242
- index += 1 if month > 6
243
- index -= 1 if @start_month > 6
244
- index
245
- end
246
-
247
- # Returns the index into @transitions of the first transition that occurs
248
- # on or after the start of the given index into @transitions_index.
249
- # Returns nil if there are no such transitions.
250
- def transition_after_start(index)
251
- if index >= @transitions_index.length
252
- nil
253
- else
254
- index = 0 if index < 0
255
- @transitions_index[index]
256
- end
257
- end
258
-
259
- # Returns the index into @transitions of the first transition that occurs
260
- # before the end of the given index into @transitions_index.
261
- # Returns nil if there are no such transitions.
262
- def transition_before_end(index)
263
- index = index + 1
264
-
265
- if index <= 0
266
- nil
267
- elsif index >= @transitions_index.length
268
- @transitions.length - 1
269
- else
270
- @transitions_index[index] - 1
271
- end
272
- end
273
- end
274
- end
@@ -1,325 +0,0 @@
1
- require 'date'
2
-
3
- module TZInfo
4
- # Base class for rules definining the transition between standard and daylight
5
- # savings time.
6
- class TransitionRule #:nodoc:
7
- # Returns the number of seconds after midnight local time on the day
8
- # identified by the rule at which the transition occurs. Can be negative to
9
- # denote a time on the prior day. Can be greater than or equal to 86,400 to
10
- # denote a time of the following day.
11
- attr_reader :transition_at
12
-
13
- # Initializes a new TransitionRule.
14
- def initialize(transition_at)
15
- raise ArgumentError, 'Invalid transition_at' unless transition_at.kind_of?(Integer)
16
- @transition_at = transition_at
17
- end
18
-
19
- # Calculates the UTC time of the transition from a given offset on a given
20
- # year.
21
- def at(offset, year)
22
- day = get_day(year)
23
- day.add_with_convert(@transition_at - offset.utc_total_offset)
24
- end
25
-
26
- # Determines if this TransitionRule is equal to another instance.
27
- def ==(r)
28
- r.kind_of?(TransitionRule) && @transition_at == r.transition_at
29
- end
30
- alias eql? ==
31
-
32
- # Returns a hash based on hash_args (defaulting to transition_at).
33
- def hash
34
- hash_args.hash
35
- end
36
-
37
- protected
38
-
39
- # Returns an Array of parameters that will influence the output of hash.
40
- def hash_args
41
- [@transition_at]
42
- end
43
-
44
- def new_time_or_datetime(year, month = 1, day = 1)
45
- result = if ((year >= 2039 || (year == 2038 && (month >= 2 || (month == 1 && day >= 20)))) && !RubyCoreSupport.time_supports_64bit) ||
46
- (year < 1970 && !RubyCoreSupport.time_supports_negative)
47
-
48
- # Time handles 29 February on a non-leap year as 1 March.
49
- # DateTime rejects. Advance manually.
50
- if month == 2 && day == 29 && !Date.gregorian_leap?(year)
51
- month = 3
52
- day = 1
53
- end
54
-
55
- RubyCoreSupport.datetime_new(year, month, day)
56
- else
57
- Time.utc(year, month, day)
58
- end
59
-
60
- TimeOrDateTime.wrap(result)
61
- end
62
- end
63
-
64
- # A base class for transition rules that activate based on an integer day of
65
- # the year.
66
- #
67
- # @private
68
- class DayOfYearTransitionRule < TransitionRule #:nodoc:
69
- # Initializes a new DayOfYearTransitionRule.
70
- def initialize(day, transition_at)
71
- super(transition_at)
72
- raise ArgumentError, 'Invalid day' unless day.kind_of?(Integer)
73
- @seconds = day * 86400
74
- end
75
-
76
- # Determines if this DayOfYearTransitionRule is equal to another instance.
77
- def ==(r)
78
- super(r) && r.kind_of?(DayOfYearTransitionRule) && @seconds == r.seconds
79
- end
80
- alias eql? ==
81
-
82
- protected
83
-
84
- # @return [Integer] the day multipled by the number of seconds in a day.
85
- attr_reader :seconds
86
-
87
- # Returns an Array of parameters that will influence the output of hash.
88
- def hash_args
89
- [@seconds] + super
90
- end
91
- end
92
-
93
- # Defines transitions that occur on the zero-based nth day of the year.
94
- #
95
- # Day 0 is 1 January.
96
- #
97
- # Leap days are counted. Day 59 will be 29 February on a leap year and 1 March
98
- # on a non-leap year. Day 365 will be 31 December on a leap year and 1 January
99
- # the following year on a non-leap year.
100
- #
101
- # @private
102
- class AbsoluteDayOfYearTransitionRule < DayOfYearTransitionRule #:nodoc:
103
- # Initializes a new AbsoluteDayOfYearTransitionRule.
104
- def initialize(day, transition_at = 0)
105
- super(day, transition_at)
106
- raise ArgumentError, 'Invalid day' unless day >= 0 && day <= 365
107
- end
108
-
109
- # Returns true if the day specified by this transition is the first in the
110
- # year (a day number of 0), otherwise false.
111
- def is_always_first_day_of_year?
112
- seconds == 0
113
- end
114
-
115
- # @returns false.
116
- def is_always_last_day_of_year?
117
- false
118
- end
119
-
120
- # Determines if this AbsoluteDayOfYearTransitionRule is equal to another
121
- # instance.
122
- def ==(r)
123
- super(r) && r.kind_of?(AbsoluteDayOfYearTransitionRule)
124
- end
125
- alias eql? ==
126
-
127
- protected
128
-
129
- # Returns a TimeOrDateTime representing midnight local time on the day
130
- # specified by the rule for the given offset and year.
131
- def get_day(year)
132
- new_time_or_datetime(year).add_with_convert(seconds)
133
- end
134
-
135
- # Returns an Array of parameters that will influence the output of hash.
136
- def hash_args
137
- [AbsoluteDayOfYearTransitionRule] + super
138
- end
139
- end
140
-
141
- # Defines transitions that occur on the one-based nth Julian day of the year.
142
- #
143
- # Leap days are not counted. Day 1 is 1 January. Day 60 is always 1 March.
144
- # Day 365 is always 31 December.
145
- #
146
- # @private
147
- class JulianDayOfYearTransitionRule < DayOfYearTransitionRule #:nodoc:
148
- # The 60 days in seconds.
149
- LEAP = 60 * 86400
150
-
151
- # The length of a non-leap year in seconds.
152
- YEAR = 365 * 86400
153
-
154
- # Initializes a new JulianDayOfYearTransitionRule.
155
- def initialize(day, transition_at = 0)
156
- super(day, transition_at)
157
- raise ArgumentError, 'Invalid day' unless day >= 1 && day <= 365
158
- end
159
-
160
- # Returns true if the day specified by this transition is the first in the
161
- # year (a day number of 1), otherwise false.
162
- def is_always_first_day_of_year?
163
- seconds == 86400
164
- end
165
-
166
- # Returns true if the day specified by this transition is the last in the
167
- # year (a day number of 365), otherwise false.
168
- def is_always_last_day_of_year?
169
- seconds == YEAR
170
- end
171
-
172
- # Determines if this JulianDayOfYearTransitionRule is equal to another
173
- # instance.
174
- def ==(r)
175
- super(r) && r.kind_of?(JulianDayOfYearTransitionRule)
176
- end
177
- alias eql? ==
178
-
179
- protected
180
-
181
- # Returns a TimeOrDateTime representing midnight local time on the day
182
- # specified by the rule for the given offset and year.
183
- def get_day(year)
184
- # Returns 1 March on non-leap years.
185
- leap = new_time_or_datetime(year, 2, 29)
186
- diff = seconds - LEAP
187
- diff += 86400 if diff >= 0 && leap.mday == 29
188
- leap.add_with_convert(diff)
189
- end
190
-
191
- # Returns an Array of parameters that will influence the output of hash.
192
- def hash_args
193
- [JulianDayOfYearTransitionRule] + super
194
- end
195
- end
196
-
197
- # A base class for rules that transition on a particular day of week of a
198
- # given week (subclasses specify which week of the month).
199
- #
200
- # @private
201
- class DayOfWeekTransitionRule < TransitionRule #:nodoc:
202
- # Initializes a new DayOfWeekTransitionRule.
203
- def initialize(month, day_of_week, transition_at)
204
- super(transition_at)
205
- raise ArgumentError, 'Invalid month' unless month.kind_of?(Integer) && month >= 1 && month <= 12
206
- raise ArgumentError, 'Invalid day_of_week' unless day_of_week.kind_of?(Integer) && day_of_week >= 0 && day_of_week <= 6
207
- @month = month
208
- @day_of_week = day_of_week
209
- end
210
-
211
- # Returns false.
212
- def is_always_first_day_of_year?
213
- false
214
- end
215
-
216
- # Returns false.
217
- def is_always_last_day_of_year?
218
- false
219
- end
220
-
221
- # Determines if this DayOfWeekTransitionRule is equal to another instance.
222
- def ==(r)
223
- super(r) && r.kind_of?(DayOfWeekTransitionRule) && @month == r.month && @day_of_week == r.day_of_week
224
- end
225
- alias eql? ==
226
-
227
- protected
228
-
229
- # Returns the month of the year (1 to 12).
230
- attr_reader :month
231
-
232
- # Returns the day of the week (0 to 6 for Sunday to Monday).
233
- attr_reader :day_of_week
234
-
235
- # Returns an Array of parameters that will influence the output of hash.
236
- def hash_args
237
- [@month, @day_of_week] + super
238
- end
239
- end
240
-
241
- # A rule that transitions on the nth occurrence of a particular day of week
242
- # of a calendar month.
243
- #
244
- # @private
245
- class DayOfMonthTransitionRule < DayOfWeekTransitionRule #:nodoc:
246
- # Initializes a new DayOfMonthTransitionRule.
247
- def initialize(month, week, day_of_week, transition_at = 0)
248
- super(month, day_of_week, transition_at)
249
- raise ArgumentError, 'Invalid week' unless week.kind_of?(Integer) && week >= 1 && week <= 4
250
- @offset_start = (week - 1) * 7 + 1
251
- end
252
-
253
- # Determines if this DayOfMonthTransitionRule is equal to another instance.
254
- def ==(r)
255
- super(r) && r.kind_of?(DayOfMonthTransitionRule) && @offset_start == r.offset_start
256
- end
257
- alias eql? ==
258
-
259
- protected
260
-
261
- # Returns the day the week starts on for a month starting on a Sunday.
262
- attr_reader :offset_start
263
-
264
- # Returns a TimeOrDateTime representing midnight local time on the day
265
- # specified by the rule for the given offset and year.
266
- def get_day(year)
267
- candidate = new_time_or_datetime(year, month, @offset_start)
268
- diff = day_of_week - candidate.wday
269
-
270
- if diff < 0
271
- candidate.add_with_convert((7 + diff) * 86400)
272
- elsif diff > 0
273
- candidate.add_with_convert(diff * 86400)
274
- else
275
- candidate
276
- end
277
- end
278
-
279
- # Returns an Array of parameters that will influence the output of hash.
280
- def hash_args
281
- [@offset_start] + super
282
- end
283
- end
284
-
285
- # A rule that transitions on the last occurrence of a particular day of week
286
- # of a calendar month.
287
- #
288
- # @private
289
- class LastDayOfMonthTransitionRule < DayOfWeekTransitionRule #:nodoc:
290
- # Initializes a new LastDayOfMonthTransitionRule.
291
- def initialize(month, day_of_week, transition_at = 0)
292
- super(month, day_of_week, transition_at)
293
- end
294
-
295
- # Determines if this LastDayOfMonthTransitionRule is equal to another
296
- # instance.
297
- def ==(r)
298
- super(r) && r.kind_of?(LastDayOfMonthTransitionRule)
299
- end
300
- alias eql? ==
301
-
302
- protected
303
-
304
- # Returns a TimeOrDateTime representing midnight local time on the day
305
- # specified by the rule for the given offset and year.
306
- def get_day(year)
307
- next_month = month + 1
308
- if next_month == 13
309
- year += 1
310
- next_month = 1
311
- end
312
-
313
- candidate = new_time_or_datetime(year, next_month).add_with_convert(-86400)
314
- diff = candidate.wday - day_of_week
315
-
316
- if diff < 0
317
- candidate - (diff + 7) * 86400
318
- elsif diff > 0
319
- candidate - diff * 86400
320
- else
321
- candidate
322
- end
323
- end
324
- end
325
- end
@@ -1,37 +0,0 @@
1
- module TZInfo
2
- # Represents information about a country returned by ZoneinfoDataSource.
3
- #
4
- # @private
5
- class ZoneinfoCountryInfo < CountryInfo #:nodoc:
6
- # Constructs a new CountryInfo with an ISO 3166 country code, name and
7
- # an array of CountryTimezones.
8
- def initialize(code, name, zones)
9
- super(code, name)
10
- @zones = zones.dup.freeze
11
- @zone_identifiers = nil
12
- end
13
-
14
- # Returns a frozen array of all the zone identifiers for the country ordered
15
- # geographically, most populous first.
16
- def zone_identifiers
17
- # Thread-safety: It is possible that the value of @zone_identifiers may be
18
- # calculated multiple times in concurrently executing threads. It is not
19
- # worth the overhead of locking to ensure that @zone_identifiers is only
20
- # calculated once.
21
-
22
- unless @zone_identifiers
23
- result = zones.collect {|zone| zone.identifier}.freeze
24
- return result if frozen?
25
- @zone_identifiers = result
26
- end
27
-
28
- @zone_identifiers
29
- end
30
-
31
- # Returns a frozen array of all the timezones for the for the country
32
- # ordered geographically, most populous first.
33
- def zones
34
- @zones
35
- end
36
- end
37
- end