Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Time interceptions (employee night working time) - VB.net, C#, Pseudo Code

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;
like image 220
Rainer Thiele Avatar asked May 22 '26 18:05

Rainer Thiele


2 Answers

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;
    }
}
like image 71
MrZander Avatar answered May 24 '26 17:05

MrZander


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

like image 26
djv Avatar answered May 24 '26 17:05

djv