tzinfo 1.1.0 → 1.2.0

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.

Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/CHANGES.md +33 -0
  5. data/LICENSE +1 -1
  6. data/README.md +36 -31
  7. data/Rakefile +17 -23
  8. data/lib/tzinfo.rb +0 -22
  9. data/lib/tzinfo/country.rb +3 -22
  10. data/lib/tzinfo/country_index_definition.rb +0 -22
  11. data/lib/tzinfo/country_info.rb +0 -22
  12. data/lib/tzinfo/country_timezone.rb +46 -31
  13. data/lib/tzinfo/data_source.rb +7 -24
  14. data/lib/tzinfo/data_timezone.rb +7 -22
  15. data/lib/tzinfo/data_timezone_info.rb +0 -22
  16. data/lib/tzinfo/info_timezone.rb +0 -22
  17. data/lib/tzinfo/linked_timezone.rb +7 -22
  18. data/lib/tzinfo/linked_timezone_info.rb +0 -22
  19. data/lib/tzinfo/offset_rationals.rb +0 -22
  20. data/lib/tzinfo/ruby_core_support.rb +14 -22
  21. data/lib/tzinfo/ruby_country_info.rb +3 -25
  22. data/lib/tzinfo/ruby_data_source.rb +1 -23
  23. data/lib/tzinfo/time_or_datetime.rb +13 -27
  24. data/lib/tzinfo/timezone.rb +51 -23
  25. data/lib/tzinfo/timezone_definition.rb +0 -22
  26. data/lib/tzinfo/timezone_index_definition.rb +0 -22
  27. data/lib/tzinfo/timezone_info.rb +0 -22
  28. data/lib/tzinfo/timezone_offset.rb +0 -22
  29. data/lib/tzinfo/timezone_period.rb +1 -23
  30. data/lib/tzinfo/timezone_proxy.rb +6 -23
  31. data/lib/tzinfo/timezone_transition.rb +2 -24
  32. data/lib/tzinfo/timezone_transition_definition.rb +1 -23
  33. data/lib/tzinfo/transition_data_timezone_info.rb +0 -22
  34. data/lib/tzinfo/zoneinfo_country_info.rb +1 -23
  35. data/lib/tzinfo/zoneinfo_data_source.rb +177 -61
  36. data/lib/tzinfo/zoneinfo_timezone_info.rb +0 -22
  37. data/test/tc_country.rb +6 -24
  38. data/test/tc_country_index_definition.rb +1 -23
  39. data/test/tc_country_info.rb +1 -23
  40. data/test/tc_country_timezone.rb +82 -62
  41. data/test/tc_data_source.rb +22 -24
  42. data/test/tc_data_timezone.rb +12 -24
  43. data/test/tc_data_timezone_info.rb +1 -23
  44. data/test/tc_info_timezone.rb +1 -23
  45. data/test/tc_linked_timezone.rb +37 -24
  46. data/test/tc_linked_timezone_info.rb +1 -23
  47. data/test/tc_offset_rationals.rb +1 -23
  48. data/test/tc_ruby_core_support.rb +84 -33
  49. data/test/tc_ruby_country_info.rb +5 -27
  50. data/test/tc_ruby_data_source.rb +1 -23
  51. data/test/tc_time_or_datetime.rb +44 -36
  52. data/test/tc_timezone.rb +32 -48
  53. data/test/tc_timezone_definition.rb +1 -23
  54. data/test/tc_timezone_index_definition.rb +1 -23
  55. data/test/tc_timezone_info.rb +1 -23
  56. data/test/tc_timezone_london.rb +1 -23
  57. data/test/tc_timezone_melbourne.rb +1 -23
  58. data/test/tc_timezone_new_york.rb +1 -23
  59. data/test/tc_timezone_offset.rb +1 -23
  60. data/test/tc_timezone_period.rb +5 -27
  61. data/test/tc_timezone_proxy.rb +34 -28
  62. data/test/tc_timezone_transition.rb +1 -23
  63. data/test/tc_timezone_transition_definition.rb +1 -23
  64. data/test/tc_timezone_utc.rb +1 -23
  65. data/test/tc_transition_data_timezone_info.rb +3 -25
  66. data/test/tc_zoneinfo_country_info.rb +13 -35
  67. data/test/tc_zoneinfo_data_source.rb +358 -34
  68. data/test/tc_zoneinfo_timezone_info.rb +3 -27
  69. data/test/test_utils.rb +26 -30
  70. data/test/ts_all.rb +0 -22
  71. data/test/ts_all_ruby.rb +0 -22
  72. data/test/ts_all_zoneinfo.rb +0 -22
  73. data/test/tzinfo-data/tzinfo/data.rb +0 -22
  74. data/test/tzinfo-data/tzinfo/data/version.rb +0 -22
  75. data/tzinfo.gemspec +2 -2
  76. metadata +80 -80
  77. metadata.gz.sig +1 -3
@@ -1,31 +1,9 @@
1
- #--
2
- # Copyright (c) 2005-2013 Philip Ross
3
- #
4
- # Permission is hereby granted, free of charge, to any person obtaining a copy
5
- # of this software and associated documentation files (the "Software"), to deal
6
- # in the Software without restriction, including without limitation the rights
7
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
- # copies of the Software, and to permit persons to whom the Software is
9
- # furnished to do so, subject to the following conditions:
10
- #
11
- # The above copyright notice and this permission notice shall be included in all
12
- # copies or substantial portions of the Software.
13
- #
14
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
- # THE SOFTWARE.
21
- #++
22
-
23
1
  require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils')
