From f1b2682d58f997fd26ed4d7df59d1910ce464203 Mon Sep 17 00:00:00 2001 From: Adam Turner <9087854+aa-turner@users.noreply.github.com> Date: Sun, 13 Aug 2023 19:38:34 +0100 Subject: [PATCH] Format modified times without ``datetime`` --- sphinx/builders/html/__init__.py | 18 +++++++++++------- sphinx/environment/__init__.py | 24 +++++++++++------------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/sphinx/builders/html/__init__.py b/sphinx/builders/html/__init__.py index 5e20f7100..425d7bfa1 100644 --- a/sphinx/builders/html/__init__.py +++ b/sphinx/builders/html/__init__.py @@ -8,8 +8,8 @@ import os import posixpath import re import sys +import time import warnings -from datetime import datetime, timezone from os import path from typing import IO, TYPE_CHECKING, Any from urllib.parse import quote @@ -397,17 +397,15 @@ class StandaloneHTMLBuilder(Builder): except Exception: targetmtime = 0 try: - srcmtime = max(path.getmtime(self.env.doc2path(docname)), - template_mtime) + srcmtime = max(path.getmtime(self.env.doc2path(docname)), template_mtime) if srcmtime > targetmtime: logger.debug( '[build target] targetname %r(%s), template(%s), docname %r(%s)', targetname, - datetime.fromtimestamp(targetmtime, tz=timezone.utc), - datetime.fromtimestamp(template_mtime, tz=timezone.utc), + _format_modified_time(targetmtime), + _format_modified_time(template_mtime), docname, - datetime.fromtimestamp(path.getmtime(self.env.doc2path(docname)), - tz=timezone.utc), + _format_modified_time(path.getmtime(self.env.doc2path(docname))), ) yield docname except OSError: @@ -1192,6 +1190,12 @@ def convert_html_css_files(app: Sphinx, config: Config) -> None: config.html_css_files = html_css_files # type: ignore[attr-defined] +def _format_modified_time(timestamp: float) -> str: + """Return an RFC 3339 formatted string representing the given timestamp.""" + seconds, fraction = divmod(timestamp, 1) + return time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(seconds)) + f'.{fraction:.3f}' + + def convert_html_js_files(app: Sphinx, config: Config) -> None: """This converts string styled html_js_files to tuple styled one.""" html_js_files: list[tuple[str, dict]] = [] diff --git a/sphinx/environment/__init__.py b/sphinx/environment/__init__.py index 04c46f2e5..13a0ae400 100644 --- a/sphinx/environment/__init__.py +++ b/sphinx/environment/__init__.py @@ -5,9 +5,9 @@ from __future__ import annotations import functools import os import pickle +import time from collections import defaultdict from copy import copy -from datetime import datetime, timezone from os import path from typing import TYPE_CHECKING, Any, Callable @@ -488,12 +488,9 @@ class BuildEnvironment: mtime = self.all_docs[docname] newmtime = _last_modified_time(self.doc2path(docname)) if newmtime > mtime: - # convert integer microseconds to floating-point seconds, - # and then to timezone-aware datetime objects. - mtime_dt = datetime.fromtimestamp(mtime / 1_000_000, tz=timezone.utc) - newmtime_dt = datetime.fromtimestamp(mtime / 1_000_000, tz=timezone.utc) logger.debug('[build target] outdated %r: %s -> %s', - docname, mtime_dt, newmtime_dt) + docname, + _format_modified_time(mtime), _format_modified_time(newmtime)) changed.add(docname) continue # finally, check the mtime of dependencies @@ -510,15 +507,10 @@ class BuildEnvironment: break depmtime = _last_modified_time(deppath) if depmtime > mtime: - mtime_dt = datetime.fromtimestamp( - mtime / 1_000_000, tz=timezone.utc, - ) - depmtime_dt = datetime.fromtimestamp( - depmtime / 1_000_000, tz=timezone.utc, - ) logger.debug( '[build target] outdated %r from dependency %r: %s -> %s', - docname, deppath, mtime_dt, depmtime_dt, + docname, deppath, + _format_modified_time(mtime), _format_modified_time(depmtime), ) changed.add(docname) break @@ -748,6 +740,12 @@ def _last_modified_time(filename: str | os.PathLike[str]) -> int: return -(os.stat(filename).st_mtime_ns // -1_000) +def _format_modified_time(timestamp: int) -> str: + """Return an RFC 3339 formatted string representing the given timestamp.""" + seconds, fraction = divmod(timestamp, 10**6) + return time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(seconds)) + f'.{fraction//1_000}' + + def _traverse_toctree( traversed: set[str], parent: str | None,