概要
PHPの質問に、タイムカード打刻時刻datetimeから「時・分・秒」を求める方法の質問があったので、ぐぐったところ、差の秒数をgmdateに渡すサンプルやDateTime::diff()を使用するサンプルなどが出てきたが、どれも私はイマイチに感じたのでシンプルに書いた
サンプル
出勤時刻 '2022-08-12 17:18:30'
休憩開始 '2022-08-12 23:30:00'
休憩終了 '2022-08-13 00:35:00'
退勤時刻 '2022-08-13 20:20:18'
※退勤時刻は計算の確認のため、
あえて24時間オーバーさせてます。
test.php
<?php
/**
* Class hmsClass
*/
class hmsClass {
/**
* @var int
*/
public $h = 0;
/**
* @var int
*/
public $m = 0;
/**
* @var int
*/
public $s = 0;
/**
* 秒を「時、分、秒」へ
*
* @param int $time
* @return false|static
*/
public static function gethms($time) {
// 数値でない時
if (! preg_match('/^[\-+]?[0-9]+$/', strval($time))) {
trigger_error(__METHOD__.'(): Argument #1 ($time) must be number', E_USER_WARNING);
return false;
}
$time = intval($time);
$obj = new static();
$obj->h = (int)($time / 3600);
$obj->m = ($time / 60) % 60;
$obj->s = $time % 60;
return $obj;
}
}
// 打刻時刻 出勤時刻(1970年1月1日午前0時0分0秒からの経過秒)
$begin_time = strtotime('2022-08-12 17:18:30');
// 打刻時刻 休憩開始時刻(1970年1月1日午前0時0分0秒からの経過秒)
$break_begin_time = strtotime('2022-08-12 23:30:00');
// 打刻時刻 休憩終了時刻(1970年1月1日午前0時0分0秒からの経過秒)
$break_end_time = strtotime('2022-08-13 00:35:00');
// 打刻時刻 退勤時刻(1970年1月1日午前0時0分0秒からの経過秒)
$end_time = strtotime('2022-08-13 20:20:18');
// 休憩時間(秒) = 休憩開始時刻(秒) - 休憩終了時刻(秒)
$break_time = $break_end_time - $break_begin_time;
$hms = hmsClass::gethms($break_time);
echo('$hms='.print_r($hms, true))."\n";
// $hms=stdClass hmsect
// (
// [h] => 1
// [m] => 5
// [s] => 0
// )
// 労働時間(秒) = 退勤時刻(秒) - 出社時刻(秒) - 休憩時間(秒)
$work_time = $end_time - $begin_time - $break_time;
$hms = hmsClass::gethms($work_time);
echo('$hms='.print_r($hms, true))."\n";
// $hms=stdClass hmsect
// (
// [h] => 25
// [m] => 56
// [s] => 48
// )
テスト
コメントで負数の時のコメントをいただいたので、テストを書いてみました。
gethmsTest.php
<?php
use PHPUnit\Framework\TestCase;
require 'gethms.php';
/**
* Class gethmsTest
*/
class gethmsTest extends TestCase {
public function test() {
$hms = hmsClass::gethms(0);
$this->assertSame(0, $hms->h);
$this->assertSame(0, $hms->m);
$this->assertSame(0, $hms->s);
$hms = hmsClass::gethms(1);
$this->assertSame(0, $hms->h);
$this->assertSame(0, $hms->m);
$this->assertSame(1, $hms->s);
$hms = hmsClass::gethms(-1);
$this->assertSame(0, $hms->h);
$this->assertSame(0, $hms->m);
$this->assertSame(-1, $hms->s);
$hms = hmsClass::gethms(3600);
$this->assertSame(1, $hms->h);
$this->assertSame(0, $hms->m);
$this->assertSame(0, $hms->s);
$hms = hmsClass::gethms(-3600);
$this->assertSame(-1, $hms->h);
$this->assertSame(0, $hms->m);
$this->assertSame(0, $hms->s);
$hms = hmsClass::gethms(99999);
$this->assertSame(27, $hms->h);
$this->assertSame(46, $hms->m);
$this->assertSame(39, $hms->s);
$hms = hmsClass::gethms(-99999);
$this->assertSame(-27, $hms->h);
$this->assertSame(-46, $hms->m);
$this->assertSame(-39, $hms->s);
$hms = hmsClass::gethms('1');
$this->assertSame(0, $hms->h);
$this->assertSame(0, $hms->m);
$this->assertSame(1, $hms->s);
$hms = hmsClass::gethms('-1');
$this->assertSame(0, $hms->h);
$this->assertSame(0, $hms->m);
$this->assertSame(-1, $hms->s);
// 数字ではない時は例外
$e = null;
try {
$hms = hmsClass::gethms('string');
}
catch (\Exception $e) {
// trigger_errorメッセージの確認
$this->assertSame('hmsClass::gethms(): Argument #1 ($time) must be number', $e->getMessage());
}
// 例外が発生した事を確認
$this->assertIsObject($e);
}
}