Skip to content

Commit de90dae

Browse files
author
Mithun Thomas
committed
Refactor datetime handling to use UTC throughout
the application Update datetime handling across the application to consistently utilize UTC, ensuring uniformity and eliminating potential discrepancies due to time zone differences.
1 parent a81db5c commit de90dae

File tree

9 files changed

+22
-22
lines changed

9 files changed

+22
-22
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -734,7 +734,7 @@ crud_users.update(db=db, object={name="Updated Name"}, username="myusername")
734734
To delete we have two options:
735735
- db_delete: actually deletes the row from the database
736736
- delete:
737-
- adds `"is_deleted": True` and `deleted_at: datetime.now(timezone.utc)` if the model inherits from `PersistentDeletion` (performs a soft delete), but keeps the object in the database.
737+
- adds `"is_deleted": True` and `deleted_at: datetime.now(UTC)` if the model inherits from `PersistentDeletion` (performs a soft delete), but keeps the object in the database.
738738
- actually deletes the row from the database if the model does not inherit from `PersistentDeletion`
739739

740740
```python

src/app/core/db/models.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import uuid as uuid_pkg
2-
from datetime import datetime, timezone
2+
from datetime import datetime, UTC
33
from sqlalchemy import Column, DateTime, Boolean, text
44
from sqlalchemy.dialects.postgresql import UUID
55

@@ -8,8 +8,8 @@ class UUIDMixin:
88

99

1010
class TimestampMixin:
11-
created_at: datetime = Column(DateTime, default=datetime.now(timezone.utc), server_default=text("current_timestamp(0)"))
12-
updated_at: datetime = Column(DateTime, nullable=True, onupdate=datetime.now(timezone.utc), server_default=text("current_timestamp(0)"))
11+
created_at: datetime = Column(DateTime, default=datetime.now(UTC), server_default=text("current_timestamp(0)"))
12+
updated_at: datetime = Column(DateTime, nullable=True, onupdate=datetime.now(UTC), server_default=text("current_timestamp(0)"))
1313

1414

1515
class SoftDeleteMixin:

src/app/core/schemas.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from typing import Any
22
import uuid as uuid_pkg
3-
from datetime import datetime, timezone
3+
from datetime import datetime, UTC
44

55
from pydantic import BaseModel, Field, field_serializer
66

@@ -15,7 +15,7 @@ class UUIDSchema(BaseModel):
1515

1616

1717
class TimestampSchema(BaseModel):
18-
created_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc).replace(tzinfo=None))
18+
created_at: datetime = Field(default_factory=lambda: datetime.now(UTC).replace(tzinfo=None))
1919
updated_at: datetime = Field(default=None)
2020

2121
@field_serializer("created_at")

src/app/core/security.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from typing import Union, Literal, Dict, Any
2-
from datetime import datetime, timedelta, timezone
2+
from datetime import datetime, timedelta, UTC
33

44
import bcrypt
55
from sqlalchemy.ext.asyncio import AsyncSession
@@ -41,19 +41,19 @@ async def authenticate_user(username_or_email: str, password: str, db: AsyncSess
4141
async def create_access_token(data: dict[str, Any], expires_delta: timedelta | None = None) -> str:
4242
to_encode = data.copy()
4343
if expires_delta:
44-
expire = datetime.now(timezone.utc) + expires_delta
44+
expire = datetime.now(UTC).replace(tzinfo=None) + expires_delta
4545
else:
46-
expire = datetime.now(timezone.utc) + timedelta(minutes=15)
46+
expire = datetime.now(UTC).replace(tzinfo=None) + timedelta(minutes=15)
4747
to_encode.update({"exp": expire})
4848
encoded_jwt: str = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
4949
return encoded_jwt
5050

5151
async def create_refresh_token(data: dict[str, Any], expires_delta: timedelta | None = None) -> str:
5252
to_encode = data.copy()
5353
if expires_delta:
54-
expire = datetime.now(timezone.utc) + expires_delta
54+
expire = datetime.now(UTC).replace(tzinfo=None) + expires_delta
5555
else:
56-
expire = datetime.now(timezone.utc) + timedelta(days=REFRESH_TOKEN_EXPIRE_DAYS)
56+
expire = datetime.now(UTC).replace(tzinfo=None) + timedelta(days=REFRESH_TOKEN_EXPIRE_DAYS)
5757
to_encode.update({"exp": expire})
5858
encoded_jwt: str = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
5959
return encoded_jwt

src/app/core/utils/rate_limit.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from datetime import datetime, timezone
1+
from datetime import datetime, UTC
22

33
from redis.asyncio import Redis, ConnectionPool
44
from sqlalchemy.ext.asyncio import AsyncSession
@@ -22,7 +22,7 @@ async def is_rate_limited(
2222
logger.error("Redis client is not initialized.")
2323
raise Exception("Redis client is not initialized.")
2424

25-
current_timestamp = int(datetime.now(timezone.utc).timestamp())
25+
current_timestamp = int(datetime.now(UTC).timestamp())
2626
window_start = current_timestamp - (current_timestamp % period)
2727

2828
sanitized_path = sanitize_path(path)

src/app/crud/crud_base.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from typing import Any, Dict, Generic, List, Type, TypeVar, Union
2-
from datetime import datetime, timezone
2+
from datetime import datetime, UTC
33

44
from pydantic import BaseModel
55
from sqlalchemy import select, update, delete, func, and_, inspect
@@ -441,7 +441,7 @@ async def update(
441441
update_data = object.model_dump(exclude_unset=True)
442442

443443
if "updated_at" in update_data.keys():
444-
update_data["updated_at"] = datetime.now(timezone.utc)
444+
update_data["updated_at"] = datetime.now(UTC)
445445

446446
stmt = update(self._model) \
447447
.filter_by(**kwargs) \
@@ -500,7 +500,7 @@ async def delete(
500500
if "is_deleted" in self._model.__table__.columns:
501501
object_dict = {
502502
"is_deleted": True,
503-
"deleted_at": datetime.now(timezone.utc)
503+
"deleted_at": datetime.now(UTC)
504504
}
505505
stmt = update(self._model) \
506506
.filter_by(**kwargs) \

src/app/models/tier.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from typing import Optional
2-
from datetime import datetime, timezone
2+
from datetime import datetime, UTC
33

44
from sqlalchemy import String, DateTime
55
from sqlalchemy.orm import Mapped, mapped_column
@@ -15,6 +15,6 @@ class Tier(Base):
1515
name: Mapped[str] = mapped_column(String, nullable=False, unique=True)
1616

1717
created_at: Mapped[datetime] = mapped_column(
18-
DateTime, default_factory=lambda: datetime.now(timezone.utc).replace(tzinfo=None)
18+
DateTime, default_factory=lambda: datetime.now(UTC).replace(tzinfo=None)
1919
)
2020
updated_at: Mapped[Optional[datetime]] = mapped_column(default=None)

src/app/models/user.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from typing import Optional
22
import uuid as uuid_pkg
3-
from datetime import datetime, timezone
3+
from datetime import datetime, UTC
44

55
from sqlalchemy import String, DateTime, ForeignKey
66
from sqlalchemy.orm import Mapped, mapped_column
@@ -24,7 +24,7 @@ class User(Base):
2424
default_factory=uuid_pkg.uuid4, primary_key=True, unique=True
2525
)
2626
created_at: Mapped[datetime] = mapped_column(
27-
DateTime, default_factory=lambda: datetime.now(timezone.utc).replace(tzinfo=None)
27+
DateTime, default_factory=lambda: datetime.now(UTC).replace(tzinfo=None)
2828
)
2929
updated_at: Mapped[Optional[datetime]] = mapped_column(default=None)
3030
deleted_at: Mapped[Optional[datetime]] = mapped_column(default=None)

src/scripts/create_first_superuser.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
)
1414
from sqlalchemy.dialects.postgresql import UUID
1515
import uuid
16-
from datetime import datetime, timezone
16+
from datetime import datetime, UTC
1717

1818
from ..app.core.db.database import async_engine
1919
from ..app.core.db.database import AsyncSession, local_session
@@ -42,7 +42,7 @@ async def create_first_user(session: AsyncSession) -> None:
4242
Column("hashed_password", String, nullable=False),
4343
Column("profile_image_url", String, default="https://profileimageurl.com"),
4444
Column("uuid", UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, unique=True),
45-
Column("created_at", DateTime, default=lambda: datetime.now(timezone.utc).replace(tzinfo=None), nullable=False),
45+
Column("created_at", DateTime, default=lambda: datetime.now(UTC).replace(tzinfo=None), nullable=False),
4646
Column("updated_at", DateTime),
4747
Column("deleted_at", DateTime),
4848
Column("is_deleted", Boolean, default=False, index=True),

0 commit comments

Comments
 (0)