feat: drop timezone, assume UTC for all datetime values in DB
i guess it was worth a try, but preserving system timezone was doomed to failure since only postgres actually supports it. from now on all DateTime columns will be naive, but understood / assumed to be UTC-local
This commit is contained in:
parent
900937826c
commit
a5d641d5bc
7 changed files with 201 additions and 21 deletions
|
|
@ -862,7 +862,8 @@ class AppHandler: # pylint: disable=too-many-public-methods
|
|||
|
||||
:returns: Text to display.
|
||||
"""
|
||||
return humanize.naturaltime(value)
|
||||
# TODO: this now assumes naive UTC value incoming...
|
||||
return humanize.naturaltime(value, when=self.make_utc(tzinfo=False))
|
||||
|
||||
##############################
|
||||
# getters for other handlers
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@
|
|||
Batch Handlers
|
||||
"""
|
||||
|
||||
import datetime
|
||||
import os
|
||||
import shutil
|
||||
|
||||
|
|
@ -481,7 +480,7 @@ class BatchHandler(GenericHandler): # pylint: disable=too-many-public-methods
|
|||
result = self.execute( # pylint: disable=assignment-from-none
|
||||
batch, user=user, progress=progress, **kwargs
|
||||
)
|
||||
batch.executed = datetime.datetime.now()
|
||||
batch.executed = self.app.make_utc()
|
||||
batch.executed_by = user
|
||||
return result
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,186 @@
|
|||
"""drop time zones
|
||||
|
||||
Revision ID: b59a34266288
|
||||
Revises: efdcb2c75034
|
||||
Create Date: 2025-12-14 19:10:11.627188
|
||||
|
||||
"""
|
||||
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
import wuttjamaican.db.util
|
||||
from sqlalchemy.dialects import postgresql
|
||||
from wuttjamaican.util import make_utc
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = "b59a34266288"
|
||||
down_revision: Union[str, None] = "efdcb2c75034"
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
|
||||
# upgrade.created
|
||||
op.add_column("upgrade", sa.Column("created_new", sa.DateTime(), nullable=True))
|
||||
upgrade = sa.sql.table(
|
||||
"upgrade",
|
||||
sa.sql.column("uuid"),
|
||||
sa.sql.column("created"),
|
||||
sa.sql.column("created_new"),
|
||||
)
|
||||
cursor = op.get_bind().execute(upgrade.select())
|
||||
for row in cursor.fetchall():
|
||||
op.get_bind().execute(
|
||||
upgrade.update()
|
||||
.where(upgrade.c.uuid == row.uuid)
|
||||
.values({"created_new": make_utc(row.created)})
|
||||
)
|
||||
op.drop_column("upgrade", "created")
|
||||
op.alter_column(
|
||||
"upgrade",
|
||||
"created_new",
|
||||
new_column_name="created",
|
||||
nullable=False,
|
||||
existing_type=sa.DateTime(),
|
||||
existing_nullable=True,
|
||||
)
|
||||
|
||||
# upgrade.executed
|
||||
op.add_column("upgrade", sa.Column("executed_new", sa.DateTime(), nullable=True))
|
||||
upgrade = sa.sql.table(
|
||||
"upgrade",
|
||||
sa.sql.column("uuid"),
|
||||
sa.sql.column("executed"),
|
||||
sa.sql.column("executed_new"),
|
||||
)
|
||||
cursor = op.get_bind().execute(upgrade.select())
|
||||
for row in cursor.fetchall():
|
||||
if row.executed:
|
||||
op.get_bind().execute(
|
||||
upgrade.update()
|
||||
.where(upgrade.c.uuid == row.uuid)
|
||||
.values({"executed_new": make_utc(row.executed)})
|
||||
)
|
||||
op.drop_column("upgrade", "executed")
|
||||
op.alter_column(
|
||||
"upgrade",
|
||||
"executed_new",
|
||||
new_column_name="executed",
|
||||
existing_type=sa.DateTime(),
|
||||
existing_nullable=True,
|
||||
)
|
||||
|
||||
# user_api_token.created
|
||||
op.add_column(
|
||||
"user_api_token", sa.Column("created_new", sa.DateTime(), nullable=True)
|
||||
)
|
||||
user_api_token = sa.sql.table(
|
||||
"user_api_token",
|
||||
sa.sql.column("uuid"),
|
||||
sa.sql.column("created"),
|
||||
sa.sql.column("created_new"),
|
||||
)
|
||||
cursor = op.get_bind().execute(user_api_token.select())
|
||||
for row in cursor.fetchall():
|
||||
op.get_bind().execute(
|
||||
user_api_token.update()
|
||||
.where(user_api_token.c.uuid == row.uuid)
|
||||
.values({"created_new": make_utc(row.created)})
|
||||
)
|
||||
op.drop_column("user_api_token", "created")
|
||||
op.alter_column(
|
||||
"user_api_token",
|
||||
"created_new",
|
||||
new_column_name="created",
|
||||
nullable=False,
|
||||
existing_type=sa.DateTime(),
|
||||
existing_nullable=True,
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
|
||||
# user_api_token.created
|
||||
op.add_column(
|
||||
"user_api_token",
|
||||
sa.Column("created_old", sa.DateTime(timezone=True), nullable=True),
|
||||
)
|
||||
user_api_token = sa.sql.table(
|
||||
"user_api_token",
|
||||
sa.sql.column("uuid"),
|
||||
sa.sql.column("created"),
|
||||
sa.sql.column("created_old"),
|
||||
)
|
||||
cursor = op.get_bind().execute(user_api_token.select())
|
||||
for row in cursor.fetchall():
|
||||
op.get_bind().execute(
|
||||
user_api_token.update()
|
||||
.where(user_api_token.c.uuid == row.uuid)
|
||||
.values({"created_old": row.created})
|
||||
)
|
||||
op.drop_column("user_api_token", "created")
|
||||
op.alter_column(
|
||||
"user_api_token",
|
||||
"created_old",
|
||||
new_column_name="created",
|
||||
nullable=False,
|
||||
existing_type=sa.DateTime(timezone=True),
|
||||
existing_nullable=True,
|
||||
)
|
||||
|
||||
# upgrade.executed
|
||||
op.add_column(
|
||||
"upgrade", sa.Column("executed_old", sa.DateTime(timezone=True), nullable=True)
|
||||
)
|
||||
upgrade = sa.sql.table(
|
||||
"upgrade",
|
||||
sa.sql.column("uuid"),
|
||||
sa.sql.column("executed"),
|
||||
sa.sql.column("executed_old"),
|
||||
)
|
||||
cursor = op.get_bind().execute(upgrade.select())
|
||||
for row in cursor.fetchall():
|
||||
if row.executed:
|
||||
op.get_bind().execute(
|
||||
upgrade.update()
|
||||
.where(upgrade.c.uuid == row.uuid)
|
||||
.values({"executed_old": row.executed})
|
||||
)
|
||||
op.drop_column("upgrade", "executed")
|
||||
op.alter_column(
|
||||
"upgrade",
|
||||
"executed_old",
|
||||
new_column_name="executed",
|
||||
existing_type=sa.DateTime(timezone=True),
|
||||
existing_nullable=True,
|
||||
)
|
||||
|
||||
# upgrade.created
|
||||
op.add_column(
|
||||
"upgrade", sa.Column("created_old", sa.DateTime(timezone=True), nullable=True)
|
||||
)
|
||||
upgrade = sa.sql.table(
|
||||
"upgrade",
|
||||
sa.sql.column("uuid"),
|
||||
sa.sql.column("created"),
|
||||
sa.sql.column("created_old"),
|
||||
)
|
||||
cursor = op.get_bind().execute(upgrade.select())
|
||||
for row in cursor.fetchall():
|
||||
op.get_bind().execute(
|
||||
upgrade.update()
|
||||
.where(upgrade.c.uuid == row.uuid)
|
||||
.values({"created_old": row.created})
|
||||
)
|
||||
op.drop_column("upgrade", "created")
|
||||
op.alter_column(
|
||||
"upgrade",
|
||||
"created_old",
|
||||
new_column_name="created",
|
||||
nullable=False,
|
||||
existing_type=sa.DateTime(timezone=True),
|
||||
existing_nullable=True,
|
||||
)
|
||||
|
|
@ -39,14 +39,13 @@ So a user's permissions are "inherited" from the role(s) to which they
|
|||
belong.
|
||||
"""
|
||||
|
||||
import datetime
|
||||
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy import orm
|
||||
from sqlalchemy.ext.associationproxy import association_proxy
|
||||
|
||||
from wuttjamaican.db.util import uuid_column, uuid_fk_column
|
||||
from wuttjamaican.db.model.base import Base
|
||||
from wuttjamaican.util import make_utc
|
||||
|
||||
|
||||
class Role(Base): # pylint: disable=too-few-public-methods
|
||||
|
|
@ -343,9 +342,9 @@ class UserAPIToken(Base): # pylint: disable=too-few-public-methods
|
|||
)
|
||||
|
||||
created = sa.Column(
|
||||
sa.DateTime(timezone=True),
|
||||
sa.DateTime(),
|
||||
nullable=False,
|
||||
default=datetime.datetime.now,
|
||||
default=make_utc,
|
||||
doc="""
|
||||
Date/time when the token was created.
|
||||
""",
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ from sqlalchemy.ext.orderinglist import ordering_list
|
|||
from wuttjamaican.db.model.base import uuid_column
|
||||
from wuttjamaican.db.model.auth import User
|
||||
from wuttjamaican.db.util import UUID
|
||||
from wuttjamaican.util import make_utc
|
||||
|
||||
|
||||
class BatchMixin:
|
||||
|
|
@ -223,9 +224,7 @@ class BatchMixin:
|
|||
status_code = sa.Column(sa.Integer(), nullable=True)
|
||||
status_text = sa.Column(sa.String(length=255), nullable=True)
|
||||
|
||||
created = sa.Column(
|
||||
sa.DateTime(timezone=True), nullable=False, default=datetime.datetime.now
|
||||
)
|
||||
created = sa.Column(sa.DateTime(), nullable=False, default=make_utc)
|
||||
created_by_uuid = sa.Column(UUID(), nullable=False)
|
||||
|
||||
@declared_attr
|
||||
|
|
@ -238,7 +237,7 @@ class BatchMixin:
|
|||
cascade_backrefs=False,
|
||||
)
|
||||
|
||||
executed = sa.Column(sa.DateTime(timezone=True), nullable=True)
|
||||
executed = sa.Column(sa.DateTime(), nullable=True)
|
||||
executed_by_uuid = sa.Column(UUID(), nullable=True)
|
||||
|
||||
@declared_attr
|
||||
|
|
@ -428,8 +427,5 @@ class BatchRowMixin: # pylint: disable=too-few-public-methods
|
|||
status_text = sa.Column(sa.String(length=255), nullable=True)
|
||||
|
||||
modified = sa.Column(
|
||||
sa.DateTime(timezone=True),
|
||||
nullable=True,
|
||||
default=datetime.datetime.now,
|
||||
onupdate=datetime.datetime.now,
|
||||
sa.DateTime(), nullable=True, default=make_utc, onupdate=make_utc
|
||||
)
|
||||
|
|
|
|||
|
|
@ -24,14 +24,13 @@
|
|||
Upgrade Model
|
||||
"""
|
||||
|
||||
import datetime
|
||||
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy import orm
|
||||
|
||||
from wuttjamaican.enum import UpgradeStatus
|
||||
from wuttjamaican.db.util import uuid_column, uuid_fk_column
|
||||
from wuttjamaican.db.model.base import Base
|
||||
from wuttjamaican.util import make_utc
|
||||
|
||||
|
||||
class Upgrade(Base): # pylint: disable=too-few-public-methods
|
||||
|
|
@ -44,9 +43,9 @@ class Upgrade(Base): # pylint: disable=too-few-public-methods
|
|||
uuid = uuid_column()
|
||||
|
||||
created = sa.Column(
|
||||
sa.DateTime(timezone=True),
|
||||
sa.DateTime(),
|
||||
nullable=False,
|
||||
default=datetime.datetime.now,
|
||||
default=make_utc,
|
||||
doc="""
|
||||
When the upgrade record was created.
|
||||
""",
|
||||
|
|
@ -98,7 +97,7 @@ class Upgrade(Base): # pylint: disable=too-few-public-methods
|
|||
)
|
||||
|
||||
executed = sa.Column(
|
||||
sa.DateTime(timezone=True),
|
||||
sa.DateTime(),
|
||||
nullable=True,
|
||||
doc="""
|
||||
When the upgrade was executed.
|
||||
|
|
|
|||
|
|
@ -571,7 +571,7 @@ app_title = WuttaTest
|
|||
now = datetime.datetime.now()
|
||||
result = self.app.render_time_ago(now)
|
||||
self.assertEqual(result, "now")
|
||||
humanize.naturaltime.assert_called_once_with(now)
|
||||
humanize.naturaltime.assert_called_once()
|
||||
|
||||
def test_get_person(self):
|
||||
people = self.app.get_people_handler()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue