Update datetime parse helper

Allow non T in isotime format, add non T normal datetime parsing
This commit is contained in:
Clemens Schwaighofer
2025-11-06 13:24:27 +09:00
parent 0981c74da9
commit c98c5df63c
5 changed files with 60 additions and 8 deletions

View File

@@ -52,7 +52,7 @@ Have the following setup in `project.toml`
```toml ```toml
[[tool.uv.index]] [[tool.uv.index]]
name = "egra-gitea" name = "opj-pypi"
url = "https://git.egplusww.jp/api/packages/PyPI/pypi/simple/" url = "https://git.egplusww.jp/api/packages/PyPI/pypi/simple/"
publish-url = "https://git.egplusww.jp/api/packages/PyPI/pypi" publish-url = "https://git.egplusww.jp/api/packages/PyPI/pypi"
explicit = true explicit = true
@@ -60,15 +60,15 @@ explicit = true
```sh ```sh
uv build uv build
uv publish --index egra-gitea --token <gitea token> uv publish --index opj-pypi --token <gitea token>
``` ```
## Test package ## Use package
We must set the full index URL here because we run with "--no-project" We must set the full index URL here because we run with "--no-project"
```sh ```sh
uv run --with corelibs --index egra-gitea=https://git.egplusww.jp/api/packages/PyPI/pypi/simple/ --no-project -- python -c "import corelibs" uv run --with corelibs --index opj-pypi=https://git.egplusww.jp/api/packages/PyPI/pypi/simple/ --no-project -- python -c "import corelibs"
``` ```
### Python tests ### Python tests
@@ -101,7 +101,7 @@ uv run test-run/<script>
This will also add the index entry This will also add the index entry
```sh ```sh
uv add corelibs --index egra-gitea=https://git.egplusww.jp/api/packages/PyPI/pypi/simple/ uv add corelibs --index opj-pypi=https://git.egplusww.jp/api/packages/PyPI/pypi/simple/
``` ```
## Python venv setup ## Python venv setup

View File

@@ -17,7 +17,7 @@ dependencies = [
# MARK: build target # MARK: build target
[[tool.uv.index]] [[tool.uv.index]]
name = "egra-gitea" name = "opj-pypi"
url = "https://git.egplusww.jp/api/packages/PyPI/pypi/simple/" url = "https://git.egplusww.jp/api/packages/PyPI/pypi/simple/"
publish-url = "https://git.egplusww.jp/api/packages/PyPI/pypi" publish-url = "https://git.egplusww.jp/api/packages/PyPI/pypi"
explicit = true explicit = true
@@ -63,12 +63,13 @@ ignore = [
[tool.pylint.MASTER] [tool.pylint.MASTER]
# this is for the tests/etc folders # this is for the tests/etc folders
init-hook='import sys; sys.path.append("src/")' init-hook='import sys; sys.path.append("src/")'
# MARK: Testing
[tool.pytest.ini_options] [tool.pytest.ini_options]
testpaths = [ testpaths = [
"tests", "tests",
] ]
[tool.coverage.run] [tool.coverage.run]
omit = [ omit = [
"*/tests/*", "*/tests/*",

View File

@@ -159,10 +159,14 @@ def parse_flexible_date(
# Try different parsing methods # Try different parsing methods
parsers: list[Callable[[str], datetime]] = [ parsers: list[Callable[[str], datetime]] = [
# ISO 8601 format # ISO 8601 format, also with missing "T"
lambda x: datetime.fromisoformat(x), # pylint: disable=W0108 lambda x: datetime.fromisoformat(x), # pylint: disable=W0108
lambda x: datetime.fromisoformat(x.replace(' ', 'T')), # pylint: disable=W0108
# Simple date format # Simple date format
lambda x: datetime.strptime(x, "%Y-%m-%d"), lambda x: datetime.strptime(x, "%Y-%m-%d"),
# datetime without T
lambda x: datetime.strptime(x, "%Y-%m-%d %H:%M:%S"),
lambda x: datetime.strptime(x, "%Y-%m-%d %H:%M:%S.%f"),
# Alternative ISO formats (fallback) # Alternative ISO formats (fallback)
lambda x: datetime.strptime(x, "%Y-%m-%dT%H:%M:%S"), lambda x: datetime.strptime(x, "%Y-%m-%dT%H:%M:%S"),
lambda x: datetime.strptime(x, "%Y-%m-%dT%H:%M:%S.%f"), lambda x: datetime.strptime(x, "%Y-%m-%dT%H:%M:%S.%f"),

View File

View File

@@ -275,6 +275,53 @@ class TestParseFlexibleDate:
assert isinstance(result, datetime) assert isinstance(result, datetime)
assert result.tzinfo is not None assert result.tzinfo is not None
def test_parse_flexible_date_missing_t_with_timezone_shift(self):
"""Test parse_flexible_date with timezone shift"""
result = parse_flexible_date('2023-12-25 15:30:45+00:00', timezone_tz='Asia/Tokyo', shift_time_zone=True)
assert isinstance(result, datetime)
assert result.tzinfo is not None
def test_parse_flexible_date_space_separated_datetime(self):
"""Test parse_flexible_date with space-separated datetime format"""
result = parse_flexible_date('2023-12-25 15:30:45')
assert isinstance(result, datetime)
assert result.year == 2023
assert result.month == 12
assert result.day == 25
assert result.hour == 15
assert result.minute == 30
assert result.second == 45
def test_parse_flexible_date_space_separated_with_microseconds(self):
"""Test parse_flexible_date with space-separated datetime and microseconds"""
result = parse_flexible_date('2023-12-25 15:30:45.123456')
assert isinstance(result, datetime)
assert result.year == 2023
assert result.month == 12
assert result.day == 25
assert result.hour == 15
assert result.minute == 30
assert result.second == 45
assert result.microsecond == 123456
def test_parse_flexible_date_t_separated_datetime(self):
"""Test parse_flexible_date with T-separated datetime (alternative ISO format)"""
result = parse_flexible_date('2023-12-25T15:30:45')
assert isinstance(result, datetime)
assert result.year == 2023
assert result.month == 12
assert result.day == 25
assert result.hour == 15
assert result.minute == 30
assert result.second == 45
def test_parse_flexible_date_t_separated_with_microseconds(self):
"""Test parse_flexible_date with T-separated datetime and microseconds"""
result = parse_flexible_date('2023-12-25T15:30:45.123456')
assert isinstance(result, datetime)
assert result.year == 2023
assert result.microsecond == 123456
def test_parse_flexible_date_invalid_format(self): def test_parse_flexible_date_invalid_format(self):
"""Test parse_flexible_date with invalid format returns None""" """Test parse_flexible_date with invalid format returns None"""
result = parse_flexible_date('invalid-date') result = parse_flexible_date('invalid-date')