Как мне моделировать произвольные периоды времени? - PullRequest
1 голос
/ 16 сентября 2010

Мне трудно представить объектную модель, которая может хранить периоды времени, подобные следующим:

"Any Wednesday from 2:00PM to 3:00PM"
"April 1, 2010"
"All April for any year"
"Any day in April from 2:00PM to 3:00PM for any year"
"Any day 1:30PM to 2:00PM"
"Any April 1 to Any April 3"

Иногда период будет для определенной даты, а иногда для днянедели плюс промежуток времени.Может быть, целый месяц.

Тестирование данного DateTime на модели - это отдельная проблема, которую мне придется решить позже.Есть ли способ смоделировать эту идею в POCO?Я рисую пробел.

Я не ищу набор DateTime s, представляющих два разных момента времени.Я ищу структуру, в которой будут храниться те же самые периоды времени, которые вы использовали бы для создания плана звонков по мобильному телефону или смены.

Ответы [ 4 ]

1 голос
/ 16 сентября 2010

Я был вовлечен в систему, которая представляла аналогичную проблему.Нашим разрешением было Schedule, которое определяло общее время начала и окончания, каждое из которых имело совокупность (до семи) ScheduleDay, которые представляют дни недели.

Schedule
StartDateTime
EndDateTime

ScheduleDay
DayOfWeek (enum for Mon, Tues etc)
StartTime (time of day, expressed as minutes)
EndTime (time of day, expressed as minutes)

Это позволяетпериоды времени, такие как «13:00 - 15:00 каждый вторник с 1 марта 2010 года по 10 сентября 2010 года»;например, достаточно сложные, но все еще формирующие периоды времени.

Хотя это все еще немного неуклюже.То, что вы действительно хотите, - это представление данных диаграммы Ганта;коллекция периодов «вкл» и «выкл», которые образуют временные интервалы.

Если бы я проектировал эту систему, я бы подумал о сохранении унарной функции, которая принимает DateTime и возвращает bool, которая описывает, существует ли данное время в период времени.Вашему бизнес-объекту нужен делегат;это может быть просто if (date.Year == 2010) return true else return false, или он может быть чрезвычайно сложным в зависимости от периода времени, который вы представляете, но он позволяет полностью расширяемые периоды времени (не ограничения на то, что может быть представлено).

К сожалению, я не понимаюне знаю, как это можно сделать внутри базы данных, и, очевидно, это не POCO.

1 голос
/ 16 сентября 2010

Лично я, вероятно, использовал бы группу обнуляемых значений, например:

public class /* or struct? */ ArbitraryPointInTime
{
    public int? Year { get; private set; }
    public int? Month { get; private set; }
    public int? Day { get; private set; }
    public int? Hour { get; private set; }
    public int? Minute { get; private set; }
    public int? Second { get; private set; }
    public TimeZone TimeZone { get; private set; }

    // Bunch of constructors that construct a valid structure
    // Prevent nonsensical combinations, e.g. Second specified but Minute null
}

public class /* or struct? */ ArbitraryTimePeriod
{
    public ArbitraryPointInTime? Start { get; private set; }
    public ArbitraryPointInTime? End { get; private set; }

    // Bunch of constructors as above
}

Тогда я бы подумал, какие методы вам нужны для манипулирования этими данными. Лично я бы оставил структуру неизменной, и каждый метод возвращал бы новый экземпляр (если, конечно, он не возвращает bool или что-то в этом роде). Напишите спецификацию для каждого из этих методов и тщательно продумайте все возможные варианты. Эрик Липперт привел несколько примерных примеров в комментариях к вопросу. Запишите, что должен делать каждый метод в каждом из этих случаев, даже если ответ «выбросить исключение».

Затем реализуйте спецификацию.

Тогда напишите кучу юнит-тестов. :)

1 голос
/ 16 сентября 2010

Что не так с хранением двух DateTimes?

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

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

Конечно, вы также можете хранить некоторую меру степени детализации или получить ее из кода - если переменные не имеют информации о времени, тогда ясно, что выходные данные должны быть только «с 1 апреля по 3 апреля»; если начальная и конечная точки попадают точно на месяц, выводится только месяц.

Я думаю, что это проще, чем кажется, потому что вам нужно обработать только несколько дел для каждого компонента даты. Это также облегчит сравнение и сопоставление интервалов позже. Конечно, реальный код может быть намного более хорошо структурирован, чем то, что я описал - ни в коем случае я не предлагаю несколько больших вложенных ifs!

0 голосов
/ 16 сентября 2010

Вы можете написать класс, в котором хранится время начала (DateTime) и интервал времени, представляющий период, начинающийся во время начала. Как уже упоминал Эрик, вам нужно будет учитывать часовые пояса при установке даты начала.

...