3
0

More than 3 years have passed since last update.

PHP 2つの日時の差の「時・分・秒」を取得する。タイムカードの打刻時刻など

Last updated at Posted at 2021-07-26

概要

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);
    }
}
3
0
6

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0