Move repo from git to gitea
Signed-off-by: Boris Yumankulov <boria138@altlinux.org>
This commit is contained in:
159
portprotonqt/time_utils.py
Normal file
159
portprotonqt/time_utils.py
Normal file
@ -0,0 +1,159 @@
|
||||
import os
|
||||
from datetime import datetime, timedelta
|
||||
from babel.dates import format_timedelta, format_date
|
||||
from portprotonqt.config_utils import read_time_config
|
||||
from portprotonqt.localization import _, get_system_locale
|
||||
from portprotonqt.logger import get_logger
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
def get_cache_file_path():
|
||||
"""Возвращает путь к файлу кеша portproton_last_launch."""
|
||||
cache_home = os.getenv("XDG_CACHE_HOME", os.path.join(os.path.expanduser("~"), ".cache"))
|
||||
return os.path.join(cache_home, "PortProtonQT", "last_launch")
|
||||
|
||||
def save_last_launch(exe_name, launch_time):
|
||||
"""
|
||||
Сохраняет время запуска для exe.
|
||||
Формат файла: <exe_name> <isoformatted_time>
|
||||
"""
|
||||
file_path = get_cache_file_path()
|
||||
data = {}
|
||||
if os.path.exists(file_path):
|
||||
with open(file_path, encoding="utf-8") as f:
|
||||
for line in f:
|
||||
parts = line.strip().split(maxsplit=1)
|
||||
if len(parts) == 2:
|
||||
data[parts[0]] = parts[1]
|
||||
data[exe_name] = launch_time.isoformat()
|
||||
os.makedirs(os.path.dirname(file_path), exist_ok=True)
|
||||
with open(file_path, "w", encoding="utf-8") as f:
|
||||
for key, iso_time in data.items():
|
||||
f.write(f"{key} {iso_time}\n")
|
||||
|
||||
def format_last_launch(launch_time):
|
||||
"""
|
||||
Форматирует время запуска с использованием Babel.
|
||||
|
||||
Для detail_level "detailed" возвращает относительный формат с добавлением "назад"
|
||||
(например, "2 мин. назад"). Если время меньше минуты – возвращает переведённую строку.
|
||||
Для "brief" – дату в формате "день месяц год" (например, "1 апреля 2023")
|
||||
на основе системной локали.
|
||||
"""
|
||||
detail_level = read_time_config() or "detailed"
|
||||
system_locale = get_system_locale()
|
||||
if detail_level == "detailed":
|
||||
# Вычисляем delta как launch_time - datetime.now() чтобы получить отрицательное значение для прошедшего времени.
|
||||
delta = launch_time - datetime.now()
|
||||
if abs(delta.total_seconds()) < 60:
|
||||
return _("just now")
|
||||
return format_timedelta(delta, locale=system_locale, granularity='second', format='short', add_direction=True)
|
||||
else:
|
||||
return format_date(launch_time, format="d MMMM yyyy", locale=system_locale)
|
||||
|
||||
def get_last_launch(exe_name):
|
||||
"""
|
||||
Читает время последнего запуска для заданного exe из файла кеша.
|
||||
Возвращает время запуска в нужном формате или перевод строки "Never".
|
||||
"""
|
||||
file_path = get_cache_file_path()
|
||||
if not os.path.exists(file_path):
|
||||
return _("Never")
|
||||
with open(file_path, encoding="utf-8") as f:
|
||||
for line in f:
|
||||
parts = line.strip().split(maxsplit=1)
|
||||
if len(parts) == 2 and parts[0] == exe_name:
|
||||
iso_time = parts[1]
|
||||
launch_time = datetime.fromisoformat(iso_time)
|
||||
return format_last_launch(launch_time)
|
||||
return _("Never")
|
||||
|
||||
def parse_playtime_file(file_path):
|
||||
"""
|
||||
Парсит файл с данными о времени игры.
|
||||
|
||||
Формат строки в файле:
|
||||
<полный путь к exe> <хэш> <playtime_seconds> <platform> <build>
|
||||
|
||||
Возвращает словарь вида:
|
||||
{
|
||||
'<exe_path>': playtime_seconds (int),
|
||||
...
|
||||
}
|
||||
"""
|
||||
playtime_data = {}
|
||||
if not os.path.exists(file_path):
|
||||
logger.error(f"Файл не найден: {file_path}")
|
||||
return playtime_data
|
||||
|
||||
with open(file_path, encoding="utf-8") as f:
|
||||
for line in f:
|
||||
if not line.strip():
|
||||
continue
|
||||
parts = line.strip().split()
|
||||
if len(parts) < 3:
|
||||
continue
|
||||
exe_path = parts[0]
|
||||
seconds = int(parts[2])
|
||||
playtime_data[exe_path] = seconds
|
||||
return playtime_data
|
||||
|
||||
def format_playtime(seconds):
|
||||
"""
|
||||
Конвертирует время в секундах в форматированную строку с использованием Babel.
|
||||
|
||||
При "detailed" выводится полный разбор времени, без округления
|
||||
(например, "1 ч 1 мин 15 сек").
|
||||
|
||||
При "brief":
|
||||
- если время менее часа, выводится точное время с секундами (например, "9 мин 28 сек"),
|
||||
- если больше часа – только часы (например, "3 ч").
|
||||
"""
|
||||
detail_level = read_time_config() or "detailed"
|
||||
system_locale = get_system_locale()
|
||||
seconds = int(seconds)
|
||||
|
||||
if detail_level == "detailed":
|
||||
days, rem = divmod(seconds, 86400)
|
||||
hours, rem = divmod(rem, 3600)
|
||||
minutes, secs = divmod(rem, 60)
|
||||
parts = []
|
||||
if days > 0:
|
||||
parts.append(f"{days} " + _("d."))
|
||||
if hours > 0:
|
||||
parts.append(f"{hours} " + _("h."))
|
||||
if minutes > 0:
|
||||
parts.append(f"{minutes} " + _("min."))
|
||||
if secs > 0 or not parts:
|
||||
parts.append(f"{secs} " + _("sec."))
|
||||
return " ".join(parts)
|
||||
else:
|
||||
# Режим brief
|
||||
if seconds < 3600:
|
||||
minutes, secs = divmod(seconds, 60)
|
||||
parts = []
|
||||
if minutes > 0:
|
||||
parts.append(f"{minutes} " + _("min."))
|
||||
if secs > 0 or not parts:
|
||||
parts.append(f"{secs} " + _("sec."))
|
||||
return " ".join(parts)
|
||||
else:
|
||||
hours = seconds // 3600
|
||||
return format_timedelta(timedelta(hours=hours), locale=system_locale, granularity='hour', format='short')
|
||||
|
||||
def get_last_launch_timestamp(exe_name):
|
||||
"""
|
||||
Возвращает метку времени последнего запуска (timestamp) для заданного exe.
|
||||
Если записи нет, возвращает 0.
|
||||
"""
|
||||
file_path = get_cache_file_path()
|
||||
if not os.path.exists(file_path):
|
||||
return 0
|
||||
with open(file_path, encoding="utf-8") as f:
|
||||
for line in f:
|
||||
parts = line.strip().split(maxsplit=1)
|
||||
if len(parts) == 2 and parts[0] == exe_name:
|
||||
iso_time = parts[1]
|
||||
dt = datetime.fromisoformat(iso_time)
|
||||
return dt.timestamp()
|
||||
return 0
|
Reference in New Issue
Block a user