reference = r0 · 1024 tokens · r0–9 identical
```python
import re
from typing import Tuple, ValueError
def parse_iso8601(s: str) -> Tuple[int, int, int, int, int, int, int, int]:
"""
Parse an ISO 8601 timestamp string into a tuple (year, month, day, hour, minute,
second, microsecond, utc_offset_minutes).
Args:
s: ISO 8601 formatted string (e.g., "2026-10-12T14:03:07.250+02:00")
Returns:
Tuple of (year, month, day, hour, minute, second, microsecond, utc_offset_minutes)
Raises:
ValueError: If the input string is malformed or does not conform to ISO 8601 format
"""
# Validate input
if not isinstance(s, str):
raise ValueError("Input must be a string")
if not s or s.isspace():
raise ValueError("Input string cannot be empty or contain only whitespace")
# Define the expected pattern
# Format: YYYY-MM-DDTHH:MM:SS.sss[+-]HH:MM
pattern = r'^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})\.(\d{3})([+-])(\d{2}):(\d{2})$'
match = re.match(pattern, s)
if not match:
# Try without microseconds (e.g., "2026-10-12T14:03:07+02:00")
pattern_no_micro = r'^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})([+-])(\d{2}):(\d{2})$'
match_no_micro = re.match(pattern_no_micro, s)
if not match_no_micro:
raise ValueError(f"Invalid ISO 8601 format: {s}")
# Extract values from the no-microsecond version
year, month, day, hour, minute, second, utc_sign, utc_hour, utc_minute = match_no_micro.groups()
# Microsecond is 0
microsecond = 0
# UTC offset in minutes
offset_minutes = int(utc_hour) * 60 + int(utc_minute) if utc_sign == '+' else -(int(utc_hour) * 60 + int(utc_minute))
return (
int(year), int(month), int(day),
int(hour), int(minute), int(second),
microsecond, offset_minutes
)
# Extract values from the full pattern
year, month, day, hour, minute, second, microsecond_str, utc_sign, utc_hour, utc_minute = match.groups()
# Convert to integers
year, month, day, hour, minute, second = int(year), int(month), int(day), int(hour), int(minute), int(second)
microsecond = int(microsecond_str)
# UTC offset in minutes
offset_minutes = int(utc_hour) * 60 + int(utc_minute) if utc_sign == '+' else -(int(utc_hour) * 60 + int(utc_minute))
# Validate date components
if not (1 <= month <= 12):
raise ValueError(f"Invalid month: {month}")
if not (1 <= day <= 31):
raise ValueError(f"Invalid day: {day}")
# Validate time components
if not (0 <= hour <= 23):
raise ValueError(f"Invalid hour: {hour}")
if not (0 <= minute <= 59):
raise ValueError(f"Invalid minute: {minute}")
if not (0 <= second <= 59):
raise ValueError(f"Invalid second: {second}")
if not (0 <= microsecond <= 999999):
raise ValueError(f"Invalid microsecond: {microsecond}")
# Validate UTC offset
if not (-1440 <= offset_minutes <= 1440):
raise ValueError(f"Invalid UTC offset: {offset_minutes} minutes")
# Validate day of month based on month (basic check)
# This is a simplified check - we don't validate leap years or month-specific days
# in this function for simplicity
if month in [4, 6, 9, 11] and day > 30:
raise ValueError(f"Invalid day for month {month}: {day}