@@ -160,17 +160,35 @@ def get_time(self, id):
160160 return value_str
161161
162162 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 ):
165172 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
174192 else :
175193 value = value_str
176194
0 commit comments