Last active
February 7, 2019 07:44
-
-
Save kaho2063/f366582aba63b617fbe532eb385a10d2 to your computer and use it in GitHub Desktop.
時間範囲を引いた後の合計時間を出すための時間範囲クラス(php7.2.11でのみ動作確認)
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 | |
/** | |
* 時間範囲型(PostgreSQLのtstzrange(https://www.postgresql.jp/document/9.4/html/rangetypes.html )を参考にした) | |
*/ | |
class TimeRange { | |
/** | |
* 開始時刻 | |
* @var \DateTimeImmutable null不許可 | |
*/ | |
private $start; | |
/** | |
* 終了時刻 | |
* @var \DateTimeImmutable null不許可 | |
*/ | |
private $end; | |
/** | |
* 時間範囲型 | |
* @param \DateTimeImmutable $start 開始時刻 | |
* @param \DateTimeImmutable $end 終了時刻 | |
* @throws \InvalidArgumentException 時刻のどちらかがnull、もしくは 開始時刻 < 終了時刻 でない場合に発生 | |
*/ | |
function __construct(\DateTimeImmutable $start, \DateTimeImmutable $end) { | |
if ($start === null || $end === null || $start >= $end) { | |
throw new \InvalidArgumentException(); | |
} | |
$this->start = $start; | |
$this->end = $end; | |
} | |
/** | |
* 差分のTimeRange配列を返す | |
* 自身に引数が完全に含まれるときのみ2つのTimeRangeに分かれる | |
* @param TimeRange|TimeRange[] $rangeOrRangeArray 差分を求めたいTimeRangeかその配列 | |
* @return TimeRange[] 差分のTimeRange配列 | |
*/ | |
function sub($rangeOrRangeArray): array { | |
$returnArray = []; | |
if ($rangeOrRangeArray instanceof TimeRange) { | |
if ($rangeOrRangeArray->start >= $this->end || $rangeOrRangeArray->end <= $this->start) { | |
// 自身と引数の期間が重複しないため、変更なし | |
$returnArray[] = clone $this; | |
} else { | |
if ($rangeOrRangeArray->start > $this->start) { | |
// 自身に引数の開始時刻が含まれる | |
$returnArray[] = new TimeRange($this->start, $rangeOrRangeArray->start); | |
} | |
if ($rangeOrRangeArray->end < $this->end) { | |
// 自身に引数の終了時刻が含まれる | |
$returnArray[] = new TimeRange($rangeOrRangeArray->end, $this->end); | |
} | |
} | |
return $returnArray; | |
} | |
if (!empty($rangeOrRangeArray) && (is_array($rangeOrRangeArray) || $rangeOrRangeArray instanceof \Traversable)) { | |
foreach ($rangeOrRangeArray as $value) { | |
if (!($value instanceof TimeRange)) { | |
throw new \InvalidArgumentException(); | |
} | |
$returnArray += $this->sub($value); | |
} | |
return $returnArray; | |
} | |
throw new \InvalidArgumentException(); | |
} | |
} |
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 | |
/** | |
* 時間範囲型用配列 | |
*/ | |
class TimeRangeArray extends \SplFixedArray { | |
/** | |
* 時間範囲型用配列 | |
* @param TimeRangeArray|TimeRange[] $rangeArray 初期化時に追加するTimeRangeの配列 | |
* @throws \InvalidArgumentException 引数が間違っていたとき発生する | |
*/ | |
function __construct($rangeArray = null) { | |
parent::__construct(); | |
if (!empty($rangeArray)) { | |
if (!(is_array($rangeArray) || $rangeArray instanceof \Traversable)) { | |
throw new \InvalidArgumentException(); | |
} | |
foreach ($rangeArray as $value) { | |
if (!($value instanceof TimeRange)) { | |
throw new \InvalidArgumentException(); | |
} | |
$this[] = $value; | |
} | |
} | |
} | |
/** | |
* 指定したインデックスに新しい値をセットする | |
* @param ?int $index インデックス | |
* @param TimeRange $newval 新しい値 | |
* @throws \DomainException 重複する値を追加しようとしたときに発生 | |
*/ | |
public function offsetSet($index = null, $newval = null) { | |
if (!($newval instanceof TimeRange)) { | |
throw new \DomainException('Illegal value.'); | |
} | |
if ($index === null) { | |
$index = count($this); | |
$this->setSize($index + 1); | |
} | |
// 重複する範囲は追加させない | |
foreach ($this as $range) { | |
if (($newval->start < $range->start && $newval->end > $range->start) || ($newval->start < $range->end && $newval->end > $range->end)) { | |
throw new \DomainException('Illegal value.'); | |
} | |
} | |
return parent::offsetSet($index, $newval); | |
} | |
/** | |
* 差分のTimeRange配列を返す | |
* 自身に引数が完全に含まれるときのみ2つのTimeRangeに分かれる | |
* @param TimeRange[] $rangeArray 差分を求めたいTimeRangeの配列 | |
* @return TimeRangeArray 差分のTimeRange配列 | |
*/ | |
function sub($rangeArray): TimeRangeArray { | |
if (!empty($rangeArray) && (is_array($rangeArray) || $rangeArray instanceof \Traversable)) { | |
$returnArray = new TimeRangeArray(); | |
foreach ($this as $thisRange) { | |
$returnArray += $thisRange->sub($rangeArray); | |
} | |
return $returnArray; | |
} | |
throw new \InvalidArgumentException(); | |
} | |
/** | |
* 時間範囲の合計時間を出す | |
* @return int 30分以上繰り上げ、それ未満切り捨ての時間範囲の合計時間(hours) | |
*/ | |
function sum(): int { | |
$sumSeconds = 0; | |
foreach ($this as $range) { | |
$sumSeconds += ($range->end->getTimestamp() - $range->start->getTimestamp()); | |
} | |
$sumMinutes = $sumSeconds / 60; | |
// 30分以上繰り上げ、それ未満切り捨て | |
$sumHours = round($sumMinutes / 60); | |
return $sumHours; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment