tzinfo 1.2.11 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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,2149 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils')
4
- require 'tempfile'
5
-
6
- include TZInfo
7
-
8
- class TCZoneinfoTimezoneInfo < Minitest::Test
9
- class FakePosixTimeZoneParser
10
- def initialize(&block)
11
- @on_parse = block
12
- end
13
-
14
- def parse(tz_string)
15
- @on_parse.call(tz_string)
16
- end
17
- end
18
-
19
- begin
20
- Time.at(-2147483649)
21
- Time.at(2147483648)
22
- SUPPORTS_64BIT = true
23
- rescue RangeError
24
- SUPPORTS_64BIT = false
25
- end
26
-
27
- begin
28
- Time.at(-1)
29
- Time.at(-2147483648)
30
- SUPPORTS_NEGATIVE = true
31
- rescue ArgumentError
32
- SUPPORTS_NEGATIVE = false
33
- end
34
-
35
- def setup
36
- @expect_tz_string = nil
37
- @tz_parse_result = nil
38
- @posix_tz_parser = FakePosixTimeZoneParser.new do |tz_string|
39
- raise "Unexpected tz_string passed to PosixTimeZoneParser: #{tz_string}" unless tz_string == @expect_tz_string
40
- raise InvalidPosixTimeZone, 'FakePosixTimeZoneParser Failure.' if @tz_parse_result == :fail
41
- @tz_parse_result
42
- end
43
- end
44
-
45
- def assert_period(abbreviation, utc_offset, std_offset, dst, start_at, end_at, info)
46
- if start_at
47
- period = info.period_for_utc(start_at)
48
- elsif end_at
49
- period = info.period_for_utc(TimeOrDateTime.wrap(end_at).add_with_convert(-1).to_orig)
50
- else
51
- # no transitions, pick the epoch
52
- period = info.period_for_utc(Time.utc(1970, 1, 1))
53
- end
54
-
55
- assert_equal(abbreviation, period.abbreviation, 'abbreviation')
56
- assert_equal(utc_offset, period.utc_offset, 'utc_offset')
57
- assert_equal(std_offset, period.std_offset, 'std_offset')
58
- assert_equal(dst, period.dst?, 'dst')
59
-
60
- if start_at
61
- refute_nil(period.utc_start_time, 'utc_start_time')
62
- assert_equal(start_at, period.utc_start_time, 'utc_start_time')
63
- else
64
- assert_nil(period.utc_start_time, 'utc_start_time')
65
- end
66
-
67
- if end_at
68
- refute_nil(period.utc_end_time, 'utc_end_time')
69
- assert_equal(end_at, period.utc_end_time, 'utc_end_time')
70
- else
71
- assert_nil(period.utc_end_time, 'utc_end_time')
72
- end
73
- end
74
-
75
- def convert_times_to_i(items, key = :at)
76
- items.each do |item|
77
- if item[key].kind_of?(Time)
78
- item[key] = item[key].utc.to_i
79
- end
80
- end
81
- end
82
-
83
- def select_with_32bit_values(items, key = :at)
84
- items.select do |item|
85
- i = item[key]
86
- i >= -2147483648 && i <= 2147483647
87
- end
88
- end
89
-
90
- def pack_int64_network_order(values)
91
- values.collect {|value| [value >> 32, value & 0xFFFFFFFF]}.flatten.pack('NN' * values.length)
92
- end
93
-
94
- def pack_int64_signed_network_order(values)
95
- # Convert to the equivalent 64-bit unsigned integer with the same bit representation
96
- pack_int64_network_order(values.collect {|value| value < 0 ? value + 0x10000000000000000 : value})
97
- end
98
-
99
- def write_tzif(format, offsets, transitions, tz_string, leaps, options = {})
100
-
101
- # Options for testing malformed zoneinfo files.
102
- magic = options[:magic]
103
- section2_magic = options[:section2_magic]
104
- abbrev_separator = options[:abbrev_separator] || "\0"
105
- abbrev_offset_base = options[:abbrev_offset_base] || 0
106
- omit_tz_string_start_new_line = options[:omit_tz_string_start_new_line]
107
- omit_tz_string_end_new_line = options[:omit_tz_string_end_new_line]
108
-
109
- unless magic
110
- if format == 1
111
- magic = "TZif\0"
112
- elsif format >= 2
113
- magic = "TZif#{format}"
114
- else
115
- raise ArgumentError, 'Invalid format specified'
116
- end
117
- end
118
-
119
- if section2_magic.kind_of?(Proc)
120
- section2_magic = section2_magic.call(format)
121
- else
122
- section2_magic = magic unless section2_magic
123
- end
124
-
125
- convert_times_to_i(transitions)
126
- convert_times_to_i(leaps)
127
-
128
- abbrevs = offsets.collect {|o| o[:abbrev]}.uniq
129
-
130
- if abbrevs.length > 0
131
- abbrevs = abbrevs.collect {|a| a.encode('UTF-8')} if abbrevs.first.respond_to?(:encode)
132
-
133
- if abbrevs.first.respond_to?(:bytesize)
134
- abbrevs_length = abbrevs.inject(0) {|sum, a| sum + a.bytesize + abbrev_separator.bytesize}
135
- else
136
- abbrevs_length = abbrevs.inject(0) {|sum, a| sum + a.length + abbrev_separator.length}
137
- end
138
- else
139
- abbrevs_length = 0
140
- end
141
-
142
- b32_transitions = select_with_32bit_values(transitions)
143
- b32_leaps = select_with_32bit_values(leaps)
144
-
145
- Tempfile.open('tzinfo-test-zone') do |file|
146
- file.binmode
147
-
148
- file.write(
149
- [magic, offsets.length, offsets.length, leaps.length,
150
- b32_transitions.length, offsets.length, abbrevs_length].pack('a5 x15 NNNNNN'))
151
-
152
- unless b32_transitions.empty?
153
- file.write(b32_transitions.collect {|t| t[:at]}.pack('N' * b32_transitions.length))
154
- file.write(b32_transitions.collect {|t| t[:offset_index]}.pack('C' * b32_transitions.length))
155
- end
156
-
157
- offsets.each do |offset|
158
- index = abbrevs.index(offset[:abbrev])
159
- abbrev_offset = abbrev_offset_base
160
- 0.upto(index - 1) {|i| abbrev_offset += abbrevs[i].length + 1}
161
-
162
- file.write([offset[:gmtoff], offset[:isdst] ? 1 : 0, abbrev_offset].pack('NCC'))
163
- end
164
-
165
- abbrevs.each do |a|
166
- file.write(a)
167
- file.write(abbrev_separator)
168
- end
169
-
170
- b32_leaps.each do |leap|
171
- file.write([leap[:at], leap[:seconds]].pack('NN'))
172
- end
173
-
174
- unless offsets.empty?
175
- file.write("\0" * offsets.length * 2)
176
- end
177
-
178
- if format >= 2
179
- file.write(
180
- [section2_magic, offsets.length, offsets.length, leaps.length,
181
- transitions.length, offsets.length, abbrevs_length].pack('a5 x15 NNNNNN'))
182
-
183
- unless transitions.empty?
184
- file.write(pack_int64_signed_network_order(transitions.collect {|t| t[:at]}))
185
- file.write(transitions.collect {|t| t[:offset_index]}.pack('C' * transitions.length))
186
- end
187
-
188
- offsets.each do |offset|
189
- index = abbrevs.index(offset[:abbrev])
190
- abbrev_offset = abbrev_offset_base
191
- 0.upto(index - 1) {|i| abbrev_offset += abbrevs[i].length + 1}
192
-
193
- file.write([offset[:gmtoff], offset[:isdst] ? 1 : 0, abbrev_offset].pack('NCC'))
194
- end
195
-
196
- abbrevs.each do |a|
197
- file.write(a)
198
- file.write(abbrev_separator)
199
- end
200
-
201
- leaps.each do |leap|
202
- file.write(pack_int64_signed_network_order([leap[:at]]))
203
- file.write([leap[:seconds]].pack('N'))
204
- end
205
-
206
- unless offsets.empty?
207
- file.write("\0" * offsets.length * 2)
208
- end
209
-
210
- # Empty POSIX timezone string
211
- file.write("\n") unless omit_tz_string_start_new_line
212
- tz_string = tz_string.encode(Encoding::UTF_8) if tz_string.respond_to?(:encode)
213
- file.write(tz_string)
214
- file.write("\n") unless omit_tz_string_end_new_line
215
- end
216
-
217
- file.flush
218
-
219
- yield file.path
220
- end
221
- end
222
-
223
- def tzif_test(offsets, transitions, options = {}, &block)
224
- rules = options[:rules]
225
- tz_string = options[:tz_string] || (rules ? "TEST_TZ_STRING_#{rand(1000000)}" : '')
226
- leaps = options[:leaps] || []
227
- min_format = options[:min_format] || (tz_string.empty? ? 1 : 2)
228
-
229
- min_format.upto(3) do |format|
230
- write_tzif(format, offsets, transitions, tz_string, leaps, options) do |path|
231
- if format >= 2
232
- @tz_parse_result = rules
233
- @expect_tz_string = tz_string
234
- end
235
- begin
236
- yield path, format
237
- ensure
238
- @tz_parse_result = nil
239
- @expect_tz_string = nil
240
- end
241
- end
242
- end
243
- end
244
-
245
- def test_load
246
- offsets = [
247
- {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'},
248
- {:gmtoff => 3600, :isdst => false, :abbrev => 'XST'},
249
- {:gmtoff => 7200, :isdst => true, :abbrev => 'XDT'},
250
- {:gmtoff => 0, :isdst => false, :abbrev => 'XNST'}]
251
-
252
- transitions = [
253
- {:at => Time.utc(1971, 1, 2), :offset_index => 1},
254
- {:at => Time.utc(1980, 4, 22), :offset_index => 2},
255
- {:at => Time.utc(1980, 10, 21), :offset_index => 1},
256
- {:at => Time.utc(2000, 12, 31), :offset_index => 3}]
257
-
258
- tzif_test(offsets, transitions) do |path, format|
259
- info = ZoneinfoTimezoneInfo.new('Zone/One', path, @posix_tz_parser)
260
- assert_equal('Zone/One', info.identifier)
261
-
262
- assert_period(:LMT, 3542, 0, false, nil, Time.utc(1971, 1, 2), info)
263
- assert_period(:XST, 3600, 0, false, Time.utc(1971, 1, 2), Time.utc(1980, 4, 22), info)
264
- assert_period(:XDT, 3600, 3600, true, Time.utc(1980, 4, 22), Time.utc(1980, 10, 21), info)
265
- assert_period(:XST, 3600, 0, false, Time.utc(1980, 10, 21), Time.utc(2000, 12, 31), info)
266
- assert_period(:XNST, 0, 0, false, Time.utc(2000, 12, 31), nil, info)
267
- end
268
- end
269
-
270
- def test_load_negative_utc_offset
271
- offsets = [
272
- {:gmtoff => -12492, :isdst => false, :abbrev => 'LMT'},
273
- {:gmtoff => -12000, :isdst => false, :abbrev => 'XST'},
274
- {:gmtoff => -8400, :isdst => true, :abbrev => 'XDT'},
275
- {:gmtoff => -8400, :isdst => false, :abbrev => 'XNST'}]
276
-
277
- transitions = [
278
- {:at => Time.utc(1971, 7, 9, 3, 0, 0), :offset_index => 1},
279
- {:at => Time.utc(1972, 10, 12, 3, 0, 0), :offset_index => 2},
280
- {:at => Time.utc(1973, 4, 29, 3, 0, 0), :offset_index => 1},
281
- {:at => Time.utc(1992, 4, 1, 4, 30, 0), :offset_index => 3}]
282
-
283
- tzif_test(offsets, transitions) do |path, format|
284
- info = ZoneinfoTimezoneInfo.new('Zone/One', path, @posix_tz_parser)
285
- assert_equal('Zone/One', info.identifier)
286
-
287
- assert_period(:LMT, -12492, 0, false, nil, Time.utc(1971, 7, 9, 3, 0, 0), info)
288
- assert_period(:XST, -12000, 0, false, Time.utc(1971, 7, 9, 3, 0, 0), Time.utc(1972, 10, 12, 3, 0, 0), info)
289
- assert_period(:XDT, -12000, 3600, true, Time.utc(1972, 10, 12, 3, 0, 0), Time.utc(1973, 4, 29, 3, 0, 0), info)
290
- assert_period(:XST, -12000, 0, false, Time.utc(1973, 4, 29, 3, 0, 0), Time.utc(1992, 4, 1, 4, 30, 0), info)
291
- assert_period(:XNST, -8400, 0, false, Time.utc(1992, 4, 1, 4, 30, 0), nil, info)
292
- end
293
- end
294
-
295
- def test_load_dst_first
296
- offsets = [
297
- {:gmtoff => 7200, :isdst => true, :abbrev => 'XDT'},
298
- {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'},
299
- {:gmtoff => 3600, :isdst => false, :abbrev => 'XST'},
300
- {:gmtoff => 0, :isdst => false, :abbrev => 'XNST'}]
301
-
302
- transitions = [
303
- {:at => Time.utc(1979, 1, 2), :offset_index => 2},
304
- {:at => Time.utc(1980, 4, 22), :offset_index => 0},
305
- {:at => Time.utc(1980, 10, 21), :offset_index => 2},
306
- {:at => Time.utc(2000, 12, 31), :offset_index => 3}]
307
-
308
- tzif_test(offsets, transitions) do |path, format|
309
- info = ZoneinfoTimezoneInfo.new('Zone/Two', path, @posix_tz_parser)
310
- assert_equal('Zone/Two', info.identifier)
311
-
312
- assert_period(:LMT, 3542, 0, false, nil, Time.utc(1979, 1, 2), info)
313
- end
314
- end
315
-
316
- def test_load_no_transitions
317
- offsets = [{:gmtoff => -12094, :isdst => false, :abbrev => 'LT'}]
318
-
319
- tzif_test(offsets, []) do |path, format|
320
- info = ZoneinfoTimezoneInfo.new('Zone/three', path, @posix_tz_parser)
321
- assert_equal('Zone/three', info.identifier)
322
-
323
- assert_period(:LT, -12094, 0, false, nil, nil, info)
324
- end
325
- end
326
-
327
- def test_load_no_offsets
328
- offsets = []
329
- transitions = [{:at => Time.utc(2000, 12, 31), :offset_index => 0}]
330
-
331
- tzif_test(offsets, transitions) do |path, format|
332
- assert_raises(InvalidZoneinfoFile) do
333
- ZoneinfoTimezoneInfo.new('Zone', path, @posix_tz_parser)
334
- end
335
- end
336
- end
337
-
338
- def test_load_invalid_offset_index
339
- offsets = [{:gmtoff => -0, :isdst => false, :abbrev => 'LMT'}]
340
- transitions = [{:at => Time.utc(2000, 12, 31), :offset_index => 2}]
341
-
342
- tzif_test(offsets, transitions) do |path, format|
343
- assert_raises(InvalidZoneinfoFile) do
344
- ZoneinfoTimezoneInfo.new('Zone', path, @posix_tz_parser)
345
- end
346
- end
347
- end
348
-
349
- def test_load_with_leap_seconds
350
- offsets = [{:gmtoff => -0, :isdst => false, :abbrev => 'LMT'}]
351
- leaps = [{:at => Time.utc(1972,6,30,23,59,60), :seconds => 1}]
352
-
353
- tzif_test(offsets, [], :leaps => leaps) do |path, format|
354
- assert_raises(InvalidZoneinfoFile) do
355
- ZoneinfoTimezoneInfo.new('Zone', path, @posix_tz_parser)
356
- end
357
- end
358
- end
359
-
360
- def test_load_invalid_magic
361
- ['TZif4', 'tzif2', '12345'].each do |magic|
362
- offsets = [{:gmtoff => -12094, :isdst => false, :abbrev => 'LT'}]
363
-
364
- tzif_test(offsets, [], :magic => magic) do |path, format|
365
- assert_raises(InvalidZoneinfoFile) do
366
- ZoneinfoTimezoneInfo.new('Zone2', path, @posix_tz_parser)
367
- end
368
- end
369
- end
370
- end
371
-
372
- def test_load_invalid_section2_magic
373
- ['TZif4', 'tzif2', '12345'].each do |section2_magic|
374
- offsets = [{:gmtoff => -12094, :isdst => false, :abbrev => 'LT'}]
375
-
376
- tzif_test(offsets, [], :min_format => 2, :section2_magic => section2_magic) do |path, format|
377
- assert_raises(InvalidZoneinfoFile) do
378
- ZoneinfoTimezoneInfo.new('Zone4', path, @posix_tz_parser)
379
- end
380
- end
381
- end
382
- end
383
-
384
- def test_load_mismatched_section2_magic
385
- minus_one = Proc.new {|f| f == 2 ? "TZif\0" : "TZif#{f - 1}" }
386
- plus_one = Proc.new {|f| "TZif#{f + 1}" }
387
-
388
- [minus_one, plus_one].each do |section2_magic|
389
- offsets = [{:gmtoff => -12094, :isdst => false, :abbrev => 'LT'}]
390
-
391
- tzif_test(offsets, [], :min_format => 2, :section2_magic => section2_magic) do |path, format|
392
- assert_raises(InvalidZoneinfoFile) do
393
- ZoneinfoTimezoneInfo.new('Zone5', path, @posix_tz_parser)
394
- end
395
- end
396
- end
397
- end
398
-
399
- def test_load_invalid_format
400
- Tempfile.open('tzinfo-test-zone') do |file|
401
- file.write('Invalid')
402
- file.flush
403
-
404
- assert_raises(InvalidZoneinfoFile) do
405
- ZoneinfoTimezoneInfo.new('Zone3', file.path, @posix_tz_parser)
406
- end
407
- end
408
- end
409
-
410
- def test_load_missing_abbrev_null_termination
411
- offsets = [
412
- {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'},
413
- {:gmtoff => 3600, :isdst => false, :abbrev => 'XST'}]
414
-
415
- transitions = [
416
- {:at => Time.utc(2000, 1, 1), :offset_index => 1}]
417
-
418
- tzif_test(offsets, transitions, :abbrev_separator => '^') do |path, format|
419
- assert_raises(InvalidZoneinfoFile) do
420
- ZoneinfoTimezoneInfo.new('Zone', path, @posix_tz_parser)
421
- end
422
- end
423
- end
424
-
425
- def test_load_out_of_range_abbrev_offsets
426
- offsets = [
427
- {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'},
428
- {:gmtoff => 3600, :isdst => false, :abbrev => 'XST'}]
429
-
430
- transitions = [
431
- {:at => Time.utc(2000, 1, 1), :offset_index => 1}]
432
-
433
- tzif_test(offsets, transitions, :abbrev_offset_base => 8) do |path, format|
434
- assert_raises(InvalidZoneinfoFile) do
435
- ZoneinfoTimezoneInfo.new('Zone', path, @posix_tz_parser)
436
- end
437
- end
438
- end
439
-
440
- def test_load_before_epoch
441
- # Some platforms don't support negative timestamps for times before the
442
- # epoch. Check that they are returned when supported and skipped when not.
443
-
444
- # Note the last transition before the epoch (and within the 32-bit range) is
445
- # moved to the epoch on platforms that do not support negative timestamps.
446
-
447
- offsets = [
448
- {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'},
449
- {:gmtoff => 3600, :isdst => false, :abbrev => 'XST'},
450
- {:gmtoff => 7200, :isdst => true, :abbrev => 'XDT'},
451
- {:gmtoff => 0, :isdst => false, :abbrev => 'XNST'}]
452
-
453
- transitions = [
454
- {:at => -694224000, :offset_index => 1}, # Time.utc(1948, 1, 2)
455
- {:at => -21945600, :offset_index => 2}, # Time.utc(1969, 4, 22)
456
- {:at => Time.utc(1970, 10, 21), :offset_index => 1},
457
- {:at => Time.utc(2000, 12, 31), :offset_index => 3}]
458
-
459
- tzif_test(offsets, transitions) do |path, format|
460
- info = ZoneinfoTimezoneInfo.new('Zone/Negative', path, @posix_tz_parser)
461
- assert_equal('Zone/Negative', info.identifier)
462
-
463
- if SUPPORTS_NEGATIVE
464
- assert_period(:LMT, 3542, 0, false, nil, Time.utc(1948, 1, 2), info)
465
- assert_period(:XST, 3600, 0, false, Time.utc(1948, 1, 2), Time.utc(1969, 4, 22), info)
466
- assert_period(:XDT, 3600, 3600, true, Time.utc(1969, 4, 22), Time.utc(1970, 10, 21), info)
467
- else
468
- assert_period(:LMT, 3542, 0, false, nil, Time.utc(1970, 1, 1), info)
469
- assert_period(:XDT, 3600, 3600, true, Time.utc(1970, 1, 1), Time.utc(1970, 10, 21), info)
470
- end
471
-
472
- assert_period(:XST, 3600, 0, false, Time.utc(1970, 10, 21), Time.utc(2000, 12, 31), info)
473
- assert_period(:XNST, 0, 0, false, Time.utc(2000, 12, 31), nil, info)
474
- end
475
- end
476
-
477
- def test_load_on_epoch
478
- offsets = [
479
- {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'},
480
- {:gmtoff => 3600, :isdst => false, :abbrev => 'XST'},
481
- {:gmtoff => 7200, :isdst => true, :abbrev => 'XDT'},
482
- {:gmtoff => 0, :isdst => false, :abbrev => 'XNST'}]
483
-
484
- transitions = [
485
- {:at => -694224000, :offset_index => 1}, # Time.utc(1948, 1, 2)
486
- {:at => -21945600, :offset_index => 2}, # Time.utc(1969, 4, 22)
487
- {:at => Time.utc(1970, 1, 1), :offset_index => 1},
488
- {:at => Time.utc(2000, 12, 31), :offset_index => 3}]
489
-
490
- tzif_test(offsets, transitions) do |path, format|
491
- info = ZoneinfoTimezoneInfo.new('Zone/Negative', path, @posix_tz_parser)
492
- assert_equal('Zone/Negative', info.identifier)
493
-
494
- if SUPPORTS_NEGATIVE
495
- assert_period(:LMT, 3542, 0, false, nil, Time.utc(1948, 1, 2), info)
496
- assert_period(:XST, 3600, 0, false, Time.utc(1948, 1, 2), Time.utc(1969, 4, 22), info)
497
- assert_period(:XDT, 3600, 3600, true, Time.utc(1969, 4, 22), Time.utc(1970, 1, 1), info)
498
- else
499
- assert_period(:LMT, 3542, 0, false, nil, Time.utc(1970, 1, 1), info)
500
- end
501
-
502
- assert_period(:XST, 3600, 0, false, Time.utc(1970, 1, 1), Time.utc(2000, 12, 31), info)
503
- assert_period(:XNST, 0, 0, false, Time.utc(2000, 12, 31), nil, info)
504
- end
505
- end
506
-
507
- def test_load_64bit
508
- # The TZif version2 and later format contains both 32-bit and 64-bit
509
- # sections. The 64-bit section is always used.
510
- #
511
- # Negative transitions before the supported range are moved to the start of
512
- # the supported range.
513
- #
514
- # Transitions after 2**31 - 1 are discarded if 64-bit times aren't
515
- # supported.
516
-
517
- offsets = [
518
- {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'},
519
- {:gmtoff => 3600, :isdst => false, :abbrev => 'XST'},
520
- {:gmtoff => 7200, :isdst => true, :abbrev => 'XDT'},
521
- {:gmtoff => 0, :isdst => false, :abbrev => 'XNST'}]
522
-
523
- transitions = [
524
- {:at => -3786739200, :offset_index => 1}, # Time.utc(1850, 1, 2)
525
- {:at => Time.utc(2003, 4, 22), :offset_index => 2},
526
- {:at => Time.utc(2003, 10, 21), :offset_index => 1},
527
- {:at => 2240524800, :offset_index => 3}] # Time.utc(2040, 12, 31)
528
-
529
- tzif_test(offsets, transitions) do |path, format|
530
- info = ZoneinfoTimezoneInfo.new('Zone/SixtyFour', path, @posix_tz_parser)
531
- assert_equal('Zone/SixtyFour', info.identifier)
532
-
533
- if SUPPORTS_64BIT && SUPPORTS_NEGATIVE && format >= 2
534
- assert_period(:LMT, 3542, 0, false, nil, Time.utc(1850, 1, 2), info)
535
- assert_period(:XST, 3600, 0, false, Time.utc(1850, 1, 2), Time.utc(2003, 4, 22), info)
536
- assert_period(:XDT, 3600, 3600, true, Time.utc(2003, 4, 22), Time.utc(2003, 10, 21), info)
537
- assert_period(:XST, 3600, 0, false, Time.utc(2003, 10, 21), Time.utc(2040, 12, 31), info)
538
- assert_period(:XNST, 0, 0, false, Time.utc(2040, 12, 31), nil, info)
539
- elsif format < 2
540
- assert_period(:LMT, 3542, 0, false, nil, Time.utc(2003, 4, 22), info)
541
- assert_period(:XDT, 3600, 3600, true, Time.utc(2003, 4, 22), Time.utc(2003, 10, 21), info)
542
- assert_period(:XST, 3600, 0, false, Time.utc(2003, 10, 21), nil, info)
543
- else
544
- min_supported = SUPPORTS_NEGATIVE ? -2**31 : 0
545
- assert_period(:LMT, 3542, 0, false, nil, Time.at(min_supported).utc, info)
546
- assert_period(:XST, 3600, 0, false, Time.at(min_supported).utc, Time.utc(2003, 4, 22), info)
547
- assert_period(:XDT, 3600, 3600, true, Time.utc(2003, 4, 22), Time.utc(2003, 10, 21), info)
548
- assert_period(:XST, 3600, 0, false, Time.utc(2003, 10, 21), nil, info)
549
- end
550
- end
551
- end
552
-
553
- def test_load_64bit_range
554
- # The full range of 64 bit timestamps is not currently supported because of
555
- # the way transitions are indexed. The last transition before the earliest
556
- # supported time will be moved to that time if there isn't already a
557
- # transition at that time. Transitions after the latest supported time are
558
- # ignored.
559
-
560
- offsets = [
561
- {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'},
562
- {:gmtoff => 3600, :isdst => false, :abbrev => 'XST'},
563
- {:gmtoff => 7200, :isdst => false, :abbrev => 'XNST'}]
564
-
565
- transitions = [
566
- {:at => -2**63, :offset_index => 1},
567
- {:at => Time.utc(2014, 5, 27), :offset_index => 2},
568
- {:at => 2**63 - 1, :offset_index => 0}]
569
-
570
- tzif_test(offsets, transitions) do |path, format|
571
- info = ZoneinfoTimezoneInfo.new('Zone/SixtyFourRange', path, @posix_tz_parser)
572
- assert_equal('Zone/SixtyFourRange', info.identifier)
573
-
574
- if SUPPORTS_64BIT && format >= 2
575
- # When the full range is supported, the following periods will be defined:
576
- #assert_period(:LMT, 3542, 0, false, nil, Time.at(-2**63).utc, info)
577
- #assert_period(:XST, 3600, 0, false, Time.at(-2**63).utc, Time.utc(2014, 5, 27), info)
578
- #assert_period(:XNST, 7200, 0, false, Time.utc(2014, 5, 27), Time.at(2**63 - 1).utc, info)
579
- #assert_period(:LMT, 3542, 0, false, Time.at(2**63 - 1).utc, nil, info)
580
-
581
- # Without full range support, the following periods will be defined:
582
- assert_period(:LMT, 3542, 0, false, nil, Time.utc(1700, 1, 1), info)
583
- assert_period(:XST, 3600, 0, false, Time.utc(1700, 1, 1), Time.utc(2014, 5, 27), info)
584
- assert_period(:XNST, 7200, 0, false, Time.utc(2014, 5, 27), nil, info)
585
- elsif format < 2
586
- assert_period(:LMT, 3542, 0, false, nil, Time.utc(2014, 5, 27), info)
587
- assert_period(:XNST, 7200, 0, false, Time.utc(2014, 5, 27), nil, info)
588
- else
589
- min_supported = SUPPORTS_NEGATIVE ? -2**31 : 0
590
- assert_period(:LMT, 3542, 0, false, nil, Time.at(min_supported).utc, info)
591
- assert_period(:XST, 3600, 0, false, Time.at(min_supported).utc, Time.utc(2014, 5, 27), info)
592
- assert_period(:XNST, 7200, 0, false, Time.utc(2014, 5, 27), nil, info)
593
- end
594
- end
595
- end
596
-
597
- def test_load_64bit_range_transition_at_earliest_supported
598
- # The full range of 64 bit timestamps is not currently supported because of
599
- # the way transitions are indexed. The last transition before the earliest
600
- # supported time will be moved to that time if there isn't already a
601
- # transition at that time. Transitions after the latest supported time are
602
- # ignored.
603
-
604
- offsets = [
605
- {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'},
606
- {:gmtoff => 3600, :isdst => false, :abbrev => 'XST'},
607
- {:gmtoff => 3600, :isdst => false, :abbrev => 'XST2'},
608
- {:gmtoff => 7200, :isdst => false, :abbrev => 'XNST'}]
609
-
610
- transitions = [
611
- {:at => -2**63, :offset_index => 1},
612
- {:at => -8520336000, :offset_index => 2}, # Time.utc(1700, 1, 1).to_i
613
- {:at => Time.utc(2014, 5, 27), :offset_index => 3},
614
- {:at => 2**63 - 1, :offset_index => 0}]
615
-
616
- tzif_test(offsets, transitions) do |path, format|
617
- info = ZoneinfoTimezoneInfo.new('Zone/SixtyFourRange', path, @posix_tz_parser)
618
- assert_equal('Zone/SixtyFourRange', info.identifier)
619
-
620
- if SUPPORTS_64BIT && format >= 2
621
- # When the full range is supported, the following periods will be defined:
622
- #assert_period(:LMT, 3542, 0, false, nil, Time.at(-2**63).utc, info)
623
- #assert_period(:XST, 3600, 0, false, Time.at(-2**63).utc, Time.utc(2014, 5, 27), info)
624
- #assert_period(:XNST, 7200, 0, false, Time.utc(2014, 5, 27), Time.at(2**63 - 1).utc, info)
625
- #assert_period(:LMT, 3542, 0, false, Time.at(2**63 - 1).utc, nil, info)
626
-
627
- # Without full range support, the following periods will be defined:
628
- assert_period(:LMT, 3542, 0, false, nil, Time.utc(1700, 1, 1), info)
629
- assert_period(:XST2, 3600, 0, false, Time.utc(1700, 1, 1), Time.utc(2014, 5, 27), info)
630
- assert_period(:XNST, 7200, 0, false, Time.utc(2014, 5, 27), nil, info)
631
- elsif format < 2
632
- assert_period(:LMT, 3542, 0, false, nil, Time.utc(2014, 5, 27), info)
633
- assert_period(:XNST, 7200, 0, false, Time.utc(2014, 5, 27), nil, info)
634
- elsif SUPPORTS_NEGATIVE
635
- assert_period(:LMT, 3542, 0, false, nil, Time.at(-2**31).utc, info)
636
- assert_period(:XST, 3600, 0, false, Time.at(-2**31).utc, Time.utc(2014, 5, 27), info)
637
- assert_period(:XNST, 7200, 0, false, Time.utc(2014, 5, 27), nil, info)
638
- else
639
- assert_period(:LMT, 3542, 0, false, nil, Time.utc(1970, 1, 1), info)
640
- assert_period(:XST2, 3600, 0, false, Time.utc(1970, 1, 1), Time.utc(2014, 5, 27), info)
641
- assert_period(:XNST, 7200, 0, false, Time.utc(2014, 5, 27), nil, info)
642
- end
643
- end
644
- end
645
-
646
- def test_load_supported_64bit_range
647
- # The full range of 64 bit timestamps is not currently supported because of
648
- # the way transitions are indexed.
649
-
650
- min_timestamp = -8520336000 # Time.utc(1700, 1, 1).to_i
651
- max_timestamp = 16725225600 # Time.utc(2500, 1, 1).to_i
652
-
653
- offsets = [
654
- {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'},
655
- {:gmtoff => 3600, :isdst => false, :abbrev => 'XST'},
656
- {:gmtoff => 7200, :isdst => false, :abbrev => 'XNST'}]
657
-
658
- transitions = [
659
- {:at => min_timestamp, :offset_index => 1},
660
- {:at => Time.utc(2014, 5, 27), :offset_index => 2},
661
- {:at => max_timestamp - 1, :offset_index => 0}]
662
-
663
- tzif_test(offsets, transitions) do |path, format|
664
- info = ZoneinfoTimezoneInfo.new('Zone/SupportedSixtyFourRange', path, @posix_tz_parser)
665
- assert_equal('Zone/SupportedSixtyFourRange', info.identifier)
666
-
667
- if SUPPORTS_64BIT && format >= 2
668
- assert_period(:LMT, 3542, 0, false, nil, Time.at(min_timestamp).utc, info)
669
- assert_period(:XST, 3600, 0, false, Time.at(min_timestamp).utc, Time.utc(2014, 5, 27), info)
670
- assert_period(:XNST, 7200, 0, false, Time.utc(2014, 5, 27), Time.at(max_timestamp - 1).utc, info)
671
- assert_period(:LMT, 3542, 0, false, Time.at(max_timestamp - 1).utc, nil, info)
672
- elsif format < 2
673
- assert_period(:LMT, 3542, 0, false, nil, Time.utc(2014, 5, 27), info)
674
- assert_period(:XNST, 7200, 0, false, Time.utc(2014, 5, 27), nil, info)
675
- else
676
- min_supported = SUPPORTS_NEGATIVE ? -2**31 : 0
677
- assert_period(:LMT, 3542, 0, false, nil, Time.at(min_supported).utc, info)
678
- assert_period(:XST, 3600, 0, false, Time.at(min_supported).utc, Time.utc(2014, 5, 27), info)
679
- assert_period(:XNST, 7200, 0, false, Time.utc(2014, 5, 27), nil, info)
680
- end
681
- end
682
- end
683
-
684
- def test_load_32bit_range
685
- offsets = [
686
- {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'},
687
- {:gmtoff => 3600, :isdst => false, :abbrev => 'XST'},
688
- {:gmtoff => 7200, :isdst => false, :abbrev => 'XNST'}]
689
-
690
- transitions = [
691
- {:at => -2**31, :offset_index => 1},
692
- {:at => Time.utc(2014, 5, 27), :offset_index => 2},
693
- {:at => 2**31 - 1, :offset_index => 0}]
694
-
695
- tzif_test(offsets, transitions) do |path, format|
696
- info = ZoneinfoTimezoneInfo.new('Zone/ThirtyTwoRange', path, @posix_tz_parser)
697
- assert_equal('Zone/ThirtyTwoRange', info.identifier)
698
-
699
- min_supported = SUPPORTS_NEGATIVE ? -2**31 : 0
700
- assert_period(:LMT, 3542, 0, false, nil, Time.at(min_supported).utc, info)
701
- assert_period(:XST, 3600, 0, false, Time.at(min_supported).utc, Time.utc(2014, 5, 27), info)
702
- assert_period(:XNST, 7200, 0, false, Time.utc(2014, 5, 27), Time.at(2**31 - 1), info)
703
- assert_period(:LMT, 3542, 0, false, Time.at(2**31 - 1).utc, nil, info)
704
- end
705
- end
706
-
707
- def test_load_std_offset_changes
708
- # The zoneinfo files don't include the offset from standard time, so this
709
- # has to be derived by looking at changes in the total UTC offset.
710
-
711
- offsets = [
712
- {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'},
713
- {:gmtoff => 3600, :isdst => false, :abbrev => 'XST'},
714
- {:gmtoff => 7200, :isdst => true, :abbrev => 'XDT'},
715
- {:gmtoff => 10800, :isdst => true, :abbrev => 'XDDT'}]
716
-
717
- transitions = [
718
- {:at => Time.utc(2000, 1, 1), :offset_index => 1},
719
- {:at => Time.utc(2000, 2, 1), :offset_index => 2},
720
- {:at => Time.utc(2000, 3, 1), :offset_index => 3},
721
- {:at => Time.utc(2000, 4, 1), :offset_index => 1}]
722
-
723
- tzif_test(offsets, transitions) do |path, format|
724
- info = ZoneinfoTimezoneInfo.new('Zone/DoubleDaylight', path, @posix_tz_parser)
725
- assert_equal('Zone/DoubleDaylight', info.identifier)
726
-
727
- assert_period(:LMT, 3542, 0, false, nil, Time.utc(2000, 1, 1), info)
728
- assert_period(:XST, 3600, 0, false, Time.utc(2000, 1, 1), Time.utc(2000, 2, 1), info)
729
- assert_period(:XDT, 3600, 3600, true, Time.utc(2000, 2, 1), Time.utc(2000, 3, 1), info)
730
- assert_period(:XDDT, 3600, 7200, true, Time.utc(2000, 3, 1), Time.utc(2000, 4, 1), info)
731
- assert_period(:XST, 3600, 0, false, Time.utc(2000, 4, 1), nil, info)
732
- end
733
- end
734
-
735
- def test_load_std_offset_changes_jump_to_double_dst
736
- # The zoneinfo files don't include the offset from standard time, so this
737
- # has to be derived by looking at changes in the total UTC offset.
738
-
739
- offsets = [
740
- {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'},
741
- {:gmtoff => 3600, :isdst => false, :abbrev => 'XST'},
742
- {:gmtoff => 10800, :isdst => true, :abbrev => 'XDDT'}]
743
-
744
- transitions = [
745
- {:at => Time.utc(2000, 4, 1), :offset_index => 1},
746
- {:at => Time.utc(2000, 5, 1), :offset_index => 2},
747
- {:at => Time.utc(2000, 6, 1), :offset_index => 1}]
748
-
749
- tzif_test(offsets, transitions) do |path, format|
750
- info = ZoneinfoTimezoneInfo.new('Zone/DoubleDaylight', path, @posix_tz_parser)
751
- assert_equal('Zone/DoubleDaylight', info.identifier)
752
-
753
- assert_period(:LMT, 3542, 0, false, nil, Time.utc(2000, 4, 1), info)
754
- assert_period(:XST, 3600, 0, false, Time.utc(2000, 4, 1), Time.utc(2000, 5, 1), info)
755
- assert_period(:XDDT, 3600, 7200, true, Time.utc(2000, 5, 1), Time.utc(2000, 6, 1), info)
756
- assert_period(:XST, 3600, 0, false, Time.utc(2000, 6, 1), nil, info)
757
- end
758
- end
759
-
760
- def test_load_std_offset_changes_negative
761
- # The zoneinfo files don't include the offset from standard time, so this
762
- # has to be derived by looking at changes in the total UTC offset.
763
-
764
- offsets = [
765
- {:gmtoff => -10821, :isdst => false, :abbrev => 'LMT'},
766
- {:gmtoff => -10800, :isdst => false, :abbrev => 'XST'},
767
- {:gmtoff => -7200, :isdst => true, :abbrev => 'XDT'},
768
- {:gmtoff => -3600, :isdst => true, :abbrev => 'XDDT'}]
769
-
770
- transitions = [
771
- {:at => Time.utc(2000, 1, 1), :offset_index => 1},
772
- {:at => Time.utc(2000, 2, 1), :offset_index => 2},
773
- {:at => Time.utc(2000, 3, 1), :offset_index => 3},
774
- {:at => Time.utc(2000, 4, 1), :offset_index => 1},
775
- {:at => Time.utc(2000, 5, 1), :offset_index => 3},
776
- {:at => Time.utc(2000, 6, 1), :offset_index => 1}]
777
-
778
- tzif_test(offsets, transitions) do |path, format|
779
- info = ZoneinfoTimezoneInfo.new('Zone/DoubleDaylight', path, @posix_tz_parser)
780
- assert_equal('Zone/DoubleDaylight', info.identifier)
781
-
782
- assert_period(:LMT, -10821, 0, false, nil, Time.utc(2000, 1, 1), info)
783
- assert_period(:XST, -10800, 0, false, Time.utc(2000, 1, 1), Time.utc(2000, 2, 1), info)
784
- assert_period(:XDT, -10800, 3600, true, Time.utc(2000, 2, 1), Time.utc(2000, 3, 1), info)
785
- assert_period(:XDDT, -10800, 7200, true, Time.utc(2000, 3, 1), Time.utc(2000, 4, 1), info)
786
- assert_period(:XST, -10800, 0, false, Time.utc(2000, 4, 1), Time.utc(2000, 5, 1), info)
787
- assert_period(:XDDT, -10800, 7200, true, Time.utc(2000, 5, 1), Time.utc(2000, 6, 1), info)
788
- assert_period(:XST, -10800, 0, false, Time.utc(2000, 6, 1), nil, info)
789
- end
790
- end
791
-
792
- def test_load_starts_two_hour_std_offset
793
- # The zoneinfo files don't include the offset from standard time, so this
794
- # has to be derived by looking at changes in the total UTC offset.
795
-
796
- offsets = [
797
- {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'},
798
- {:gmtoff => 3600, :isdst => false, :abbrev => 'XST'},
799
- {:gmtoff => 7200, :isdst => true, :abbrev => 'XDT'},
800
- {:gmtoff => 10800, :isdst => true, :abbrev => 'XDDT'}]
801
-
802
- transitions = [
803
- {:at => Time.utc(2000, 1, 1), :offset_index => 3},
804
- {:at => Time.utc(2000, 2, 1), :offset_index => 2},
805
- {:at => Time.utc(2000, 3, 1), :offset_index => 1}]
806
-
807
- tzif_test(offsets, transitions) do |path, format|
808
- info = ZoneinfoTimezoneInfo.new('Zone/DoubleDaylight', path, @posix_tz_parser)
809
- assert_equal('Zone/DoubleDaylight', info.identifier)
810
-
811
- assert_period(:LMT, 3542, 0, false, nil, Time.utc(2000, 1, 1), info)
812
- assert_period(:XDDT, 3600, 7200, true, Time.utc(2000, 1, 1), Time.utc(2000, 2, 1), info)
813
- assert_period(:XDT, 3600, 3600, true, Time.utc(2000, 2, 1), Time.utc(2000, 3, 1), info)
814
- assert_period(:XST, 3600, 0, false, Time.utc(2000, 3, 1), nil, info)
815
- end
816
- end
817
-
818
- def test_load_starts_only_dst_transition_with_lmt
819
- # The zoneinfo files don't include the offset from standard time, so this
820
- # has to be derived by looking at changes in the total UTC offset.
821
-
822
- offsets = [
823
- {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'},
824
- {:gmtoff => 7200, :isdst => true, :abbrev => 'XDT'}]
825
-
826
- transitions = [{:at => Time.utc(2000, 1, 1), :offset_index => 1}]
827
-
828
- tzif_test(offsets, transitions) do |path, format|
829
- info = ZoneinfoTimezoneInfo.new('Zone/OnlyDST', path, @posix_tz_parser)
830
- assert_equal('Zone/OnlyDST', info.identifier)
831
-
832
- assert_period(:LMT, 3542, 0, false, nil, Time.utc(2000, 1, 1), info)
833
- assert_period(:XDT, 3542, 3658, true, Time.utc(2000, 1, 1), nil, info)
834
- end
835
- end
836
-
837
- def test_load_starts_only_dst_transition_without_lmt
838
- # The zoneinfo files don't include the offset from standard time, so this
839
- # has to be derived by looking at changes in the total UTC offset.
840
-
841
- offsets = [{:gmtoff => 7200, :isdst => true, :abbrev => 'XDT'}]
842
-
843
- transitions = [{:at => Time.utc(2000, 1, 1), :offset_index => 0}]
844
-
845
- tzif_test(offsets, transitions) do |path, format|
846
- info = ZoneinfoTimezoneInfo.new('Zone/OnlyDST', path, @posix_tz_parser)
847
- assert_equal('Zone/OnlyDST', info.identifier)
848
-
849
- assert_period(:XDT, 3600, 3600, true, nil, Time.utc(2000, 1, 1), info)
850
- assert_period(:XDT, 3600, 3600, true, Time.utc(2000, 1, 1), nil, info)
851
- end
852
- end
853
-
854
- def test_load_switch_to_dst_and_change_utc_offset
855
- # The zoneinfo files don't include the offset from standard time, so this
856
- # has to be derived by looking at changes in the total UTC offset.
857
-
858
- # Switch from non-DST to DST at the same time as moving the UTC offset
859
- # back an hour (i.e. wall clock time doesn't change).
860
-
861
- offsets = [
862
- {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'},
863
- {:gmtoff => 3600, :isdst => false, :abbrev => 'YST'},
864
- {:gmtoff => 3600, :isdst => true, :abbrev => 'XDT'}]
865
-
866
- transitions = [
867
- {:at => Time.utc(2000, 1, 1), :offset_index => 1},
868
- {:at => Time.utc(2000, 2, 1), :offset_index => 2}]
869
-
870
- tzif_test(offsets, transitions) do |path, format|
871
- info = ZoneinfoTimezoneInfo.new('Zone/DoubleDaylight', path, @posix_tz_parser)
872
- assert_equal('Zone/DoubleDaylight', info.identifier)
873
-
874
- assert_period(:LMT, 3542, 0, false, nil, Time.utc(2000, 1, 1), info)
875
- assert_period(:YST, 3600, 0, false, Time.utc(2000, 1, 1), Time.utc(2000, 2, 1), info)
876
- assert_period(:XDT, 0, 3600, true, Time.utc(2000, 2, 1), nil, info)
877
- end
878
- end
879
-
880
- def test_load_apia_international_dateline_change
881
- # The zoneinfo files don't include the offset from standard time, so this
882
- # has to be derived by looking at changes in the total UTC offset.
883
-
884
- # Pacific/Apia moved across the International Date Line whilst observing
885
- # daylight savings time.
886
-
887
- offsets = [
888
- {:gmtoff => 45184, :isdst => false, :abbrev => 'LMT'},
889
- {:gmtoff => -39600, :isdst => false, :abbrev => '-11'},
890
- {:gmtoff => -36000, :isdst => true, :abbrev => '-10'},
891
- {:gmtoff => 50400, :isdst => true, :abbrev => '+14'},
892
- {:gmtoff => 46800, :isdst => false, :abbrev => '+13'}]
893
-
894
- transitions = [
895
- {:at => Time.utc(2011, 4, 2, 14, 0, 0), :offset_index => 1},
896
- {:at => Time.utc(2011, 9, 24, 14, 0, 0), :offset_index => 2},
897
- {:at => Time.utc(2011, 12, 30, 10, 0, 0), :offset_index => 3},
898
- {:at => Time.utc(2012, 3, 31, 14, 0, 0), :offset_index => 4}]
899
-
900
- tzif_test(offsets, transitions) do |path, format|
901
- info = ZoneinfoTimezoneInfo.new('Test/Pacific/Apia', path, @posix_tz_parser)
902
- assert_equal('Test/Pacific/Apia', info.identifier)
903
-
904
- assert_period( :LMT, 45184, 0, false, nil, Time.utc(2011, 4, 2, 14, 0, 0), info)
905
- assert_period(:'-11', -39600, 0, false, Time.utc(2011, 4, 2, 14, 0, 0), Time.utc(2011, 9, 24, 14, 0, 0), info)
906
- assert_period(:'-10', -39600, 3600, true, Time.utc(2011, 9, 24, 14, 0, 0), Time.utc(2011, 12, 30, 10, 0, 0), info)
907
- assert_period(:'+14', 46800, 3600, true, Time.utc(2011, 12, 30, 10, 0, 0), Time.utc(2012, 3, 31, 14, 0, 0), info)
908
- assert_period(:'+13', 46800, 0, false, Time.utc(2012, 3, 31, 14, 0, 0), nil, info)
909
- end
910
- end
911
-
912
- def test_load_offset_split_for_different_utc_offset
913
- # The zoneinfo files don't include the offset from standard time, so this
914
- # has to be derived by looking at changes in the total UTC offset.
915
-
916
- offsets = [
917
- {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'},
918
- {:gmtoff => 3600, :isdst => false, :abbrev => 'XST1'},
919
- {:gmtoff => 7200, :isdst => false, :abbrev => 'XST2'},
920
- {:gmtoff => 10800, :isdst => true, :abbrev => 'XDT'}]
921
-
922
- transitions = [
923
- {:at => Time.utc(2000, 1, 1), :offset_index => 1},
924
- {:at => Time.utc(2000, 2, 1), :offset_index => 3},
925
- {:at => Time.utc(2000, 3, 1), :offset_index => 1},
926
- {:at => Time.utc(2000, 4, 1), :offset_index => 2},
927
- {:at => Time.utc(2000, 5, 1), :offset_index => 3},
928
- {:at => Time.utc(2000, 6, 1), :offset_index => 2},
929
- {:at => Time.utc(2000, 7, 1), :offset_index => 1},
930
- {:at => Time.utc(2000, 8, 1), :offset_index => 3},
931
- {:at => Time.utc(2000, 9, 1), :offset_index => 1},
932
- {:at => Time.utc(2000, 10, 1), :offset_index => 2},
933
- {:at => Time.utc(2000, 11, 1), :offset_index => 3},
934
- {:at => Time.utc(2000, 12, 1), :offset_index => 2}]
935
-
936
- # XDT will be split and defined according to its surrounding standard time
937
- # offsets.
938
-
939
- tzif_test(offsets, transitions) do |path, format|
940
- info = ZoneinfoTimezoneInfo.new('Zone/SplitUtcOffset', path, @posix_tz_parser)
941
- assert_equal('Zone/SplitUtcOffset', info.identifier)
942
-
943
- assert_period( :LMT, 3542, 0, false, nil, Time.utc(2000, 1, 1), info)
944
- assert_period(:XST1, 3600, 0, false, Time.utc(2000, 1, 1), Time.utc(2000, 2, 1), info)
945
- assert_period( :XDT, 3600, 7200, true, Time.utc(2000, 2, 1), Time.utc(2000, 3, 1), info)
946
- assert_period(:XST1, 3600, 0, false, Time.utc(2000, 3, 1), Time.utc(2000, 4, 1), info)
947
- assert_period(:XST2, 7200, 0, false, Time.utc(2000, 4, 1), Time.utc(2000, 5, 1), info)
948
- assert_period( :XDT, 7200, 3600, true, Time.utc(2000, 5, 1), Time.utc(2000, 6, 1), info)
949
- assert_period(:XST2, 7200, 0, false, Time.utc(2000, 6, 1), Time.utc(2000, 7, 1), info)
950
- assert_period(:XST1, 3600, 0, false, Time.utc(2000, 7, 1), Time.utc(2000, 8, 1), info)
951
- assert_period( :XDT, 3600, 7200, true, Time.utc(2000, 8, 1), Time.utc(2000, 9, 1), info)
952
- assert_period(:XST1, 3600, 0, false, Time.utc(2000, 9, 1), Time.utc(2000, 10, 1), info)
953
- assert_period(:XST2, 7200, 0, false, Time.utc(2000, 10, 1), Time.utc(2000, 11, 1), info)
954
- assert_period( :XDT, 7200, 3600, true, Time.utc(2000, 11, 1), Time.utc(2000, 12, 1), info)
955
- assert_period(:XST2, 7200, 0, false, Time.utc(2000, 12, 1), nil, info)
956
-
957
- 1.upto(6) do |i|
958
- assert_same(info.period_for_utc(Time.utc(2000, i, 1)).offset, info.period_for_utc(Time.utc(2000, i + 6, 1)).offset)
959
- end
960
- end
961
- end
962
-
963
- def test_load_offset_utc_offset_taken_from_minimum_difference_minimum_after
964
- # The zoneinfo files don't include the offset from standard time, so this
965
- # has to be derived by looking at changes in the total UTC offset.
966
-
967
- offsets = [
968
- {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'},
969
- {:gmtoff => 3600, :isdst => false, :abbrev => 'XST1'},
970
- {:gmtoff => 7200, :isdst => false, :abbrev => 'XST2'},
971
- {:gmtoff => 10800, :isdst => true, :abbrev => 'XDT'}]
972
-
973
- transitions = [
974
- {:at => Time.utc(2000, 1, 1), :offset_index => 1},
975
- {:at => Time.utc(2000, 2, 1), :offset_index => 3},
976
- {:at => Time.utc(2000, 3, 1), :offset_index => 2}]
977
-
978
- # XDT should use the closest utc_offset (7200) (and not an equivalent
979
- # utc_offset of 3600 and std_offset of 7200).
980
-
981
- tzif_test(offsets, transitions) do |path, format|
982
- info = ZoneinfoTimezoneInfo.new('Zone/MinimumUtcOffset', path, @posix_tz_parser)
983
- assert_equal('Zone/MinimumUtcOffset', info.identifier)
984
-
985
- assert_period( :LMT, 3542, 0, false, nil, Time.utc(2000, 1, 1), info)
986
- assert_period(:XST1, 3600, 0, false, Time.utc(2000, 1, 1), Time.utc(2000, 2, 1), info)
987
- assert_period( :XDT, 7200, 3600, true, Time.utc(2000, 2, 1), Time.utc(2000, 3, 1), info)
988
- assert_period(:XST2, 7200, 0, false, Time.utc(2000, 3, 1), nil, info)
989
- end
990
- end
991
-
992
- def test_load_offset_utc_offset_taken_from_minimum_difference_minimum_before
993
- # The zoneinfo files don't include the offset from standard time, so this
994
- # has to be derived by looking at changes in the total UTC offset.
995
-
996
- offsets = [
997
- {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'},
998
- {:gmtoff => 3600, :isdst => false, :abbrev => 'XST1'},
999
- {:gmtoff => 7200, :isdst => false, :abbrev => 'XST2'},
1000
- {:gmtoff => 10800, :isdst => true, :abbrev => 'XDT'}]
1001
-
1002
- transitions = [
1003
- {:at => Time.utc(2000, 1, 1), :offset_index => 2},
1004
- {:at => Time.utc(2000, 2, 1), :offset_index => 3},
1005
- {:at => Time.utc(2000, 3, 1), :offset_index => 1}]
1006
-
1007
- # XDT should use the closest utc_offset (7200) (and not an equivalent
1008
- # utc_offset of 3600 and std_offset of 7200).
1009
-
1010
- tzif_test(offsets, transitions) do |path, format|
1011
- info = ZoneinfoTimezoneInfo.new('Zone/MinimumUtcOffset', path, @posix_tz_parser)
1012
- assert_equal('Zone/MinimumUtcOffset', info.identifier)
1013
-
1014
- assert_period( :LMT, 3542, 0, false, nil, Time.utc(2000, 1, 1), info)
1015
- assert_period(:XST2, 7200, 0, false, Time.utc(2000, 1, 1), Time.utc(2000, 2, 1), info)
1016
- assert_period( :XDT, 7200, 3600, true, Time.utc(2000, 2, 1), Time.utc(2000, 3, 1), info)
1017
- assert_period(:XST1, 3600, 0, false, Time.utc(2000, 3, 1), nil, info)
1018
- end
1019
- end
1020
-
1021
- def test_load_offset_does_not_use_equal_utc_total_offset_equal_after
1022
- # The zoneinfo files don't include the offset from standard time, so this
1023
- # has to be derived by looking at changes in the total UTC offset.
1024
-
1025
- offsets = [
1026
- {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'},
1027
- {:gmtoff => 3600, :isdst => false, :abbrev => 'XST1'},
1028
- {:gmtoff => 7200, :isdst => false, :abbrev => 'XST2'},
1029
- {:gmtoff => 7200, :isdst => true, :abbrev => 'XDT'}]
1030
-
1031
- transitions = [
1032
- {:at => Time.utc(2000, 1, 1), :offset_index => 1},
1033
- {:at => Time.utc(2000, 2, 1), :offset_index => 3},
1034
- {:at => Time.utc(2000, 3, 1), :offset_index => 2}]
1035
-
1036
- # XDT will be based on the utc_offset of XST1 even though XST2 has an
1037
- # equivalent (or greater) utc_total_offset.
1038
-
1039
- tzif_test(offsets, transitions) do |path, format|
1040
- info = ZoneinfoTimezoneInfo.new('Zone/UtcOffsetEqual', path, @posix_tz_parser)
1041
- assert_equal('Zone/UtcOffsetEqual', info.identifier)
1042
-
1043
- assert_period( :LMT, 3542, 0, false, nil, Time.utc(2000, 1, 1), info)
1044
- assert_period(:XST1, 3600, 0, false, Time.utc(2000, 1, 1), Time.utc(2000, 2, 1), info)
1045
- assert_period( :XDT, 3600, 3600, true, Time.utc(2000, 2, 1), Time.utc(2000, 3, 1), info)
1046
- assert_period(:XST2, 7200, 0, false, Time.utc(2000, 3, 1), nil, info)
1047
- end
1048
- end
1049
-
1050
- def test_load_offset_does_not_use_equal_utc_total_offset_equal_before
1051
- # The zoneinfo files don't include the offset from standard time, so this
1052
- # has to be derived by looking at changes in the total UTC offset.
1053
-
1054
- offsets = [
1055
- {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'},
1056
- {:gmtoff => 3600, :isdst => false, :abbrev => 'XST1'},
1057
- {:gmtoff => 7200, :isdst => false, :abbrev => 'XST2'},
1058
- {:gmtoff => 7200, :isdst => true, :abbrev => 'XDT'}]
1059
-
1060
- transitions = [
1061
- {:at => Time.utc(2000, 1, 1), :offset_index => 2},
1062
- {:at => Time.utc(2000, 2, 1), :offset_index => 3},
1063
- {:at => Time.utc(2000, 3, 1), :offset_index => 1}]
1064
-
1065
- # XDT will be based on the utc_offset of XST1 even though XST2 has an
1066
- # equivalent (or greater) utc_total_offset.
1067
-
1068
- tzif_test(offsets, transitions) do |path, format|
1069
- info = ZoneinfoTimezoneInfo.new('Zone/UtcOffsetEqual', path, @posix_tz_parser)
1070
- assert_equal('Zone/UtcOffsetEqual', info.identifier)
1071
-
1072
- assert_period( :LMT, 3542, 0, false, nil, Time.utc(2000, 1, 1), info)
1073
- assert_period(:XST2, 7200, 0, false, Time.utc(2000, 1, 1), Time.utc(2000, 2, 1), info)
1074
- assert_period( :XDT, 3600, 3600, true, Time.utc(2000, 2, 1), Time.utc(2000, 3, 1), info)
1075
- assert_period(:XST1, 3600, 0, false, Time.utc(2000, 3, 1), nil, info)
1076
- end
1077
- end
1078
-
1079
- def test_load_offset_both_adjacent_non_dst_equal_utc_total_offset
1080
- # The zoneinfo files don't include the offset from standard time, so this
1081
- # has to be derived by looking at changes in the total UTC offset.
1082
-
1083
- offsets = [
1084
- {:gmtoff => 7142, :isdst => false, :abbrev => 'LMT'},
1085
- {:gmtoff => 7200, :isdst => false, :abbrev => 'XST'},
1086
- {:gmtoff => 7200, :isdst => true, :abbrev => 'XDT'}]
1087
-
1088
- transitions = [
1089
- {:at => Time.utc(2000, 1, 1), :offset_index => 1},
1090
- {:at => Time.utc(2000, 2, 1), :offset_index => 2},
1091
- {:at => Time.utc(2000, 3, 1), :offset_index => 1}]
1092
-
1093
- # XDT will just assume an std_offset of +1 hour and calculate the utc_offset
1094
- # from utc_total_offset - std_offset.
1095
-
1096
- tzif_test(offsets, transitions) do |path, format|
1097
- info = ZoneinfoTimezoneInfo.new('Zone/AdjacentEqual', path, @posix_tz_parser)
1098
- assert_equal('Zone/AdjacentEqual', info.identifier)
1099
-
1100
- assert_period(:LMT, 7142, 0, false, nil, Time.utc(2000, 1, 1), info)
1101
- assert_period(:XST, 7200, 0, false, Time.utc(2000, 1, 1), Time.utc(2000, 2, 1), info)
1102
- assert_period(:XDT, 3600, 3600, true, Time.utc(2000, 2, 1), Time.utc(2000, 3, 1), info)
1103
- assert_period(:XST, 7200, 0, false, Time.utc(2000, 3, 1), nil, info)
1104
- end
1105
- end
1106
-
1107
- def test_load_offset_utc_offset_preserved_from_next
1108
- # The zoneinfo files don't include the offset from standard time, so this
1109
- # has to be derived by looking at changes in the total UTC offset.
1110
-
1111
- offsets = [
1112
- {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'},
1113
- {:gmtoff => 3600, :isdst => false, :abbrev => 'XST1'},
1114
- {:gmtoff => 7200, :isdst => false, :abbrev => 'XST2'},
1115
- {:gmtoff => 10800, :isdst => true, :abbrev => 'XDT1'},
1116
- {:gmtoff => 10800, :isdst => true, :abbrev => 'XDT2'}]
1117
-
1118
- transitions = [
1119
- {:at => Time.utc(2000, 1, 1), :offset_index => 1},
1120
- {:at => Time.utc(2000, 2, 1), :offset_index => 3},
1121
- {:at => Time.utc(2000, 3, 1), :offset_index => 4},
1122
- {:at => Time.utc(2000, 4, 1), :offset_index => 2}]
1123
-
1124
- # Both XDT1 and XDT2 should both use the closest utc_offset (7200) (and not
1125
- # an equivalent utc_offset of 3600 and std_offset of 7200).
1126
-
1127
- tzif_test(offsets, transitions) do |path, format|
1128
- info = ZoneinfoTimezoneInfo.new('Zone/UtcOffsetPreserved', path, @posix_tz_parser)
1129
- assert_equal('Zone/UtcOffsetPreserved', info.identifier)
1130
-
1131
- assert_period( :LMT, 3542, 0, false, nil, Time.utc(2000, 1, 1), info)
1132
- assert_period(:XST1, 3600, 0, false, Time.utc(2000, 1, 1), Time.utc(2000, 2, 1), info)
1133
- assert_period(:XDT1, 7200, 3600, true, Time.utc(2000, 2, 1), Time.utc(2000, 3, 1), info)
1134
- assert_period(:XDT2, 7200, 3600, true, Time.utc(2000, 3, 1), Time.utc(2000, 4, 1), info)
1135
- assert_period(:XST2, 7200, 0, false, Time.utc(2000, 4, 1), nil, info)
1136
- end
1137
- end
1138
-
1139
- def test_load_offset_utc_offset_preserved_from_previous
1140
- # The zoneinfo files don't include the offset from standard time, so this
1141
- # has to be derived by looking at changes in the total UTC offset.
1142
-
1143
- offsets = [
1144
- {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'},
1145
- {:gmtoff => 3600, :isdst => false, :abbrev => 'XST1'},
1146
- {:gmtoff => 7200, :isdst => false, :abbrev => 'XST2'},
1147
- {:gmtoff => 10800, :isdst => true, :abbrev => 'XDT1'},
1148
- {:gmtoff => 10800, :isdst => true, :abbrev => 'XDT2'}]
1149
-
1150
- transitions = [
1151
- {:at => Time.utc(2000, 1, 1), :offset_index => 2},
1152
- {:at => Time.utc(2000, 2, 1), :offset_index => 3},
1153
- {:at => Time.utc(2000, 3, 1), :offset_index => 4},
1154
- {:at => Time.utc(2000, 4, 1), :offset_index => 1}]
1155
-
1156
- # Both XDT1 and XDT2 should both use the closest utc_offset (7200) (and not
1157
- # an equivalent utc_offset of 3600 and std_offset of 7200).
1158
-
1159
- tzif_test(offsets, transitions) do |path, format|
1160
- info = ZoneinfoTimezoneInfo.new('Zone/UtcOffsetPreserved', path, @posix_tz_parser)
1161
- assert_equal('Zone/UtcOffsetPreserved', info.identifier)
1162
-
1163
- assert_period( :LMT, 3542, 0, false, nil, Time.utc(2000, 1, 1), info)
1164
- assert_period(:XST2, 7200, 0, false, Time.utc(2000, 1, 1), Time.utc(2000, 2, 1), info)
1165
- assert_period(:XDT1, 7200, 3600, true, Time.utc(2000, 2, 1), Time.utc(2000, 3, 1), info)
1166
- assert_period(:XDT2, 7200, 3600, true, Time.utc(2000, 3, 1), Time.utc(2000, 4, 1), info)
1167
- assert_period(:XST1, 3600, 0, false, Time.utc(2000, 4, 1), nil, info)
1168
- end
1169
- end
1170
-
1171
- def test_read_offset_negative_std_offset_dst
1172
- # The zoneinfo files don't include the offset from standard time, so this
1173
- # has to be derived by looking at changes in the total UTC offset.
1174
-
1175
- offsets = [
1176
- {:gmtoff => -100, :isdst => false, :abbrev => 'LMT'},
1177
- {:gmtoff => 3600, :isdst => false, :abbrev => 'XST'},
1178
- {:gmtoff => 0, :isdst => true, :abbrev => 'XWT'}]
1179
-
1180
- transitions = [
1181
- {:at => Time.utc(2000, 1, 1), :offset_index => 1},
1182
- {:at => Time.utc(2000, 2, 1), :offset_index => 2},
1183
- {:at => Time.utc(2000, 3, 1), :offset_index => 1},
1184
- {:at => Time.utc(2000, 4, 1), :offset_index => 2},
1185
- {:at => Time.utc(2000, 5, 1), :offset_index => 1}]
1186
-
1187
- tzif_test(offsets, transitions) do |path, format|
1188
- info = ZoneinfoTimezoneInfo.new('Zone/NegativeStdOffsetDst', path, @posix_tz_parser)
1189
- assert_equal('Zone/NegativeStdOffsetDst', info.identifier)
1190
-
1191
- assert_period(:LMT, -100, 0, false, nil, Time.utc(2000, 1, 1), info)
1192
- assert_period(:XST, 3600, 0, false, Time.utc(2000, 1, 1), Time.utc(2000, 2, 1), info)
1193
- assert_period(:XWT, 3600, -3600, true, Time.utc(2000, 2, 1), Time.utc(2000, 3, 1), info)
1194
- assert_period(:XST, 3600, 0, false, Time.utc(2000, 3, 1), Time.utc(2000, 4, 1), info)
1195
- assert_period(:XWT, 3600, -3600, true, Time.utc(2000, 4, 1), Time.utc(2000, 5, 1), info)
1196
- assert_period(:XST, 3600, 0, false, Time.utc(2000, 5, 1), nil, info)
1197
- end
1198
- end
1199
-
1200
- def test_read_offset_negative_std_offset_dst_initial_dst
1201
- # The zoneinfo files don't include the offset from standard time, so this
1202
- # has to be derived by looking at changes in the total UTC offset.
1203
-
1204
- offsets = [
1205
- {:gmtoff => -100, :isdst => false, :abbrev => 'LMT'},
1206
- {:gmtoff => 0, :isdst => true, :abbrev => 'XWT'},
1207
- {:gmtoff => 3600, :isdst => false, :abbrev => 'XST'}]
1208
-
1209
- transitions = [
1210
- {:at => Time.utc(2000, 1, 1), :offset_index => 1},
1211
- {:at => Time.utc(2000, 2, 1), :offset_index => 2},
1212
- {:at => Time.utc(2000, 3, 1), :offset_index => 1},
1213
- {:at => Time.utc(2000, 4, 1), :offset_index => 2},
1214
- {:at => Time.utc(2000, 5, 1), :offset_index => 1}]
1215
-
1216
- tzif_test(offsets, transitions) do |path, format|
1217
- info = ZoneinfoTimezoneInfo.new('Zone/NegativeStdOffsetDstInitialDst', path, @posix_tz_parser)
1218
- assert_equal('Zone/NegativeStdOffsetDstInitialDst', info.identifier)
1219
-
1220
- assert_period(:LMT, -100, 0, false, nil, Time.utc(2000, 1, 1), info)
1221
- assert_period(:XWT, 3600, -3600, true, Time.utc(2000, 1, 1), Time.utc(2000, 2, 1), info)
1222
- assert_period(:XST, 3600, 0, false, Time.utc(2000, 2, 1), Time.utc(2000, 3, 1), info)
1223
- assert_period(:XWT, 3600, -3600, true, Time.utc(2000, 3, 1), Time.utc(2000, 4, 1), info)
1224
- assert_period(:XST, 3600, 0, false, Time.utc(2000, 4, 1), Time.utc(2000, 5, 1), info)
1225
- assert_period(:XWT, 3600, -3600, true, Time.utc(2000, 5, 1), nil, info)
1226
- end
1227
- end
1228
-
1229
- def test_read_offset_prefer_base_offset_moves_to_dst_not_hour
1230
- offsets = [
1231
- {:gmtoff => -100, :isdst => false, :abbrev => 'LMT'},
1232
- {:gmtoff => 0, :isdst => false, :abbrev => 'XST'},
1233
- {:gmtoff => 1800, :isdst => true, :abbrev => 'XDT'},
1234
- {:gmtoff => 1800, :isdst => false, :abbrev => 'XST'}]
1235
-
1236
- transitions = [
1237
- {:at => Time.utc(2000, 1, 1), :offset_index => 1},
1238
- {:at => Time.utc(2000, 2, 1), :offset_index => 2},
1239
- {:at => Time.utc(2000, 3, 1), :offset_index => 3}]
1240
-
1241
- tzif_test(offsets, transitions) do |path, format|
1242
- info = ZoneinfoTimezoneInfo.new('Zone/BaseOffsetMovesToDstNotHour', path, @posix_tz_parser)
1243
- assert_equal('Zone/BaseOffsetMovesToDstNotHour', info.identifier)
1244
-
1245
- assert_period(:LMT, -100, 0, false, nil, Time.utc(2000, 1, 1), info)
1246
- assert_period(:XST, 0, 0, false, Time.utc(2000, 1, 1), Time.utc(2000, 2, 1), info)
1247
- assert_period(:XDT, 0, 1800, true, Time.utc(2000, 2, 1), Time.utc(2000, 3, 1), info)
1248
- assert_period(:XST, 1800, 0, false, Time.utc(2000, 3, 1), nil, info)
1249
- end
1250
- end
1251
-
1252
- def test_read_offset_prefer_base_offset_moves_from_dst_not_hour
1253
- offsets = [
1254
- {:gmtoff => -100, :isdst => false, :abbrev => 'LMT'},
1255
- {:gmtoff => 1800, :isdst => false, :abbrev => 'XST'},
1256
- {:gmtoff => 1800, :isdst => true, :abbrev => 'XDT'},
1257
- {:gmtoff => 0, :isdst => false, :abbrev => 'XST'}]
1258
-
1259
- transitions = [
1260
- {:at => Time.utc(2000, 1, 1), :offset_index => 1},
1261
- {:at => Time.utc(2000, 2, 1), :offset_index => 2},
1262
- {:at => Time.utc(2000, 3, 1), :offset_index => 3}]
1263
-
1264
- tzif_test(offsets, transitions) do |path, format|
1265
- info = ZoneinfoTimezoneInfo.new('Zone/BaseOffsetMovesFromDstNotHour', path, @posix_tz_parser)
1266
- assert_equal('Zone/BaseOffsetMovesFromDstNotHour', info.identifier)
1267
-
1268
- assert_period(:LMT, -100, 0, false, nil, Time.utc(2000, 1, 1), info)
1269
- assert_period(:XST, 1800, 0, false, Time.utc(2000, 1, 1), Time.utc(2000, 2, 1), info)
1270
- assert_period(:XDT, 0, 1800, true, Time.utc(2000, 2, 1), Time.utc(2000, 3, 1), info)
1271
- assert_period(:XST, 0, 0, false, Time.utc(2000, 3, 1), nil, info)
1272
- end
1273
- end
1274
-
1275
- def test_load_in_safe_mode
1276
- offsets = [{:gmtoff => -12094, :isdst => false, :abbrev => 'LT'}]
1277
-
1278
- tzif_test(offsets, []) do |path, format|
1279
- # untaint only required for Ruby 1.9.2
1280
- RubyCoreSupport.untaint(path)
1281
-
1282
- safe_test do
1283
- info = ZoneinfoTimezoneInfo.new('Zone/three', path, @posix_tz_parser)
1284
- assert_equal('Zone/three', info.identifier)
1285
-
1286
- assert_period(:LT, -12094, 0, false, nil, nil, info)
1287
- end
1288
- end
1289
- end
1290
-
1291
- def test_load_encoding
1292
- # tzfile.5 doesn't specify an encoding, but the source data is in ASCII.
1293
- # ZoneinfoTimezoneInfo will load as UTF-8 (a superset of ASCII).
1294
-
1295
- offsets = [
1296
- {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'},
1297
- {:gmtoff => 3600, :isdst => false, :abbrev => 'XST©'}]
1298
-
1299
- transitions = [
1300
- {:at => Time.utc(1971, 1, 2), :offset_index => 1}]
1301
-
1302
- tzif_test(offsets, transitions) do |path, format|
1303
- info = ZoneinfoTimezoneInfo.new('Zone/One', path, @posix_tz_parser)
1304
- assert_equal('Zone/One', info.identifier)
1305
-
1306
- assert_period(:LMT, 3542, 0, false, nil, Time.utc(1971, 1, 2), info)
1307
- assert_period(:"XST©", 3600, 0, false, Time.utc(1971, 1, 2), nil, info)
1308
- end
1309
- end
1310
-
1311
- def test_load_binmode
1312
- offsets = [
1313
- {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'},
1314
- {:gmtoff => 3600, :isdst => false, :abbrev => 'XST'}]
1315
-
1316
- # Transition time that includes CRLF (4EFF0D0A).
1317
- # Test that this doesn't get corrupted by translating CRLF to LF.
1318
- transitions = [
1319
- {:at => Time.utc(2011, 12, 31, 13, 24, 26), :offset_index => 1}]
1320
-
1321
- tzif_test(offsets, transitions) do |path, format|
1322
- info = ZoneinfoTimezoneInfo.new('Zone/One', path, @posix_tz_parser)
1323
- assert_equal('Zone/One', info.identifier)
1324
-
1325
- assert_period(:LMT, 3542, 0, false, nil, Time.utc(2011, 12, 31, 13, 24, 26), info)
1326
- assert_period(:XST, 3600, 0, false, Time.utc(2011, 12, 31, 13, 24, 26), nil, info)
1327
- end
1328
- end
1329
-
1330
- def test_load_invalid_tz_string
1331
- offsets = [{:gmtoff => 0, :isdst => false, :abbrev => 'UTC'}]
1332
-
1333
- tzif_test(offsets, [], :rules => :fail) do |path, format|
1334
- error = assert_raises(InvalidZoneinfoFile) { ZoneinfoTimezoneInfo.new('Invalid/String', path, @posix_tz_parser) }
1335
- assert_equal("Failed to parse POSIX-style TZ string in file '#{path}': FakePosixTimeZoneParser Failure.", error.message)
1336
- end
1337
- end
1338
-
1339
- def test_load_tz_string_missing_start_newline
1340
- offsets = [{:gmtoff => 0, :isdst => false, :abbrev => 'UTC'}]
1341
- rules = TimezoneOffset.new(0, 0, 'UTC')
1342
-
1343
- tzif_test(offsets, [], :rules => rules, :omit_tz_string_start_new_line => true) do |path, format|
1344
- error = assert_raises(InvalidZoneinfoFile) { ZoneinfoTimezoneInfo.new('Missing/Start', path, @posix_tz_parser) }
1345
- assert_equal("Expected newline starting POSIX-style TZ string in file '#{path}'.", error.message)
1346
- end
1347
- end
1348
-
1349
- def test_load_tz_string_missing_end_newline
1350
- offsets = [{:gmtoff => 0, :isdst => false, :abbrev => 'UTC'}]
1351
- rules = TimezoneOffset.new(0, 0, 'UTC')
1352
-
1353
- tzif_test(offsets, [], :rules => rules, :omit_tz_string_end_new_line => true) do |path, format|
1354
- error = assert_raises(InvalidZoneinfoFile) { ZoneinfoTimezoneInfo.new('Missing/End', path, @posix_tz_parser) }
1355
- assert_equal("Expected newline ending POSIX-style TZ string in file '#{path}'.", error.message)
1356
- end
1357
- end
1358
-
1359
- [
1360
- [false, 1, 0, 'TEST'],
1361
- [false, 0, 1, 'TEST'],
1362
- [false, 0, 0, 'TEST2'],
1363
- [false, -1, 1, 'TEST'],
1364
- [true, 0, 0, 'TEST']
1365
- ].each do |(isdst, base_utc_offset, std_offset, abbreviation)|
1366
- define_method "test_load_tz_string_does_not_match_#{isdst ? 'dst' : 'std'}_constant_offset_#{base_utc_offset}_#{std_offset}_#{abbreviation}" do
1367
- offsets = [{:gmtoff => 0, :isdst => isdst, :abbrev => 'TEST'}]
1368
- rules = TimezoneOffset.new(base_utc_offset, std_offset, abbreviation)
1369
-
1370
- tzif_test(offsets, [], :rules => rules) do |path, format|
1371
- error = assert_raises(InvalidZoneinfoFile) { ZoneinfoTimezoneInfo.new('Offset/Mismatch', path, @posix_tz_parser) }
1372
- assert_equal("Constant offset POSIX-style TZ string does not match constant offset in file '#{path}'.", error.message)
1373
- end
1374
- end
1375
- end
1376
-
1377
- [
1378
- [3601, 'XST'],
1379
- [3600, 'YST']
1380
- ].each do |(base_utc_offset, abbreviation)|
1381
- define_method "test_load_tz_string_does_not_match_final_std_transition_offset_#{base_utc_offset}_#{abbreviation}" do
1382
- offsets = [
1383
- {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'},
1384
- {:gmtoff => 3600, :isdst => false, :abbrev => 'XST'},
1385
- {:gmtoff => 7200, :isdst => true, :abbrev => 'XDT'}
1386
- ]
1387
-
1388
- transitions = [
1389
- {:at => Time.utc(1971, 1, 2, 2, 0, 0) - 3542, :offset_index => 1},
1390
- {:at => Time.utc(1981, 4, 10, 2, 0, 0) - 3600, :offset_index => 2},
1391
- {:at => Time.utc(1981, 10, 27, 2, 0, 0) - 7200, :offset_index => 1}
1392
- ]
1393
-
1394
- rules = AnnualRules.new(
1395
- TimezoneOffset.new(base_utc_offset, 0, abbreviation),
1396
- TimezoneOffset.new(3600, 3600, 'XDT'),
1397
- JulianDayOfYearTransitionRule.new(100, 7200),
1398
- JulianDayOfYearTransitionRule.new(300, 7200)
1399
- )
1400
-
1401
- tzif_test(offsets, transitions, :rules => rules) do |path, format|
1402
- error = assert_raises(InvalidZoneinfoFile) { ZoneinfoTimezoneInfo.new('Offset/Mismatch', path, @posix_tz_parser) }
1403
- assert_equal("The first offset indicated by the POSIX-style TZ string did not match the final defined offset in file '#{path}'.", error.message)
1404
- end
1405
- end
1406
- end
1407
-
1408
- [
1409
- [3601, 0, 'XST'],
1410
- [3600, 1, 'XST'],
1411
- [3600, 0, 'YST']
1412
- ].each do |(base_utc_offset, std_offset, abbreviation)|
1413
- define_method "test_load_tz_string_does_not_match_final_dst_transition_offset_#{base_utc_offset}_#{std_offset}_#{abbreviation}" do
1414
- offsets = [
1415
- {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'},
1416
- {:gmtoff => 3600, :isdst => false, :abbrev => 'XST'},
1417
- {:gmtoff => 7200, :isdst => true, :abbrev => 'XDT'}
1418
- ]
1419
-
1420
- transitions = [
1421
- {:at => Time.utc(1971, 1, 2, 2, 0, 0) - 3542, :offset_index => 1},
1422
- {:at => Time.utc(1981, 4, 10, 2, 0, 0) - 3600, :offset_index => 2}
1423
- ]
1424
-
1425
- rules = AnnualRules.new(
1426
- TimezoneOffset.new(3600, 0, 'XST'),
1427
- TimezoneOffset.new(base_utc_offset, std_offset, abbreviation),
1428
- JulianDayOfYearTransitionRule.new(100, 7200),
1429
- JulianDayOfYearTransitionRule.new(300, 7200)
1430
- )
1431
-
1432
- tzif_test(offsets, transitions, :rules => rules) do |path, format|
1433
- error = assert_raises(InvalidZoneinfoFile) { ZoneinfoTimezoneInfo.new('Offset/Mismatch', path, @posix_tz_parser) }
1434
- assert_equal("The first offset indicated by the POSIX-style TZ string did not match the final defined offset in file '#{path}'.", error.message)
1435
- end
1436
- end
1437
- end
1438
-
1439
- [
1440
- [3600, 0],
1441
- [3600, 3600],
1442
- [10800, -3600]
1443
- ].each do |(base_utc_offset, std_offset)|
1444
- rules = TimezoneOffset.new(base_utc_offset, std_offset, 'TEST')
1445
-
1446
- define_method "test_load_tz_string_uses_constant_offset_with_no_transitions_#{base_utc_offset}_#{std_offset}" do
1447
- offsets = [{:gmtoff => base_utc_offset + std_offset, :isdst => std_offset != 0, :abbrev => 'TEST'}]
1448
-
1449
- tzif_test(offsets, [], :rules => rules) do |path, format|
1450
- info = ZoneinfoTimezoneInfo.new('Constant/Offset', path, @posix_tz_parser)
1451
- assert_equal('Constant/Offset', info.identifier)
1452
- assert_period(:TEST, base_utc_offset, std_offset, std_offset != 0, nil, nil, info)
1453
- end
1454
- end
1455
-
1456
- define_method "test_load_tz_string_uses_constant_offset_after_last_transition_#{base_utc_offset}_#{std_offset}" do
1457
- offsets = [
1458
- {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'},
1459
- {:gmtoff => base_utc_offset + std_offset, :isdst => std_offset != 0, :abbrev => 'TEST'}
1460
- ]
1461
-
1462
- transitions = [
1463
- {:at => Time.utc(1971, 1, 2, 2, 0, 0) - 3542, :offset_index => 1}
1464
- ]
1465
-
1466
- t0 = Time.utc(1971, 1, 2, 2, 0, 0) - 3542
1467
-
1468
- tzif_test(offsets, transitions, :rules => rules) do |path, format|
1469
- info = ZoneinfoTimezoneInfo.new('Constant/After', path, @posix_tz_parser)
1470
- assert_equal('Constant/After', info.identifier)
1471
- assert_period(:LMT, 3542, 0, false, nil, t0, info)
1472
- assert_period(:TEST, base_utc_offset, std_offset, std_offset != 0, t0, nil, info)
1473
- end
1474
- end
1475
- end
1476
-
1477
- def test_load_tz_string_uses_rules_to_generate_all_transitions_when_none_defined
1478
- offsets = [{:gmtoff => 7200, :isdst => false, :abbrev => 'XST'}]
1479
-
1480
- rules = AnnualRules.new(
1481
- TimezoneOffset.new(7200, 0, 'XST'),
1482
- TimezoneOffset.new(7200, 3600, 'XDT'),
1483
- JulianDayOfYearTransitionRule.new(100, 3600),
1484
- JulianDayOfYearTransitionRule.new(300, 7200)
1485
- )
1486
-
1487
- generate_up_to = ZoneinfoTimezoneInfo::GENERATE_UP_TO
1488
-
1489
- tzif_test(offsets, [], :rules => rules) do |path, format|
1490
- info = ZoneinfoTimezoneInfo.new('All/Rules', path, @posix_tz_parser)
1491
- assert_equal('All/Rules', info.identifier)
1492
-
1493
- assert_period(:XST, 7200, 0, false, nil, Time.utc(1970, 4, 10, 1, 0, 0) - 7200, info)
1494
-
1495
- 1970.upto(generate_up_to - 1).each do |year|
1496
- assert_period(:XDT, 7200, 3600, true, Time.utc(year, 4, 10, 1, 0, 0) - 7200, Time.utc(year, 10, 27, 2, 0, 0) - 10800, info)
1497
- assert_period(:XST, 7200, 0, false, Time.utc(year, 10, 27, 2, 0, 0) - 10800, Time.utc(year + 1, 4, 10, 1, 0, 0) - 7200, info)
1498
- end
1499
-
1500
- assert_period(:XDT, 7200, 3600, true, Time.utc(generate_up_to, 4, 10, 1, 0, 0) - 7200, Time.utc(generate_up_to, 10, 27, 2, 0, 0) - 10800, info)
1501
- assert_period(:XST, 7200, 0, false, Time.utc(generate_up_to, 10, 27, 2, 0, 0) - 10800, nil, info)
1502
- end
1503
- end
1504
-
1505
- def test_load_tz_string_uses_rules_to_generate_all_transitions_when_none_defined_omitting_first_if_matches_first_offset
1506
- offsets = [{:gmtoff => 10800, :isdst => true, :abbrev => 'XDT'}]
1507
-
1508
- rules = AnnualRules.new(
1509
- TimezoneOffset.new(7200, 0, 'XST'),
1510
- TimezoneOffset.new(7200, 3600, 'XDT'),
1511
- JulianDayOfYearTransitionRule.new(100, 3600),
1512
- JulianDayOfYearTransitionRule.new(300, 7200)
1513
- )
1514
-
1515
- generate_up_to = ZoneinfoTimezoneInfo::GENERATE_UP_TO
1516
-
1517
- tzif_test(offsets, [], :rules => rules) do |path, format|
1518
- info = ZoneinfoTimezoneInfo.new('All/Rules', path, @posix_tz_parser)
1519
- assert_equal('All/Rules', info.identifier)
1520
-
1521
- assert_period(:XDT, 7200, 3600, true, nil, Time.utc(1970, 10, 27, 2, 0, 0) - 10800, info)
1522
- assert_period(:XST, 7200, 0, false, Time.utc(1970, 10, 27, 2, 0, 0) - 10800, Time.utc(1971, 4, 10, 1, 0, 0) - 7200, info)
1523
-
1524
- 1971.upto(generate_up_to - 1).each do |year|
1525
- assert_period(:XDT, 7200, 3600, true, Time.utc(year, 4, 10, 1, 0, 0) - 7200, Time.utc(year, 10, 27, 2, 0, 0) - 10800, info)
1526
- assert_period(:XST, 7200, 0, false, Time.utc(year, 10, 27, 2, 0, 0) - 10800, Time.utc(year + 1, 4, 10, 1, 0, 0) - 7200, info)
1527
- end
1528
-
1529
- assert_period(:XDT, 7200, 3600, true, Time.utc(generate_up_to, 4, 10, 1, 0, 0) - 7200, Time.utc(generate_up_to, 10, 27, 2, 0, 0) - 10800, info)
1530
- assert_period(:XST, 7200, 0, false, Time.utc(generate_up_to, 10, 27, 2, 0, 0) - 10800, nil, info)
1531
- end
1532
- end
1533
-
1534
- def test_load_tz_string_uses_rules_to_generate_all_transitions_when_none_defined_with_previous_offset_of_first_matching_first_offset
1535
- offsets = [{:gmtoff => 7142, :isdst => false, :abbrev => 'LMT'}]
1536
-
1537
- rules = AnnualRules.new(
1538
- TimezoneOffset.new(7200, 0, 'XST'),
1539
- TimezoneOffset.new(7200, 3600, 'XDT'),
1540
- JulianDayOfYearTransitionRule.new(100, 3600),
1541
- JulianDayOfYearTransitionRule.new(300, 7200)
1542
- )
1543
-
1544
- generate_up_to = ZoneinfoTimezoneInfo::GENERATE_UP_TO
1545
-
1546
- tzif_test(offsets, [], :rules => rules) do |path, format|
1547
- info = ZoneinfoTimezoneInfo.new('All/Rules', path, @posix_tz_parser)
1548
- assert_equal('All/Rules', info.identifier)
1549
-
1550
- assert_period(:LMT, 7142, 0, false, nil, Time.utc(1970, 4, 10, 1, 0, 0) - 7200, info)
1551
-
1552
- 1970.upto(generate_up_to - 1).each do |year|
1553
- assert_period(:XDT, 7200, 3600, true, Time.utc(year, 4, 10, 1, 0, 0) - 7200, Time.utc(year, 10, 27, 2, 0, 0) - 10800, info)
1554
- assert_period(:XST, 7200, 0, false, Time.utc(year, 10, 27, 2, 0, 0) - 10800, Time.utc(year + 1, 4, 10, 1, 0, 0) - 7200, info)
1555
- end
1556
-
1557
- assert_period(:XDT, 7200, 3600, true, Time.utc(generate_up_to, 4, 10, 1, 0, 0) - 7200, Time.utc(generate_up_to, 10, 27, 2, 0, 0) - 10800, info)
1558
- assert_period(:XST, 7200, 0, false, Time.utc(generate_up_to, 10, 27, 2, 0, 0) - 10800, nil, info)
1559
- end
1560
- end
1561
-
1562
- def test_load_tz_string_uses_rules_to_generate_all_transitions_when_none_defined_correcting_initial_offset
1563
- offsets = [{:gmtoff => 10800, :isdst => true, :abbrev => 'XDDT'}]
1564
-
1565
- rules = AnnualRules.new(
1566
- TimezoneOffset.new(3600, 0, 'XST'),
1567
- TimezoneOffset.new(3600, 7200, 'XDDT'),
1568
- JulianDayOfYearTransitionRule.new(100, 3600),
1569
- JulianDayOfYearTransitionRule.new(300, 7200)
1570
- )
1571
-
1572
- generate_up_to = ZoneinfoTimezoneInfo::GENERATE_UP_TO
1573
-
1574
- tzif_test(offsets, [], :rules => rules) do |path, format|
1575
- info = ZoneinfoTimezoneInfo.new('All/Rules', path, @posix_tz_parser)
1576
- assert_equal('All/Rules', info.identifier)
1577
-
1578
- assert_period(:XDDT, 3600, 7200, true, nil, Time.utc(1970, 10, 27, 2, 0, 0) - 10800, info) # would be :XDT, 7200, 3600 otherwise
1579
- assert_period(:XST, 3600, 0, false, Time.utc(1970, 10, 27, 2, 0, 0) - 10800, Time.utc(1971, 4, 10, 1, 0, 0) - 3600, info)
1580
-
1581
- 1971.upto(generate_up_to - 1).each do |year|
1582
- assert_period(:XDDT, 3600, 7200, true, Time.utc(year, 4, 10, 1, 0, 0) - 3600, Time.utc(year, 10, 27, 2, 0, 0) - 10800, info)
1583
- assert_period(:XST, 3600, 0, false, Time.utc(year, 10, 27, 2, 0, 0) - 10800, Time.utc(year + 1, 4, 10, 1, 0, 0) - 3600, info)
1584
- end
1585
-
1586
- assert_period(:XDDT, 3600, 7200, true, Time.utc(generate_up_to, 4, 10, 1, 0, 0) - 3600, Time.utc(generate_up_to, 10, 27, 2, 0, 0) - 10800, info)
1587
- assert_period(:XST, 3600, 0, false, Time.utc(generate_up_to, 10, 27, 2, 0, 0) - 10800, nil, info)
1588
- end
1589
- end
1590
-
1591
- def test_load_tz_string_extends_transitions_starting_from_std_to_dst_following_year
1592
- offsets = [
1593
- {:gmtoff => 7142, :isdst => false, :abbrev => 'LMT'},
1594
- {:gmtoff => 7200, :isdst => false, :abbrev => 'XST'},
1595
- {:gmtoff => 10800, :isdst => true, :abbrev => 'XDT'}
1596
- ]
1597
-
1598
- transitions = [
1599
- {:at => Time.utc(1971, 1, 2, 2, 0, 0) - 7142, :offset_index => 1},
1600
- {:at => Time.utc(1981, 4, 10, 1, 0, 0) - 7200, :offset_index => 2},
1601
- {:at => Time.utc(1981, 10, 27, 2, 0, 0) - 10800, :offset_index => 1}
1602
- ]
1603
-
1604
- rules = AnnualRules.new(
1605
- TimezoneOffset.new(7200, 0, 'XST'),
1606
- TimezoneOffset.new(7200, 3600, 'XDT'),
1607
- JulianDayOfYearTransitionRule.new(100, 3600),
1608
- JulianDayOfYearTransitionRule.new(300, 7200)
1609
- )
1610
-
1611
- generate_up_to = ZoneinfoTimezoneInfo::GENERATE_UP_TO
1612
-
1613
- tzif_test(offsets, transitions, :rules => rules) do |path, format|
1614
- info = ZoneinfoTimezoneInfo.new('From/Rules', path, @posix_tz_parser)
1615
- assert_equal('From/Rules', info.identifier)
1616
-
1617
- assert_period(:LMT, 7142, 0, false, nil, Time.utc(1971, 1, 2, 2, 0, 0) - 7142, info)
1618
- assert_period(:XST, 7200, 0, false, Time.utc(1971, 1, 2, 2, 0, 0) - 7142, Time.utc(1981, 4, 10, 1, 0, 0) - 7200, info)
1619
-
1620
- 1981.upto(generate_up_to - 1).each do |year|
1621
- assert_period(:XDT, 7200, 3600, true, Time.utc(year, 4, 10, 1, 0, 0) - 7200, Time.utc(year, 10, 27, 2, 0, 0) - 10800, info)
1622
- assert_period(:XST, 7200, 0, false, Time.utc(year, 10, 27, 2, 0, 0) - 10800, Time.utc(year + 1, 4, 10, 1, 0, 0) - 7200, info)
1623
- end
1624
-
1625
- assert_period(:XDT, 7200, 3600, true, Time.utc(generate_up_to, 4, 10, 1, 0, 0) - 7200, Time.utc(generate_up_to, 10, 27, 2, 0, 0) - 10800, info)
1626
- assert_period(:XST, 7200, 0, false, Time.utc(generate_up_to, 10, 27, 2, 0, 0) - 10800, nil, info)
1627
- end
1628
- end
1629
-
1630
- def test_load_tz_string_extends_transitions_starting_from_dst_to_std_same_year
1631
- offsets = [
1632
- {:gmtoff => 7142, :isdst => false, :abbrev => 'LMT'},
1633
- {:gmtoff => 7200, :isdst => false, :abbrev => 'XST'},
1634
- {:gmtoff => 10800, :isdst => true, :abbrev => 'XDT'}
1635
- ]
1636
-
1637
- transitions = [
1638
- {:at => Time.utc(1971, 1, 2, 2, 0, 0) - 7142, :offset_index => 1},
1639
- {:at => Time.utc(1981, 4, 10, 1, 0, 0) - 7200, :offset_index => 2},
1640
- {:at => Time.utc(1981, 10, 27, 2, 0, 0) - 10800, :offset_index => 1},
1641
- {:at => Time.utc(1982, 4, 10, 1, 0, 0) - 7200, :offset_index => 2}
1642
- ]
1643
-
1644
- rules = AnnualRules.new(
1645
- TimezoneOffset.new(7200, 0, 'XST'),
1646
- TimezoneOffset.new(7200, 3600, 'XDT'),
1647
- JulianDayOfYearTransitionRule.new(100, 3600),
1648
- JulianDayOfYearTransitionRule.new(300, 7200)
1649
- )
1650
-
1651
- generate_up_to = ZoneinfoTimezoneInfo::GENERATE_UP_TO
1652
-
1653
- tzif_test(offsets, transitions, :rules => rules) do |path, format|
1654
- info = ZoneinfoTimezoneInfo.new('From/Rules', path, @posix_tz_parser)
1655
- assert_equal('From/Rules', info.identifier)
1656
-
1657
- assert_period(:LMT, 7142, 0, false, nil, Time.utc(1971, 1, 2, 2, 0, 0) - 7142, info)
1658
- assert_period(:XST, 7200, 0, false, Time.utc(1971, 1, 2, 2, 0, 0) - 7142, Time.utc(1981, 4, 10, 1, 0, 0) - 7200, info)
1659
-
1660
- 1981.upto(generate_up_to - 1).each do |year|
1661
- assert_period(:XDT, 7200, 3600, true, Time.utc(year, 4, 10, 1, 0, 0) - 7200, Time.utc(year, 10, 27, 2, 0, 0) - 10800, info)
1662
- assert_period(:XST, 7200, 0, false, Time.utc(year, 10, 27, 2, 0, 0) - 10800, Time.utc(year + 1, 4, 10, 1, 0, 0) - 7200, info)
1663
- end
1664
-
1665
- assert_period(:XDT, 7200, 3600, true, Time.utc(generate_up_to, 4, 10, 1, 0, 0) - 7200, Time.utc(generate_up_to, 10, 27, 2, 0, 0) - 10800, info)
1666
- assert_period(:XST, 7200, 0, false, Time.utc(generate_up_to, 10, 27, 2, 0, 0) - 10800, nil, info)
1667
- end
1668
- end
1669
-
1670
- def test_load_tz_string_extends_transitions_starting_from_dst_to_std_following_year
1671
- offsets = [
1672
- {:gmtoff => 7142, :isdst => false, :abbrev => 'LMT'},
1673
- {:gmtoff => 7200, :isdst => false, :abbrev => 'XST'},
1674
- {:gmtoff => 10800, :isdst => true, :abbrev => 'XDT'}
1675
- ]
1676
-
1677
- transitions = [
1678
- {:at => Time.utc(1971, 1, 2, 1, 0, 0) - 7142, :offset_index => 1},
1679
- {:at => Time.utc(1981, 10, 27, 1, 0, 0) - 7200, :offset_index => 2},
1680
- {:at => Time.utc(1982, 4, 10, 2, 0, 0) - 10800, :offset_index => 1},
1681
- {:at => Time.utc(1982, 10, 27, 1, 0, 0) - 7200, :offset_index => 2}
1682
- ]
1683
-
1684
- rules = AnnualRules.new(
1685
- TimezoneOffset.new(7200, 0, 'XST'),
1686
- TimezoneOffset.new(7200, 3600, 'XDT'),
1687
- JulianDayOfYearTransitionRule.new(300, 3600),
1688
- JulianDayOfYearTransitionRule.new(100, 7200)
1689
- )
1690
-
1691
- generate_up_to = ZoneinfoTimezoneInfo::GENERATE_UP_TO
1692
-
1693
- tzif_test(offsets, transitions, :rules => rules) do |path, format|
1694
- info = ZoneinfoTimezoneInfo.new('From/Rules', path, @posix_tz_parser)
1695
- assert_equal('From/Rules', info.identifier)
1696
-
1697
- assert_period(:LMT, 7142, 0, false, nil, Time.utc(1971, 1, 2, 1, 0, 0) - 7142, info)
1698
- assert_period(:XST, 7200, 0, false, Time.utc(1971, 1, 2, 1, 0, 0) - 7142, Time.utc(1981, 10, 27, 1, 0, 0) - 7200, info)
1699
- assert_period(:XDT, 7200, 3600, true, Time.utc(1981, 10, 27, 1, 0, 0) - 7200, Time.utc(1982, 4, 10, 2, 0, 0) - 10800, info)
1700
-
1701
- 1982.upto(generate_up_to - 1).each do |year|
1702
- assert_period(:XST, 7200, 0, false, Time.utc(year, 4, 10, 1, 0, 0) - 7200, Time.utc(year, 10, 27, 2, 0, 0) - 10800, info)
1703
- assert_period(:XDT, 7200, 3600, true, Time.utc(year, 10, 27, 2, 0, 0) - 10800, Time.utc(year + 1, 4, 10, 1, 0, 0) - 7200, info)
1704
- end
1705
-
1706
- assert_period(:XST, 7200, 0, false, Time.utc(generate_up_to, 4, 10, 1, 0, 0) - 7200, Time.utc(generate_up_to, 10, 27, 2, 0, 0) - 10800, info)
1707
- assert_period(:XDT, 7200, 3600, true, Time.utc(generate_up_to, 10, 27, 2, 0, 0) - 10800, nil, info)
1708
- end
1709
- end
1710
-
1711
- def test_load_tz_string_extends_transitions_starting_from_std_to_dst_same_year
1712
- offsets = [
1713
- {:gmtoff => 7142, :isdst => false, :abbrev => 'LMT'},
1714
- {:gmtoff => 7200, :isdst => false, :abbrev => 'XST'},
1715
- {:gmtoff => 10800, :isdst => true, :abbrev => 'XDT'}
1716
- ]
1717
-
1718
- transitions = [
1719
- {:at => Time.utc(1971, 1, 2, 1, 0, 0) - 7142, :offset_index => 1},
1720
- {:at => Time.utc(1981, 10, 27, 1, 0, 0) - 7200, :offset_index => 2},
1721
- {:at => Time.utc(1982, 4, 10, 2, 0, 0) - 10800, :offset_index => 1},
1722
- {:at => Time.utc(1982, 10, 27, 1, 0, 0) - 7200, :offset_index => 2},
1723
- {:at => Time.utc(1983, 4, 10, 2, 0, 0) - 10800, :offset_index => 1}
1724
- ]
1725
-
1726
- rules = AnnualRules.new(
1727
- TimezoneOffset.new(7200, 0, 'XST'),
1728
- TimezoneOffset.new(7200, 3600, 'XDT'),
1729
- JulianDayOfYearTransitionRule.new(300, 3600),
1730
- JulianDayOfYearTransitionRule.new(100, 7200)
1731
- )
1732
-
1733
- generate_up_to = ZoneinfoTimezoneInfo::GENERATE_UP_TO
1734
-
1735
- tzif_test(offsets, transitions, :rules => rules) do |path, format|
1736
- info = ZoneinfoTimezoneInfo.new('From/Rules', path, @posix_tz_parser)
1737
- assert_equal('From/Rules', info.identifier)
1738
-
1739
- assert_period(:LMT, 7142, 0, false, nil, Time.utc(1971, 1, 2, 1, 0, 0) - 7142, info)
1740
- assert_period(:XST, 7200, 0, false, Time.utc(1971, 1, 2, 1, 0, 0) - 7142, Time.utc(1981, 10, 27, 1, 0, 0) - 7200, info)
1741
- assert_period(:XDT, 7200, 3600, true, Time.utc(1981, 10, 27, 1, 0, 0) - 7200, Time.utc(1982, 4, 10, 2, 0, 0) - 10800, info)
1742
-
1743
- 1982.upto(generate_up_to - 1).each do |year|
1744
- assert_period(:XST, 7200, 0, false, Time.utc(year, 4, 10, 1, 0, 0) - 7200, Time.utc(year, 10, 27, 2, 0, 0) - 10800, info)
1745
- assert_period(:XDT, 7200, 3600, true, Time.utc(year, 10, 27, 2, 0, 0) - 10800, Time.utc(year + 1, 4, 10, 1, 0, 0) - 7200, info)
1746
- end
1747
-
1748
- assert_period(:XST, 7200, 0, false, Time.utc(generate_up_to, 4, 10, 1, 0, 0) - 7200, Time.utc(generate_up_to, 10, 27, 2, 0, 0) - 10800, info)
1749
- assert_period(:XDT, 7200, 3600, true, Time.utc(generate_up_to, 10, 27, 2, 0, 0) - 10800, nil, info)
1750
- end
1751
- end
1752
-
1753
- def test_load_tz_string_extends_transitions_negative_dst
1754
- offsets = [
1755
- {:gmtoff => 7142, :isdst => false, :abbrev => 'LMT'},
1756
- {:gmtoff => 7200, :isdst => true, :abbrev => 'XDT'},
1757
- {:gmtoff => 10800, :isdst => false, :abbrev => 'XST'}
1758
- ]
1759
-
1760
- transitions = [
1761
- {:at => Time.utc(1971, 1, 2, 2, 0, 0) - 7142, :offset_index => 1},
1762
- {:at => Time.utc(1981, 4, 10, 1, 0, 0) - 7200, :offset_index => 2},
1763
- {:at => Time.utc(1981, 10, 27, 2, 0, 0) - 10800, :offset_index => 1}
1764
- ]
1765
-
1766
- rules = AnnualRules.new(
1767
- TimezoneOffset.new(10800, 0, 'XST'),
1768
- TimezoneOffset.new(10800, -3600, 'XDT'),
1769
- JulianDayOfYearTransitionRule.new(300, 7200),
1770
- JulianDayOfYearTransitionRule.new(100, 3600)
1771
- )
1772
-
1773
- generate_up_to = ZoneinfoTimezoneInfo::GENERATE_UP_TO
1774
-
1775
- tzif_test(offsets, transitions, :rules => rules) do |path, format|
1776
- info = ZoneinfoTimezoneInfo.new('From/Rules', path, @posix_tz_parser)
1777
- assert_equal('From/Rules', info.identifier)
1778
-
1779
- assert_period(:LMT, 7142, 0, false, nil, Time.utc(1971, 1, 2, 2, 0, 0) - 7142, info)
1780
- assert_period(:XDT, 10800, -3600, true, Time.utc(1971, 1, 2, 2, 0, 0) - 7142, Time.utc(1981, 4, 10, 1, 0, 0) - 7200, info)
1781
-
1782
- 1981.upto(generate_up_to - 1).each do |year|
1783
- assert_period(:XST, 10800, 0, false, Time.utc(year, 4, 10, 1, 0, 0) - 7200, Time.utc(year, 10, 27, 2, 0, 0) - 10800, info)
1784
- assert_period(:XDT, 10800, -3600, true, Time.utc(year, 10, 27, 2, 0, 0) - 10800, Time.utc(year + 1, 4, 10, 1, 0, 0) - 7200, info)
1785
- end
1786
-
1787
- assert_period(:XST, 10800, 0, false, Time.utc(generate_up_to, 4, 10, 1, 0, 0) - 7200, Time.utc(generate_up_to, 10, 27, 2, 0, 0) - 10800, info)
1788
- assert_period(:XDT, 10800, -3600, true, Time.utc(generate_up_to, 10, 27, 2, 0, 0) - 10800, nil, info)
1789
- end
1790
- end
1791
-
1792
- def test_load_tz_string_extends_single_transition_in_final_year
1793
- offsets = [
1794
- {:gmtoff => 7142, :isdst => false, :abbrev => 'LMT'},
1795
- {:gmtoff => 7200, :isdst => false, :abbrev => 'XST'},
1796
- {:gmtoff => 10800, :isdst => true, :abbrev => 'XDT'}
1797
- ]
1798
-
1799
- generate_up_to = ZoneinfoTimezoneInfo::GENERATE_UP_TO
1800
-
1801
- transitions = [
1802
- {:at => Time.utc( 1971, 1, 2, 2, 0, 0) - 7142, :offset_index => 1},
1803
- {:at => Time.utc(generate_up_to - 1, 4, 10, 1, 0, 0) - 7200, :offset_index => 2},
1804
- {:at => Time.utc(generate_up_to - 1, 10, 27, 2, 0, 0) - 10800, :offset_index => 1},
1805
- {:at => Time.utc(generate_up_to, 4, 10, 1, 0, 0) - 7200, :offset_index => 2}
1806
- ]
1807
-
1808
- rules = AnnualRules.new(
1809
- TimezoneOffset.new(7200, 0, 'XST'),
1810
- TimezoneOffset.new(7200, 3600, 'XDT'),
1811
- JulianDayOfYearTransitionRule.new(100, 3600),
1812
- JulianDayOfYearTransitionRule.new(300, 7200)
1813
- )
1814
-
1815
- tzif_test(offsets, transitions, :rules => rules) do |path, format|
1816
- info = ZoneinfoTimezoneInfo.new('Final/Year', path, @posix_tz_parser)
1817
- assert_equal('Final/Year', info.identifier)
1818
-
1819
- assert_period(:LMT, 7142, 0, false, nil, Time.utc( 1971, 1, 2, 2, 0, 0) - 7142, info)
1820
- assert_period(:XST, 7200, 0, false, Time.utc( 1971, 1, 2, 2, 0, 0) - 7142, Time.utc(generate_up_to - 1, 4, 10, 1, 0, 0) - 7200, info)
1821
- assert_period(:XDT, 7200, 3600, true, Time.utc(generate_up_to - 1, 4, 10, 1, 0, 0) - 7200, Time.utc(generate_up_to - 1, 10, 27, 2, 0, 0) - 10800, info)
1822
- assert_period(:XST, 7200, 0, false, Time.utc(generate_up_to - 1, 10, 27, 2, 0, 0) - 10800, Time.utc(generate_up_to, 4, 10, 1, 0, 0) - 7200, info)
1823
- assert_period(:XDT, 7200, 3600, true, Time.utc(generate_up_to, 4, 10, 1, 0, 0) - 7200, Time.utc(generate_up_to, 10, 27, 2, 0, 0) - 10800, info)
1824
- assert_period(:XST, 7200, 0, false, Time.utc(generate_up_to, 10, 27, 2, 0, 0) - 10800, nil, info)
1825
- end
1826
- end
1827
-
1828
- def test_load_tz_string_adds_nothing_if_transitions_up_to_final_year
1829
- offsets = [
1830
- {:gmtoff => 7142, :isdst => false, :abbrev => 'LMT'},
1831
- {:gmtoff => 7200, :isdst => false, :abbrev => 'XST'},
1832
- {:gmtoff => 10800, :isdst => true, :abbrev => 'XDT'}
1833
- ]
1834
-
1835
- generate_up_to = ZoneinfoTimezoneInfo::GENERATE_UP_TO
1836
-
1837
- transitions = [
1838
- {:at => Time.utc( 1971, 1, 2, 2, 0, 0) - 7142, :offset_index => 1},
1839
- {:at => Time.utc(generate_up_to, 4, 10, 1, 0, 0) - 7200, :offset_index => 2},
1840
- {:at => Time.utc(generate_up_to, 10, 27, 2, 0, 0) - 10800, :offset_index => 1},
1841
- ]
1842
-
1843
- rules = AnnualRules.new(
1844
- TimezoneOffset.new(7200, 0, 'XST'),
1845
- TimezoneOffset.new(7200, 3600, 'XDT'),
1846
- JulianDayOfYearTransitionRule.new(100, 3600),
1847
- JulianDayOfYearTransitionRule.new(300, 7200)
1848
- )
1849
-
1850
- tzif_test(offsets, transitions, :rules => rules) do |path, format|
1851
- info = ZoneinfoTimezoneInfo.new('Final/Year', path, @posix_tz_parser)
1852
- assert_equal('Final/Year', info.identifier)
1853
-
1854
- assert_period(:LMT, 7142, 0, false, nil, Time.utc( 1971, 1, 2, 2, 0, 0) - 7142, info)
1855
- assert_period(:XDT, 7200, 3600, true, Time.utc(generate_up_to, 4, 10, 1, 0, 0) - 7200, Time.utc(generate_up_to, 10, 27, 2, 0, 0) - 10800, info)
1856
- assert_period(:XST, 7200, 0, false, Time.utc(generate_up_to, 10, 27, 2, 0, 0) - 10800, nil, info)
1857
- end
1858
- end
1859
-
1860
- def test_load_tz_string_corrects_offset_of_final_transition
1861
- offsets = [
1862
- {:gmtoff => 3542, :isdst => false, :abbrev => 'LMT'},
1863
- {:gmtoff => 7200, :isdst => true, :abbrev => 'XDT'}]
1864
-
1865
- transitions = [{:at => Time.utc(2000, 4, 10, 1, 0, 0) - 3542, :offset_index => 1}]
1866
-
1867
- rules = AnnualRules.new(
1868
- TimezoneOffset.new(3600, 0, 'XST'),
1869
- TimezoneOffset.new(3600, 3600, 'XDT'),
1870
- JulianDayOfYearTransitionRule.new(100, 3600),
1871
- JulianDayOfYearTransitionRule.new(300, 7200)
1872
- )
1873
-
1874
- generate_up_to = ZoneinfoTimezoneInfo::GENERATE_UP_TO
1875
-
1876
- tzif_test(offsets, transitions, :rules => rules) do |path, format|
1877
- info = ZoneinfoTimezoneInfo.new('Correct/Final', path, @posix_tz_parser)
1878
- assert_equal('Correct/Final', info.identifier)
1879
-
1880
- assert_period(:LMT, 3542, 0, false, nil, Time.utc(2000, 4, 10, 1, 0, 0) - 3542, info)
1881
- assert_period(:XDT, 3600, 3600, true, Time.utc(2000, 4, 10, 1, 0, 0) - 3542, Time.utc(2000, 10, 27, 2, 0, 0) - 7200, info) # would be :XDT, 3542, 3658 without tz_string
1882
- assert_period(:XST, 3600, 0, false, Time.utc(2000, 10, 27, 2, 0, 0) - 7200, Time.utc(2001, 4, 10, 1, 0, 0) - 3600, info)
1883
-
1884
- 2001.upto(generate_up_to - 1).each do |year|
1885
- assert_period(:XDT, 3600, 3600, true, Time.utc(year, 4, 10, 1, 0, 0) - 3600, Time.utc(year, 10, 27, 2, 0, 0) - 7200, info)
1886
- assert_period(:XST, 3600, 0, false, Time.utc(year, 10, 27, 2, 0, 0) - 7200, Time.utc(year + 1, 4, 10, 1, 0, 0) - 3600, info)
1887
- end
1888
-
1889
- assert_period(:XDT, 3600, 3600, true, Time.utc(generate_up_to, 4, 10, 1, 0, 0) - 3600, Time.utc(generate_up_to, 10, 27, 2, 0, 0) - 7200, info)
1890
- assert_period(:XST, 3600, 0, false, Time.utc(generate_up_to, 10, 27, 2, 0, 0) - 7200, nil, info)
1891
- end
1892
- end
1893
-
1894
- def test_load_tz_string_specifies_transition_to_offset_of_final_transition_same_year_skip_dst_start
1895
- # TZInfo v1.2.8 considered this to be an error. However, this is a valid
1896
- # situation with Africa/Casablanca in 2018e.
1897
- #
1898
- # The last defined transitions are:
1899
- # At 2037-03-29 02:00Z change to WEST UTC+1
1900
- # At 2037-10-04 02:00Z change to WET UTC+0
1901
- #
1902
- # The rules define the end of DST to be at 03:00 local time on the last
1903
- # Sunday of October (2037-10-31). This later transition needs to be
1904
- # ignored.
1905
-
1906
- offsets = [
1907
- {:gmtoff => 7142, :isdst => false, :abbrev => 'LMT'},
1908
- {:gmtoff => 7200, :isdst => false, :abbrev => 'XST'},
1909
- {:gmtoff => 10800, :isdst => true, :abbrev => 'XDT'}
1910
- ]
1911
-
1912
- transitions = [
1913
- {:at => Time.utc(1971, 1, 2, 2, 0, 0) - 7142, :offset_index => 1},
1914
- {:at => Time.utc(1981, 4, 10, 1, 0, 0) - 7200, :offset_index => 2},
1915
- {:at => Time.utc(1981, 10, 27, 2, 0, 0) - 10800, :offset_index => 1},
1916
- {:at => Time.utc(1982, 4, 10, 1, 0, 0) - 7200, :offset_index => 2}
1917
- ]
1918
-
1919
- rules = AnnualRules.new(
1920
- TimezoneOffset.new(7200, 0, 'XST'),
1921
- TimezoneOffset.new(7200, 3600, 'XDT'),
1922
- JulianDayOfYearTransitionRule.new(101, 3600),
1923
- JulianDayOfYearTransitionRule.new(300, 7200)
1924
- )
1925
-
1926
- generate_up_to = ZoneinfoTimezoneInfo::GENERATE_UP_TO
1927
-
1928
- tzif_test(offsets, transitions, :rules => rules) do |path, format|
1929
- info = ZoneinfoTimezoneInfo.new('Ignore/Std', path, @posix_tz_parser)
1930
- assert_equal('Ignore/Std', info.identifier)
1931
-
1932
- assert_period(:LMT, 7142, 0, false, nil, Time.utc(1971, 1, 2, 2, 0, 0) - 7142, info)
1933
- assert_period(:XST, 7200, 0, false, Time.utc(1971, 1, 2, 2, 0, 0) - 7142, Time.utc(1981, 4, 10, 1, 0, 0) - 7200, info)
1934
- assert_period(:XDT, 7200, 3600, true, Time.utc(1981, 4, 10, 1, 0, 0) - 7200, Time.utc(1981, 10, 27, 2, 0, 0) - 10800, info)
1935
- assert_period(:XST, 7200, 0, false, Time.utc(1981, 10, 27, 2, 0, 0) - 10800, Time.utc(1982, 4, 10, 1, 0, 0) - 7200, info)
1936
- assert_period(:XDT, 7200, 3600, true, Time.utc(1982, 4, 10, 1, 0, 0) - 7200, Time.utc(1982, 10, 27, 2, 0, 0) - 10800, info)
1937
-
1938
- 1983.upto(generate_up_to).each do |year|
1939
- assert_period(:XST, 7200, 0, false, Time.utc(year - 1, 10, 27, 2, 0, 0) - 10800, Time.utc(year, 4, 11, 1, 0, 0) - 7200, info)
1940
- assert_period(:XDT, 7200, 3600, true, Time.utc(year, 4, 11, 1, 0, 0) - 7200, Time.utc(year, 10, 27, 2, 0, 0) - 10800, info)
1941
- end
1942
-
1943
- assert_period(:XST, 7200, 0, false, Time.utc(generate_up_to, 10, 27, 2, 0, 0) - 10800, nil, info)
1944
- end
1945
- end
1946
-
1947
- def test_load_tz_string_specifies_transition_to_offset_of_final_transition_same_year_skip_dst_end
1948
- # TZInfo v1.2.8 considered this to be an error. However, this is a valid
1949
- # situation with Africa/Casablanca in 2018e.
1950
- #
1951
- # The last defined transitions are:
1952
- # At 2037-03-29 02:00Z change to WEST UTC+1
1953
- # At 2037-10-04 02:00Z change to WET UTC+0
1954
- #
1955
- # The rules define the end of DST to be at 03:00 local time on the last
1956
- # Sunday of October (2037-10-31). This later transition needs to be
1957
- # ignored.
1958
-
1959
- offsets = [
1960
- {:gmtoff => 7142, :isdst => false, :abbrev => 'LMT'},
1961
- {:gmtoff => 7200, :isdst => false, :abbrev => 'XST'},
1962
- {:gmtoff => 10800, :isdst => true, :abbrev => 'XDT'}
1963
- ]
1964
-
1965
- transitions = [
1966
- {:at => Time.utc(1971, 1, 2, 2, 0, 0) - 7142, :offset_index => 1},
1967
- {:at => Time.utc(1981, 4, 10, 1, 0, 0) - 7200, :offset_index => 2},
1968
- {:at => Time.utc(1981, 10, 27, 2, 0, 0) - 10800, :offset_index => 1}
1969
- ]
1970
-
1971
- rules = AnnualRules.new(
1972
- TimezoneOffset.new(7200, 0, 'XST'),
1973
- TimezoneOffset.new(7200, 3600, 'XDT'),
1974
- JulianDayOfYearTransitionRule.new(100, 3600),
1975
- JulianDayOfYearTransitionRule.new(301, 7200)
1976
- )
1977
-
1978
- generate_up_to = ZoneinfoTimezoneInfo::GENERATE_UP_TO
1979
-
1980
- tzif_test(offsets, transitions, :rules => rules) do |path, format|
1981
- info = ZoneinfoTimezoneInfo.new('Ignore/Std', path, @posix_tz_parser)
1982
- assert_equal('Ignore/Std', info.identifier)
1983
-
1984
- assert_period(:LMT, 7142, 0, false, nil, Time.utc(1971, 1, 2, 2, 0, 0) - 7142, info)
1985
- assert_period(:XST, 7200, 0, false, Time.utc(1971, 1, 2, 2, 0, 0) - 7142, Time.utc(1981, 4, 10, 1, 0, 0) - 7200, info)
1986
- assert_period(:XDT, 7200, 3600, true, Time.utc(1981, 4, 10, 1, 0, 0) - 7200, Time.utc(1981, 10, 27, 2, 0, 0) - 10800, info)
1987
- assert_period(:XST, 7200, 0, false, Time.utc(1981, 10, 27, 2, 0, 0) - 10800, Time.utc(1982, 4, 10, 1, 0, 0) - 7200, info)
1988
-
1989
- 1982.upto(generate_up_to - 1).each do |year|
1990
- assert_period(:XDT, 7200, 3600, true, Time.utc(year, 4, 10, 1, 0, 0) - 7200, Time.utc(year, 10, 28, 2, 0, 0) - 10800, info)
1991
- assert_period(:XST, 7200, 0, false, Time.utc(year, 10, 28, 2, 0, 0) - 10800, Time.utc(year + 1, 4, 10, 1, 0, 0) - 7200, info)
1992
- end
1993
-
1994
- assert_period(:XDT, 7200, 3600, true, Time.utc(generate_up_to, 4, 10, 1, 0, 0) - 7200, Time.utc(generate_up_to, 10, 28, 2, 0, 0) - 10800, info)
1995
- assert_period(:XST, 7200, 0, false, Time.utc(generate_up_to, 10, 28, 2, 0, 0) - 10800, nil, info)
1996
- end
1997
- end
1998
-
1999
- def test_load_tz_string_specifies_transition_to_offset_of_final_transition_following_year
2000
- offsets = [
2001
- {:gmtoff => 7142, :isdst => false, :abbrev => 'LMT'},
2002
- {:gmtoff => 7200, :isdst => false, :abbrev => 'XST'},
2003
- {:gmtoff => 10800, :isdst => true, :abbrev => 'XDT'}
2004
- ]
2005
-
2006
- transitions = [
2007
- {:at => Time.utc(1971, 1, 2, 2, 0, 0) - 7142, :offset_index => 1},
2008
- {:at => Time.utc(1981, 10, 27, 2, 0, 0) - 7200, :offset_index => 2}
2009
- ]
2010
-
2011
- rules = AnnualRules.new(
2012
- TimezoneOffset.new(7200, 0, 'XST'),
2013
- TimezoneOffset.new(7200, 3600, 'XDT'),
2014
- JulianDayOfYearTransitionRule.new(100, 3600),
2015
- JulianDayOfYearTransitionRule.new(299, 7200)
2016
- )
2017
-
2018
- tzif_test(offsets, transitions, :rules => rules) do |path, format|
2019
- error = assert_raises(InvalidZoneinfoFile) { ZoneinfoTimezoneInfo.new('Invalid/Offset', path, @posix_tz_parser) }
2020
- assert_equal("The first offset indicated by the POSIX-style TZ string did not match the final defined offset in file '#{path}'.", error.message)
2021
- end
2022
- end
2023
-
2024
- unless SUPPORTS_64BIT
2025
- def test_generate_up_to_limited_to_2037_with_no_64_bit_support
2026
- assert_equal(2037, ZoneinfoTimezoneInfo::GENERATE_UP_TO)
2027
- end
2028
-
2029
- def test_load_tz_string_does_not_generate_if_transition_after_32_bit_range_with_no_64_bit_support
2030
- offsets = [
2031
- {:gmtoff => 7142, :isdst => false, :abbrev => 'LMT'},
2032
- {:gmtoff => 7200, :isdst => false, :abbrev => 'XST'},
2033
- {:gmtoff => 10800, :isdst => true, :abbrev => 'XDT'}
2034
- ]
2035
-
2036
- transitions = [
2037
- {:at => Time.utc(1971, 1, 2, 2, 0, 0) - 7142, :offset_index => 1},
2038
- {:at => 2154474000 - 7200, :offset_index => 2}, # Time.utc(2038, 4, 10, 1, 0, 0).to_i
2039
- {:at => 2171757600 - 10800, :offset_index => 1} # Time.utc(2038, 10, 27, 2, 0, 0).to_i
2040
- ]
2041
-
2042
- rules = AnnualRules.new(
2043
- TimezoneOffset.new(7200, 0, 'XST'),
2044
- TimezoneOffset.new(7200, 3600, 'XDT'),
2045
- JulianDayOfYearTransitionRule.new(100, 3600),
2046
- JulianDayOfYearTransitionRule.new(300, 7200)
2047
- )
2048
-
2049
- tzif_test(offsets, transitions, :rules => rules) do |path, format|
2050
- info = ZoneinfoTimezoneInfo.new('From/Rules', path, @posix_tz_parser)
2051
- assert_equal('From/Rules', info.identifier)
2052
-
2053
- assert_period(:LMT, 7142, 0, false, nil, Time.utc(1971, 1, 2, 2, 0, 0) - 7142, info)
2054
- assert_period(:XST, 7200, 0, false, Time.utc(1971, 1, 2, 2, 0, 0) - 7142, nil, info)
2055
- end
2056
- end
2057
- end
2058
-
2059
- if SUPPORTS_NEGATIVE
2060
- def test_load_tz_string_generates_from_last_transition_if_before_1970_and_supports_negative
2061
- offsets = [
2062
- {:gmtoff => 7142, :isdst => false, :abbrev => 'LMT'},
2063
- {:gmtoff => 7200, :isdst => false, :abbrev => 'XST'},
2064
- {:gmtoff => 10800, :isdst => true, :abbrev => 'XDT'}
2065
- ]
2066
-
2067
- transitions = [
2068
- {:at => Time.utc(1961, 1, 2, 2, 0, 0) - 7142, :offset_index => 1},
2069
- {:at => Time.utc(1962, 4, 10, 1, 0, 0) - 7200, :offset_index => 2},
2070
- {:at => Time.utc(1962, 10, 27, 2, 0, 0) - 10800, :offset_index => 1}
2071
- ]
2072
-
2073
- rules = AnnualRules.new(
2074
- TimezoneOffset.new(7200, 0, 'XST'),
2075
- TimezoneOffset.new(7200, 3600, 'XDT'),
2076
- JulianDayOfYearTransitionRule.new(100, 3600),
2077
- JulianDayOfYearTransitionRule.new(300, 7200)
2078
- )
2079
-
2080
- generate_up_to = ZoneinfoTimezoneInfo::GENERATE_UP_TO
2081
-
2082
- tzif_test(offsets, transitions, :rules => rules) do |path, format|
2083
- info = ZoneinfoTimezoneInfo.new('Pre/1970', path, @posix_tz_parser)
2084
- assert_equal('Pre/1970', info.identifier)
2085
-
2086
- assert_period(:LMT, 7142, 0, false, nil, Time.utc(1961, 1, 2, 2, 0, 0) - 7142, info)
2087
- assert_period(:XST, 7200, 0, false, Time.utc(1961, 1, 2, 2, 0, 0) - 7142, Time.utc(1962, 4, 10, 1, 0, 0) - 7200, info)
2088
-
2089
- 1962.upto(generate_up_to - 1).each do |year|
2090
- assert_period(:XDT, 7200, 3600, true, Time.utc(year, 4, 10, 1, 0, 0) - 7200, Time.utc(year, 10, 27, 2, 0, 0) - 10800, info)
2091
- assert_period(:XST, 7200, 0, false, Time.utc(year, 10, 27, 2, 0, 0) - 10800, Time.utc(year + 1, 4, 10, 1, 0, 0) - 7200, info)
2092
- end
2093
-
2094
- assert_period(:XDT, 7200, 3600, true, Time.utc(generate_up_to, 4, 10, 1, 0, 0) - 7200, Time.utc(generate_up_to, 10, 27, 2, 0, 0) - 10800, info)
2095
- assert_period(:XST, 7200, 0, false, Time.utc(generate_up_to, 10, 27, 2, 0, 0) - 10800, nil, info)
2096
- end
2097
- end
2098
- else
2099
- def test_load_tz_string_generates_from_1970_if_last_transition_before_1970_and_does_not_support_negative
2100
- offsets = [
2101
- {:gmtoff => 7142, :isdst => false, :abbrev => 'LMT'},
2102
- {:gmtoff => 7200, :isdst => false, :abbrev => 'XST'},
2103
- {:gmtoff => 10800, :isdst => true, :abbrev => 'XDT'}
2104
- ]
2105
-
2106
- transitions = [
2107
- {:at => -283903200 - 7142, :offset_index => 1}, # Time.utc(1961, 1, 2, 2, 0, 0)
2108
- {:at => -243903600 - 7200, :offset_index => 2}, # Time.utc(1962, 4, 10, 1, 0, 0)
2109
- {:at => -226620000 - 10800, :offset_index => 1} # Time.utc(1962, 10, 27, 2, 0, 0)
2110
- ]
2111
-
2112
- rules = AnnualRules.new(
2113
- TimezoneOffset.new(7200, 0, 'XST'),
2114
- TimezoneOffset.new(7200, 3600, 'XDT'),
2115
- JulianDayOfYearTransitionRule.new(100, 3600),
2116
- JulianDayOfYearTransitionRule.new(300, 7200)
2117
- )
2118
-
2119
- generate_up_to = ZoneinfoTimezoneInfo::GENERATE_UP_TO
2120
-
2121
- tzif_test(offsets, transitions, :rules => rules) do |path, format|
2122
- info = ZoneinfoTimezoneInfo.new('Pre/1970', path, @posix_tz_parser)
2123
- assert_equal('Pre/1970', info.identifier)
2124
-
2125
- assert_period(:LMT, 7142, 0, false, nil, Time.utc(1970, 1, 1), info)
2126
- assert_period(:XST, 7200, 0, false, Time.utc(1970, 1, 1), Time.utc(1970, 4, 10, 1, 0, 0) - 7200, info)
2127
-
2128
- 1970.upto(generate_up_to - 1).each do |year|
2129
- assert_period(:XDT, 7200, 3600, true, Time.utc(year, 4, 10, 1, 0, 0) - 7200, Time.utc(year, 10, 27, 2, 0, 0) - 10800, info)
2130
- assert_period(:XST, 7200, 0, false, Time.utc(year, 10, 27, 2, 0, 0) - 10800, Time.utc(year + 1, 4, 10, 1, 0, 0) - 7200, info)
2131
- end
2132
-
2133
- assert_period(:XDT, 7200, 3600, true, Time.utc(generate_up_to, 4, 10, 1, 0, 0) - 7200, Time.utc(generate_up_to, 10, 27, 2, 0, 0) - 10800, info)
2134
- assert_period(:XST, 7200, 0, false, Time.utc(generate_up_to, 10, 27, 2, 0, 0) - 10800, nil, info)
2135
- end
2136
- end
2137
- end
2138
-
2139
- def test_load_tz_string_as_utf8
2140
- offsets = [{:gmtoff => 3600, :isdst => false, :abbrev => 'áccént'}]
2141
- rules = TimezoneOffset.new(3600, 0, 'áccént')
2142
-
2143
- tzif_test(offsets, [], :tz_string => '<áccént>1', :rules => rules) do |path, format|
2144
- # FakePosixTimeZoneParser will test that the tz_string matches.
2145
- info = ZoneinfoTimezoneInfo.new('Test/Utf8', path, @posix_tz_parser)
2146
- assert_period(:'áccént', 3600, 0, false, nil, nil, info)
2147
- end
2148
- end
2149
- end