fix: standardize datetime.now() to use UTC-aware datetimes#894
fix: standardize datetime.now() to use UTC-aware datetimes#894ashsolei wants to merge 1 commit intohesreallyhim:mainfrom
Conversation
Replace all datetime.now() calls with datetime.now(timezone.utc) and ensure all strptime results include tzinfo=timezone.utc for consistent timezone-aware datetime comparisons across the codebase. Files changed: - 12 source files: added timezone import, updated datetime.now() calls - 3 test files: updated expected values to match UTC-aware datetimes - readme_utils.py: parse_resource_date() now returns UTC-aware datetimes - flat.py: fixed local strptime and datetime.min sentinel
There was a problem hiding this comment.
Pull request overview
This PR standardizes the codebase’s usage of “current time” by replacing timezone-naive datetime.now() calls with UTC-aware alternatives, reducing the risk of TypeError from mixing naive/aware datetimes and improving cross-environment determinism.
Changes:
- Replaced
datetime.now()with UTC-aware equivalents (primarilydatetime.now(timezone.utc), anddatetime.now(UTC)wheredatetime.UTCis used). - Updated README generation and resource/validation scripts to consistently generate/compare UTC-based timestamps.
- Updated tests to expect UTC-aware datetimes and to parse CSV timestamps as UTC-aware.
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| scripts/badges/badge_notification_core.py | Store notification timestamps as UTC-aware ISO strings; use UTC-aware “now” for cutoff calculations. |
| scripts/readme/generators/base.py | Use UTC-aware timestamps for backup naming. |
| scripts/readme/generators/flat.py | Use UTC-aware cutoff for releases; parse release dates as UTC-aware; UTC-aware generated date. |
| scripts/readme/helpers/readme_utils.py | parse_resource_date() now returns UTC-aware datetimes. |
| scripts/readme/markup/awesome.py | Weekly cutoff uses UTC-aware “now”. |
| scripts/readme/markup/minimal.py | Weekly cutoff uses UTC-aware “now”. |
| scripts/readme/markup/visual.py | Weekly cutoff uses UTC-aware “now”. |
| scripts/resources/create_resource_pr.py | Branch timestamp uses UTC-aware “now”. |
| scripts/resources/download_resources.py | Track start/end times using UTC-aware “now”. |
| scripts/resources/resource_utils.py | CSV date fields default from UTC-aware “now”. |
| scripts/validation/validate_links.py | Update “last_checked” and summary timestamp using UTC-aware “now” (datetime.UTC). |
| scripts/validation/validate_single_resource.py | Populate last_checked using UTC-aware “now”. |
| tests/test_flat_list_generator.py | Use UTC-aware “now” in release-sort tests. |
| tests/test_generate_readme.py | Update expected parsed dates to be UTC-aware. |
| tests/test_resource_utils.py | Make test window UTC-aware and parse CSV timestamps as UTC-aware. |
Comments suppressed due to low confidence (1)
scripts/badges/badge_notification_core.py:452
record_notification()now writes UTC-aware ISO timestamps, butget_notification_count()may still read older history entries that were written as offset-naive ISO strings.datetime.fromisoformat(...).timestamp()will interpret those naive values in the current local timezone, which can miscount “recent” notifications if the history file is moved between environments/timezones. Consider normalizing parsed timestamps: iftzinfo is None, assume UTC (or explicitly convert from local) before comparing tocutoff.
"""Get count of recent notifications for a repository"""
cutoff = datetime.now(timezone.utc).timestamp() - (time_window_hours * 3600)
count = 0
for entry in self.history:
if entry["repo_url"] == repo_url:
try:
timestamp = datetime.fromisoformat(entry["timestamp"]).timestamp()
if timestamp > cutoff:
| # Update timestamp if not locked | ||
| if "last_checked" not in locked_fields: | ||
| row[LAST_CHECKED_HEADER_NAME] = datetime.now().strftime("%Y-%m-%d:%H-%M-%S") | ||
| row[LAST_CHECKED_HEADER_NAME] = datetime.now(UTC).strftime("%Y-%m-%d:%H-%M-%S") | ||
|
|
There was a problem hiding this comment.
This file now uses datetime.now(UTC) (with UTC imported from datetime) rather than datetime.now(timezone.utc). Functionally both are UTC-aware, but it diverges from the PR description’s stated standard (timezone.utc). Consider either switching these calls to timezone.utc for consistency across the PR, or updating the PR description to explicitly allow UTC as the standardized approach.
Summary
Standardize all
datetime.now()calls to usedatetime.now(timezone.utc)across the entire codebase, preventing potential bugs from naive vs. aware datetime comparisons.Problem
The codebase uses
datetime.now()(which returns timezone-naive local datetimes) throughout. This creates a latent bug: if any code path introduces a timezone-aware datetime (e.g., from an API response or database), comparisons with naive datetimes raiseTypeError: can't compare offset-naive and offset-aware datetimes.Additionally, using local time makes the codebase behave differently depending on the server's timezone, which is unreliable in CI/CD environments and distributed systems.
Changes
12 source files — added
from datetime import timezoneimport and replaceddatetime.now()→datetime.now(timezone.utc):scripts/badges/badge_notification_core.pyscripts/readme/generators/base.pyscripts/readme/generators/flat.py(also fixed localstrptimeanddatetime.minsentinel)scripts/readme/helpers/readme_utils.py(parse_resource_date()now returns UTC-aware)scripts/readme/markup/awesome.pyscripts/readme/markup/minimal.pyscripts/readme/markup/visual.pyscripts/resources/create_resource_pr.pyscripts/resources/download_resources.pyscripts/resources/resource_utils.pyscripts/validation/validate_links.pyscripts/validation/validate_single_resource.py3 test files — updated expected datetime values to include
tzinfo=timezone.utc:tests/test_flat_list_generator.pytests/test_generate_readme.pytests/test_resource_utils.pyTesting
All 314 tests pass:
Risk
Low — this is a mechanical change with no behavioral difference when running in UTC environments (CI). In non-UTC environments, timestamps will now correctly reflect UTC instead of local time.