2

夜間が20.30hから6.15h(AM)に設定されているとします。これらの2つのパラメーターは、ユーザースコープの変数です。到着日と出発日が数分から合計1日を超える場合があるとします。夜間の合計時間をどのように計算しますか?

public static double CalculateTotalNightTimeHours(DateTime arrival, 
                                                  DateTime departure,
                                                  int nightTimeStartHour, 
                                                  int nightTimeStartMinute, 
                                                  int nightTimeEndHour, 
                                                  int nightTimeEndMinute)
{ 
    //??
}

編集:私はこれが簡単なはい/いいえの答えではないかもしれないことを理解していますが、おそらく誰かがこの問題のエレガントな解決策を持っています。コメントに答えるには:私は確かに、ユーザーが編集可能な夜の開始時間と終了時間の間にある合計時間(または分)を計算したいと思います。私は訪問時間を計算しています、そして最初の日付は確かに到着パラメータです。

私がソファに持っていたコード:

DateTime nightStart = new DateTime( departure.Year, departure.Month, departure.Day,
                                    nightTimeStartHour, nightTimeStartMinute, 0);
DateTime nightEnd = new DateTime( arrival.Year, arrival.Month, arrival.Day,
                                  nightTimeEndHour, nightTimeEndMinute, 0);
if (arrival < nightEnd)
{
    decimal totalHoursNight = (decimal)nightEnd.Subtract(arrival).TotalHours;
}
//...
4

2 に答える 2

5

私が挑戦したからといって、次の機能をうまく使えるはずです。これはおそらく最も効率的な方法ではないことに注意してください。ただし、ロジックをレイアウトできるように、この方法で実行しました。これを改善するためのポイントとして編集することもできますが、そのままで問題なく動作するはずです。

ここでいくつかの仮定に注意することも重要です。

  1. 'end'パラメーターは常に'start'パラメーターよりも大きくなります(とにかく最初にチェックしますが)
  2. 夜の終わりのパラメータは夜の開始のパラメータよりも早いです(つまり、夜の時間は翌日に終了しますが、24時間後になることはありません)
  3. 夏時間は存在しません!(これはトリッキーな懸念事項です。対処すべき重要な質問の1つは、開始時刻または終了時刻が時計が戻る日の01:30である場合、時刻がロールバックの前または後に記録されたかどうかをどのように知るかです。時計が01:30に当たったのは1回目ですか2回目ですか?)

それを念頭に置いて...

public static double Calc(DateTime start, DateTime end, int startHour, int startMin, int endHour, int endMin)
{
    if (start > end)
        throw new Exception();//or whatever you want to do

    //create timespans for night hours
    TimeSpan nightStart = new TimeSpan(startHour, startMin, 0);
    TimeSpan nightEnd = new TimeSpan(endHour, endMin, 0);

    //check to see if any overlapping actually happens
    if (start.Date == end.Date && start.TimeOfDay >= nightEnd && end.TimeOfDay <= nightStart)
    {
        //no overlapping occurs so return 0
        return 0;
    }

    //check if same day as will process this differently
    if (start.Date == end.Date)
    {
        if (start.TimeOfDay > nightStart || end.TimeOfDay < nightEnd)
        {
            return (end - start).TotalHours;
        }

        double total = 0;
        if (start.TimeOfDay < nightEnd)
        {
            total += (nightEnd - start.TimeOfDay).TotalHours;
        }
        if(end.TimeOfDay > nightStart)
        {
            total += (end.TimeOfDay - nightStart).TotalHours;
        }
        return total;
    }
    else//spans multiple days
    {
        double total = 0;

        //add up first day
        if (start.TimeOfDay < nightEnd)
        {
            total += (nightEnd - start.TimeOfDay).TotalHours;
        }
        if (start.TimeOfDay < nightStart)
        {
            total += ((new TimeSpan(24, 0, 0)) - nightStart).TotalHours;
        }
        else
        {
            total += ((new TimeSpan(24, 0, 0)) - start.TimeOfDay).TotalHours;
        }

        //add up the last day
        if (end.TimeOfDay > nightStart)
        {
            total += (end.TimeOfDay - nightStart).TotalHours;
        }
        if (end.TimeOfDay > nightEnd)
        {
            total += nightEnd.TotalHours;
        }
        else
        {
            total += end.TimeOfDay.TotalHours;
        }

        //add up any full days
        int numberOfFullDays = (end - start).Days;
        if (end.TimeOfDay > start.TimeOfDay)
        {
            numberOfFullDays--;
        }
        if (numberOfFullDays > 0)
        {
            double hoursInFullDay = ((new TimeSpan(24, 0, 0)) - nightStart).TotalHours + nightEnd.TotalHours;
            total += hoursInFullDay * numberOfFullDays;
        }

        return total;
    }
}

次に、次のように呼び出すことができます。

double result = Calc(startDateTime, endDateTime, 20, 30, 6, 15);
于 2013-01-02T15:21:13.787 に答える
2

基本的に、夜の始まりと終わりを計算する必要があります。次に、それらを到着日と出発日と比較して、夜が始まってから到着するか、夜が終わる前に出発するかを確認して、合計夜時間を決定するために差し引く必要のある値を取得します。次に、夜の開始時刻が出発日を過ぎるまで、毎日これを計算し続ける必要があります。これが私の解決策です。

public static double CalculateTotalNightTimeHours(
    DateTime arrival,
    DateTime departure,
    int nightTimeStartHour,
    int nightTimeStartMinute,
    int nightTimeEndHour,
    int nightTimeEndMinute)
{
    if (arrival >= departure)
        return 0;

    var nightStart = arrival.Date.AddHours(nightTimeStartHour).AddMinutes(nightTimeStartMinute);
    var nightEnd = nightStart.Date.AddDays(1).AddHours(nightTimeEndHour).AddMinutes(nightTimeEndMinute);

    double nightHours = 0;
    while (departure > nightStart)
    {
        if (nightStart < arrival)
            nightStart = arrival;
        if (departure < nightEnd)
            nightEnd = departure;
        nightHours += (nightEnd - nightStart).TotalHours;
        nightStart = nightStart.Date.AddDays(1).AddHours(nightTimeStartHour).AddMinutes(nightTimeStartMinute);
        nightEnd = nightStart.Date.AddDays(1).AddHours(nightTimeEndHour).AddMinutes(nightTimeEndMinute);
    }

    return nightHours;
}

開始時間と終了時間が範囲内にあることを確認するためのチェックも追加することをお勧めします。これはまた、夜が1日で始まり、次の日に終わることを前提としているため、夜を深夜より前に終了したい場合は、別のことを行う必要があります。

于 2013-01-02T15:23:46.043 に答える