Skip to content

Commit d7a9c83

Browse files
fix #1145 - normalize git commit timestamp to utc
1 parent 5440b83 commit d7a9c83

File tree

4 files changed

+49
-6
lines changed

4 files changed

+49
-6
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
### Fixed
1717

18+
- fix #1145: ensure GitWorkdir.get_head_date returns consistent UTC dates regardless of local timezone
1819
- reintroduce Python 3.9 entrypoints shim for compatibility
1920
- fix #1136: update customizing.md to fix missing import
2021

src/setuptools_scm/_run_cmd.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,16 @@ def parse_success(
8181
return parse(self.stdout)
8282

8383

84+
KEEP_GIT_ENV = (
85+
"GIT_CEILING_DIRECTORIES",
86+
"GIT_EXEC_PATH",
87+
"GIT_SSH",
88+
"GIT_SSH_COMMAND",
89+
"GIT_AUTHOR_DATE",
90+
"GIT_COMMITTER_DATE",
91+
)
92+
93+
8494
def no_git_env(env: Mapping[str, str]) -> dict[str, str]:
8595
# adapted from pre-commit
8696
# Too many bugs dealing with environment variables and GIT:
@@ -95,11 +105,7 @@ def no_git_env(env: Mapping[str, str]) -> dict[str, str]:
95105
if k.startswith("GIT_"):
96106
log.debug("%s: %s", k, v)
97107
return {
98-
k: v
99-
for k, v in env.items()
100-
if not k.startswith("GIT_")
101-
or k
102-
in ("GIT_CEILING_DIRECTORIES", "GIT_EXEC_PATH", "GIT_SSH", "GIT_SSH_COMMAND")
108+
k: v for k, v in env.items() if not k.startswith("GIT_") or k in KEEP_GIT_ENV
103109
}
104110

105111

src/setuptools_scm/git.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,13 @@ def parse_timestamp(timestamp_text: str) -> date | None:
123123
return None
124124
if sys.version_info < (3, 11) and timestamp_text.endswith("Z"):
125125
timestamp_text = timestamp_text[:-1] + "+00:00"
126-
return datetime.fromisoformat(timestamp_text).date()
126+
127+
# Convert to UTC to ensure consistent date regardless of local timezone
128+
dt = datetime.fromisoformat(timestamp_text)
129+
log.debug("dt: %s", dt)
130+
dt_utc = dt.astimezone(timezone.utc).date()
131+
log.debug("dt utc: %s", dt_utc)
132+
return dt_utc
127133

128134
res = run_git(
129135
[

testing/test_git.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,36 @@ def test_git_getdate_git_2_45_0_plus(
515515
assert git_wd.get_head_date() == date(2024, 4, 30)
516516

517517

518+
def test_git_getdate_timezone_consistency(
519+
wd: WorkDir, monkeypatch: pytest.MonkeyPatch
520+
) -> None:
521+
"""Test that get_head_date returns consistent UTC dates regardless of local timezone.
522+
523+
This test forces a git commit with a timestamp that represents a time
524+
after midnight in a positive timezone offset but still the previous day in UTC.
525+
This is the exact scenario that was causing test failures in issue #1145.
526+
"""
527+
# Create a timestamp that's problematic:
528+
# - In Europe/Berlin (UTC+2): 2025-06-12 00:30:00 (June 12th)
529+
# - In UTC: 2025-06-11 22:30:00 (June 11th)
530+
problematic_timestamp = "2025-06-12T00:30:00+02:00"
531+
532+
# Force git to use this specific timestamp for the commit
533+
monkeypatch.setenv("GIT_AUTHOR_DATE", problematic_timestamp)
534+
monkeypatch.setenv("GIT_COMMITTER_DATE", problematic_timestamp)
535+
536+
wd.commit_testfile()
537+
538+
git_wd = git.GitWorkdir(wd.cwd)
539+
result_date = git_wd.get_head_date()
540+
541+
# The correct behavior is to return the UTC date (2025-06-11)
542+
# If the bug is present, it would return the timezone-local date (2025-06-12)
543+
expected_utc_date = date(2025, 6, 11)
544+
545+
assert result_date == expected_utc_date
546+
547+
518548
@pytest.fixture
519549
def signed_commit_wd(monkeypatch: pytest.MonkeyPatch, wd: WorkDir) -> WorkDir:
520550
if not has_command("gpg", args=["--version"], warn=False):

0 commit comments

Comments
 (0)