timezone 0.6.0 → 0.99.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +99 -1
  4. data/.travis.yml +6 -3
  5. data/CHANGES.markdown +10 -0
  6. data/Gemfile +1 -1
  7. data/README.markdown +129 -89
  8. data/Rakefile +7 -4
  9. data/benchmark.rb +13 -13
  10. data/lib/timezone/active_support.rb +147 -134
  11. data/lib/timezone/configure.rb +131 -110
  12. data/lib/timezone/deprecate.rb +32 -0
  13. data/lib/timezone/error.rb +16 -5
  14. data/lib/timezone/loader.rb +19 -16
  15. data/lib/timezone/lookup/basic.rb +24 -2
  16. data/lib/timezone/lookup/geonames.rb +9 -5
  17. data/lib/timezone/lookup/google.rb +24 -15
  18. data/lib/timezone/lookup/test.rb +8 -8
  19. data/lib/timezone/lookup.rb +68 -0
  20. data/lib/timezone/net_http_client.rb +23 -9
  21. data/lib/timezone/nil_zone.rb +32 -0
  22. data/lib/timezone/parser.rb +10 -5
  23. data/lib/timezone/version.rb +2 -1
  24. data/lib/timezone/zone.rb +230 -99
  25. data/lib/timezone.rb +75 -1
  26. data/test/basic_lookup_test.rb +2 -2
  27. data/test/geonames_lookup_test.rb +13 -6
  28. data/test/google_lookup_test.rb +34 -24
  29. data/test/http_test_client.rb +7 -6
  30. data/test/test_lookup_test.rb +3 -1
  31. data/test/test_timezone.rb +59 -0
  32. data/test/timezone/lookup/test_geonames.rb +59 -0
  33. data/test/timezone/lookup/test_google.rb +94 -0
  34. data/test/timezone/lookup/test_test.rb +24 -0
  35. data/test/timezone/test_deprecate.rb +20 -0
  36. data/test/timezone/test_loader.rb +32 -0
  37. data/test/timezone/test_lookup.rb +53 -0
  38. data/test/timezone/test_nil_zone.rb +26 -0
  39. data/test/timezone/test_zone.rb +49 -0
  40. data/test/timezone_test.rb +64 -63
  41. data/timezone.gemspec +16 -15
  42. metadata +39 -38
  43. data/.rubocop_todo.yml +0 -235
@@ -1,235 +1,256 @@
1
1
  require 'timezone/net_http_client'
2
2
  require 'timezone/lookup'
3
+ require 'timezone/deprecate'
3
4
 
4
5
  module Timezone
5
- # Configuration class for the Timezone gem.
6
- #
7
- # You'll want to sign up for a geonames username at
8
- # {http://www.geonames.org/login Geonames}. Use the username to
9
- # configure your application for latitude and longitude based
10
- # timezone searches.
11
- # Alternatively, you'll want to sign up for a Google api key at
12
- # {https://code.google.com/apis/console/ Google}. Use the api key to
13
- # configure your application for latitude and longitude based
14
- # timezone searches.
15
- #
16
- # If you aren't going to initialize timezone objects based on lat,lng
17
- # then this configuration is not necessary.
18
- #
19
- # @example
20
- # Timezone::Configure.begin do |c|
21
- # c.geonames_url = 'api.geonames.org'
22
- # c.username = 'foo-bar'
23
- # c.google_api_key = 'abc123'
24
- # end
6
+ # @deprecated `Timezone::Configure` will be removed in the release
7
+ # of the `timezone gem. Use `Timezone::Lookup::config` instead.
25
8
  #
9
+ # The old way to configure this gem.
10
+ # rubocop:disable Style/ClassVars
26
11
  class Configure
27
- # The Google API key
28
- #
29
- # @return [String]
30
- # the Google API key ('abc123')
12
+ DEPRECATE = '[DEPRECATED] `Timezone::Configure` will be removed ' \
13
+ 'in the release of the `timezone gem. Use `Timezone::Lookup` ' \
14
+ 'instead.'.freeze
15
+
16
+ # @deprecated `Timezone::Configure` will be removed in the release
17
+ # of the `timezone gem. Use `Timezone::Lookup instead.
31
18
  def self.google_api_key
