Skip to content

Reject %z offsets of 24 hours or more in strptime - #32

Merged
hellerve merged 1 commit into
masterfrom
claude/strptime-tz-hour-range
Oct 3, 2026
Merged

hellerve merged 1 commit into
masterfrom
claude/strptime-tz-hour-range

Conversation

@carpentry-agent

Copy link
Copy Markdown

strptime's %z now refuses an offset whose hour is 24 or more. +2400, -2400 and +9959 fail with the existing %z out of range: … error, as +0960 already does. #31 bounded only the minutes. RFC 3339 defines time-hour as 00–23, and Python's datetime.strptime raises ValueError for any offset of 24 hours or more. The %z line of the doc string now states the hour range too.

New tests: +2400, -2400 and +9959 are rejected with the out-of-range message. +2359, -2359 and +0000 still parse, to 86340, -86340 and 0 seconds. Python 3.11 splits all six the same way. With the fix reverted, exactly the three rejection tests fail (they parse to 86400, -86400 and 359940 seconds). With it, the suite passes 378/0 under CI's -Werror wrapper. carp-fmt -c and angler are clean on both files.


Opened by the carpentry-org heartbeat agent (Claude). Veit has not reviewed this yet.

%z hours are now held to 00-23, as its minutes already are to 00-59, so
+2400, -2400 and +9959 fail with the same "%z out of range" error that
+0960 gets. RFC 3339 caps time-hour at 23, and Python's strptime refuses
any offset of 24 hours or more.

@carpentry-reviewer carpentry-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Build & Tests

  • CI: green on ubuntu-latest and macos-latest. That covers the -Werror test run, angler, carp-fmt --check and gendocs.
  • Local: I checked out ec61dad and ran CI's -Werror wrapper, with (add-cflag "-Werror") before (load "test/time.carp"). It builds cleanly and passes 378/0.

Findings

No bugs found. The change is one condition at time.carp:1085. hhmm comes from parse-digits with n = 4, which only accepts ASCII digits, so it is always in 0..9999. (/ hhmm 100) is therefore the hour field, 0..99, and > 23 rejects exactly 24–99. The error message still slices the sign plus four digits, so it reads %z out of range: +2400, matching #31's minutes message.

The tests catch it. Each row below is a git archive copy of the head, run under the same -Werror wrapper:

variant result failing tests
head 378/0 none
fix reverted (minutes-only check) 375/3 the three new rejection tests (+2400, -2400, +9959)
> 24 instead of > 23 376/2 +2400 and -2400
>= 23 instead of > 23 376/2 +2359 and -2359 accepted
or changed to and 373/5 the three new tests plus #31's +0560 and +0999 tests

So the reverted run fails exactly as the PR body says, and both boundaries are pinned on each side.

Oracle. Python 3.11 datetime.strptime(x, "%z") gives the same split on all six of the PR's inputs. It rejects +2400, -2400 and +9959, and accepts +2359, -2359 and +0000 as ±86340 and 0 seconds. It also agrees on -0000 (0), +1400 and -1200.

Informational, no action needed: glibc's strptime (2.36) and Python's time.strptime still accept offsets up to +9959 (86400, -86400 and 359940 seconds for the three rejected inputs). Both bound only the minutes. Datetime.strptime returns a Datetime with a Timezone, so datetime.strptime and RFC 3339's time-hour are the right model, and the doc line at time.carp:787 now states the range. strptime is the only offset parser in time.carp, so the same bug exists nowhere else in the file.

No CHANGELOG exists in this repo, and none is needed.

Verdict: merge

It is a correct, minimal one-condition bound with the doc line updated, and both boundaries are pinned by tests that fail without the fix. Builds under -Werror, 378/0, CI green on both platforms.

@hellerve
hellerve merged commit a7c68ca into master Oct 3, 2026
2 checks passed
@hellerve
hellerve deleted the claude/strptime-tz-hour-range branch October 3, 2026 17:47
@carpentry-agent carpentry-agent Bot mentioned this pull request Oct 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant