I don't really have a technical question, it's more that I have been wracking my brain for hours to find a solution for a certain problem. I cannot belive that I am the first one to solve this, but google left me alone. So, may be there is someone who did this before.
This is the problem: Let's say employees who work during night time get certain surcharges on their salary. "Night time", per definition, goes from 23:00 to 06:00 (11 pm to 6 am). How can I calculate how much of a certain working period is night time. Pretty simple for the human brain, but I can't figure out the logic. Let me give you some examples:
Working time: 22:00 - 8:00 = 7 hours night time, 3 hours normal
Working time: 23:00 - 5:00 = 6 hours night time, 0 hours normal
Working time: 20:00 - 4:00 = 5 hours night time, 3 hours normal
Working time: 04:00 - 8:00 = 2 hours night time, 2 hours normal
Working time: 16:00 - 22:00 = 0 hours night time, 6 hours normal
This is my code so far (shift is the actual working time of the employee), but it does not work. It doesn't work for working times after midnight.
DateTime nightTimeStart = new DateTime(1, 1, 1, 23, 0, 0);
DateTime nightTimeEnd = new DateTime(1, 1, 2, 6, 0, 0);
if (shift.UntilTime < nightTimeStart || shift.FromTime > nightTimeEnd)
return 0;
else if (shift.UntilTime <= nightTimeEnd && shift.FromTime >= nightTimeStart)
return (decimal)(shift.UntilTime - shift.FromTime).TotalHours;
else if (shift.UntilTime > nightTimeEnd && shift.FromTime < nightTimeStart)
return (decimal)(nightTimeEnd - nightTimeStart).TotalHours;
else if (shift.UntilTime < nightTimeEnd && shift.FromTime < nightTimeStart)
return (decimal)(nightTimeEnd - shift.FromTime).TotalHours;
else
return (decimal)(shift.UntilTime - nightTimeStart).TotalHours;
This GitHub Repo has a good implementation that may fit your needs
You can use it like so (note the day change from 01 to 02):
var nightTime = new DateTimeInterval()
{
From = new DateTime(0001, 01, 01, 20, 00, 00),
To = new DateTime(0001, 01, 02, 6, 00, 00)
};
var shiftTime = new DateTimeInterval()
{
From = new DateTime(0001, 01, 01, 21, 00, 00),
To = new DateTime(0001, 01, 01, 8, 00, 00)
};
if(shiftTime.From.Value.Hour > shiftTime.To.Value.Hour)
{
shiftTime.To = shiftTime.To.Value.AddDays(1);
}
var overlap = DateTimeUtils.GetIntervalIntersection(nightTime, shiftTime);
var duration = (overlap.To.Value - overlap.From.Value).TotalHours;
Here is a stripped down version of the code (in case the repo is ever removed):
public class DateTimeInterval
{
public DateTime? From { get; set; }
public DateTime? To { get; set; }
}
public static class DateTimeUtils
{
public static DateTimeInterval GetIntervalIntersection(DateTimeInterval testInterval, DateTimeInterval allowedInterval)
{
if (testInterval.From.Value < allowedInterval.From.Value && testInterval.To.Value < allowedInterval.From.Value
|| testInterval.From.Value > allowedInterval.To.Value && testInterval.To.Value > allowedInterval.To.Value)
{
return new DateTimeInterval();
}
DateTime from = testInterval.From < allowedInterval.From
? allowedInterval.From.Value
: testInterval.From.Value;
DateTime to = testInterval.To > allowedInterval.To
? allowedInterval.To.Value
: testInterval.To.Value;
var result = new DateTimeInterval
{
From = from,
To = to
};
return result;
}
}
You can also loop over the time and check if it's within the night range
private static DateTime nightTimeStart = new DateTime(1, 1, 1, 23, 0, 0);
private static DateTime nightTimeEnd = new DateTime(1, 1, 2, 6, 0, 0);
private struct WorkHours
{
public int NightHours;
public int DayHours;
}
private static WorkHours GetWorkHours(DateTime t1, DateTime t2)
{
WorkHours result = new WorkHours();
for (DateTime i = t1; i < t2; i = i.AddHours(1))
{
if (i >= nightTimeStart && i < nightTimeEnd)
result.NightHours++;
else
result.DayHours++;
}
return result;
}
static void Main(string[] args)
{
WorkHours result;
result = GetWorkHours(new DateTime(1, 1, 1, 22, 0, 0), new DateTime(1, 1, 2, 8, 0, 0));
Console.WriteLine("{0} hours night time, {1} hours normal",
result.NightHours, result.DayHours);
result = GetWorkHours(new DateTime(1, 1, 1, 23, 0, 0), new DateTime(1, 1, 2, 5, 0, 0));
Console.WriteLine("{0} hours night time, {1} hours normal",
result.NightHours, result.DayHours);
result = GetWorkHours(new DateTime(1, 1, 1, 20, 0, 0), new DateTime(1, 1, 2, 4, 0, 0));
Console.WriteLine("{0} hours night time, {1} hours normal",
result.NightHours, result.DayHours);
result = GetWorkHours(new DateTime(1, 1, 2, 4, 0, 0), new DateTime(1, 1, 2, 8, 0, 0));
Console.WriteLine("{0} hours night time, {1} hours normal",
result.NightHours, result.DayHours);
result = GetWorkHours(new DateTime(1, 1, 1, 16, 0, 0), new DateTime(1, 1, 1, 22, 0, 0));
Console.WriteLine("{0} hours night time, {1} hours normal",
result.NightHours, result.DayHours);
Console.ReadLine();
}
7 hours night time, 3 hours normal
6 hours night time, 0 hours normal
5 hours night time, 3 hours normal
2 hours night time, 2 hours normal
0 hours night time, 6 hours normal
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With