C#: пограничные случаи при ежедневном удалении подмножества дней из TimeSpan

Я пытаюсь определить TimeSpan (например, время между выходом из системы и входом в систему), но с оговоркой, что не следует учитывать часть каждого дня (например, не учитывать время между 7 вечера и 7 утра на данный день). Удалить это время из полных дней достаточно просто, но как лучше всего проверить части дня (например, пользователь выходит из системы в 18:00 и снова входит в 20:00 того же дня) и другие пограничные случаи?

ETA: В настоящее время у меня есть установка, которая выглядит следующим образом:

public class HasProductiveHours
{
    //These fields should represent an hour of the day (in 24-hour format)
    // in which production should start or stop.
    public int startProductiveHour;
    public int endProductiveHour;
    //Resource type enum
    public ResourceType resourceType
    //How often this resource is collected, in seconds
    public float harvestTime

    public HasProductiveHours (int startProductiveHour, int endProductiveHour, ResourceType resourceType, int harvestTime)
    {
        // Other creation-time things
        this.startProductiveHour = startProductiveHour;
        this.endProductiveHour = endProductiveHour;
        this.resourceType = resourceType;
        this.harvestTime = harvestTime;
        TimeSimulator.Instance.SimulateElapsedTime (this);
    }
}

Экземпляры этого класса и его дочерние элементы имитируют производство некоторого ресурса каждый час или около того (в зависимости от ресурса). Существует система для имитации времени, прошедшего с момента последнего выхода пользователя из системы.

DateTime lastLogoutTime;

public void Logout ()
{
    // Other logout things
    lastLogoutTime = DateTime.Now;
}

public void SimulateElapsedTime (HasProductiveHours toSimulate)
{
    DateTime currentTime = DateTime.Now;
    TimeSpan timeSinceLogout = currentTime - lastLogout;
    int unproductiveHours = Math.Abs (toSimulate.startProductionHour - toSimulate.endProductionHour) * timeSinceLogout.Days;
    timeSinceLogout.Subtract (new TimeSpan (unproductiveHours, 0, 0);
    double secondsElapsed = timeSinceLogout.TotalSeconds;
int harvestsElapsed = (int)(secondsElapsed / toSimulate.harvestTime);
PlayerData.Instance.AddResource (toSimulate.resourceType, harvestsElapsed);
}

person burnumd    schedule 01.09.2010    source источник
comment
Вы действительно не дали нам достаточного представления о том, как выглядит ваш API, чтобы мы могли должным образом вам помочь.   -  person Jon Skeet    schedule 01.09.2010


Ответы (2)


Несколько шагов должны легко исправить это:

  1. Проверьте время выхода — посмотрите, находится ли оно между 7:00 и 19:00 (метод часа дает вам количество часов, прошедших с полуночи. Вы хотите увидеть, составляет ли оно >=7 и ‹=19). Если это не так, переместите время вперед на 7 утра. Это должно быть достаточно легко сделать. Если время ‹7 утра, измените время на 7 утра. Если время больше 19:00, измените время на 7:00 следующего дня.

  2. Проверьте время входа в систему — убедитесь, что оно между 7:00 и 19:00. Если это не так, переместите время обратно на 19:00. Должно быть достаточно просто сделать - если час > 7 вечера, установите его на 7 вечера, если час ‹7 утра, измените время на 7 вечера в предыдущий день

  3. Убедитесь, что время выхода ‹ время входа. Если нет, то все время выхода из системы было в течение неисчисляемых часов, поэтому ваш временной интервал должен быть установлен на 0. Если ваше время выхода из системы ‹ входа в систему, просто вычтите их, чтобы получить свой временной интервал.

Это для ситуации, описанной в комментарии:

Если номера дней теперь такие же, вот шаги, которые я бы предпринял:

  1. Создайте новую дату и время с датой выхода из системы и временем 19:00. Вычтите новую дату из даты выхода из системы — это даст вам временной интервал до конца дня.

  2. Перенесите дату выхода на 7 утра следующего дня. Если выход из системы и вход в систему теперь происходят в один и тот же день, просто вычтите выход из системы из входа в систему, это будет временной интервал для этого дня. Если они не совпадают, повторите шаг 1.

  3. Сложите промежутки времени, созданные на шаге 1 и шаге 2, вместе. Это дает ваше общее время

Например: я выхожу из системы 1 января в 16:00. Я захожу 2 января в 10:00

Время, когда я вышел из системы 1 января в часы отслеживания, составляет 3 часа (1 января, 19:00 - 1 января, 16:00).

Я переношу время выхода на 2 января, в 07:00.

День выхода равен 2, а день входа равен 2, теперь я могу их вычесть

Время, когда я выходил из системы 2 января в часы отслеживания, составляет 3 часа (2 января, 10:00 - 2 января, 07:00).

Теперь я складываю их вместе и получаю 6 часов времени выхода из системы в часы отслеживания.

person thorkia    schedule 01.09.2010
comment
Эти предложения очень помогли, но, похоже, они не охватывают случай, когда выход из системы и вход в систему не изменены (например, выход из системы между 07:00 и 19:00 и вход в систему между 07:00 и 19:00) и прошло менее 24 часов. Например, если я выйду из системы в 18:00 1 января и войду в 08:00 2 января, количество прошедших дней равно 0, но следует вычесть один полный цикл непродуктивных часов. Как я могу отличить этот случай от, скажем, выхода из системы в 08:00 1 января и повторного входа в 09:00 1 января? - person burnumd; 02.09.2010
comment
см. мою правку. Я добавил логику для обработки, когда даты не совпадают - person thorkia; 02.09.2010

У @thorkia есть несколько хороших предложений.

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

So

8:00-6:00 = 2 часа всего

с 6:00 до 7:00 = 1 час свободного времени

результат = 1 час всего в режиме реального времени

person John M    schedule 01.09.2010
comment
Интересная идея... Никогда не думал сделать это таким образом. Это тоже будет очень хорошо работать. - person thorkia; 02.09.2010