diff --git a/src/CloudEvent.php b/src/CloudEvent.php index 0f17ef58..7f75b39c 100644 --- a/src/CloudEvent.php +++ b/src/CloudEvent.php @@ -18,6 +18,8 @@ namespace Google\CloudFunctions; +use DateTimeImmutable; +use DateTimeInterface; use JsonSerializable; class CloudEvent implements JsonSerializable @@ -32,6 +34,9 @@ class CloudEvent implements JsonSerializable private $datacontenttype; private $dataschema; private $subject; + /** + * @var DateTimeImmutable|null + */ private $time; /** * @var mixed $data @@ -56,7 +61,7 @@ public function __construct( $this->datacontenttype = $datacontenttype; $this->dataschema = $dataschema; $this->subject = $subject; - $this->time = $time; + $this->time = DateTimeImmutable::createFromFormat(DateTimeInterface::RFC3339_EXTENDED, $time) ?: null; $this->data = $data; } @@ -88,7 +93,7 @@ public function getSubject(): ?string { return $this->subject; } - public function getTime(): ?string + public function getTime(): ?DateTimeImmutable { return $this->time; } @@ -132,7 +137,7 @@ public function jsonSerialize() 'datacontenttype' => $this->datacontenttype, 'dataschema' => $this->dataschema, 'subject' => $this->subject, - 'time' => $this->time, + 'time' => $this->time->format(DateTimeInterface::RFC3339_EXTENDED), 'data' => $this->data, ]; } @@ -148,7 +153,7 @@ public function __toString() "- datacontenttype: $this->datacontenttype", "- dataschema: $this->dataschema", "- subject: $this->subject", - "- time: $this->time", + "- time: {$this->time->format(DateTimeInterface::RFC3339_EXTENDED)}", ]); return $output; } diff --git a/src/CloudEventSdkCompliant.php b/src/CloudEventSdkCompliant.php index dd2b1fa3..3d121ff7 100644 --- a/src/CloudEventSdkCompliant.php +++ b/src/CloudEventSdkCompliant.php @@ -69,11 +69,7 @@ public function getSubject(): ?string } public function getTime(): ?DateTimeImmutable { - $time = DateTimeImmutable::createFromFormat(DateTimeInterface::RFC3339_EXTENDED, $this->cloudevent->getTime()); - if ($time === false) { - return null; - } - return $time; + return $this->cloudevent->getTime(); } public function getExtension(string $attribute) { diff --git a/src/LegacyEventMapper.php b/src/LegacyEventMapper.php index 77f57a2a..a4748836 100644 --- a/src/LegacyEventMapper.php +++ b/src/LegacyEventMapper.php @@ -17,6 +17,8 @@ namespace Google\CloudFunctions; +use DateTime; +use DateTimeInterface; use RuntimeException; class LegacyEventMapper @@ -193,7 +195,7 @@ private function convertRawPubsubPayload(array $jsonData, string $requestUriPath if (array_key_exists('publishTime', $jsonData['message'])) { $timestamp = $jsonData['message']['publishTime']; } else { - $timestamp = gmdate('%Y-%m-%dT%H:%M:%S.%6NZ'); + $timestamp = gmdate('Y-m-d\TH:i:s.v\Z'); } return [ diff --git a/tests/CloudEventFunctionsWrapperTest.php b/tests/CloudEventFunctionsWrapperTest.php index b93d6ccb..7212cb16 100644 --- a/tests/CloudEventFunctionsWrapperTest.php +++ b/tests/CloudEventFunctionsWrapperTest.php @@ -18,6 +18,7 @@ namespace Google\CloudFunctions\Tests; +use DateTimeInterface; use Google\CloudFunctions\CloudEventFunctionWrapper; use Google\CloudFunctions\CloudEvent; use PHPUnit\Framework\TestCase; @@ -239,7 +240,7 @@ public function invokeThis(CloudEvent $cloudevent): void $this->assertSame('application/json', $cloudevent->getDataContentType()); $this->assertSame('type.googleapis.com/google.logging.v2.LogEntry', $cloudevent->getDataSchema()); $this->assertSame('My Subject', $cloudevent->getSubject()); - $this->assertSame('2020-12-08T20:03:19.162Z', $cloudevent->getTime()); + $this->assertSame('2020-12-08T20:03:19.162+00:00', $cloudevent->getTime()->format(DateTimeInterface::RFC3339_EXTENDED)); } public function testWithNotFullButValidCloudEvent(): void @@ -306,7 +307,7 @@ public function invokeThisLegacy(CloudEvent $cloudevent): void $this->assertSame('application/json', $cloudevent->getDataContentType()); $this->assertNull($cloudevent->getDataSchema()); $this->assertNull($cloudevent->getSubject()); - $this->assertSame('2020-12-08T20:03:19.162Z', $cloudevent->getTime()); + $this->assertSame('2020-12-08T20:03:19.162+00:00', $cloudevent->getTime()->format(DateTimeInterface::RFC3339_EXTENDED)); } public function testFromStructuredEventRequest(): void diff --git a/tests/CloudEventSdkCompliantTest.php b/tests/CloudEventSdkCompliantTest.php index e0f6a86b..67c9a7f8 100644 --- a/tests/CloudEventSdkCompliantTest.php +++ b/tests/CloudEventSdkCompliantTest.php @@ -66,7 +66,7 @@ public function testJsonSerialize(): void "datacontenttype": "application\/json", "dataschema": "type.googleapis.com\/google.logging.v2.LogEntry", "subject": "My Subject", - "time": "2020-12-08T20:03:19.162Z", + "time": "2020-12-08T20:03:19.162+00:00", "data": { "message": { "data": "SGVsbG8gdGhlcmU=", @@ -91,7 +91,7 @@ public function testWrapsCloudEvent(): void $this->assertSame($this->cloudevent->getDataContentType(), $wrappedEvent->getDataContentType()); $this->assertSame($this->cloudevent->getDataSchema(), $wrappedEvent->getDataSchema()); $this->assertSame($this->cloudevent->getSubject(), $wrappedEvent->getSubject()); - $this->assertEquals(DateTimeImmutable::createFromFormat(DateTimeInterface::RFC3339_EXTENDED, $this->cloudevent->getTime()), $wrappedEvent->getTime()); + $this->assertSame($this->cloudevent->getTime(), $wrappedEvent->getTime()); } public function testUnimplementedGetExtensionThrowsError(): void diff --git a/tests/CloudEventTest.php b/tests/CloudEventTest.php index 7caee367..dabbb31d 100644 --- a/tests/CloudEventTest.php +++ b/tests/CloudEventTest.php @@ -55,7 +55,7 @@ public function testJsonSerialize(): void "datacontenttype": "application\/json", "dataschema": "type.googleapis.com\/google.logging.v2.LogEntry", "subject": "My Subject", - "time": "2020-12-08T20:03:19.162Z", + "time": "2020-12-08T20:03:19.162+00:00", "data": { "message": { "data": "SGVsbG8gdGhlcmU=", diff --git a/tests/LegacyEventMapperTest.php b/tests/LegacyEventMapperTest.php index 2a3dda7d..ddf4c6d2 100644 --- a/tests/LegacyEventMapperTest.php +++ b/tests/LegacyEventMapperTest.php @@ -18,6 +18,7 @@ namespace Google\CloudFunctions\Tests; +use DateTimeInterface; use Google\CloudFunctions\LegacyEventMapper; use PHPUnit\Framework\TestCase; use stdClass; @@ -93,7 +94,7 @@ public function testWithoutContextProperty(): void $this->assertSame('application/json', $cloudevent->getDataContentType()); $this->assertNull($cloudevent->getDataSchema()); $this->assertNull($cloudevent->getSubject()); - $this->assertSame('2020-12-08T20:03:19.162Z', $cloudevent->getTime()); + $this->assertSame('2020-12-08T20:03:19.162+00:00', $cloudevent->getTime()->format(DateTimeInterface::RFC3339_EXTENDED)); // Verify Pub/Sub-specific data transformation. $message = $cloudevent->getData()['message']; @@ -128,8 +129,8 @@ public function testRawPubsubNoPath(): void ); $this->assertNull($cloudevent->getSubject()); $this->assertEqualsWithDelta( - strtotime(gmdate('%Y-%m-%dT%H:%M:%S.%6NZ')), - strtotime($cloudevent->getTime()), + strtotime(gmdate(DateTimeInterface::RFC3339_EXTENDED)), + strtotime($cloudevent->getTime()->format(DateTimeInterface::RFC3339_EXTENDED)), 1 ); $this->assertSame( @@ -168,8 +169,8 @@ public function testRawPubsubWithPath(): void ); $this->assertNull($cloudevent->getSubject()); $this->assertEqualsWithDelta( - strtotime(gmdate('%Y-%m-%dT%H:%M:%S.%6NZ')), - strtotime($cloudevent->getTime()), + strtotime(gmdate(DateTimeInterface::RFC3339_EXTENDED)), + strtotime($cloudevent->getTime()->format(DateTimeInterface::RFC3339_EXTENDED)), 1 ); $this->assertSame( @@ -207,7 +208,7 @@ public function testResourceAsString(): void $this->assertSame('application/json', $cloudevent->getDataContentType()); $this->assertNull($cloudevent->getDataSchema()); $this->assertNull($cloudevent->getSubject()); - $this->assertSame('2020-12-08T20:03:19.162Z', $cloudevent->getTime()); + $this->assertSame('2020-12-08T20:03:19.162+00:00', $cloudevent->getTime()->format(DateTimeInterface::RFC3339_EXTENDED)); // Verify Pub/Sub-specific data transformation. $message = $cloudevent->getData()['message']; @@ -249,7 +250,7 @@ public function testCloudStorage(): void 'objects/MyFile#1588778055917163', $cloudevent->getSubject() ); - $this->assertSame('2020-12-08T20:03:19.162Z', $cloudevent->getTime()); + $this->assertSame('2020-12-08T20:03:19.162+00:00', $cloudevent->getTime()->format(DateTimeInterface::RFC3339_EXTENDED)); $this->assertSame('foo', $cloudevent->getData()); } @@ -296,7 +297,8 @@ public function testFirebaseAuth(): void 'users/UUpby3s4spZre6kHsgVSPetzQ8l2', $cloudevent->getSubject() ); - $this->assertSame('2020-09-29T11:32:00.000Z', $cloudevent->getTime()); + var_dump($cloudevent->getTime()); + $this->assertSame('2020-09-29T11:32:00.000+00:00', $cloudevent->getTime()->format(DateTimeInterface::RFC3339_EXTENDED)); $this->assertSame('2020-05-26T10:42:27Z', $cloudevent->getData()['metadata']['createTime']); $this->assertSame('2020-10-24T11:00:00Z', $cloudevent->getData()['metadata']['lastSignInTime']); } @@ -341,7 +343,7 @@ public function testFirebaseAuthDbDelete(): void 'refs/gcf-test/xyz', $cloudevent->getSubject() ); - $this->assertSame('2020-05-21T11:53:45.337Z', $cloudevent->getTime()); + $this->assertSame('2020-05-21T11:53:45.337+00:00', $cloudevent->getTime()->format(DateTimeInterface::RFC3339_EXTENDED)); } public function testFirebaseAuthDbDeleteWithAlternateDomain(): void @@ -384,7 +386,7 @@ public function testFirebaseAuthDbDeleteWithAlternateDomain(): void 'refs/gcf-test/xyz', $cloudevent->getSubject() ); - $this->assertSame('2020-05-21T11:53:45.337Z', $cloudevent->getTime()); + $this->assertSame('2020-05-21T11:53:45.337+00:00', $cloudevent->getTime()->format(DateTimeInterface::RFC3339_EXTENDED)); } public function testFirebaseAuthDbDeleteWithInvalidDomain(): void @@ -424,6 +426,6 @@ public function testFirebaseAuthDbDeleteWithInvalidDomain(): void $this->assertSame('application/json', $cloudevent->getDataContentType()); $this->assertNull($cloudevent->getDataSchema()); $this->assertNull($cloudevent->getSubject()); - $this->assertSame('2020-05-21T11:53:45.337Z', $cloudevent->getTime()); + $this->assertSame('2020-05-21T11:53:45.337+00:00', $cloudevent->getTime()->format(DateTimeInterface::RFC3339_EXTENDED)); } } diff --git a/tests/conformance/index.php b/tests/conformance/index.php index ac4b1f21..34da6e54 100644 --- a/tests/conformance/index.php +++ b/tests/conformance/index.php @@ -93,7 +93,7 @@ function fixCloudEventData(CloudEvent $cloudevent): CloudEvent $cloudevent->getDatacontenttype(), $cloudevent->getDataschema(), $cloudevent->getSubject(), - $cloudevent->getTime(), + $cloudevent->getTime()->format(DateTimeInterface::RFC3339_EXTENDED), $data ); }