Working out how many hours worked after a certain time I am working on some custom rules in a time managment system and need to know how many hours in a shift have been before a certain time (19:00pm) and how many hours after. Shifts can start in the evening and finish in the morning so need to take that into account.

So far I have the below (this is just a snippet for one day) however it seems very clumsy and eloborate what I have written, can't help but feel I am missing a simpler solution, anyone have any ideas?

    DateTime cutOffTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 19, 00, 00);
    string cutOffTimeOfDay = GetTimeOfDayFromDateTime(cutOffTime);

    double baseMondayHours = 10.00;
    baseMondayHours = (baseMondayHours - 0.5);

    if (GetTimeOfDayOnlyFromDateTime(monday.ShiftStart.Value) == "AM" &amp;&amp; GetTimeOfDayOnlyFromDateTime(monday.ShiftEnd.Value) == "PM"
        &amp;&amp; monday.ShiftEnd.Value.TimeOfDay &lt; cutOffTime.TimeOfDay)
    {
        postCutOffMondayHours = 0;
        baseMondayHours = monday.HoursWorked.Value;
    }
    else
    {
        string endTimeOfDay = GetTimeOfDayFromDateTime(monday.ShiftEnd.Value);
        double hoursAfterCutOff = GetDuration(cutOffTimeOfDay, endTimeOfDay);

        postCutOffMondayHours = hoursAfterCutOff;
        baseMondayHours = (baseMondayHours - hoursAfterCutOff);
    }

public static string GetTimeOfDayFromDateTime(DateTime d)
{
    return d.ToString("HH:mm") + " " + d.ToString("tt", CultureInfo.InvariantCulture);
}

public static string GetTimeOfDayOnlyFromDateTime(DateTime d)
{
    return d.ToString("tt", CultureInfo.InvariantCulture).ToUpper();
}

    public static double GetDuration(string startTime, string endTime)
    {
        DateTime start = DateTime.Parse(startTime);
        DateTime end = DateTime.Parse(endTime);
        if (start &gt; end)
            end = end.AddDays(1);

        TimeSpan duration = end.Subtract(start);

        return duration.TotalHours;
    }
I agree with your summation that it is clumsy.  I see you like to stringly type objects, such as GetTimeOfDayFromDateTime.  It would be neater to just get the time of day as a TimeSpan.  Also, you may have several overloads accepting different input arguments, so you don't need to include the FromDateTime in the name.

public static TimeSpan GetTimeOfDay(DateTime d) =&gt; d - d.Date;


Or if you want to simply check AM versus PM, you could use the DateTime.Hour.  If the hour is &lt; 12, it's AM.  Otherwise, it's PM.

Now GetDuration doesn't have to accept string inputs.  They can accept the TimeSpan (i.e. time of day) for start and end, or just better yet, just subtract the 2 DateTime objects.

This just looks clumsy:

double baseMondayHours = 10.00;
baseMondayHours = (baseMondayHours - 0.5);


Cleaner would be either:

double baseMondayHours = 10.0 - 0.5;


or directly

double baseMondayHours = 9.5;


Another tip to keep in mind: Subtracting dates can produce bad results if the Kind of each DateTime is different.  Doesn't seem to be the case here, but be forewarned.