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
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2005-2018 Philip Ross
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
4
|
+
this software and associated documentation files (the "Software"), to deal in
|
5
|
+
the Software without restriction, including without limitation the rights to
|
6
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
7
|
+
of the Software, and to permit persons to whom the Software is furnished to do
|
8
|
+
so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
11
|
+
copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
TZInfo - Ruby Timezone Library
|
2
|
+
==============================
|
3
|
+
|
4
|
+
[![Gem Version](https://badge.fury.io/rb/tzinfo.svg)](http://badge.fury.io/rb/tzinfo) [![Build Status](https://travis-ci.org/tzinfo/tzinfo.svg?branch=master)](https://travis-ci.org/tzinfo/tzinfo)
|
5
|
+
|
6
|
+
[TZInfo](http://tzinfo.github.io) provides daylight savings aware
|
7
|
+
transformations between times in different timezones.
|
8
|
+
|
9
|
+
|
10
|
+
Data Sources
|
11
|
+
------------
|
12
|
+
|
13
|
+
TZInfo requires a source of timezone data. There are two built-in options:
|
14
|
+
|
15
|
+
1. The TZInfo::Data library (the tzinfo-data gem). TZInfo::Data contains a set
|
16
|
+
of Ruby modules that are generated from the [IANA Time Zone Database](http://www.iana.org/time-zones).
|
17
|
+
2. A zoneinfo directory. Most Unix-like systems include a zoneinfo directory
|
18
|
+
containing timezone definitions. These are also generated from the
|
19
|
+
[IANA Time Zone Database](http://www.iana.org/time-zones).
|
20
|
+
|
21
|
+
By default, TZInfo::Data will be used. If TZInfo::Data is not available (i.e.
|
22
|
+
if `require 'tzinfo/data'` fails), then TZInfo will search for a zoneinfo
|
23
|
+
directory instead (using the search path specified by
|
24
|
+
`TZInfo::ZoneinfoDataSource::DEFAULT_SEARCH_PATH`).
|
25
|
+
|
26
|
+
If no data source can be found, a `TZInfo::DataSourceNotFound` exception will be
|
27
|
+
raised when TZInfo is used. Further information is available
|
28
|
+
[in the wiki](http://tzinfo.github.io/datasourcenotfound) to help with
|
29
|
+
resolving `TZInfo::DataSourceNotFound` errors.
|
30
|
+
|
31
|
+
The default data source selection can be overridden using
|
32
|
+
`TZInfo::DataSource.set`.
|
33
|
+
|
34
|
+
Custom data sources can also be used. See `TZInfo::DataSource.set` for
|
35
|
+
further details.
|
36
|
+
|
37
|
+
|
38
|
+
Installation
|
39
|
+
------------
|
40
|
+
|
41
|
+
The TZInfo gem can be installed by running:
|
42
|
+
|
43
|
+
gem install tzinfo
|
44
|
+
|
45
|
+
To use the Ruby modules as the data source, TZInfo::Data will also need to be
|
46
|
+
installed:
|
47
|
+
|
48
|
+
gem install tzinfo-data
|
49
|
+
|
50
|
+
|
51
|
+
Example Usage
|
52
|
+
-------------
|
53
|
+
|
54
|
+
The following code will obtain the America/New_York timezone (as an instance
|
55
|
+
of `TZInfo::Timezone`) and convert a time in UTC to local New York time:
|
56
|
+
|
57
|
+
require 'tzinfo'
|
58
|
+
|
59
|
+
tz = TZInfo::Timezone.get('America/New_York')
|
60
|
+
local = tz.utc_to_local(Time.utc(2005,8,29,15,35,0))
|
61
|
+
|
62
|
+
Note that the local Time returned will have a UTC timezone (`local.zone` will
|
63
|
+
return `"UTC"`). This is because the Ruby Time class only supports two timezones:
|
64
|
+
UTC and the current system local timezone.
|
65
|
+
|
66
|
+
To convert from a local time to UTC, the `local_to_utc` method can be used as
|
67
|
+
follows:
|
68
|
+
|
69
|
+
utc = tz.local_to_utc(local)
|
70
|
+
|
71
|
+
Note that the timezone information of the local Time object is ignored (TZInfo
|
72
|
+
will just read the date and time and treat them as if there were in the `tz`
|
73
|
+
timezone). The following two lines will return the same result regardless of
|
74
|
+
the system's local timezone:
|
75
|
+
|
76
|
+
tz.local_to_utc(Time.local(2006,6,26,1,0,0))
|
77
|
+
tz.local_to_utc(Time.utc(2006,6,26,1,0,0))
|
78
|
+
|
79
|
+
To obtain information about the rules in force at a particular UTC or local
|
80
|
+
time, the `TZInfo::Timezone.period_for_utc` and
|
81
|
+
`TZInfo::Timezone.period_for_local` methods can be used. Both of these methods
|
82
|
+
return `TZInfo::TimezonePeriod` objects. The following gets the identifier for
|
83
|
+
the period (in this case EDT).
|
84
|
+
|
85
|
+
period = tz.period_for_utc(Time.utc(2005,8,29,15,35,0))
|
86
|
+
id = period.zone_identifier
|
87
|
+
|
88
|
+
The current local time in a `Timezone` can be obtained with the
|
89
|
+
`TZInfo::Timezone#now` method:
|
90
|
+
|
91
|
+
now = tz.now
|
92
|
+
|
93
|
+
All methods in TZInfo that operate on a time can be used with either `Time` or
|
94
|
+
`DateTime` instances or with Integer timestamps (i.e. as returned by
|
95
|
+
`Time#to_i`). The type of the values returned will match the type passed in.
|
96
|
+
|
97
|
+
A list of all the available timezone identifiers can be obtained using the
|
98
|
+
`TZInfo::Timezone.all_identifiers` method. `TZInfo::Timezone.all` can be called
|
99
|
+
to get an `Array` of all the `TZInfo::Timezone` instances.
|
100
|
+
|
101
|
+
Timezones can also be accessed by country (using an ISO 3166-1 alpha-2 country
|
102
|
+
code). The following code retrieves the `TZInfo::Country` instance representing
|
103
|
+
the USA (country code 'US') and then gets all the timezone identifiers used in
|
104
|
+
the USA.
|
105
|
+
|
106
|
+
us = TZInfo::Country.get('US')
|
107
|
+
timezones = us.zone_identifiers
|
108
|
+
|
109
|
+
The `TZInfo::Country#zone_info` method provides an additional description and
|
110
|
+
geographic location for each timezone in a country.
|
111
|
+
|
112
|
+
A list of all the available country codes can be obtained using the
|
113
|
+
`TZInfo::Country.all_codes` method. `TZInfo::Country.all` can be called to get
|
114
|
+
an `Array` of all the `Country` instances.
|
115
|
+
|
116
|
+
For further detail, please refer to the API documentation for the
|
117
|
+
`TZInfo::Timezone` and `TZInfo::Country` classes.
|
118
|
+
|
119
|
+
|
120
|
+
Thread-Safety
|
121
|
+
-------------
|
122
|
+
|
123
|
+
The `TZInfo::Country` and `TZInfo::Timezone` classes are thread-safe. It is safe
|
124
|
+
to use class and instance methods of `TZInfo::Country` and `TZInfo::Timezone` in
|
125
|
+
concurrently executing threads. Instances of both classes can be shared across
|
126
|
+
thread boundaries.
|
127
|
+
|
128
|
+
|
129
|
+
Documentation
|
130
|
+
-------------
|
131
|
+
|
132
|
+
API documentation for TZInfo is available on [RubyDoc.info](http://rubydoc.info/gems/tzinfo/frames).
|
133
|
+
|
134
|
+
|
135
|
+
License
|
136
|
+
-------
|
137
|
+
|
138
|
+
TZInfo is released under the MIT license, see LICENSE for details.
|
139
|
+
|
140
|
+
|
141
|
+
Source Code
|
142
|
+
-----------
|
143
|
+
|
144
|
+
Source code for TZInfo is available on [GitHub](https://github.com/tzinfo/tzinfo).
|
145
|
+
|
146
|
+
|
147
|
+
Issue Tracker
|
148
|
+
-------------
|
149
|
+
|
150
|
+
Please post any bugs, issues, feature requests or questions to the
|
151
|
+
[GitHub issue tracker](https://github.com/tzinfo/tzinfo/issues).
|
data/Rakefile
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rubygems/package_task'
|
3
|
+
require 'fileutils'
|
4
|
+
require 'rake/testtask'
|
5
|
+
|
6
|
+
# Ignore errors loading rdoc/task (the rdoc tasks will be excluded if
|
7
|
+
# rdoc is unavailable).
|
8
|
+
begin
|
9
|
+
require 'rdoc/task'
|
10
|
+
rescue LoadError, RuntimeError
|
11
|
+
end
|
12
|
+
|
13
|
+
BASE_DIR = File.expand_path(File.dirname(__FILE__))
|
14
|
+
|
15
|
+
task :default => [:test]
|
16
|
+
|
17
|
+
spec = eval(File.read('tzinfo.gemspec'))
|
18
|
+
|
19
|
+
class TZInfoPackageTask < Gem::PackageTask
|
20
|
+
alias_method :orig_sh, :sh
|
21
|
+
private :orig_sh
|
22
|
+
|
23
|
+
def sh(*cmd, &block)
|
24
|
+
if cmd[0] == '__tar_with_owner__' && cmd[1] =~ /\A-?[zjcvf]+\z/
|
25
|
+
opts = cmd[1]
|
26
|
+
cmd = ['tar', 'c', '--owner', '0', '--group', '0', "#{opts.start_with?('-') ? '' : '-'}#{opts.gsub('c', '')}"] + cmd.drop(2)
|
27
|
+
elsif cmd.first =~ /\A__tar_with_owner__ -?([zjcvf]+)(.*)\z/
|
28
|
+
opts = $1
|
29
|
+
args = $2
|
30
|
+
cmd[0] = "tar c --owner 0 --group 0 -#{opts.gsub('c', '')}#{args}"
|
31
|
+
end
|
32
|
+
|
33
|
+
orig_sh(*cmd, &block)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def add_signing_key(spec)
|
38
|
+
# Attempt to find the private key and add options to sign the gem if found.
|
39
|
+
private_key_path = File.expand_path(File.join(BASE_DIR, '..', 'key', 'gem-private_key.pem'))
|
40
|
+
|
41
|
+
if File.exist?(private_key_path)
|
42
|
+
spec = spec.clone
|
43
|
+
spec.signing_key = private_key_path
|
44
|
+
spec.cert_chain = [File.join(BASE_DIR, 'gem-public_cert.pem')]
|
45
|
+
else
|
46
|
+
puts 'WARNING: Private key not found. Not signing gem file.'
|
47
|
+
end
|
48
|
+
|
49
|
+
spec
|
50
|
+
end
|
51
|
+
|
52
|
+
package_task = TZInfoPackageTask.new(add_signing_key(spec)) do |pkg|
|
53
|
+
pkg.need_zip = true
|
54
|
+
pkg.need_tar_gz = true
|
55
|
+
pkg.tar_command = '__tar_with_owner__'
|
56
|
+
end
|
57
|
+
|
58
|
+
# Skip the rdoc task if RDoc::Task is unavailable
|
59
|
+
if defined?(RDoc) && defined?(RDoc::Task)
|
60
|
+
RDoc::Task.new do |rdoc|
|
61
|
+
rdoc.rdoc_dir = 'doc'
|
62
|
+
rdoc.options.concat spec.rdoc_options
|
63
|
+
rdoc.rdoc_files.include(spec.extra_rdoc_files)
|
64
|
+
rdoc.rdoc_files.include('lib')
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
Rake::Task[package_task.package_dir_path].enhance do
|
69
|
+
recurse_chmod(package_task.package_dir_path)
|
70
|
+
end
|
71
|
+
|
72
|
+
Rake::Task[:package].enhance do
|
73
|
+
FileUtils.rm_rf(package_task.package_dir_path)
|
74
|
+
end
|
75
|
+
|
76
|
+
def recurse_chmod(dir)
|
77
|
+
File.chmod(0755, dir)
|
78
|
+
|
79
|
+
Dir.entries(dir).each do |entry|
|
80
|
+
if entry != '.' && entry != '..'
|
81
|
+
path = File.join(dir, entry)
|
82
|
+
if File.directory?(path)
|
83
|
+
recurse_chmod(path)
|
84
|
+
else
|
85
|
+
File.chmod(0644, path)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
desc 'Run tests using RubyDataSource, then ZoneinfoDataSource'
|
92
|
+
task :test => [:test_ruby, :test_zoneinfo] do
|
93
|
+
end
|
94
|
+
|
95
|
+
def setup_tests(test_task, type)
|
96
|
+
test_task.libs = [File.join(BASE_DIR, 'lib')]
|
97
|
+
test_task.pattern = File.join(BASE_DIR, 'test', "ts_all_#{type}.rb")
|
98
|
+
test_task.warning = true
|
99
|
+
end
|
100
|
+
|
101
|
+
Rake::TestTask.new(:test_ruby) do |t|
|
102
|
+
setup_tests(t, :ruby)
|
103
|
+
end
|
104
|
+
|
105
|
+
Rake::TestTask.new(:test_zoneinfo) do |t|
|
106
|
+
setup_tests(t, :zoneinfo)
|
107
|
+
end
|
data/lib/tzinfo.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# Top level module for TZInfo.
|
2
|
+
module TZInfo
|
3
|
+
end
|
4
|
+
|
5
|
+
require 'tzinfo/ruby_core_support'
|
6
|
+
require 'tzinfo/offset_rationals'
|
7
|
+
require 'tzinfo/time_or_datetime'
|
8
|
+
|
9
|
+
require 'tzinfo/timezone_definition'
|
10
|
+
|
11
|
+
require 'tzinfo/timezone_offset'
|
12
|
+
require 'tzinfo/timezone_transition'
|
13
|
+
require 'tzinfo/timezone_transition_definition'
|
14
|
+
|
15
|
+
require 'tzinfo/timezone_index_definition'
|
16
|
+
|
17
|
+
require 'tzinfo/timezone_info'
|
18
|
+
require 'tzinfo/data_timezone_info'
|
19
|
+
require 'tzinfo/linked_timezone_info'
|
20
|
+
require 'tzinfo/transition_data_timezone_info'
|
21
|
+
require 'tzinfo/zoneinfo_timezone_info'
|
22
|
+
|
23
|
+
require 'tzinfo/data_source'
|
24
|
+
require 'tzinfo/ruby_data_source'
|
25
|
+
require 'tzinfo/zoneinfo_data_source'
|
26
|
+
|
27
|
+
require 'tzinfo/timezone_period'
|
28
|
+
require 'tzinfo/timezone'
|
29
|
+
require 'tzinfo/info_timezone'
|
30
|
+
require 'tzinfo/data_timezone'
|
31
|
+
require 'tzinfo/linked_timezone'
|
32
|
+
require 'tzinfo/timezone_proxy'
|
33
|
+
|
34
|
+
require 'tzinfo/country_index_definition'
|
35
|
+
require 'tzinfo/country_info'
|
36
|
+
require 'tzinfo/ruby_country_info'
|
37
|
+
require 'tzinfo/zoneinfo_country_info'
|
38
|
+
|
39
|
+
require 'tzinfo/country'
|
40
|
+
require 'tzinfo/country_timezone'
|
@@ -0,0 +1,196 @@
|
|
1
|
+
require 'thread_safe'
|
2
|
+
|
3
|
+
module TZInfo
|
4
|
+
# Raised by Country#get if the code given is not valid.
|
5
|
+
class InvalidCountryCode < StandardError
|
6
|
+
end
|
7
|
+
|
8
|
+
# The Country class represents an ISO 3166-1 country. It can be used to
|
9
|
+
# obtain a list of Timezones for a country. For example:
|
10
|
+
#
|
11
|
+
# us = Country.get('US')
|
12
|
+
# us.zone_identifiers
|
13
|
+
# us.zones
|
14
|
+
# us.zone_info
|
15
|
+
#
|
16
|
+
# The Country class is thread-safe. It is safe to use class and instance
|
17
|
+
# methods of Country in concurrently executing threads. Instances of Country
|
18
|
+
# can be shared across thread boundaries.
|
19
|
+
#
|
20
|
+
# Country information available through TZInfo is intended as an aid for
|
21
|
+
# users, to help them select time zone data appropriate for their practical
|
22
|
+
# needs. It is not intended to take or endorse any position on legal or
|
23
|
+
# territorial claims.
|
24
|
+
class Country
|
25
|
+
include Comparable
|
26
|
+
|
27
|
+
# Defined countries.
|
28
|
+
#
|
29
|
+
# @!visibility private
|
30
|
+
@@countries = nil
|
31
|
+
|
32
|
+
# Whether the countries index has been loaded yet.
|
33
|
+
#
|
34
|
+
# @!visibility private
|
35
|
+
@@index_loaded = false
|
36
|
+
|
37
|
+
# Gets a Country by its ISO 3166-1 alpha-2 code. Raises an
|
38
|
+
# InvalidCountryCode exception if it couldn't be found.
|
39
|
+
def self.get(identifier)
|
40
|
+
instance = @@countries[identifier]
|
41
|
+
|
42
|
+
unless instance
|
43
|
+
# Thread-safety: It is possible that multiple equivalent Country
|
44
|
+
# instances could be created here in concurrently executing threads.
|
45
|
+
# The consequences of this are that the data may be loaded more than
|
46
|
+
# once (depending on the data source) and memoized calculations could
|
47
|
+
# be discarded. The performance benefit of ensuring that only a single
|
48
|
+
# instance is created is unlikely to be worth the overhead of only
|
49
|
+
# allowing one Country to be loaded at a time.
|
50
|
+
info = data_source.load_country_info(identifier)
|
51
|
+
instance = Country.new(info)
|
52
|
+
@@countries[identifier] = instance
|
53
|
+
end
|
54
|
+
|
55
|
+
instance
|
56
|
+
end
|
57
|
+
|
58
|
+
# If identifier is a CountryInfo object, initializes the Country instance,
|
59
|
+
# otherwise calls get(identifier).
|
60
|
+
def self.new(identifier)
|
61
|
+
if identifier.kind_of?(CountryInfo)
|
62
|
+
instance = super()
|
63
|
+
instance.send :setup, identifier
|
64
|
+
instance
|
65
|
+
else
|
66
|
+
get(identifier)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# Returns an Array of all the valid country codes.
|
71
|
+
def self.all_codes
|
72
|
+
data_source.country_codes
|
73
|
+
end
|
74
|
+
|
75
|
+
# Returns an Array of all the defined Countries.
|
76
|
+
def self.all
|
77
|
+
data_source.country_codes.collect {|code| get(code)}
|
78
|
+
end
|
79
|
+
|
80
|
+
# The ISO 3166-1 alpha-2 country code.
|
81
|
+
def code
|
82
|
+
@info.code
|
83
|
+
end
|
84
|
+
|
85
|
+
# The name of the country.
|
86
|
+
def name
|
87
|
+
@info.name
|
88
|
+
end
|
89
|
+
|
90
|
+
# Alias for name.
|
91
|
+
def to_s
|
92
|
+
name
|
93
|
+
end
|
94
|
+
|
95
|
+
# Returns internal object state as a programmer-readable string.
|
96
|
+
def inspect
|
97
|
+
"#<#{self.class}: #{@info.code}>"
|
98
|
+
end
|
99
|
+
|
100
|
+
# Returns a frozen array of all the zone identifiers for the country. These
|
101
|
+
# are in an order that
|
102
|
+
#
|
103
|
+
# 1. makes some geographical sense, and
|
104
|
+
# 2. puts the most populous zones first, where that does not contradict 1.
|
105
|
+
#
|
106
|
+
# Returned zone identifiers may refer to cities and regions outside of the
|
107
|
+
# country. This will occur if the zone covers multiple countries. Any zones
|
108
|
+
# referring to a city or region in a different country will be listed after
|
109
|
+
# those relating to this country.
|
110
|
+
def zone_identifiers
|
111
|
+
@info.zone_identifiers
|
112
|
+
end
|
113
|
+
alias zone_names zone_identifiers
|
114
|
+
|
115
|
+
# An array of all the Timezones for this country. Returns TimezoneProxy
|
116
|
+
# objects to avoid the overhead of loading Timezone definitions until
|
117
|
+
# a conversion is actually required. The Timezones are returned in an order
|
118
|
+
# that
|
119
|
+
#
|
120
|
+
# 1. makes some geographical sense, and
|
121
|
+
# 2. puts the most populous zones first, where that does not contradict 1.
|
122
|
+
#
|
123
|
+
# Identifiers of the zones returned may refer to cities and regions outside
|
124
|
+
# of the country. This will occur if the zone covers multiple countries. Any
|
125
|
+
# zones referring to a city or region in a different country will be listed
|
126
|
+
# after those relating to this country.
|
127
|
+
def zones
|
128
|
+
zone_identifiers.collect {|id|
|
129
|
+
Timezone.get_proxy(id)
|
130
|
+
}
|
131
|
+
end
|
132
|
+
|
133
|
+
# Returns a frozen array of all the timezones for the for the country as
|
134
|
+
# CountryTimezone instances (containing extra information about each zone).
|
135
|
+
# These are in an order that
|
136
|
+
#
|
137
|
+
# 1. makes some geographical sense, and
|
138
|
+
# 2. puts the most populous zones first, where that does not contradict 1.
|
139
|
+
#
|
140
|
+
# Identifiers and descriptions of the zones returned may refer to cities and
|
141
|
+
# regions outside of the country. This will occur if the zone covers
|
142
|
+
# multiple countries. Any zones referring to a city or region in a different
|
143
|
+
# country will be listed after those relating to this country.
|
144
|
+
def zone_info
|
145
|
+
@info.zones
|
146
|
+
end
|
147
|
+
|
148
|
+
# Compare two Countries based on their code. Returns -1 if c is less
|
149
|
+
# than self, 0 if c is equal to self and +1 if c is greater than self.
|
150
|
+
#
|
151
|
+
# Returns nil if c is not comparable with Country instances.
|
152
|
+
def <=>(c)
|
153
|
+
return nil unless c.is_a?(Country)
|
154
|
+
code <=> c.code
|
155
|
+
end
|
156
|
+
|
157
|
+
# Returns true if and only if the code of c is equal to the code of this
|
158
|
+
# Country.
|
159
|
+
def eql?(c)
|
160
|
+
self == c
|
161
|
+
end
|
162
|
+
|
163
|
+
# Returns a hash value for this Country.
|
164
|
+
def hash
|
165
|
+
code.hash
|
166
|
+
end
|
167
|
+
|
168
|
+
# Dumps this Country for marshalling.
|
169
|
+
def _dump(limit)
|
170
|
+
code
|
171
|
+
end
|
172
|
+
|
173
|
+
# Loads a marshalled Country.
|
174
|
+
def self._load(data)
|
175
|
+
Country.get(data)
|
176
|
+
end
|
177
|
+
|
178
|
+
private
|
179
|
+
# Called by Country.new to initialize a new Country instance. The info
|
180
|
+
# parameter is a CountryInfo that defines the country.
|
181
|
+
def setup(info)
|
182
|
+
@info = info
|
183
|
+
end
|
184
|
+
|
185
|
+
# Initializes @@countries.
|
186
|
+
def self.init_countries
|
187
|
+
@@countries = ThreadSafe::Cache.new
|
188
|
+
end
|
189
|
+
init_countries
|
190
|
+
|
191
|
+
# Returns the current DataSource
|
192
|
+
def self.data_source
|
193
|
+
DataSource.get
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|