3
0
Fork 0

feat: add "complete" timezone support

at least for now, this is all we need i think..  if nothing
configured, will fallback to default system local timezone.  or can
configure the default, or alternate(s) as needed.

some day when we drop support for python 3.8, can also remove the
python-dateutil dependency..
This commit is contained in:
Lance Edgar 2025-12-16 21:28:40 -06:00
parent dac91406c7
commit 0ffc72f766
6 changed files with 396 additions and 87 deletions

View file

@ -16,9 +16,10 @@ from mako.template import Template
import wuttjamaican.enum
from wuttjamaican import app as mod
from wuttjamaican.exc import ConfigurationError
from wuttjamaican.progress import ProgressBase
from wuttjamaican.conf import WuttaConfig
from wuttjamaican.util import UNSPECIFIED
from wuttjamaican.util import UNSPECIFIED, get_timezone_by_name
from wuttjamaican.testing import FileTestCase, ConfigTestCase
from wuttjamaican.batch import BatchHandler
@ -426,6 +427,80 @@ app_title = WuttaTest
name = self.app.make_full_name("Fred", "", "Flintstone", "")
self.assertEqual(name, "Fred Flintstone")
def test_get_timezone(self):
# cache is empty at first
self.assertEqual(self.app.timezones, {})
# fetch default system local timezone
# nb. actual value depends on machine where tests run
system = self.app.get_timezone()
self.assertIsInstance(system, datetime.tzinfo)
# cache no longer empty
self.assertEqual(len(self.app.timezones), 1)
self.assertIn("default", self.app.timezones)
self.assertIs(self.app.timezones["default"], system)
# fetch configured default
self.app.timezones.clear() # clear cache
self.config.setdefault("wuttatest.timezone.default", "Africa/Addis_Ababa")
default = self.app.get_timezone()
self.assertIsInstance(default, datetime.tzinfo)
dt = datetime.datetime(2025, 12, 16, 22, 0, tzinfo=default)
self.assertEqual(default.utcoffset(dt), datetime.timedelta(hours=3))
# cache no longer empty
self.assertEqual(len(self.app.timezones), 1)
self.assertIn("default", self.app.timezones)
self.assertIs(self.app.timezones["default"], default)
# fetching again gives cached instance
self.assertIs(self.app.get_timezone(), default)
# fetch configured alternate
self.config.setdefault("wuttatest.timezone.foo", "America/New_York")
foo = self.app.get_timezone("foo")
self.assertIsInstance(foo, datetime.tzinfo)
self.assertIn("foo", self.app.timezones)
self.assertIs(self.app.timezones["foo"], foo)
# error if alternate not configured
self.assertRaises(ConfigurationError, self.app.get_timezone, "bar")
self.assertNotIn("bar", self.app.timezones)
def test_get_timezone_name(self):
# cache is empty at first
self.assertEqual(self.app.timezones, {})
# fetch default system local timezone
# nb. actual value depends on machine where tests run
system = self.app.get_timezone_name()
self.assertIsInstance(system, str)
self.assertLess(0, len(system))
# cache no longer empty
self.assertEqual(len(self.app.timezones), 1)
self.assertIn("default", self.app.timezones)
# fetch configured default
self.app.timezones.clear() # clear cache
self.config.setdefault("wuttatest.timezone.default", "Africa/Addis_Ababa")
default = self.app.get_timezone_name()
# nb. this check won't work for python 3.8
if sys.version_info >= (3, 9):
self.assertEqual(default, "Africa/Addis_Ababa")
# cache no longer empty
self.assertEqual(len(self.app.timezones), 1)
self.assertIn("default", self.app.timezones)
# fetch configured alternate
self.config.setdefault("wuttatest.timezone.foo", "America/New_York")
foo = self.app.get_timezone_name("foo")
# nb. this check won't work for python 3.8
if sys.version_info >= (3, 9):
self.assertEqual(foo, "America/New_York")
self.assertIn("foo", self.app.timezones)
# error if alternate not configured
self.assertRaises(ConfigurationError, self.app.get_timezone_name, "bar")
self.assertNotIn("bar", self.app.timezones)
def test_localtime(self):
dt = self.app.localtime()
self.assertIsInstance(dt, datetime.datetime)
@ -516,15 +591,38 @@ app_title = WuttaTest
self.assertEqual(self.app.render_date(dt), "2024-12-11")
def test_render_datetime(self):
self.assertEqual(self.app.render_datetime(None), "")
tzlocal = get_timezone_by_name("America/Los_Angeles")
with patch.object(self.app, "get_timezone", return_value=tzlocal):
dt = datetime.datetime(2024, 12, 11, 8, 30, tzinfo=datetime.timezone.utc)
self.assertEqual(self.app.render_datetime(dt), "2024-12-11 08:30+0000")
# null value
self.assertEqual(self.app.render_datetime(None), "")
dt = datetime.datetime(2024, 12, 11, 8, 30)
text = self.app.render_datetime(dt)
# TODO: should override local timezone for more complete test
self.assertTrue(text.startswith("2024-12-"))
# naive UTC
dt = datetime.datetime(2024, 12, 17, 1, 12)
self.assertEqual(
self.app.render_datetime(dt, local=True), "2024-12-16 17:12-0800"
)
self.assertEqual(
self.app.render_datetime(dt, local=False), "2024-12-17 01:12"
)
# aware UTC
dt = datetime.datetime(2024, 12, 17, 1, 12, tzinfo=datetime.timezone.utc)
self.assertEqual(
self.app.render_datetime(dt, local=True), "2024-12-16 17:12-0800"
)
self.assertEqual(
self.app.render_datetime(dt, local=False), "2024-12-17 01:12+0000"
)
# aware local
dt = datetime.datetime(2024, 12, 16, 19, 12, tzinfo=tzlocal)
self.assertEqual(
self.app.render_datetime(dt, local=True), "2024-12-16 19:12-0800"
)
self.assertEqual(
self.app.render_datetime(dt, local=False), "2024-12-16 19:12-0800"
)
def test_render_error(self):