Skip to content

Commit 75c6020

Browse files
committed
feat: Provide time zone functions
1 parent cc45b7c commit 75c6020

4 files changed

Lines changed: 103 additions & 0 deletions

File tree

src/NotConvertable.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ public static function toDateTime(mixed $value): self
3838
return self::withMessage(sprintf('%s is not convertable to date time object', get_debug_type($value)));
3939
}
4040

41+
public static function toDateTimeZone(mixed $value): self
42+
{
43+
return self::withMessage(sprintf('%s is not convertable to date time zone', get_debug_type($value)));
44+
}
45+
4146
private static function withMessage(string $message): self
4247
{
4348
$me = new self($message);

src/TypeGuard.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,28 @@ public function asDateTimeImmutable(mixed $value, DateTimeZone|string|null $time
147147
return new DateTimeImmutable(asString($value), $tz);
148148
}
149149

150+
/** @return ($value is null ? null : DateTimeZone) */
151+
public function asDateTimeZone(mixed $value): DateTimeZone|null
152+
{
153+
if ($value === null) {
154+
return null;
155+
}
156+
157+
if ($value instanceof DateTimeZone) {
158+
return $value;
159+
}
160+
161+
if ($value instanceof Stringable) {
162+
$value = (string) $value;
163+
}
164+
165+
if (!is_string($value)) {
166+
throw NotConvertable::toDateTimeZone($value);
167+
}
168+
169+
return new DateTimeZone($value);
170+
}
171+
150172
/** @return ($value is null ? null : string) */
151173
public function asDateTimeString(mixed $value): string|null
152174
{

src/functions.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,15 @@ function asDateTimeImmutable(
5858
}
5959
}
6060

61+
if (!function_exists('\Plook\TypeGuard\asDateTimeZone')) { // @codeCoverageIgnore
62+
63+
/** @return ($value is null ? null : DateTimeZone) */
64+
function asDateTimeZone(mixed $value): DateTimeZone|null
65+
{
66+
return TypeGuard::instance()->asDateTimeZone($value);
67+
}
68+
}
69+
6170
if (!function_exists('\Plook\TypeGuard\asDateTimeString')) { // @codeCoverageIgnore
6271

6372
/** @return ($value is null ? null : string) */

tests/AsDateTimeZoneTest.php

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Plook\Tests\TypeGuard;
6+
7+
use DateTimeZone;
8+
use PHPUnit\Framework\Attributes\CoversClass;
9+
use PHPUnit\Framework\Attributes\CoversFunction;
10+
use PHPUnit\Framework\TestCase;
11+
use Plook\Tests\TypeGuard\Helper\StringableString;
12+
use Plook\TypeGuard\NotConvertable;
13+
use Plook\TypeGuard\TypeGuard;
14+
15+
use function basename;
16+
use function Plook\TypeGuard\asDateTimeZone;
17+
use function sprintf;
18+
19+
#[CoversClass(TypeGuard::class)]
20+
#[CoversClass(NotConvertable::class)]
21+
#[CoversFunction('Plook\TypeGuard\asDateTimeZone')]
22+
final class AsDateTimeZoneTest extends TestCase
23+
{
24+
public function testConvertsStrings(): void
25+
{
26+
$dateTimeZone = asDateTimeZone('Europe/Berlin');
27+
28+
self::assertInstanceOf(DateTimeZone::class, $dateTimeZone);
29+
self::assertSame('Europe/Berlin', $dateTimeZone->getName());
30+
}
31+
32+
public function testConvertsStringables(): void
33+
{
34+
$dateTimeZone = asDateTimeZone(new StringableString('Australia/Adelaide'));
35+
36+
self::assertInstanceOf(DateTimeZone::class, $dateTimeZone);
37+
self::assertSame('Australia/Adelaide', $dateTimeZone->getName());
38+
}
39+
40+
public function testReturnsSameDateTimeZone(): void
41+
{
42+
$dateTimeZone = new DateTimeZone('Europe/Berlin');
43+
44+
$result = asDateTimeZone($dateTimeZone);
45+
46+
self::assertSame($dateTimeZone, $result);
47+
}
48+
49+
public function testDoesNotTouchNull(): void
50+
{
51+
self::assertNull(asDateTimeZone(null));
52+
}
53+
54+
public function testOnlyStringsAreConvertable(): void
55+
{
56+
$this->expectException(NotConvertable::class);
57+
$this->expectExceptionMessageMatches(
58+
sprintf(
59+
'/Closure is not convertable to date time zone in %s:%s/',
60+
basename(__FILE__),
61+
__LINE__ + 4,
62+
),
63+
);
64+
65+
asDateTimeZone(static fn (): null => null);
66+
}
67+
}

0 commit comments

Comments
 (0)