From 8b9d58faa5675ec49417efb730080301e9d62f47 Mon Sep 17 00:00:00 2001 From: Rod Vince Date: Sun, 11 Oct 2026 13:39:34 -0600 Subject: [PATCH] fix: the refusal of an expiry that is not a date says a form, not an example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A grant whose «expires_at» cannot be read was refused with «… as a date and time, e.g. 2026-12-31T00:00:00Z». Nothing a package of the family says gives a concrete example where a form will do (greenhouse decisions/0598), and the gate that asks it of the published family went red on this one sentence the day 0.30.0 was released: 465 examples, 464 forms, this one. It now says «as a date and time with its offset, in ISO 8601». With that sentence in a house born of the published family, the same gate is green. --- src/Standing/StandingGrant.php | 2 +- tests/Standing/AStandingGrantNeverCrossesItsFloorsTest.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Standing/StandingGrant.php b/src/Standing/StandingGrant.php index 6eebc37..dab0942 100644 --- a/src/Standing/StandingGrant.php +++ b/src/Standing/StandingGrant.php @@ -290,7 +290,7 @@ public static function fromArray(array $data): self $expires = $data['expires_at'] ?? null; $expiresAt = \is_string($expires) ? date_create_immutable($expires) : null; if ($expires !== null && !$expiresAt instanceof \DateTimeImmutable) { - throw new \InvalidArgumentException("{$where} gives «expires_at» as a date and time, e.g. 2026-12-31T00:00:00Z"); + throw new \InvalidArgumentException("{$where} gives «expires_at» as a date and time with its offset, in ISO 8601"); } $supersedes = $data['supersedes'] ?? null; diff --git a/tests/Standing/AStandingGrantNeverCrossesItsFloorsTest.php b/tests/Standing/AStandingGrantNeverCrossesItsFloorsTest.php index c1c052d..f20ee48 100644 --- a/tests/Standing/AStandingGrantNeverCrossesItsFloorsTest.php +++ b/tests/Standing/AStandingGrantNeverCrossesItsFloorsTest.php @@ -100,8 +100,8 @@ public static function documentsThatAreRefused(): iterable ['name' => 'c', 'statement' => 't', 'by' => ['operation' => 'lab:build']], ]], 'each under its own name']; yield 'conditions not given as a list' => [['conditions' => ['c' => ['name' => 'c']]], 'gives «conditions» as a list']; - yield 'an expiry that is not a date' => [['expires_at' => 'next week, maybe'], 'gives «expires_at» as a date and time']; - yield 'an expiry that is not text' => [['expires_at' => 1790000000], 'gives «expires_at» as a date and time']; + yield 'an expiry that is not a date' => [['expires_at' => 'next week, maybe'], 'gives «expires_at» as a date and time with its offset, in ISO 8601']; + yield 'an expiry that is not text' => [['expires_at' => 1790000000], 'gives «expires_at» as a date and time with its offset, in ISO 8601']; } public function testTheValuesRefuseTheSameThingsWhenBuiltByHand(): void