117 lines
3.0 KiB
Python
117 lines
3.0 KiB
Python
"""Formatting utilities for dates, times, and text."""
|
|
|
|
from datetime import datetime, timedelta
|
|
from typing import Optional
|
|
|
|
|
|
def format_datetime(dt: datetime, include_time: bool = True) -> str:
|
|
"""
|
|
Format datetime for display.
|
|
|
|
Args:
|
|
dt: datetime object
|
|
include_time: Whether to include time in output
|
|
|
|
Returns:
|
|
Formatted datetime string
|
|
"""
|
|
if include_time:
|
|
return dt.strftime("%d.%m.%Y в %H:%M")
|
|
else:
|
|
return dt.strftime("%d.%m.%Y")
|
|
|
|
|
|
def format_timedelta(td: timedelta) -> str:
|
|
"""
|
|
Format timedelta for human-readable display.
|
|
|
|
Args:
|
|
td: timedelta object
|
|
|
|
Returns:
|
|
Formatted string (e.g., "2 дня", "5 часов")
|
|
"""
|
|
total_seconds = int(td.total_seconds())
|
|
|
|
if total_seconds < 0:
|
|
return "просрочено"
|
|
|
|
days = total_seconds // 86400
|
|
hours = (total_seconds % 86400) // 3600
|
|
minutes = (total_seconds % 3600) // 60
|
|
|
|
if days > 0:
|
|
days_word = get_plural_form(days, "день", "дня", "дней")
|
|
if hours > 0:
|
|
hours_word = get_plural_form(hours, "час", "часа", "часов")
|
|
return f"{days} {days_word} {hours} {hours_word}"
|
|
return f"{days} {days_word}"
|
|
elif hours > 0:
|
|
hours_word = get_plural_form(hours, "час", "часа", "часов")
|
|
if minutes > 0:
|
|
minutes_word = get_plural_form(minutes, "минута", "минуты", "минут")
|
|
return f"{hours} {hours_word} {minutes} {minutes_word}"
|
|
return f"{hours} {hours_word}"
|
|
else:
|
|
minutes_word = get_plural_form(minutes, "минута", "минуты", "минут")
|
|
return f"{minutes} {minutes_word}"
|
|
|
|
|
|
def get_plural_form(number: int, form1: str, form2: str, form5: str) -> str:
|
|
"""
|
|
Get correct plural form for Russian language.
|
|
|
|
Args:
|
|
number: The number
|
|
form1: Form for 1 (день)
|
|
form2: Form for 2-4 (дня)
|
|
form5: Form for 5+ (дней)
|
|
|
|
Returns:
|
|
Correct plural form
|
|
"""
|
|
n = abs(number) % 100
|
|
n1 = n % 10
|
|
|
|
if 10 < n < 20:
|
|
return form5
|
|
if n1 == 1:
|
|
return form1
|
|
if 2 <= n1 <= 4:
|
|
return form2
|
|
return form5
|
|
|
|
|
|
def format_interval_days(days: int) -> str:
|
|
"""
|
|
Format interval in days for display.
|
|
|
|
Args:
|
|
days: Number of days
|
|
|
|
Returns:
|
|
Formatted string (e.g., "каждый день", "каждые 3 дня")
|
|
"""
|
|
if days == 1:
|
|
return "каждый день"
|
|
else:
|
|
days_word = get_plural_form(days, "день", "дня", "дней")
|
|
return f"каждые {days} {days_word}"
|
|
|
|
|
|
def truncate_text(text: str, max_length: int = 50, suffix: str = "...") -> str:
|
|
"""
|
|
Truncate text to maximum length.
|
|
|
|
Args:
|
|
text: Text to truncate
|
|
max_length: Maximum length
|
|
suffix: Suffix to add if truncated
|
|
|
|
Returns:
|
|
Truncated text
|
|
"""
|
|
if len(text) <= max_length:
|
|
return text
|
|
return text[:max_length - len(suffix)] + suffix
|