- Introduced a new configuration file `.cursorrules` to define coding standards, error handling, testing requirements, and project-specific guidelines. - Refactored `config.py` to implement a `Settings` dataclass for better management of environment variables, improving testability and maintainability. - Updated the import duty schedule handler to utilize session management with `session_scope`, ensuring proper database session handling. - Enhanced the import service to streamline the duty schedule import process, improving code organization and readability. - Added new service layer functions to encapsulate business logic related to group duty pinning and duty schedule imports. - Updated README documentation to reflect the new configuration structure and improved import functionality.
47 lines
1.5 KiB
Python
47 lines
1.5 KiB
Python
"""Date and ISO helpers for duty ranges and API validation."""
|
|
|
|
import re
|
|
from datetime import date, datetime, timezone
|
|
|
|
|
|
def day_start_iso(d: date) -> str:
|
|
"""ISO 8601 start of calendar day UTC: YYYY-MM-DDT00:00:00Z."""
|
|
return d.isoformat() + "T00:00:00Z"
|
|
|
|
|
|
def day_end_iso(d: date) -> str:
|
|
"""ISO 8601 end of calendar day UTC: YYYY-MM-DDT23:59:59Z."""
|
|
return d.isoformat() + "T23:59:59Z"
|
|
|
|
|
|
def duty_to_iso(d: date, hour_utc: int, minute_utc: int) -> str:
|
|
"""ISO 8601 with Z for start of duty on date d at given UTC time."""
|
|
dt = datetime(d.year, d.month, d.day, hour_utc, minute_utc, 0, tzinfo=timezone.utc)
|
|
return dt.strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
|
|
|
|
# ISO date YYYY-MM-DD
|
|
_ISO_DATE_RE = re.compile(r"^\d{4}-\d{2}-\d{2}$")
|
|
|
|
|
|
def parse_iso_date(s: str) -> date | None:
|
|
"""Parse YYYY-MM-DD string to date. Returns None if invalid."""
|
|
if not s or not _ISO_DATE_RE.match(s.strip()):
|
|
return None
|
|
try:
|
|
return date.fromisoformat(s.strip())
|
|
except ValueError:
|
|
return None
|
|
|
|
|
|
def validate_date_range(from_date: str, to_date: str) -> None:
|
|
"""Validate from_date and to_date are YYYY-MM-DD and from_date <= to_date.
|
|
|
|
Raises:
|
|
ValueError: With a user-facing message if invalid.
|
|
"""
|
|
if not _ISO_DATE_RE.match(from_date or "") or not _ISO_DATE_RE.match(to_date or ""):
|
|
raise ValueError("Параметры from и to должны быть в формате YYYY-MM-DD")
|
|
if from_date > to_date:
|
|
raise ValueError("Дата from не должна быть позже to")
|