2017-06-27 3 views
-1

曜日と時間を指定すると、平日のみ(土曜日または日曜日の時間なし)を使用して時間を差し引くと、新しい日付が計算されます。日付から曜日を差し引いた新しい日付を計算する良い方法はありますか?

私は平日の時間を引いた日付を計算する次の2つの関数を持っています。より良い方法がありますか?

static DateTime SubtractWeekdayHours 
    (
     DateTime date2subtractFrom 
     , int hours2subtract 
    ) 
    { 
     if (hours2subtract < 1 || hours2subtract > 120) 
      throw new Exception("SubtractWeekdayHours() only subtracts hours between 1 and 120 inclusive."); 

     var weekdayDateTime = DateTime.Now; 

     // Check if the end of the span touches the weekend: 
     if (date2subtractFrom.DayOfWeek == DayOfWeek.Saturday || date2subtractFrom.DayOfWeek == DayOfWeek.Sunday) 
     { 
      Debug.Write(", End of span EXCEPTION: " + date2subtractFrom.ToString("F")); 
      var SaturdayStartOf = date2subtractFrom.DayOfWeek == DayOfWeek.Saturday ? date2subtractFrom.Date : date2subtractFrom.AddDays(-1).Date; 
      weekdayDateTime = SaturdayStartOf.AddHours(-hours2subtract); 
     } 
     else 
     { // Check if the start of the span touches the weekend: 
      var possibleWeekendDate = date2subtractFrom.AddHours(-hours2subtract); 
      if (possibleWeekendDate.DayOfWeek == DayOfWeek.Saturday || possibleWeekendDate.DayOfWeek == DayOfWeek.Sunday) 
      { 
       Debug.Write(", Start of span EXCEPTION: " + possibleWeekendDate.ToString("F")); 
       weekdayDateTime = calculateWeekdayDateTimeWhenSpanTouchesWeekend(possibleWeekendDate, date2subtractFrom, hours2subtract); 
      } 
      else 
      { 
       var simpleSubtraction = false; 
       var daysToCheck = hours2subtract/24; 
       if (daysToCheck > 0) 
       { // Check if any part of the span touches the weekend: 
        var weekendTouched = false; 
        for (var x = -daysToCheck; x < 0; x++) 
        { 
         possibleWeekendDate = date2subtractFrom.AddDays(x); 
         if (possibleWeekendDate.DayOfWeek == DayOfWeek.Saturday || possibleWeekendDate.DayOfWeek == DayOfWeek.Sunday) 
         { 
          weekendTouched = true; 
          Debug.Write(", Span EXCEPTION:" + possibleWeekendDate.ToString("F")); 
          weekdayDateTime = calculateWeekdayDateTimeWhenSpanTouchesWeekend(possibleWeekendDate, date2subtractFrom, hours2subtract); 
          break; 
         } 
        } 

        if (!weekendTouched) 
        { // Span start and end do not touch a weekend and do not span a weekend, so it is just simple subtraction: 
         simpleSubtraction = true; 
        } 
       } 
       else 
       { // Span start and end do not touch a weekend and the number of hours are less than 24, so it is just simple subtraction: 
        simpleSubtraction = true; 
       } 

       if (simpleSubtraction) 
       { 
        Debug.Write(", Simple subtraction:"); 
        weekdayDateTime = date2subtractFrom.AddHours(-hours2subtract); 
       } 
      } 
     } 

     return weekdayDateTime; 
    } 

    private static DateTime calculateWeekdayDateTimeWhenSpanTouchesWeekend 
    (
     DateTime weekendDate 
     , DateTime date2subtractFrom 
     , int hours2subtract 
    ) 
    { 
     var MondayStartOf = weekendDate.DayOfWeek == DayOfWeek.Saturday ? weekendDate.AddDays(2).Date : weekendDate.AddDays(1).Date; 
     var timeSpan = date2subtractFrom - MondayStartOf; 
     var hoursLeft = hours2subtract - timeSpan.TotalHours; 
     var SaturdayStartOf = MondayStartOf.AddDays(-2); 
     return SaturdayStartOf.AddHours(-hoursLeft); 
    } 
+0

私は次のtodoを期待しているからです。休日を含める - しかしこれはhttp://codereview.stackexchange.comの質問です –

+0

私は正直に自分自身の例外を作成しますこれを対応して。そうすれば、try-catchブロックで日付計算をラップすることができます。それをWeekendSpanExceptionなどと呼んでください。おそらくすぐにメンテナンスの悪夢を防ぐのに役立ちます。 – Ingenioushax

答えて

1

私はこれがあなたの説明どおりに機能すると信じていますが、いくつかのテストをする必要があります。 基本的には、ループの開始日から1時間を連続的に減算し、結果の日付が無視されない場合は、ゼロに達するまで「時間」カウンタを減らします。

この方法では、発信者はDayOfWeek(日)のリストと無視するべきDateTime(日)のリストを渡すことができます。以下は、あなたがやっていることを反映する実装です(週末は無視します)。

static DateTime SubtractWeekdayHours(DateTime startDate, int hours) 
{ 
    var daysOfWeekToIgnore = new List<DayOfWeek> {DayOfWeek.Saturday, DayOfWeek.Sunday}; 
    return SubtractHours(startDate, hours, daysOfWeekToIgnore); 
} 

注:私は120時間の最大のあなたの制限を追加しませんでしたが、あなたはその部分を追加することができます

static DateTime SubtractHours(DateTime startDate, int hours, 
    List<DayOfWeek> daysToIgnore = null, List<DateTime> datesToIgnore = null) 
{ 
    if (hours < 1) throw new ArgumentOutOfRangeException(nameof(hours), 
     "hours must be a positive integer"); 
    if (daysToIgnore == null) daysToIgnore = new List<DayOfWeek>(); 
    if (datesToIgnore == null) datesToIgnore = new List<DateTime>(); 
    var endDate = startDate; 

    do 
    { 
     // In this loop, we continually subtract an hour from our start date 
     endDate = endDate.AddHours(-1); 

     // If that does not result in a day of week or date that 
     // we should ignore, then subtract one from our hours 
     if (!daysToIgnore.Any(d => d.Equals(endDate.DayOfWeek)) && 
      !datesToIgnore.Any(d => d.Date.Equals(endDate.Date))) 
     { 
      hours--; 
     } 
    } while (hours > 0); 

    return endDate; 
} 

ここでは、作成したものに代わる方法です!

関連する問題