【kintone】標準機能で、休憩時間を除いた労働時間を計算する

今回は、休憩時間を除いた労働時間を算出するような計算式を考えてみたいと思います。


# 計算したい時間

下図のように、出勤時刻をs、退勤時刻をeとして
休憩Aの時間、休憩Bの時間、その他の時間に分けたいと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/4e9cd2e1-7b6e-ce02-721a-bb976d2f9a58.png)

※例えば、
休憩A（12:00 - 13:00）の途中（12:40）に出勤して、
休憩B（18:00 - 18:30）の途中（18:10）に退勤した場合

休憩Aの時間：20分
休憩Bの時間：10分
その他作業した時間： 5時間
のようになりますがそういった時間を計算する式を考えます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/fa3d7c36-b079-ac42-7567-0d7c486d7c45.png" width=400px>


# 計算式を考える

記号の意味は下記とします。

| 記号（フィールドコード） | 意味 |
|:-:|:-:|
|  s | 出勤時刻  |
|  e | 退勤時刻  |
| A  |  休憩A |
|  B | 休憩B  |
|  As | 休憩A開始時刻  |
|  Ae | 休憩A終了時刻  |
|  Bs | 休憩B開始時刻  |
| Be  |  休憩B終了時刻 |

計算式は
出勤から退勤までの時間から、休憩A,Bの時間を引くという方針で考えます。

## Aのことだけ考えた

まずは休憩Aのことだけ考えましょう。
s:出勤時刻
e:退勤時刻
ですが、

下図のように、出退勤のタイミングの組み合わせで、Aの休憩時間は6パターン考えられます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/65d93989-57a9-c9bf-68af-3d1cedae090c.png" width=400px>

| パターン | 内容| 休憩Aの時間 |
|:-:|:-:|:-:|
| 1  | 休憩Aの前に出勤して退勤(e<As)  | 0  |
| 2  | 休憩Aの後に出勤して退勤(Ae<s)  | 0  |
| 3  | 休憩Aの前に出勤して、休憩Aの途中で退勤(s<As かつ As<e<Ae)  | e - As  |
| 4  | 休憩Aの前に出勤して、休憩Aの後で退勤(s<As かつ Ae<e  | Ae - As  |
| 5  | 休憩Aの途中に出勤と退勤(As<s かつ e<Ae)  | e - s  |
| 6  | 休憩Aの途中に出勤して、休憩Aの後で退勤した場合(As<s<Ae かつ Ae<e)  | Ae - s  |

計算式を考えていきます。

## パターン1と2
パターン1 と パターン2 から、
e<As または Ae<s のときは 0
それ以外のときはパターン3～6

なので、OR演算子を用いて、
IF(OR(e<As, Ae<s), 0, パターン3～6)
とできます。

## パターン3～6
図を見ると、
パターン3とパターン4はどちらも s<As のときのパターンです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/c1e9aada-d0ed-6036-aa58-f01add209c49.png)

パターン5とパターン6は、その逆(As<=s)のときのパターンとなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/c4e2d69e-f34f-bae2-3759-f7d6ebf801b7.png)

すると、パターン3～6はこのようなIF文で表されます。
`IF(s<As, パターン3と4 , パターン5と6)`

## パターン3と4
パターン3と4の違いは、退勤時刻eが休憩Aの終わりAeの右か左か？の違いです。
e<Ae のときがパターン3、逆のe>=Ae のときがパターン4なので

`IF(e<Ae, パターン3, パターン4)`
となり、
パターン3のときは休憩Aの時間 = e - As
パターン4のときは休憩Aの時間 = Ae - As
となるので、パターン3と4はこのようなIF文で表されます。
`IF(e<Ae, e-As, Ae-As)`

## パターン5と6
パターン5と6の違いは、同様に、退勤時刻eが休憩Aの終わりAeの右か左か？の違いです。
これまたパターン3と4のときと同様に考えるとこのようなIF文で表されます。
`IF(e<Ae, e-s, Ae-s)`

## 休憩Aの時間を求める計算式
パターン1～6をまとめると、休憩Aの時間を求める計算式は下記となります。
`IF(OR(e<As, Ae<s), 0, IF(s<As, IF(e<Ae, e-As, Ae-As), IF(e<Ae, e-s, Ae-s)))`

## 休憩Bの時間を求める計算式
休憩Bの計算式も実は全く同様に考えることができ、AをBに置換して以下の計算式となります。
`IF(OR(e<Bs, Be<s), 0, IF(s<Bs, IF(e<Be, e-Bs, Be-Bs), IF(e<Be, e-s, Be-s)))`

例えば、休憩Cが増えたとしても同じようにAをCに置換した式を書けば良さそうです。

## 休憩以外の時間を求める
結果、休憩A、Bを除いた時間を求める式は下記となります。

`e-s-A-B`

# 実際のアプリ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/4b7538e6-652a-1c49-a140-6c22a4c501e0.png)

| フィールド名（フィールドコード） | フィールド種類 |意味|計算式|
|:-:|:-:|:-:|:-:|
|  s | 時刻|出勤時刻  ||
|  e | 時刻| 退勤時刻  ||
|  As | 時刻| 休憩A開始時刻 | |
|  Ae | 時刻| 休憩A終了時刻  ||
|  Bs | 時刻| 休憩B開始時刻  ||
| Be  | 時刻|  休憩B終了時刻 ||
| A  |計算|  休憩Aの時間 |IF(OR(e<As, Ae<s), 0, IF(s<As, IF(e<Ae, e-As, Ae-As), IF(e<Ae, e-s, Ae-s)))|
|  B |計算| 休憩Bの時間  |IF(OR(e<Bs, Be<s), 0, IF(s<Bs, IF(e<Be, e-Bs, Be-Bs), IF(e<Be, e-s, Be-s)))|
|他|計算|休憩A、Bを除いた時間|e - s - A - B|


# まとめ
kintoneの標準機能でここまでできます（もっと効率の良い計算式があるかもしれません）。
時間外労働の時間などももしかするといい具合に計算できるかも？？
計算式、混乱のない範囲で是非使ってみてくださいね。