Как правильно посчитать дату

Рейтинг: 0Ответов: 1Опубликовано: 20.06.2023

У меня есть объект который представляет какую-то рабочую смену, допустим с 20:00 до 7:00: В ней нет никакой даты и добавить тоже не получится

class WorkingShift
{
   public TimeSpan Start { get; set; }
   public TimeSpan End { get; set; }
}

Я веду статистику по проходам через КПП относительно рабочей смены, так как эта рабочая смена переваливает через сутки, то не получается посчитать полную дату прохода. Для статистики у меня есть объект (ключ на WorkingShift):

class StaffPresence
{
   public DateTime EntranceDate { get; set; }
   public DateTime ExitDate { get; set; }

   public DateTime WorkingShiftStart { get; set; }
   public DateTime WorkingShiftEnd { get; set; }
   public Guid WorkingShiftId { get; set; }
}

Поля EntranceDate и ExitDate заполнить просто т.к он берётся с момента прохождения через КПП. А вот как посчитать WorkingShiftStart и WorkingShiftEnd для следующего кейса: смена началась 01.01.2023 20:00, заканчивается 02.01.2023 07:00, а вход-выход через КПП был 02.01.2023 01:00 и 02:00. Как мне посчитать и получить на выходе WorkingShiftStart/WorkingShiftEnd равным 01.01.2023 20:00 и 02.01.2023 07:00? У меня сейчас есть некоторый алгоритм для вычисления рабочей смены, но он неработает для описанного мною кейса когда смена проходит через разные сутки.

public static (DateTime StartDate, DateTime EndDate) GetWorkingTime(TimeSpan workStart, TimeSpan workEnd, DateTime date)
{
    var start = new DateTime(date.Year, date.Month, date.Day);
    var end = new DateTime(date.Year, date.Month, date.Day);

    if (workStart > workEnd)
    {
        var time = date.TimeOfDay;
        var midnight = new TimeSpan(00, 00, 00);
        if (time >= workStart && time <= workEnd || time >= midnight && time <= workEnd)
        {
            if (time >= workStart && time <= midnight)
            {
                start = start.Add(workStart);
                end = end.AddDays(1)
                    .Add(workEnd);

                return new(start, end);
            }
            else
            {
                start = start
                    .Add(workStart);

                end = end.AddDays(1)
                    .Add(workEnd);

                return new(start, end);
            }
        }
        else
        {
            start = start.Add(workStart);

            end = end.AddDays(1)
                        .Add(workEnd);

            return new(start, end);
        }
    }

    start = start.Add(workStart);
    end = end.Add(workEnd);
    return new(start, end);
}

Ответы

▲ 1Принят

Это несложная задача.

  1. Во-первых, нужно использовать реальные моменты времени для начала смен, то есть не 20:00 и 07:00, а "02.01.ХХХХ 20:00" смена № 1,"03.01.ХХХХ 07:00" смена № 2, "03.01.ХХХХ 20:00" смена № 3 и т. д.
  2. Примем, что смена человека определяется большей продолжительностью его пребывания в течение 1-го посещения предприятия, то есть если работник зашёл в 19:00, а вышел в 23:00, то 3 часа будут относится к смене с 20:00.
  3. Разбиваем пребывание работника на части, максимум 3, то есть добросовестный работник может придти до начала смены, а уйти после её окончания. Из этих кусков (от 1 до 3) выбираем наибольший и смотрим, в какую смену он попал.

Как определить попадание в смену? Для момента времени AMoment:

  1. Если AMoment < 'AMoment.Day 07:00' - смена с '(AMoment.Day - 1) 20:00' до 'AMoment.Day 07:00'.
  2. Если AMoment >= 'AMoment.Day 20:00' - смена с 'AMoment.Day 20:00' до '(AMoment.Day + 1) 07:00'.
  3. Иначе это смена с 'AMoment.Day 07:00' до 'AMoment.Day 20:00'.

Примерно так.