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