📝

日程がかぶっているかどうかを判定するロジック

1 min read 2

はじめに

業務で日程がかぶっているかどうかを判定するロジックを書く機会があったのですが、こういったロジックは正面から考えると複雑で可読性の低いコードになってしまうケースも多いかと思います。

そこで今回はこれを割とスッキリ書くためにやったことについて書いていきます。

要件

予定Aと予定Bがかぶっているかどうかを判定するロジックを書く。

例)
予定A: 2019/10/4 10:00~11:00
予定B: 2019/10/4 10:30~11:30
→期待値:かぶっている(true)

予定がかぶるケース

全部で5つあります。

①予定Aと予定Bが丸かぶりの場合(2019/10/4 10:00~11:00と2019/10/4 10:00~11:00)
②予定Aの終了時刻のみが予定Bの範囲内の場合(2019/10/4 10:00~11:00と2019/10/4 10:30~11:30)
③予定Aの開始時刻のみが予定Bの範囲内の場合(2019/10/4 10:00~11:00と2019/10/4 9:30~10:30)
④予定Aが予定Bに覆いかぶさっている場合(2019/10/4 10:00~11:00と2019/10/4 10:15~10:45)
⑤予定Bが予定Aに覆いかぶさっている場合(2019/10/4 10:00~11:00と2019/10/4 9:00~12:00)

実装…?

上記の5つのケースをOR条件で結んでやると要件を満たせるのですが、コードが冗長になってしまいます。
こういう場合は発想を逆転して(©︎逆転裁判)、予定がかぶらないケースを考えると良いと思います。

予定がかぶらないケース

こちらは2つのみです。
①予定Aの終了時刻が予定Bの開始時刻より前の場合(2019/10/4 10:00~11:00と2019/10/4 11:00~12:00)
②予定Aの開始時刻が予定Bの終了時刻より後の場合(2019/10/4 10:00~11:00と2019/10/4 9:00~10:00)

実装!

上記の2つケースをOR条件で結んだものを否定してやると要件を満たせます。

!(予定Aの終了時刻 <= 予定Bの開始時刻 || 予定Aの開始時刻 >= 予定Bの終了時刻)

こんな感じですかね。(例はJavaScriptです。)

ここでは便宜的に「予定がかぶらないケース」の日本語をそのままコードに変換していますが、コメントでご指摘いただいているように、コードコンプリート形式で不等号の向きについて意識して書くとさらにリーダブルになるかと思います。

おわりに

実装はできそうだけど複雑で可読性の低いコードになってしまうな…という時は、逆のケースを考えてみるのはおすすめです。(全てのケースで役に立つわけではありませんが…)

あと今回のケースであれば、実装前にかぶるケース、かぶらないケースのテストを書いてTDDで実装するのもおすすめです。

Discussion

A.start < A.end
B.start < B.end は前提として

!((B.end <= A.start) || (A.end <= B.start))

コードコンプリート形式で書くと読みやすいと思います。

不等号の向きについて〜リーダブルコード🆚コードコンプリート〜 - Qiita

https://qiita.com/kitoo/items/bec038105471eec82689

ご指摘ありがとうございます!
記事に反映させていただきました!

ログインするとコメントできます