32
- @google_api_key ||= nil
19
+ @@google_api_key ||= nil
33
20
  end
34
21
 
35
- # Google API key
36
- #
37
- # @param [String] api_key
38
- # the Google API key
22
+ # @deprecated `Timezone::Configure` will be removed in the release
23
+ # of the `timezone gem. Use `Timezone::Lookup instead.
39
24
  def self.google_api_key=(api_key)
40
- @google_api_key = api_key
25
+ @@google_api_key = api_key
41
26
  end
42
27
 
43
- # The Google Client ID (for enterprise)
44
- #
45
- # @return [String]
46
- # the Google Client ('abc123')
28
+ # @deprecated `Timezone::Configure` will be removed in the release
29
+ # of the `timezone gem. Use `Timezone::Lookup instead.
47
30
  def self.google_client_id
48
- @google_client_id ||= nil
31
+ @@google_client_id ||= nil
49
32
  end
50
33
 
51
- # Google Client ID (for enterprise)
52
- #
53
- # @param [String] client
54
- # the Google Client
34
+ # @deprecated `Timezone::Configure` will be removed in the release
35
+ # of the `timezone gem. Use `Timezone::Lookup instead.
55
36
  def self.google_client_id=(client)
56
- @google_client_id = client
37
+ @@google_client_id = client
57
38
  end
58
39
 
59
- # Use Google API if key has been set
60
- #
61
- # @return [Boolean]
40
+ # @deprecated `Timezone::Configure` will be removed in the release
41
+ # of the `timezone gem. Use `Timezone::Lookup instead.
62
42
  def self.use_google?
63
- !!google_api_key
43
+ !google_api_key.nil?
64
44
  end
65
45
 
66
- # Sign Google API request if client given (for enterprise)
67
- #
68
- # @return [Boolean]
46
+ # @deprecated `Timezone::Configure` will be removed in the release
47
+ # of the `timezone gem. Use `Timezone::Lookup instead.
69
48
  def self.use_google_enterprise?
70
- use_google? && !!google_client_id
49
+ use_google? && !google_client_id.nil?
71
50
  end
72
51
 
52
+ # @deprecated `Timezone::Configure` will be removed in the release
53
+ # of the `timezone gem. Use `Timezone::Lookup instead.
73
54
  def self.lookup=(lookup)
74
55
  @lookup = lookup && lookup.new(self)
75
56
  end
76
57
 
58
+ # @deprecated `Timezone::Configure` will be removed in the release
59
+ # of the `timezone gem. Use `Timezone::Lookup instead.
77
60
  def self.lookup
78
61
  return @lookup if @lookup
79
62
 
80
63
  use_google? ? google_lookup : geonames_lookup
81
64
  end
82
65
 
66
+ # Responsible for mapping old configuration options to new
67
+ # configuration style for forwards-compatability with the
68
+ # updated Google lookup.
69
+ class GoogleConfigMapper
70
+ def initialize(config)
71
+ @config = config
72
+ end
73
+
74
+ def protocol; @config.protocol; end
75
+
76
+ def url; @config.url; end
77
+
78
+ def http_client; @config.http_client; end
79
+
80
+ def api_key; @config.google_api_key; end
81
+
82
+ def client_id; @config.google_client_id; end
83
+
84
+ def request_handler; nil; end
85
+ end
86
+
87
+ private_constant :GoogleConfigMapper
88
+
89
+ # @deprecated `Timezone::Configure` will be removed in the release
90
+ # of the `timezone gem. Use `Timezone::Lookup instead.
83
91
  def self.google_lookup
