Skip to content

Commit 981183a

Browse files
committed
Normalize timezone handling across DateTime and Timestamp classes by defaulting to UTC. Implement FromString interface. Update tests to validate adjustments.
1 parent 3cef635 commit 981183a

23 files changed

+95
-79
lines changed

src/Base/Primitive/Bool/BoolType.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace PhpTypedValues\Base\Primitive\Bool;
66

77
use PhpTypedValues\Base\Primitive\PrimitiveType;
8+
use PhpTypedValues\Base\Shared\FromString;
89

910
/**
1011
* Base implementation for boolean typed values.
@@ -23,6 +24,6 @@
2324
*
2425
* @psalm-immutable
2526
*/
26-
abstract readonly class BoolType extends PrimitiveType implements BoolTypeInterface
27+
abstract readonly class BoolType extends PrimitiveType implements BoolTypeInterface, FromString
2728
{
2829
}

src/Base/Primitive/DateTime/DateTimeType.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
abstract readonly class DateTimeType extends PrimitiveType implements DateTimeTypeInterface
3636
{
3737
protected const FORMAT = '';
38-
protected const ZONE = 'UTC';
38+
public const ZONE = 'UTC';
3939
protected const MIN_TIMESTAMP_SECONDS = -62135596800; // 0001-01-01
4040
protected const MAX_TIMESTAMP_SECONDS = 253402300799; // 9999-12-31 23:59:59
4141

src/Base/Primitive/DateTime/DateTimeTypeInterface.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
*/
2323
interface DateTimeTypeInterface
2424
{
25+
public const ZONE = 'UTC';
26+
2527
public function value(): DateTimeImmutable;
2628

2729
public static function fromDateTime(DateTimeImmutable $value): static;
@@ -30,8 +32,17 @@ public static function tryFromMixed(mixed $value): static|Undefined;
3032

3133
public static function tryFromString(string $value): static|Undefined;
3234

35+
/**
36+
* @param non-empty-string $timezone
37+
*/
38+
public static function fromString(string $value, string $timezone = self::ZONE): static;
39+
3340
/**
3441
* @param non-empty-string $timezone
3542
*/
3643
public function withTimeZone(string $timezone): static;
44+
45+
public static function getFormat(): string;
46+
47+
public function toString(): string;
3748
}

src/Base/Primitive/Float/FloatType.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace PhpTypedValues\Base\Primitive\Float;
66

77
use PhpTypedValues\Base\Primitive\PrimitiveType;
8+
use PhpTypedValues\Base\Shared\FromString;
89
use PhpTypedValues\Exception\FloatTypeException;
910

1011
use function sprintf;
@@ -26,7 +27,7 @@
2627
*
2728
* @psalm-immutable
2829
*/
29-
abstract readonly class FloatType extends PrimitiveType implements FloatTypeInterface
30+
abstract readonly class FloatType extends PrimitiveType implements FloatTypeInterface, FromString
3031
{
3132
/**
3233
* @throws FloatTypeException

src/Base/Primitive/Integer/IntType.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace PhpTypedValues\Base\Primitive\Integer;
66

77
use PhpTypedValues\Base\Primitive\PrimitiveType;
8+
use PhpTypedValues\Base\Shared\FromString;
89
use PhpTypedValues\Exception\IntegerTypeException;
910

1011
use function sprintf;
@@ -26,7 +27,7 @@
2627
*
2728
* @psalm-immutable
2829
*/
29-
abstract readonly class IntType extends PrimitiveType implements IntTypeInterface
30+
abstract readonly class IntType extends PrimitiveType implements IntTypeInterface, FromString
3031
{
3132
/**
3233
* @throws IntegerTypeException

src/Base/Primitive/PrimitiveTypeInterface.php

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,13 @@
88
use PhpTypedValues\Base\Shared\IsEmptyInterface;
99
use PhpTypedValues\Base\Shared\IsUndefinedInterface;
1010
use PhpTypedValues\Base\TypeInterface;
11-
use PhpTypedValues\Exception\TypeException;
1211
use PhpTypedValues\Undefined\Alias\Undefined;
1312

1413
/**
1514
* Base contract for all immutable typed values in this library.
1615
*
1716
* Responsibilities
18-
* - Provide strict construction from a validated string via {@see fromString}.
17+
* - Provide strict construction from a validated string via {@see FromString}.
1918
* - Provide a lossless string representation via {@see toString} and {@see __toString}.
2019
* - Concrete implementations may also provide tolerant factories like
2120
* `tryFromMixed(mixed): static|Undefined` that return {@see Undefined} on failure.
@@ -27,17 +26,6 @@
2726
*/
2827
interface PrimitiveTypeInterface extends TypeInterface, JsonSerializable, IsEmptyInterface, IsUndefinedInterface
2928
{
30-
/**
31-
* Create an instance from a validated string representation.
32-
*
33-
* Implementations should perform strict validation and may throw a
34-
* domain-specific subtype of {@see TypeException}
35-
* when the provided value is invalid.
36-
*
37-
* @throws TypeException
38-
*/
39-
public static function fromString(string $value): static;
40-
4129
/**
4230
* Returns a normalized string representation of the underlying value.
4331
*/

src/Base/Primitive/String/StrType.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace PhpTypedValues\Base\Primitive\String;
66

77
use PhpTypedValues\Base\Primitive\PrimitiveType;
8+
use PhpTypedValues\Base\Shared\FromString;
89

910
/**
1011
* Base implementation for string-typed values.
@@ -23,6 +24,6 @@
2324
*
2425
* @psalm-immutable
2526
*/
26-
abstract readonly class StrType extends PrimitiveType implements StrTypeInterface
27+
abstract readonly class StrType extends PrimitiveType implements StrTypeInterface, FromString
2728
{
2829
}

src/Base/Primitive/Undefined/UndefinedType.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace PhpTypedValues\Base\Primitive\Undefined;
66

77
use PhpTypedValues\Base\Primitive\PrimitiveType;
8+
use PhpTypedValues\Base\Shared\FromString;
89

910
/**
1011
* Base implementation for a special "Undefined/Unknown" typed value.
@@ -22,6 +23,6 @@
2223
*
2324
* @psalm-immutable
2425
*/
25-
abstract readonly class UndefinedType extends PrimitiveType implements UndefinedTypeInterface
26+
abstract readonly class UndefinedType extends PrimitiveType implements UndefinedTypeInterface, FromString
2627
{
2728
}

src/Base/Shared/FromString.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpTypedValues\Base\Shared;
6+
7+
use PhpTypedValues\Exception\TypeException;
8+
9+
/**
10+
* Base contract to convert string to an object.
11+
*
12+
* @psalm-immutable
13+
*/
14+
interface FromString
15+
{
16+
/**
17+
* Create an instance from a validated string representation.
18+
*
19+
* Implementations should perform strict validation and may throw a
20+
* domain-specific subtype of {@see TypeException}
21+
* when the provided value is invalid.
22+
*
23+
* @throws TypeException
24+
*/
25+
public static function fromString(string $value): static;
26+
}

src/DateTime/DateTimeAtom.php

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@
3636

3737
public function __construct(DateTimeImmutable $value)
3838
{
39-
$this->value = $value;
39+
// normalized time zone
40+
$this->value = $value->setTimezone(new DateTimeZone(static::ZONE));
4041
}
4142

4243
/**
@@ -96,10 +97,7 @@ public function toString(): string
9697

9798
public static function fromDateTime(DateTimeImmutable $value): static
9899
{
99-
// normalized timezone
100-
return new static(
101-
$value->setTimezone(new DateTimeZone(static::ZONE))
102-
);
100+
return new static($value);
103101
}
104102

105103
public function jsonSerialize(): string

0 commit comments

Comments
 (0)