@@ -160,17 +160,35 @@ def get_time(self, id):
160
160
return value_str
161
161
162
162
if isinstance (value_str , str ):
163
- # The format contains a : in the timezone which is supported from 3.7 on.
164
- if sys .version_info <= (3 , 7 ):
163
+ # Normalize timestamps that include a timezone followed by an
164
+ # extraneous 'Z' (e.g. '2025-09-18T21:26:38+00:00Z') by removing the
165
+ # final 'Z'. This pattern appears in some Bitbucket responses.
166
+ if re .search (r"[+-]\d{2}:\d{2}Z$" , value_str ):
167
+ value_str = value_str [:- 1 ]
168
+
169
+ # Python < 3.7 does not accept a ':' in the %z timezone, so strip
170
+ # it for older interpreters.
171
+ if sys .version_info < (3 , 7 ):
165
172
value_str = RE_TIMEZONE .sub (r"\1\2" , value_str )
166
- try :
167
- value_str = value_str [:26 ] + "Z"
168
- value = datetime .strptime (value_str , self .CONF_TIMEFORMAT )
169
- except ValueError :
170
- value = datetime .strptime (
171
- value_str ,
172
- "%Y-%m-%dT%H:%M:%S.%fZ" ,
173
- )
173
+
174
+ # Try several likely formats, from most to least specific.
175
+ value = None
176
+ for fmt in (
177
+ "%Y-%m-%dT%H:%M:%S.%f%z" ,
178
+ "%Y-%m-%dT%H:%M:%S%z" ,
179
+ "%Y-%m-%dT%H:%M:%S.%f" ,
180
+ "%Y-%m-%dT%H:%M:%S" ,
181
+ ):
182
+ try :
183
+ value = datetime .strptime (value_str , fmt )
184
+ break
185
+ except ValueError :
186
+ continue
187
+
188
+ # If parsing failed for all formats, leave the original string
189
+ # intact so the timeformat lambda can decide what to do with it.
190
+ if value is None :
191
+ value = value_str
174
192
else :
175
193
value = value_str
176
194
0 commit comments