mirror of
https://gitlab.archlinux.org/archlinux/aurweb.git
synced 2025-02-03 10:43:03 +01:00
add aurweb.time module
This module includes timezone-based utilities for a FastAPI request. This commit introduces use of the AURTZ cookie within get_request_timezone. This cookie should be set to the user or session's timezone. * `make_context` has been modified to parse the request's timezone and include the "timezone" and "timezones" variables, along with a timezone specified "now" date. + Added `Timezone` attribute to aurweb.testing.requests.Request.user. Signed-off-by: Kevin Morris <kevr@0cost.org>
This commit is contained in:
parent
07d5907ecd
commit
9052688ed2
4 changed files with 104 additions and 4 deletions
|
@ -1,5 +1,6 @@
|
|||
import copy
|
||||
import os
|
||||
import zoneinfo
|
||||
|
||||
from datetime import datetime
|
||||
from http import HTTPStatus
|
||||
|
@ -11,7 +12,7 @@ from fastapi.responses import HTMLResponse
|
|||
|
||||
import aurweb.config
|
||||
|
||||
from aurweb import l10n
|
||||
from aurweb import l10n, time
|
||||
|
||||
# Prepare jinja2 objects.
|
||||
loader = jinja2.FileSystemLoader(os.path.join(
|
||||
|
@ -26,14 +27,15 @@ env.filters["tr"] = l10n.tr
|
|||
def make_context(request: Request, title: str, next: str = None):
|
||||
""" Create a context for a jinja2 TemplateResponse. """
|
||||
|
||||
timezone = time.get_request_timezone(request)
|
||||
return {
|
||||
"request": request,
|
||||
"language": l10n.get_request_language(request),
|
||||
"languages": l10n.SUPPORTED_LANGUAGES,
|
||||
"timezone": timezone,
|
||||
"timezones": time.SUPPORTED_TIMEZONES,
|
||||
"title": title,
|
||||
# The 'now' context variable will not show proper datetimes
|
||||
# until we've implemented timezone support here.
|
||||
"now": datetime.now(),
|
||||
"now": datetime.now(tz=zoneinfo.ZoneInfo(timezone)),
|
||||
"config": aurweb.config,
|
||||
"next": next if next else request.url.path
|
||||
}
|
||||
|
@ -60,4 +62,5 @@ def render_template(request: Request,
|
|||
|
||||
response = HTMLResponse(rendered, status_code=status_code)
|
||||
response.set_cookie("AURLANG", context.get("language"))
|
||||
response.set_cookie("AURTZ", context.get("timezone"))
|
||||
return response
|
||||
|
|
|
@ -5,6 +5,7 @@ class User:
|
|||
""" A fake User model. """
|
||||
# Fake columns.
|
||||
LangPreference = aurweb.config.get("options", "default_lang")
|
||||
Timezone = aurweb.config.get("options", "default_timezone")
|
||||
|
||||
# A fake authenticated flag.
|
||||
authenticated = False
|
||||
|
|
63
aurweb/time.py
Normal file
63
aurweb/time.py
Normal file
|
@ -0,0 +1,63 @@
|
|||
import zoneinfo
|
||||
|
||||
from collections import OrderedDict
|
||||
from datetime import datetime
|
||||
|
||||
from fastapi import Request
|
||||
|
||||
import aurweb.config
|
||||
|
||||
|
||||
def tz_offset(name: str):
|
||||
""" Get a timezone offset in the form "+00:00" by its name.
|
||||
|
||||
Example: tz_offset('America/Los_Angeles')
|
||||
|
||||
:param name: Timezone name
|
||||
:return: UTC offset in the form "+00:00"
|
||||
"""
|
||||
dt = datetime.now(tz=zoneinfo.ZoneInfo(name))
|
||||
|
||||
# Our offset in hours.
|
||||
offset = dt.utcoffset().total_seconds() / 60 / 60
|
||||
|
||||
# Prefix the offset string with a - or +.
|
||||
offset_string = '-' if offset < 0 else '+'
|
||||
|
||||
# Remove any negativity from the offset. We want a good offset. :)
|
||||
offset = abs(offset)
|
||||
|
||||
# Truncate the floating point digits, giving the hours.
|
||||
hours = int(offset)
|
||||
|
||||
# Subtract hours from the offset, and multiply the remaining fraction
|
||||
# (0 - 0.99[repeated]) with 60 minutes to get the number of minutes
|
||||
# remaining in the hour.
|
||||
minutes = int((offset - hours) * 60)
|
||||
|
||||
# Pad the hours and minutes by two places.
|
||||
offset_string += "{:0>2}:{:0>2}".format(hours, minutes)
|
||||
return offset_string
|
||||
|
||||
|
||||
SUPPORTED_TIMEZONES = OrderedDict({
|
||||
# Flatten out the list of tuples into an OrderedDict.
|
||||
timezone: offset for timezone, offset in sorted([
|
||||
# Comprehend a list of tuples (timezone, offset display string)
|
||||
# and sort them by (offset, timezone).
|
||||
(tz, "(UTC%s) %s" % (tz_offset(tz), tz))
|
||||
for tz in zoneinfo.available_timezones()
|
||||
], key=lambda element: (tz_offset(element[0]), element[0]))
|
||||
})
|
||||
|
||||
|
||||
def get_request_timezone(request: Request):
|
||||
""" Get a request's timezone by its AURTZ cookie. We use the
|
||||
configuration's [options] default_timezone otherwise.
|
||||
|
||||
@param request FastAPI request
|
||||
"""
|
||||
if request.user.is_authenticated():
|
||||
return request.user.Timezone
|
||||
default_tz = aurweb.config.get("options", "default_timezone")
|
||||
return request.cookies.get("AURTZ", default_tz)
|
33
test/test_time.py
Normal file
33
test/test_time.py
Normal file
|
@ -0,0 +1,33 @@
|
|||
import aurweb.config
|
||||
|
||||
from aurweb.testing.requests import Request
|
||||
from aurweb.time import get_request_timezone, tz_offset
|
||||
|
||||
|
||||
def test_tz_offset_utc():
|
||||
offset = tz_offset("UTC")
|
||||
assert offset == "+00:00"
|
||||
|
||||
|
||||
def test_tz_offset_mst():
|
||||
offset = tz_offset("MST")
|
||||
assert offset == "-07:00"
|
||||
|
||||
|
||||
def test_request_timezone():
|
||||
request = Request()
|
||||
tz = get_request_timezone(request)
|
||||
assert tz == aurweb.config.get("options", "default_timezone")
|
||||
|
||||
|
||||
def test_authenticated_request_timezone():
|
||||
# Modify a fake request to be authenticated with the
|
||||
# America/Los_Angeles timezone.
|
||||
request = Request()
|
||||
request.user.authenticated = True
|
||||
request.user.Timezone = "America/Los_Angeles"
|
||||
|
||||
# Get the request's timezone, it should be America/Los_Angeles.
|
||||
tz = get_request_timezone(request)
|
||||
assert tz == request.user.Timezone
|
||||
assert tz == "America/Los_Angeles"
|
Loading…
Add table
Reference in a new issue