Created
January 29, 2022 07:54
-
-
Save Schrank/d1f3243e47e52bc20809a3c20cd0441a to your computer and use it in GitHub Desktop.
Doctrine 2.11, Datetime and Microseconds
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
namespace Winkelwagen\Dbal; | |
use Doctrine\DBAL\Platforms\AbstractPlatform; | |
use Doctrine\DBAL\Platforms\PostgreSQLPlatform; | |
use Doctrine\DBAL\Types\ConversionException; | |
use Doctrine\DBAL\Types\Type; | |
class DateTimeWithMicroseconds extends Type | |
{ | |
private const TYPENAME = 'datetime'; | |
public function getSQLDeclaration(array $column, AbstractPlatform $platform): string | |
{ | |
if (isset($column['version']) && $column['version'] === true) { | |
return 'TIMESTAMP'; | |
} | |
if ($platform instanceof PostgreSqlPlatform) { | |
return 'TIMESTAMP(6) WITHOUT TIME ZONE'; | |
} | |
return 'DATETIME(6)'; | |
} | |
public function convertToPHPValue($value, AbstractPlatform $platform): mixed | |
{ | |
if ($value === null || $value instanceof \DateTimeInterface) { | |
return $value; | |
} | |
if (str_contains($value, '.')) { | |
return \DateTimeImmutable::createFromFormat('Y-m-d H:i:s.u', $value); | |
} | |
return \DateTimeImmutable::createFromFormat('Y-m-d H:i:s', $value); | |
} | |
public function convertToDatabaseValue($value, AbstractPlatform $platform): mixed | |
{ | |
if (null === $value) { | |
return null; | |
} | |
if ($value instanceof \DateTimeInterface) { | |
return $value->format('Y-m-d H:i:s.u'); | |
} | |
throw ConversionException::conversionFailedInvalidType( | |
$value, | |
$this->getName(), | |
['null', 'DateTime'] | |
); | |
} | |
public function getName(): string | |
{ | |
return self::TYPENAME; | |
} | |
public function requiresSQLCommentHint(AbstractPlatform $platform): bool | |
{ | |
return true; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
namespace Winkelwagen\Dbal; | |
use Doctrine\DBAL\Platforms\AbstractPlatform; | |
use Doctrine\DBAL\Platforms\PostgreSQLPlatform; | |
use Doctrine\DBAL\Types\ConversionException; | |
use JetBrains\PhpStorm\ArrayShape; | |
use PHPUnit\Framework\TestCase; | |
class DateTimeWithMicrosecondsTest extends TestCase | |
{ | |
private DateTimeWithMicroseconds $type; | |
protected function setUp(): void | |
{ | |
parent::setUp(); | |
$this->type = new DateTimeWithMicroseconds(); | |
} | |
public function testSqlDeclarationIsTimestampForVersionTrue(): void | |
{ | |
$column = ['version' => true]; | |
$platform = $this->createMock(AbstractPlatform::class); | |
$this->assertSame('TIMESTAMP', $this->type->getSQLDeclaration($column, $platform)); | |
} | |
public function testSqlDeclarationForPostgre(): void | |
{ | |
$column = []; | |
$platform = $this->createMock(PostgreSqlPlatform::class); | |
$this->assertSame('TIMESTAMP(6) WITHOUT TIME ZONE', $this->type->getSQLDeclaration($column, $platform)); | |
} | |
public function testSqlDeclarationDefaultIsTimestamp6(): void | |
{ | |
$column = []; | |
$platform = $this->createMock(AbstractPlatform::class); | |
$this->assertSame('DATETIME(6)', $this->type->getSQLDeclaration($column, $platform)); | |
} | |
/** | |
* @dataProvider provideTimestamps | |
*/ | |
public function testConvertToPhpValue($value, $expected): void | |
{ | |
$platform = $this->createMock(AbstractPlatform::class); | |
$this->assertEquals($expected, $this->type->convertToPHPValue($value, $platform)); | |
} | |
#[ArrayShape([ | |
'null' => "null[]", | |
'with zero microseconds' => "array", | |
'without microseconds' => "array", | |
'with 200 microseconds' => "array" | |
])] public function provideTimestamps(): array | |
{ | |
return [ | |
'null' => [null, null], | |
'with zero microseconds' => ['2001-01-03 12:46:18.000', new \DateTimeImmutable('2001-01-03 12:46:18.000')], | |
'without microseconds' => ['2001-01-03 12:46:18', new \DateTimeImmutable('2001-01-03 12:46:18.000')], | |
'with 200 microseconds' => ['2001-01-03 12:46:18.200', new \DateTimeImmutable('2001-01-03 12:46:18.200')], | |
]; | |
} | |
/** | |
* @dataProvider provideDateTimeObject | |
*/ | |
public function testConvertToDatabaseValue($value, $expected): void | |
{ | |
$platform = $this->createMock(AbstractPlatform::class); | |
$this->assertSame($expected, $this->type->convertToDatabaseValue($value, $platform)); | |
} | |
#[ArrayShape([ | |
'null' => "null[]", | |
'with zero microseconds' => "array", | |
'without microseconds' => "array", | |
'with 200 microseconds' => "array" | |
])] public function provideDateTimeObject(): array | |
{ | |
return [ | |
'null' => [null, null], | |
'with zero microseconds' => [ | |
new \DateTimeImmutable('2001-01-03 12:46:18.000'), | |
'2001-01-03 12:46:18.000000' | |
], | |
'without microseconds' => [new \DateTimeImmutable('2001-01-03 12:46:18.000'), '2001-01-03 12:46:18.000000'], | |
'with 200 microseconds' => [ | |
new \DateTimeImmutable('2001-01-03 12:46:18.200'), | |
'2001-01-03 12:46:18.200000' | |
], | |
]; | |
} | |
public function testThrowsExceptionIfNotDateTimeOrNullOnConvertToDatabase(): void | |
{ | |
$this->expectException(ConversionException::class); | |
$platform = $this->createMock(AbstractPlatform::class); | |
$this->type->convertToDatabaseValue('not an object', $platform); | |
} | |
public function testGetName(): void | |
{ | |
$this->assertSame('datetime', $this->type->getName()); | |
} | |
public function testRequiresSqlCommentHint(): void | |
{ | |
$platform = $this->createMock(AbstractPlatform::class); | |
$this->assertTrue($this->type->requiresSQLCommentHint($platform)); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
doctrine: | |
dbal: | |
types: | |
datetime: \Paddox\Dbal\DateTimeWithMicroseconds |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment