(tstr)
| 442 | return time_comps |
| 443 | |
| 444 | def _parse_isoformat_time(tstr): |
| 445 | # Format supported is HH[:MM[:SS[.fff[fff]]]][+HH:MM[:SS[.ffffff]]] |
| 446 | len_str = len(tstr) |
| 447 | if len_str < 2: |
| 448 | raise ValueError("Isoformat time too short") |
| 449 | |
| 450 | # This is equivalent to re.search('[+-Z]', tstr), but faster |
| 451 | tz_pos = (tstr.find('-') + 1 or tstr.find('+') + 1 or tstr.find('Z') + 1) |
| 452 | timestr = tstr[:tz_pos-1] if tz_pos > 0 else tstr |
| 453 | |
| 454 | time_comps = _parse_hh_mm_ss_ff(timestr) |
| 455 | |
| 456 | hour, minute, second, microsecond = time_comps |
| 457 | became_next_day = False |
| 458 | error_from_components = False |
| 459 | error_from_tz = None |
| 460 | if (hour == 24): |
| 461 | if all(time_comp == 0 for time_comp in time_comps[1:]): |
| 462 | hour = 0 |
| 463 | time_comps[0] = hour |
| 464 | became_next_day = True |
| 465 | else: |
| 466 | error_from_components = True |
| 467 | |
| 468 | tzi = None |
| 469 | if tz_pos == len_str and tstr[-1] == 'Z': |
| 470 | tzi = timezone.utc |
| 471 | elif tz_pos > 0: |
| 472 | tzstr = tstr[tz_pos:] |
| 473 | |
| 474 | # Valid time zone strings are: |
| 475 | # HH len: 2 |
| 476 | # HHMM len: 4 |
| 477 | # HH:MM len: 5 |
| 478 | # HHMMSS len: 6 |
| 479 | # HHMMSS.f+ len: 7+ |
| 480 | # HH:MM:SS len: 8 |
| 481 | # HH:MM:SS.f+ len: 10+ |
| 482 | |
| 483 | if len(tzstr) in (0, 1, 3) or tstr[tz_pos-1] == 'Z': |
| 484 | raise ValueError("Malformed time zone string") |
| 485 | |
| 486 | tz_comps = _parse_hh_mm_ss_ff(tzstr) |
| 487 | |
| 488 | if all(x == 0 for x in tz_comps): |
| 489 | tzi = timezone.utc |
| 490 | else: |
| 491 | tzsign = -1 if tstr[tz_pos - 1] == '-' else 1 |
| 492 | |
| 493 | try: |
| 494 | # This function is intended to validate datetimes, but because |
| 495 | # we restrict time zones to ±24h, it serves here as well. |
| 496 | _check_time_fields(hour=tz_comps[0], minute=tz_comps[1], |
| 497 | second=tz_comps[2], microsecond=tz_comps[3], |
| 498 | fold=0) |
| 499 | except ValueError as e: |
| 500 | error_from_tz = e |
| 501 | else: |
no test coverage detected
searching dependent graphs…