feat: add "complete" (sic) timezone support
at least for now, this is enough to let admin define the global default timezone for app, and override system local timezone. eventually should support per-user timezone..some day..
This commit is contained in:
parent
286c683c93
commit
7fcb331806
10 changed files with 274 additions and 93 deletions
|
|
@ -11,88 +11,86 @@ from pyramid import testing
|
|||
from sqlalchemy import orm
|
||||
|
||||
from wuttjamaican.conf import WuttaConfig
|
||||
from wuttjamaican.util import get_timezone_by_name
|
||||
from wuttjamaican.testing import DataTestCase
|
||||
from wuttaweb.forms import schema as mod
|
||||
from wuttaweb.forms import widgets
|
||||
from wuttaweb.testing import WebTestCase
|
||||
|
||||
|
||||
class TestWuttaDateTime(TestCase):
|
||||
class TestWuttaDateTime(WebTestCase):
|
||||
|
||||
def test_serialize(self):
|
||||
typ = mod.WuttaDateTime()
|
||||
node = colander.SchemaNode(typ)
|
||||
tzlocal = get_timezone_by_name("America/Los_Angeles")
|
||||
with patch.object(self.app, "get_timezone", return_value=tzlocal):
|
||||
typ = mod.WuttaDateTime()
|
||||
node = colander.SchemaNode(
|
||||
typ, widget=widgets.WuttaDateTimeWidget(self.request)
|
||||
)
|
||||
|
||||
result = typ.serialize(node, colander.null)
|
||||
self.assertIs(result, colander.null)
|
||||
# null
|
||||
self.assertIs(typ.serialize(node, colander.null), colander.null)
|
||||
self.assertIs(typ.serialize(node, None), colander.null)
|
||||
self.assertIs(typ.serialize(node, ""), colander.null)
|
||||
|
||||
result = typ.serialize(node, None)
|
||||
self.assertIs(result, colander.null)
|
||||
# naive, UTC
|
||||
result = typ.serialize(node, datetime.datetime(2024, 12, 11, 22, 33))
|
||||
self.assertEqual(result, "2024-12-11T14:33:00-08:00")
|
||||
|
||||
result = typ.serialize(node, "")
|
||||
self.assertIs(result, colander.null)
|
||||
# aware, UTC
|
||||
result = typ.serialize(
|
||||
node,
|
||||
datetime.datetime(2024, 12, 11, 22, 33, tzinfo=datetime.timezone.utc),
|
||||
)
|
||||
self.assertEqual(result, "2024-12-11T14:33:00-08:00")
|
||||
|
||||
# naive, UTC
|
||||
# TODO: must override local timezone for a complete test
|
||||
result = typ.serialize(node, datetime.datetime(2024, 12, 11, 22, 33))
|
||||
self.assertTrue(result.startswith("2024-12-"))
|
||||
# aware, local
|
||||
result = typ.serialize(
|
||||
node,
|
||||
datetime.datetime(2024, 12, 11, 14, 33, tzinfo=tzlocal),
|
||||
)
|
||||
self.assertEqual(result, "2024-12-11T14:33:00-08:00")
|
||||
|
||||
# aware, UTC
|
||||
result = typ.serialize(
|
||||
node, datetime.datetime(2024, 12, 11, 22, 33, tzinfo=datetime.timezone.utc)
|
||||
)
|
||||
self.assertEqual(result, "2024-12-11T22:33:00+00:00")
|
||||
|
||||
# aware, local
|
||||
result = typ.serialize(
|
||||
node,
|
||||
datetime.datetime(
|
||||
2024,
|
||||
12,
|
||||
11,
|
||||
22,
|
||||
33,
|
||||
tzinfo=datetime.timezone(-datetime.timedelta(hours=5)),
|
||||
),
|
||||
)
|
||||
self.assertEqual(result, "2024-12-11T22:33:00-05:00")
|
||||
|
||||
# custom format
|
||||
typ = mod.WuttaDateTime(format="%Y-%m-%d %I:%M %p")
|
||||
node = colander.SchemaNode(typ)
|
||||
result = typ.serialize(
|
||||
node, datetime.datetime(2024, 12, 11, 22, 33, tzinfo=datetime.timezone.utc)
|
||||
)
|
||||
self.assertEqual(result, "2024-12-11 10:33 PM")
|
||||
# custom format
|
||||
typ = mod.WuttaDateTime(format="%Y-%m-%d %I:%M %p")
|
||||
node = colander.SchemaNode(
|
||||
typ, widget=widgets.WuttaDateTimeWidget(self.request)
|
||||
)
|
||||
result = typ.serialize(
|
||||
node,
|
||||
datetime.datetime(2024, 12, 11, 22, 33, tzinfo=datetime.timezone.utc),
|
||||
)
|
||||
self.assertEqual(result, "2024-12-11 02:33 PM")
|
||||
|
||||
def test_deserialize(self):
|
||||
typ = mod.WuttaDateTime()
|
||||
node = colander.SchemaNode(typ)
|
||||
tzlocal = get_timezone_by_name("America/Los_Angeles")
|
||||
with patch.object(self.app, "get_timezone", return_value=tzlocal):
|
||||
typ = mod.WuttaDateTime()
|
||||
node = colander.SchemaNode(
|
||||
typ, widget=widgets.WuttaDateTimeWidget(self.request)
|
||||
)
|
||||
|
||||
result = typ.deserialize(node, colander.null)
|
||||
self.assertIs(result, colander.null)
|
||||
# null
|
||||
self.assertIs(typ.deserialize(node, colander.null), colander.null)
|
||||
self.assertIs(typ.deserialize(node, None), colander.null)
|
||||
self.assertIs(typ.deserialize(node, ""), colander.null)
|
||||
|
||||
result = typ.deserialize(node, None)
|
||||
self.assertIs(result, colander.null)
|
||||
# format #1
|
||||
result = typ.deserialize(node, "2024-12-11T22:33:00")
|
||||
self.assertIsInstance(result, datetime.datetime)
|
||||
self.assertEqual(
|
||||
result, datetime.datetime(2024, 12, 12, 6, 33, tzinfo=None)
|
||||
)
|
||||
|
||||
result = typ.deserialize(node, "")
|
||||
self.assertIs(result, colander.null)
|
||||
# format #2
|
||||
result = typ.deserialize(node, "2024-12-11T10:33 PM")
|
||||
self.assertIsInstance(result, datetime.datetime)
|
||||
self.assertEqual(
|
||||
result, datetime.datetime(2024, 12, 12, 6, 33, tzinfo=None)
|
||||
)
|
||||
|
||||
# TODO: must override local timezone for a complete test
|
||||
result = typ.deserialize(node, "2024-12-11T10:33 PM")
|
||||
self.assertIsInstance(result, datetime.datetime)
|
||||
dt = datetime.datetime(2024, 12, 11, 22, 33)
|
||||
self.assertLess(abs((result - dt).total_seconds()), 60 * 60 * 24)
|
||||
self.assertIsNone(result.tzinfo)
|
||||
|
||||
# TODO: must override local timezone for a complete test
|
||||
result = typ.deserialize(node, "2024-12-11T22:33:00")
|
||||
self.assertIsInstance(result, datetime.datetime)
|
||||
dt = datetime.datetime(2024, 12, 11, 22, 33)
|
||||
self.assertLess(abs((result - dt).total_seconds()), 60 * 60 * 24)
|
||||
self.assertIsNone(result.tzinfo)
|
||||
|
||||
self.assertRaises(colander.Invalid, typ.deserialize, node, "bogus")
|
||||
# invalid
|
||||
self.assertRaises(colander.Invalid, typ.deserialize, node, "bogus")
|
||||
|
||||
|
||||
class TestObjectNode(DataTestCase):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue