Files
MoviePilot/app/foundation/temporal.py

112 lines
3.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""日期、时间戳和时长的无状态转换能力。"""
import bisect
import datetime
from typing import Any, Optional, Union
import dateparser
import dateutil.parser
def format_approx_duration(seconds: Union[str, int, float]) -> str:
"""把秒数格式化为单一最大单位的近似时长。"""
try:
seconds = float(seconds)
except (TypeError, ValueError):
return ""
thresholds = [(0, ""), (60 - 1, ""), (3600 - 1, "小时"), (86400 - 1, "")]
index = bisect.bisect_left(
[threshold for threshold, _unit in thresholds], seconds
) - 1
if index == -1:
return str(seconds)
threshold, unit = thresholds[index]
return f"{round(seconds / (threshold + 1))}{unit}"
def format_duration(seconds: Union[str, int, float]) -> str:
"""把秒数格式化为时分秒组合文本。"""
hours = seconds // 3600
remainder_seconds = seconds % 3600
minutes = remainder_seconds // 60
seconds = remainder_seconds % 60
result = f"{int(seconds)}"
if minutes:
result = f"{int(minutes)}{result}"
if hours:
result = f"{int(hours)}{result}"
return result
def parse_datetime(value: Any) -> Optional[datetime.datetime]:
"""将常见日期表达解析为 datetime无法解析时返回 None。"""
try:
return dateutil.parser.parse(value)
except (TypeError, ValueError, dateutil.parser.ParserError):
return None
def normalize_datetime(value: str) -> str:
"""把常见绝对或相对日期文本统一为本地日期时间格式。"""
if not value:
return value
try:
parsed = dateparser.parse(value)
return parsed.strftime("%Y-%m-%d %H:%M:%S") if parsed else value
except (TypeError, ValueError, OverflowError):
return value
def format_timestamp(timestamp: str, date_format: str = "%Y-%m-%d %H:%M:%S") -> str:
"""把 Unix 时间戳转换为指定格式的本地日期文本。"""
if isinstance(timestamp, str) and not timestamp.isdigit():
return timestamp
try:
return datetime.datetime.fromtimestamp(int(timestamp)).strftime(date_format)
except (TypeError, ValueError, OverflowError, OSError):
return timestamp
def parse_timestamp(value: str) -> float:
"""把日期表达转换为 Unix 时间戳,无法解析时返回零。"""
if not value:
return 0
try:
parsed = dateparser.parse(value)
return parsed.timestamp() if parsed else 0
except (TypeError, ValueError, OverflowError):
return 0
def format_minutes(minutes: int) -> str:
"""把分钟数格式化为小时和分钟组合文本。"""
if not minutes:
return ""
hours, remaining_minutes = divmod(minutes, 60)
if hours:
return f"{hours}小时{remaining_minutes}"
return f"{remaining_minutes}分钟"
def format_remaining(value: str) -> str:
"""把本地日期时间文本格式化为距当前时间的剩余时长。"""
if not value:
return ""
try:
target = datetime.datetime.strptime(value, "%Y-%m-%d %H:%M:%S")
except ValueError:
return value
difference = target - datetime.datetime.now()
seconds = difference.seconds
days = difference.days
hours = seconds // 3600
minutes = (seconds % 3600) // 60
if days > 0:
return f"{days}{hours}小时{minutes}分钟"
if hours > 0:
return f"{hours}小时{minutes}分钟"
if minutes > 0:
return f"{minutes}分钟"
return ""