google_maps_apis 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,101 @@
1
+ require_relative '../validator'
2
+
3
+ module GoogleMapsApis::Services
4
+
5
+ # Performs requests to the Google Maps Directions API.
6
+ module Directions
7
+
8
+ # Get directions between an origin point and a destination point.
9
+ #
10
+ # @example Simple directions
11
+ # routes = client.directions('Sydney', 'Melbourne')
12
+ #
13
+ # @example Complex bicycling directions
14
+ # routes = client.directions('Sydney', 'Melbourne',
15
+ # mode: 'bicycling',
16
+ # avoid: ['highways', 'tolls', 'ferries'],
17
+ # units: 'metric',
18
+ # region: 'au')
19
+ #
20
+ # @example Public transportation directions
21
+ # an_hour_from_now = Time.now - (1.0/24)
22
+ # routes = client.directions('Sydney Town Hall', 'Parramatta, NSW',
23
+ # mode: 'transit',
24
+ # arrival_time: an_hour_from_now)
25
+ #
26
+ # @example Walking with alternative routes
27
+ # routes = client.directions('Sydney Town Hall', 'Parramatta, NSW',
28
+ # mode: 'walking',
29
+ # alternatives: true)
30
+ #
31
+ # @param [String, Hash, Array] origin The address or latitude/longitude value from which you wish
32
+ # to calculate directions.
33
+ # @param [String, Hash, Array] destination The address or latitude/longitude value from which
34
+ # you wish to calculate directions.
35
+ # @param [String] mode Specifies the mode of transport to use when calculating
36
+ # directions. One of `driving`, `walking`, `bicycling` or `transit`.
37
+ # @param [Array<String>, Array<Hash>, Array<Array>] waypoints Specifies an array of waypoints. Waypoints alter a
38
+ # route by routing it through the specified location(s).
39
+ # @param [Boolean] alternatives If True, more than one route may be returned in the
40
+ # response.
41
+ # @param [Array, String] avoid Indicates that the calculated route(s) should avoid the
42
+ # indicated features.
43
+ # @param [String] language The language in which to return results.
44
+ # @param [String] units Specifies the unit system to use when displaying results.
45
+ # `metric` or `imperial`.
46
+ # @param [String] region The region code, specified as a ccTLD (_top-level domain_)
47
+ # two-character value.
48
+ # @param [Integer, DateTime] departure_time Specifies the desired time of departure.
49
+ # @param [Integer, DateTime] arrival_time Specifies the desired time of arrival for transit
50
+ # directions. Note: you can not specify both `departure_time` and
51
+ # `arrival_time`.
52
+ # @param [Boolean] optimize_waypoints Optimize the provided route by rearranging the
53
+ # waypoints in a more efficient order.
54
+ # @param [String, Array<String>] transit_mode Specifies one or more preferred modes of transit.
55
+ # This parameter may only be specified for requests where the mode is
56
+ # transit. Valid values are `bus`, `subway`, `train`, `tram` or `rail`.
57
+ # `rail` is equivalent to `["train", "tram", "subway"]`.
58
+ # @param [String] transit_routing_preference Specifies preferences for transit
59
+ # requests. Valid values are `less_walking` or `fewer_transfers`.
60
+ #
61
+ # @return [Array] Array of routes.
62
+ def directions(origin, destination,
63
+ mode: nil, waypoints: nil, alternatives: false, avoid: nil,
64
+ language: nil, units: nil, region: nil, departure_time: nil,
65
+ arrival_time: nil, optimize_waypoints: false, transit_mode: nil,
66
+ transit_routing_preference: nil)
67
+
68
+ params = {
69
+ origin: GoogleMapsApis::Convert.waypoint(origin),
70
+ destination: GoogleMapsApis::Convert.waypoint(destination)
71
+ }
72
+
73
+ params[:mode] = GoogleMapsApis::Validator.travel_mode(mode) if mode
74
+
75
+ if waypoints = waypoints
76
+ waypoints = GoogleMapsApis::Convert.as_list(waypoints)
77
+ waypoints = waypoints.map { |waypoint| GoogleMapsApis::Convert.waypoint(waypoint) }
78
+ waypoints = ['optimize:true'] + waypoints if optimize_waypoints
79
+
80
+ params[:waypoints] = GoogleMapsApis::Convert.join_list("|", waypoints)
81
+ end
82
+
83
+ params[:alternatives] = 'true' if alternatives
84
+ params[:avoid] = GoogleMapsApis::Convert.join_list('|', avoid) if avoid
85
+ params[:language] = language if language
86
+ params[:units] = units if units
87
+ params[:region] = region if region
88
+ params[:departure_time] = GoogleMapsApis::Convert.time(departure_time) if departure_time
89
+ params[:arrival_time] = GoogleMapsApis::Convert.time(arrival_time) if arrival_time
90
+
91
+ if departure_time and arrival_time
92
+ raise ArgumentError, 'Should not specify both departure_time and arrival_time.'
93
+ end
94
+
95
+ params[:transit_mode] = GoogleMapsApis::Convert.join_list("|", transit_mode) if transit_mode
96
+ params[:transit_routing_preference] = transit_routing_preference if transit_routing_preference
97
+
98
+ return get('/maps/api/directions/json', params)[:routes]
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,85 @@
1
+ require_relative '../validator'
2
+
3
+ module GoogleMapsApis::Services
4
+
5
+ # Performs requests to the Google Maps Distance Matrix API.
6
+ module DistanceMatrix
7
+
8
+ # Gets travel distance and time for a matrix of origins and destinations.
9
+ #
10
+ # @example Simple distance matrix
11
+ # origins = ["Perth, Australia", "Sydney, Australia",
12
+ # "Melbourne, Australia", "Adelaide, Australia",
13
+ # "Brisbane, Australia", "Darwin, Australia",
14
+ # "Hobart, Australia", "Canberra, Australia"]
15
+ # destinations = ["Uluru, Australia",
16
+ # "Kakadu, Australia",
17
+ # "Blue Mountains, Australia",
18
+ # "Bungle Bungles, Australia",
19
+ # "The Pinnacles, Australia"]
20
+ # matrix = client.distance_matrix(origins, destinations)
21
+ #
22
+ # @example Complex distance matrix
23
+ # origins = ["Bobcaygeon ON", [41.43206, -81.38992]]
24
+ # destinations = [[43.012486, -83.6964149], {lat: 42.8863855, lng: -78.8781627}]
25
+ # matrix = client.distance_matrix(origins, destinations,
26
+ # mode: 'driving',
27
+ # language: 'en-AU',
28
+ # avoid: 'tolls',
29
+ # units: 'imperial')
30
+ #
31
+ # @param [Array] origins One or more addresses and/or lat/lon pairs,
32
+ # from which to calculate distance and time. If you pass an address
33
+ # as a string, the service will geocode the string and convert it to
34
+ # a lat/lon coordinate to calculate directions.
35
+ # @param [Array] destinations One or more addresses and/or lat/lon pairs, to
36
+ # which to calculate distance and time. If you pass an address as a
37
+ # string, the service will geocode the string and convert it to a
38
+ # lat/lon coordinate to calculate directions.
39
+ # @param [String] mode Specifies the mode of transport to use when calculating
40
+ # directions. Valid values are `driving`, `walking`, `transit` or `bicycling`.
41
+ # @param [String] language The language in which to return results.
42
+ # @param [String] avoid Indicates that the calculated route(s) should avoid the
43
+ # indicated features. Valid values are `tolls`, `highways` or `ferries`.
44
+ # @param [String] units Specifies the unit system to use when displaying results.
45
+ # Valid values are `metric` or `imperial`.
46
+ # @param [Integer, DateTime] departure_time Specifies the desired time of departure.
47
+ # @param [Integer, DateTime] arrival_time Specifies the desired time of arrival for transit
48
+ # directions. Note: you can not specify both `departure_time` and `arrival_time`.
49
+ # @param [String, Array<String>] transit_mode Specifies one or more preferred modes of transit.
50
+ # This parameter may only be specified for requests where the mode is
51
+ # transit. Valid values are `bus`, `subway`, `train`, `tram`, or `rail`.
52
+ # `rail` is equivalent to `["train", "tram", "subway"]`.
53
+ # @param [String] transit_routing_preference Specifies preferences for transit
54
+ # requests. Valid values are `less_walking` or `fewer_transfers`.
55
+ #
56
+ # @return [Hash] Matrix of distances. Results are returned in rows, each row
57
+ # containing one origin paired with each destination.
58
+ def distance_matrix(origins, destinations,
59
+ mode: nil, language: nil, avoid: nil, units: nil,
60
+ departure_time: nil, arrival_time: nil, transit_mode: nil,
61
+ transit_routing_preference: nil)
62
+ params = {
63
+ origins: GoogleMapsApis::Convert.waypoints(origins),
64
+ destinations: GoogleMapsApis::Convert.waypoints(destinations)
65
+ }
66
+
67
+ params[:language] = language if language
68
+ params[:mode] = GoogleMapsApis::Validator.travel_mode(mode) if mode
69
+ params[:avoid] = GoogleMapsApis::Validator.avoid(avoid) if avoid
70
+
71
+ params[:units] = units if units
72
+ params[:departure_time] = GoogleMapsApis::Convert.time(departure_time) if departure_time
73
+ params[:arrival_time] = GoogleMapsApis::Convert.time(arrival_time) if arrival_time
74
+
75
+ if departure_time and arrival_time
76
+ raise ArgumentError, 'Should not specify both departure_time and arrival_time.'
77
+ end
78
+
79
+ params[:transit_mode] = GoogleMapsApis::Convert.join_list('|', transit_mode) if transit_mode
80
+ params[:transit_routing_preference] = transit_routing_preference if transit_routing_preference
81
+
82
+ return get('/maps/api/distancematrix/json', params)
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,58 @@
1
+ module GoogleMapsApis::Services
2
+
3
+ # Performs requests to the Google Maps Elevation API.
4
+ module Elevation
5
+
6
+ # Provides elevation data for locations provided on the surface of the
7
+ # earth, including depth locations on the ocean floor (which return negative
8
+ # values).
9
+ #
10
+ # @example Single point elevation
11
+ # results = client.elevation({latitude: 40.714728, longitude: -73.998672})
12
+ #
13
+ # @example Multiple points elevation
14
+ # locations = [[40.714728, -73.998672], [-34.397, 150.644]]
15
+ # results = client.elevation(locations)
16
+ #
17
+ # @param [Array] locations A single latitude/longitude hash, or an array of
18
+ # latitude/longitude hash from which you wish to calculate
19
+ # elevation data.
20
+ #
21
+ # @return [Array] Array of elevation data responses
22
+ def elevation(locations)
23
+ params = {
24
+ locations: GoogleMapsApis::Convert.waypoints(locations)
25
+ }
26
+
27
+ return get('/maps/api/elevation/json', params)[:results]
28
+ end
29
+
30
+ # Provides elevation data sampled along a path on the surface of the earth.
31
+ #
32
+ # @example Elevation along path
33
+ # locations = [[40.714728, -73.998672], [-34.397, 150.644]]
34
+ # results = client.elevation_along_path(locations, 5)
35
+ #
36
+ # @param [String, Array] path A encoded polyline string, or a list of
37
+ # latitude/longitude pairs from which you wish to calculate
38
+ # elevation data.
39
+ # @param [Integer] samples The number of sample points along a path for which to
40
+ # return elevation data.
41
+ #
42
+ # @return [Array] Array of elevation data responses
43
+ def elevation_along_path(path, samples)
44
+ if path.kind_of?(String)
45
+ path = "enc:%s" % path
46
+ else
47
+ path = GoogleMapsApis::Convert.waypoints(path)
48
+ end
49
+
50
+ params = {
51
+ path: path,
52
+ samples: samples
53
+ }
54
+
55
+ return get('/maps/api/elevation/json', params)[:results]
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,85 @@
1
+ require 'google_maps_apis/convert'
2
+
3
+ module GoogleMapsApis::Services
4
+
5
+ # Performs requests to the Google Maps Geocoding API.
6
+ module Geocoding
7
+
8
+ # Geocoding is the process of converting addresses
9
+ # (like `"1600 Amphitheatre Parkway, Mountain View, CA"`) into geographic
10
+ # coordinates (like latitude 37.423021 and longitude -122.083739), which you
11
+ # can use to place markers or position the map.
12
+ #
13
+ # @example Geocode an address
14
+ # results = client.geocode('Sydney')
15
+ #
16
+ # @example Geocode a component only
17
+ # results = client.geocode(nil, components: {administrative_area: 'TX', country: 'US'})
18
+ #
19
+ # @example Geocode an address and component
20
+ # results = client.geocode('Sydney', components: {administrative_area: 'TX', country: 'US'})
21
+ #
22
+ # @example Multiple parameters
23
+ # results = client.geocode('Sydney',
24
+ # components: {administrative_area: 'TX', country: 'US'},
25
+ # bounds: {
26
+ # northeast: {lat: 32.7183997, lng: -97.26864001970849},
27
+ # southwest: {lat: 32.7052583, lng: -97.27133798029149}
28
+ # },
29
+ # region: 'us')
30
+ #
31
+ # @param [String] address The address to geocode. You must specify either this value and/or `components`.
32
+ # @param [Hash] components A component filter for which you wish to obtain a geocode,
33
+ # for example: `{'administrative_area': 'TX','country': 'US'}`
34
+ # @param [String, Hash] bounds The bounding box of the viewport within which to bias geocode
35
+ # results more prominently. Accept string or hash with `northeast` and `southwest` keys.
36
+ # @param [String] region The region code, specified as a ccTLD (_top-level domain_)
37
+ # two-character value.
38
+ # @param [String] language The language in which to return results.
39
+ #
40
+ # @return [Array] Array of geocoding results.
41
+ def geocode(address, components: nil, bounds: nil, region: nil, language: nil)
42
+ params = {}
43
+
44
+ params[:address] = address if address
45
+ params[:components] = GoogleMapsApis::Convert.components(components) if components
46
+ params[:bounds] = GoogleMapsApis::Convert.bounds(bounds) if bounds
47
+ params[:region] = region if region
48
+ params[:language] = language if language
49
+
50
+ return get('/maps/api/geocode/json', params)[:results]
51
+ end
52
+
53
+ # Reverse geocoding is the process of converting geographic coordinates into a
54
+ # human-readable address.
55
+ #
56
+ # @example Simple lat/lon pair
57
+ # client.reverse_geocode({lat: 40.714224, lng: -73.961452})
58
+ #
59
+ # @example Multiple parameters
60
+ # client.reverse_geocode([40.714224, -73.961452],
61
+ # location_type: ['ROOFTOP', 'RANGE_INTERPOLATED'],
62
+ # result_type: ['street_address', 'route'],
63
+ # language: 'es')
64
+ #
65
+ # @param [Hash, Array] latlng The latitude/longitude value for which you wish to obtain
66
+ # the closest, human-readable address.
67
+ # @param [String, Array<String>] location_type One or more location types to restrict results to.
68
+ # @param [String, Array<String>] result_type One or more address types to restrict results to.
69
+ # @param [String] language The language in which to return results.
70
+ #
71
+ # @return [Array] Array of reverse geocoding results.
72
+ def reverse_geocode(latlng, location_type: nil, result_type: nil, language: nil)
73
+ params = {
74
+ latlng: GoogleMapsApis::Convert.latlng(latlng)
75
+ }
76
+
77
+ params[:result_type] = GoogleMapsApis::Convert.join_list('|', result_type) if result_type
78
+ params[:location_type] = GoogleMapsApis::Convert.join_list('|', location_type) if location_type
79
+ params[:language] = language if language
80
+
81
+ return get('/maps/api/geocode/json', params)[:results]
82
+ end
83
+
84
+ end
85
+ end
@@ -0,0 +1,20 @@
1
+ require 'google_maps_apis/convert'
2
+
3
+ module GoogleMapsApis::Services
4
+
5
+ # Performs requests to the Google Maps Geocoding API.
6
+ module Places
7
+ def places_autocomplete(input, components: nil, bounds: nil, types: nil, region: nil, language: nil)
8
+ params = {}
9
+
10
+ params[:input] = input
11
+ params[:components] = GoogleMapsApis::Convert.components(components) if components
12
+ params[:bounds] = GoogleMapsApis::Convert.bounds(bounds) if bounds
13
+ params[:region] = region if region
14
+ params[:language] = language if language
15
+ params[:types] = types if types
16
+
17
+ return get('/maps/api/place/autocomplete/json', params)[:predictions]
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,187 @@
1
+ require 'multi_json'
2
+
3
+ module GoogleMapsApis::Services
4
+
5
+ # Performs requests to the Google Maps Roads API.
6
+ module Roads
7
+
8
+ # Base URL of Google Maps Roads API
9
+ ROADS_BASE_URL = "https://roads.googleapis.com"
10
+
11
+ # Snaps a path to the most likely roads travelled.
12
+ #
13
+ # Takes up to 100 GPS points collected along a route, and returns a similar
14
+ # set of data with the points snapped to the most likely roads the vehicle
15
+ # was traveling along.
16
+ #
17
+ # @example Single point snap
18
+ # results = client.snap_to_roads([40.714728, -73.998672])
19
+ #
20
+ # @example Multi points snap
21
+ # path = [
22
+ # [-33.8671, 151.20714],
23
+ # [-33.86708, 151.20683000000002],
24
+ # [-33.867070000000005, 151.20674000000002],
25
+ # [-33.86703, 151.20625]
26
+ # ]
27
+ # results = client.snap_to_roads(path, interpolate: true)
28
+ #
29
+ # @param [Array] path The path to be snapped. Array of latitude/longitude pairs.
30
+ # @param [Boolean] interpolate Whether to interpolate a path to include all points
31
+ # forming the full road-geometry. When true, additional interpolated
32
+ # points will also be returned, resulting in a path that smoothly
33
+ # follows the geometry of the road, even around corners and through
34
+ # tunnels. Interpolated paths may contain more points than the
35
+ # original path.
36
+ #
37
+ # @return [Array] Array of snapped points.
38
+ def snap_to_roads(path, interpolate: false)
39
+ path = GoogleMapsApis::Convert.waypoints(path)
40
+
41
+ params = {
42
+ path: path
43
+ }
44
+
45
+ params[:interpolate] = 'true' if interpolate
46
+
47
+ return get('/v1/snapToRoads', params,
48
+ base_url: ROADS_BASE_URL,
49
+ accepts_client_id: false,
50
+ custom_response_decoder: method(:extract_roads_body))[:snappedPoints]
51
+ end
52
+
53
+ # Returns the posted speed limit (in km/h) for given road segments.
54
+ #
55
+ # @example Multi places snap
56
+ # place_ids = [
57
+ # 'ChIJ0wawjUCuEmsRgfqC5Wd9ARM',
58
+ # 'ChIJ6cs2kkCuEmsRUfqC5Wd9ARM'
59
+ # ]
60
+ # results = client.speed_limits(place_ids)
61
+ #
62
+ # @param [String, Array<String>] place_ids The Place ID of the road segment. Place IDs are returned
63
+ # by the snap_to_roads function. You can pass up to 100 Place IDs.
64
+ #
65
+ # @return [Array] Array of speed limits.
66
+ def speed_limits(place_ids)
67
+ params = GoogleMapsApis::Convert.as_list(place_ids).map { |place_id| ['placeId', place_id] }
68
+
69
+ return get('/v1/speedLimits', params,
70
+ base_url: ROADS_BASE_URL,
71
+ accepts_client_id: false,
72
+ custom_response_decoder: method(:extract_roads_body))[:speedLimits]
73
+ end
74
+
75
+ # Returns the posted speed limit (in km/h) for given road segments.
76
+ #
77
+ # The provided points will first be snapped to the most likely roads the
78
+ # vehicle was traveling along.
79
+ #
80
+ # @example Multi points snap
81
+ # path = [
82
+ # [-33.8671, 151.20714],
83
+ # [-33.86708, 151.20683000000002],
84
+ # [-33.867070000000005, 151.20674000000002],
85
+ # [-33.86703, 151.20625]
86
+ # ]
87
+ # results = client.snapped_speed_limits(path)
88
+ #
89
+ # @param [Hash, Array] path The path of points to be snapped. A list of (or single)
90
+ # latitude/longitude tuples.
91
+ #
92
+ # @return [Hash] A hash with both a list of speed limits and a list of the snapped
93
+ # points.
94
+ def snapped_speed_limits(path)
95
+ path = GoogleMapsApis::Convert.waypoints(path)
96
+
97
+ params = {
98
+ path: path
99
+ }
100
+
101
+ return get('/v1/speedLimits', params,
102
+ base_url: ROADS_BASE_URL,
103
+ accepts_client_id: false,
104
+ custom_response_decoder: method(:extract_roads_body))
105
+ end
106
+
107
+ # Returns the nearest road segments for provided points.
108
+ # The points passed do not need to be part of a continuous path.
109
+ #
110
+ # @example Single point snap
111
+ # results = client.nearest_roads([40.714728, -73.998672])
112
+ #
113
+ # @example Multi points snap
114
+ # points = [
115
+ # [-33.8671, 151.20714],
116
+ # [-33.86708, 151.20683000000002],
117
+ # [-33.867070000000005, 151.20674000000002],
118
+ # [-33.86703, 151.20625]
119
+ # ]
120
+ # results = client.nearest_roads(points)
121
+ #
122
+ # @param [Array] points The points to be used for nearest road segment lookup. Array of latitude/longitude pairs
123
+ # which do not need to be a part of continuous part.
124
+ # Takes up to 100 independent coordinates, and returns the closest road segment for each point.
125
+ #
126
+ # @return [Array] Array of snapped points.
127
+
128
+ def nearest_roads(points)
129
+ points = GoogleMapsApis::Convert.waypoints(points)
130
+
131
+ params = {
132
+ points: points
133
+ }
134
+
135
+ return get('/v1/nearestRoads', params,
136
+ base_url: ROADS_BASE_URL,
137
+ accepts_client_id: false,
138
+ custom_response_decoder: method(:extract_roads_body))[:snappedPoints]
139
+ end
140
+
141
+
142
+
143
+ private
144
+ # Extracts a result from a Roads API HTTP response.
145
+ def extract_roads_body(response)
146
+ begin
147
+ body = MultiJson.load(response.body, :symbolize_keys => true)
148
+ rescue
149
+ unless response.status == 200
150
+ check_response_status(response)
151
+ end
152
+ raise GoogleMapsApis::Error::ApiError.new(response), 'Received a malformed response.'
153
+ end
154
+
155
+ check_roads_body_error(response, body)
156
+
157
+ unless response.status == 200
158
+ raise GoogleMapsApis::Error::ApiError.new(response)
159
+ end
160
+ return body
161
+ end
162
+
163
+ # Check response body for error status.
164
+ #
165
+ # @param [Faraday::Response] response Response object.
166
+ # @param [Hash] body Response body.
167
+ def check_roads_body_error(response, body)
168
+ error = body[:error]
169
+ return unless error
170
+
171
+ case error[:status]
172
+ when 'INVALID_ARGUMENT'
173
+ if error[:message] == 'The provided API key is invalid.'
174
+ raise GoogleMapsApis::Error::RequestDeniedError.new(response), error[:message]
175
+ end
176
+ raise GoogleMapsApis::Error::InvalidRequestError.new(response), error[:message]
177
+ when 'PERMISSION_DENIED'
178
+ raise GoogleMapsApis::Error::RequestDeniedError.new(response), error[:message]
179
+ when 'RESOURCE_EXHAUSTED'
180
+ raise GoogleMapsApis::Error::RateLimitError.new(response), error[:message]
181
+ else
182
+ raise GoogleMapsApis::Error::ApiError.new(response), error[:message]
183
+ end
184
+ end
185
+
186
+ end
187
+ end
@@ -0,0 +1,41 @@
1
+ require 'date'
2
+
3
+ module GoogleMapsApis::Services
4
+
5
+ # Performs requests to the Google Maps TimeZone API."""
6
+ module TimeZone
7
+
8
+ # Get time zone for a location on the earth, as well as that location's
9
+ # time offset from UTC.
10
+ #
11
+ # @example Current time zone
12
+ # timezone = client.timezone([39.603481, -119.682251])
13
+ #
14
+ # @example Time zone at certain time
15
+ # timezone = client.timezone([39.603481, -119.682251], timestamp: Time.at(1608))
16
+ #
17
+ # @param [Hash, Array] location The latitude/longitude value representing the location to
18
+ # look up.
19
+ # @param [Integer, DateTime] timestamp Timestamp specifies the desired time as seconds since
20
+ # midnight, January 1, 1970 UTC. The Time Zone API uses the timestamp to
21
+ # determine whether or not Daylight Savings should be applied. Times
22
+ # before 1970 can be expressed as negative values. Optional. Defaults to
23
+ # `Time.now`.
24
+ # @param [String] language The language in which to return results.
25
+ #
26
+ # @return [Hash] Time zone object.
27
+ def timezone(location, timestamp: Time.now, language: nil)
28
+ location = GoogleMapsApis::Convert.latlng(location)
29
+ timestamp = GoogleMapsApis::Convert.time(timestamp)
30
+
31
+ params = {
32
+ location: location,
33
+ timestamp: timestamp
34
+ }
35
+
36
+ params[:language] = language if language
37
+
38
+ return get('/maps/api/timezone/json', params)
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,6 @@
1
+ module GoogleMapsApis
2
+
3
+ # Collections of Google Maps Web Services
4
+ module Services
5
+ end
6
+ end
@@ -0,0 +1,64 @@
1
+ require 'base64'
2
+ require 'uri'
3
+
4
+ module GoogleMapsApis
5
+
6
+ # Helper for handling URL.
7
+ module Url
8
+ module_function
9
+
10
+ # Returns a base64-encoded HMAC-SHA1 signature of a given string.
11
+ #
12
+ # @param [String] secret The key used for the signature, base64 encoded.
13
+ # @param [String] payload The payload to sign.
14
+ #
15
+ # @return [String] Base64-encoded HMAC-SHA1 signature
16
+ def sign_hmac(secret, payload)
17
+ secret = secret.encode('ASCII')
18
+ payload = payload.encode('ASCII')
19
+
20
+ # Decode the private key
21
+ raw_key = Base64.urlsafe_decode64(secret)
22
+
23
+ # Create a signature using the private key and the URL
24
+ digest = OpenSSL::Digest.new('sha1')
25
+ raw_signature = OpenSSL::HMAC.digest(digest, raw_key, payload)
26
+
27
+ # Encode the signature into base64 for url use form.
28
+ signature = Base64.urlsafe_encode64(raw_signature)
29
+ return signature
30
+ end
31
+
32
+ # URL encodes the parameters.
33
+ # @param [Hash, Array<Array>] params The parameters
34
+ # @return [String]
35
+ def urlencode_params(params)
36
+ unquote_unreserved(URI.encode_www_form(params))
37
+ end
38
+
39
+ # Un-escape any percent-escape sequences in a URI that are unreserved
40
+ # characters. This leaves all reserved, illegal and non-ASCII bytes encoded.
41
+ #
42
+ # @param [String] uri
43
+ #
44
+ # @return [String]
45
+ def unquote_unreserved(uri)
46
+ parts = uri.split('%')
47
+
48
+ (1..parts.length-1).each do |i|
49
+ h = parts[i][0..1]
50
+
51
+ if h =~ /^([\h]{2})(.*)/ and c = $1.to_i(16).chr and UNRESERVED_SET.include?(c)
52
+ parts[i] = c + $2
53
+ else
54
+ parts[i] = '%' + parts[i]
55
+ end
56
+ end
57
+
58
+ parts.join
59
+ end
60
+
61
+ # The unreserved URI characters (RFC 3986)
62
+ UNRESERVED_SET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~"
63
+ end
64
+ end