diff --git a/routingpy/direction.py b/routingpy/direction.py index 76fa1ef..2cb6aa1 100644 --- a/routingpy/direction.py +++ b/routingpy/direction.py @@ -87,10 +87,10 @@ def __init__( :param distance: The distance of the direction in meters. :type distance: int - :param departure_datetime: The departure timezone aware date and time of the direction. + :param departure_datetime: The departure date and time of the direction. :type departure_datetime: datetime.datetime - :param arrival_datetime: The arrival timezone aware date and time of the direction. + :param arrival_datetime: The arrival date and time of the direction. :type arrival_datetime: datetime.datetime :param raw: The raw response of an individual direction (for multiple alternative routes) or the whole direction @@ -134,7 +134,7 @@ def distance(self) -> int: @property def departure_datetime(self) -> Optional[datetime.datetime]: """ - The departure timezone aware date and time of the direction. + The departure date and time of the direction. :rtype: datetime.datetime or None """ @@ -143,7 +143,7 @@ def departure_datetime(self) -> Optional[datetime.datetime]: @property def arrival_datetime(self) -> Optional[datetime.datetime]: """ - The arrival timezone aware date and time of the direction. + The arrival date and time of the direction. :rtype: datetime.datetime or None """ diff --git a/routingpy/routers/google.py b/routingpy/routers/google.py index 2a657f2..7b38c83 100644 --- a/routingpy/routers/google.py +++ b/routingpy/routers/google.py @@ -326,11 +326,12 @@ def directions( # noqa: C901 self.client._request("/directions/json", get_params=params, dry_run=dry_run), alternatives ) - def _time_object_to_aware_datetime(self, time_object): + def _time_object_to_naive_datetime(self, time_object): timestamp = time_object["value"] dt = datetime.datetime.fromtimestamp(timestamp) timezone = pytz.timezone(time_object["time_zone"]) - return dt.astimezone(timezone) + aware_dt = dt.astimezone(timezone) + return aware_dt.replace(tzinfo=None) def _parse_legs(self, legs): duration = 0 @@ -343,12 +344,12 @@ def _parse_legs(self, legs): departure_time = leg.get("departure_time") if departure_time: assert len(legs) == 1, "departure_time is only supported for single leg routes" - departure_datetime = self._time_object_to_aware_datetime(departure_time) + departure_datetime = self._time_object_to_naive_datetime(departure_time) arrival_time = leg.get("arrival_time") if arrival_time: assert len(legs) == 1, "arrival_time is only supported for single leg routes" - arrival_datetime = self._time_object_to_aware_datetime(arrival_time) + arrival_datetime = self._time_object_to_naive_datetime(arrival_time) duration += leg["duration"]["value"] distance += leg["distance"]["value"] diff --git a/routingpy/routers/opentripplanner_v2.py b/routingpy/routers/opentripplanner_v2.py index f9a8eba..b50d7a9 100644 --- a/routingpy/routers/opentripplanner_v2.py +++ b/routingpy/routers/opentripplanner_v2.py @@ -17,6 +17,8 @@ import datetime from typing import List, Optional +import pytz + from .. import convert, utils from ..client_base import DEFAULT from ..client_default import Client @@ -97,6 +99,7 @@ def directions( profile: Optional[str] = "WALK,TRANSIT", date: Optional[datetime.date] = datetime.datetime.now().date(), time: Optional[datetime.time] = datetime.datetime.now().time(), + timezone: Optional[str] = "UTC", arrive_by: Optional[bool] = False, num_itineraries: Optional[int] = 3, dry_run: Optional[bool] = None, @@ -118,6 +121,10 @@ def directions( :param time: Time of departure or arrival. Default value: current time. :type time: datetime.time + :param timezone: Timezone used to transform output departure and arrival timestamps to naive + datetimes. Default value: UTC. + :type time: str + :arrive_by: Whether the itinerary should depart at the specified time (False), or arrive to the destination at the specified time (True). Default value: False. :type arrive_by: bool @@ -165,21 +172,22 @@ def directions( response = self.client._request( "/otp/routers/default/index/graphql", post_params=params, dry_run=dry_run ) - return self._parse_directions_response(response, num_itineraries) + return self._parse_directions_response(response, num_itineraries, timezone) - def _timestamp_to_utc_datetime(self, timestamp): + def _timestamp_to_naive_datetime(self, timestamp, timezone): dt = datetime.datetime.fromtimestamp(timestamp / 1000) - return dt.astimezone(datetime.timezone.utc) + aware_dt = dt.astimezone(pytz.timezone(timezone)) + return aware_dt.replace(tzinfo=None) - def _parse_directions_response(self, response, num_itineraries): + def _parse_directions_response(self, response, num_itineraries, timezone): if response is None: # pragma: no cover return Directions() if num_itineraries > 1 else Direction() directions = [] for itinerary in response["data"]["plan"]["itineraries"]: distance, geometry = self._parse_legs(itinerary["legs"]) - departure_datetime = self._timestamp_to_utc_datetime(itinerary["startTime"]) - arrival_datetime = self._timestamp_to_utc_datetime(itinerary["endTime"]) + departure_datetime = self._timestamp_to_naive_datetime(itinerary["startTime"], timezone) + arrival_datetime = self._timestamp_to_naive_datetime(itinerary["endTime"], timezone) directions.append( Direction( geometry=geometry, @@ -202,7 +210,7 @@ def _parse_legs(self, legs): geometry = [] for leg in legs: points = utils.decode_polyline5(leg["legGeometry"]["points"]) - geometry.extend(list(reversed(points))) + geometry.extend(points) distance += int(leg["distance"]) return distance, geometry diff --git a/tests/test_google.py b/tests/test_google.py index 3a1af98..6b526c6 100644 --- a/tests/test_google.py +++ b/tests/test_google.py @@ -91,9 +91,9 @@ def test_directions_transit(self): self.assertIsInstance(direction.distance, int) self.assertIsInstance(direction.duration, int) self.assertIsInstance(direction.departure_datetime, datetime.datetime) - self.assertEqual(direction.departure_datetime.tzinfo.zone, "Europe/Berlin") + self.assertEqual(direction.departure_datetime.tzinfo, None) self.assertIsInstance(direction.arrival_datetime, datetime.datetime) - self.assertEqual(direction.arrival_datetime.tzinfo.zone, "Europe/Berlin") + self.assertEqual(direction.arrival_datetime.tzinfo, None) self.assertIsInstance(direction.raw, dict) @responses.activate diff --git a/tests/test_opentripplanner_v2.py b/tests/test_opentripplanner_v2.py index faa1b55..8a354cd 100644 --- a/tests/test_opentripplanner_v2.py +++ b/tests/test_opentripplanner_v2.py @@ -56,9 +56,9 @@ def test_directions(self): self.assertIsInstance(direction.duration, int) self.assertIsInstance(direction.geometry, list) self.assertIsInstance(direction.departure_datetime, datetime.datetime) - self.assertEqual(direction.departure_datetime.tzinfo, datetime.timezone.utc) + self.assertEqual(direction.departure_datetime.tzinfo, None) self.assertIsInstance(direction.arrival_datetime, datetime.datetime) - self.assertEqual(direction.arrival_datetime.tzinfo, datetime.timezone.utc) + self.assertEqual(direction.arrival_datetime.tzinfo, None) @responses.activate def test_directions_alternative(self): @@ -85,9 +85,9 @@ def test_directions_alternative(self): self.assertIsInstance(direction.geometry, list) self.assertIsInstance(direction.raw, dict) self.assertIsInstance(direction.departure_datetime, datetime.datetime) - self.assertEqual(direction.departure_datetime.tzinfo, datetime.timezone.utc) + self.assertEqual(direction.departure_datetime.tzinfo, None) self.assertIsInstance(direction.arrival_datetime, datetime.datetime) - self.assertEqual(direction.arrival_datetime.tzinfo, datetime.timezone.utc) + self.assertEqual(direction.arrival_datetime.tzinfo, None) @responses.activate def test_isochrones(self):