Compare commits
2 Commits
c4b0347f3b
...
dba8414fd9
Author | SHA1 | Date |
---|---|---|
Lukáš Kucharczyk | dba8414fd9 | |
Lukáš Kucharczyk | 0e2113eefd |
|
@ -1,3 +1,11 @@
|
||||||
|
## 1.1.2 / 2023-10-13 16:30+02:00
|
||||||
|
|
||||||
|
### Enhancements
|
||||||
|
* Durations are formatted in a consisent manner across all pages
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
* Game Overview: display duration when >1 hour instead of displaying 0
|
||||||
|
|
||||||
## 1.1.1 / 2023-10-09 20:52+02:00
|
## 1.1.1 / 2023-10-09 20:52+02:00
|
||||||
|
|
||||||
### New
|
### New
|
||||||
|
|
|
@ -6,7 +6,7 @@ RUN npm install && \
|
||||||
|
|
||||||
FROM python:3.10.9-slim-bullseye
|
FROM python:3.10.9-slim-bullseye
|
||||||
|
|
||||||
ENV VERSION_NUMBER 1.1.1
|
ENV VERSION_NUMBER 1.1.2
|
||||||
ENV PROD 1
|
ENV PROD 1
|
||||||
ENV PYTHONUNBUFFERED=1
|
ENV PYTHONUNBUFFERED=1
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,8 @@ def format_duration(
|
||||||
from the formatting string. For example:
|
from the formatting string. For example:
|
||||||
- 61 seconds as "%s" = 61 seconds
|
- 61 seconds as "%s" = 61 seconds
|
||||||
- 61 seconds as "%m %s" = 1 minutes 1 seconds"
|
- 61 seconds as "%m %s" = 1 minutes 1 seconds"
|
||||||
|
Format specifiers can include width and precision options:
|
||||||
|
- %5.2H: hours formatted with width 5 and 2 decimal places (padded with zeros)
|
||||||
"""
|
"""
|
||||||
minute_seconds = 60
|
minute_seconds = 60
|
||||||
hour_seconds = 60 * minute_seconds
|
hour_seconds = 60 * minute_seconds
|
||||||
|
@ -46,18 +48,29 @@ def format_duration(
|
||||||
remainder = seconds = seconds_total
|
remainder = seconds = seconds_total
|
||||||
if "%d" in format_string:
|
if "%d" in format_string:
|
||||||
days, remainder = divmod(seconds_total, day_seconds)
|
days, remainder = divmod(seconds_total, day_seconds)
|
||||||
if "%H" in format_string:
|
if re.search(r"%\d*\.?\d*H", format_string):
|
||||||
hours, remainder = divmod(remainder, hour_seconds)
|
hours_float, remainder = divmod(remainder, hour_seconds)
|
||||||
if "%m" in format_string:
|
hours = float(hours_float) + remainder / hour_seconds
|
||||||
|
if re.search(r"%\d*\.?\d*m", format_string):
|
||||||
minutes, seconds = divmod(remainder, minute_seconds)
|
minutes, seconds = divmod(remainder, minute_seconds)
|
||||||
literals = {
|
literals = {
|
||||||
"%d": str(days),
|
"d": str(days),
|
||||||
"%H": str(hours),
|
"H": str(hours),
|
||||||
"%m": str(minutes),
|
"m": str(minutes),
|
||||||
"%s": str(seconds),
|
"s": str(seconds),
|
||||||
"%r": str(seconds_total),
|
"r": str(seconds_total),
|
||||||
}
|
}
|
||||||
formatted_string = format_string
|
formatted_string = format_string
|
||||||
for pattern, replacement in literals.items():
|
for pattern, replacement in literals.items():
|
||||||
formatted_string = re.sub(pattern, replacement, formatted_string)
|
# Match format specifiers with optional width and precision
|
||||||
|
match = re.search(rf"%(\d*\.?\d*){pattern}", formatted_string)
|
||||||
|
if match:
|
||||||
|
format_spec = match.group(1)
|
||||||
|
if format_spec:
|
||||||
|
# Format the number according to the specifier
|
||||||
|
replacement = f"{float(replacement):{format_spec}f}"
|
||||||
|
# Replace the format specifier with the formatted number
|
||||||
|
formatted_string = re.sub(
|
||||||
|
rf"%\d*\.?\d*{pattern}", replacement, formatted_string
|
||||||
|
)
|
||||||
return formatted_string
|
return formatted_string
|
||||||
|
|
|
@ -114,7 +114,7 @@ class Session(models.Model):
|
||||||
return timedelta(seconds=(manual + calculated).total_seconds())
|
return timedelta(seconds=(manual + calculated).total_seconds())
|
||||||
|
|
||||||
def duration_formatted(self) -> str:
|
def duration_formatted(self) -> str:
|
||||||
result = format_duration(self.duration_seconds(), "%H:%m")
|
result = format_duration(self.duration_seconds(), "%02.0H:%02.0m")
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
|
@ -101,8 +101,8 @@ def view_game(request, game_id=None):
|
||||||
context["sessions"] = Session.objects.filter(
|
context["sessions"] = Session.objects.filter(
|
||||||
purchase__edition__game_id=game_id
|
purchase__edition__game_id=game_id
|
||||||
).order_by("-timestamp_start")
|
).order_by("-timestamp_start")
|
||||||
context["total_hours"] = int(
|
context["total_hours"] = float(
|
||||||
format_duration(context["sessions"].total_duration_unformatted(), "%H")
|
format_duration(context["sessions"].total_duration_unformatted(), "%2.1H")
|
||||||
)
|
)
|
||||||
context["session_average"] = round(
|
context["session_average"] = round(
|
||||||
(context["total_hours"]) / int(context["sessions"].count()), 1
|
(context["total_hours"]) / int(context["sessions"].count()), 1
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "timetracker"
|
name = "timetracker"
|
||||||
version = "1.1.1"
|
version = "1.1.2"
|
||||||
description = "A simple time tracker."
|
description = "A simple time tracker."
|
||||||
authors = ["Lukáš Kucharczyk <lukas@kucharczyk.xyz>"]
|
authors = ["Lukáš Kucharczyk <lukas@kucharczyk.xyz>"]
|
||||||
license = "GPL"
|
license = "GPL"
|
||||||
|
|
Loading…
Reference in New Issue