tzinfo 1.2.10 → 2.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (153) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.yardopts +3 -0
  4. data/CHANGES.md +573 -391
  5. data/LICENSE +12 -12
  6. data/README.md +368 -114
  7. data/lib/tzinfo/annual_rules.rb +32 -12
  8. data/lib/tzinfo/country.rb +141 -129
  9. data/lib/tzinfo/country_timezone.rb +70 -112
  10. data/lib/tzinfo/data_source.rb +400 -144
  11. data/lib/tzinfo/data_sources/constant_offset_data_timezone_info.rb +56 -0
  12. data/lib/tzinfo/data_sources/country_info.rb +42 -0
  13. data/lib/tzinfo/data_sources/data_timezone_info.rb +91 -0
  14. data/lib/tzinfo/data_sources/linked_timezone_info.rb +33 -0
  15. data/lib/tzinfo/data_sources/posix_time_zone_parser.rb +181 -0
  16. data/lib/tzinfo/data_sources/ruby_data_source.rb +145 -0
  17. data/lib/tzinfo/data_sources/timezone_info.rb +47 -0
  18. data/lib/tzinfo/data_sources/transitions_data_timezone_info.rb +214 -0
  19. data/lib/tzinfo/data_sources/zoneinfo_data_source.rb +596 -0
  20. data/lib/tzinfo/data_sources/zoneinfo_reader.rb +486 -0
  21. data/lib/tzinfo/data_sources.rb +8 -0
  22. data/lib/tzinfo/data_timezone.rb +33 -47
  23. data/lib/tzinfo/datetime_with_offset.rb +153 -0
  24. data/lib/tzinfo/format1/country_definer.rb +17 -0
  25. data/lib/tzinfo/format1/country_index_definition.rb +64 -0
  26. data/lib/tzinfo/format1/timezone_definer.rb +64 -0
  27. data/lib/tzinfo/format1/timezone_definition.rb +39 -0
  28. data/lib/tzinfo/format1/timezone_index_definition.rb +77 -0
  29. data/lib/tzinfo/format1.rb +10 -0
  30. data/lib/tzinfo/format2/country_definer.rb +68 -0
  31. data/lib/tzinfo/format2/country_index_definer.rb +68 -0
  32. data/lib/tzinfo/format2/country_index_definition.rb +46 -0
  33. data/lib/tzinfo/format2/timezone_definer.rb +94 -0
  34. data/lib/tzinfo/format2/timezone_definition.rb +73 -0
  35. data/lib/tzinfo/format2/timezone_index_definer.rb +45 -0
  36. data/lib/tzinfo/format2/timezone_index_definition.rb +55 -0
  37. data/lib/tzinfo/format2.rb +10 -0
  38. data/lib/tzinfo/info_timezone.rb +26 -21
  39. data/lib/tzinfo/linked_timezone.rb +33 -52
  40. data/lib/tzinfo/offset_timezone_period.rb +42 -0
  41. data/lib/tzinfo/string_deduper.rb +118 -0
  42. data/lib/tzinfo/time_with_offset.rb +154 -0
  43. data/lib/tzinfo/timestamp.rb +552 -0
  44. data/lib/tzinfo/timestamp_with_offset.rb +85 -0
  45. data/lib/tzinfo/timezone.rb +989 -502
  46. data/lib/tzinfo/timezone_offset.rb +84 -74
  47. data/lib/tzinfo/timezone_period.rb +151 -217
  48. data/lib/tzinfo/timezone_proxy.rb +70 -79
  49. data/lib/tzinfo/timezone_transition.rb +77 -109
  50. data/lib/tzinfo/transition_rule.rb +207 -77
  51. data/lib/tzinfo/transitions_timezone_period.rb +63 -0
  52. data/lib/tzinfo/untaint_ext.rb +18 -0
  53. data/lib/tzinfo/version.rb +7 -0
  54. data/lib/tzinfo/with_offset.rb +61 -0
  55. data/lib/tzinfo.rb +82 -40
  56. data.tar.gz.sig +0 -0
  57. metadata +49 -104
  58. metadata.gz.sig +0 -0
  59. data/Rakefile +0 -107
  60. data/lib/tzinfo/country_index_definition.rb +0 -31
  61. data/lib/tzinfo/country_info.rb +0 -42
  62. data/lib/tzinfo/data_timezone_info.rb +0 -55
  63. data/lib/tzinfo/linked_timezone_info.rb +0 -26
  64. data/lib/tzinfo/offset_rationals.rb +0 -77
  65. data/lib/tzinfo/posix_time_zone_parser.rb +0 -136
  66. data/lib/tzinfo/ruby_core_support.rb +0 -169
  67. data/lib/tzinfo/ruby_country_info.rb +0 -74
  68. data/lib/tzinfo/ruby_data_source.rb +0 -140
  69. data/lib/tzinfo/time_or_datetime.rb +0 -351
  70. data/lib/tzinfo/timezone_definition.rb +0 -36
  71. data/lib/tzinfo/timezone_index_definition.rb +0 -54
  72. data/lib/tzinfo/timezone_info.rb +0 -30
  73. data/lib/tzinfo/timezone_transition_definition.rb +0 -104
  74. data/lib/tzinfo/transition_data_timezone_info.rb +0 -274
  75. data/lib/tzinfo/zoneinfo_country_info.rb +0 -37
  76. data/lib/tzinfo/zoneinfo_data_source.rb +0 -512
  77. data/lib/tzinfo/zoneinfo_timezone_info.rb +0 -520
  78. data/test/assets/payload.rb +0 -1
  79. data/test/tc_annual_rules.rb +0 -95
  80. data/test/tc_country.rb +0 -238
  81. data/test/tc_country_index_definition.rb +0 -69
  82. data/test/tc_country_info.rb +0 -16
  83. data/test/tc_country_timezone.rb +0 -173
  84. data/test/tc_data_source.rb +0 -218
  85. data/test/tc_data_timezone.rb +0 -99
  86. data/test/tc_data_timezone_info.rb +0 -18
  87. data/test/tc_info_timezone.rb +0 -34
  88. data/test/tc_linked_timezone.rb +0 -155
  89. data/test/tc_linked_timezone_info.rb +0 -23
  90. data/test/tc_offset_rationals.rb +0 -23
  91. data/test/tc_posix_time_zone_parser.rb +0 -261
  92. data/test/tc_ruby_core_support.rb +0 -168
  93. data/test/tc_ruby_country_info.rb +0 -110
  94. data/test/tc_ruby_data_source.rb +0 -173
  95. data/test/tc_time_or_datetime.rb +0 -674
  96. data/test/tc_timezone.rb +0 -1361
  97. data/test/tc_timezone_definition.rb +0 -113
  98. data/test/tc_timezone_index_definition.rb +0 -73
  99. data/test/tc_timezone_info.rb +0 -11
  100. data/test/tc_timezone_london.rb +0 -143
  101. data/test/tc_timezone_melbourne.rb +0 -142
  102. data/test/tc_timezone_new_york.rb +0 -142
  103. data/test/tc_timezone_offset.rb +0 -126
  104. data/test/tc_timezone_period.rb +0 -555
  105. data/test/tc_timezone_proxy.rb +0 -136
  106. data/test/tc_timezone_transition.rb +0 -366
  107. data/test/tc_timezone_transition_definition.rb +0 -295
  108. data/test/tc_timezone_utc.rb +0 -27
  109. data/test/tc_transition_data_timezone_info.rb +0 -433
  110. data/test/tc_transition_rule.rb +0 -663
  111. data/test/tc_zoneinfo_country_info.rb +0 -78
  112. data/test/tc_zoneinfo_data_source.rb +0 -1223
  113. data/test/tc_zoneinfo_timezone_info.rb +0 -2153
  114. data/test/test_utils.rb +0 -208
  115. data/test/ts_all.rb +0 -7
  116. data/test/ts_all_ruby.rb +0 -5
  117. data/test/ts_all_zoneinfo.rb +0 -9
  118. data/test/tzinfo-data/tzinfo/data/definitions/America/Argentina/Buenos_Aires.rb +0 -89
  119. data/test/tzinfo-data/tzinfo/data/definitions/America/New_York.rb +0 -327
  120. data/test/tzinfo-data/tzinfo/data/definitions/Australia/Melbourne.rb +0 -230
  121. data/test/tzinfo-data/tzinfo/data/definitions/EST.rb +0 -19
  122. data/test/tzinfo-data/tzinfo/data/definitions/Etc/GMT__m__1.rb +0 -21
  123. data/test/tzinfo-data/tzinfo/data/definitions/Etc/GMT__p__1.rb +0 -21
  124. data/test/tzinfo-data/tzinfo/data/definitions/Etc/UTC.rb +0 -21
  125. data/test/tzinfo-data/tzinfo/data/definitions/Europe/Amsterdam.rb +0 -273
  126. data/test/tzinfo-data/tzinfo/data/definitions/Europe/Andorra.rb +0 -198
  127. data/test/tzinfo-data/tzinfo/data/definitions/Europe/London.rb +0 -333
  128. data/test/tzinfo-data/tzinfo/data/definitions/Europe/Paris.rb +0 -277
  129. data/test/tzinfo-data/tzinfo/data/definitions/Europe/Prague.rb +0 -235
  130. data/test/tzinfo-data/tzinfo/data/definitions/UTC.rb +0 -16
  131. data/test/tzinfo-data/tzinfo/data/indexes/countries.rb +0 -940
  132. data/test/tzinfo-data/tzinfo/data/indexes/timezones.rb +0 -609
  133. data/test/tzinfo-data/tzinfo/data/version.rb +0 -20
  134. data/test/tzinfo-data/tzinfo/data.rb +0 -8
  135. data/test/zoneinfo/America/Argentina/Buenos_Aires +0 -0
  136. data/test/zoneinfo/America/New_York +0 -0
  137. data/test/zoneinfo/Australia/Melbourne +0 -0
  138. data/test/zoneinfo/EST +0 -0
  139. data/test/zoneinfo/Etc/UTC +0 -0
  140. data/test/zoneinfo/Europe/Amsterdam +0 -0
  141. data/test/zoneinfo/Europe/Andorra +0 -0
  142. data/test/zoneinfo/Europe/London +0 -0
  143. data/test/zoneinfo/Europe/Paris +0 -0
  144. data/test/zoneinfo/Europe/Prague +0 -0
  145. data/test/zoneinfo/Factory +0 -0
  146. data/test/zoneinfo/iso3166.tab +0 -274
  147. data/test/zoneinfo/leapseconds +0 -78
  148. data/test/zoneinfo/posix/Europe/London +0 -0
  149. data/test/zoneinfo/posixrules +0 -0
  150. data/test/zoneinfo/right/Europe/London +0 -0
  151. data/test/zoneinfo/zone.tab +0 -452
  152. data/test/zoneinfo/zone1970.tab +0 -384
  153. data/tzinfo.gemspec +0 -21
