fix: convert utcnow() to timezone aware now(UTC).replace(tzinfo=None)#323
fix: convert utcnow() to timezone aware now(UTC).replace(tzinfo=None)#323nicolapace wants to merge 1 commit intorq:masterfrom
Conversation
Flix6x
left a comment
There was a problem hiding this comment.
This would be helpful and indeed would get rid of the warnings.
|
I was thinking of updating the change with something similar to what is show here: boto/botocore#3239, ensuring datetime instances are still timezone-unaware. |
There was a problem hiding this comment.
Pull request overview
This PR aims to replace the deprecated datetime.utcnow() method with datetime.now(UTC).replace(tzinfo=None) to ensure Python 3.12+ compatibility. However, the implementation introduces a critical compatibility issue by using datetime.UTC, which is only available in Python 3.11+, while the project supports Python 3.8+.
Key Issues Found:
- Critical: The code uses
datetime.UTCwhich doesn't exist in Python 3.8, 3.9, or 3.10 - Critical: Missing import of
UTCinrq_scheduler/utils.py - The test file correctly uses
dateutil.tz.UTC(which is compatible), but production code uses the incompatibledatetime.UTC
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
| tests/test_scheduler.py | Replaces all datetime.utcnow() calls with datetime.now(UTC).replace(tzinfo=None) using the already-imported dateutil.tz.UTC (compatible with Python 3.8+) |
| rq_scheduler/utils.py | Updates datetime.utcnow() to datetime.now(UTC).replace(tzinfo=None) but missing import and uses incompatible UTC constant |
| rq_scheduler/scheduler.py | Updates datetime.utcnow() calls and comment documentation, imports incompatible datetime.UTC instead of compatible alternative |
| README.rst | Updates example code to use new pattern but missing import statement and uses incompatible UTC constant |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
rq_scheduler/utils.py
Outdated
| until = to_unix(until) | ||
| elif isinstance(until, timedelta): | ||
| until = to_unix((datetime.utcnow() + until)) | ||
| until = to_unix((datetime.now(UTC).replace(tzinfo=None) + until)) |
There was a problem hiding this comment.
The UTC constant is used but not imported. Additionally, datetime.UTC is only available in Python 3.11+, but this project supports Python 3.8+. Import and use datetime.timezone.utc instead (available since Python 3.2+), or use dateutil.tz.UTC which is already a project dependency.
| until = to_unix((datetime.now(UTC).replace(tzinfo=None) + until)) | |
| until = to_unix((datetime.now(dateutil.tz.UTC).replace(tzinfo=None) + until)) |
|
|
||
| scheduler.schedule( | ||
| scheduled_time=datetime.utcnow(), # Time for first execution, in UTC timezone | ||
| scheduled_time=datetime.now(UTC).replace(tzinfo=None), # Time for first execution, in UTC timezone |
There was a problem hiding this comment.
The example uses datetime.now(UTC) but doesn't show the necessary import. Additionally, datetime.UTC is only available in Python 3.11+, but this project supports Python 3.8+. The example should use datetime.timezone.utc instead (e.g., datetime.now(datetime.timezone.utc).replace(tzinfo=None)), and include the proper import statement.
rq_scheduler/scheduler.py
Outdated
| from uuid import uuid4 | ||
|
|
||
| from datetime import datetime | ||
| from datetime import datetime, UTC |
There was a problem hiding this comment.
Using datetime.UTC breaks compatibility with Python 3.8, 3.9, and 3.10. According to setup.py, this project supports Python 3.8+, but datetime.UTC was only added in Python 3.11. The code should use dateutil.tz.UTC instead (which is already a dependency and used in the test file), or use datetime.timezone.utc which is available in Python 3.2+.
| job.enqueue_at_front = True | ||
| self.connection.zadd(self.scheduled_jobs_key, | ||
| {job.id: to_unix(datetime.utcnow() + time_delta)}) | ||
| {job.id: to_unix(datetime.now(UTC).replace(tzinfo=None) + time_delta)}) |
There was a problem hiding this comment.
Using datetime.UTC breaks compatibility with Python 3.8, 3.9, and 3.10. Use datetime.timezone.utc instead, which is available since Python 3.2+, or use dateutil.tz.UTC which is already a project dependency.
| it's scheduled execution time is returned. | ||
| """ | ||
| return self.get_jobs(to_unix(datetime.utcnow()), with_times=with_times) | ||
| return self.get_jobs(to_unix(datetime.now(UTC).replace(tzinfo=None)), with_times=with_times) |
There was a problem hiding this comment.
Using datetime.UTC breaks compatibility with Python 3.8, 3.9, and 3.10. Use datetime.timezone.utc instead, which is available since Python 3.2+, or use dateutil.tz.UTC which is already a project dependency.
| return | ||
| self.connection.zadd(self.scheduled_jobs_key, | ||
| {job.id: to_unix(datetime.utcnow()) + int(interval)}) | ||
| {job.id: to_unix(datetime.now(UTC).replace(tzinfo=None)) + int(interval)}) |
There was a problem hiding this comment.
Using datetime.UTC breaks compatibility with Python 3.8, 3.9, and 3.10. Use datetime.timezone.utc instead, which is available since Python 3.2+, or use dateutil.tz.UTC which is already a project dependency.
Fix deprecated
datetime.datetime.utcnow()usageReplace deprecated
datetime.datetime.utcnow()calls withdatetime.datetime.now(datetime.UTC).replace(tzinfo=None)to resolve deprecation warnings and ensure future compatibility.What changed:
Updated all instances of
datetime.datetime.utcnow()to usedatetime.datetime.now(datetime.UTC).replace(tzinfo=None)This change maintains identical functionality while using the recommended timezone un-aware approach
Why:
datetime.datetime.utcnow()is deprecated in Python 3.12+ and scheduled for removalThe new approach explicitly uses timezone-aware datetime objects, which is the recommended best practice
Prevents deprecation warnings in logs and ensures forward compatibility
Testing:
Verified all datetime operations continue to work as expected
No functional changes to application behavior