3
0
Fork 0

feat: add make_utc() function, app method

as prep for dropping timezone from DB columns
This commit is contained in:
Lance Edgar 2025-12-15 13:06:40 -06:00
parent 1a3756f47c
commit 900937826c
4 changed files with 107 additions and 0 deletions

View file

@ -39,6 +39,7 @@ from wuttjamaican.util import (
load_object,
make_title,
make_full_name,
make_utc,
make_uuid,
make_true_uuid,
progress_loop,
@ -526,6 +527,14 @@ class AppHandler: # pylint: disable=too-many-public-methods
"""
return make_full_name(*parts)
def make_utc(self, dt=None, tzinfo=False):
"""
This returns a datetime local to the UTC timezone. It is a
convenience wrapper around
:func:`~wuttjamaican.util.make_utc()`.
"""
return make_utc(dt=dt, tzinfo=tzinfo)
def make_true_uuid(self):
"""
Generate a new UUID value.

View file

@ -24,6 +24,7 @@
WuttJamaican - utilities
"""
import datetime
import importlib
import logging
import os
@ -189,6 +190,50 @@ def make_full_name(*parts):
return " ".join(parts)
def make_utc(dt=None, tzinfo=False):
"""
This returns a datetime local to the UTC timezone. By default it
will be a *naive* datetime; the common use case is to convert as
needed for sake of writing to the database.
See also the shortcut
:meth:`~wuttjamaican.app.AppHandler.make_utc()` method on the app
handler.
:param dt: Optional :class:`python:datetime.datetime` instance.
If not specified, the current time will be used.
:param tzinfo: Boolean indicating whether the return value should
have its :attr:`~python:datetime.datetime.tzinfo` attribute
set. This is false by default in which case the return value
will be naive.
:returns: :class:`python:datetime.datetime` instance local to UTC.
"""
# use current time if none provided
if dt is None:
now = datetime.datetime.now(datetime.timezone.utc)
if tzinfo:
return now
return now.replace(tzinfo=None)
# otherwise may need to convert timezone
if dt.tzinfo:
if dt.tzinfo is not datetime.timezone.utc:
dt = dt.astimezone(datetime.timezone.utc)
if tzinfo:
return dt
return dt.replace(tzinfo=None)
# naive value returned as-is..
if not tzinfo:
return dt
# ..unless tzinfo is wanted, in which case this assumes naive
# value is in the UTC timezone
return dt.replace(tzinfo=datetime.timezone.utc)
def make_true_uuid():
"""
Generate a new v7 UUID value.

View file

@ -426,6 +426,11 @@ app_title = WuttaTest
name = self.app.make_full_name("Fred", "", "Flintstone", "")
self.assertEqual(name, "Fred Flintstone")
def test_make_utc(self):
dt = self.app.make_utc()
self.assertIsInstance(dt, datetime.datetime)
self.assertIsNone(dt.tzinfo)
def test_make_uuid(self):
uuid = self.app.make_uuid()
self.assertEqual(len(uuid), 32)

View file

@ -1,5 +1,6 @@
# -*- coding: utf-8; -*-
import datetime
import sys
from unittest import TestCase
from unittest.mock import patch, MagicMock
@ -164,6 +165,53 @@ class TestLoadObject(TestCase):
self.assertIs(result, TestCase)
class TestMakeUTC(TestCase):
def test_current_time(self):
# no tzinfo by default
dt = mod.make_utc()
self.assertIsInstance(dt, datetime.datetime)
self.assertIsNone(dt.tzinfo)
now = datetime.datetime.now(datetime.timezone.utc).replace(tzinfo=None)
self.assertAlmostEqual(int(dt.timestamp()), int(now.timestamp()))
# with tzinfo
dt = mod.make_utc(tzinfo=True)
self.assertIsInstance(dt, datetime.datetime)
self.assertIs(dt.tzinfo, datetime.timezone.utc)
now = datetime.datetime.now(datetime.timezone.utc)
self.assertAlmostEqual(int(dt.timestamp()), int(now.timestamp()))
def test_convert_with_tzinfo(self):
sample = datetime.datetime(
2024, 9, 15, 8, 30, tzinfo=datetime.timezone(-datetime.timedelta(hours=5))
)
# no tzinfo by default
dt = mod.make_utc(sample)
self.assertEqual(dt, datetime.datetime(2024, 9, 15, 13, 30, tzinfo=None))
# with tzinfo
dt = mod.make_utc(sample, tzinfo=True)
self.assertEqual(
dt, datetime.datetime(2024, 9, 15, 13, 30, tzinfo=datetime.timezone.utc)
)
def test_convert_without_tzinfo(self):
sample = datetime.datetime(2024, 9, 15, 8, 30)
# no tzinfo by default
dt = mod.make_utc(sample)
self.assertEqual(dt, datetime.datetime(2024, 9, 15, 8, 30, tzinfo=None))
# with tzinfo
dt = mod.make_utc(sample, tzinfo=True)
self.assertEqual(
dt, datetime.datetime(2024, 9, 15, 8, 30, tzinfo=datetime.timezone.utc)
)
class TestMakeUUID(TestCase):
def test_basic(self):