84
- @google_lookup ||= Timezone::Lookup::Google.new(self)
92
+ @google_lookup ||=
93
+ Timezone::Lookup::Google.new(GoogleConfigMapper.new(self))
94
+ end
95
+
96
+ # Responsible for mapping old configuration options to new
97
+ # configuration style for forwards-compatability with the
98
+ # updated Geonames lookup.
99
+ class GeonamesConfigMapper
100
+ def initialize(config)
101
+ @config = config
102
+ end
103
+
104
+ def protocol; @config.protocol; end
105
+
106
+ def url; @config.url; end
107
+
108
+ def username; @config.username; end
109
+
110
+ def http_client; @config.http_client; end
111
+
112
+ def request_handler; nil; end
85
113
  end
86
114
 
115
+ private_constant :GeonamesConfigMapper
116
+
117
+ # @deprecated `Timezone::Configure` will be removed in the release
118
+ # of the `timezone gem. Use `Timezone::Lookup instead.
87
119
  def self.geonames_lookup
88
- @geonames_lookup ||= Timezone::Lookup::Geonames.new(self)
120
+ @geonames_lookup ||=
121
+ Timezone::Lookup::Geonames.new(GeonamesConfigMapper.new(self))
89
122
  end
90
123
 
91
- # The Geonames API URL
92
- #
93
- # @return [String]
94
- # the Geonames API URL ('api.geonames.org')
124
+ # @deprecated `Timezone::Configure` will be removed in the release
125
+ # of the `timezone gem. Use `Timezone::Lookup instead.
95
126
  def self.geonames_url
96
127
  @@geonames_url ||= 'api.geonames.org'
97
128
  end
98
129
 
99
- # The Geonames API URL
100
- #
101
- # @param [String] url
102
- # the Geonames API URL
130
+ # @deprecated `Timezone::Configure` will be removed in the release
131
+ # of the `timezone gem. Use `Timezone::Lookup instead.
103
132
  def self.geonames_url=(url)
104
133
  @@geonames_url = url
105
134
  end
106
135
 
107
- class << self
108
- alias url= geonames_url=
136
+ # @deprecated `Timezone::Configure` will be removed in the release
137
+ # of the `timezone gem. Use `Timezone::Lookup instead.
138
+ def self.url=(url)
139
+ self.geonames_url = url
109
140
  end
110
141
 
111
- # The Google API URL
112
- #
113
- # @return [String]
114
- # the Google API URL ('maps.googleapis.com')
142
+ # @deprecated `Timezone::Configure` will be removed in the release
143
+ # of the `timezone gem. Use `Timezone::Lookup instead.
115
144
  def self.google_url
116
145
  @@google_url ||= 'maps.googleapis.com'
117
146
  end
118
147
 
119
- # The Google API URL
120
- #
121
- # @param [String] url
122
- # the Google API URL
148
+ # @deprecated `Timezone::Configure` will be removed in the release
149
+ # of the `timezone gem. Use `Timezone::Lookup instead.
123
150
  def self.google_url=(url)
124
151
  @@google_url = url
125
152
  end
126
153
 
127
- # Use Google URL if key has been set else use Geonames URL
128
- #
129
- # @return [String]
130
- # the Google or Geonames API URL
154
+ # @deprecated `Timezone::Configure` will be removed in the release
155
+ # of the `timezone gem. Use `Timezone::Lookup instead.
131
156
  def self.url
132
157
  use_google? ? google_url : geonames_url
133
158
  end
134
159
 
135
- # The Geonames API HTTP protocol
136
- #
137
- # @param [String] protocol
138
- # the Geonames API HTTP procotol
160
+ # @deprecated `Timezone::Configure` will be removed in the release
161
+ # of the `timezone gem. Use `Timezone::Lookup instead.
139
162
  def self.geonames_protocol=(protocol)
140
163
  @@geonames_protocol = protocol
141
164
  end
142
165
 
143
- # The Geonames API HTTP protocol
144
- #
145
- # @return [String]
146
- # the Geonames API HTTP protocol ('http')
166
+ # @deprecated `Timezone::Configure` will be removed in the release
167
+ # of the `timezone gem. Use `Timezone::Lookup instead.
147
168
  def self.geonames_protocol
148
169
  @@geonames_protocol ||= 'http'
149
170
  end
150
171
 
