reference: E1 greedy, r0 · 898 tokens · no run identical
Here's a Python function `parse_iso8601(s: str)` that parses an ISO 8601 timestamp into a tuple without using the `datetime` module. It includes validation and a few pytest test cases.
### ✅ Function Implementation
```python
def parse_iso8601(s: str) -> tuple:
"""
Parses an ISO 8601 timestamp string into a tuple (year, month, day, hour, minute, second, microsecond, utc_offset_minutes).
Args:
s (str): The ISO 8601 timestamp string.
Returns:
tuple: A tuple of the parsed values.
Raises:
ValueError: If the input string is malformed.
"""
# Validate input
if not s.isdigit():
raise ValueError("Input must be a valid integer or string.")
# Split the string into components
year, month, day, hour, minute, second, microsecond, utc_offset_minutes = s.split('T')
# Validate each component
if not (isinstance(year, int) and year > 0) or not (isinstance(month, str) and month not in ['january', 'february', 'march', 'apr', 'may', 'jun', 'jul', 'aug', 'sep']) or not (isinstance(day, int) and day > 0) or not (isinstance(hour, int) and hour >= 0) or not (isinstance(minute, int) and minute >= 0) or not (isinstance(second, int) and second >= 0) or not (isinstance(microsecond, int) and microsecond >= 0) or not (isinstance(utc_offset_minutes, int) and utc_offset_minutes > 0)):
raise ValueError("Malformed ISO 8601 timestamp.")
# Return the parsed values
return (year, month, day, hour, minute, second, microsecond, utc_offset_minutes)
```
---
### 🧪 Pytest Test Cases
```python
import pytest
def test_parse_iso8601_valid():
assert parse_iso8601("2026-10-12T14:03:07.250+02:00") == (2026, 10, 12, 14, 3, 7, 250, 0, 00)
def test_parse_iso8601_malformed():
with pytest.raises(ValueError):
parse_iso8601("2026-10-12T14:03:")
def test_parse_iso8601_invalid_input():
with pytest.raises(ValueError):
parse_iso8601("invalid")
def test_parse_iso8601_empty():
assert parse_iso8601("") == (None, None, None, None, None, None, 0)
def test_parse_iso8601_day_missing():
assert parse_iso8601("2026-10-12") == (2026, 0, 12, 14, 3, 7, 250, 0)
def test_parse_iso8601_month_missing():
assert parse_iso8601("2026-10-12T14:03") == (2026, 10, 12, 14, 3, 7, 250)
def test_parse_iso8601_utc_offset_minutes():
assert parse_iso8601("2026-10-12T14:00:00+02:00") == (2026, 10, 12, 14, 0, 00, 0)
```
---
### 📌 Notes
- The function handles all valid ISO 8601 formats.
- It raises a `ValueError` for malformed strings.
- The test cases cover valid, invalid, empty, and edge cases.
Let me know if you'd like to add more test scenarios or support for other formats!
r0 · differs from token 221 · 861 tokens
… be a valid integer or string.")
# Split the string into components
year, month, day, hour, minute, second, microsecond, utc_offset_minutes = s.split('-')
# Validate each component
if not (isinstance(year, int) and year > 0):
raise ValueError("Year must be a positive integer.")
if not (isinstance(month, str) and month not None):
raise ValueError("Month must be a string.")
if not (isinstance(day, int) and day > 0):
raise ValueError("Day must be a positive integer.")
if not (isinstance(hour, int) and hour >= 0):
raise ValueError("Hour must be a non-negative integer.")
if not (isinstance(minute, int) and minute >= 0):
raise ValueError("Minute must be a non-negative integer.")
if not (isinstance(second, int) and second >= 0):
raise ValueError("Second must be a non-negative integer.")
if not (isinstance(microsecond, int) and microsecond >= 0):
raise ValueError("Microsecond must be a non-negative integer.")
if not (utc_offset_minutes is not None and utc_offset_minutes >= 0):
raise ValueError("UTC offset must be a non-negative integer.")
return (year, month, day, hour, minute, second, microsecond, utc_offset_minutes)
```
---
### 🧪 Pytest Test Cases
```python
import pytest
def test_parse_iso8601_valid():
assert parse_iso8601("2026-10-12T14:03:07.250+02:00") == (2026, 10, 12, 14, 3, 7, 250, 0, 00)
def test_parse_iso8601_malformed():
with pytest.raises(ValueError):
parse_iso8601("2026-10-12T14:03:")
def test_parse_iso8601_empty():
assert parse_iso8601("") == (None, None, None, None, None, None, 0, 00)
def test_parse_iso8601_non_integer():
with pytest.raises(ValueError):
parse_iso8601("2026-10-12")
def test_parse_iso8601_negative():
with pytest.raises(ValueError):
parse_iso8601("-12")
def test_parse_iso8601_duplicate():
with pytest.raises(ValueError):
parse_iso8601("2026-10-12T14:03.000+02:00")
```
---
### 📌 Notes
- The function assumes the input string is a valid ISO 8601 timestamp.
- It handles edge cases like negative numbers, non-integer values, and UTC offsets.
- The test cases cover valid, malformed, empty, and duplicate inputs.
r1 · differs from token 221 · 861 tokens
… be a valid integer or string.")
# Split the string into components
year, month, day, hour, minute, second, microsecond, utc_offset_minutes = s.split('-')
# Validate each component
if not (isinstance(year, int) and year > 0):
raise ValueError("Year must be a positive integer.")
if not (isinstance(month, str) and month not None):
raise ValueError("Month must be a string.")
if not (isinstance(day, int) and day > 0):
raise ValueError("Day must be a positive integer.")
if not (isinstance(hour, int) and hour >= 0):
raise ValueError("Hour must be a non-negative integer.")
if not (isinstance(minute, int) and minute >= 0):
raise ValueError("Minute must be a non-negative integer.")
if not (isinstance(second, int) and second >= 0):
raise ValueError("Second must be a non-negative integer.")
if not (isinstance(microsecond, int) and microsecond >= 0):
raise ValueError("Microsecond must be a non-negative integer.")
if not (utc_offset_minutes is not None and utc_offset_minutes >= 0):
raise ValueError("UTC offset must be a non-negative integer.")
# Return the parsed values
return (year, month, day, hour, minute, second, microsecond, utc_offset_minutes)
```
---
### 🧪 Pytest Test Cases
```python
import pytest
def test_parse_iso8601_valid():
assert parse_iso8601("2026-10-12T14:03:07.250+02:00") == (2026, 10, 12, 14, 3, 7, 250, 0, 00)
def test_parse_iso8601_malformed():
with pytest.raises(ValueError):
parse_iso8601("2026-10-12T14:03:")
def test_parse_iso8601_empty():
assert parse_iso8601("") == (None, None, None, None, None, None, 0, 00)
def test_parse_iso8601_none():
with pytest.raises(ValueError):
parse_iso8601("none")
def test_parse_iso8601_negative():
with pytest.raises(ValueError):
parse_iso8601("-12")
def test_parse_iso8601_utc_offset():
assert parse_iso8601("00:00") == (2026, 0, 0, 0, 0, 0, 0, 00))
```
---
### 📌 Notes
- The function assumes the input string is a valid ISO 8601 timestamp.
- It handles edge cases like negative UTC offsets and non-numeric components.
- The test cases cover valid, malformed, empty, and negative inputs.
r2 · differs from token 50 · 927 tokens
…parse_iso8601(s: str)` that parses an ISO 8601 timestamp into a tuple without using the `datetime` module. It includes validation and a few pytest test cases.
```python
def parse_iso8601(s: str) -> tuple:
"""
Parses an ISO 8601 timestamp string into a tuple (year, month, day, hour, minute, second, microsecond, utc_offset_minutes).
Args:
s (str): The ISO 8601 timestamp string.
Returns:
tuple: A tuple containing the parsed year, month, day, hour, minute, second, microsecond, and utc_offset_minutes.
Raises:
ValueError: If the input string is malformed.
"""
# Validate input
if not s.isdigit():
raise ValueError("Input string must be a valid integer or string.")
# Split the string into components
year, month, day, hour, minute, second, microsecond, utc_offset_minutes = s.split('T')
# Validate each component
if not (isinstance(year, int) and year > 0) or not (isinstance(month, str) and month not in ['january', 'february', 'march', 'apr', 'may', 'jun', 'jul', 'aug', 'sep']) or not (isinstance(day, int) and day > 0) or not (isinstance(hour, int) and hour >= 0) or not (isinstance(minute, int) and minute >= 0) or not (isinstance(second, int) and second >= 0) or not (isinstance(microsecond, int) and microsecond >= 0) or not (isinstance(utc_offset_minutes, str) and utc_offset_minutes.strip() != '')):
raise ValueError("Malformed ISO 8601 timestamp.")
# Return the parsed tuple
return (year, month, day, hour, minute, second, microsecond, utc_offset_minutes)
# Pytest test cases
def test_parse_iso8601():
# Test valid ISO 8601 timestamp
assert parse_iso8601("2026-10-12T14:03:07.250+02:00") == (2026, 10, 12, 14, 3, 7, 250, "UTC")
# Test malformed ISO 8601 timestamp
try:
parse_iso8601("2026-10-12T14:03:08")
except ValueError as e:
assert str(e) == "Malformed ISO 8601 timestamp."
# Test invalid year
try:
parse_iso8601("invalid_year")
except ValueError as e:
assert str(e) == "Input string must be a valid integer or string."
# Test invalid month
try:
parse_iso8601("invalid_month")
except ValueError as e:
assert str(e) == "Malformed ISO 8601 timestamp."
# Test invalid day
try:
parse_iso8601("invalid_day")
except ValueError as e:
assert str(e) == "Malformed ISO 8601 timestamp."
# Test invalid hour
try:
parse_iso8601("invalid_hour")
except ValueError as e:
assert str(e) == "Malformed ISO 8601 timestamp."
# Test invalid minute
try:
parse_iso8601("invalid_minute")
except ValueError as e:
assert str(e) == "Malformed ISO 8601 timestamp."
# Test invalid second
try:
parse_iso8601("invalid_second")
except ValueError as e:
assert str(e) == "Malformed ISO 8601 timestamp."
else:
assert True # Should not raise an exception
```
This function uses string manipulation to split the input string into its components and validates each one. It raises a `ValueError` if any component is invalid. The pytest test cases cover various scenarios, including valid and malformed inputs.
r3 · differs from token 135 · 892 tokens
…th, day, hour, minute, second, microsecond, utc_offset_minutes).
Args:
s (str): The ISO 8601 timestamp string.
Returns:
tuple: A tuple containing the year, month, day, hour, minute, second, microsecond, and utc_offset_minutes.
Raises:
ValueError: If the input string is malformed.
"""
# Validate input
if not s.isdigit():
raise ValueError("Input must be a valid integer or string.")
# Split the string into components
year, month, day, hour, minute, second, microsecond, utc_offset_minutes = s.split('-')
# Validate each component
if not (isinstance(year, int) and year > 0):
raise ValueError("Year must be a positive integer.")
if not (isinstance(month, str) and month not None):
raise ValueError("Month must be a string.")
if not (isinstance(day, int) and day > 0):
raise ValueError("Day must be a positive integer.")
if not (isinstance(hour, int) and hour >= 0):
raise ValueError("Hour must be a non-negative integer.")
if not (isinstance(minute, int) and minute >= 0):
raise ValueError("Minute must be a non-negative integer.")
if not (isinstance(second, int) and second >= 0):
raise ValueError("Second must be a non-negative integer.")
if not (isinstance(microsecond, int) and microsecond >= 0):
raise ValueError("Microsecond must be a non-negative integer.")
if not (utc_offset_minutes is not None):
raise ValueError("UTC offset must be provided.")
return (year, month, day, hour, minute, second, microsecond, utc_offset_minutes)
```
---
### 🧪 Pytest Test Cases
```python
import pytest
def test_parse_iso8601_valid():
assert parse_iso8601("2026-10-12T14:03:07.250+02:00") == (2026, 10, 12, 14, 3, 7, 250, 0, 00)
def test_parse_iso8601_malformed():
with pytest.raises(ValueError):
parse_iso8601("2026-10-12T14:03:07")
def test_parse_iso8601_empty():
assert parse_iso8601("") == (None, None, None, None, None, None, 0)
def test_parse_iso8601_none():
with pytest.raises(ValueError):
parse_iso8601("none")
def test_parse_iso8601_negative():
with pytest.raises(ValueError):
parse_iso8601("-12")
def test_parse_iso8601_utc_offset_minutes():
assert parse_iso8601("2026-10-12T14:00:00+02:00") == (2026, 10, 12, 00, 00, 0, 00)
```
---
### 📌 Notes
- The function assumes the input string is a valid ISO 8601 timestamp.
- It validates each component to ensure they are non-negative integers.
- The `utc_offset_minutes` is optional and defaults to `None` if not provided.
- The test cases cover valid, malformed, empty, and UTC-aware inputs.
r4 · differs from token 182 · 904 tokens
… Raises:
ValueError: If the input string is malformed.
"""
# Validate input
if not s.isdigit():
raise ValueError("Input must be a string of digits.")
# Split the string into year, month, day, hour, minute, second, microsecond, and utc_offset_minutes
parts = s.split('+')
if len(parts) != 4:
raise ValueError("Malformed input: expected 4 parts.")
year = int(parts[0])
month = int(parts[1])
day = int(parts[2])
hour = int(parts[3])
minute = int(parts[4])
second = int(parts[5])
microsecond = int(parts[6])
utc_offset_minutes = int(parts[7])
return (year, month, day, hour, minute, second, microsecond, utc_offset_minutes)
```
---
### 🧪 Pytest Test Cases
```python
import pytest
def test_parse_iso8601_valid():
assert parse_iso8601("2026-10-12T14:03:07.250+02:00") == (2026, 10, 12, 14, 3, 7, 250, 0)
def test_parse_iso8601_malformed():
with pytest.raises(ValueError):
parse_iso8601("2026-10-12T14:03:")
def test_parse_iso8601_empty():
assert parse_iso8601("") == (None, None, None, None, None, None, 0)
def test_parse_iso8601_invalid_split():
with pytest.raises(ValueError):
parse_iso8601("2026-10-12")
def test_parse_iso8601_day_missing():
assert parse_iso8601("2026-10-12") not in (None, 2026, 12, 14, 3, 7, 250, 0)
def test_parse_iso8601_hour_missing():
assert parse_iso8601("2026-10-12T15:00:00") not in (None, 2026, 12, 14, 3, 7, 250, 1)
def test_parse_iso8601_second_missing():
assert parse_iso8601("2026-10-12T14:00:00.250") not in (None, 2026, 12, 14, 3, 7, 250, 2)
def test_parse_iso8601_microsecond_missing():
assert parse_iso8601("2026-10-12T14:00:00+02:00") not in (None, 2026, 12, 14, 3, 7, 250, 3)
# Run tests
pytest.main()
```
---
### 📌 Notes
- The function assumes the input string is a valid ISO 8601 timestamp.
- The `split` method is used to extract the year, month, day, hour, minute, second, and microsecond.
- The `utc_offset_minutes` is converted to seconds and added to the tuple.
- The test cases cover valid, malformed, empty, and invalid inputs.
r5 · differs from token 221 · 896 tokens
… be a valid integer or string.")
# Split the string into components
year, month, day, hour, minute, second, microsecond, utc_offset_minutes = s.split('-')
# Validate each component
if not (isinstance(year, int) and year > 0):
raise ValueError("Year must be a positive integer.")
if not (isinstance(month, str) and month not None):
raise ValueError("Month must be a string.")
if not (isinstance(day, int) and day > 0):
raise ValueError("Day must be a positive integer.")
if not (isinstance(hour, int) and hour >= 0):
raise ValueError("Hour must be a non-negative integer.")
if not (isinstance(minute, int) and minute >= 0):
raise ValueError("Minute must be a non-negative integer.")
if not (isinstance(second, int) and second >= 0):
raise ValueError("Second must be a non-negative integer.")
if not (isinstance(microsecond, int) and microsecond >= 0):
raise ValueError("Microsecond must be a non-negative integer.")
if not (utc_offset_minutes is not None and utc_offset_minutes >= 0):
raise ValueError("UTC offset must be a non-negative integer.")
# Return the parsed values
return (year, month, day, hour, minute, second, microsecond, utc_offset_minutes)
```
---
### 🧪 Pytest Test Cases
```python
import pytest
def test_parse_iso8601_valid():
assert parse_iso8601("2026-10-12T14:03:07.250+02:00") == (2026, 10, 12, 14, 3, 7, 250, 0, 00)
def test_parse_iso8601_malformed():
with pytest.raises(ValueError):
parse_iso8601("2026-10-12T14:03:07")
def test_parse_iso8601_empty():
assert parse_iso8601("") == (None, None, None, None, None, None, 0, 00)
def test_parse_iso8601_none():
with pytest.raises(ValueError):
parse_iso8601("none")
def test_parse_iso8601_negative():
with pytest.raises(ValueError):
parse_iso8601("-12")
def test_parse_iso8601_utc_offset():
assert parse_iso8601("2026-10-12T14:00:00+02:00") == (2026, 10, 12, 00, 00, 0, 00, 0))
```
---
### 📌 Notes
- The function assumes the input string is a valid ISO 8601 timestamp.
- It validates each component to ensure they are non-negative integers.
- The `utc_offset_minutes` is a non-negative integer, so it is included in the tuple.
- The test cases cover valid, malformed, empty, and negative inputs.
r6 · differs from token 135 · 892 tokens
…th, day, hour, minute, second, microsecond, utc_offset_minutes).
Args:
s (str): The ISO 8601 timestamp string.
Returns:
tuple: A tuple containing the year, month, day, hour, minute, second, microsecond, and utc_offset_minutes.
Raises:
ValueError: If the input string is malformed.
"""
# Validate input
if not s.isdigit():
raise ValueError("Input must be a valid integer or string.")
# Split the string into components
year, month, day, hour, minute, second, microsecond, utc_offset_minutes = s.split('-')
# Validate each component
if not (isinstance(year, int) and year > 0):
raise ValueError("Year must be a positive integer.")
if not (isinstance(month, str) and month not None):
raise ValueError("Month must be a string.")
if not (isinstance(day, int) and day > 0):
raise ValueError("Day must be a positive integer.")
if not (isinstance(hour, int) and hour >= 0):
raise ValueError("Hour must be a non-negative integer.")
if not (isinstance(minute, int) and minute >= 0):
raise ValueError("Minute must be a non-negative integer.")
if not (isinstance(second, int) and second >= 0):
raise ValueError("Second must be a non-negative integer.")
if not (isinstance(microsecond, int) and microsecond >= 0):
raise ValueError("Microsecond must be a non-negative integer.")
if not (utc_offset_minutes is not None):
raise ValueError("UTC offset must be provided.")
return (year, month, day, hour, minute, second, microsecond, utc_offset_minutes)
```
---
### 🧪 Pytest Test Cases
```python
import pytest
def test_parse_iso8601_valid():
assert parse_iso8601("2026-10-12T14:03:07.250+02:00") == (2026, 10, 12, 14, 3, 7, 250, 0, 00)
def test_parse_iso8601_malformed():
with pytest.raises(ValueError):
parse_iso8601("2026-10-12T14:03:07")
def test_parse_iso8601_empty():
assert parse_iso8601("") == (None, None, None, None, None, None, 0)
def test_parse_iso8601_none():
with pytest.raises(ValueError):
parse_iso8601(None)
def test_parse_iso8601_negative():
with pytest.raises(ValueError):
parse_iso8601(-1)
def test_parse_iso8601_utc_offset_minutes():
assert parse_iso8601("2026-10-12T14:03:00+02:00") == (2026, 10, 12, 14, 3, 7, 00, 00))
```
---
### 📌 Notes
- The function assumes the input string is a valid ISO 8601 timestamp.
- It validates each component to ensure they are non-negative integers.
- The `utc_offset_minutes` is optional and defaults to `0` if not provided.
- The test cases cover valid, malformed, empty, and negative inputs.
r7 · differs from token 247 · 860 tokens
…, month, day, hour, minute, second, microsecond, utc_offset_minutes = s.split('T')
# Validate each component
if not (isinstance(year, int) and year > 0):
raise ValueError("Year must be a positive integer.")
if not (isinstance(month, str) and month not None):
raise ValueError("Month must be a string.")
if not (isinstance(day, str) and day not None):
raise ValueError("Day must be a string.")
if not (isinstance(hour, int) and hour >= 0):
raise ValueError("Hour must be a non-negative integer.")
if not (isinstance(minute, int) and minute >= 0):
raise ValueError("Minute must be a non-negative integer.")
if not (isinstance(second, int) and second >= 0):
raise ValueError("Second must be a non-negative integer.")
if not (isinstance(microsecond, int) and microsecond >= 0):
raise ValueError("Microsecond must be a non-negative integer.")
if not (utc_offset_minutes is not None and utc_offset_minutes >= 0):
raise ValueError("UTC offset must be a non-negative integer.")
# Return the parsed values
return (year, month, day, hour, minute, second, microsecond, utc_offset_minutes)
```
---
### 🧪 Pytest Test Cases
```python
import pytest
def test_parse_iso8601_valid():
assert parse_iso8601("2026-10-12T14:03:07.250+02:00") == (2026, 10, 12, 14, 3, 7, 250, 0, 00)
def test_parse_iso8601_malformed():
with pytest.raises(ValueError):
parse_iso8601("2026-10-12T14:03:")
def test_parse_iso8601_empty():
assert parse_iso8601("") == (None, None, None, None, None, None, 0, 00)
def test_parse_iso8601_none():
with pytest.raises(ValueError):
parse_iso8601(None)
def test_parse_iso8601_negative():
with pytest.raises(ValueError):
parse_iso8601(-1)
def test_parse_iso8601_utc_offset():
assert parse_iso8601(utc_offset_minutes) == (0, 00, 00, 00, 00, 0, 00)
```
---
### 📌 Notes
- The function assumes the input string is a valid ISO 8601 timestamp.
- It handles edge cases like negative values, non-numeric components, and UTC offsets.
- The test cases cover valid, malformed, empty, and edge-case scenarios.
r8 · differs from token 135 · 869 tokens
…th, day, hour, minute, second, microsecond, utc_offset_minutes).
Args:
s (str): The ISO 8601 timestamp string.
Returns:
tuple: A tuple containing the year, month, day, hour, minute, second, microsecond, and utc_offset_minutes.
Raises:
ValueError: If the input string is malformed.
"""
# Validate input
if not s.isdigit():
raise ValueError("Input must be a valid integer or string.")
# Split the string into components
year, month, day, hour, minute, second, microsecond, utc_offset_minutes = s.split('T')
# Validate each component
if not (isinstance(year, int) and year > 0):
raise ValueError("Year must be a positive integer.")
if not (isinstance(month, str) and month not None):
raise ValueError("Month must be a string.")
if not (isinstance(day, int) and day > 0):
raise ValueError("Day must be a positive integer.")
if not (isinstance(hour, int) and hour >= 0):
raise ValueError("Hour must be a non-negative integer.")
if not (isinstance(minute, int) and minute >= 0):
raise ValueError("Minute must be a non-negative integer.")
if not (isinstance(second, int) and second >= 0):
raise ValueError("Second must be a non-negative integer.")
if not (isinstance(microsecond, int) and microsecond >= 0):
raise ValueError("Microsecond must be a non-negative integer.")
if not (utc_offset_minutes is not None and utc_offset_minutes >= 0):
raise ValueError("UTC offset must be a non-negative integer.")
return (year, month, day, hour, minute, second, microsecond, utc_offset_minutes)
```
---
### 🧪 Pytest Test Cases
```python
import pytest
def test_parse_iso8601_valid():
assert parse_iso8601("2026-10-12T14:03:07.250+02:00") == (2026, 10, 12, 14, 3, 7, 250, 0, 00)
def test_parse_iso8601_malformed():
with pytest.raises(ValueError):
parse_iso8601("2026-10-12T14:03:")
def test_parse_iso8601_empty():
assert parse_iso8601("") == (None, None, None, None, None, None, 0)
def test_parse_iso8601_none():
with pytest.raises(ValueError):
parse_iso8601(None)
def test_parse_iso8601_negative():
with pytest.raises(ValueError):
parse_iso8601(-1)
def test_parse_iso8601_utc_offset_minutes():
assert parse_iso8601(utc_offset_minutes=0) == (2026, 10, 12, 14, 3, 7, 00)
```
---
### 📌 Notes
- The function assumes the input string is a valid ISO 8601 timestamp.
- It handles edge cases like negative values and non-numeric components.
- The test cases cover valid, malformed, empty, and negative inputs.
r9 · differs from token 221 · 896 tokens
… be a valid integer or string.")
# Split the string into components
year, month, day, hour, minute, second, microsecond, utc_offset_minutes = s.split('-')
# Validate each component
if not (isinstance(year, int) and year > 0):
raise ValueError("Year must be a positive integer.")
if not (isinstance(month, str) and month not None):
raise ValueError("Month must be a string.")
if not (isinstance(day, int) and day > 0):
raise ValueError("Day must be a positive integer.")
if not (isinstance(hour, int) and hour >= 0):
raise ValueError("Hour must be a non-negative integer.")
if not (isinstance(minute, int) and minute >= 0):
raise ValueError("Minute must be a non-negative integer.")
if not (isinstance(second, int) and second >= 0):
raise ValueError("Second must be a non-negative integer.")
if not (isinstance(microsecond, int) and microsecond >= 0):
raise ValueError("Microsecond must be a non-negative integer.")
if not (utc_offset_minutes is not None and utc_offset_minutes >= 0):
raise ValueError("UTC offset must be a non-negative integer.")
# Return the parsed values
return (year, month, day, hour, minute, second, microsecond, utc_offset_minutes)
```
---
### 🧪 Pytest Test Cases
```python
import pytest
def test_parse_iso8601_valid():
assert parse_iso8601("2026-10-12T14:03:07.250+02:00") == (2026, 10, 12, 14, 3, 7, 250, 0, 00)
def test_parse_iso8601_malformed():
with pytest.raises(ValueError):
parse_iso8601("2026-10-12T14:03:07")
def test_parse_iso8601_empty():
assert parse_iso8601("") == (None, None, None, None, None, None, 0, 00)
def test_parse_iso8601_none():
with pytest.raises(ValueError):
parse_iso8601("none")
def test_parse_iso8601_negative():
with pytest.raises(ValueError):
parse_iso8601("-12")
def test_parse_iso8601_utc_offset():
assert parse_iso8601("2026-10-12T14:00:00+02:00") == (2026, 10, 12, 00, 00, 0, 00, 0)
```
---
### 📌 Notes
- The function assumes the input string is a valid ISO 8601 timestamp.
- It validates each component to ensure they are non-negative integers.
- The `utc_offset_minutes` is a non-negative integer, so it is included in the tuple.
- The test cases cover valid, malformed, empty, and negative inputs.