Как определить выходной день на сервере Sql? - PullRequest
18 голосов
/ 19 января 2009

У меня есть приложение, написанное на c #, которое не может быть запущено в праздничные или выходные дни. Я немного осмотрелся и не нашел нигде (официального), которое бы обеспечивало все праздничные дни на ближайшие, скажем, 50 лет.

Если я смогу получить их, я просто массово вставлю их в таблицу праздничных дней на сервере sql и использую их. Однако я нигде не могу найти эти данные.

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

Ответы [ 23 ]

13 голосов
/ 17 ноября 2009

Я просто собираю информацию через Интернет и использую этот простой способ подсчета банковских выходных в США.


Праздничные дни в США

===========================

DECLARE @Year char(4)
, @Date datetime
, @Holiday datetime

SET @Year = 2010

---- New Years Day
SET @Date=CONVERT( datetime, CONVERT(varchar, YEAR( @Year ) )+'-01-01' ) 
IF DATENAME( dw, @Date ) = 'Saturday'
    SET @Date=@Date-1
ELSE IF DATENAME( dw, @Date ) = 'Sunday'
    SET @Date=@Date+1
SELECT @Date [New Years Day], DATENAME( dw, @Date ) [DayOfWeek]

---- Martin L King's Birthday ( 3rd Monday in January )
SET @Date = CONVERT( datetime, CONVERT(varchar, YEAR( @Year ) )+'-01-01' ) 
SET @Holiday = DATEADD( wk, DATEDIFF( wk, 0, dateadd( dd, 18-datepart( day, @Date ), @Date ) ), 0 ) -- 3rd Monday of the Month
SELECT @Holiday [Martin L King's Birthday], DATENAME( dw, @Holiday ) [DayOfWeek]

---- President’s Day ( 3rd Monday in February )
SET @Date = CONVERT( datetime, CONVERT(varchar, YEAR( @Year ) )+'-02-01' ) 
SET @Holiday = DATEADD( wk, DATEDIFF( wk, 0, dateadd( dd, 18-datepart( day, @Date ), @Date ) ), 0 ) -- 3rd Monday of the Month
SELECT @Holiday [President’s Day], DATENAME( dw, @Holiday ) [DayOfWeek]

---- Memorial Day ( Last Monday in May )
SET @Date = CONVERT( datetime, CONVERT(varchar, YEAR( @Year ) )+'-05-01' ) 
SET @Holiday = DATEADD( wk, DATEDIFF( wk, 0, dateadd( dd, 30-datepart( day, @Date ), @Date ) ), 0 ) -- 5th Monday of the Month
SELECT @Holiday [Memorial Day], DATENAME( dw, @Holiday ) [DayOfWeek]

---- Independence Day ( July 4 )
SET @Date=CONVERT( datetime, CONVERT(varchar, YEAR( @Year ) )+'-07-04' ) 
IF DATENAME( dw, @Date ) = 'Saturday'
    SET @Date=@Date-1
ELSE IF DATENAME( dw, @Date ) = 'Sunday'
    SET @Date=@Date+1
SELECT @Date [Independence Day], DATENAME( dw, @Date ) [DayOfWeek]

---- Labor Day ( 1st Monday in September )
SET @Date = CONVERT( datetime, CONVERT(varchar, YEAR( @Year ) )+'-09-01' ) 
SET @Holiday = DATEADD( wk, DATEDIFF( wk, 0, dateadd( dd, 6-datepart( day, @Date ), @Date ) ), 0 ) -- 1st Monday of the Month
SELECT @Holiday [Labor Day], DATENAME( dw, @Holiday ) [DayOfWeek]

---- Columbus Day ( 2nd Monday in October )
SET @Date = CONVERT( datetime, CONVERT(varchar, YEAR( @Year ) )+'-10-01' ) 
SET @Holiday = DATEADD( wk, DATEDIFF( wk, 0, dateadd( dd, 12-datepart( day, @Date ), @Date ) ), 0 ) -- 2nd Monday of the Month
SELECT @Holiday [Columbus Day], DATENAME( dw, @Holiday ) [DayOfWeek]

---- Veteran’s Day ( November 11 )
SET @Date=CONVERT( datetime, CONVERT(varchar, YEAR( @Year ) )+'-11-11' ) 
IF DATENAME( dw, @Date ) = 'Saturday'
    SET @Date=@Date-1
ELSE IF DATENAME( dw, @Date ) = 'Sunday'
    SET @Date=@Date+1
SELECT @Date [Veteran’s Day], DATENAME( dw, @Date ) [DayOfWeek]

---- Thanksgiving Day ( 4th Thursday in November )
SET @Date = CONVERT( datetime, CONVERT(varchar, YEAR( @Year ) )+'-11-04' ) 
SET @Holiday = DATEADD( wk, DATEDIFF( wk, 0, dateadd( dd, 22-datepart( day, @Date ), @Date ) ), 0 )+3 -- 4th Thursday of the Month
SELECT @Holiday [Thanksgiving Day], DATENAME( dw, @Holiday ) [DayOfWeek]

---- Christmas Day ( December 25 )
SET @Date=CONVERT( datetime, CONVERT(varchar, YEAR( @Year ) )+'-12-25' ) 
IF DATENAME( dw, @Date ) = 'Saturday'
    SET @Date=@Date-1
ELSE IF DATENAME( dw, @Date ) = 'Sunday'
    SET @Date=@Date+1
SELECT @Date [Christmas Day], DATENAME( dw, @Date ) [DayOfWeek]

---- New Years Eve Day
SET @Date=CONVERT( datetime, CONVERT(varchar, YEAR( @Year ) )+'-12-31' ) 
IF DATENAME( dw, @Date ) = 'Saturday'
    SET @Date=@Date-1
ELSE IF DATENAME( dw, @Date ) = 'Sunday'
    SET @Date=@Date+1
SELECT @Date [New Years Day], DATENAME( dw, @Date ) [DayOfWeek]
8 голосов
/ 19 января 2009

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

http://en.wikipedia.org/wiki/List_of_holidays_by_country

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

6 голосов
/ 19 января 2009

Разве государственный праздник не очень зависит от региона?

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

5 голосов
/ 19 января 2009

В наших приложениях это входит в пользовательскую конфигурацию. У пользователей есть место, чтобы установить то, что они считают выходными / праздничными днями, так далеко, как они хотят. Для простоты использования есть возможность скопировать их по дате предыдущих лет. Это также позволяет им устанавливать «обычные» публичные праздники, возможно, день, который компания считает выходным днем, но не является официально официальным ...

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

(Это включает Великобританию, потому что, как указано выше, некоторые праздники различаются и не указаны в камне, а иногда существуют особые выходные дни)

4 голосов
/ 19 января 2009

Государственные праздники редко доступны в течение следующих 50 лет. В некоторых странах они известны в течение следующих нескольких лет, в некоторых - нет. Они также различаются по штатам и даже городам.

4 голосов
/ 19 января 2009

Для этого доступен веб-сервис -

http://www.holidaywebservice.com/Holidays/servicesAvailable_HolidayService.aspx

3 голосов
/ 04 января 2017

Вы можете использовать библиотеку Nager.Date для расчета выходных дней. https://github.com/tinohager/Nager.Date

NuGet

PM> install-package Nager.Date

Пример:

var publicHolidays = DateSystem.GetPublicHoliday(CountryCode.GB, 2017);
foreach (var publicHoliday in publicHolidays)
{
    var name = publicHoliday.LocalName;
}
2 голосов
/ 26 февраля 2014

Для многих из нас в США существует стандартный список деловых каникул, который можно рассчитать детерминистически.

Черпая вдохновение из кода Вонпато, я собрал один оператор SQL, который использует функции Window (over (partition by ..)), новые в SQL Server 2008, для определения N-го или последнего вхождения дня недели в течение месяца.

Это должно быть выполнено для "DimDate", стандартной таблицы измерений даты, такой как в хранилище данных. http://www.codeproject.com/Articles/647950/Create-and-Populate-Date-Dimension-for-Data-Wareho

SELECT 
    case 
        when DayNameOfWeek = 'Saturday' then dateadd(day, -1, FullDate) 
        when DayNameOfWeek = 'Sunday' then dateadd(day, 1, FullDate) 
    else FullDate end as 'Holiday Date'
FROM (
    select row_number() over (partition by DayNameOfWeek, MonthOfYear, CalendarYear order by FullDate) as WeekdayOrdinal,
    count(*) over (partition by DayNameOfWeek, MonthOfYear, CalendarYear ) as MaxOrdinal,    *  
    from DimDate  
) D
WHERE
        (D.[MonthName] = 'January'  and [DayOfMonth]  = 1)                                              /* New Years Day    */
    OR  (D.[MonthName] = 'January'  and DayNameOfWeek = 'Monday')   and WeekdayOrdinal = 3              /* MLK Day          */
    OR  (D.[MonthName] = 'February' and DayNameOfWeek = 'Monday')   and WeekdayOrdinal = 3              /* President's Day  */
    OR  (D.[MonthName] = 'May'      and DayNameOfWeek = 'Monday')   and WeekdayOrdinal = MaxOrdinal     /* Memorial Day     */
    OR  (D.[MonthName] = 'September' and DayNameOfWeek = 'Monday')  and WeekdayOrdinal = 1              /* Labor Day        */
    OR  (D.[MonthName] = 'October'  and DayNameOfWeek = 'Monday')   and WeekdayOrdinal = 2              /* Columbus Day     */
    OR  (D.[MonthName] = 'November' and [DayOfMonth] = 11)                                              /* Veteran's Day    */
    OR  (D.[MonthName] = 'November' and DayNameOfWeek = 'Thursday') and WeekdayOrdinal = 4              /* Thanksgiving     */
    OR  (D.[MonthName] = 'December' and [DayOfMonth]  = 25 )                                            /* Christmas        */
ORDER BY FullDate
2 голосов
/ 19 января 2009

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

2 голосов
/ 19 января 2009

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

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

Наконец, вы не хотите хранить данные об отпуске за 50 лет. Это будет только неточно и потенциально замедлит весь ваш код.

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