24
2
  require 'date'
25
3
 
26
4
  include TZInfo
27
5
 
28
- class TCTimezoneTransition < Test::Unit::TestCase
6
+ class TCTimezoneTransition < Minitest::Test
29
7
 
30
8
  class TestTimezoneTransition < TimezoneTransition
31
9
  def initialize(offset, previous_offset, at)
@@ -1,31 +1,9 @@
1
- #--
2
- # Copyright (c) 2013 Philip Ross
3
- #
4
- # Permission is hereby granted, free of charge, to any person obtaining a copy
5
- # of this software and associated documentation files (the "Software"), to deal
6
- # in the Software without restriction, including without limitation the rights
7
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
- # copies of the Software, and to permit persons to whom the Software is
9
- # furnished to do so, subject to the following conditions:
10
- #
11
- # The above copyright notice and this permission notice shall be included in all
12
- # copies or substantial portions of the Software.
13
- #
14
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
- # THE SOFTWARE.
21
- #++
22
-
23
1
  require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils')
24
2
  require 'date'
25
3
 
26
4
  include TZInfo
27
5
 
28
- class TCTimezoneTransitionDefinition < Test::Unit::TestCase
6
+ class TCTimezoneTransitionDefinition < Minitest::Test
29
7
  def test_initialize_timestamp_only
30
8
  assert_nothing_raised do
31
9
  TimezoneTransitionDefinition.new(TimezoneOffset.new(3600, 3600, :TDT),
@@ -1,30 +1,8 @@
1
- #--
2
- # Copyright (c) 2006-2013 Philip Ross
3
- #
4
- # Permission is hereby granted, free of charge, to any person obtaining a copy
5
- # of this software and associated documentation files (the "Software"), to deal
6
- # in the Software without restriction, including without limitation the rights
7
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
- # copies of the Software, and to permit persons to whom the Software is
9
- # furnished to do so, subject to the following conditions:
10
- #
11
- # The above copyright notice and this permission notice shall be included in all
12
- # copies or substantial portions of the Software.
13
- #
14
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
- # THE SOFTWARE.
21
- #++
22
-
23
1
  require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils')
24
2
 
25
3
  include TZInfo
26
4
 
27
- class TCTimezoneUTC < Test::Unit::TestCase
5
+ class TCTimezoneUTC < Minitest::Test
28
6
  def test_2004
29
7
  tz = Timezone.get('UTC')
30
8
 
@@ -1,30 +1,8 @@
1
- #--
2
- # Copyright (c) 2006-2013 Philip Ross
3
- #
4
- # Permission is hereby granted, free of charge, to any person obtaining a copy
5
- # of this software and associated documentation files (the "Software"), to deal
6
- # in the Software without restriction, including without limitation the rights
7
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
- # copies of the Software, and to permit persons to whom the Software is
9
- # furnished to do so, subject to the following conditions:
10
- #
11
- # The above copyright notice and this permission notice shall be included in all
12
- # copies or substantial portions of the Software.
13
- #
14
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
- # THE SOFTWARE.
21
- #++
22
-
23
1
  require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils')
24
2
 
25
3
  include TZInfo
26
4
 
27
- class TCTransitionDataTimezoneInfo < Test::Unit::TestCase
5
+ class TCTransitionDataTimezoneInfo < Minitest::Test
28
6
 
29
7
  def test_identifier
30
8
  dti = TransitionDataTimezoneInfo.new('Test/Zone')
@@ -378,10 +356,10 @@ class TCTransitionDataTimezoneInfo < Test::Unit::TestCase
378
356
  assert_equal([], dti.transitions_up_to(DateTime.new(2011,3,1,1,0,0), DateTime.new(2010,10,1,1,0,1)))
379
357
  assert_equal([t1,t2,t3,t4], dti.transitions_up_to(DateTime.new(2011,10,1,1,0,0)))
380
358
  assert_equal([t1,t2,t3,t4,t5], dti.transitions_up_to(DateTime.new(2011,10,1,1,0,1)))
381
- assert_equal([t1,t2,t3,t4,t5], dti.transitions_up_to(DateTime.new(2011,10,1,1,0,Rational(1,1000000))))
359
+ assert_equal([t1,t2,t3,t4,t5], dti.transitions_up_to(DateTime.new(2011,10,1,1,0,Rational(DATETIME_RESOLUTION,1000000))))
382
360
  assert_equal([t1,t2,t3,t4,t5], dti.transitions_up_to(DateTime.new(2011,10,1,1,0,1), DateTime.new(2010,4,1,1,0,0)))
383
361
  assert_equal([t2,t3,t4,t5], dti.transitions_up_to(DateTime.new(2011,10,1,1,0,1), DateTime.new(2010,4,1,1,0,1)))
384
- assert_equal([t2,t3,t4,t5], dti.transitions_up_to(DateTime.new(2011,10,1,1,0,1), DateTime.new(2010,4,1,1,0,Rational(1,1000000))))
362
+ assert_equal([t2,t3,t4,t5], dti.transitions_up_to(DateTime.new(2011,10,1,1,0,1), DateTime.new(2010,4,1,1,0,Rational(DATETIME_RESOLUTION,1000000))))
385
363
  assert_equal([t5], dti.transitions_up_to(DateTime.new(2015,1,1,0,0,0), DateTime.new(2011,10,1,1,0,0)))
386
364
  assert_equal([], dti.transitions_up_to(DateTime.new(2015,1,1,0,0,0), DateTime.new(2011,10,1,1,0,1)))
387
365
  end
@@ -1,30 +1,8 @@
1
- #--
2
- # Copyright (c) 2013 Philip Ross
3
- #
4
- # Permission is hereby granted, free of charge, to any person obtaining a copy
5
- # of this software and associated documentation files (the "Software"), to deal
6
- # in the Software without restriction, including without limitation the rights
7
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
- # copies of the Software, and to permit persons to whom the Software is
9
- # furnished to do so, subject to the following conditions:
10
- #
11
- # The above copyright notice and this permission notice shall be included in all
12
- # copies or substantial portions of the Software.
13
- #
14
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
- # THE SOFTWARE.
21
- #++
22
-
23
1
  require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils')
24
2
 
25
3
  include TZInfo
26
4
 
27
- class TCZoneinfoCountryInfo < Test::Unit::TestCase
5
+ class TCZoneinfoCountryInfo < Minitest::Test
28
6
 
29
7
  def test_code
30
8
  ci = ZoneinfoCountryInfo.new('ZZ', 'Zzz', []) {|c| }
@@ -44,10 +22,10 @@ class TCZoneinfoCountryInfo < Test::Unit::TestCase
44
22
 
45
23
  def test_zone_identifiers
46
24
  zones = [
47
- CountryTimezone.new('ZZ/TimezoneB', 1, 2, 1, 2, 'Timezone B'),
48
- CountryTimezone.new('ZZ/TimezoneA', 1, 4, 1, 4, 'Timezone A'),
49
- CountryTimezone.new('ZZ/TimezoneC', -10, 3, -20, 7, 'C'),
50
- CountryTimezone.new('ZZ/TimezoneD', -10, 3, -20, 7)
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))
51
29
  ]
