Skip to content

Commit 11786ad

Browse files
authored
Merge pull request #80 from mithun2003/main
Refactor datetime.utcnow() to datetime.now(timezone.utc)
2 parents d4e8775 + eac5289 commit 11786ad

File tree

11 files changed

+33
-32
lines changed

11 files changed

+33
-32
lines changed

README.md

Lines changed: 1 addition & 1 deletion
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.utcnow()` 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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import uuid as uuid_pkg
2-
from datetime import datetime
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.utcnow, server_default=text("current_timestamp(0)"))
12-
updated_at: datetime = Column(DateTime, nullable=True, onupdate=datetime.utcnow, 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

Lines changed: 2 additions & 2 deletions
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
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=datetime.utcnow)
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

Lines changed: 5 additions & 5 deletions
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
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.utcnow() + expires_delta
44+
expire = datetime.now(UTC).replace(tzinfo=None) + expires_delta
4545
else:
46-
expire = datetime.utcnow() + 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.utcnow() + expires_delta
54+
expire = datetime.now(UTC).replace(tzinfo=None) + expires_delta
5555
else:
56-
expire = datetime.utcnow() + 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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from datetime import datetime
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.utcnow().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

Lines changed: 3 additions & 3 deletions
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
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.utcnow()
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.utcnow()
503+
"deleted_at": datetime.now(UTC)
504504
}
505505
stmt = update(self._model) \
506506
.filter_by(**kwargs) \

src/app/models/post.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
from typing import Optional
12
import uuid as uuid_pkg
2-
from datetime import datetime
3+
from datetime import datetime, UTC
34

45
from sqlalchemy import String, DateTime, ForeignKey
56
from sqlalchemy.orm import Mapped, mapped_column
@@ -21,8 +22,8 @@ class Post(Base):
2122
media_url: Mapped[str | None] = mapped_column(String, default=None)
2223

2324
created_at: Mapped[datetime] = mapped_column(
24-
DateTime, default_factory=datetime.utcnow
25+
DateTime(timezone=True), default_factory=lambda: datetime.now(UTC)
2526
)
26-
updated_at: Mapped[datetime | None] = mapped_column(default=None)
27-
deleted_at: Mapped[datetime | None] = mapped_column(default=None)
27+
updated_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), default=None)
28+
deleted_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), default=None)
2829
is_deleted: Mapped[bool] = mapped_column(default=False, index=True)

src/app/models/rate_limit.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from typing import Optional
2-
from datetime import datetime
2+
from datetime import datetime, UTC
33

44
from sqlalchemy import String, DateTime, ForeignKey, Integer
55
from sqlalchemy.orm import Mapped, mapped_column
@@ -19,6 +19,6 @@ class RateLimit(Base):
1919
period: Mapped[int] = mapped_column(Integer, nullable=False)
2020

2121
created_at: Mapped[datetime] = mapped_column(
22-
DateTime, default_factory=datetime.utcnow
22+
DateTime(timezone=True), default_factory=lambda: datetime.now(UTC)
2323
)
24-
updated_at: Mapped[Optional[datetime]] = mapped_column(default=None)
24+
updated_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), default=None)

src/app/models/tier.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from typing import Optional
2-
from datetime import datetime
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=datetime.utcnow
18+
DateTime(timezone=True), default_factory=lambda: datetime.now(UTC)
1919
)
20-
updated_at: Mapped[Optional[datetime]] = mapped_column(default=None)
20+
updated_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), default=None)

src/app/models/user.py

Lines changed: 4 additions & 4 deletions
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
3+
from datetime import datetime, UTC
44

55
from sqlalchemy import String, DateTime, ForeignKey
66
from sqlalchemy.orm import Mapped, mapped_column
@@ -24,10 +24,10 @@ 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=datetime.utcnow
27+
DateTime(timezone=True), default_factory=lambda: datetime.now(UTC)
2828
)
29-
updated_at: Mapped[Optional[datetime]] = mapped_column(default=None)
30-
deleted_at: Mapped[Optional[datetime]] = mapped_column(default=None)
29+
updated_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), default=None)
30+
deleted_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), default=None)
3131
is_deleted: Mapped[bool] = mapped_column(default=False, index=True)
3232
is_superuser: Mapped[bool] = mapped_column(default=False)
3333

0 commit comments

Comments
 (0)