質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.10%

PHPで時間計算する

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 2,028

Z-TALBO

score 493

現在タイムカードを作成しています。
一ヶ月分というか当月の○○さんで検索すると、その月のデータがずらっと出るようにしました。

<form action="" post="">
<select name="year">
<select name="month">
<select name="name">
// 中は省略しています
<input type="submit" name="serch" value="検索">
</form>

// データの受取と少し細工
$year = $_POST['year'];
$month = $_POST['month'];
$month = sprintf("%02d", $month);
$name = $_POST['name'];
$startday = $year . $month . '01';
$endday = date('Y-m-t', strtotime($year . '-' . $month));

// DBに接続し、SELECT
省略

// 抽出して表示
while ($row = $stmt->fetch()) :
$datetime = $row['period_dttm'];
list ($year, $month, $day, $hour, $minutes, $second) = preg_split('/[-: ]/', $datetime);

// 時刻の丸め処理
$minutes = round($minutes / 5) * 5;
$time = mktime($hour, $minutes, 0, 1, 1, 2000);
$minutes = date('i', $time);
$hour = date('H', $time);
?>

// table形式で表示させる予定なので、、、
<tr>
<td><?= h($row['name']); ?></td>
<td><?= h($row['dakoku']); ?></td>
<td><?= h($month) . '/' . h($day); ?></td>
<td><?= h($hour) . ':' . h($minutes); ?></td>
</tr>
<?php endwhile; ?>


多少省略して書いてしまっておりますが、だいたいの流れとしてはこのような感じで作成してみました。
表示等に関しては特に問題はなく、検索も抽出も表示もできております。


ここからが、本題であります。
一ヶ月分の$hour . $minutesを計算したいのですが、、、いくつか条件がありまして、それを踏まえつつやるにはどのような方法があるのかと思い質問いたします。

1.$row['dakoku']
出勤、退勤、休入、休戻、待入、待戻のいずれかが入っております。

2.計算式としては
(退勤 - 出勤) - (休戻 - 休入) - (待戻 - 待入)=1日の実働時間
※ここで()をつけたのは、もしかしたらこうやってまず3つの分類で計算したものを最終的に計算するのがいいのかな?と思っただけです。。。。

3.例
検索の結果下記のように表示されたとします
職員名  打刻  月日  時分
○○    出勤  3/19  9:00
○○    休入  3/19  12:00
○○    休戻  3/19  13:00
○○    退勤  3/19  18:00
○○    出勤  3/20  9:00
○○    待入  3/20  10:30
○○    待戻  3/20  11:00
○○    休入  3/20  12:00
○○    休戻  3/20  13:00
○○    待入  3/20  15:00
○○    待戻  3/20  16:00
○○    退勤  3/20  18:00
※長くなってしまうので、これくらいにしておきます。
上記の場合
3/19 18:00-9:00-(13:00-12:00)=8:00
3/20 18:00-9:00-(11:00-10:30)-(13:00-12:00)-(16:00-15:00)=6:30
「3月の実働は14時間30分です。」

このような結果を、データを検索したついでに同時に出しておきたいのですが、どのような方法が考えられますか?

Excelなどでも作業のためだけの列を作ったりして、その作業列で計算とかあるので、こちらでもそういった見えないけど、裏で作業列があってそこでまずはの計算してって形をするとどうなのか?とか考えたのですが、実行するスキルが乏しいので、アドバイスお願いできますか?


[追記]
1日の実働部分の表示ができるようになりました。ありがとうございます!

次に、実際は実働8:00であるのですが、表示は28800という数字になっておりました。そこで、、、

$jitsudo = date('H:i', $jitsudo);
// このフォーマットだと、8:00のはずが9:00となり、一時間常に多くなった

$jitsudo = date('H:i', strtotime("-1 hours", $jitsudo));
// もう一時間多いならで、一時間引くという感じにしてみまして、一応表示はされましたが、こんな感じですかね?

さて、、、最後なのですが、、、
今は1日ごとの実働が表示されるというのは満足ですが、その実働の合計が表示されるようにしたいのですが、、、

最後にこの部分に関してのロジックをアドバイスお願いできますでしょうか?

※この質問は少し内容がずれてきてしまうので、一度解決済みとさせていただき新規に質問をいたします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

まず、前提として、nameで絞り込まれており、period_dttmで昇順に並んでいるとします。

...
// 抽出して表示
$data = [];
$jitsudo = 0;
while ($row = $stmt->fetch()) :
  $datetime = $row['period_dttm'];
  list ($year, $month, $day, $hour, $minutes, $second) = preg_split('/[-: ]/', $datetime);

  // 時刻の丸め処理
  $minutes = round($minutes / 5) * 5;
  $time = mktime($hour, $minutes, 0, 1, 1, 2000);
  $minutes = date('i', $time);
  $hour = date('H', $time);
  if ($year != $data['year'] || $month != $data['month'] || $day != $data['day']) {
    $jitsudo = ($data['退勤'] - $data['出勤']) -
               (@$data['休戻'] - @$data['休入']) - 
               (@$data['待戻'] - @$data['待入']);
    $data = [];
  }
  $data['year'] = $year;
  $data['month'] = $month;
  $data['day'] = $day;
  $data[$row['dakoku']] = $time;

  if($jitsudo):
?>
<tr>
<td colspan="4">実働:<?= $jitsudo ?></td>
</tr>
<?php
    $jitsudo = 0;
  endif;
?>
// table形式で表示させる予定なので、、、
<tr>
<td><?= h($row['name']); ?></td>
<td><?= h($row['dakoku']); ?></td>
<td><?= h($month) . '/' . h($day); ?></td>
<td><?= h($hour) . ':' . h($minutes); ?></td>
</tr>
<?php endwhile;

$jitsudo = ($data['退勤'] - $data['出勤']) -
           (@$data['休戻'] - @$data['休入']) - 
           (@$data['待戻'] - @$data['待入']);

?>
<tr>
<td colspan="4">実働:<?= $jitsudo ?></td>
</tr>

もしかしたら、出勤・退勤以外はない可能性も考慮して、その他はエラー抑制演算子を付けてます。
日付が変わっているところで、実働時間の計算をしていますので、日付が渡った場合はちゃんと計算できません。
なので、日付が渡る場合は、「$dataが空じゃなくてdakoku=出勤のデータが現れたら」とかにするといいかもしれませんね。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/03/19 15:32

    一応、最後も表示させることはできました!

    そして、、、最後なんですが、、、この場合とりあえず表示される値は28800とかの数字なんですが、
    $jitsudo = date('H:i', $jitsudo);とかでやってみたら一応09:00とかで表示されるんですけど、一時間多いんですよ。
    当たり前のことなのかもしれませんが、、、

    キャンセル

  • 2016/03/19 15:53

    時間の部分に関して追記で記載してみました

    キャンセル

  • 2016/03/19 16:01

    長くなるのと、少し中身の質問変更があるので、新規で質問出すことにしますね

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.10%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る