52
30
 
53
31
  ci = ZoneinfoCountryInfo.new('ZZ', 'Zzz', zones)
@@ -66,18 +44,18 @@ class TCZoneinfoCountryInfo < Test::Unit::TestCase
66
44
 
67
45
  def test_zones
68
46
  zones = [
69
- CountryTimezone.new('ZZ/TimezoneB', 1, 2, 1, 2, 'Timezone B'),
70
- CountryTimezone.new('ZZ/TimezoneA', 1, 4, 1, 4, 'Timezone A'),
71
- CountryTimezone.new('ZZ/TimezoneC', -10, 3, -20, 7, 'C'),
72
- CountryTimezone.new('ZZ/TimezoneD', -10, 3, -20, 7)
47
+ CountryTimezone.new('ZZ/TimezoneB', Rational(1, 2), Rational(1, 2), 'Timezone B'),
48
+ CountryTimezone.new('ZZ/TimezoneA', Rational(1, 4), Rational(1, 4), 'Timezone A'),
49
+ CountryTimezone.new('ZZ/TimezoneC', Rational(-10, 3), Rational(-20, 7), 'C'),
50
+ CountryTimezone.new('ZZ/TimezoneD', Rational(-10, 3), Rational(-20, 7))
73
51
  ]
74
52
 
75
53
  ci = ZoneinfoCountryInfo.new('ZZ', 'Zzz', zones)
76
54
 
