diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml index 1b48889..e02e209 100644 --- a/.github/workflows/static.yml +++ b/.github/workflows/static.yml @@ -17,7 +17,7 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: '7.4' + php-version: '8.0' tools: composer:v2 coverage: none diff --git a/composer.json b/composer.json index b05988c..5e22f18 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,7 @@ "guzzlehttp/psr7": "^2.0", "php-http/discovery": "^1.14", "phpunit/phpunit": "^9.5 || ^10.0", - "psalm/phar": "4.8.1", + "psalm/phar": "4.15.0", "psr/http-factory": "^1.0.1", "psr/http-message": "^1.0.1", "squizlabs/php_codesniffer": "3.6.0" diff --git a/src/Utilities/TimeFormatter.php b/src/Utilities/TimeFormatter.php index f6afa67..0bee483 100644 --- a/src/Utilities/TimeFormatter.php +++ b/src/Utilities/TimeFormatter.php @@ -16,6 +16,9 @@ final class TimeFormatter private const TIME_FORMAT = 'Y-m-d\TH:i:s\Z'; private const TIME_ZONE = 'UTC'; + private const RFC3339_FORMAT = 'Y-m-d\TH:i:sP'; + private const RFC3339_EXTENDED_FORMAT = 'Y-m-d\TH:i:s.uP'; + public static function encode(?DateTimeImmutable $time): ?string { if ($time === null) { @@ -31,7 +34,11 @@ public static function decode(?string $time): ?DateTimeImmutable return null; } - $decoded = DateTimeImmutable::createFromFormat(self::TIME_FORMAT, $time, new DateTimeZone(self::TIME_ZONE)); + $decoded = DateTimeImmutable::createFromFormat( + \str_contains($time, '.') ? self::RFC3339_EXTENDED_FORMAT : self::RFC3339_FORMAT, + \strtoupper($time), + new DateTimeZone(self::TIME_ZONE) + ); if ($decoded === false) { throw new ValueError( diff --git a/src/V1/CloudEventTrait.php b/src/V1/CloudEventTrait.php index 77bf4a9..23d11cd 100644 --- a/src/V1/CloudEventTrait.php +++ b/src/V1/CloudEventTrait.php @@ -273,10 +273,6 @@ private function setExtension(string $attribute, $value): self ); } - /** - * @psalm-suppress UndefinedFunction - * @var string - */ $type = \get_debug_type($value); $types = ['bool', 'int', 'string', 'null']; diff --git a/tests/Unit/Utilities/TimeFormatterTest.php b/tests/Unit/Utilities/TimeFormatterTest.php index b648911..be3514e 100644 --- a/tests/Unit/Utilities/TimeFormatterTest.php +++ b/tests/Unit/Utilities/TimeFormatterTest.php @@ -19,11 +19,49 @@ public function testEncode(): void ); } - public function testDecode(): void + public function providesDecodeCases(): array + { + return [ + // UTC + ['2018-04-05T17:31:00Z', '2018-04-05T17:31:00Z'], + ['1985-04-12T23:20:50.100000Z', '1985-04-12T23:20:50.1Z'], + ['1985-04-12T23:20:50.100000Z', '1985-04-12T23:20:50.10Z'], + ['1985-04-12T23:20:50.100000Z', '1985-04-12T23:20:50.100Z'], + ['1985-04-12T23:20:50.120000Z', '1985-04-12T23:20:50.12Z'], + ['1985-04-12T23:20:50.120000Z', '1985-04-12T23:20:50.120Z'], + ['1985-04-12T23:20:50.123000Z', '1985-04-12T23:20:50.123Z'], + ['1985-04-12T23:20:50.123000Z', '1985-04-12T23:20:50.12300Z'], + ['1985-04-12T23:20:50.123400Z', '1985-04-12T23:20:50.1234Z'], + ['1985-04-12T23:20:50.123400Z', '1985-04-12T23:20:50.123400Z'], + ['1985-04-12T23:20:50.123450Z', '1985-04-12T23:20:50.12345Z'], + ['1985-04-12T23:20:50.123450Z', '1985-04-12T23:20:50.123450Z'], + ['1985-04-12T23:20:50.123456Z', '1985-04-12T23:20:50.123456Z'], + + // +01:00 + ['2018-04-05T16:31:00Z', '2018-04-05T17:31:00+01:00'], + ['1985-04-12T22:20:50.100000Z', '1985-04-12T23:20:50.1+01:00'], + ['1985-04-12T22:20:50.100000Z', '1985-04-12T23:20:50.10+01:00'], + ['1985-04-12T22:20:50.100000Z', '1985-04-12T23:20:50.100+01:00'], + ['1985-04-12T22:20:50.120000Z', '1985-04-12T23:20:50.12+01:00'], + ['1985-04-12T22:20:50.120000Z', '1985-04-12T23:20:50.120+01:00'], + ['1985-04-12T22:20:50.123000Z', '1985-04-12T23:20:50.123+01:00'], + ['1985-04-12T22:20:50.123000Z', '1985-04-12T23:20:50.12300+01:00'], + ['1985-04-12T22:20:50.123400Z', '1985-04-12T23:20:50.1234+01:00'], + ['1985-04-12T22:20:50.123400Z', '1985-04-12T23:20:50.123400+01:00'], + ['1985-04-12T22:20:50.123450Z', '1985-04-12T23:20:50.12345+01:00'], + ['1985-04-12T22:20:50.123450Z', '1985-04-12T23:20:50.123450+01:00'], + ['1985-04-12T22:20:50.123456Z', '1985-04-12T23:20:50.123456+01:00'], + ]; + } + + /** + * @dataProvider providesDecodeCases + */ + public function testDecode(string $expected, string $input): void { self::assertEquals( - new DateTimeImmutable('2018-04-05T17:31:00Z'), - TimeFormatter::decode('2018-04-05T17:31:00Z') + new DateTimeImmutable($expected), + TimeFormatter::decode($input) ); }