151
- # The Google API HTTP protocol
152
- #
153
- # @param [String] protocol
154
- # the Google API HTTP procotol
172
+ # @deprecated `Timezone::Configure` will be removed in the release
173
+ # of the `timezone gem. Use `Timezone::Lookup instead.
155
174
  def self.google_protocol=(protocol)
156
175
  @@google_protocol = protocol
157
176
  end
158
177
 
159
- # The Google API HTTP protocol
160
- #
161
- # @return [String]
162
- # the Google API HTTP protocol ('https')
178
+ # @deprecated `Timezone::Configure` will be removed in the release
179
+ # of the `timezone gem. Use `Timezone::Lookup instead.
163
180
  def self.google_protocol
164
181
  @@google_protocol ||= 'https'
165
182
  end
166
183
 
167
- # Use Google protocol if key has been set else use Geonames protocol
168
- #
169
- # @return [String]
170
- # the Google or Geonames API protocol
184
+ # @deprecated `Timezone::Configure` will be removed in the release
185
+ # of the `timezone gem. Use `Timezone::Lookup instead.
171
186
  def self.protocol
172
187
  use_google? ? google_protocol : geonames_protocol
173
188
  end
174
189
 
175
- # The HTTP client that handles requests to Geonames and Google
176
- #
177
- # @return [Object]
178
- # the HTTP client ({Timezone::NetHTTPClient Timezone::NetHTTPClient})
190
+ # @deprecated `Timezone::Configure` will be removed in the release
191
+ # of the `timezone gem. Use `Timezone::Lookup instead.
179
192
  def self.http_client
180
193
  @@http_client ||= Timezone::NetHTTPClient
181
194
  end
182
195
 
183
- # The HTTP client that handles requests to Geonames and Google
184
- #
185
- # @param [Object] client
186
- # the HTTP client that handles requests to Geonames and Google
187
- #
196
+ # @deprecated `Timezone::Configure` will be removed in the release
197
+ # of the `timezone gem. Use `Timezone::Lookup instead.
188
198
  def self.http_client=(client)
189
199
  @@http_client = client
190
200
  end
191
201
 
192
- # The Geonames API username
193
- #
194
- # @return [String]
195
- # the Geonames API username ('foo-bar')
202
+ # @deprecated `Timezone::Configure` will be removed in the release
203
+ # of the `timezone gem. Use `Timezone::Lookup instead.
196
204
  def self.username
197
205
  @@username ||= nil
198
206
  end
199
207
 
200
- # The Geonames API username
201
- #
202
- # @param [String] username
203
- # the Geonames API username
208
+ # @deprecated `Timezone::Configure` will be removed in the release
209
+ # of the `timezone gem. Use `Timezone::Lookup instead.
204
210
  def self.username=(username)
205
211
  @@username = username
206
212
  end
207
213
 
214
+ # @deprecated `Timezone::Configure` will be removed in the release
215
+ # of the `timezone gem. Use `Timezone::Lookup instead.
208
216
  def self.begin
217
+ Deprecate.call(self, :begin, DEPRECATE)
209
218
  yield self
210
219
  end
211
220
 
212
- def self.replace(what, with = Hash.new)
221
+ # @deprecated `Timezone::Configure` will be removed in the release
222
+ # of the `timezone gem. Use `Timezone::Lookup instead.
223
+ def self.replace(what, with = {})
213
224
  replacements # instantiate @@replacements
214
225
  @@replacements[what] = with[:with]
215
226
  end
216
227
 
228
+ # @deprecated `Timezone::Configure` will be removed in the release
229
+ # of the `timezone gem. Use `Timezone::Lookup instead.
217
230
  def self.replacements
218
231
  @@replacements ||= {}
219
232
  end
220
233
 
234
+ # @deprecated `Timezone::Configure` will be removed in the release
235
+ # of the `timezone gem. Use `Timezone::Lookup instead.
221
236
  def self.default_for_list
222
237
  @@default_list ||= nil
223
238
  end
224
239
 
240
+ # @deprecated `Timezone::Configure` will be removed in the release
241
+ # of the `timezone gem. Use `Timezone::Lookup instead.
225
242
  def self.default_for_list=(*list)
