Skip to content

Commit 00c80ea

Browse files
committed
Add expiresAt(), registeredAt(), updatedAt(), and expiresInDays() methods to Dates
1 parent ed67fc8 commit 00c80ea

File tree

2 files changed

+73
-0
lines changed

2 files changed

+73
-0
lines changed

src/Responses/Dates.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,46 @@ public static function fromArray(array $data): self
2323
updated: $data['updated'] ?? null,
2424
);
2525
}
26+
27+
/** Parse the registered date into a DateTimeImmutable, or null. */
28+
public function registeredAt(): ?\DateTimeImmutable
29+
{
30+
return self::parse($this->registered);
31+
}
32+
33+
/** Parse the expiry date into a DateTimeImmutable, or null. */
34+
public function expiresAt(): ?\DateTimeImmutable
35+
{
36+
return self::parse($this->expires);
37+
}
38+
39+
/** Parse the updated date into a DateTimeImmutable, or null. */
40+
public function updatedAt(): ?\DateTimeImmutable
41+
{
42+
return self::parse($this->updated);
43+
}
44+
45+
/** Days until expiration, or null if no expiry date is available. */
46+
public function expiresInDays(): ?int
47+
{
48+
$dt = $this->expiresAt();
49+
if ($dt === null) {
50+
return null;
51+
}
52+
53+
return (int) (new \DateTimeImmutable('now', new \DateTimeZone('UTC')))->diff($dt)->format('%r%a');
54+
}
55+
56+
private static function parse(?string $value): ?\DateTimeImmutable
57+
{
58+
if ($value === null) {
59+
return null;
60+
}
61+
62+
try {
63+
return new \DateTimeImmutable($value);
64+
} catch (\Exception) {
65+
return null;
66+
}
67+
}
2668
}

tests/ResponsesTest.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,37 @@
173173
->and($entities->abuse->name)->toBe('Abuse');
174174
});
175175

176+
it('parses dates into DateTimeImmutable', function () {
177+
$dates = Dates::fromArray([
178+
'registered' => '2020-01-01T00:00:00Z',
179+
'expires' => '2028-09-14T04:00:00Z',
180+
'updated' => '2024-02-20T10:16:08Z',
181+
]);
182+
183+
expect($dates->registeredAt())->toBeInstanceOf(\DateTimeImmutable::class)
184+
->and($dates->registeredAt()->format('Y'))->toBe('2020')
185+
->and($dates->expiresAt())->toBeInstanceOf(\DateTimeImmutable::class)
186+
->and($dates->updatedAt())->toBeInstanceOf(\DateTimeImmutable::class)
187+
->and($dates->expiresInDays())->toBeGreaterThan(0);
188+
});
189+
190+
it('returns null for missing dates', function () {
191+
$dates = Dates::fromArray([]);
192+
193+
expect($dates->registeredAt())->toBeNull()
194+
->and($dates->expiresAt())->toBeNull()
195+
->and($dates->updatedAt())->toBeNull()
196+
->and($dates->expiresInDays())->toBeNull();
197+
});
198+
199+
it('returns null for invalid date strings', function () {
200+
$dates = Dates::fromArray(['registered' => 'not-a-date', 'expires' => 'garbage']);
201+
202+
expect($dates->registeredAt())->toBeNull()
203+
->and($dates->expiresAt())->toBeNull()
204+
->and($dates->expiresInDays())->toBeNull();
205+
});
206+
176207
it('handles empty arrays gracefully', function () {
177208
$ip = IpAddresses::fromArray([]);
178209
expect($ip->v4)->toBe([])

0 commit comments

Comments
 (0)