Skip to content
This repository was archived by the owner on Sep 12, 2024. It is now read-only.

Commit 703c71f

Browse files
author
Norberto Lopes
authored
Merge pull request #275 from duffelhq/nlopes-fix-271
Use utility function to auto-detect correct datetime format > LGTM > > > Alternatively we could bring in the dateutil library. > > I agree. If we're starting to do length checks, etc, I'd say it's time. I'll take care of this in another PR.
2 parents 74e69a5 + c893df2 commit 703c71f

File tree

7 files changed

+32
-29
lines changed

7 files changed

+32
-29
lines changed

duffel_api/models/airport.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from datetime import datetime
33
from typing import Optional, Sequence
44

5-
from duffel_api.utils import get_and_transform
5+
from duffel_api.utils import get_and_transform, parse_datetime
66

77

88
@dataclass
@@ -144,6 +144,6 @@ def from_json(cls, json: dict):
144144
status=json["status"],
145145
destination=json["destination"],
146146
arrival=json["arrival"],
147-
created_at=datetime.strptime(json["created_at"], "%Y-%m-%dT%H:%M:%S.%fZ"),
148-
updated_at=datetime.strptime(json["created_at"], "%Y-%m-%dT%H:%M:%S.%fZ"),
147+
created_at=parse_datetime(json["created_at"]),
148+
updated_at=parse_datetime(json["updated_at"]),
149149
)

duffel_api/models/offer.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,7 @@ def from_json(cls, json: dict):
9999
json, "payment_required_by", parse_datetime
100100
),
101101
price_guarantee_expires_at=get_and_transform(
102-
json,
103-
"price_guarantee_expires_at",
104-
lambda value: datetime.strptime(value, "%Y-%m-%dT%H:%M:%SZ"),
102+
json, "price_guarantee_expires_at", parse_datetime
105103
),
106104
requires_instant_payment=json["requires_instant_payment"],
107105
)
@@ -251,8 +249,8 @@ def from_json(cls, json: dict):
251249
return cls(
252250
id=json["id"],
253251
aircraft=get_and_transform(json, "aircraft", Aircraft.from_json),
254-
arriving_at=datetime.strptime(json["arriving_at"], "%Y-%m-%dT%H:%M:%S"),
255-
departing_at=datetime.strptime(json["departing_at"], "%Y-%m-%dT%H:%M:%S"),
252+
arriving_at=parse_datetime(json["arriving_at"]),
253+
departing_at=parse_datetime(json["departing_at"]),
256254
destination=Airport.from_json(json["destination"]),
257255
destination_terminal=json.get("destination_terminal"),
258256
origin=Airport.from_json(json["origin"]),
@@ -466,8 +464,8 @@ def from_json(cls, json: dict):
466464
base_amount=json["base_amount"],
467465
base_currency=json["base_currency"],
468466
conditions=OfferConditions.from_json(json["conditions"]),
469-
created_at=datetime.strptime(json["created_at"], "%Y-%m-%dT%H:%M:%S.%fZ"),
470-
updated_at=datetime.strptime(json["updated_at"], "%Y-%m-%dT%H:%M:%S.%fZ"),
467+
created_at=parse_datetime(json["created_at"]),
468+
updated_at=parse_datetime(json["updated_at"]),
471469
expires_at=parse_datetime(json["expires_at"]),
472470
owner=Airline.from_json(json["owner"]),
473471
partial=json["partial"],

duffel_api/models/offer_request.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from typing import Optional, Sequence, Union
44

55
from duffel_api.models import Airport, City, LoyaltyProgrammeAccount, Offer
6-
from duffel_api.utils import get_and_transform
6+
from duffel_api.utils import get_and_transform, parse_datetime
77

88

99
@dataclass
@@ -120,5 +120,5 @@ def from_json(cls, json: dict):
120120
],
121121
[],
122122
),
123-
created_at=datetime.strptime(json["created_at"], "%Y-%m-%dT%H:%M:%S.%fZ"),
123+
created_at=parse_datetime(json["created_at"]),
124124
)

duffel_api/models/order.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from typing import Optional, Sequence, Union
44

55
from duffel_api.models import Aircraft, Airline, Airport, LoyaltyProgrammeAccount, Place
6-
from duffel_api.utils import get_and_transform
6+
from duffel_api.utils import get_and_transform, parse_datetime
77

88