77
- assert_equal([CountryTimezone.new('ZZ/TimezoneB', 1, 2, 1, 2, 'Timezone B'),
78
- CountryTimezone.new('ZZ/TimezoneA', 1, 4, 1, 4, 'Timezone A'),
79
- CountryTimezone.new('ZZ/TimezoneC', -10, 3, -20, 7, 'C'),
80
- CountryTimezone.new('ZZ/TimezoneD', -10, 3, -20, 7)],
55
+ assert_equal([CountryTimezone.new('ZZ/TimezoneB', Rational(1, 2), Rational(1, 2), 'Timezone B'),
56
+ CountryTimezone.new('ZZ/TimezoneA', Rational(1, 4), Rational(1, 4), 'Timezone A'),
57
+ CountryTimezone.new('ZZ/TimezoneC', Rational(-10, 3), Rational(-20, 7), 'C'),
58
+ CountryTimezone.new('ZZ/TimezoneD', Rational(-10, 3), Rational(-20, 7))],
81
59
  ci.zones)
82
60
  assert(ci.zones.frozen?)
83
61
  assert(!ci.zones.equal?(zones))
@@ -1,24 +1,4 @@
1
- #--
2
- # Copyright (c) 2012-2013 Philip Ross
3
- #
4
- # Permission is hereby granted, free of charge, to any person obtaining a copy
5
- # of this software and associated documentation files (the "Software"), to deal
6
- # in the Software without restriction, including without limitation the rights
7
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
- # copies of the Software, and to permit persons to whom the Software is
9
- # furnished to do so, subject to the following conditions:
10
- #
11
- # The above copyright notice and this permission notice shall be included in all
12
- # copies or substantial portions of the Software.
13
- #
14
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
- # THE SOFTWARE.
21
- #++
1
+ # encoding: UTF-8
22
2
 
23
3
  require File.join(File.expand_path(File.dirname(__FILE__)), 'test_utils')
24
4
  require 'fileutils'
@@ -27,11 +7,12 @@ require 'tmpdir'
27
7
 
28
8
  include TZInfo
29
9
 
30
- class TCZoneinfoDataSource < Test::Unit::TestCase
10
+ class TCZoneinfoDataSource < Minitest::Test
31
11
  ZONEINFO_DIR = File.join(File.expand_path(File.dirname(__FILE__)), 'zoneinfo').untaint
32
12
 
33
13
  def setup
34
14
  @orig_search_path = ZoneinfoDataSource.search_path.clone
15
+ @orig_alternate_iso3166_tab_search_path = ZoneinfoDataSource.alternate_iso3166_tab_search_path.clone
35
16
  @orig_pwd = FileUtils.pwd
36
17
 
37
18
  # A zoneinfo directory containing files needed by the tests.
@@ -41,6 +22,7 @@ class TCZoneinfoDataSource < Test::Unit::TestCase
41
22
 
42
23
  def teardown
43
24
  ZoneinfoDataSource.search_path = @orig_search_path
25
+ ZoneinfoDataSource.alternate_iso3166_tab_search_path = @orig_alternate_iso3166_tab_search_path
44
26
  FileUtils.chdir(@orig_pwd)
45
27
  end
46
28
 
@@ -62,7 +44,7 @@ class TCZoneinfoDataSource < Test::Unit::TestCase
62
44
  path = ['/tmp/zoneinfo1', '/tmp/zoneinfo2']
63
45
  ZoneinfoDataSource.search_path = path
64
46
  assert_equal(['/tmp/zoneinfo1', '/tmp/zoneinfo2'], ZoneinfoDataSource.search_path)
65
- assert_not_same(path, ZoneinfoDataSource.search_path)
47
+ refute_same(path, ZoneinfoDataSource.search_path)
66
48
  end
67
49
 
68
50
  def test_set_search_path_array_to_s
@@ -75,6 +57,37 @@ class TCZoneinfoDataSource < Test::Unit::TestCase
75
57
  assert_equal(['/tmp/zoneinfo4', '/tmp/zoneinfo5'], ZoneinfoDataSource.search_path)
76
58
  end
77
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
+
78
91
  def test_new_search
79
92
  Dir.mktmpdir('tzinfo_test_dir1') do |dir1|
80
93
  Dir.mktmpdir('tzinfo_test_dir2') do |dir2|
@@ -87,6 +100,7 @@ class TCZoneinfoDataSource < Test::Unit::TestCase
87
100
  FileUtils.touch(File.join(dir4, 'iso3166.tab'))
88
101
 
89
102
  ZoneinfoDataSource.search_path = [file, dir2, dir3, dir4]
103
+ ZoneinfoDataSource.alternate_iso3166_tab_search_path = []
90
104
 
91
105
  data_source = ZoneinfoDataSource.new
92
106
  assert_equal(dir4, data_source.zoneinfo_dir)
@@ -96,6 +110,46 @@ class TCZoneinfoDataSource < Test::Unit::TestCase
96
110
  end
97
111
  end
98
112
 
113
+ def test_new_search_solaris_tab_files
114
+ # Solaris names the tab files 'tab/country.tab' (iso3166.tab) and
115
+ # 'tab/zone_sun.tab' (zone.tab).
116
+
117
+ Dir.mktmpdir('tzinfo_test_dir') do |dir|
118
+ tab = File.join(dir, 'tab')
119
+ FileUtils.mkdir(tab)
120
+ FileUtils.touch(File.join(tab, 'country.tab'))
121
+ FileUtils.touch(File.join(tab, 'zone_sun.tab'))
122
+
123
+ ZoneinfoDataSource.search_path = [dir]
124
+ ZoneinfoDataSource.alternate_iso3166_tab_search_path = []
125
+
126
+ data_source = ZoneinfoDataSource.new
127
+ assert_equal(dir, data_source.zoneinfo_dir)
128
+ end
129
+ end
130
+
131
+ def test_new_search_alternate_iso3166_path
132
+ Dir.mktmpdir('tzinfo_test_dir_zoneinfo') do |zoneinfo_dir|
133
+ Dir.mktmpdir('tzinfo_test_dir_tab') do |tab_dir|
134
+ FileUtils.touch(File.join(zoneinfo_dir, 'zone.tab'))
135
+
136
+ tab_file = File.join(tab_dir, 'iso3166')
137
+
138
+ ZoneinfoDataSource.search_path = [zoneinfo_dir]
139
+ ZoneinfoDataSource.alternate_iso3166_tab_search_path = [tab_file]
140
+
141
+ assert_raises(ZoneinfoDirectoryNotFound) do
142
+ ZoneinfoDataSource.new
143
+ end
144
+
145
+ FileUtils.touch(tab_file)
146
+
147
+ data_source = ZoneinfoDataSource.new
148
+ assert_equal(zoneinfo_dir, data_source.zoneinfo_dir)
149
+ end
150
+ end
151
+ end
152
+
99
153
  def test_new_search_not_found
100
154
  Dir.mktmpdir('tzinfo_test_dir1') do |dir1|
101
155
  Dir.mktmpdir('tzinfo_test_dir2') do |dir2|
@@ -107,6 +161,7 @@ class TCZoneinfoDataSource < Test::Unit::TestCase
107
161
  FileUtils.touch(File.join(dir3, 'iso3166.tab'))
108
162
 
109
163
  ZoneinfoDataSource.search_path = [file, dir2, dir3, dir4]
164
+ ZoneinfoDataSource.alternate_iso3166_tab_search_path = []
110
165
 
111
166
  assert_raises(ZoneinfoDirectoryNotFound) do
112
167
  ZoneinfoDataSource.new
@@ -125,8 +180,9 @@ class TCZoneinfoDataSource < Test::Unit::TestCase
125
180
  FileUtils.chdir(dir)
126
181
 
127
182
  ZoneinfoDataSource.search_path = ['.']
183
+ ZoneinfoDataSource.alternate_iso3166_tab_search_path = []
128
184
  data_source = ZoneinfoDataSource.new
129
- assert_equal(Pathname.new(dir).realpath, Pathname.new(dir).realpath)
185
+ assert_equal(Pathname.new(dir).realpath.to_s, data_source.zoneinfo_dir)
130
186
 
131
187
  # Change out of the directory to allow it to be deleted on Windows.
132
188
  FileUtils.chdir(@orig_pwd)
@@ -143,6 +199,43 @@ class TCZoneinfoDataSource < Test::Unit::TestCase
143
199
  end
144
200
  end
145
201
 
202
+ def test_new_dir_solaris_tab_files
203
+ # Solaris names the tab files 'tab/country.tab' (iso3166.tab) and
204
+ # 'tab/zone_sun.tab' (zone.tab).
205
+
206
+ Dir.mktmpdir('tzinfo_test') do |dir|
207
+ tab = File.join(dir, 'tab')
208
+ FileUtils.mkdir(tab)
209
+ FileUtils.touch(File.join(tab, 'country.tab'))
210
+ FileUtils.touch(File.join(tab, 'zone_sun.tab'))
211
+
212
+ data_source = ZoneinfoDataSource.new(dir)
213
+ assert_equal(dir, data_source.zoneinfo_dir)
214
+ end
215
+ end
216
+
217
+ def test_new_dir_alternate_iso3166_path
218
+ Dir.mktmpdir('tzinfo_test_dir_zoneinfo') do |zoneinfo_dir|
219
+ Dir.mktmpdir('tzinfo_test_dir_tab') do |tab_dir|
220
+ FileUtils.touch(File.join(zoneinfo_dir, 'zone.tab'))
221
+
222
+ tab_file = File.join(tab_dir, 'iso3166')
223
+ FileUtils.touch(tab_file)
224
+
225
+ ZoneinfoDataSource.alternate_iso3166_tab_search_path = [tab_file]
226
+
227
+ assert_raises(InvalidZoneinfoDirectory) do
228
+ # The alternate_iso3166_tab_search_path should not be used. This should raise
229
+ # an exception.
230
+ ZoneinfoDataSource.new(zoneinfo_dir)
231
+ end
232
+
233
+ data_source = ZoneinfoDataSource.new(zoneinfo_dir, tab_file)
234
+ assert_equal(zoneinfo_dir, data_source.zoneinfo_dir)
235
+ end
236
+ end
237
+ end
238
+
146
239
  def test_new_dir_invalid
147
240
  Dir.mktmpdir('tzinfo_test') do |dir|
148
241
  assert_raises(InvalidZoneinfoDirectory) do
@@ -151,6 +244,31 @@ class TCZoneinfoDataSource < Test::Unit::TestCase
151
244
  end
152
245
  end
153
246
 
247
+ def test_new_dir_invalid_alternate_iso3166_path
248
+ Dir.mktmpdir('tzinfo_test_dir_zoneinfo') do |zoneinfo_dir|
249
+ Dir.mktmpdir('tzinfo_test_dir_tab') do |tab_dir|
250
+ FileUtils.touch(File.join(zoneinfo_dir, 'zone.tab'))
251
+
252
+ assert_raises(InvalidZoneinfoDirectory) do
253
+ ZoneinfoDataSource.new(zoneinfo_dir, File.join(tab_dir, 'iso3166'))
254
+ end
255
+ end
256
+ end
257
+ end
258
+
259
+ def test_new_dir_invalid_alternate_iso3166_path_overrides_valid
260
+ Dir.mktmpdir('tzinfo_test_dir_zoneinfo') do |zoneinfo_dir|
261
+ Dir.mktmpdir('tzinfo_test_dir_tab') do |tab_dir|
262
+ FileUtils.touch(File.join(zoneinfo_dir, 'iso3166.tab'))
263
+ FileUtils.touch(File.join(zoneinfo_dir, 'zone.tab'))
264
+
265
+ assert_raises(InvalidZoneinfoDirectory) do
266
+ ZoneinfoDataSource.new(zoneinfo_dir, File.join(tab_dir, 'iso3166'))
267
+ end
268
+ end
269
+ end
270
+ end
271
+
154
272
  def test_new_file
155
273
  Dir.mktmpdir('tzinfo_test') do |dir|
156
274
  file = File.join(dir, 'file')
@@ -170,7 +288,7 @@ class TCZoneinfoDataSource < Test::Unit::TestCase
170
288
  FileUtils.chdir(dir)
171
289
 
172
290
  data_source = ZoneinfoDataSource.new('.')
173
- assert_equal(Pathname.new(dir).realpath, Pathname.new(dir).realpath)
291
+ assert_equal(Pathname.new(dir).realpath.to_s, data_source.zoneinfo_dir)
174
292
 
175
293
  # Change out of the directory to allow it to be deleted on Windows.
176
294
  FileUtils.chdir(@orig_pwd)
@@ -493,8 +611,6 @@ class TCZoneinfoDataSource < Test::Unit::TestCase
493
611
  def get_timezone_filenames(directory)
494
612
  entries = Dir.glob(File.join(directory, '**', '*'))
495
613
 
496
- prefix = File.expand_path(directory) + File::SEPARATOR
497
-
498
614
  entries = entries.select do |file|
499
615
  file.untaint
500
616
  File.file?(file)
@@ -563,9 +679,32 @@ class TCZoneinfoDataSource < Test::Unit::TestCase
563
679
  end
564
680
  end
565
681
 
682
+ def test_timezone_identifiers_ignored_src_directory
683
+ # Solaris includes a src directory containing the source timezone data files
684
+ # from the tzdata distribution. These should be ignored.
685
+
686
+ Dir.mktmpdir('tzinfo_test') do |dir|
687
+ FileUtils.touch(File.join(dir, 'zone.tab'))
688
+ FileUtils.touch(File.join(dir, 'iso3166.tab'))
689
+ FileUtils.cp(File.join(@data_source.zoneinfo_dir, 'EST'), File.join(dir, 'EST'))
690
+
691
+ src_dir = File.join(dir, 'src')
692
+ FileUtils.mkdir(src_dir)
693
+
694
+ File.open(File.join(src_dir, 'europe'), 'w') do |f|
695
+ f.binmode
696
+ f.write("Zone\tEurope/London\t0:00\tEU\tGMT/BST\n")
697
+ end
698
+
699
+ data_source = ZoneinfoDataSource.new(dir)
700
+ assert_array_same_items(['EST'], data_source.timezone_identifiers)
701
+ end
702
+ end
703
+
566
704
  def test_load_country_info
567
705
  info = @data_source.load_country_info('GB')
568
706
  assert_equal('GB', info.code)
707
+ assert_equal('Britain (UK)', info.name)
569
708
  end
570
709
 
571
710
  def test_load_country_info_not_exist
@@ -611,12 +750,16 @@ class TCZoneinfoDataSource < Test::Unit::TestCase
611
750
 
612
751
  def test_load_country_info_check_zones
613
752
  Dir.mktmpdir('tzinfo_test') do |dir|
614
- File.open(File.join(dir, 'iso3166.tab'), 'w') do |iso3166|
753
+ RubyCoreSupport.open_file(File.join(dir, 'iso3166.tab'), 'w', :external_encoding => 'UTF-8') do |iso3166|
754
+ iso3166.puts('# iso3166.tab')
755
+ iso3166.puts('')
615
756
  iso3166.puts("FC\tFake Country")
616
757
  iso3166.puts("OC\tOther Country")
617
758
  end
618
759
 
619
- File.open(File.join(dir, 'zone.tab'), 'w') do |zone|
760
+ RubyCoreSupport.open_file(File.join(dir, 'zone.tab'), 'w', :external_encoding => 'UTF-8') do |zone|
761
+ zone.puts('# zone.tab')
762
+ zone.puts('')
620
763
  zone.puts("FC\t+513030-0000731\tFake/One\tDescription of one")
621
764
  zone.puts("FC\t+353916+1394441\tFake/Two\tAnother description")
622
765
  zone.puts("FC\t-2332-04637\tFake/Three\tThis is Three")
@@ -627,27 +770,185 @@ class TCZoneinfoDataSource < Test::Unit::TestCase
627
770
 
628
771
  info = data_source.load_country_info('FC')
629
772
  assert_equal('FC', info.code)
773
+ assert_equal('Fake Country', info.name)
630
774
  assert_equal(['Fake/One', 'Fake/Two', 'Fake/Three'], info.zone_identifiers)
631
775
  assert_equal(true, info.zone_identifiers.frozen?)
632
776
  assert_equal([
633
- CountryTimezone.new('Fake/One', 6181, 120, -451, 3600, 'Description of one'),
634
- CountryTimezone.new('Fake/Two', 32089, 900, 503081, 3600, 'Another description'),
635
- CountryTimezone.new('Fake/Three', -353, 15, -2797, 60, 'This is Three')], info.zones)
777
+ CountryTimezone.new('Fake/One', Rational(6181, 120), Rational(-451, 3600), 'Description of one'),
778
+ CountryTimezone.new('Fake/Two', Rational(32089, 900), Rational(503081, 3600), 'Another description'),
779
+ CountryTimezone.new('Fake/Three', Rational(-353, 15), Rational(-2797, 60), 'This is Three')], info.zones)
636
780
  assert_equal(true, info.zones.frozen?)
