feat: DTO Convert 인자 버그 수정, DateTimeConverter 확장
- DateTimeConverter에 목표 Timezone 설정
This commit is contained in:
@@ -11,7 +11,7 @@ class Convert
|
||||
public function __construct(
|
||||
public readonly array $targetTypes,
|
||||
public readonly string $converterType,
|
||||
array ...$args
|
||||
...$args
|
||||
) {
|
||||
if(!is_subclass_of($converterType, \sammo\DTO\Converter\Converter::class)){
|
||||
throw new \Exception("$converterType is not a subclass of \sammo\DTO\Converter\Converter");
|
||||
|
||||
@@ -7,6 +7,7 @@ use sammo\TimeUtil;
|
||||
class DateTimeConverter implements Converter
|
||||
{
|
||||
protected bool $useFraction;
|
||||
protected \DateTimeZone $timeZoneOffset;
|
||||
public function __construct(private array $types, ...$args)
|
||||
{
|
||||
if(count($args) > 0) {
|
||||
@@ -17,6 +18,48 @@ class DateTimeConverter implements Converter
|
||||
} else {
|
||||
$this->useFraction = false;
|
||||
}
|
||||
|
||||
if(count($args) > 1) {
|
||||
$args1 = $args[1];
|
||||
if(is_int($args1)){
|
||||
if($args1 < -12 || $args1 > 14){
|
||||
throw new \Exception('TimeZone argument must be between -12 and 14');
|
||||
}
|
||||
if($args1 > 0){
|
||||
$offset = sprintf('+%02d00', $args1);
|
||||
}
|
||||
else{
|
||||
$offset = sprintf('-%02d00', abs($args1));
|
||||
}
|
||||
$this->timeZoneOffset = new \DateTimeZone($offset);
|
||||
} else if(is_float($args1)) {
|
||||
if($args1 < -12 || $args1 > 14){
|
||||
throw new \Exception('TimeZone argument must be between -12 and 14');
|
||||
}
|
||||
$isPositive = $args1 > 0;
|
||||
$offset = abs($args1);
|
||||
$hour = floor($offset);
|
||||
$minute = floor(($offset - $hour) * 60);
|
||||
if($isPositive){
|
||||
$offset = sprintf('+%02d%02d', $hour, $minute);
|
||||
} else {
|
||||
$offset = sprintf('-%02d%02d', $hour, $minute);
|
||||
}
|
||||
$this->timeZoneOffset = new \DateTimeZone($offset);
|
||||
}
|
||||
else if(is_string($args1)){
|
||||
$this->timeZoneOffset = new \DateTimeZone($args1);
|
||||
} else if($args1 instanceof \DateTimeZone){
|
||||
$this->timeZoneOffset = $args1;
|
||||
} else if($args1 === null){
|
||||
$this->timeZoneOffset = new \DateTimeZone(\date_default_timezone_get());
|
||||
} else {
|
||||
throw new \Exception('DateTimeConverter constructor argument must be int|string|\DateTimeZone');
|
||||
}
|
||||
}
|
||||
else{
|
||||
$this->timeZoneOffset = new \DateTimeZone(\date_default_timezone_get());
|
||||
}
|
||||
}
|
||||
|
||||
public function convertFrom(string|array|int|float|bool|null $raw): mixed
|
||||
@@ -27,10 +70,20 @@ class DateTimeConverter implements Converter
|
||||
if (!is_string($raw)){
|
||||
throw new \Exception('DateTimeConverter can not convert non-string');
|
||||
}
|
||||
if (array_search('DateTime', $this->types, true) === false) {
|
||||
return new \DateTime($raw);
|
||||
if (array_search('DateTimeImmutable', $this->types, true) !== false) {
|
||||
$objDateTime = new \DateTimeImmutable($raw, $this->timeZoneOffset);
|
||||
}
|
||||
return new \DateTimeImmutable($raw);
|
||||
else if (array_search('DateTime', $this->types, true) !== false) {
|
||||
$objDateTime = new \DateTime($raw, $this->timeZoneOffset);
|
||||
}
|
||||
else{
|
||||
$objDateTime = new \DateTimeImmutable($raw, $this->timeZoneOffset);
|
||||
}
|
||||
|
||||
if($objDateTime->getTimezone() !== $this->timeZoneOffset){
|
||||
$objDateTime = $objDateTime->setTimezone($this->timeZoneOffset);
|
||||
}
|
||||
return $objDateTime;
|
||||
}
|
||||
|
||||
public function convertTo(mixed $data): string|array|int|float|bool|null
|
||||
@@ -41,6 +94,10 @@ class DateTimeConverter implements Converter
|
||||
if (!$data instanceof \DateTimeInterface) {
|
||||
throw new \Exception('DateTimeConverter can not convert non-DateTimeInterface');
|
||||
}
|
||||
|
||||
if($data->getTimezone() !== $this->timeZoneOffset){
|
||||
$data = \DateTimeImmutable::createFromInterface($data)->setTimezone($this->timeZoneOffset);
|
||||
}
|
||||
return TimeUtil::format($data, $this->useFraction);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ use sammo\DTO\Attr\RawName;
|
||||
use sammo\DTO\Converter\ArrayConverter;
|
||||
use sammo\DTO\Converter\Converter;
|
||||
use sammo\DTO\Converter\MapConverter;
|
||||
use sammo\DTO\Converter\DateTimeConverter;
|
||||
use sammo\Json;
|
||||
|
||||
class TypeA extends DTO
|
||||
@@ -155,6 +156,21 @@ class TypeRawName extends DTO
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class TypeDateTime extends DTO{
|
||||
public function __construct(
|
||||
#[Convert(DateTimeConverter::class)]
|
||||
public \DateTimeImmutable $a,
|
||||
#[Convert(DateTimeConverter::class, false, 9)]
|
||||
public \DateTime $b,
|
||||
#[Convert(DateTimeConverter::class, true, 8)]
|
||||
public \DateTimeImmutable|\DateTime $c,
|
||||
#[Convert(DateTimeConverter::class)]
|
||||
public \DateTimeInterface $d,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
class DTOTest extends PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function testBasic()
|
||||
@@ -351,4 +367,24 @@ class DTOTest extends PHPUnit\Framework\TestCase
|
||||
|
||||
$this->assertEquals($rawType, $testType);
|
||||
}
|
||||
|
||||
public function testDateTime(){
|
||||
$rawType = [
|
||||
'a' => '2022-01-01 10:11:22',
|
||||
'b' => '2022-02-01T12:34:56.1234+09:00',
|
||||
'c' => '2022-03-01T00:00:00.1234+09:00',
|
||||
'd' => '2022-04-01',
|
||||
];
|
||||
|
||||
$testValue = [
|
||||
'a' => '2022-01-01 10:11:22',
|
||||
'b' => '2022-02-01 12:34:56',
|
||||
'c' => '2022-02-28 23:00:00.123400',
|
||||
'd' => '2022-04-01 00:00:00',
|
||||
];
|
||||
$obj = TypeDateTime::fromArray($rawType);
|
||||
$testType = $obj->toArray();
|
||||
|
||||
$this->assertEquals($testValue, $testType);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user