refactor[#281]: whenever migration - replace stdlib datetime with whenever across fenn - #289
Merged
ApusBerliozi merged 4 commits intoJul 28, 2026
Merged
Conversation
ApusBerliozi
self-requested a review
July 28, 2026 06:45
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes: #281
Changes
datetimeusage infenn/logging.py,fenn/reproducibility.py,fenn/cli/pull.py,fenn/dashboard/app.pyandfenn/dashboard/scanner.pyto thewheneverlibrary.whenever>=0.10.3to the project dependencies inpyproject.toml.datetime.now()anddatetime.now().replace(microsecond=0)withwheneverequivalents usingInstant/PlainDateTime(Instant.now().to_system_tz().to_plain()).datetime.fromtimestamp(ts, tz=timezone.utc)withInstant.from_timestamp(ts)for UTC log-entry timestamps.datetime.strptime(...)parsing (used for the sessionstartedfield and the/api/sessionsstarted_after/started_beforequery parameters) withPlainDateTime.parse(..., format=...).(ended_at - started_at).total_seconds()) withPlainDateTime.difference(..., naive_arithmetic_ok=True).total("seconds").datetime.now(timezone.utc).isoformat()infenn/cli/pull.py's template registry with a small_isoformat_utc_now()helper incli/utils.py.Notes
wheneverpattern strings (such as"YYYY-MM-DD hh:mm:ss"and"YYYYMMDD_hhmm") instead of relying on the library’s default string or ISO formatting. This is important because the default output includes aTseparator and nanosecond precision with aZUTC suffix, which would change the existing on-disk formats. By using explicit patterns, we ensure that all stored strings in.fnXML files,.logfiles, the template registry, and session IDs remain exactly byte-for-byte identical to what was produced by the previous standard library implementation.PERMANENT_SESSION_LIFETIMEsetting was intentionally left using the standard librarytimedeltabecause it is a Flask/Werkzeug configuration value. Flask internally expects a standarddatetime.timedeltawhen calculating session expiration. Specifically,SessionInterface.get_expiration_timeaddsdatetime.now(timezone.utc)to this value, and mixing it withwhenever.TimeDeltawould cause a type error since the two types are incompatible. For this reason, it must remain a standard librarytimedeltaand is excluded from the migration.test_reproducibility.pytest for timestamp behavior was also updated because it previously mockedfenn.reproducibility.datetime, which no longer exists after switching towhenever. Timestamps are now generated usingInstant, which is an immutable Rust-backed type and cannot be monkeypatched directly. As a result, the test was adjusted to mock the module-levelInstantreference instead.