Skip to content

Commit f0c37e5

Browse files
authored
Merge pull request #417 from keboola/jv-fix-datetime-format
[internal-api-client] Fix datetime timezone offset format #2
2 parents 422db12 + b5d3b56 commit f0c37e5

File tree

2 files changed

+59
-35
lines changed

2 files changed

+59
-35
lines changed

src/JobFactory/Job.php

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
use JsonSerializable;
1111
use Keboola\JobQueueInternalClient\Exception\ClientException;
1212
use Keboola\JobQueueInternalClient\JobFactory;
13-
use Keboola\JobQueueInternalClient\JobFactory\JobObjectEncryptor;
1413
use Keboola\JobQueueInternalClient\JobFactory\Runtime\Backend;
1514
use Keboola\JobQueueInternalClient\JobFactory\Runtime\Executor;
1615
use Keboola\JobQueueInternalClient\Result\JobMetrics;
@@ -27,8 +26,8 @@
2726

2827
class Job implements JsonSerializable, JobInterface
2928
{
30-
private ?DateTimeImmutable $endTime;
31-
private ?DateTimeImmutable $startTime;
29+
private ?DateTimeImmutable $endTime = null;
30+
private ?DateTimeImmutable $startTime = null;
3231
private ?DateTimeImmutable $createdTime = null;
3332
private ?string $tokenDecrypted = null;
3433
private ?string $executionTokenDecrypted = null;
@@ -52,18 +51,17 @@ public function __construct(
5251
$this->data['isFinished'] = in_array($this->getStatus(), JobInterface::STATUSES_FINISHED);
5352
$this->data['parentRunId'] = $this->getParentRunId();
5453

55-
$this->startTime = null;
56-
$this->endTime = null;
57-
5854
if (!empty($this->data['startTime'])) {
59-
$this->startTime = $this->data['startTime'] = $this->createNormalizedDatetime($this->data['startTime']);
55+
$this->startTime = new DateTimeImmutable($this->data['startTime'], new DateTimeZone('utc'));
56+
$this->data['startTime'] = $this->startTime->format('c');
6057
}
6158
if (!empty($this->data['endTime'])) {
62-
$this->endTime = $this->data['endTime']= $this->createNormalizedDatetime($this->data['endTime']);
59+
$this->endTime = new DateTimeImmutable($this->data['endTime'], new DateTimeZone('utc'));
60+
$this->data['endTime'] = $this->endTime->format('c');
6361
}
6462
if (!empty($this->data['createdTime'])) {
65-
$this->createdTime = $this->data['createdTime'] =
66-
$this->createNormalizedDatetime($this->data['createdTime']);
63+
$this->createdTime = new DateTimeImmutable($this->data['createdTime'], new DateTimeZone('utc'));
64+
$this->data['createdTime'] = $this->createdTime->format('c');
6765
}
6866
}
6967

@@ -423,15 +421,4 @@ public function getCreatedTime(): ?DateTimeImmutable
423421
{
424422
return $this->createdTime;
425423
}
426-
427-
private function createNormalizedDatetime(string $datetimeString): ?DateTimeImmutable
428-
{
429-
try {
430-
$date = new DateTimeImmutable($datetimeString, new DateTimeZone('utc'));
431-
$timezoneOffset = $date->format('P'); // e.g. Z => +00:00
432-
return $date->setTimezone(new DateTimeZone($timezoneOffset));
433-
} catch (Throwable) {
434-
return null;
435-
}
436-
}
437424
}

tests/JobFactory/JobTest.php

Lines changed: 51 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use Keboola\StorageApiBranch\Factory\StorageClientPlainFactory;
2121
use RuntimeException;
2222
use Symfony\Component\Uid\Uuid;
23+
use Throwable;
2324

2425
class JobTest extends BaseTest
2526
{
@@ -1019,45 +1020,81 @@ public function testGetExecutionTokenDecryptedNoFeature(): void
10191020
self::assertSame('token', $executionToken);
10201021
}
10211022

