1515# the License.
1616#
1717
18+ import datetime
1819from operator import itemgetter
1920from typing import List , Optional , Tuple , Union
2021
22+ import pytz
23+
2124from .. import convert , utils
2225from ..client_base import DEFAULT
2326from ..client_default import Client
@@ -319,12 +322,42 @@ def directions( # noqa: C901
319322 if transit_routing_preference :
320323 params ["transit_routing_preference" ] = transit_routing_preference
321324
322- return self .parse_direction_json (
325+ return self ._parse_direction_json (
323326 self .client ._request ("/directions/json" , get_params = params , dry_run = dry_run ), alternatives
324327 )
325328
326- @staticmethod
327- def parse_direction_json (response , alternatives ):
329+ def _time_object_to_aware_datetime (self , time_object ):
330+ timestamp = time_object ["value" ]
331+ dt = datetime .datetime .fromtimestamp (timestamp )
332+ timezone = pytz .timezone (time_object ["time_zone" ])
333+ return dt .astimezone (timezone )
334+
335+ def _parse_legs (self , legs ):
336+ duration = 0
337+ distance = 0
338+ geometry = []
339+ departure_datetime = None
340+ arrival_datetime = None
341+
342+ for leg in legs :
343+ departure_time = leg .get ("departure_time" )
344+ if departure_time :
345+ assert len (legs ) == 1 , "departure_time is only supported for single leg routes"
346+ departure_datetime = self ._time_object_to_aware_datetime (departure_time )
347+
348+ arrival_time = leg .get ("arrival_time" )
349+ if arrival_time :
350+ assert len (legs ) == 1 , "arrival_time is only supported for single leg routes"
351+ arrival_datetime = self ._time_object_to_aware_datetime (arrival_time )
352+
353+ duration += leg ["duration" ]["value" ]
354+ distance += leg ["distance" ]["value" ]
355+ for step in leg ["steps" ]:
356+ geometry .extend (utils .decode_polyline5 (step ["polyline" ]["points" ]))
357+
358+ return duration , distance , geometry , departure_datetime , arrival_datetime
359+
360+ def _parse_direction_json (self , response , alternatives ):
328361 if response is None : # pragma: no cover
329362 if alternatives :
330363 return Directions ()
@@ -345,33 +378,27 @@ def parse_direction_json(response, alternatives):
345378
346379 raise error (STATUS_CODES [status ]["code" ], STATUS_CODES [status ]["message" ])
347380
348- if alternatives :
349- routes = []
350- for route in response ["routes" ]:
351- geometry = []
352- duration , distance = 0 , 0
353- for leg in route ["legs" ]:
354- duration += leg ["duration" ]["value" ]
355- distance += leg ["distance" ]["value" ]
356- for step in leg ["steps" ]:
357- geometry .extend (utils .decode_polyline5 (step ["polyline" ]["points" ]))
358-
359- routes .append (
360- Direction (
361- geometry = geometry , duration = int (duration ), distance = int (distance ), raw = route
362- )
381+ directions = []
382+ for route in response ["routes" ]:
383+ duration , distance , geometry , departure_datetime , arrival_datetime = self ._parse_legs (
384+ route ["legs" ]
385+ )
386+ directions .append (
387+ Direction (
388+ geometry = geometry ,
389+ duration = int (duration ),
390+ distance = int (distance ),
391+ departure_datetime = departure_datetime ,
392+ arrival_datetime = arrival_datetime ,
393+ raw = route ,
363394 )
364- return Directions (routes , response )
365- else :
366- geometry = []
367- duration , distance = 0 , 0
368- for leg in response ["routes" ][0 ]["legs" ]:
369- duration += leg ["duration" ]["value" ]
370- distance += leg ["distance" ]["value" ]
371- for step in leg ["steps" ]:
372- geometry .extend (utils .decode_polyline5 (step ["polyline" ]["points" ]))
373-
374- return Direction (geometry = geometry , duration = duration , distance = distance , raw = response )
395+ )
396+
397+ if alternatives :
398+ return Directions (directions , raw = response )
399+
400+ elif directions :
401+ return directions [0 ]
375402
376403 def isochrones (self ): # pragma: no cover
377404 raise NotImplementedError
@@ -506,12 +533,11 @@ def matrix( # noqa: C901
506533 if transit_routing_preference :
507534 params ["transit_routing_preference" ] = transit_routing_preference
508535
509- return self .parse_matrix_json (
536+ return self ._parse_matrix_json (
510537 self .client ._request ("/distancematrix/json" , get_params = params , dry_run = dry_run )
511538 )
512539
513- @staticmethod
514- def parse_matrix_json (response ):
540+ def _parse_matrix_json (self , response ):
515541 if response is None : # pragma: no cover
516542 return Matrix ()
517543
0 commit comments