226
243
  @@default_list = list.flatten!
227
244
  end
228
245
 
246
+ # @deprecated `Timezone::Configure` will be removed in the release
247
+ # of the `timezone gem. Use `Timezone::Lookup instead.
229
248
  def self.order_list_by
230
249
  @@order_by ||= :utc_offset
231
250
  end
232
251
 
252
+ # @deprecated `Timezone::Configure` will be removed in the release
253
+ # of the `timezone gem. Use `Timezone::Lookup instead.
233
254
  def self.order_list_by=(order)
234
255
  @@order_by = order
235
256
  end
@@ -0,0 +1,32 @@
1
+ module Timezone
2
+ # This class provides a way to set a custom hook for deprecations.
3
+ module Deprecate
4
+ class << self
5
+ # Set the custom deprecation callback. By default this
6
+ # issues a deprecation warning.
7
+ #
8
+ # @param callback [#call] the custom callback
9
+ #
10
+ # @example Send a message to StatsD
11
+ # Timezone::Deprecate.callback = lambda do |klass, method, _|
12
+ # StatsD.increment(sanitize(klass, method))
13
+ # end
14
+ #
15
+ # @example Send a message to a custom logger
16
+ # Timezone::Deprecate.callback = lambda do |klass, method, msg|
17
+ # MyLogger.log("[#{klass} : #{method}] #{msg}")
18
+ # end
19
+ attr_writer :callback
20
+
21
+ # @!visibility private
22
+ def callback
23
+ @callback || -> (_, _, message) { warn(message) }
24
+ end
25
+
26
+ # @!visibility private
27
+ def call(klass, method, message)
28
+ callback && callback.call(klass, method, message)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -1,5 +1,6 @@
1
1
  module Timezone
2
- # Error messages that can be raised by this gem. To catch any related error message, simply use Error::Base.
2
+ # Error messages that can be raised by this gem. To catch any
3
+ # related error message, use Error::Base.
3
4
  #
4
5
  # begin
5
6
  # ...
@@ -7,13 +8,23 @@ module Timezone
7
8
  # puts "Timezone Error: #{e.message}"
8
9
  # end
9
10
  module Error
11
+ # Top-level error. All other timezone errors subclass this one.
10
12
  class Base < StandardError; end
13
+ # Indicates an invalid timezone name.
11
14
  class InvalidZone < Base; end
15
+ # @deprecated this class will be removed in the next release of the gem.
12
16
  class NilZone < Base; end
13
- class GeoNames < Base; end
14
- class Google < Base; end
17
+ # Indicates a lookup failure.
18
+ class Lookup < Base; end
19
+ # Indicates an error during lookup using the geonames API.
20
+ class GeoNames < Lookup; end
21
+ # Indicates an error during lookup using the google API.
22
+ class Google < Lookup; end
23
+ # @deprecated this class will be removed in the next release of the gem.
15
24
  class ParseTime < Base; end
16
- class Test < Base ; end
17
- class InvalidConfig < Base ; end
25
+ # Indicates a missing stub during a test lookup.
26
+ class Test < Lookup; end
27
+ # Indicates an invalid configuration.
28
+ class InvalidConfig < Base; end
18
29
  end
19
30
  end
@@ -1,27 +1,34 @@
1
1
  require 'timezone/error'
2
2
 
3
- module Timezone
3
+ module Timezone # rubocop:disable Style/Documentation
4
+ # Responsible for loading and parsing timezone data from files.
4
5
  module Loader
5
- ZONE_FILE_PATH = File.expand_path(File.dirname(__FILE__)+'/../../data')
6
+ ZONE_FILE_PATH = File.expand_path(File.dirname(__FILE__) + '/../../data')
6
7
  SOURCE_BIT = 0
7
8
 
8
9
  class << self
9
- def load(zone)
10
+ def load(name)
11
+ raise ::Timezone::Error::InvalidZone unless valid?(name)
12
+
10
13
  @rules ||= {}
11
- @rules[zone] ||= parse_zone_data(get_zone_data(zone))
14
+ @rules[name] ||= parse_zone_data(get_zone_data(name))
12
15
  end
