192 lines
5.8 KiB
PHP
192 lines
5.8 KiB
PHP
<?php
|
|
|
|
namespace sammo;
|
|
|
|
class VarTurn60
|
|
{
|
|
const MonthAdjustOffset = 2;
|
|
|
|
static array $min30ToTurn = [
|
|
[0, 0, 120], //00:00 2
|
|
[0, 30, 120], //00:30
|
|
[0, 60, 120], //01:00
|
|
[0, 90, 120], //01:30
|
|
[1, 0, 120], //02:00 3
|
|
[1, 30, 120], //02:30
|
|
[1, 60, 120], //03:00
|
|
[1, 90, 120], //03:30
|
|
[2, 0, 120], //04:00 4
|
|
[2, 30, 120], //04:30
|
|
[2, 60, 120], //05:00
|
|
[2, 90, 120], //05:30
|
|
[3, 0, 60], //06:00 5
|
|
[3, 30, 60], //06:30
|
|
[4, 0, 60], //07:00 6
|
|
[4, 30, 60], //07:30
|
|
[5, 0, 60], //08:00 7
|
|
[5, 30, 60], //08:30
|
|
[6, 0, 60], //09:00 8
|
|
[6, 30, 60], //09:30
|
|
[7, 0, 60], //10:00 9
|
|
[7, 30, 60], //10:30
|
|
[8, 0, 60], //11:00 10
|
|
[8, 30, 60], //11:30
|
|
[9, 0, 60], //12:00 11
|
|
[9, 30, 60], //12:30
|
|
[10, 0, 60], //13:00 0(12)
|
|
[10, 30, 60], //13:30
|
|
[11, 0, 60], //14:00 1(13)
|
|
[11, 30, 60], //14:30
|
|
[12, 0, 60], //15:00 2(14)
|
|
[12, 30, 60], //15:30
|
|
[13, 0, 60], //16:00 3(15)
|
|
[13, 30, 60], //16:30
|
|
[14, 0, 60], //17:00 4(16)
|
|
[14, 30, 60], //17:30
|
|
[15, 0, 60], //18:00 5(17)
|
|
[15, 30, 60], //18:30
|
|
[16, 0, 30], //19:00 6(18)
|
|
[17, 0, 30], //19:30 7(19)
|
|
[18, 0, 30], //20:00 8(20)
|
|
[19, 0, 30], //20:30 9(21)
|
|
[20, 0, 30], //21:00 10(22)
|
|
[21, 0, 30], //21:30 11(23)
|
|
[22, 0, 60], //22:00 0
|
|
[22, 30, 60], //22:30
|
|
[23, 0, 60], //23:00 1
|
|
[23, 30, 60], //23:30
|
|
//[24, 0, 60], //24:00 2
|
|
];
|
|
|
|
static array $turnToHM = [
|
|
[0, 0, 120], //0
|
|
[2, 0, 120], //1
|
|
[4, 0, 120], //2
|
|
[6, 0, 60], //3
|
|
[7, 0, 60], //4
|
|
[8, 0, 60], //5
|
|
[9, 0, 60], //6
|
|
[10, 0, 60], //7
|
|
[11, 0, 60], //8
|
|
[12, 0, 60], //9
|
|
[13, 0, 60], //10
|
|
[14, 0, 60], //11
|
|
[15, 0, 60], //12
|
|
[16, 0, 60], //13
|
|
[17, 0, 60], //14
|
|
[18, 0, 60], //15
|
|
[19, 0, 30], //16
|
|
[19, 30, 30],//17
|
|
[20, 0, 30], //18
|
|
[20, 30, 30],//19
|
|
[21, 0, 30], //20
|
|
[21, 30, 30],//21
|
|
[22, 0, 60], //22
|
|
[23, 0, 60], //23
|
|
//[24, 0, 60], //24(?)
|
|
];
|
|
|
|
function __construct(
|
|
public \DateTimeImmutable $baseDay,
|
|
public int $turnIdx, //0~23
|
|
public float $secOffset, ///turnTerm에 따라 최대치가 30*60, 60*60, 120*60 가변
|
|
)
|
|
{
|
|
|
|
}
|
|
|
|
static function fromDatetime(\DateTimeInterface $date): self {
|
|
$baseDay = new \DateTimeImmutable($date->format('Y-m-d'));
|
|
$totalSec = $date->getTimestamp() - $baseDay->getTimestamp();
|
|
|
|
$min30 = intdiv($totalSec, 60 * 30);
|
|
|
|
assert($min30 < 48);
|
|
|
|
[$turnIdx, $minOffset, ] = static::$min30ToTurn[$min30];
|
|
|
|
$secOffset = $totalSec - 60 * 30 * $min30 + $minOffset * 60;
|
|
return new static($baseDay, $turnIdx, $secOffset);
|
|
}
|
|
|
|
/// $b - $a 의 턴차
|
|
static function calcTurnDiff(\DateTimeInterface $a, \DateTimeInterface $b): int{
|
|
$aObj = static::fromDatetime($a);
|
|
$bObj = static::fromDatetime($b);
|
|
|
|
$resDays = $aObj->baseDay->diff($bObj->baseDay)->days; //놀랍게도 절대값
|
|
if($aObj->baseDay > $bObj->baseDay){
|
|
$resDays *= -1;
|
|
}
|
|
|
|
$res = $resDays * 24 + $bObj->turnIdx - $aObj->turnIdx;
|
|
|
|
return $res;
|
|
}
|
|
|
|
function cutTurn($withFraction = true): array{
|
|
[$hour, $minOffset, $turnTerm] = static::$turnToHM[$this->turnIdx];
|
|
$date = $this->baseDay->add(TimeUtil::secondsToDateInterval(($hour * 60 + $minOffset) * 60));
|
|
return [TimeUtil::format($date, $withFraction), $turnTerm];
|
|
}
|
|
|
|
function toDateStr($withFraction = true): string{
|
|
[$hour, $minOffset, ] = static::$turnToHM[$this->turnIdx];
|
|
$date = $this->baseDay->add(TimeUtil::secondsToDateInterval(($hour * 60 + $minOffset) * 60 + $this->secOffset));
|
|
return TimeUtil::format($date, $withFraction);
|
|
}
|
|
|
|
function cutDay($withFraction = true): array{
|
|
//고정 시간 기준 cutDay()의 이식
|
|
//상수 테이블이 이미 13:00에 1월이 되도록 맞춰져 있음.
|
|
//다만 20:00인 경우 8월이 아니라 9월이 됨 ^^;
|
|
$newMonth = ($this->turnIdx + static::MonthAdjustOffset) % 12 + 1;
|
|
|
|
$yearPulled = $newMonth > 3;
|
|
|
|
$obj = $yearPulled ? $this->addTurn(12): $this;
|
|
[$date, ] = $obj->addTurn(-($newMonth - 1))->cutTurn($withFraction);
|
|
|
|
|
|
return [$date, $yearPulled, $newMonth];
|
|
}
|
|
|
|
function addTurn(int $moreTurn): self{
|
|
$dayDiff = intdiv($moreTurn, 24);
|
|
$moreTurn %= 24;
|
|
|
|
$nextTurnIdx = $this->turnIdx + $moreTurn;
|
|
if($nextTurnIdx < 0){
|
|
$dayDiff -= 1;
|
|
$nextTurnIdx += 24;
|
|
}
|
|
else if($nextTurnIdx >= 24){
|
|
$dayDiff += 1;
|
|
$nextTurnIdx -= 24;
|
|
}
|
|
|
|
[, , $oldTurnTerm] = static::$turnToHM[$this->turnIdx];
|
|
[, , $nextTurnTerm] = static::$turnToHM[$nextTurnIdx];
|
|
|
|
$nextSecOffset = $this->secOffset;
|
|
if($oldTurnTerm != $nextTurnTerm){
|
|
$nextSecOffset *= $nextTurnTerm;
|
|
$nextSecOffset /= $oldTurnTerm;
|
|
}
|
|
|
|
if($dayDiff == 0){
|
|
return new static($this->baseDay, $nextTurnIdx, $nextSecOffset);
|
|
}
|
|
|
|
if($dayDiff > 0){
|
|
$nextBaseDay = $this->baseDay->add(new \DateInterval("P{$dayDiff}D"));
|
|
}
|
|
else{
|
|
$dayAbsDiff = abs($dayDiff);
|
|
$nextBaseDay = $this->baseDay->sub(new \DateInterval("P{$dayAbsDiff}D"));
|
|
}
|
|
|
|
return new static($nextBaseDay, $nextTurnIdx, $nextSecOffset);
|
|
}
|
|
}
|