(text: str, **options: str)
| 264 | |
| 265 | |
| 266 | def _parse_iso8601_duration(text: str, **options: str) -> Duration | None: |
| 267 | m = ISO8601_DURATION.fullmatch(text) |
| 268 | if not m or (not m.group("w") and not m.group("ymd") and not m.group("hms")): |
| 269 | return None |
| 270 | |
| 271 | years = 0 |
| 272 | months = 0 |
| 273 | weeks = 0 |
| 274 | days: int | float = 0 |
| 275 | hours: int | float = 0 |
| 276 | minutes: int | float = 0 |
| 277 | seconds: int | float = 0 |
| 278 | microseconds: int | float = 0 |
| 279 | fractional = False |
| 280 | |
| 281 | _days: str | float |
| 282 | _hours: str | int | None |
| 283 | _minutes: str | int | None |
| 284 | _seconds: str | int | None |
| 285 | if m.group("w"): |
| 286 | # Weeks |
| 287 | if m.group("ymd") or m.group("hms"): |
| 288 | # Specifying anything more than weeks is not supported |
| 289 | raise ParserError("Invalid duration string") |
| 290 | |
| 291 | _weeks = m.group("weeks") |
| 292 | if not _weeks: |
| 293 | raise ParserError("Invalid duration string") |
| 294 | |
| 295 | _weeks = _weeks.replace(",", ".").replace("W", "") |
| 296 | if "." in _weeks: |
| 297 | _weeks, portion = _weeks.split(".") |
| 298 | weeks = int(_weeks) |
| 299 | _days = int(portion) / 10 * 7 |
| 300 | days, hours = int(_days // 1), int(_days % 1 * HOURS_PER_DAY) |
| 301 | else: |
| 302 | weeks = int(_weeks) |
| 303 | |
| 304 | if m.group("ymd"): |
| 305 | # Years, months and/or days |
| 306 | _years = m.group("years") |
| 307 | _months = m.group("months") |
| 308 | _days = m.group("days") |
| 309 | |
| 310 | # Checking order |
| 311 | years_start = m.start("years") if _years else -3 |
| 312 | months_start = m.start("months") if _months else years_start + 1 |
| 313 | days_start = m.start("days") if _days else months_start + 1 |
| 314 | |
| 315 | # Check correct order |
| 316 | if not (years_start < months_start < days_start): |
| 317 | raise ParserError("Invalid duration") |
| 318 | |
| 319 | if _years: |
| 320 | _years = _years.replace(",", ".").replace("Y", "") |
| 321 | if "." in _years: |
| 322 | raise ParserError("Float years in duration are not supported") |
| 323 | else: |
no test coverage detected
searching dependent graphs…