From a81db1cf9a53647c8f0006a7857e67e13a626ae2 Mon Sep 17 00:00:00 2001 From: ArrayIterator Date: Fri, 26 Jul 2024 00:15:12 +0700 Subject: [PATCH] add date fixer --- .../Types/Converters/DateConversionTrait.php | 72 +++++++++++++++++++ .../Types/Converters/DatetimeConversion.php | 24 +++++++ .../DatetimeImmutableConversion.php | 24 +++++++ src/Database/Types/DateTypeWrapper.php | 66 +++++------------ 4 files changed, 137 insertions(+), 49 deletions(-) create mode 100644 src/Database/Types/Converters/DateConversionTrait.php create mode 100644 src/Database/Types/Converters/DatetimeConversion.php create mode 100644 src/Database/Types/Converters/DatetimeImmutableConversion.php diff --git a/src/Database/Types/Converters/DateConversionTrait.php b/src/Database/Types/Converters/DateConversionTrait.php new file mode 100644 index 0000000..5a32fd2 --- /dev/null +++ b/src/Database/Types/Converters/DateConversionTrait.php @@ -0,0 +1,72 @@ + $val) { + $value[$key] = $this->convertDateString($val); + } + return $value; + } + if ($value && is_string($value) && str_starts_with($value, '-000')) { + $value = preg_replace_callback( + '/^-(0001)([^0-9]+)?(?:(0[0-9]|1[1-2])([^0-9]+)([1-2][0-9]|3[0-1]))?/', + static function ($match) { + if ($match[0] === '0001-11-30 00:00:00') { + return '0000-00-00 00:00:00'; + } + if ($match[0] === '0001-11-30') { + return '0000-00-00'; + } + if ($match[0] === '0001') { + return '0000'; + } + if (str_starts_with($match[0], '0001-11-')) { + return substr_replace($match[0], '0000-00-00', 0, 10); + } + if (str_starts_with($match[0], '0001-11')) { + return substr_replace($match[0], '0000-00', 0, 7); + } + if (!isset($match[3])) { + return $match[1] . ($match[2]??''); + } + if (intval($match[3]) >= 11) { + $year = intval($match[1]) - 1; + $match[1] = str_pad((string)$year, 4, '0', STR_PAD_LEFT); + $match[3] = '00'; + $match[5] = '00'; + } else { + $month = $match[3]; + $intMonth = intval($month); + $match[3] = str_pad((string)($intMonth + 1), 2, '0', STR_PAD_LEFT); + $day = intval($match[5]) + 1; + $_31_days_month = [1, 3, 5, 7, 8, 10, 12]; + if (in_array($intMonth, $_31_days_month, true) && $day > 31) { + $match[5] = '01'; + } elseif ($intMonth === 2 && $day > 29) { + $match[5] = '01'; + } elseif ($day > 30) { + $match[5] = '01'; + } else { + $match[5] = str_pad((string)$day, 2, '0', STR_PAD_LEFT); + } + } + return $match[1] . $match[2] . $match[3] . $match[4] . $match[5]; + }, + $value + ); + } + return $value; + } +} diff --git a/src/Database/Types/Converters/DatetimeConversion.php b/src/Database/Types/Converters/DatetimeConversion.php new file mode 100644 index 0000000..b345d39 --- /dev/null +++ b/src/Database/Types/Converters/DatetimeConversion.php @@ -0,0 +1,24 @@ +getTimezone()), true); + return [ + 'date' => $this->convertDateString($this->format(self::FORMAT)), + ...$tz + ]; + } +} diff --git a/src/Database/Types/Converters/DatetimeImmutableConversion.php b/src/Database/Types/Converters/DatetimeImmutableConversion.php new file mode 100644 index 0000000..dd5b93a --- /dev/null +++ b/src/Database/Types/Converters/DatetimeImmutableConversion.php @@ -0,0 +1,24 @@ +getTimezone()), true); + return [ + 'date' => $this->convertDateString($this->format(self::FORMAT)), + ...$tz + ]; + } +} diff --git a/src/Database/Types/DateTypeWrapper.php b/src/Database/Types/DateTypeWrapper.php index 5fc5623..7110b24 100644 --- a/src/Database/Types/DateTypeWrapper.php +++ b/src/Database/Types/DateTypeWrapper.php @@ -4,8 +4,13 @@ namespace ArrayAccess\TrayDigita\Database\Types; +use ArrayAccess\TrayDigita\Database\Types\Converters\DatetimeConversion; +use ArrayAccess\TrayDigita\Database\Types\Converters\DatetimeImmutableConversion; +use ArrayAccess\TrayDigita\Database\Types\Converters\DateConversionTrait; use ArrayAccess\TrayDigita\Exceptions\InvalidArgument\InvalidArgumentException; use BadMethodCallException; +use DateTime; +use DateTimeImmutable; use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Types\DateType; use Doctrine\DBAL\Types\PhpDateTimeMappingType; @@ -18,6 +23,8 @@ */ class DateTypeWrapper extends Type implements PhpDateTimeMappingType { + use DateConversionTrait; + /** * Wrapped type of DateType. * @@ -72,53 +79,7 @@ public function convertToDatabaseValue($value, AbstractPlatform $platform) : ?st } else { $value = parent::convertToDatabaseValue($value, $platform); } - if ($value && is_string($value) && str_starts_with($value, '-000')) { - $value = preg_replace_callback( - '/^-(0001)([^0-9]+)?(?:(0[0-9]|1[1-2])([^0-9]+)([1-2][0-9]|3[0-1]))?/', - static function ($match) { - if ($match[0] === '0001-11-30 00:00:00') { - return '0000-00-00 00:00:00'; - } - if ($match[0] === '0001') { - return '0000'; - } - if (str_starts_with($match[0], '0001-11-')) { - return substr_replace($match[0], '0000-00-00', 0, 10); - } - if (str_starts_with($match[0], '0001-11')) { - return substr_replace($match[0], '0000-00', 0, 7); - } - if (!isset($match[3])) { - return $match[1] . ($match[2]??''); - } - if (intval($match[3]) >= 11) { - $year = intval($match[1]) + 1; - $match[1] = str_pad((string)$year, 4, '0', STR_PAD_LEFT); - $match[3] = '00'; - $match[5] = '00'; - } else { - $month = $match[3]; - $intMonth = intval($month); - $match[3] = str_pad((string)($intMonth + 1), 2, '0', STR_PAD_LEFT); - $day = intval($match[5]) + 1; - $_31_days_month = [1, 3, 5, 7, 8, 10, 12]; - if (in_array($intMonth, $_31_days_month, true) && $day > 31) { - $match[5] = '01'; - } elseif ($intMonth === 2 && $day > 29) { - $match[5] = '01'; - } elseif ($day > 30) { - $match[5] = '01'; - } else { - $match[5] = str_pad((string)$day, 2, '0', STR_PAD_LEFT); - } - } - return $match[1] . $match[2] . $match[3] . $match[4] . $match[5]; - }, - $value - ); - } - - return $value; + return $this->convertDateString($value); } /** @@ -127,9 +88,16 @@ static function ($match) { public function convertToPHPValue($value, AbstractPlatform $platform): mixed { if (isset($this->wrappedType)) { - return $this->wrappedType->convertToPHPValue($value, $platform); + $date = $this->wrappedType->convertToPHPValue($value, $platform); + } else { + $date = parent::convertToPHPValue($value, $platform); + } + if ($date instanceof DateTimeImmutable) { + $date = DatetimeImmutableConversion::createFromInterface($date); + } elseif ($date instanceof DateTime) { + $date = DatetimeConversion::createFromInterface($date); } - return parent::convertToPHPValue($value, $platform); + return $date; } public function getSQLDeclaration(array $column, AbstractPlatform $platform): string