Skip to content

Commit 6a5c3f4

Browse files
authored
fix: handle Z timezone in ISO8601 datetime format (#228)
* fix: handle Z timezone in ISO8601 datetime format Fixes #226
1 parent c821dbe commit 6a5c3f4

File tree

19 files changed

+87
-63
lines changed

19 files changed

+87
-63
lines changed

hcloud/_compat.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from datetime import datetime
2+
3+
4+
def isoparse(value: str) -> datetime:
5+
# Python <3.11 doesn't fully support parsing ISO8601 datetime strings. This
6+
# workaround replaces the ending `Z` or `z` with `+00:00` and allows
7+
# `datetime.fromisoformat` to parse the datetime string.
8+
if value[-1] in "Zz":
9+
value = value[:-1] + "+00:00"
10+
11+
return datetime.fromisoformat(value)

hcloud/actions/domain.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
from datetime import datetime
2-
1+
from .._compat import isoparse
32
from .._exceptions import HCloudException
43
from ..core.domain import BaseDomain
54

@@ -51,8 +50,8 @@ def __init__(
5150

5251
self.status = status
5352
self.progress = progress
54-
self.started = datetime.fromisoformat(started) if started else None
55-
self.finished = datetime.fromisoformat(finished) if finished else None
53+
self.started = isoparse(started) if started else None
54+
self.finished = isoparse(finished) if finished else None
5655
self.resources = resources
5756
self.error = error
5857

hcloud/certificates/domain.py

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
from datetime import datetime
2-
1+
from .._compat import isoparse
32
from ..core.domain import BaseDomain, DomainIdentityMixin
43

54

@@ -59,13 +58,9 @@ def __init__(
5958
self.certificate = certificate
6059
self.domain_names = domain_names
6160
self.fingerprint = fingerprint
62-
self.not_valid_before = (
63-
datetime.fromisoformat(not_valid_before) if not_valid_before else None
64-
)
65-
self.not_valid_after = (
66-
datetime.fromisoformat(not_valid_after) if not_valid_after else None
67-
)
68-
self.created = datetime.fromisoformat(created) if created else None
61+
self.not_valid_before = isoparse(not_valid_before) if not_valid_before else None
62+
self.not_valid_after = isoparse(not_valid_after) if not_valid_after else None
63+
self.created = isoparse(created) if created else None
6964
self.labels = labels
7065
self.status = status
7166

hcloud/deprecation/domain.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
from datetime import datetime
2-
1+
from .._compat import isoparse
32
from ..core.domain import BaseDomain
43

54

@@ -25,7 +24,7 @@ def __init__(
2524
announced=None,
2625
unavailable_after=None,
2726
):
28-
self.announced = datetime.fromisoformat(announced) if announced else None
27+
self.announced = isoparse(announced) if announced else None
2928
self.unavailable_after = (
30-
datetime.fromisoformat(unavailable_after) if unavailable_after else None
29+
isoparse(unavailable_after) if unavailable_after else None
3130
)

hcloud/firewalls/domain.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
from datetime import datetime
2-
1+
from .._compat import isoparse
32
from ..core.domain import BaseDomain
43

54

@@ -30,7 +29,7 @@ def __init__(
3029
self.rules = rules
3130
self.applied_to = applied_to
3231
self.labels = labels
33-
self.created = datetime.fromisoformat(created) if created else None
32+
self.created = isoparse(created) if created else None
3433

3534

3635
class FirewallRule:

hcloud/floating_ips/domain.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
from datetime import datetime
2-
1+
from .._compat import isoparse
32
from ..core.domain import BaseDomain
43

54

@@ -72,7 +71,7 @@ def __init__(
7271
self.blocked = blocked
7372
self.protection = protection
7473
self.labels = labels
75-
self.created = datetime.fromisoformat(created) if created else None
74+
self.created = isoparse(created) if created else None
7675
self.name = name
7776

7877

hcloud/images/domain.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
from datetime import datetime
2-
1+
from .._compat import isoparse
32
from ..core.domain import BaseDomain, DomainIdentityMixin
43

54

@@ -85,11 +84,11 @@ def __init__(
8584
self.id = id
8685
self.name = name
8786
self.type = type
88-
self.created = datetime.fromisoformat(created) if created else None
87+
self.created = isoparse(created) if created else None
8988
self.description = description
9089
self.image_size = image_size
9190
self.disk_size = disk_size
92-
self.deprecated = datetime.fromisoformat(deprecated) if deprecated else None
91+
self.deprecated = isoparse(deprecated) if deprecated else None
9392
self.bound_to = bound_to
9493
self.os_flavor = os_flavor
9594
self.os_version = os_version

hcloud/isos/domain.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
from datetime import datetime
2-
1+
from .._compat import isoparse
32
from ..core.domain import BaseDomain, DomainIdentityMixin
43

54

@@ -36,4 +35,4 @@ def __init__(
3635
self.type = type
3736
self.architecture = architecture
3837
self.description = description
39-
self.deprecated = datetime.fromisoformat(deprecated) if deprecated else None
38+
self.deprecated = isoparse(deprecated) if deprecated else None

hcloud/load_balancers/domain.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
from datetime import datetime
2-
1+
from .._compat import isoparse
32
from ..core.domain import BaseDomain
43

54

@@ -76,7 +75,7 @@ def __init__(
7675
):
7776
self.id = id
7877
self.name = name
79-
self.created = datetime.fromisoformat(created) if created else None
78+
self.created = isoparse(created) if created else None
8079
self.public_net = public_net
8180
self.private_net = private_net
8281
self.location = location

hcloud/networks/domain.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
from datetime import datetime
2-
1+
from .._compat import isoparse
32
from ..core.domain import BaseDomain
43

54

@@ -54,7 +53,7 @@ def __init__(
5453
):
5554
self.id = id
5655
self.name = name
57-
self.created = datetime.fromisoformat(created) if created else None
56+
self.created = isoparse(created) if created else None
5857
self.ip_range = ip_range
5958
self.subnets = subnets
6059
self.routes = routes

0 commit comments

Comments
 (0)