13
16
 
14
17
  def names
15
- @@names ||= parse_zone_names
18
+ @names ||= parse_zone_names
19
+ end
20
+
21
+ def valid?(name)
22
+ names.include?(name)
16
23
  end
17
24
 
18
25
  private
19
26
 
20
27
  def parse_zone_names
21
- files = Dir[File.join(ZONE_FILE_PATH, "**/*")].map do |file|
28
+ files = Dir[File.join(ZONE_FILE_PATH, '**/*')].map do |file|
22
29
  next if File.directory?(file)
23
30
 
24
- file.gsub("#{ZONE_FILE_PATH}/", '')
31
+ file.sub("#{ZONE_FILE_PATH}/", '')
25
32
  end
26
33
 
27
34
  files.compact
@@ -35,7 +42,7 @@ module Timezone
35
42
  source = source.to_i
36
43
  dst = dst == '1'
37
44
  offset = offset.to_i
38
- source = rules.last[SOURCE_BIT]+source if rules.last
45
+ source = rules.last[SOURCE_BIT] + source if rules.last
39
46
  rules << [source, name, dst, offset]
40
47
  end
41
48
 
@@ -43,15 +50,11 @@ module Timezone
43
50
  end
44
51
 
45
52
  # Retrieve the data from a particular time zone
46
- def get_zone_data(zone)
47
- file = File.join(ZONE_FILE_PATH, zone)
48
-
49
- if !File.exists?(file)
50
- raise Timezone::Error::InvalidZone, "'#{zone}' is not a valid zone."
51
- end
52
-
53
- File.read(file)
53
+ def get_zone_data(name)
54
+ File.read(File.join(ZONE_FILE_PATH, name))
54
55
  end
55
56
  end
56
57
  end
58
+
59
+ private_constant :Loader
57
60
  end
@@ -2,9 +2,13 @@ require 'timezone/error'
2
2
 
3
3
  module Timezone
4
4
  module Lookup
5
+ # @abstract Subclass and override {#lookup} to implement
6
+ # a custom Lookup class.
5
7
  class Basic
6
8
  attr_reader :config
7
9
 
10
+ # @param config [#protocol, #url, #request_handler] a configuration
11
+ # object
8
12
  def initialize(config)
9
13
  if config.protocol.nil?
10
14
  raise(::Timezone::Error::InvalidConfig, 'missing protocol')
@@ -17,11 +21,29 @@ module Timezone
17
21
  @config = config
18
22
  end
19
23
 
24
+ # Returns an instance of the request handler.
25
+ #
26
+ # @return [#get] an instance of a request handler
20
27
  def client
21
- @client ||= config.http_client.new(config.protocol, config.url)
28
+ # TODO: Remove http_client once on 1.0.0
29
+ @client ||=
30
+ if !config.request_handler.nil?
31
+ config.request_handler.new(config)
32
+ else
33
+ config.http_client.new(config.protocol, config.url)
34
+ end
22
35
  end
23
36
 
24
- def lookup(lat, lng)
37
+ # Returns a timezone name for a given lat, long pair.
38
+ #
39
+ # @param lat [Double] latitude coordinate
40
+ # @param long [Double] longitude coordinate
41
+ # @return [String] the timezone name
42
+ # @return [nil] if the lat, long pair does not resolve to an
43
+ # actual timezone
44
+ # @raise [Timezone::Error::Base] if an error occurred while
45
+ # while performing the lookup
46
+ def lookup(_lat, _long)
25
47
  raise NoMethodError, 'lookup is not implemented'
26
48
  end
27
49
  end
@@ -5,17 +5,21 @@ require 'uri'
5
5
 
6
6
  module Timezone
7
7
  module Lookup
8
+ # @!visibility private
8
9
  class Geonames < ::Timezone::Lookup::Basic
9
10
  def initialize(config)
10
11
  if config.username.nil?
11
- raise(::Timezone::Error::InvalidConfig, 'missing username')
12
+ raise(::Timezone::Error::InvalidConfig, 'missing username'.freeze)
12
13
  end
