Вычесть определенные часы и дни из TimeSpan

Я хочу рассчитать время в часах и минутах между двумя датами. Но также вычтите определенные часы и даты в этом периоде.

Пример:

DateTime startDate = new DateTime(2022,10,8,14,35,1)
DateTime endDate = new DateTime(2022,11,1,17,46,62)

С:

Timespan ts = endDate.Subtract(starDate);

Я получаю весь промежуток времени между датами.

Но я хочу вычесть все время между:

  • 00:00 - 08:00 все дни
  • 19:00 - 24:00 все дни
  • 00:00 — 24:00 по субботам и воскресеньям
  • 00:00 - 24:00 в определенные дни

Я могу получить правильные результаты для этого, но не очень эффективно.

Псевдокод:

int seconds = 0
while(startDate <= endDate)
{
 if (startDate not in excludedTime)
    seconds++;

 startDate = startDate.AddSeconds(1);
}

Должен быть более эффективный способ сделать это?

Основываясь на предоставленных данных, каков ожидаемый результат?

Chetan 16.11.2022 03:24

Вы просто применяете исключения к дате начала? Или также дата окончания? Или все даты между ними? Как сказал @Chetan, покажите ожидаемый результат.

Rufus L 16.11.2022 03:54

Я знаю, что это было закрыто, и кто-то ответил ниже, но у меня была открытая рабочий пример с чем-то, за чем вам может быть легче следовать (или нет). Удачи!

NPras 16.11.2022 07:18
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
3
62
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Одна идея состоит в том, чтобы написать один метод, который будет корректировать дату на основе правил выходных/праздничных дней, другой, чтобы получить временной интервал дня на основе правил рабочего времени, а затем третий, который использует их для суммирования временных интервалов для каждого дня. в диапазоне.

Для первого метода я добавил аргумент bool forward, которому мы можем присвоить значение false для корректировки конечной даты, поскольку, предположительно, реализация перемещения даты назад немного отличается. Обратите внимание, что при перемещении дня на новый день я использую свойство .Date результата для сброса информации о времени:

public static DateTime AdjustDate(DateTime input, bool forward = true)
{
    var skipDates = new List<DateTime>
    { 
        // add a comma-separated list of dates to skip here 
    };

    while (skipDates.Contains(input.Date)) 
        input = input.AddDays(forward ? 1 : -1).Date;

    if (input.DayOfWeek == DayOfWeek.Saturday) 
        input = input.AddDays(forward ? 2 : -1).Date;
    if (input.DayOfWeek == DayOfWeek.Sunday) 
        input = input.AddDays(forward ? 1 : -2).Date;
    
    return input;
}

Как только этот метод заработает, нам понадобится такой, который даст нам временной интервал только для определенных рабочих часов этого дня. И снова у нас есть логический аргумент, который указывает, считаем ли мы часы ОТ начала дня или ДО конца дня. Затем мы можем добавить логику, чтобы настроить фактический час даты и выполнить нашу математику на основе указанных часов начала и окончания дня.

public static TimeSpan GetNetTimeSpan(DateTime input, bool fromStart = true)
{
    if (input.Hour > 19)
    {
        if (fromStart) 
            input = new DateTime(input.Year, input.Month, input.Day, 19, 0, 0);
        else return TimeSpan.Zero;
    }
    if (input.Hour < 8)
    {
        if (fromStart) return TimeSpan.Zero;
        else input = new DateTime(input.Year, input.Month, input.Day, 8, 0, 0);
    }

    if (fromStart)
    {
        return input - new DateTime(input.Year, input.Month, input.Day, 8, 0, 0);
    }
    else
    {
        return new DateTime(input.Year, input.Month, input.Day, 19, 0, 0) - input;
    }
}

Имея это на месте, теперь мы должны иметь возможность перебрать все дни и создать временной интервал, который инкапсулирует действительные тики каждого дня:

public static TimeSpan GetNetDifference(DateTime start, DateTime end)
{
    // First, adjust our start and end dates to avoid weekends and holidays
    start = AdjustDate(start);
    end = AdjustDate(end, false);

    // If our start is no longer less than our end, return zero
    if (start >= end) return TimeSpan.Zero;

    // Begin with the start date timespan
    var result = GetNetTimeSpan(start);

    // Next loop through each day between start and end and add them to the result
    var current = AdjustDate(start.AddDays(1).Date);

    while(current.Date < end.Date)
    {
        result += GetNetTimeSpan(current);
        current = AdjustDate(current.AddDays(1).Date);
    }

    // Add our last day and return the result
    return result + GetNetTimeSpan(end);
}

Я не проверял это, отчасти потому, что не совсем ясно, следует ли это вашим правилам, но это должно дать вам хорошую отправную точку.

Кроме того, было бы более гибко, если бы мы параметризовали время начала и окончания, а не жестко запрограммировали их на 8 и 19.

Другие вопросы по теме