TransWikia.com

TimeSpan で指定した時間の一部を判定して取得したい

スタック・オーバーフロー Asked by Kow1210 on February 12, 2021

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

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

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

よろしくお願いします。

3 Answers

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

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"));

追記

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

見落としていました。

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


        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;
        }
        [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
        }

Answered by k system on February 12, 2021

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

TimeSpan ans = end + day - start;

ではだめですか?

Answered by 池田茂樹 on February 12, 2021

おそらく、深夜勤務時間の計算がやりたいのだと思われます。
VBでのこんな記事がありますので、参考にしてください。
VB2013での時間帯判定で困っています

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

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;
    }
  }
}

Answered by kunif on February 12, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP