-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Open
Description
Hello,
I'm trying to create a custom type for datetime with microseconds, but I can't figure how.
Schema tool always wants me to execute ALTER TABLE foo ALTER occurred_at TYPE IMESTAMP(6) WITHOUT TIME ZONE;
because PostgreSQL introspection returns just timestamp without time zone, even if I defined timestamp(6).
Before DBAL 4, this could be easily solved by using a comment with an exact type and requiresSQLCommentHint().
Or in general - what can I do if I have multiple custom types (PHP objects) represented in the database by the same data type?
What should I do with DBAL 4, please? I am using PostgreSQL 17.1.
Here is my custom DateTimeImmutableMicroType:
<?php declare(strict_types = 1);
namespace MyApp\DateTime;
use DateTimeImmutable;
use DateTimeZone;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
use Doctrine\DBAL\Types\DateTimeImmutableType as DoctrineDateTimeImmutableTypeAlias;
use Doctrine\DBAL\Types\Exception\InvalidFormat;
use Doctrine\DBAL\Types\Exception\InvalidType;
class DateTimeImmutableMicroType extends DoctrineDateTimeImmutableTypeAlias
{
private const string DATABASE_TIME_ZONE = 'Europe/Prague';
/**
* {@inheritDoc}
*/
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform): string
{
if (isset($fieldDeclaration['version']) && $fieldDeclaration['version'] === true) {
return 'TIMESTAMP';
}
if ($platform instanceof PostgreSqlPlatform) {
return 'TIMESTAMP(6) WITHOUT TIME ZONE';
}
return 'DATETIME(6)';
}
/**
* @param T $value
* @return (T is null ? null : string)
* @template T
*/
public function convertToDatabaseValue(mixed $value, AbstractPlatform $platform): ?string
{
if ($value === null) {
return $value;
}
if ($value instanceof DateTimeImmutable) {
$value = $value->setTimezone(new DateTimeZone(self::DATABASE_TIME_ZONE));
return $value->format('Y-m-d H:i:s.u');
}
throw InvalidType::new(
$value,
static::class,
['null', DateTimeImmutable::class],
);
}
/**
* @param T $value
* @return (T is null ? null : DateTimeImmutable)
* @template T
*/
public function convertToPHPValue(mixed $value, AbstractPlatform $platform): ?DateTimeImmutable
{
if ($value === null || $value instanceof DateTimeImmutable) {
return $value;
}
$dateTime = DateTimeImmutable::createFromFormat('Y-m-d H:i:s.u', $value, new DateTimeZone(self::DATABASE_TIME_ZONE));
if ($dateTime !== false) {
return $dateTime;
}
try {
return new DateTimeImmutable($value);
} catch (\Throwable $e) {
throw InvalidFormat::new(
$value,
static::class,
$platform->getDateTimeFormatString(),
$e,
);
}
}
}
Metadata
Metadata
Assignees
Labels
No labels