35 lines
1.2 KiB
Python
35 lines
1.2 KiB
Python
"""Interpret user-curated date folders without guessing dates from image files."""
|
||||
|
|
|
|||
|
|
import re
|
|||
|
|
from datetime import date
|
|||
|
|
from pathlib import PurePosixPath
|
|||
|
|
|
|||
|
|
_DATE = r"(?P<year>\d{4})(?:[-._年]?)(?P<month>\d{2})(?:[-._月]?)(?P<day>\d{2})(?:日)?(?!\d)"
|
|||
|
|
_PREFIX = re.compile(r"^" + _DATE)
|
|||
|
|
|
|||
|
|
|
|||
|
|
def folder_caption(name: str) -> dict[str, str] | None:
|
|||
|
|
match = _PREFIX.match(name.strip())
|
|||
|
|
if not match:
|
|||
|
|
return None
|
|||
|
|
try:
|
|||
|
|
captured = date(int(match["year"]), int(match["month"]), int(match["day"]))
|
|||
|
|
except ValueError:
|
|||
|
|
return None
|
|||
|
|
remainder = name.strip()[match.end() :].strip(" _-—–::")
|
|||
|
|
title, separator, place = remainder.replace("@", "@").partition("@")
|
|||
|
|
return {
|
|||
|
|
"title": " ".join(title.split()),
|
|||
|
|
"date": captured.isoformat(),
|
|||
|
|
"place": " ".join(place.split()) if separator else "",
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
def path_caption(path: str) -> dict[str, str] | None:
|
|||
|
|
# Children inherit their nearest date folder, rather than their filename.
|
|||
|
|
for component in reversed(PurePosixPath(path).parent.parts):
|
|||
|
|
caption = folder_caption(component)
|
|||
|
|
if caption is not None:
|
|||
|
|
return caption
|
|||
|
|
return None
|