Skip to content

Commit 5b55d8b

Browse files
committed
Add tryFromString method for DateTime-based types with tests and usage updates
- Implemented `tryFromString` in `DateTimeAtom`, `DateTimeRFC3339`, `DateTimeRFC3339Extended`, `DateTimeW3C`, `TimestampMilliseconds`, and `TimestampSeconds` to return `Undefined` for invalid input. - Updated relevant interfaces to include `tryFromString` declaration. - Added comprehensive unit tests to validate behavior for valid and invalid cases. - Enhanced `Usage` examples to demonstrate correct usage of `tryFromString`.
1 parent db1e98b commit 5b55d8b

File tree

14 files changed

+221
-0
lines changed

14 files changed

+221
-0
lines changed

src/Abstract/DateTime/DateTimeTypeInterface.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace PhpTypedValues\Abstract\DateTime;
66

77
use DateTimeImmutable;
8+
use PhpTypedValues\Undefined\Alias\Undefined;
89

910
/**
1011
* @psalm-immutable
@@ -15,6 +16,8 @@ public function value(): DateTimeImmutable;
1516

1617
public static function fromDateTime(DateTimeImmutable $value): static;
1718

19+
public static function tryFromString(string $value): static|Undefined;
20+
1821
public function toString(): string;
1922

2023
public static function fromString(string $value): static;

src/DateTime/DateTimeAtom.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
use DateTimeZone;
1111
use PhpTypedValues\Abstract\DateTime\DateTimeType;
1212
use PhpTypedValues\Exception\DateTimeTypeException;
13+
use PhpTypedValues\Exception\TypeException;
14+
use PhpTypedValues\Undefined\Alias\Undefined;
1315

1416
/**
1517
* ATOM RFC 3339 format based on ISO 8601.
@@ -36,6 +38,15 @@ public static function fromString(string $value): static
3638
);
3739
}
3840

41+
public static function tryFromString(string $value): static|Undefined
42+
{
43+
try {
44+
return static::fromString($value);
45+
} catch (TypeException) {
46+
return Undefined::create();
47+
}
48+
}
49+
3950
public function toString(): string
4051
{
4152
return $this->value()->format(static::FORMAT);

src/DateTime/DateTimeRFC3339.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
use DateTimeZone;
1111
use PhpTypedValues\Abstract\DateTime\DateTimeType;
1212
use PhpTypedValues\Exception\DateTimeTypeException;
13+
use PhpTypedValues\Exception\TypeException;
14+
use PhpTypedValues\Undefined\Alias\Undefined;
1315

1416
/**
1517
* RFC 3339 format based on ISO 8601.
@@ -36,6 +38,15 @@ public static function fromString(string $value): static
3638
);
3739
}
3840

41+
public static function tryFromString(string $value): static|Undefined
42+
{
43+
try {
44+
return static::fromString($value);
45+
} catch (TypeException) {
46+
return Undefined::create();
47+
}
48+
}
49+
3950
public function toString(): string
4051
{
4152
return $this->value()->format(static::FORMAT);

src/DateTime/DateTimeRFC3339Extended.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
use DateTimeZone;
1111
use PhpTypedValues\Abstract\DateTime\DateTimeType;
1212
use PhpTypedValues\Exception\DateTimeTypeException;
13+
use PhpTypedValues\Exception\TypeException;
14+
use PhpTypedValues\Undefined\Alias\Undefined;
1315

1416
/**
1517
* RFC 3339 EXTENDED format based on ISO 8601 (with microseconds).
@@ -36,6 +38,15 @@ public static function fromString(string $value): static
3638
);
3739
}
3840

41+
public static function tryFromString(string $value): static|Undefined
42+
{
43+
try {
44+
return static::fromString($value);
45+
} catch (TypeException) {
46+
return Undefined::create();
47+
}
48+
}
49+
3950
public function toString(): string
4051
{
4152
return $this->value()->format(static::FORMAT);

src/DateTime/DateTimeW3C.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
use DateTimeZone;
1111
use PhpTypedValues\Abstract\DateTime\DateTimeType;
1212
use PhpTypedValues\Exception\DateTimeTypeException;
13+
use PhpTypedValues\Exception\TypeException;
14+
use PhpTypedValues\Undefined\Alias\Undefined;
1315

1416
/**
1517
* W3C RFC 3339 format based on ISO 8601.
@@ -36,6 +38,15 @@ public static function fromString(string $value): static
3638
);
3739
}
3840

41+
public static function tryFromString(string $value): static|Undefined
42+
{
43+
try {
44+
return static::fromString($value);
45+
} catch (TypeException) {
46+
return Undefined::create();
47+
}
48+
}
49+
3950
public function toString(): string
4051
{
4152
return $this->value()->format(static::FORMAT);

src/DateTime/Timestamp/TimestampMilliseconds.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
use DateTimeZone;
88
use PhpTypedValues\Abstract\DateTime\DateTimeType;
99
use PhpTypedValues\Exception\DateTimeTypeException;
10+
use PhpTypedValues\Exception\TypeException;
11+
use PhpTypedValues\Undefined\Alias\Undefined;
1012

1113
use function intdiv;
1214
use function sprintf;
@@ -58,6 +60,15 @@ public static function fromString(string $value): static
5860
);
5961
}
6062

63+
public static function tryFromString(string $value): static|Undefined
64+
{
65+
try {
66+
return static::fromString($value);
67+
} catch (TypeException) {
68+
return Undefined::create();
69+
}
70+
}
71+
6172
/**
6273
* Render as milliseconds since epoch, e.g. "1732445696123".
6374
*/