13
14
 
15
+ config.protocol ||= 'http'.freeze
16
+ config.url ||= 'api.geonames.org'.freeze
17
+
14
18
  super
15
19
  end
16
20
 
17
- def lookup(lat, lng)
18
- response = client.get(url(lat, lng))
21
+ def lookup(lat, long)
22
+ response = client.get(url(lat, long))
19
23
 
20
24
  return unless response.code =~ /^2\d\d$/
21
25
 
@@ -32,10 +36,10 @@ module Timezone
32
36
 
33
37
  private
34
38
 
35
- def url(lat, lng)
39
+ def url(lat, long)
36
40
  query = URI.encode_www_form(
37
41
  'lat' => lat,
38
- 'lng' => lng,
42
+ 'lng' => long,
39
43
  'username' => config.username)
40
44
  "/timezoneJSON?#{query}"
41
45
  end
@@ -8,53 +8,62 @@ require 'cgi'
8
8
 
9
9
  module Timezone
10
10
  module Lookup
11
+ # @!visibility private
11
12
  class Google < ::Timezone::Lookup::Basic
12
13
  def initialize(config)
13
- if config.google_api_key.nil?
14
- raise(::Timezone::Error::InvalidConfig, 'missing api key')
14
+ if config.api_key.nil?
15
+ raise(::Timezone::Error::InvalidConfig, 'missing api key'.freeze)
15
16
  end
17
+
18
+ config.protocol ||= 'https'.freeze
19
+ config.url ||= 'maps.googleapis.com'.freeze
20
+
16
21
  super
17
22
  end
18
23
 
19
- def lookup(lat,lng)
20
- response = client.get(url(lat,lng))
24
+ def lookup(lat, long)
25
+ response = client.get(url(lat, long))
21
26
 
22
- if response.code == '403'
23
- raise(Timezone::Error::Google, '403 Forbidden')
27
+ if response.code == '403'.freeze
28
+ raise(Timezone::Error::Google, '403 Forbidden'.freeze)
24
29
  end
25
30
 
26
31
  return unless response.code =~ /^2\d\d$/
27
32
  data = JSON.parse(response.body)
28
33
 
29
- if data['status'] != 'OK'
34
+ if data['status'.freeze] != 'OK'.freeze
30
35
  raise(Timezone::Error::Google, data['errorMessage'])
31
36
  end
32
37
 
33
- data['timeZoneId']
38
+ data['timeZoneId'.freeze]
34
39
  rescue => e
35
40
  raise(Timezone::Error::Google, e.message)
36
41
  end
37
42
 
38
43
  private
39
44
 
45
+ def use_google_enterprise?
46
+ !config.client_id.nil?
47
+ end
48
+
40
49
  def authorize(url)
41
- if config.use_google_enterprise?
42
- url += "&client=#{CGI.escape(config.google_client_id)}"
50
+ if use_google_enterprise?
51
+ url += "&client=#{CGI.escape(config.client_id)}"
43
52
 
44
53
  sha1 = OpenSSL::Digest.new('sha1')
45
- binary_key = Base64.decode64(config.google_api_key.tr('-_','+/'))
54
+ binary_key = Base64.decode64(config.api_key.tr('-_', '+/'))
46
55
  binary_signature = OpenSSL::HMAC.digest(sha1, binary_key, url)
47
- signature = Base64.encode64(binary_signature).tr('+/','-_').strip
56
+ signature = Base64.encode64(binary_signature).tr('+/', '-_').strip
48
57
 
49
58
  url + "&signature=#{signature}"
50
59
  else
51
- url + "&key=#{config.google_api_key}"
60
+ url + "&key=#{config.api_key}"
52
61
  end
53
62
  end
54
63
 
55
- def url(lat,lng)
64
+ def url(lat, long)
56
65
  query = URI.encode_www_form(
57
- 'location' => "#{lat},#{lng}",
66
+ 'location' => "#{lat},#{long}",
58
67
  'timestamp' => Time.now.to_i)
59
68
 
60
69
  authorize("/maps/api/timezone/json?#{query}")