Help us understand the problem. What is going on with this article?

日付期間の重複チェック

はじめに

業務アプリケーションでも、予約管理する機能を作成するときがあります。
その時に予約した日付期間が重複しているかチェックするわけですが、日付期間の重複チェックを複雑に記述される方を見られます。

しかし、これには定石のチェック方法があります。
「比較開始日付 <= 対象終了日付 AND 比較終了日付 >= 対象開始日付」
※条件に、=が成り立っていいかどうかは仕様によります。

別ブログに書いた記事(2008年)ですが別ブログを破棄したので、情報を新たに変更してQiitaに移行しました。

【2019/10/06 追記】
重複するパターンとして対象期間より短いパターン⑦を追加しました。
これによるチェック方法に変更点はありませんが、テストパターンが無いことで誤解を生じさせてしまったみたいです。

また、定石のチェック方法の導き方について書かれた記事がありました。
期間が重複しているかを判定する条件式の導出方法

日付期間の重複チェックパターン

例では日付にしてますが、DateTime型を使ってますので時間でも同様です。

重複するパターン

重複5.png

対象期間 2019/08/05 ~ 2019/09/15 
期間①  2019/07/01 ~ 2019/08/31
期間②  2019/08/10 ~ 2019/09/20
期間③  2019/09/15 ~ 2019/10/10
期間④  2019/08/01 ~ 2019/09/30
期間⑦  2019/08/15 ~ 2019/09/05

条件式
比較開始日付 <= 対象終了日付 AND 比較終了日付 >= 対象開始日付

重複しないパターン

重複しない以下のパターンでは、定石の条件式は成立しません。
重複無し2.png
対象期間 2019/08/05 ~ 2019/09/15
期間⑤  2019/07/01 ~ 2019/08/04
期間⑥  2019/09/16 ~ 2019/09/30

条件式
比較開始日付 > 対象終了日付 OR 比較終了日付 < 対象開始日付

ソースコード

C#でLinqを使用しています。

using System;
using System.Linq;
using System.Data;

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            DataTable dtTable = new DataTable();
            DataRow drRow;

            dtTable.Columns.Add("START_DATE", Type.GetType("System.DateTime"));
            dtTable.Columns.Add("END_DATE", Type.GetType("System.DateTime"));
            drRow = dtTable.NewRow();

            //重複するパターン①~④
            drRow["START_DATE"] = DateTime.Parse("2019/07/01");
            drRow["END_DATE"] = DateTime.Parse("2019/08/31");
            dtTable.Rows.Add(drRow);
            drRow = dtTable.NewRow();
            drRow["START_DATE"] = DateTime.Parse("2019/08/10");
            drRow["END_DATE"] = DateTime.Parse("2019/09/20");
            dtTable.Rows.Add(drRow);
            drRow = dtTable.NewRow();
            drRow["START_DATE"] = DateTime.Parse("2019/09/15");
            drRow["END_DATE"] = DateTime.Parse("2019/10/10");
            dtTable.Rows.Add(drRow);
            drRow = dtTable.NewRow();
            drRow["START_DATE"] = DateTime.Parse("2019/08/01");
            drRow["END_DATE"] = DateTime.Parse("2019/09/30");
            dtTable.Rows.Add(drRow);
            //重複するパターン⑦
            drRow = dtTable.NewRow();
            drRow["START_DATE"] = DateTime.Parse("2019/08/15");
            drRow["END_DATE"] = DateTime.Parse("2019/09/05");
            dtTable.Rows.Add(drRow);

            //重複しないパターン⑤~⑥
            drRow = dtTable.NewRow();
            drRow["START_DATE"] = DateTime.Parse("2019/07/01");
            drRow["END_DATE"] = DateTime.Parse("2019/08/04");
            dtTable.Rows.Add(drRow);
            drRow = dtTable.NewRow();
            drRow["START_DATE"] = DateTime.Parse("2019/09/16");
            drRow["END_DATE"] = DateTime.Parse("2019/09/30");
            dtTable.Rows.Add(drRow);

            //対象期間
            DateTime startdate = DateTime.Parse("2019/08/05");
            DateTime enddate = DateTime.Parse("2019/09/15");

            //重複している場合の抽出条件
            //比較開始日付 <= 対象終了日付 AND 比較終了日付 >= 対象開始日付
            var query = from x in dtTable.AsEnumerable()
                        where x.Field<DateTime>("START_DATE") <= enddate && x.Field<DateTime>("END_DATE") >= startdate
                        select x;

            int count = query.Count();  //7件中の5件抽出
            if (count > 0)
                Console.WriteLine(string.Format("{0}件の期間が重複しています。", count));


            //重複していない場合の抽出条件
            //比較開始日付 > 対象終了日付 OR 比較終了日付 < 対象開始日付
            var query2 = from x in dtTable.AsEnumerable()
                         where x.Field<DateTime>("START_DATE") > enddate || x.Field<DateTime>("END_DATE") < startdate
                         select x;

            int count2 = query2.Count();  //7件中の2件抽出
            if (count2 > 0)
                Console.WriteLine(string.Format("{0}件の期間が重複していません。", count2));
        }
    }
}

参考

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away