Исключить выходные и нестандартные дни (т.е. праздники) из расчета даты - PullRequest
3 голосов
/ 22 октября 2009

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

Итак, моё решение неверно. Это было только отправной точкой.

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

Проблема в том, что программное обеспечение, над которым я работаю, позволяет пользователям устанавливать свой собственный календарь проекта. Не станет ли таблица слишком большой для обслуживания, учитывая, что программное обеспечение позволяет пользователям управлять несколькими проектами?

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

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

Есть идеи?

Кстати: я использую SQL Server 2005.

Ответы [ 6 ]

1 голос
/ 22 октября 2009

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

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

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

1 голос
/ 22 октября 2009

Создайте большой календарь, который содержит все выходные и праздничные дни для остальной части [длительного периода времени], установите его на выбор только. Затем каждый раз при создании нового проекта копируйте нужные дни в календарь в календарь проекта.

0 голосов
/ 04 октября 2013

Используйте приведенный ниже код, чтобы получить следующую рабочую дату после исключения выходных и праздничных дней

Declare @AddDay as integer = 3
Declare @NextWorkingDate  DateTime
Declare @StartDate  DateTime = Cast(getdate() as date)

While  @AddDay > 0 
    begin

        Select @NextWorkingDate =  @StartDate + @AddDay +
        (datediff(wk, @StartDate, @StartDate+ @AddDay  ) * 2) -- add weekend 

        --Exclude weekend
        If datepart(dw,@NextWorkingDate ) = 1 or datepart(dw,@NextWorkingDate ) = 7  --Add 2 days if target date is either Saturday or Sunday
            set @NextWorkingDate = @NextWorkingDate + 2 

        --Count no of holidays if falling within start date and nextwrking date
        Select @AddDay = Count(*)  from HolidayTable ST --Holiday list
                    where ST.OffDate between @StartDate+1 and @NextWorkingDate
        Set @StartDate = @NextWorkingDate
    End         

Select @NextWorkingDate
0 голосов
/ 29 июня 2013

Привет, это как я решаю:

Сначала я создал таблицу календаря (tb_cal) с двумя полями date_day (smalldate), holiday (bit)

CREATE TABLE [user].[tb_cal](
[date_day] [smalldatetime] NULL,
[holiday] [bit] NULL
) ON [PRIMARY]

тогда эта функция:

CREATE FUNCTION [user].[fc_get_labor_days]
(@from datetime, @to datetime)
RETURNS int
AS
BEGIN
return ( 
select count(*) as total 
from tb_cal 
where datepart(dw, date_day) not in (1,7)   
and holiday <> 1 
and date_day > @from and date_day <= @to )
END 

Вы можете вызвать эту функцию, передав параметр (от, до)

SELECT user.fc_get_labor_days(my_date_from, my_date_to) as [days]

Надеюсь, это поможет

0 голосов
/ 22 октября 2009

@ Стюарт: Да, 50 дней - это тип = P. Я имел в виду 50 лет.

@ rexem: Это правда. Расчеты будут слишком сложными и подвержены ошибкам.

@ Дэвид: Создание основной таблицы календаря только для выбора, а затем копирование нужных мне дат для каждого проекта звучит как отличная идея.

(простите, мой ответ, похожий на твиттер, хаха)

Спасибо за отличные отзывы!

0 голосов
/ 22 октября 2009

Предположим, у вас есть таблица с именем AllDays, в которой есть столбцы с именами theDay и IsPublicHoliday. Также предположим, что для @@ DATEFIRST установлено значение 1, поэтому ваши выходные дни - это дни 1 и 7. Вы хотите найти дату @n дней после @ StartDate.

WITH NumberedDays AS
(
SELECT theDay, ROW_NUMBER() OVER (ORDER BY theDay) AS DayNum
FROM AllDays
WHERE DATEPART(dw, theDay) NOT IN (1,7)
AND IsPublicHoliday = 0
AND theDay > @StartDate
)
SELECT theDay
FROM NumberedDays
WHERE DayNum = @n
;

Если у вас нет таблицы с именем AllDays, вы можете легко использовать таблицу чисел, где theDay - DATEADD (день, число, @ StartDate). Вы можете сделать ЛЕВОЕ СОЕДИНЕНИЕ с вашим списком неподходящих дней (которые, конечно, должны быть проиндексированы).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...