637
781
 
638
782
  info = data_source.load_country_info('OC')
639
783
  assert_equal('OC', info.code)
784
+ assert_equal('Other Country', info.name)
640
785
  assert_equal(['Other/One'], info.zone_identifiers)
641
786
  assert_equal(true, info.zone_identifiers.frozen?)
642
- assert_equal([CountryTimezone.new('Other/One', 601, 12, 433, 30)], info.zones)
787
+ assert_equal([CountryTimezone.new('Other/One', Rational(601, 12), Rational(433, 30))], info.zones)
643
788
  assert_equal(true, info.zones.frozen?)
644
789
  end
645
790
  end
646
791
 
792
+ def test_load_country_info_check_zones_solaris_tab_files
793
+ # Solaris uses 5 columns instead of the usual 4 in zone_sun.tab.
794
+ # An extra column before the comment gives an optional linked/alternate
795
+ # timezone identifier (or '-' if not set).
796
+ #
797
+ # Additionally, there is a section at the end of the file for timezones
798
+ # covering regions. These are given lower-case "country" codes. The timezone
799
+ # identifier column refers to a continent instead of an identifier. These
800
+ # lines will be ignored by TZInfo.
801
+
802
+ Dir.mktmpdir('tzinfo_test') do |dir|
803
+ tab_dir = File.join(dir, 'tab')
804
+ FileUtils.mkdir(tab_dir)
805
+
806
+ RubyCoreSupport.open_file(File.join(tab_dir, 'country.tab'), 'w', :external_encoding => 'UTF-8') do |country|
807
+ country.puts('# country.tab')
808
+ country.puts('# Solaris')
809
+ country.puts("FC\tFake Country")
810
+ country.puts("OC\tOther Country")
811
+ end
812
+
813
+ RubyCoreSupport.open_file(File.join(tab_dir, 'zone_sun.tab'), 'w', :external_encoding => 'UTF-8') do |zone_sun|
814
+ zone_sun.puts('# zone_sun.tab')
815
+ zone_sun.puts('# Solaris')
816
+ zone_sun.puts('# Countries')
817
+ zone_sun.puts("FC\t+513030-0000731\tFake/One\t-\tDescription of one")
818
+ zone_sun.puts("FC\t+353916+1394441\tFake/Two\tFake/Alias/Two\tAnother description")
819
+ zone_sun.puts("FC\t-2332-04637\tFake/Three\tFake/Alias/Three\tThis is Three")
820
+ zone_sun.puts("OC\t+5005+01426\tOther/One\tOther/Linked/One")
821
+ zone_sun.puts("OC\t+5015+01436\tOther/Two\t-")
822
+ zone_sun.puts('# Regions')
823
+ zone_sun.puts("ee\t+0000+00000\tEurope/\tEET")
824
+ zone_sun.puts("me\t+0000+00000\tEurope/\tMET")
825
+ zone_sun.puts("we\t+0000+00000\tEurope/\tWET")
826
+ end
827
+
828
+ data_source = ZoneinfoDataSource.new(dir)
829
+
830
+ info = data_source.load_country_info('FC')
831
+ assert_equal('FC', info.code)
832
+ assert_equal('Fake Country', info.name)
833
+ assert_equal(['Fake/One', 'Fake/Two', 'Fake/Three'], info.zone_identifiers)
834
+ assert_equal(true, info.zone_identifiers.frozen?)
835
+ assert_equal([
836
+ CountryTimezone.new('Fake/One', Rational(6181, 120), Rational(-451, 3600), 'Description of one'),
837
+ CountryTimezone.new('Fake/Two', Rational(32089, 900), Rational(503081, 3600), 'Another description'),
838
+ CountryTimezone.new('Fake/Three', Rational(-353, 15), Rational(-2797, 60), 'This is Three')], info.zones)
839
+ assert_equal(true, info.zones.frozen?)
840
+
841
+ info = data_source.load_country_info('OC')
842
+ assert_equal('OC', info.code)
843
+ assert_equal('Other Country', info.name)
844
+ assert_equal(['Other/One', 'Other/Two'], info.zone_identifiers)
845
+ assert_equal(true, info.zone_identifiers.frozen?)
846
+ assert_equal([
847
+ CountryTimezone.new('Other/One', Rational(601, 12), Rational(433, 30)),
848
+ CountryTimezone.new('Other/Two', Rational(201, 4), Rational(73, 5))], info.zones)
849
+ assert_equal(true, info.zones.frozen?)
850
+ end
851
+ end
852
+
853
+ def test_load_country_info_check_zones_alternate_iso3166_file
854
+ Dir.mktmpdir('tzinfo_test') do |dir|
855
+ zoneinfo_dir = File.join(dir, 'zoneinfo')
856
+ tab_dir = File.join(dir, 'tab')
857
+ FileUtils.mkdir(zoneinfo_dir)
858
+ FileUtils.mkdir(tab_dir)
859
+
860
+ tab_file = File.join(tab_dir, 'iso3166')
861
+ RubyCoreSupport.open_file(tab_file, 'w', :external_encoding => 'UTF-8') do |iso3166|
862
+ # Use the BSD 4 column format (alternate iso3166 is used on BSD).
863
+ iso3166.puts("FC\tFCC\t001\tFake Country")
864
+ iso3166.puts("OC\tOCC\t002\tOther Country")
865
+ end
866
+
867
+ RubyCoreSupport.open_file(File.join(zoneinfo_dir, 'zone.tab'), 'w', :external_encoding => 'UTF-8') do |zone|
868
+ zone.puts("FC\t+513030-0000731\tFake/One\tDescription of one")
869
+ zone.puts("FC\t+353916+1394441\tFake/Two\tAnother description")
870
+ zone.puts("FC\t-2332-04637\tFake/Three\tThis is Three")
871
+ zone.puts("OC\t+5005+01426\tOther/One")
872
+ end
873
+
874
+ data_source = ZoneinfoDataSource.new(zoneinfo_dir, tab_file)
875
+
876
+ info = data_source.load_country_info('FC')
877
+ assert_equal('FC', info.code)
878
+ assert_equal('Fake Country', info.name)
879
+ assert_equal(['Fake/One', 'Fake/Two', 'Fake/Three'], info.zone_identifiers)
880
+ assert_equal(true, info.zone_identifiers.frozen?)
881
+ assert_equal([
882
+ CountryTimezone.new('Fake/One', Rational(6181, 120), Rational(-451, 3600), 'Description of one'),
883
+ CountryTimezone.new('Fake/Two', Rational(32089, 900), Rational(503081, 3600), 'Another description'),
884
+ CountryTimezone.new('Fake/Three', Rational(-353, 15), Rational(-2797, 60), 'This is Three')], info.zones)
885
+ assert_equal(true, info.zones.frozen?)
886
+
887
+ info = data_source.load_country_info('OC')
888
+ assert_equal('OC', info.code)
889
+ assert_equal('Other Country', info.name)
890
+ assert_equal(['Other/One'], info.zone_identifiers)
891
+ assert_equal(true, info.zone_identifiers.frozen?)
892
+ assert_equal([CountryTimezone.new('Other/One', Rational(601, 12), Rational(433, 30))], info.zones)
893
+ assert_equal(true, info.zones.frozen?)
894
+ end
895
+ end
896
+
897
+ def test_load_country_info_four_column_iso31611
898
+ # OpenBSD and FreeBSD use a 4 column iso3166.tab file that includes
899
+ # alpha-3 and numeric-3 codes in addition to the alpha-2 and name in the
900
+ # tz database version.
901
+
902
+ Dir.mktmpdir('tzinfo_test') do |dir|
903
+ RubyCoreSupport.open_file(File.join(dir, 'iso3166.tab'), 'w', :external_encoding => 'UTF-8') do |iso3166|
904
+ iso3166.puts("FC\tFCC\t001\tFake Country")
905
+ iso3166.puts("OC\tOCC\t002\tOther Country")
906
+ end
907
+
908
+ RubyCoreSupport.open_file(File.join(dir, 'zone.tab'), 'w', :external_encoding => 'UTF-8') do |zone|
909
+ zone.puts("FC\t+513030-0000731\tFake/One\tDescription of one")
910
+ zone.puts("OC\t+5005+01426\tOther/One")
911
+ end
912
+
913
+ data_source = ZoneinfoDataSource.new(dir)
914
+
915
+ info = data_source.load_country_info('FC')
916
+ assert_equal('FC', info.code)
917
+ assert_equal('Fake Country', info.name)
918
+
919
+ info = data_source.load_country_info('OC')
920
+ assert_equal('OC', info.code)
921
+ assert_equal('Other Country', info.name)
922
+ end
923
+ end
924
+
925
+ def test_load_country_info_utf8
926
+ # Files are in ASCII, but may change to UTF-8 (a superset of ASCII) in
927
+ # the future.
928
+
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("UT\tUnicode Test ✓")
932
+ end
933
+
934
+ RubyCoreSupport.open_file(File.join(dir, 'zone.tab'), 'w', :external_encoding => 'UTF-8') do |zone|
935
+ zone.puts("UT\t+513030-0000731\tUnicode✓/One\tUnicode Description ✓")
936
+ end
937
+
938
+ data_source = ZoneinfoDataSource.new(dir)
939
+
940
+ info = data_source.load_country_info('UT')
941
+ assert_equal('UT', info.code)
942
+ assert_equal('Unicode Test ✓', info.name)
943
+ assert_equal(['Unicode✓/One'], info.zone_identifiers)
944
+ assert_equal([CountryTimezone.new('Unicode✓/One', Rational(6181, 120), Rational(-451, 3600), 'Unicode Description ✓')], info.zones)
945
+ end
946
+ end
947
+
647
948
  def test_country_codes