@@ -1,1223 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils')
4
- require 'fileutils'
5
- require 'pathname'
6
- require 'tmpdir'
7
-
8
- include TZInfo
9
-
10
- # Use send as a workaround for an issue on JRuby 9.2.9.0 where using the
11
- # refinement causes calls to RubyCoreSupport.file_open to fail to pass the block
12
- # parameter.
13
- #
14
- # https://travis-ci.org/tzinfo/tzinfo/jobs/628812051#L1931
15
- # https://github.com/jruby/jruby/issues/6009
16
- send(:using, TZInfo::RubyCoreSupport::UntaintExt) if TZInfo::RubyCoreSupport.const_defined?(:UntaintExt)
17
- send(:using, TaintExt) if Module.const_defined?(:TaintExt)
18
-
19
- class TCZoneinfoDataSource < Minitest::Test
20
- ZONEINFO_DIR = File.join(File.expand_path(File.dirname(__FILE__)), 'zoneinfo').untaint
21
-
22
- def setup
23
- @orig_search_path = ZoneinfoDataSource.search_path.clone
24
- @orig_alternate_iso3166_tab_search_path = ZoneinfoDataSource.alternate_iso3166_tab_search_path.clone
25
- @orig_pwd = FileUtils.pwd
26
-
27
- # A zoneinfo directory containing files needed by the tests.
28
- # The symlinks in this directory are set up in test_utils.rb.
29
- @data_source = ZoneinfoDataSource.new(ZONEINFO_DIR)
30
- end
31
-
32
- def teardown
33
- ZoneinfoDataSource.search_path = @orig_search_path
34
- ZoneinfoDataSource.alternate_iso3166_tab_search_path = @orig_alternate_iso3166_tab_search_path
35
- FileUtils.chdir(@orig_pwd)
36
- end
37
-
38
- def test_default_search_path
39
- assert_equal(['/usr/share/zoneinfo', '/usr/share/lib/zoneinfo', '/etc/zoneinfo'], ZoneinfoDataSource.search_path)
40
- assert_equal(false, ZoneinfoDataSource.search_path.frozen?)
41
- end
42
-
43
- def test_set_search_path_default
44
- ZoneinfoDataSource.search_path = ['/tmp/zoneinfo1', '/tmp/zoneinfo2']
45
- assert_equal(['/tmp/zoneinfo1', '/tmp/zoneinfo2'], ZoneinfoDataSource.search_path)
46
-
47
- ZoneinfoDataSource.search_path = nil
48
- assert_equal(['/usr/share/zoneinfo', '/usr/share/lib/zoneinfo', '/etc/zoneinfo'], ZoneinfoDataSource.search_path)
49
- assert_equal(false, ZoneinfoDataSource.search_path.frozen?)
50
- end
51
-
52
- def test_set_search_path_array
53
- path = ['/tmp/zoneinfo1', '/tmp/zoneinfo2']
54
- ZoneinfoDataSource.search_path = path
55
- assert_equal(['/tmp/zoneinfo1', '/tmp/zoneinfo2'], ZoneinfoDataSource.search_path)
56
- refute_same(path, ZoneinfoDataSource.search_path)
57
- end
58
-
59
- def test_set_search_path_array_to_s
60
- ZoneinfoDataSource.search_path = [Pathname.new('/tmp/zoneinfo3')]
61
- assert_equal(['/tmp/zoneinfo3'], ZoneinfoDataSource.search_path)
62
- end
63
-
64
- def test_set_search_path_string
65
- ZoneinfoDataSource.search_path = ['/tmp/zoneinfo4', '/tmp/zoneinfo5'].join(File::PATH_SEPARATOR)
66
- assert_equal(['/tmp/zoneinfo4', '/tmp/zoneinfo5'], ZoneinfoDataSource.search_path)
67
- end
68
-
69
- def test_default_alternate_iso3166_tab_search_path
70
- assert_equal(['/usr/share/misc/iso3166.tab', '/usr/share/misc/iso3166'], ZoneinfoDataSource.alternate_iso3166_tab_search_path)
71
- assert_equal(false, ZoneinfoDataSource.alternate_iso3166_tab_search_path.frozen?)
72
- end
73
-
74
- def test_set_alternate_iso3166_tab_search_path_default
75
- ZoneinfoDataSource.alternate_iso3166_tab_search_path = ['/tmp/iso3166.tab', '/tmp/iso3166']
76
- assert_equal(['/tmp/iso3166.tab', '/tmp/iso3166'], ZoneinfoDataSource.alternate_iso3166_tab_search_path)
77
-
78
- ZoneinfoDataSource.alternate_iso3166_tab_search_path = nil
79
- assert_equal(['/usr/share/misc/iso3166.tab', '/usr/share/misc/iso3166'], ZoneinfoDataSource.alternate_iso3166_tab_search_path)
80
- assert_equal(false, ZoneinfoDataSource.alternate_iso3166_tab_search_path.frozen?)
81
- end
82
-
83
- def test_set_alternate_iso3166_tab_search_path_array
84
- path = ['/tmp/iso3166.tab', '/tmp/iso3166']
85
- ZoneinfoDataSource.alternate_iso3166_tab_search_path = path
86
- assert_equal(['/tmp/iso3166.tab', '/tmp/iso3166'], ZoneinfoDataSource.alternate_iso3166_tab_search_path)
87
- refute_same(path, ZoneinfoDataSource.alternate_iso3166_tab_search_path)
88
- end
89
-
90
- def test_set_alternate_iso3166_tab_search_path_array_to_s
91
- ZoneinfoDataSource.alternate_iso3166_tab_search_path = [Pathname.new('/tmp/iso3166.tab')]
92
- assert_equal(['/tmp/iso3166.tab'], ZoneinfoDataSource.alternate_iso3166_tab_search_path)
93
- end
94
-
95
- def test_set_alternate_iso3166_tab_search_path_string
96
- ZoneinfoDataSource.alternate_iso3166_tab_search_path = ['/tmp/iso3166.tab', '/tmp/iso3166'].join(File::PATH_SEPARATOR)
97
- assert_equal(['/tmp/iso3166.tab', '/tmp/iso3166'], ZoneinfoDataSource.alternate_iso3166_tab_search_path)
98
- end
99
-
100
- def test_new_search
101
- Dir.mktmpdir('tzinfo_test_dir1') do |dir1|
102
- Dir.mktmpdir('tzinfo_test_dir2') do |dir2|
103
- Dir.mktmpdir('tzinfo_test_dir3') do |dir3|
104
- Dir.mktmpdir('tzinfo_test_dir4') do |dir4|
105
- file = File.join(dir1, 'file')
106
- FileUtils.touch(File.join(dir2, 'zone.tab'))
107
- FileUtils.touch(File.join(dir3, 'iso3166.tab'))
108
- FileUtils.touch(File.join(dir4, 'zone.tab'))
109
- FileUtils.touch(File.join(dir4, 'iso3166.tab'))
110
-
111
- ZoneinfoDataSource.search_path = [file, dir2, dir3, dir4]
112
- ZoneinfoDataSource.alternate_iso3166_tab_search_path = []
113
-
114
- data_source = ZoneinfoDataSource.new
115
- assert_equal(dir4, data_source.zoneinfo_dir)
116
- end
117
- end
118
- end
119
- end
120
- end
121
-
122
- def test_new_search_zone1970
123
- Dir.mktmpdir('tzinfo_test_dir1') do |dir1|
124
- Dir.mktmpdir('tzinfo_test_dir2') do |dir2|
125
- Dir.mktmpdir('tzinfo_test_dir3') do |dir3|
126
- Dir.mktmpdir('tzinfo_test_dir4') do |dir4|
127
- file = File.join(dir1, 'file')
128
- FileUtils.touch(File.join(dir2, 'zone1970.tab'))
129
- FileUtils.touch(File.join(dir3, 'iso3166.tab'))
130
- FileUtils.touch(File.join(dir4, 'zone1970.tab'))
131
- FileUtils.touch(File.join(dir4, 'iso3166.tab'))
132
-
133
- ZoneinfoDataSource.search_path = [file, dir2, dir3, dir4]
134
- ZoneinfoDataSource.alternate_iso3166_tab_search_path = []
135
-
136
- data_source = ZoneinfoDataSource.new
137
- assert_equal(dir4, data_source.zoneinfo_dir)
138
- end
139
- end
140
- end
141
- end
142
- end
143
-
144
- def test_new_search_solaris_tab_files
145
- # Solaris names the tab files 'tab/country.tab' (iso3166.tab) and
146
- # 'tab/zone_sun.tab' (zone.tab).
147
-
148
- Dir.mktmpdir('tzinfo_test_dir') do |dir|
149
- tab = File.join(dir, 'tab')
150
- FileUtils.mkdir(tab)
151
- FileUtils.touch(File.join(tab, 'country.tab'))
152
- FileUtils.touch(File.join(tab, 'zone_sun.tab'))
153
-
154
- ZoneinfoDataSource.search_path = [dir]
155
- ZoneinfoDataSource.alternate_iso3166_tab_search_path = []
156
-
157
- data_source = ZoneinfoDataSource.new
158
- assert_equal(dir, data_source.zoneinfo_dir)
159
- end
160
- end
161
-
162
- def test_new_search_alternate_iso3166_path
163
- Dir.mktmpdir('tzinfo_test_dir_zoneinfo') do |zoneinfo_dir|
164
- Dir.mktmpdir('tzinfo_test_dir_tab') do |tab_dir|
165
- FileUtils.touch(File.join(zoneinfo_dir, 'zone.tab'))
166
-
167
- tab_file = File.join(tab_dir, 'iso3166')
168
-
169
- ZoneinfoDataSource.search_path = [zoneinfo_dir]
170
- ZoneinfoDataSource.alternate_iso3166_tab_search_path = [tab_file]
171
-
172
- assert_raises(ZoneinfoDirectoryNotFound) do
173
- ZoneinfoDataSource.new
174
- end
175
-
176
- FileUtils.touch(tab_file)
177
-
178
- data_source = ZoneinfoDataSource.new
179
- assert_equal(zoneinfo_dir, data_source.zoneinfo_dir)
180
- end
181
- end
182
- end
183
-
184
- def test_new_search_not_found
185
- Dir.mktmpdir('tzinfo_test_dir1') do |dir1|
186
- Dir.mktmpdir('tzinfo_test_dir2') do |dir2|
187
- Dir.mktmpdir('tzinfo_test_dir3') do |dir3|
188
- Dir.mktmpdir('tzinfo_test_dir4') do |dir4|
189
- Dir.mktmpdir('tzinfo_test_dir5') do |dir5|
190
- file = File.join(dir1, 'file')
191
- FileUtils.touch(file)
192
- FileUtils.touch(File.join(dir2, 'zone.tab'))
193
- FileUtils.touch(File.join(dir3, 'zone1970.tab'))
194
- FileUtils.touch(File.join(dir4, 'iso3166.tab'))
195
-
196
- ZoneinfoDataSource.search_path = [file, dir2, dir3, dir4, dir5]
197
- ZoneinfoDataSource.alternate_iso3166_tab_search_path = []
198
-
199
- assert_raises(ZoneinfoDirectoryNotFound) do
200
- ZoneinfoDataSource.new
201
- end
202
- end
203
- end
204
- end
205
- end
206
- end
207
- end
208
-
209
- def test_new_search_relative
210
- Dir.mktmpdir('tzinfo_test') do |dir|
211
- FileUtils.touch(File.join(dir, 'zone.tab'))
212
- FileUtils.touch(File.join(dir, 'iso3166.tab'))
213
-
214
- FileUtils.chdir(dir)
215
-
216
- ZoneinfoDataSource.search_path = ['.']
217
- ZoneinfoDataSource.alternate_iso3166_tab_search_path = []
218
- data_source = ZoneinfoDataSource.new
219
- assert_equal(Pathname.new(dir).realpath.to_s, data_source.zoneinfo_dir)
220
-
221
- # Change out of the directory to allow it to be deleted on Windows.
222
- FileUtils.chdir(@orig_pwd)
223
- end
224
- end
225
-
226
- def test_new_dir
227
- Dir.mktmpdir('tzinfo_test') do |dir|
228
- FileUtils.touch(File.join(dir, 'zone.tab'))
229
- FileUtils.touch(File.join(dir, 'iso3166.tab'))
230
-
231
- data_source = ZoneinfoDataSource.new(dir)
232
- assert_equal(dir, data_source.zoneinfo_dir)
233
- end
234
- end
235
-
236
- def test_new_dir_zone1970
237
- Dir.mktmpdir('tzinfo_test') do |dir|
238
- FileUtils.touch(File.join(dir, 'zone1970.tab'))
239
- FileUtils.touch(File.join(dir, 'iso3166.tab'))
240
-
241
- data_source = ZoneinfoDataSource.new(dir)
242
- assert_equal(dir, data_source.zoneinfo_dir)
243
- end
244
- end
245
-
246
- def test_new_dir_solaris_tab_files
247
- # Solaris names the tab files 'tab/country.tab' (iso3166.tab) and
248
- # 'tab/zone_sun.tab' (zone.tab).
249
-
250
- Dir.mktmpdir('tzinfo_test') do |dir|
251
- tab = File.join(dir, 'tab')
252
- FileUtils.mkdir(tab)
253
- FileUtils.touch(File.join(tab, 'country.tab'))
254
- FileUtils.touch(File.join(tab, 'zone_sun.tab'))
255
-
256
- data_source = ZoneinfoDataSource.new(dir)
257
- assert_equal(dir, data_source.zoneinfo_dir)
258
- end
259
- end
260
-
261
- def test_new_dir_alternate_iso3166_path
262
- Dir.mktmpdir('tzinfo_test_dir_zoneinfo') do |zoneinfo_dir|
263
- Dir.mktmpdir('tzinfo_test_dir_tab') do |tab_dir|
264
- FileUtils.touch(File.join(zoneinfo_dir, 'zone.tab'))
265
-
266
- tab_file = File.join(tab_dir, 'iso3166')
267
- FileUtils.touch(tab_file)
268
-
269
- ZoneinfoDataSource.alternate_iso3166_tab_search_path = [tab_file]
270
-
271
- assert_raises(InvalidZoneinfoDirectory) do
272
- # The alternate_iso3166_tab_search_path should not be used. This should raise
273
- # an exception.
274
- ZoneinfoDataSource.new(zoneinfo_dir)
275
- end
276
-
277
- data_source = ZoneinfoDataSource.new(zoneinfo_dir, tab_file)
278
- assert_equal(zoneinfo_dir, data_source.zoneinfo_dir)
279
- end
280
- end
281
- end
282
-
283
- def test_new_dir_invalid
284
- Dir.mktmpdir('tzinfo_test') do |dir|
285
- assert_raises(InvalidZoneinfoDirectory) do
286
- ZoneinfoDataSource.new(dir)
287
- end
288
- end
289
- end
290
-
291
- def test_new_dir_invalid_alternate_iso3166_path
292
- Dir.mktmpdir('tzinfo_test_dir_zoneinfo') do |zoneinfo_dir|
293
- Dir.mktmpdir('tzinfo_test_dir_tab') do |tab_dir|
294
- FileUtils.touch(File.join(zoneinfo_dir, 'zone.tab'))
295
-
296
- assert_raises(InvalidZoneinfoDirectory) do
297
- ZoneinfoDataSource.new(zoneinfo_dir, File.join(tab_dir, 'iso3166'))
298
- end
299
- end
300
- end
301
- end
302
-
303
- def test_new_dir_invalid_alternate_iso3166_path_overrides_valid
304
- Dir.mktmpdir('tzinfo_test_dir_zoneinfo') do |zoneinfo_dir|
305
- Dir.mktmpdir('tzinfo_test_dir_tab') do |tab_dir|
306
- FileUtils.touch(File.join(zoneinfo_dir, 'iso3166.tab'))
307
- FileUtils.touch(File.join(zoneinfo_dir, 'zone.tab'))
308
-
309
- assert_raises(InvalidZoneinfoDirectory) do
310
- ZoneinfoDataSource.new(zoneinfo_dir, File.join(tab_dir, 'iso3166'))
311
- end
312
- end
313
- end
314
- end
315
-
316
- def test_new_file
317
- Dir.mktmpdir('tzinfo_test') do |dir|
318
- file = File.join(dir, 'file')
319
- FileUtils.touch(file)
320
-
321
- assert_raises(InvalidZoneinfoDirectory) do
322
- ZoneinfoDataSource.new(file)
323
- end
324
- end
325
- end
326
-
327
- def test_new_dir_relative
328
- Dir.mktmpdir('tzinfo_test') do |dir|
329
- FileUtils.touch(File.join(dir, 'zone.tab'))
330
- FileUtils.touch(File.join(dir, 'iso3166.tab'))
331
-
332
- FileUtils.chdir(dir)
333
-
334
- data_source = ZoneinfoDataSource.new('.')
335
- assert_equal(Pathname.new(dir).realpath.to_s, data_source.zoneinfo_dir)
336
-
337
- # Change out of the directory to allow it to be deleted on Windows.
338
- FileUtils.chdir(@orig_pwd)
339
- end
340
- end
341
-
342
- def test_zoneinfo_dir
343
- Dir.mktmpdir('tzinfo_test') do |dir|
344
- FileUtils.touch(File.join(dir, 'zone.tab'))
345
- FileUtils.touch(File.join(dir, 'iso3166.tab'))
346
-
347
- data_source = ZoneinfoDataSource.new(dir)
348
- assert_equal(dir, data_source.zoneinfo_dir)
349
- assert_equal(true, data_source.zoneinfo_dir.frozen?)
350
- end
351
- end
352
-
353
- def test_load_timezone_info_data
354
- info = @data_source.load_timezone_info('Europe/London')
355
- assert_kind_of(ZoneinfoTimezoneInfo, info)
356
- assert_equal('Europe/London', info.identifier)
357
- end
358
-
359
- def test_load_timezone_info_linked
360
- info = @data_source.load_timezone_info('UTC')
361
-
362
- # On platforms that don't support symlinks, 'UTC' will be created as a copy.
363
- # Either way, a ZoneinfoTimezoneInfo should be returned.
364
-
365
- assert_kind_of(ZoneinfoTimezoneInfo, info)
366
- assert_equal('UTC', info.identifier)
367
- end
368
-
369
- def test_load_timezone_info_does_not_exist
370
- assert_raises(InvalidTimezoneIdentifier) do
371
- @data_source.load_timezone_info('Nowhere/Special')
372
- end
373
- end
374
-
375
- def test_load_timezone_info_invalid
376
- assert_raises(InvalidTimezoneIdentifier) do
377
- @data_source.load_timezone_info('../zoneinfo/Europe/London')
378
- end
379
- end
380
-
381
- %w(leapseconds localtime).each do |file_name|
382
- define_method("test_load_timezone_info_ignored_#{file_name}_file") do
383
- assert_raises(InvalidTimezoneIdentifier) do
384
- @data_source.load_timezone_info(file_name)
385
- end
386
- end
387
- end
388
-
389
- def test_load_timezone_info_ignored_plus_version_file
390
- # Mac OS X includes a file named +VERSION containing the tzdata version.
391
-
392
- Dir.mktmpdir('tzinfo_test') do |dir|
393
- FileUtils.touch(File.join(dir, 'zone.tab'))
394
- FileUtils.touch(File.join(dir, 'iso3166.tab'))
395
-
396
- File.open(File.join(dir, '+VERSION'), 'w') do |f|
397
- f.binmode
398
- f.write("2013a\n")
399
- end
400
-
401
- data_source = ZoneinfoDataSource.new(dir)
402
-
403
- assert_raises(InvalidTimezoneIdentifier) do
404
- data_source.load_timezone_info('+VERSION')
405
- end
406
- end
407
- end
408
-
409
- def test_load_timezone_info_ignored_timeconfig_symlink
410
- # Slackware includes a symlink named timeconfig that points at /usr/sbin/timeconfig.
411
-
412
- Dir.mktmpdir('tzinfo_test_target') do |target_dir|
413
- target_path = File.join(target_dir, 'timeconfig')
414
-
415
- File.open(target_path, 'w') do |f|
416
- f.write("#!/bin/sh\n")
417
- f.write("#\n")
418
- f.write('# timeconfig Slackware Linux timezone configuration utility.\n')
419
- end
420
-
421
- Dir.mktmpdir('tzinfo_test') do |dir|
422
- FileUtils.touch(File.join(dir, 'zone.tab'))
423
- FileUtils.touch(File.join(dir, 'iso3166.tab'))
424
- FileUtils.cp(File.join(@data_source.zoneinfo_dir, 'EST'), File.join(dir, 'EST'))
425
-
426
- symlink_path = File.join(dir, 'timeconfig')
427
- begin
428
- FileUtils.ln_s(target_path, symlink_path)
429
- rescue NotImplementedError, Errno::EACCES
430
- # Symlinks not supported on this platform, or permission denied
431
- # (administrative rights are required on Windows). Copy instead.
432
- FileUtils.cp(target_path, symlink_path)
433
- end
434
-
435
- data_source = ZoneinfoDataSource.new(dir)
436
-
437
- assert_raises(InvalidTimezoneIdentifier) do
438
- data_source.load_timezone_info('timeconfig')
439
- end
440
- end
441
- end
442
- end
443
-
444
- def test_load_timezone_info_nil
445
- assert_raises(InvalidTimezoneIdentifier) do
446
- @data_source.load_timezone_info(nil)
447
- end
448
- end
449
-
450
- def test_load_timezone_info_case
451
- assert_raises(InvalidTimezoneIdentifier) do
452
- @data_source.load_timezone_info('europe/london')
453
- end
454
- end
455
-
456
- def test_load_timezone_info_permission_denied
457
- Dir.mktmpdir('tzinfo_test') do |dir|
458
- FileUtils.touch(File.join(dir, 'zone.tab'))
459
- FileUtils.touch(File.join(dir, 'iso3166.tab'))
460
-
461
- file = File.join(dir, 'UTC')
462
- FileUtils.touch(file)
463
- FileUtils.chmod(0200, file)
464
-
465
- data_source = ZoneinfoDataSource.new(dir)
466
-
467
- assert_raises(InvalidTimezoneIdentifier) do
468
- data_source.load_timezone_info('UTC')
469
- end
470
- end
471
- end
472
-
473
- def test_load_timezone_info_directory
474
- Dir.mktmpdir('tzinfo_test') do |dir|
475
- FileUtils.touch(File.join(dir, 'zone.tab'))
476
- FileUtils.touch(File.join(dir, 'iso3166.tab'))
477
-
478
- subdir = File.join(dir, 'Subdir')
479
- FileUtils.mkdir(subdir)
480
-
481
- data_source = ZoneinfoDataSource.new(dir)
482
-
483
- assert_raises(InvalidTimezoneIdentifier) do
484
- data_source.load_timezone_info('Subdir')
485
- end
486
- end
487
- end
488
-
489
- def test_load_timezone_info_linked_absolute_outside
490
- Dir.mktmpdir('tzinfo_test') do |dir|
491
- Dir.mktmpdir('tzinfo_test') do |outside|
492
- outside_file = File.join(outside, 'EST')
493
- FileUtils.cp(File.join(@data_source.zoneinfo_dir, 'EST'), outside_file)
494
-
495
- FileUtils.touch(File.join(dir, 'zone.tab'))
496
- FileUtils.touch(File.join(dir, 'iso3166.tab'))
497
-
498
- file = File.join(dir, 'EST')
499
-
500
- begin
501
- FileUtils.ln_s(outside_file, file)
502
- rescue NotImplementedError, Errno::EACCES
503
- # Symlinks not supported on this platform, or permission denied
504
- # (administrative rights are required on Windows). Skip test.
505
- return
506
- end
507
-
508
- data_source = ZoneinfoDataSource.new(dir)
509
-
510
- info = data_source.load_timezone_info('EST')
511
- assert_kind_of(ZoneinfoTimezoneInfo, info)
512
- assert_equal('EST', info.identifier)
513
- end
514
- end
515
- end
516
-
517
- def test_load_timezone_info_linked_absolute_inside
518
- Dir.mktmpdir('tzinfo_test') do |dir|
519
- FileUtils.touch(File.join(dir, 'zone.tab'))
520
- FileUtils.touch(File.join(dir, 'iso3166.tab'))
521
-
522
- FileUtils.cp(File.join(@data_source.zoneinfo_dir, 'EST'), File.join(dir, 'EST'))
523
-
524
- link = File.join(dir, 'Link')
525
-
526
- begin
527
- FileUtils.ln_s(File.join(File.expand_path(dir), 'EST'), link)
528
- rescue NotImplementedError, Errno::EACCES
529
- # Symlinks not supported on this platform, or permission denied
530
- # (administrative rights are required on Windows). Skip test.
531
- return
532
- end
533
-
534
- data_source = ZoneinfoDataSource.new(dir)
535
-
536
- info = data_source.load_timezone_info('Link')
537
- assert_kind_of(ZoneinfoTimezoneInfo, info)
538
- assert_equal('Link', info.identifier)
539
- end
540
- end
541
-
542
- def test_load_timezone_info_linked_relative_outside
543
- Dir.mktmpdir('tzinfo_test') do |root|
544
- FileUtils.cp(File.join(@data_source.zoneinfo_dir, 'EST'), File.join(root, 'outside'))
545
-
546
- dir = File.join(root, 'zoneinfo')
547
- FileUtils.mkdir(dir)
548
-
549
- FileUtils.touch(File.join(dir, 'zone.tab'))
550
- FileUtils.touch(File.join(dir, 'iso3166.tab'))
551
-
552
- link = File.join(dir, 'Link')
553
-
554
- begin
555
- FileUtils.ln_s('../outside', link)
556
- rescue NotImplementedError, Errno::EACCES
557
- # Symlinks not supported on this platform, or permission denied
558
- # (administrative rights are required on Windows). Skip test.
559
- return
560
- end
561
-
562
- subdir = File.join(dir, 'Subdir')
563
- subdir_link = File.join(subdir, 'Link')
564
- FileUtils.mkdir(subdir)
565
- FileUtils.ln_s('../../outside', subdir_link)
566
-
567
- data_source = ZoneinfoDataSource.new(dir)
568
-
569
- info = data_source.load_timezone_info('Link')
570
- assert_kind_of(ZoneinfoTimezoneInfo, info)
571
- assert_equal('Link', info.identifier)
572
-
573
- info = data_source.load_timezone_info('Subdir/Link')
574
- assert_kind_of(ZoneinfoTimezoneInfo, info)
575
- assert_equal('Subdir/Link', info.identifier)
576
- end
577
- end
578
-
579
- def test_load_timezone_info_linked_relative_parent_inside
580
- Dir.mktmpdir('tzinfo_test') do |dir|
581
- FileUtils.touch(File.join(dir, 'zone.tab'))
582
- FileUtils.touch(File.join(dir, 'iso3166.tab'))
583
-
584
- FileUtils.cp(File.join(@data_source.zoneinfo_dir, 'EST'), File.join(dir, 'EST'))
585
-
586
- subdir = File.join(dir, 'Subdir')
587
- FileUtils.mkdir(subdir)
588
- FileUtils.cp(File.join(@data_source.zoneinfo_dir, 'EST'), File.join(subdir, 'EST'))
589
-
590
- subdir_link = File.join(subdir, 'Link')
591
- begin
592
- FileUtils.ln_s('../Subdir/EST', subdir_link)
593
- rescue NotImplementedError, Errno::EACCES
594
- # Symlinks not supported on this platform, or permission denied
595
- # (administrative rights are required on Windows). Skip test.
596
- return
597
- end
598
-
599
- subdir_link2 = File.join(subdir, 'Link2')
600
- FileUtils.ln_s('../EST', subdir_link2)
601
-
602
- subdir2 = File.join(dir, 'Subdir2')
603
- FileUtils.mkdir(subdir2)
604
- subdir2_link = File.join(subdir2, 'Link')
605
- FileUtils.ln_s('../Subdir/EST', subdir2_link)
606
-
607
- data_source = ZoneinfoDataSource.new(dir)
608
-
609
- info = data_source.load_timezone_info('Subdir/Link')
610
- assert_kind_of(ZoneinfoTimezoneInfo, info)
611
- assert_equal('Subdir/Link', info.identifier)
612
-
613
- info = data_source.load_timezone_info('Subdir/Link2')
614
- assert_kind_of(ZoneinfoTimezoneInfo, info)
615
- assert_equal('Subdir/Link2', info.identifier)
616
-
617
- info = data_source.load_timezone_info('Subdir2/Link')
618
- assert_kind_of(ZoneinfoTimezoneInfo, info)
619
- assert_equal('Subdir2/Link', info.identifier)
620
- end
621
- end
622
-
623
- def test_load_timezone_info_invalid_file
624
- Dir.mktmpdir('tzinfo_test') do |dir|
625
- FileUtils.touch(File.join(dir, 'zone.tab'))
626
- FileUtils.touch(File.join(dir, 'iso3166.tab'))
627
-
628
- File.open(File.join(dir, 'Zone'), 'wb') do |file|
629
- file.write('NotAValidTZifFile')
630
- end
631
-
632
- data_source = ZoneinfoDataSource.new(dir)
633
-
634
- assert_raises(InvalidTimezoneIdentifier) do
635
- data_source.load_timezone_info('Zone')
636
- end
637
- end
638
- end
639
-
640
- def test_load_timezone_info_invalid_file_2
641
- Dir.mktmpdir('tzinfo_test') do |dir|
642
- FileUtils.touch(File.join(dir, 'zone.tab'))
643
- FileUtils.touch(File.join(dir, 'iso3166.tab'))
644
-
645
- zone = File.join(dir, 'Zone')
646
-
647
- File.open(File.join(@data_source.zoneinfo_dir, 'EST')) do |src|
648
- # Change header to TZif1 (which is not a valid header).
649
- File.open(zone, 'wb') do |dest|
650
- dest.write('TZif1')
651
- src.pos = 5
652
- FileUtils.copy_stream(src, dest)
653
- end
654
- end
655
-
656
- data_source = ZoneinfoDataSource.new(dir)
657
-
658
- assert_raises(InvalidTimezoneIdentifier) do
659
- data_source.load_timezone_info('Zone')
660
- end
661
- end
662
- end
663
-
664
- def test_load_timezone_info_tainted
665
- safe_test(:unavailable => :skip) do
666
- identifier = 'Europe/Amsterdam'.dup.taint
667
- assert(identifier.tainted?)
668
- info = @data_source.load_timezone_info(identifier)
669
- assert_equal('Europe/Amsterdam', info.identifier)
670
- assert(identifier.tainted?)
671
- end
672
- end
673
-
674
- def test_load_timezone_info_tainted_and_frozen
675
- safe_test do
676
- info = @data_source.load_timezone_info('Europe/Amsterdam'.dup.taint.freeze)
677
- assert_equal('Europe/Amsterdam', info.identifier)
678
- end
679
- end
680
-
681
- def test_load_timezone_info_tainted_zoneinfo_dir_safe_mode
682
- safe_test(:unavailable => :skip) do
683
- assert_raises(SecurityError) do
684
- ZoneinfoDataSource.new(@data_source.zoneinfo_dir.dup.taint)
685
- end
686
- end
687
- end
688
-
689
- def test_load_timezone_info_tainted_zoneinfo_dir
690
- data_source = ZoneinfoDataSource.new(@data_source.zoneinfo_dir.dup.taint)
691
- info = data_source.load_timezone_info('Europe/London')
692
- assert_kind_of(ZoneinfoTimezoneInfo, info)
693
- assert_equal('Europe/London', info.identifier)
694
- end
695
-
696
- def get_timezone_filenames(directory)
697
- entries = Dir.glob(File.join(directory, '**', '*'))
698
-
699
- entries = entries.select do |file|
700
- file.untaint
701
- File.file?(file)
702
- end
703
-
704
- entries = entries.collect {|file| file[directory.length + File::SEPARATOR.length, file.length - directory.length - File::SEPARATOR.length]}
705
-
706
- # Exclude right (with leapseconds) and posix (copy) directories; .tab files; leapseconds, localtime and posixrules files.
707
- entries = entries.select do |file|
708
- file !~ /\A(posix|right)\// &&
709
- file !~ /\.tab\z/ &&
710
- !%w(leapseconds localtime posixrules).include?(file)
711
- end
712
-
713
- entries.sort
714
- end
715
-
716
- def test_timezone_identifiers
717
- expected = get_timezone_filenames(@data_source.zoneinfo_dir)
718
- all = @data_source.timezone_identifiers
719
- assert_kind_of(Array, all)
720
- assert_array_same_items(expected, all)
721
- assert_equal(true, all.frozen?)
722
- end
723
-
724
- def test_data_timezone_identifiers
725
- expected = get_timezone_filenames(@data_source.zoneinfo_dir)
726
- all_data = @data_source.data_timezone_identifiers
727
- assert_kind_of(Array, all_data)
728
- assert_array_same_items(expected, all_data)
729
- assert_equal(true, all_data.frozen?)
730
- end
731
-
732
- def test_linked_timezone_identifiers
733
- all_linked = @data_source.linked_timezone_identifiers
734
- assert_kind_of(Array, all_linked)
735
- assert_equal(true, all_linked.empty?)
736
- assert_equal(true, all_linked.frozen?)
737
- end
738
-
739
- def test_timezone_identifiers_safe_mode
740
- safe_test do
741
- expected = get_timezone_filenames(@data_source.zoneinfo_dir)
742
- all = @data_source.timezone_identifiers
743
- assert_kind_of(Array, all)
744
- assert_array_same_items(expected, all)
745
- assert_equal(true, all.frozen?)
746
- end
747
- end
748
-
749
- def test_timezone_identifiers_ignored_plus_version_file
750
- # Mac OS X includes a file named +VERSION containing the tzdata version.
751
-
752
- Dir.mktmpdir('tzinfo_test') do |dir|
753
- FileUtils.touch(File.join(dir, 'zone.tab'))
754
- FileUtils.touch(File.join(dir, 'iso3166.tab'))
755
- FileUtils.cp(File.join(@data_source.zoneinfo_dir, 'EST'), File.join(dir, 'EST'))
756
-
757
- File.open(File.join(dir, '+VERSION'), 'w') do |f|
758
- f.binmode
759
- f.write("2013a\n")
760
- end
761
-
762
- data_source = ZoneinfoDataSource.new(dir)
763
- assert_array_same_items(['EST'], data_source.timezone_identifiers)
764
- end
765
- end
766
-
767
- def test_timezone_identifiers_ignored_timeconfig_symlink
768
- # Slackware includes a symlink named timeconfig that points at /usr/sbin/timeconfig.
769
-
770
- Dir.mktmpdir('tzinfo_test_target') do |target_dir|
771
- target_path = File.join(target_dir, 'timeconfig')
772
-
773
- File.open(target_path, 'w') do |f|
774
- f.write("#!/bin/sh\n")
775
- f.write("#\n")
776
- f.write('# timeconfig Slackware Linux timezone configuration utility.\n')
777
- end
778
-
779
- Dir.mktmpdir('tzinfo_test') do |dir|
780
- FileUtils.touch(File.join(dir, 'zone.tab'))
781
- FileUtils.touch(File.join(dir, 'iso3166.tab'))
782
- FileUtils.cp(File.join(@data_source.zoneinfo_dir, 'EST'), File.join(dir, 'EST'))
783
-
784
- symlink_path = File.join(dir, 'timeconfig')
785
- begin
786
- FileUtils.ln_s(target_path, symlink_path)
787
- rescue NotImplementedError, Errno::EACCES
788
- # Symlinks not supported on this platform, or permission denied
789
- # (administrative rights are required on Windows). Copy instead.
790
- FileUtils.cp(target_path, symlink_path)
791
- end
792
-
793
- data_source = ZoneinfoDataSource.new(dir)
794
- assert_array_same_items(['EST'], data_source.timezone_identifiers)
795
- end
796
- end
797
- end
798
-
799
- def test_timezone_identifiers_ignored_src_directory
800
- # Solaris includes a src directory containing the source timezone data files
801
- # from the tzdata distribution. These should be ignored.
802
-
803
- Dir.mktmpdir('tzinfo_test') do |dir|
804
- FileUtils.touch(File.join(dir, 'zone.tab'))
805
- FileUtils.touch(File.join(dir, 'iso3166.tab'))
806
- FileUtils.cp(File.join(@data_source.zoneinfo_dir, 'EST'), File.join(dir, 'EST'))
807
-
808
- src_dir = File.join(dir, 'src')
809
- FileUtils.mkdir(src_dir)
810
-
811
- File.open(File.join(src_dir, 'europe'), 'w') do |f|
812
- f.binmode
813
- f.write("Zone\tEurope/London\t0:00\tEU\tGMT/BST\n")
814
- end
815
-
816
- data_source = ZoneinfoDataSource.new(dir)
817
- assert_array_same_items(['EST'], data_source.timezone_identifiers)
818
- end
819
- end
820
-
821
- def test_timezone_identifiers_ignored_security_file
822
- # The Arch linux tzdata package includes a file named SECURITY giving
823
- # instructions for reporting security-related bugs.
824
-
825
- Dir.mktmpdir('tzinfo_test') do |dir|
826
- FileUtils.touch(File.join(dir, 'zone.tab'))
827
- FileUtils.touch(File.join(dir, 'iso3166.tab'))
828
- FileUtils.cp(File.join(@data_source.zoneinfo_dir, 'EST'), File.join(dir, 'EST'))
829
-
830
- File.open(File.join(dir, 'SECURITY'), 'w') do |f|
831
- f.binmode
832
- f.write("Please report any sensitive security-related bugs...\n")
833
- end
834
-
835
- data_source = ZoneinfoDataSource.new(dir)
836
- assert_equal(['EST'], data_source.timezone_identifiers)
837
- end
838
- end
839
-
840
- def test_load_country_info
841
- info = @data_source.load_country_info('GB')
842
- assert_equal('GB', info.code)
843
- assert_equal('Britain (UK)', info.name)
844
- end
845
-
846
- def test_load_country_info_not_exist
847
- assert_raises(InvalidCountryCode) do
848
- @data_source.load_country_info('ZZ')
849
- end
850
- end
851
-
852
- def test_load_country_info_invalid
853
- assert_raises(InvalidCountryCode) do
854
- @data_source.load_country_info('../Countries/GB')
855
- end
856
- end
857
-
858
- def test_load_country_info_nil
859
- assert_raises(InvalidCountryCode) do
860
- @data_source.load_country_info(nil)
861
- end
862
- end
863
-
864
- def test_load_country_info_case
865
- assert_raises(InvalidCountryCode) do
866
- @data_source.load_country_info('gb')
867
- end
868
- end
869
-
870
- def test_load_country_info_tainted
871
- safe_test(:unavailable => :skip) do
872
- code = 'NL'.dup.taint
873
- assert(code.tainted?)
874
- info = @data_source.load_country_info(code)
875
- assert_equal('NL', info.code)
876
- assert(code.tainted?)
877
- end
878
- end
879
-
880
- def test_load_country_info_tainted_and_frozen
881
- safe_test do
882
- info = @data_source.load_country_info('NL'.dup.taint.freeze)
883
- assert_equal('NL', info.code)
884
- end
885
- end
886
-
887
- def test_load_country_info_check_zones
888
- Dir.mktmpdir('tzinfo_test') do |dir|
889
- RubyCoreSupport.open_file(File.join(dir, 'iso3166.tab'), 'w', :external_encoding => 'UTF-8') do |iso3166|
890
- iso3166.puts('# iso3166.tab')
891
- iso3166.puts('')
892
- iso3166.puts("FC\tFake Country")
893
- iso3166.puts("OC\tOther Country")
894
- end
895
-
896
- RubyCoreSupport.open_file(File.join(dir, 'zone.tab'), 'w', :external_encoding => 'UTF-8') do |zone|
897
- zone.puts('# zone.tab')
898
- zone.puts('')
899
- zone.puts("FC\t+513030-0000731\tFake/One\tDescription of one")
900
- zone.puts("FC\t+353916+1394441\tFake/Two\tAnother description")
901
- zone.puts("FC\t-2332-04637\tFake/Three\tThis is Three")
902
- zone.puts("OC\t+5005+01426\tOther/One")
903
- end
904
-
905
- data_source = ZoneinfoDataSource.new(dir)
906
-
907
- info = data_source.load_country_info('FC')
908
- assert_equal('FC', info.code)
909
- assert_equal('Fake Country', info.name)
910
- assert_equal(['Fake/One', 'Fake/Two', 'Fake/Three'], info.zone_identifiers)
911
- assert_equal(true, info.zone_identifiers.frozen?)
912
- assert_equal([
913
- CountryTimezone.new('Fake/One', Rational(6181, 120), Rational(-451, 3600), 'Description of one'),
914
- CountryTimezone.new('Fake/Two', Rational(32089, 900), Rational(503081, 3600), 'Another description'),
915
- CountryTimezone.new('Fake/Three', Rational(-353, 15), Rational(-2797, 60), 'This is Three')], info.zones)
916
- assert_equal(true, info.zones.frozen?)
917
-
918
- info = data_source.load_country_info('OC')
919
- assert_equal('OC', info.code)
920
- assert_equal('Other Country', info.name)
921
- assert_equal(['Other/One'], info.zone_identifiers)
922
- assert_equal(true, info.zone_identifiers.frozen?)
923
- assert_equal([CountryTimezone.new('Other/One', Rational(601, 12), Rational(433, 30))], info.zones)
924
- assert_equal(true, info.zones.frozen?)
925
- end
926
- end
927
-
928
- def test_load_country_info_check_zones_zone1970
929
- Dir.mktmpdir('tzinfo_test') do |dir|
930
- RubyCoreSupport.open_file(File.join(dir, 'iso3166.tab'), 'w', :external_encoding => 'UTF-8') do |iso3166|
931
- iso3166.puts('# iso3166.tab')
932
- iso3166.puts('')
933
- iso3166.puts("AC\tAnother Country")
934
- iso3166.puts("FC\tFake Country")
935
- iso3166.puts("OC\tOther Country")
936
- end
937
-
938
- # zone.tab will be ignored.
939
- RubyCoreSupport.open_file(File.join(dir, 'zone.tab'), 'w', :external_encoding => 'UTF-8') do |zone|
940
- zone.puts('# zone.tab')
941
- zone.puts('')
942
- zone.puts("FC\t+513030-0000731\tFake/One\tDescription of one")
943
- zone.puts("FC\t+353916+1394441\tFake/Two\tAnother description")
944
- zone.puts("FC\t-2332-04637\tFake/Three\tThis is Three")
945
- zone.puts("OC\t+5005+01426\tOther/One")
946
- end
947
-
948
- # zone1970.tab will be used.
949
- RubyCoreSupport.open_file(File.join(dir, 'zone1970.tab'), 'w', :external_encoding => 'UTF-8') do |zone|
950
- zone.puts('# zone1970.tab')
951
- zone.puts('')
952
- zone.puts("AC,OC\t+0000+00000\tMiddle/Another/One\tAnother's One")
953
- zone.puts("FC\t+513030-0000731\tFake/One\tDescription of one")
954
- zone.puts("FC,OC\t+353916+1394441\tFake/Two\tAnother description")
955
- zone.puts("FC,OC\t-2332-04637\tFake/Three\tThis is Three")
956
- zone.puts("OC\t+5005+01426\tOther/One")
957
- zone.puts("OC\t+5015+11426\tOther/Two")
958
- end
959
-
960
- data_source = ZoneinfoDataSource.new(dir)
961
-
962
- info = data_source.load_country_info('AC')
963
- assert_equal('AC', info.code)
964
- assert_equal('Another Country', info.name)
965
- assert_equal(['Middle/Another/One'], info.zone_identifiers)
966
- assert_equal(true, info.zone_identifiers.frozen?)
967
- assert_equal([CountryTimezone.new('Middle/Another/One', Rational(0, 1), Rational(0, 1), "Another's One")], info.zones)
968
- assert_equal(true, info.zones.frozen?)
969
-
970
- info = data_source.load_country_info('FC')
971
- assert_equal('FC', info.code)
972
- assert_equal('Fake Country', info.name)
973
- assert_equal(['Fake/One', 'Fake/Two', 'Fake/Three'], info.zone_identifiers)
974
- assert_equal(true, info.zone_identifiers.frozen?)
975
- assert_equal([
976
- CountryTimezone.new('Fake/One', Rational(6181, 120), Rational(-451, 3600), 'Description of one'),
977
- CountryTimezone.new('Fake/Two', Rational(32089, 900), Rational(503081, 3600), 'Another description'),
978
- CountryTimezone.new('Fake/Three', Rational(-353, 15), Rational(-2797, 60), 'This is Three')], info.zones)
979
- assert_equal(true, info.zones.frozen?)
980
-
981
- # Testing the ordering of zones. A zone can either be primary (country
982
- # code is the first in the first column), or secondary (country code is
983
- # not the first). Should return all the primaries first in the order they
984
- # appeared in the file, followed by all the secondaries in the order they
985
- # appeared in file.
986
-
987
- info = data_source.load_country_info('OC')
988
- assert_equal('OC', info.code)
989
- assert_equal('Other Country', info.name)
990
- assert_equal(['Other/One', 'Other/Two', 'Middle/Another/One', 'Fake/Two', 'Fake/Three'], info.zone_identifiers)
991
- assert_equal(true, info.zone_identifiers.frozen?)
992
- assert_equal([
993
- CountryTimezone.new('Other/One', Rational(601, 12), Rational( 433, 30)),
994
- CountryTimezone.new('Other/Two', Rational(201, 4), Rational(3433, 30)),
995
- CountryTimezone.new('Middle/Another/One', Rational(0, 1), Rational(0, 1), "Another's One"),
996
- CountryTimezone.new('Fake/Two', Rational(32089, 900), Rational(503081, 3600), 'Another description'),
997
- CountryTimezone.new('Fake/Three', Rational(-353, 15), Rational(-2797, 60), 'This is Three')], info.zones)
998
- assert_equal(true, info.zones.frozen?)
999
- end
1000
- end
1001
-
1002
- def test_load_country_info_check_zones_solaris_tab_files
1003
- # Solaris uses 5 columns instead of the usual 4 in zone_sun.tab.
1004
- # An extra column before the comment gives an optional linked/alternate
1005
- # timezone identifier (or '-' if not set).
1006
- #
1007
- # Additionally, there is a section at the end of the file for timezones
1008
- # covering regions. These are given lower-case "country" codes. The timezone
1009
- # identifier column refers to a continent instead of an identifier. These
1010
- # lines will be ignored by TZInfo.
1011
-
1012
- Dir.mktmpdir('tzinfo_test') do |dir|
1013
- tab_dir = File.join(dir, 'tab')
1014
- FileUtils.mkdir(tab_dir)
1015
-
1016
- RubyCoreSupport.open_file(File.join(tab_dir, 'country.tab'), 'w', :external_encoding => 'UTF-8') do |country|
1017
- country.puts('# country.tab')
1018
- country.puts('# Solaris')
1019
- country.puts("FC\tFake Country")
1020
- country.puts("OC\tOther Country")
1021
- end
1022
-
1023
- RubyCoreSupport.open_file(File.join(tab_dir, 'zone_sun.tab'), 'w', :external_encoding => 'UTF-8') do |zone_sun|
1024
- zone_sun.puts('# zone_sun.tab')
1025
- zone_sun.puts('# Solaris')
1026
- zone_sun.puts('# Countries')
1027
- zone_sun.puts("FC\t+513030-0000731\tFake/One\t-\tDescription of one")
1028
- zone_sun.puts("FC\t+353916+1394441\tFake/Two\tFake/Alias/Two\tAnother description")
1029
- zone_sun.puts("FC\t-2332-04637\tFake/Three\tFake/Alias/Three\tThis is Three")
1030
- zone_sun.puts("OC\t+5005+01426\tOther/One\tOther/Linked/One")
1031
- zone_sun.puts("OC\t+5015+01436\tOther/Two\t-")
1032
- zone_sun.puts('# Regions')
1033
- zone_sun.puts("ee\t+0000+00000\tEurope/\tEET")
1034
- zone_sun.puts("me\t+0000+00000\tEurope/\tMET")
1035
- zone_sun.puts("we\t+0000+00000\tEurope/\tWET")
1036
- end
1037
-
1038
- data_source = ZoneinfoDataSource.new(dir)
1039
-
1040
- info = data_source.load_country_info('FC')
1041
- assert_equal('FC', info.code)
1042
- assert_equal('Fake Country', info.name)
1043
- assert_equal(['Fake/One', 'Fake/Two', 'Fake/Three'], info.zone_identifiers)
1044
- assert_equal(true, info.zone_identifiers.frozen?)
1045
- assert_equal([
1046
- CountryTimezone.new('Fake/One', Rational(6181, 120), Rational(-451, 3600), 'Description of one'),
1047
- CountryTimezone.new('Fake/Two', Rational(32089, 900), Rational(503081, 3600), 'Another description'),
1048
- CountryTimezone.new('Fake/Three', Rational(-353, 15), Rational(-2797, 60), 'This is Three')], info.zones)
1049
- assert_equal(true, info.zones.frozen?)
1050
-
1051
- info = data_source.load_country_info('OC')
1052
- assert_equal('OC', info.code)
1053
- assert_equal('Other Country', info.name)
1054
- assert_equal(['Other/One', 'Other/Two'], info.zone_identifiers)
1055
- assert_equal(true, info.zone_identifiers.frozen?)
1056
- assert_equal([
1057
- CountryTimezone.new('Other/One', Rational(601, 12), Rational(433, 30)),
1058
- CountryTimezone.new('Other/Two', Rational(201, 4), Rational(73, 5))], info.zones)
1059
- assert_equal(true, info.zones.frozen?)
1060
- end
1061
- end
1062
-
1063
- def test_load_country_info_check_zones_alternate_iso3166_file
1064
- Dir.mktmpdir('tzinfo_test') do |dir|
1065
- zoneinfo_dir = File.join(dir, 'zoneinfo')
1066
- tab_dir = File.join(dir, 'tab')
1067
- FileUtils.mkdir(zoneinfo_dir)
1068
- FileUtils.mkdir(tab_dir)
1069
-
1070
- tab_file = File.join(tab_dir, 'iso3166')
1071
- RubyCoreSupport.open_file(tab_file, 'w', :external_encoding => 'UTF-8') do |iso3166|
1072
- # Use the BSD 4 column format (alternate iso3166 is used on BSD).
1073
- iso3166.puts("FC\tFCC\t001\tFake Country")
1074
- iso3166.puts("OC\tOCC\t002\tOther Country")
1075
- end
1076
-
1077
- RubyCoreSupport.open_file(File.join(zoneinfo_dir, 'zone.tab'), 'w', :external_encoding => 'UTF-8') do |zone|
1078
- zone.puts("FC\t+513030-0000731\tFake/One\tDescription of one")
1079
- zone.puts("FC\t+353916+1394441\tFake/Two\tAnother description")
1080
- zone.puts("FC\t-2332-04637\tFake/Three\tThis is Three")
1081
- zone.puts("OC\t+5005+01426\tOther/One")
1082
- end
1083
-
1084
- data_source = ZoneinfoDataSource.new(zoneinfo_dir, tab_file)
1085
-
1086
- info = data_source.load_country_info('FC')
1087
- assert_equal('FC', info.code)
1088
- assert_equal('Fake Country', info.name)
1089
- assert_equal(['Fake/One', 'Fake/Two', 'Fake/Three'], info.zone_identifiers)
1090
- assert_equal(true, info.zone_identifiers.frozen?)
1091
- assert_equal([
1092
- CountryTimezone.new('Fake/One', Rational(6181, 120), Rational(-451, 3600), 'Description of one'),
1093
- CountryTimezone.new('Fake/Two', Rational(32089, 900), Rational(503081, 3600), 'Another description'),
1094
- CountryTimezone.new('Fake/Three', Rational(-353, 15), Rational(-2797, 60), 'This is Three')], info.zones)
1095
- assert_equal(true, info.zones.frozen?)
1096
-
1097
- info = data_source.load_country_info('OC')
1098
- assert_equal('OC', info.code)
1099
- assert_equal('Other Country', info.name)
1100
- assert_equal(['Other/One'], info.zone_identifiers)
1101
- assert_equal(true, info.zone_identifiers.frozen?)
1102
- assert_equal([CountryTimezone.new('Other/One', Rational(601, 12), Rational(433, 30))], info.zones)
1103
- assert_equal(true, info.zones.frozen?)
1104
- end
1105
- end
1106
-
1107
- def test_load_country_info_four_column_iso31611
1108
- # OpenBSD and FreeBSD use a 4 column iso3166.tab file that includes
1109
- # alpha-3 and numeric-3 codes in addition to the alpha-2 and name in the
1110
- # tz database version.
1111
-
1112
- Dir.mktmpdir('tzinfo_test') do |dir|
1113
- RubyCoreSupport.open_file(File.join(dir, 'iso3166.tab'), 'w', :external_encoding => 'UTF-8') do |iso3166|
1114
- iso3166.puts("FC\tFCC\t001\tFake Country")
1115
- iso3166.puts("OC\tOCC\t002\tOther Country")
1116
- end
1117
-
1118
- RubyCoreSupport.open_file(File.join(dir, 'zone.tab'), 'w', :external_encoding => 'UTF-8') do |zone|
1119
- zone.puts("FC\t+513030-0000731\tFake/One\tDescription of one")
1120
- zone.puts("OC\t+5005+01426\tOther/One")
1121
- end
1122
-
1123
- data_source = ZoneinfoDataSource.new(dir)
1124
-
1125
- info = data_source.load_country_info('FC')
1126
- assert_equal('FC', info.code)
1127
- assert_equal('Fake Country', info.name)
1128
-
1129
- info = data_source.load_country_info('OC')
1130
- assert_equal('OC', info.code)
1131
- assert_equal('Other Country', info.name)
1132
- end
1133
- end
1134
-
1135
- def test_load_country_info_utf8
1136
- # iso3166.tab is currently in ASCII (as of tzdata 2014f), but will be
1137
- # changed to UTF-8 in the future.
1138
-
1139
- # zone.tab is in ASCII, with no plans to change. Since ASCII is a subset of
1140
- # UTF-8, test that this is loaded in UTF-8 anyway.
1141
-
1142
- Dir.mktmpdir('tzinfo_test') do |dir|
1143
- RubyCoreSupport.open_file(File.join(dir, 'iso3166.tab'), 'w', :external_encoding => 'UTF-8') do |iso3166|
1144
- iso3166.puts("UT\tUnicode Test ✓")
1145
- end
1146
-
1147
- RubyCoreSupport.open_file(File.join(dir, 'zone.tab'), 'w', :external_encoding => 'UTF-8') do |zone|
1148
- zone.puts("UT\t+513030-0000731\tUnicode✓/One\tUnicode Description ✓")
1149
- end
1150
-
1151
- data_source = ZoneinfoDataSource.new(dir)
1152
-
1153
- info = data_source.load_country_info('UT')
1154
- assert_equal('UT', info.code)
1155
- assert_equal('Unicode Test ✓', info.name)
1156
- assert_equal(['Unicode✓/One'], info.zone_identifiers)
1157
- assert_equal([CountryTimezone.new('Unicode✓/One', Rational(6181, 120), Rational(-451, 3600), 'Unicode Description ✓')], info.zones)
1158
- end
1159
- end
1160
-
1161
- def test_load_country_info_utf8_zone1970
1162
- # iso3166.tab is currently in ASCII (as of tzdata 2014f), but will be
1163
- # changed to UTF-8 in the future.
1164
-
1165
- # zone1970.tab is in UTF-8.
1166
-
1167
- Dir.mktmpdir('tzinfo_test') do |dir|
1168
- RubyCoreSupport.open_file(File.join(dir, 'iso3166.tab'), 'w', :external_encoding => 'UTF-8') do |iso3166|
1169
- iso3166.puts("UT\tUnicode Test ✓")
1170
- end
1171
-
1172
- RubyCoreSupport.open_file(File.join(dir, 'zone1970.tab'), 'w', :external_encoding => 'UTF-8') do |zone|
1173
- zone.puts("UT\t+513030-0000731\tUnicode✓/One\tUnicode Description ✓")
1174
- end
1175
-
1176
- data_source = ZoneinfoDataSource.new(dir)
1177
-
1178
- info = data_source.load_country_info('UT')
1179
- assert_equal('UT', info.code)
1180
- assert_equal('Unicode Test ✓', info.name)
1181
- assert_equal(['Unicode✓/One'], info.zone_identifiers)
1182
- assert_equal([CountryTimezone.new('Unicode✓/One', Rational(6181, 120), Rational(-451, 3600), 'Unicode Description ✓')], info.zones)
1183
- end
1184
- end
1185
-
1186
- def test_country_codes
1187
- file_codes = []
1188
-
1189
- RubyCoreSupport.open_file(File.join(@data_source.zoneinfo_dir, 'iso3166.tab'), 'r', :external_encoding => 'UTF-8', :internal_encoding => 'UTF-8') do |file|
1190
- file.each_line do |line|
1191
- line.chomp!
1192
- file_codes << $1 if line =~ /\A([A-Z]{2})\t/
1193
- end
1194
- end
1195
-
1196
- codes = @data_source.country_codes
1197
- assert_array_same_items(file_codes, codes)
1198
- assert_equal(true, codes.frozen?)
1199
- end
1200
-
1201
- def test_country_codes_four_column_iso3166
1202
- # OpenBSD and FreeBSD use a 4 column iso3166.tab file that includes
1203
- # alpha-3 and numeric-3 codes in addition to the alpha-2 and name in the
1204
- # tz database version.
1205
-
1206
- Dir.mktmpdir('tzinfo_test') do |dir|
1207
- RubyCoreSupport.open_file(File.join(dir, 'iso3166.tab'), 'w', :external_encoding => 'UTF-8') do |iso3166|
1208
- iso3166.puts("FC\tFCC\t001\tFake Country")
1209
- iso3166.puts("OC\tOCC\t002\tOther Country")
1210
- end
1211
-
1212
- RubyCoreSupport.open_file(File.join(dir, 'zone.tab'), 'w', :external_encoding => 'UTF-8') do |zone|
1213
- zone.puts("FC\t+513030-0000731\tFake/One\tDescription of one")
1214
- zone.puts("OC\t+5005+01426\tOther/One")
1215
- end
1216
-
1217
- data_source = ZoneinfoDataSource.new(dir)
1218
-
1219
- codes = data_source.country_codes
1220
- assert_array_same_items(%w(FC OC), codes)
1221
- end
1222
- end
1223
- end