1022-
public static function provideDatetimeStrings(): iterable
1023+
public static function provideValidDatetimeStrings(): iterable
10231024
{
10241025
yield 'endTime - MySQL offset' => [
10251026
'datetimeString' => '2024-06-11T10:11:37+00:00',
1026-
'timeField' => 'endTime',
1027+
'datetimeField' => 'endTime',
10271028
];
10281029
yield 'endTime - Elastic offset' => [
10291030
'datetimeString' => '2024-06-11T10:11:37.000Z',
1030-
'timeField' => 'endTime',
1031+
'datetimeField' => 'endTime',
10311032
];
10321033
yield 'startTime - MySQL offset' => [
10331034
'datetimeString' => '2024-06-11T10:11:37+00:00',
1034-
'timeField' => 'startTime',
1035+
'datetimeField' => 'startTime',
10351036
];
10361037
yield 'startTime - Elastic offset' => [
10371038
'datetimeString' => '2024-06-11T10:11:37.000Z',
1038-
'timeField' => 'startTime',
1039+
'datetimeField' => 'startTime',
10391040
];
10401041
yield 'createdTime - MySQL offset' => [
10411042
'datetimeString' => '2024-06-11T10:11:37+00:00',
1042-
'timeField' => 'createdTime',
1043+
'datetimeField' => 'createdTime',
10431044
];
10441045
yield 'createdTime - Elastic offset' => [
10451046
'datetimeString' => '2024-06-11T10:11:37.000Z',
1046-
'timeField' => 'createdTime',
1047+
'datetimeField' => 'createdTime',
10471048
];
10481049
}
10491050

1050-
/** @dataProvider provideDatetimeStrings */
1051-
public function testTimeGetters(string $datetimeString, string $timeField): void
1051+
/** @dataProvider provideValidDatetimeStrings */
1052+
public function testDatetimeFields(string $datetimeString, string $datetimeField): void
10521053
{
10531054
$jobData = $this->jobData;
1054-
$getterMethodName = 'get' . ucfirst($timeField);
1055-
self::assertNull($this->getJob($jobData)->$getterMethodName());
1055+
$fieldGetterName = 'get' . ucfirst($datetimeField);
1056+
self::assertNull($this->getJob($jobData)->$fieldGetterName());
10561057

1057-
$jobData[$timeField] = $datetimeString;
1058+
$jobData[$datetimeField] = $datetimeString;
10581059
$job = $this->getJob($jobData);
10591060

1060-
self::assertEquals(new DateTimeImmutable('2024-06-11T10:11:37+00:00'), $job->$getterMethodName());
1061-
self::assertEquals('+00:00', $job->$getterMethodName()->getTimezone()->getName());
1061+
self::assertEquals(new DateTimeImmutable('2024-06-11T10:11:37+00:00'), $job->$fieldGetterName());
1062+
self::assertEquals('2024-06-11T10:11:37+00:00', $job->jsonSerialize()[$datetimeField]);
1063+
}
1064+
1065+
public static function provideDatetimeFields(): iterable
1066+
{
1067+
yield 'endTime' => ['datetimeField' => 'endTime'];
1068+
yield 'startTime' => ['datetimeField' => 'startTime'];
1069+
yield 'createdTime' => ['datetimeField' => 'createdTime'];
1070+
}
1071+
1072+
/** @dataProvider provideDatetimeFields */
1073+
public function testDatetimeFieldsEmpty(string $datetimeField): void
1074+
{
1075+
$jobData = $this->jobData;
1076+
$fieldGetterName = 'get' . ucfirst($datetimeField);
1077+
self::assertNull($this->getJob($jobData)->$fieldGetterName());
1078+
1079+
$jobData[$datetimeField] = null;
1080+
$job = $this->getJob($jobData);
1081+
1082+
self::assertNull($job->$fieldGetterName());
1083+
self::assertNull($job->jsonSerialize()[$datetimeField]);
1084+
}
1085+
1086+
/** @dataProvider provideDatetimeFields */
1087+
public function testDatetimeFieldsException(string $datetimeField): void
1088+
{
1089+
$jobData = $this->jobData;
1090+
$fieldGetterName = 'get' . ucfirst($datetimeField);
1091+
self::assertNull($this->getJob($jobData)->$fieldGetterName());
1092+
1093+
$jobData[$datetimeField] = 'invalid datetime string';
1094+
1095+
self::expectException(Throwable::class);
1096+
self::expectExceptionMessage('Failed to parse time string');
1097+
1098+
$this->getJob($jobData);
10621099
}
10631100
}

0 commit comments

Comments
 (0)