勤怠表などで打刻する場合、四捨五入でなく 15 分区切り/30 分区切りといった区切り時刻で打刻する必要があります。どうすればいいですか?
例) 8:01 出社 → 勤怠打刻時間:08:15 (14分間の 切り上げ)
例) 11:32 出社 → 勤怠打刻時間:11:45 (13分間の 切り上げ)
例) 18:42 退社 → 勤怠打刻時間:18:30 (12分間の 切り下げ)
例) 22:02 退社 → 勤怠打刻時間:22:00 (02分間の 切り下げ)
実は「禁断の計算術」です
勤怠、つまり毎日の勤労時間を記録する際に、5 分や 15 分単位で切り捨てる計算は「切り捨て御免」と呼ばれる古くからの計算術です。
しかし、この計算術は Qiita では禁断の術式とされており、しかも日本国内では違法になります。そのため、禁断の術を暴露したこの記事も、書いた私も消されるかもしれません。
あなたが総務の方で上司に頼まれたり、従来からの勤怠ルールで効率化を図るために訪れた場合、「計算方法は簡単らしいが、勤怠に利用するには上司の承諾が必要である」旨をメールで伝え、下記の「理由」を上司の方にお見せください。
禁断の計算術/違法な計算式である理由
違法だと言っているのに労働局から叱られないとわからない企業はまだまだ多いのです
アルバイト・派遣社員・社員と言った「自社株を持たない労働者」つまり、法的に言う「従業員」の労働時間における勤怠記録は「1分単位で記録する」か「切り上げのみ」が許されています。
というのも、日々の勤怠記録において実際の労働時間を切り捨てる行為は労働基準法第24条および第37条に違反し違法となるからです。(月締めの集計時の端数処理でなく「毎日の勤怠記録」の時点での切り捨てを指しています)
つまり、体勢的に「実際の労働時間をなかったことにするのは1分でも違法」と言うことです。逆に「18:25 に退社して 18:30 に退社したことにする」のは問題ありません。会社側からすると理不尽ですが、労働者を守る法律ではそうなっているそうです。
勤務時間 8:00 〜 18:00(10 分前出社強制)
例) 7:59 出社 → 勤怠打刻時間:08:00 (01分間の 切り上げ => 01分間の実務時間の切り捨て)
例) 8:00 出社 → 勤怠打刻時間:08:15 (15分間の 切り上げ => 15分間の実務時間の切り捨て)
例) 8:01 出社 → 勤怠打刻時間:08:15 (14分間の 切り上げ => 14分間の実務時間の切り捨て)
例) 11:32 出社 → 勤怠打刻時間:11:45 (13分間の 切り上げ => 13分間の実務時間の切り捨て)
例) 18:42 退社 → 勤怠打刻時間:18:30 (12分間の 切り下げ => 12分間の実務時間の切り捨て)
例) 22:02 退社 → 勤怠打刻時間:22:00 (02分間の 切り下げ => 02分間の実務時間の切り捨て)
そのため、ここをお読みになった時点で禁断の計算術である旨を知った以上、あなたが違法を承知でこの計算式を勤怠の計算に組み込むのであれば幇助の疑いを持たれる可能性があります。いや、ほんとに。
従来からの習慣で手の付けようがない/わからないという場合は、所在地を管轄する労働基準監督署に相談することをおすすめします。労働局による抜き打ちや査察などが入ると、過去にまたがって不足分の支払いが命じられる可能性もあります。
また「遅刻ばかりする」「退勤しろと言ったのに勝手に仕事をしていた」などの、ペナルティや勤務態度は勤怠の集計とは別問題です。労務士の方に相談いただく必要があります。
参考文献
禁断の計算術
「現在の時刻」を「区切り時間」で割った整数の値に「区切り時間」を掛ける
(現在の分 割る 15分) 掛ける 15分
このように、勤怠の計算においては禁断の計算術ではあるものの、計算自体は簡単です。
min = minute(time()) # 現在時刻から分を取得
step = 15 # 15分区切り
stamp = (min // step) * step # // は整数の割り算とする
print(stamp)
また、切り上げは「1」を掛ける前に加えます。
((現在の分 割る 15分) 足す 1) 掛ける 15分
min = minute(time()) # 現在時刻から分を取得
step = 15 # 15分区切り
stamp = (min // step + 1) * step # // は整数の割り算とする
print(stamp)
鋭い方^1はお気付きかもしれません。切り上げ時の +1
をすると 0
分ピッタリに出社しても遅刻扱いとなる「10
分前出社」を強制する黒魔術の術式となります。
- オンラインで Python3 の場合の動作例をみる @ paiza.IO
禁断の秘術の使い所
n 分区切りが好まれるのは、タイムスタンプや手書きを勤怠ソフトに手打ちしたり、月締めで手計算するのが大変だったりすることからポカをする可能性があった時代の名残りなのです。つまり「総務のリスクを減らすために n 分区切りにする」という習慣が大半なのです。
では「勤怠の計算以外での活用方法」といえば、細かすぎて伝わらないデータをわかりやすくするなどに使われます。
// ポットのお湯が使われた時間のログ
// 詳細な時間 → 5分区切り → 15分区切り
08:06 → 08:05 → 08:00
08:11 → 08:10 → 08:00
08:16 → 08:15 → 08:15
08:10 → 08:10 → 08:00
09:13 → 09:10 → 09:00
08:30 → 08:30 → 08:30
例えば、センサーで集計した莫大なデータから機械学習用の教材(教師データ)などにも使われます。具体的には、詳細なデータ以外にも大雑把なくくりでデータを荒くして教材を増やすなどです。
グラフィックなどでは RGB などの色情報を荒くして画像サイズを落とすのにも使われたり、サウンド・ソフトでは解像度を荒くしてプレビューに使われたりします。
データ(の集計結果)の処理以外では集計のタイミングといった時間を扱った「インターバル」処理にも使われます。
上記の「ポットのお湯が使われた時間のログ」のサンプルを見ると、時間がキリ番(キリの良い番号)になっていると思います。この「キリの良いところでの区切り」を「インターバル」と言い、インターバル(区切り)で何か処理を行うことを「インターバル処理」などと呼びます。
身近なところでは「タイマー」であったり、「定例処理」(定期的な処理)などがあります。このようなループさせる秘術を極めたい方は以下のキーワードで調べてみてはいかがでしょう。
- 剰余, MOD
- お使いのプログラム言語で 0〜99 までの数値を任意の値で割った余りの変化をみてください。ゲームの画面で左に消えたキャラクターが右から出てくるような仕組みにも使われています。
- Timer Event
禁断の呪文集
他の言語の呪文があれば遠慮なく編集リクエストください。
public class compiler
shared function Main as integer
Dim minute As Integer '現在時刻(分)
Dim steps As Integer = 15 '15分区切り
Dim stamp As Integer = 0 '打刻時間
' 0分〜59分までをテスト
for minute = 0 to 59
stamp = (minute \ steps) * steps ' バックスラッシュ(\)は整数の除算
Console.WriteLine (minute & " = " & stamp)
next minute
return 0
End function
end class
- オンラインで動作確認する @ paiza.IO
<?php
$minute = 0; //現在時刻(分)
$steps = 15; //15分区切り
$stamp = 0; //打刻時間
// 0分〜59分のテスト
for ($minute = 0; $minute < 60; ++$minute) {
$stamp = intdiv($minute, $steps) * $steps; // `intdiv`は整数の除算
echo $minute, ' = ', $stamp, PHP_EOL;
}
- オンラインで動作確認する @ paiza.IO
minute = 0 # 現在時刻(分)
steps = 15 # 15分区切り
stamp = 0 # 打刻時間
for minute in range(60):
stamp = (minute // steps ) * steps # // は整数の除算
print(str(minute) + ' = ' + str(stamp))
- オンラインで動作確認する @ paiza.IO
package main
import (
"testing"
)
func Test15MinInterval(t *testing.T) {
const interval = 15
for _, data := range []struct {
input int // minute
expect int // minute
}{
{50, 0}, // 50分出社 -> 00分打刻(10分前出社)
{59, 0}, // 59分出社 -> 00分打刻
{0, 15}, // 00分出社 -> 15分打刻
{1, 15}, // 01分出社 -> 15分打刻
{15, 30}, // 15分出社 -> 30分打刻
{29, 30}, // 29分出社 -> 30分打刻
{30, 45}, // 30分出社 -> 45分打刻
{45, 0}, // 45分出社 -> 00分打刻(1時間遅刻)
} {
actual := ((data.input / interval) + 1) * interval % 60
if data.expect != actual {
t.Errorf("Input: %v, Expect: %v, Actual: %v\n", data.input, data.expect, actual)
}
}
}
- オンラインで動作確認する @ Go Playground
履歴
- 2018/07/26 @7of9 さんのコメントよりインターバルについて追記 THX!
所感
本件に限らず、プログラム的な問い合わせを受けた際に「まずは Qiita の記事に絞ってググる」ように案内しています。
しかし、ネットにはエクセル向けの本記事のような情報は多いものの、当然すぎるのか、意外にも Qiita にはありませんでした。
何を調べたかったのか聞いてみたところ、「早く出社したら遅い方に打刻、遅く退社したら早い方に打刻したい」というのです。そんなブラックブラックを噛み締めながら仕事をするようなことの手助けはしたくありませんし、Qiita ないことはよくありません。
そこで、「Qiita では禁断の計算術」という名のもとに「これは遺憾」と書いた次第であります。