83 lines
2.7 KiB
Python
Executable File
83 lines
2.7 KiB
Python
Executable File
#!/usr/bin/env python3
|
||
"""
|
||
Утилита для вычисления разницы между двумя датами.
|
||
|
||
Поддерживает:
|
||
- Разницу в днях и полных годах.
|
||
- Автоматическое сравнение с текущей датой при указании одной даты.
|
||
|
||
Формат даты: YYYY-MM-DD
|
||
"""
|
||
|
||
import sys
|
||
from datetime import date, datetime
|
||
|
||
|
||
def parse_date(date_str: str) -> date:
|
||
"""Преобразует строку вида 'YYYY-MM-DD' в объект date."""
|
||
if not isinstance(date_str, str):
|
||
raise TypeError("Ожидалась строка с датой")
|
||
return datetime.strptime(date_str.strip(), "%Y-%m-%d").date()
|
||
|
||
|
||
def years_between(start: date, end: date) -> int:
|
||
"""
|
||
Возвращает количество полных лет между двумя датами.
|
||
|
||
Учитывает високосные годы (например, 29 февраля).
|
||
"""
|
||
|
||
if start > end:
|
||
start, end = end, start
|
||
|
||
try:
|
||
candidate = start.replace(year=end.year)
|
||
except ValueError:
|
||
# Обработка 29 февраля в невисокосный год
|
||
candidate = start.replace(year=end.year, day=28)
|
||
|
||
years = end.year - start.year
|
||
if candidate > end:
|
||
years -= 1
|
||
return years
|
||
|
||
|
||
def days_between(start: date, end: date) -> int:
|
||
"""Возвращает абсолютное количество дней между двумя датами."""
|
||
return abs((end - start).days)
|
||
|
||
|
||
def diff_dates(d1: date, d2: date) -> tuple[int, int]:
|
||
"""
|
||
Возвращает кортеж (дней, полных лет) между двумя датами.
|
||
|
||
Порядок дат не важен — результат всегда положительный.
|
||
"""
|
||
days = days_between(d1, d2)
|
||
years = years_between(d1, d2)
|
||
return days, years
|
||
|
||
|
||
def main() -> None:
|
||
args = sys.argv[1:]
|
||
if not args or len(args) > 2:
|
||
print("Использование:", file=sys.stderr)
|
||
print(" datediff <дата> # от даты до сегодня", file=sys.stderr)
|
||
print(" datediff <дата1> <дата2> # между двумя датами", file=sys.stderr)
|
||
print("Формат даты: YYYY-MM-DD", file=sys.stderr)
|
||
sys.exit(1)
|
||
|
||
try:
|
||
d1 = parse_date(args[0])
|
||
d2 = parse_date(args[1]) if len(args) == 2 else date.today()
|
||
except (ValueError, TypeError) as e:
|
||
print(f"Ошибка: неверный формат даты — {e}", file=sys.stderr)
|
||
sys.exit(1)
|
||
|
||
days, years = diff_dates(d1, d2)
|
||
print(f"Дней: {days}, Полных лет: {years}")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|