Skip to content

Commit ae2a92b

Browse files
authored
Added modifyDateTime scalar function (#1543)
1 parent 4b452a2 commit ae2a92b

4 files changed

Lines changed: 170 additions & 0 deletions

File tree

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Flow\ETL\Function;
6+
7+
use Flow\ETL\Row;
8+
9+
final class ModifyDateTime extends ScalarFunctionChain
10+
{
11+
public function __construct(
12+
private readonly mixed $reference,
13+
private readonly string|ScalarFunction $modifier,
14+
) {
15+
}
16+
17+
public function eval(Row $row) : mixed
18+
{
19+
$value = (new Parameter($this->reference))->asInstanceOf($row, \DateTimeInterface::class);
20+
$modifier = (new Parameter($this->modifier))->asString($row);
21+
22+
if ($modifier === null || $value === null) {
23+
return null;
24+
}
25+
26+
if (!$value instanceof \DateTime && !$value instanceof \DateTimeImmutable) {
27+
return null;
28+
}
29+
30+
return $value->modify($modifier);
31+
}
32+
}

src/core/etl/src/Flow/ETL/Function/ScalarFunctionChain.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,11 @@ public function mod(ScalarFunction|int|float $value) : self
372372
return new Mod($this, $value);
373373
}
374374

375+
public function modifyDateTime(string|ScalarFunction $modifier) : self
376+
{
377+
return new ModifyDateTime($this, $modifier);
378+
}
379+
375380
public function multiply(ScalarFunction|int|float $value) : self
376381
{
377382
return new Multiply($this, $value);
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Flow\ETL\Tests\Integration\Function;
6+
7+
use function Flow\ETL\DSL\data_frame;
8+
use function Flow\ETL\DSL\{array_get, concat, from_array, lit, ref, to_memory};
9+
use Flow\ETL\Memory\ArrayMemory;
10+
use Flow\ETL\Tests\FlowTestCase;
11+
12+
final class ModifyDateTimeTest extends FlowTestCase
13+
{
14+
public function test_concat_on_non_string_value() : void
15+
{
16+
$rows = (data_frame())
17+
->read(
18+
from_array(
19+
[
20+
['id' => 1, 'created_at' => new \DateTimeImmutable('2025-01-01')],
21+
['id' => 2, 'created_at' => new \DateTimeImmutable('2025-02-01')],
22+
]
23+
)
24+
)
25+
->withEntry('expiration_at', ref('created_at')->modifyDateTime('last day of this month'))
26+
->fetch()
27+
->toArray();
28+
29+
self::assertEquals(
30+
[
31+
['id' => 1, 'created_at' => new \DateTimeImmutable('2025-01-01'), 'expiration_at' => new \DateTimeImmutable('2025-01-31')],
32+
['id' => 2, 'created_at' => new \DateTimeImmutable('2025-02-01'), 'expiration_at' => new \DateTimeImmutable('2025-02-28')],
33+
],
34+
$rows,
35+
);
36+
}
37+
38+
public function test_concat_on_nulls() : void
39+
{
40+
(data_frame())
41+
->read(
42+
from_array(
43+
[
44+
['id' => 1, 'array' => ['field' => 'value']],
45+
['id' => 2],
46+
]
47+
)
48+
)
49+
->withEntry('concat', concat(lit(null), lit(null)))
50+
->drop('array')
51+
->write(to_memory($memory = new ArrayMemory()))
52+
->run();
53+
54+
self::assertSame(
55+
[
56+
['id' => 1, 'concat' => ''],
57+
['id' => 2, 'concat' => ''],
58+
],
59+
$memory->dump()
60+
);
61+
}
62+
63+
public function test_concat_on_stringable_value() : void
64+
{
65+
(data_frame())
66+
->read(
67+
from_array(
68+
[
69+
['id' => 1, 'array' => ['field' => 'value']],
70+
['id' => 2],
71+
]
72+
)
73+
)
74+
->withEntry('concat', concat(ref('id'), '-', array_get(ref('array'), 'field')))
75+
->drop('array')
76+
->write(to_memory($memory = new ArrayMemory()))
77+
->run();
78+
79+
self::assertSame(
80+
[
81+
['id' => 1, 'concat' => '1-value'],
82+
['id' => 2, 'concat' => '2-'],
83+
],
84+
$memory->dump()
85+
);
86+
}
87+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Flow\ETL\Tests\Unit\Function;
6+
7+
use function Flow\ETL\DSL\{date_entry, datetime_entry, lit, ref, row};
8+
use Flow\ETL\Tests\FlowTestCase;
9+
10+
final class ModifyDateTimeTest extends FlowTestCase
11+
{
12+
public function test_modify_date() : void
13+
{
14+
self::assertEquals(
15+
new \DateTimeImmutable('2025-01-01 12:00:00 +00:00'),
16+
ref('datetime')->modifyDateTime('noon')->eval(
17+
row(
18+
date_entry('datetime', '2025-01-01'),
19+
)
20+
)
21+
);
22+
}
23+
24+
public function test_modify_datetime() : void
25+
{
26+
self::assertEquals(
27+
new \DateTimeImmutable('2025-01-01 00:00:00 +00:00'),
28+
ref('datetime')->modifyDateTime('midnight')->eval(
29+
row(
30+
datetime_entry('datetime', '2025-01-01 10:00:23 +00:00'),
31+
)
32+
)
33+
);
34+
}
35+
36+
public function test_modify_using_invalid_modifier() : void
37+
{
38+
self::assertNull(
39+
ref('datetime')->modifyDateTime(lit(1))->eval(
40+
row(
41+
datetime_entry('datetime', '2025-01-01 10:00:23 +00:00'),
42+
)
43+
)
44+
);
45+
}
46+
}

0 commit comments

Comments
 (0)