21
21
# really be a big deal.
22
22
reDuration = re .compile (r'^([0-9]{1,5}(h|m|s|ms)){1,4}$' )
23
23
24
+ # maxDuration_ms is the maximum duration that GEP-2257 can support, in
25
+ # milliseconds.
26
+ maxDuration_ms = (((99999 * 3600 ) + (59 * 60 ) + 59 ) * 1_000 ) + 999
27
+
28
+
24
29
def parse_duration (duration ) -> datetime .timedelta :
25
30
"""
26
31
Parse GEP-2257 Duration format to a datetime.timedelta object.
@@ -32,17 +37,47 @@ def parse_duration(duration) -> datetime.timedelta:
32
37
See https://gateway-api.sigs.k8s.io/geps/gep-2257/ for more details.
33
38
34
39
Input: duration: string
35
-
36
40
Returns: datetime.timedelta
37
41
38
42
Raises: ValueError on invalid or unknown input
43
+
44
+ Examples:
45
+ >>> parse_duration("1h")
46
+ datetime.timedelta(seconds=3600)
47
+ >>> parse_duration("1m")
48
+ datetime.timedelta(seconds=60)
49
+ >>> parse_duration("1s")
50
+ datetime.timedelta(seconds=1)
51
+ >>> parse_duration("1ms")
52
+ datetime.timedelta(microseconds=1000)
53
+ >>> parse_duration("1h1m1s")
54
+ datetime.timedelta(seconds=3661)
55
+ >>> parse_duration("10s30m1h")
56
+ datetime.timedelta(seconds=5410)
57
+
58
+ Units are always required.
59
+ >>> parse_duration("1")
60
+ Traceback (most recent call last):
61
+ ...
62
+ ValueError: Invalid duration format: 1
63
+
64
+ Floating-point and negative durations are not valid.
65
+ >>> parse_duration("1.5m")
66
+ Traceback (most recent call last):
67
+ ...
68
+ ValueError: Invalid duration format: 1.5m
69
+ >>> parse_duration("-1m")
70
+ Traceback (most recent call last):
71
+ ...
72
+ ValueError: Invalid duration format: -1m
39
73
"""
40
74
41
75
if not reDuration .match (duration ):
42
76
raise ValueError ("Invalid duration format: {}" .format (duration ))
43
77
44
78
return durationpy .from_str (duration )
45
79
80
+
46
81
def format_duration (delta : datetime .timedelta ) -> str :
47
82
"""
48
83
Format a datetime.timedelta object to GEP-2257 Duration format.
@@ -59,12 +94,48 @@ def format_duration(delta: datetime.timedelta) -> str:
59
94
60
95
Raises: ValueError if the timedelta given cannot be expressed as a
61
96
GEP-2257 Duration.
97
+
98
+ Examples:
99
+ >>> format_duration(datetime.timedelta(seconds=3600))
100
+ '1h'
101
+ >>> format_duration(datetime.timedelta(seconds=60))
102
+ '1m'
103
+ >>> format_duration(datetime.timedelta(seconds=1))
104
+ '1s'
105
+ >>> format_duration(datetime.timedelta(microseconds=1000))
106
+ '1ms'
107
+ >>> format_duration(datetime.timedelta(seconds=5410))
108
+ '1h30m10s'
109
+
110
+ The zero duration is always "0s".
111
+ >>> format_duration(datetime.timedelta(0))
112
+ '0s'
113
+
114
+ Sub-millisecond precision is not allowed.
115
+ >>> format_duration(datetime.timedelta(microseconds=100))
116
+ Traceback (most recent call last):
117
+ ...
118
+ ValueError: Cannot express sub-millisecond precision in GEP-2257: 0:00:00.000100
119
+
120
+ Negative durations are not allowed.
121
+ >>> format_duration(datetime.timedelta(seconds=-1))
122
+ Traceback (most recent call last):
123
+ ...
124
+ ValueError: Cannot express negative durations in GEP-2257: -1 day, 23:59:59
62
125
"""
63
126
64
127
# Short-circuit if we have a zero delta.
65
128
if delta == datetime .timedelta (0 ):
66
129
return "0s"
67
130
131
+ # Check range early.
132
+ if delta < datetime .timedelta (0 ):
133
+ raise ValueError ("Cannot express negative durations in GEP-2257: {}" .format (delta ))
134
+
135
+ if delta > datetime .timedelta (milliseconds = maxDuration_ms ):
136
+ raise ValueError (
137
+ "Cannot express durations longer than 99999h59m59s999ms in GEP-2257: {}" .format (delta ))
138
+
68
139
# durationpy.to_str() is happy to use floating-point seconds, which
69
140
# GEP-2257 is _not_ happy with. So start by peeling off any microseconds
70
141
# from our delta.
@@ -90,8 +161,4 @@ def format_duration(delta: datetime.timedelta) -> str:
90
161
91
162
delta_str += f"{ delta_ms } ms"
92
163
93
- if not reDuration .match (delta_str ):
94
- raise ValueError ("Invalid duration format: {}" .format (durationpy .to_str (delta )))
95
-
96
164
return delta_str
97
-
0 commit comments