

C#で時間のかかった一部を判定したいのですが…  
例えば

[code]

    var start = TimeSpan.Parse("19:00");//ここは変動する
    var end = TimeSpan.Parse("3:00");   //次の日の3時 ここも変動する
    
[/code]

start と end の間に 22:00～5:00がある場合、何時間なのかを知りたいのです。

よろしくお願いします。


CC BY-SA 4.0
2019-06-16T06:30:00.100
55838
2023-09-25T09:08:10.940
2019-06-16T07:53:56.150
3060
34750
question
c#
TimeSpan で指定した時間の一部を判定して取得したい


おそらく、深夜勤務時間の計算がやりたいのだと思われます。  
VBでのこんな記事がありますので、参考にしてください。  
[VB2013での時間帯判定で困っています](https://oshiete.goo.ne.jp/qa/9248389.html)

上記を参考に、C#で作ってみたのが以下になります。  
出退勤の情報には、時刻だけではなく、日付も必要になります。

[code]

    using System;
    using System.Collections.Generic;
    
    namespace ConsoleApp1
    {
      class Program
      {
        static void Main(string[] args)
        {
          DateTime workStart = DateTime.Parse("2019-06-21 19:00");
          DateTime workEnd = DateTime.Parse("2019-06-22 03:00");
    
          TimeSpan workMidNight = CalcMidNightWork(workStart, workEnd);
    
          Console.WriteLine("出勤日時 = " + workStart.ToString());
          Console.WriteLine("退勤日時 = " + workEnd.ToString());
          Console.WriteLine("深夜勤務 = " + workMidNight.ToString());
    
          return;
        }
    
        // 計算対象時間帯の開始・終了時刻のペア情報クラス
        public class TimeSpanPair
        {
          public TimeSpan TSStart { get; set; }
          public TimeSpan TSEnd { get; set; }
        }
    
        // 計算対象(深夜)時間帯のリスト:計算対象日の00:00が起点
        static List<TimeSpanPair> tsMidNight = new List<TimeSpanPair>() {
          new TimeSpanPair(){ TSStart = new TimeSpan(0,0,0), TSEnd = new TimeSpan(5,0,0) },   // 00:00-05:00
          new TimeSpanPair(){ TSStart = new TimeSpan(22,0,0), TSEnd = new TimeSpan(24,0,0) }  // 22:00-24:00
        };
    
        /// <summary>
        /// 深夜勤務時間取得(複数日をまたぐ連続勤務も計算可)
        /// </summary>
        /// <param name="startTime">出勤日付時刻</param>
        /// <param name="endTime">退勤日付時刻</param>
        /// <returns>深夜勤務時間</returns>
        static TimeSpan CalcMidNightWork(DateTime startTime, DateTime endTime)
        {
          TimeSpan result = new TimeSpan(0, 0, 0, 0); // 深夜勤務時間報告初期値00:00
          DateTime workStart = startTime;     // 該当日毎の勤務開始時刻
          DateTime workDate = workStart.Date; // 該当日の00:00
          DateTime tspStart = workDate;       // 計算対象(深夜)時間帯の開始時刻作業用
          DateTime tspEnd = workDate;         // 計算対象(深夜)時間帯の終了時刻作業用
          do
          {
            workDate = workStart.Date;          // 該当日の00:00を計算ベース値として設定
            // 計算対象(深夜)時間帯リストの要素数でループする
            foreach (TimeSpanPair tsp in tsMidNight)
            {
              tspStart = workDate.Add(tsp.TSStart); // 計算対象時間帯の開始時刻設定
              tspEnd = workDate.Add(tsp.TSEnd);     // 計算対象時間帯の終了時刻設定
              // 勤務時間が計算対象時間帯に入っているか判定
              if (!((workStart >= tspEnd) || (endTime <= tspStart)))
              {
                tspStart = (tspStart < workStart) ? workStart : tspStart; // 実際の開始時刻に調整
                tspEnd = (tspEnd > endTime) ? endTime : tspEnd;           // 実際の終了時刻に調整
                result += (tspEnd - tspStart);  // 計算対象時間帯の勤務時間を計算して報告値に加算
              }
            }
            workStart = workDate.AddDays(1.0);  // 翌日の勤務開始時刻を00:00とする
          } while (workStart < endTime);        // 勤務時間が残っている間はループする
          return result;
        }
      }
    }
    
[/code]


CC BY-SA 4.0
2019-06-18T00:38:23.610
55889
2019-06-18T00:47:17.073
2019-06-18T00:47:17.073
26370
26370
55838
answer

[code]

    var start = TimeSpan.Parse("19:00");//ここは変動する
    var end = TimeSpan.Parse("3:00");   //次の日の3時 ここも変動する
    var day = new TimeSpan(1, 0, 0, 0);   //次の日のため１日
    
    TimeSpan ans = end + day - start;
    
[/code]

ではだめですか？


CC BY-SA 4.0
2019-07-18T07:21:15.450
56722
2019-09-17T10:15:49.477
2019-09-17T10:15:49.477
32986
24490
55838
answer


単純に 終了時間が 開始時間より小さい場合には １日加算して計算します。  
TimeSpan は + - < > 等の演算子がオーバーロードされて定義されているので  
時間としての加減算ができます。

[code]

    var start = TimeSpan.Parse("19:00");//ここは変動する
    var end = TimeSpan.Parse("3:00");   //次の日の3時 ここも変動する
    
    if (end < start) {
           end = end.Add(TimeSpan.FromDays(1));
           // end += TimeSpan.FromDays(1); でもよい
    }
    TimeSpan diff = end - start;
    Console.WriteLine(diff.ToString(@".hh\:mm"));
    
[/code]

### 追記

> start と end の間に 22:00～5:00がある場合、何時間なのかを知りたいのです。

見落としていました。

区間の交差があるか判定するためには  
開始時点の 最大値と 終了時点の 最小値を 求めれば簡単です。

[code]

            TimeSpan CalcCross(TimeSpan begin, TimeSpan end)
            {
                if (end < begin) {
                    end += TimeSpan.FromDays(1);
                }
                TimeSpan m1 = TimeSpan.Parse("22:00");
                TimeSpan m2 = TimeSpan.Parse("1.05:00");
    
                TimeSpan x1 = Max(begin ,m1);
                TimeSpan x2 = Min(end, m2);
    
                TimeSpan cross = x2 - x1;
                if (cross < TimeSpan.Zero) return TimeSpan.Zero;
                else return cross;
            }
    
            TimeSpan Min(TimeSpan t1, TimeSpan t2)
            {
                if (t1 > t2) return t2;
                else return t1;
            }
    
            TimeSpan Max(TimeSpan t1, TimeSpan t2)
            {
                if (t1 > t2) return t1;
                else return t2;
            }
    
[/code]

[code]

            [Test]
            public void Test1()
            {
                // 5パターンを試せばよい
                Console.WriteLine(CalcCross(TimeSpan.Parse("9:00"), TimeSpan.Parse("19:00"))); // 重ならない      0:00:00
                Console.WriteLine(CalcCross(TimeSpan.Parse("19:00"), TimeSpan.Parse("6:00"))); // 開始と終了を含む  7:00:00
                Console.WriteLine(CalcCross(TimeSpan.Parse("23:00"), TimeSpan.Parse("1:00"))); // 範囲が含まれる   2:00:00
                Console.WriteLine(CalcCross(TimeSpan.Parse("20:00"), TimeSpan.Parse("2:00"))); // 前半が重なる     4:00:00
                Console.WriteLine(CalcCross(TimeSpan.Parse("23:00"), TimeSpan.Parse("6:00"))); // 後半が重なる     6:00:00
            }
    
[/code]


CC BY-SA 4.0
2020-02-26T14:29:08.920
63385
2020-02-26T15:06:42.467
2020-02-26T15:06:42.467
18851
18851
55838
answer