Skip to content

Commit a024cad

Browse files
committed
feat: support clickhouse timezone input in ParamValueConverterRegistry
1 parent 9a90f8e commit a024cad

File tree

2 files changed

+50
-22
lines changed

2 files changed

+50
-22
lines changed

src/Param/ParamValueConverterRegistry.php

Lines changed: 47 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66

77
use Closure;
88
use DateTimeInterface;
9+
use DateTimeZone;
910
use Psr\Http\Message\StreamInterface;
1011
use SimPod\ClickHouseClient\Exception\UnsupportedParamType;
12+
use SimPod\ClickHouseClient\Exception\UnsupportedParamValue;
1113
use SimPod\ClickHouseClient\Sql\Type;
1214

1315
use function array_keys;
@@ -16,6 +18,8 @@
1618
use function implode;
1719
use function in_array;
1820
use function is_array;
21+
use function is_float;
22+
use function is_int;
1923
use function is_string;
2024
use function json_encode;
2125
use function sprintf;
@@ -24,11 +28,10 @@
2428
use function strtolower;
2529
use function trim;
2630

27-
/** @phpstan-type Converter = Closure(mixed, Type|string|null, bool):(StreamInterface|string) */
28-
final class ParamValueConverterRegistry
31+
/** @phpstan-type Converter Closure(mixed, Type|string|null, bool):(StreamInterface|string) */
32+
final readonly class ParamValueConverterRegistry
2933
{
30-
/** @var list<string> */
31-
private static array $caseInsensitiveTypes = [
34+
private const CaseInsensitiveTypes = [
3235
'bool',
3336
'date',
3437
'date32',
@@ -47,8 +50,9 @@ final class ParamValueConverterRegistry
4750
/** @phpstan-var array<string, Converter> */
4851
private array $registry;
4952

50-
public function __construct()
51-
{
53+
public function __construct(
54+
private DateTimeZone|null $clickHouseTimeZone = null,
55+
) {
5256
$formatPoint = static fn (array $point) => sprintf('(%s)', implode(',', $point));
5357
// phpcs:ignore SlevomatCodingStandard.Functions.RequireArrowFunction.RequiredArrowFunction
5458
$formatRingOrLineString = static function (array $v) use ($formatPoint) {
@@ -85,10 +89,10 @@ public function __construct()
8589

8690
'bool' => static fn (bool $value) => $value,
8791

88-
'date' => self::dateConverter(),
89-
'date32' => self::dateConverter(),
90-
'datetime' => self::dateTimeConverter(),
91-
'datetime32' => self::dateTimeConverter(),
92+
'date' => self::dateConverter($this->clickHouseTimeZone),
93+
'date32' => self::dateConverter($this->clickHouseTimeZone),
94+
'datetime' => self::dateTimeConverter($this->clickHouseTimeZone),
95+
'datetime32' => self::dateTimeConverter($this->clickHouseTimeZone),
9296
'datetime64' => static fn (DateTimeInterface|string|int|float $value) => $value instanceof DateTimeInterface
9397
? $value->format('Y-m-d H:i:s.u')
9498
: $value,
@@ -227,7 +231,7 @@ public function get(Type|string $type): Closure
227231

228232
$typeName = strtolower($typeName);
229233
$converter = $this->registry[$typeName] ?? null;
230-
if ($converter !== null && in_array($typeName, self::$caseInsensitiveTypes, true)) {
234+
if ($converter !== null && in_array($typeName, self::CaseInsensitiveTypes, true)) {
231235
return $converter;
232236
}
233237

@@ -264,18 +268,42 @@ private static function decimalConverter(): Closure
264268
return static fn (float|int|string $value) => $value;
265269
}
266270

267-
private static function dateConverter(): Closure
271+
private static function dateConverter(DateTimeZone|null $clickHouseTimeZone): Closure
268272
{
269-
return static fn (DateTimeInterface|string|int|float $value) => $value instanceof DateTimeInterface
270-
? $value->format('Y-m-d')
271-
: $value;
273+
return static function (mixed $value) use ($clickHouseTimeZone) {
274+
if ($value instanceof DateTimeInterface) {
275+
if ($clickHouseTimeZone !== null) {
276+
$value = $value->setTimezone($clickHouseTimeZone);
277+
}
278+
279+
return $value->format('Y-m-d');
280+
}
281+
282+
if (is_string($value) || is_float($value) || is_int($value)) {
283+
return $value;
284+
}
285+
286+
throw UnsupportedParamValue::type($value);
287+
};
272288
}
273289

274-
private static function dateTimeConverter(): Closure
290+
private static function dateTimeConverter(DateTimeZone|null $clickHouseTimeZone): Closure
275291
{
276-
return static fn (DateTimeInterface|string|int|float $value) => $value instanceof DateTimeInterface
277-
? $value->format('Y-m-d H:i:s')
278-
: $value;
292+
return static function (mixed $value) use ($clickHouseTimeZone) {
293+
if ($value instanceof DateTimeInterface) {
294+
if ($clickHouseTimeZone !== null) {
295+
$value = $value->setTimezone($clickHouseTimeZone);
296+
}
297+
298+
return $value->format('Y-m-d H:i:s');
299+
}
300+
301+
if (is_string($value) || is_float($value) || is_int($value)) {
302+
return $value;
303+
}
304+
305+
throw UnsupportedParamValue::type($value);
306+
};
279307
}
280308

281309
private static function dateIntervalConverter(): Closure

src/Sql/ValueFormatter.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
/** @internal */
2727
final readonly class ValueFormatter
2828
{
29-
public function __construct(private DateTimeZone|null $dateTimeZone = null)
29+
public function __construct(private DateTimeZone|null $clickHouseTimeZone = null)
3030
{
3131
}
3232

@@ -67,8 +67,8 @@ public function format(mixed $value, string|null $paramName = null, string|null
6767
}
6868

6969
if ($value instanceof DateTimeImmutable) {
70-
if ($this->dateTimeZone !== null) {
71-
$value = $value->setTimezone($this->dateTimeZone);
70+
if ($this->clickHouseTimeZone !== null) {
71+
$value = $value->setTimezone($this->clickHouseTimeZone);
7272
}
7373

7474
return "'" . $value->format('Y-m-d H:i:s') . "'";

0 commit comments

Comments
 (0)