src/DateTime/Timestamp/TimestampSeconds.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
use DateTimeZone;
88
use PhpTypedValues\Abstract\DateTime\DateTimeType;
99
use PhpTypedValues\Exception\DateTimeTypeException;
10+
use PhpTypedValues\Exception\TypeException;
11+
use PhpTypedValues\Undefined\Alias\Undefined;
1012

1113
/**
1214
* Unix timestamp (seconds since Unix epoch, UTC).
@@ -40,6 +42,15 @@ public static function fromString(string $value): static
4042
);
4143
}
4244

45+
public static function tryFromString(string $value): static|Undefined
46+
{
47+
try {
48+
return static::fromString($value);
49+
} catch (TypeException) {
50+
return Undefined::create();
51+
}
52+
}
53+
4354
public function toString(): string
4455
{
4556
return $this->value()->format(static::FORMAT);

src/Usage/DateTime.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@
44

55
use PhpTypedValues\DateTime\DateTimeAtom;
66
use PhpTypedValues\DateTime\DateTimeRFC3339;
7+
use PhpTypedValues\DateTime\DateTimeRFC3339Extended;
8+
use PhpTypedValues\DateTime\DateTimeW3C;
79
use PhpTypedValues\DateTime\Timestamp\TimestampMilliseconds;
810
use PhpTypedValues\DateTime\Timestamp\TimestampSeconds;
11+
use PhpTypedValues\Undefined\Alias\Undefined;
912

1013
/**
1114
* DateTime.
@@ -24,3 +27,34 @@
2427

2528
$tsVo = TimestampMilliseconds::fromString('1735787045123');
2629
echo TimestampMilliseconds::fromDateTime($tsVo->value())->toString() . \PHP_EOL;
30+
31+
// tryFromString usages to satisfy Psalm (ensure both success and failure branches are referenced)
32+
$a = DateTimeAtom::tryFromString('2025-01-02T03:04:05+00:00');
33+
if (!($a instanceof Undefined)) {
34+
echo $a->toString() . \PHP_EOL;
35+
}
36+
37+
$r = DateTimeRFC3339::tryFromString('2025-01-02T03:04:05+00:00');
38+
if (!($r instanceof Undefined)) {
39+
echo $r->toString() . \PHP_EOL;
40+
}
41+
42+
$re = DateTimeRFC3339Extended::tryFromString('2025-01-02T03:04:05.123456+00:00');
43+
if (!($re instanceof Undefined)) {
44+
echo $re->toString() . \PHP_EOL;
45+
}
46+
47+
$w = DateTimeW3C::tryFromString('2025-01-02T03:04:05+00:00');
48+
if (!($w instanceof Undefined)) {
49+
echo $w->toString() . \PHP_EOL;
50+
}
51+
52+
$ts = TimestampSeconds::tryFromString('1735787045');
53+
if (!($ts instanceof Undefined)) {
54+
echo $ts->toString() . \PHP_EOL;
55+
}
56+
57+
$tm = TimestampMilliseconds::tryFromString('1735787045123');
58+
if (!($tm instanceof Undefined)) {
59+
echo $tm->toString() . \PHP_EOL;
60+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use PhpTypedValues\DateTime\DateTimeAtom;
6+
use PhpTypedValues\Undefined\Alias\Undefined;
7+
8+
it('DateTimeAtom::tryFromString returns value for valid ATOM string', function (): void {
9+
$s = '2025-01-02T03:04:05+00:00';
10+
$v = DateTimeAtom::tryFromString($s);
11+
12+
expect($v)
13+
->toBeInstanceOf(DateTimeAtom::class)
14+
->and($v->toString())
15+
->toBe($s);
16+
});
17+
18+
it('DateTimeAtom::tryFromString returns Undefined for invalid string', function (): void {
19+
// Missing timezone offset
20+
$u = DateTimeAtom::tryFromString('2025-01-02T03:04:05');
21+
22+
expect($u)->toBeInstanceOf(Undefined::class);
23+
});
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use PhpTypedValues\DateTime\DateTimeRFC3339;
6+
use PhpTypedValues\Undefined\Alias\Undefined;
7+
8+
it('DateTimeRFC3339::tryFromString returns value for valid RFC3339 string', function (): void {
9+
$s = '2025-01-02T03:04:05+00:00';
10+
$v = DateTimeRFC3339::tryFromString($s);
11+
12+
expect($v)
13+
->toBeInstanceOf(DateTimeRFC3339::class)
14+
->and($v->toString())
15+
->toBe($s);
16+
});
17+
18+
it('DateTimeRFC3339::tryFromString returns Undefined for invalid string', function (): void {
19+
// Missing timezone
20+
$u = DateTimeRFC3339::tryFromString('2025-01-02T03:04:05');
21+
22+
expect($u)->toBeInstanceOf(Undefined::class);
23+
});

0 commit comments

Comments
 (0)