40 lines
1.3 KiB
Python
40 lines
1.3 KiB
Python
"""
|
|
core/tz.py - Timezone-aware date/time helpers
|
|
|
|
The frontend sends X-Timezone-Offset (minutes from UTC, same sign as
|
|
JavaScript's getTimezoneOffset — positive means behind UTC).
|
|
These helpers convert server UTC to the user's local date/time.
|
|
"""
|
|
|
|
from datetime import datetime, date, timezone, timedelta
|
|
|
|
|
|
def _get_offset_minutes():
|
|
"""Read the timezone offset header from the current Flask request.
|
|
Returns 0 if outside a request context or header is absent."""
|
|
try:
|
|
import flask
|
|
return int(flask.request.headers.get("X-Timezone-Offset", 0))
|
|
except (ValueError, TypeError, RuntimeError):
|
|
# RuntimeError: outside of request context
|
|
return 0
|
|
|
|
|
|
def _offset_to_tz(offset_minutes):
|
|
"""Convert JS-style offset (positive = behind UTC) to a timezone object."""
|
|
return timezone(timedelta(minutes=-offset_minutes))
|
|
|
|
|
|
def user_now(offset_minutes=None):
|
|
"""Current datetime in the user's timezone.
|
|
If offset_minutes is provided, uses that instead of the request header."""
|
|
if offset_minutes is None:
|
|
offset_minutes = _get_offset_minutes()
|
|
tz = _offset_to_tz(offset_minutes)
|
|
return datetime.now(tz)
|
|
|
|
|
|
def user_today(offset_minutes=None):
|
|
"""Current date in the user's timezone."""
|
|
return user_now(offset_minutes).date()
|