648
949
  file_codes = []
649
950
 
650
- File.open(File.join(@data_source.zoneinfo_dir, 'iso3166.tab')) do |file|
951
+ RubyCoreSupport.open_file(File.join(@data_source.zoneinfo_dir, 'iso3166.tab'), 'r', :external_encoding => 'UTF-8', :internal_encoding => 'UTF-8') do |file|
651
952
  file.each_line do |line|
652
953
  line.chomp!
653
954
  file_codes << $1 if line =~ /\A([A-Z]{2})\t/
@@ -658,4 +959,27 @@ class TCZoneinfoDataSource < Test::Unit::TestCase
658
959
  assert_array_same_items(file_codes, codes)
659
960
  assert_equal(true, codes.frozen?)
660
961
  end
962
+
963
+ def test_country_codes_four_column_iso3166
964
+ # OpenBSD and FreeBSD use a 4 column iso3166.tab file that includes
965
+ # alpha-3 and numeric-3 codes in addition to the alpha-2 and name in the
966
+ # tz database version.
967
+
968
+ Dir.mktmpdir('tzinfo_test') do |dir|
969
+ RubyCoreSupport.open_file(File.join(dir, 'iso3166.tab'), 'w', :external_encoding => 'UTF-8') do |iso3166|
970
+ iso3166.puts("FC\tFCC\t001\tFake Country")
971
+ iso3166.puts("OC\tOCC\t002\tOther Country")
972
+ end
973
+
974
+ RubyCoreSupport.open_file(File.join(dir, 'zone.tab'), 'w', :external_encoding => 'UTF-8') do |zone|
975
+ zone.puts("FC\t+513030-0000731\tFake/One\tDescription of one")
976
+ zone.puts("OC\t+5005+01426\tOther/One")
977
+ end
978
+
979
+ data_source = ZoneinfoDataSource.new(dir)
980
+
981
+ codes = data_source.country_codes
982
+ assert_array_same_items(%w(FC OC), codes)
983
+ end
984
+ end
661
985
  end