99
@dataclass
@@ -200,8 +200,8 @@ def from_json(cls, json: dict):
200200
return cls(
201201
id=json["id"],
202202
aircraft=get_and_transform(json, "aircraft", Aircraft.from_json),
203-
arriving_at=datetime.strptime(json["arriving_at"], "%Y-%m-%dT%H:%M:%S"),
204-
departing_at=datetime.strptime(json["departing_at"], "%Y-%m-%dT%H:%M:%S"),
203+
arriving_at=parse_datetime(json["arriving_at"]),
204+
departing_at=parse_datetime(json["departing_at"]),
205205
destination=Airport.from_json(json["destination"]),
206206
destination_terminal=json.get("destination_terminal"),
207207
origin=Airport.from_json(json["origin"]),
@@ -420,12 +420,12 @@ def from_json(cls, json: dict):
420420
payment_required_by=get_and_transform(
421421
json,
422422
"payment_required_by",
423-
lambda value: datetime.strptime(value, "%Y-%m-%dT%H:%M:%SZ"),
423+
parse_datetime,
424424
),
425425
price_guarantee_expires_at=get_and_transform(
426426
json,
427427
"price_guarantee_expires_at",
428-
lambda value: datetime.strptime(value, "%Y-%m-%dT%H:%M:%SZ"),
428+
parse_datetime,
429429
),
430430
)
431431

@@ -529,14 +529,14 @@ def from_json(cls, json: dict):
529529
cancelled_at=get_and_transform(
530530
json,
531531
"cancelled_at",
532-
lambda value: datetime.strptime(value, "%Y-%m-%dT%H:%M:%S.%fZ"),
532+
parse_datetime,
533533
),
534534
content=json["content"],
535-
created_at=datetime.strptime(json["created_at"], "%Y-%m-%dT%H:%M:%S.%fZ"),
535+
created_at=parse_datetime(json["created_at"]),
536536
synced_at=get_and_transform(
537537
json,
538538
"synced_at",
539-
lambda value: datetime.strptime(value, "%Y-%m-%dT%H:%M:%SZ"),
539+
parse_datetime,
540540
),
541541
documents=get_and_transform(
542542
json,

duffel_api/models/payment.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
from datetime import datetime
33
from typing import Optional
44

5+
from duffel_api.utils import parse_datetime
6+
57

68
@dataclass
79
class Payment:
@@ -40,5 +42,5 @@ def from_json(cls, json: dict):
4042
live_mode=json["live_mode"],
4143
amount=json["amount"],
4244
currency=json.get("currency"),
43-
created_at=datetime.strptime(json["created_at"], "%Y-%m-%dT%H:%M:%S.%fZ"),
45+
created_at=parse_datetime(json["created_at"]),
4446
)

duffel_api/utils.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,14 @@ def parse_datetime(value: str) -> datetime:
3232
"""Parse a datetime string regardless of having milliseconds or not"""
3333
# There are inconsistent formats used for the field, therefore we try to accomodate
3434
# instead of making an API breaking change.
35-
if len(value) == 20:
36-
return datetime.strptime(value, "%Y-%m-%dT%H:%M:%SZ")
35+
#
36+
# I'm really not happy with this but it helps so I'm leaving it for now.
37+
if value.endswith("Z"):
38+
if len(value) == 20:
39+
return datetime.strptime(value, "%Y-%m-%dT%H:%M:%SZ")
40+
else:
41+
return datetime.strptime(value, "%Y-%m-%dT%H:%M:%S.%fZ")
42+
if len(value) == 19:
43+
return datetime.strptime(value, "%Y-%m-%dT%H:%M:%S")
3744
else:
38-
return datetime.strptime(value, "%Y-%m-%dT%H:%M:%S.%fZ")
45+
return datetime.strptime(value, "%Y-%m-%dT%H:%M:%S.%f")

tests/test_utils.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,9 @@ def test_parse_datetime():
1010
assert parse_datetime("2022-11-02T12:24:52.012Z") == datetime(
1111
2022, 11, 2, 12, 24, 52, 12000
1212
)
13+
assert parse_datetime("2022-11-02T12:24:52") == datetime(2022, 11, 2, 12, 24, 52)
1314
with pytest.raises(
1415
ValueError,
1516
match="time data '2022-11-02T-2:24:52Z' does not match format '%Y-%m-%dT%H:%M:%SZ'", # noqa: E501
1617
):
1718
parse_datetime("2022-11-02T-2:24:52Z")
18-
with pytest.raises(
19-
ValueError,
20-
match="time data '2022-11-02T12:24:52' does not match format '%Y-%m-%dT%H:%M:%S.%fZ'", # noqa: E501
21-
):
22-
parse_datetime("2022-11-02T12:24:52")

0 commit comments

Comments
 (0)