google_maps_apis 1.0.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.
@@ -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