У меня есть приложение, написанное на C#, которое не может работать в праздничные или выходные дни. Я немного огляделся и не нашел нигде (официального), где бы проводились все государственные праздники на следующие, скажем, 50 лет.
Если я смогу их получить, я просто вставлю их в таблицу праздников на сервере sql и буду использовать. Однако я нигде не могу найти эти данные.
Кто-нибудь знает, поддерживает ли сервер Sql какие-либо праздничные дни или какой-то алгоритм для их решения? Или у кого-нибудь есть где-то официальное, откуда я могу массово вставить.





Разве государственный праздник не очень зависит от региона?
Программно нет возможности вычислить этого. В качестве альтернативы вам нужно будет найти официальный список праздников для каждого из ваших регионов. И даже в этом случае вы не получите желаемой детализации.
Почему ты не можешь это вычислить? Например, если Рождество выпадает на выходные, то следующий понедельник будет выходным днем, не так ли?
Если в стране, конечно, Рождество. И это только для расчетных праздников. Кроме того, что происходит при добавлении одного?
Некоторые праздничные дни не так просто рассчитать, например, Пасха довольно сложна, а некоторые праздники в Великобритании приходятся на последний понедельник месяца.
Я обнаружил, что библиотека рассчитывает праздничные дни на каждый год. Написан на C# github.com/tinohager/Nager.Date
В Австралии праздничные дни могут быть перенесены по усмотрению правительства. Это то, что нужно поместить в таблицу и поддерживать вручную. Не пытайтесь их вычислить.
В ближайшие 50 лет государственные праздники будут редко. В некоторых странах они известны в ближайшие пару лет, в некоторых - нет. Они также различаются в зависимости от штата и даже города.
Да, они различаются, но, конечно, как только вы узнаете, чем они отличаются, вы сможете определить праздники в каждом
Насколько мне известно, «официального» источника не существует, и это действительно сильно зависит от локали. Вам придется управлять ими вручную. Хорошим источником кажется:
http://en.wikipedia.org/wiki/List_of_holidays_by_country
Даже в этих условиях очень сложно управлять. Например, я живу в Бельгии, и в разных частях страны праздники разные. Государственные служащие, например, имеют разные выходные по сравнению с остальной частью рабочей силы, и это в том же региональном коде.
Я считаю, что для Великобритании официальным источником является Департамент бизнеса, предпринимательства и регуляторной реформы (то есть то, что раньше было DTI): berr.gov.uk/whatwedo/employment/bank-public-holidays
В наших приложениях это часть пользовательской конфигурации. Есть место, где пользователи могут установить, что они считают государственными / банковскими праздниками, на сколько угодно отдаленное будущее. Для удобства использования есть возможность скопировать их по дате из прошлых лет. Это также позволяет им устанавливать `` индивидуальные '' публичные удержания, возможно, день, который компания рассматривает как праздник, но не является национальным официальным ...
Однако с точки зрения программирования здесь нет абсолютно никаких предположений. Фактически это просто таблица дат, поддерживаемая пользователем.
(Это включает в себя Великобританию, потому что, как указано выше, некоторые праздники различаются и не высечены в камне, а иногда бывают специальные одноразовые дни.)
Ааа, праздничные календари. Проклятие жизни любого программиста инвестиционного банка. Боюсь, что нет другого способа сделать это, кроме как вести собственный список!
В дополнение к разрешению пользователю настраивать, какие дни являются праздниками, было бы неплохо, если бы вы разрешили пользователю выбирать календарь для импорта или даже для подписки. У iCalShare хороший список. Однако, вероятно, это слишком много для функции, которая просто приятна.
Чтобы добавить то, что уже сказали другие люди, поместить свое собственное в таблицу - единственный реальный способ сделать это. Классический пример - дополнительный банковский выходной день к золотому юбилею королевы. Об этом было объявлено только за пару лет, и у вас не было возможности получить его за пятьдесят лет вперед.
По этой причине существует ряд коммерческих сервисов для надежного предоставления этих данных. Один из них - GoodBusinessDay.com, но у меня нет опыта с ним.
Для этого есть веб-сервис -
http://www.holidaywebservice.com/Holidays/servicesAvailable_HolidayService.aspx
Это было частью критериев в вопросе выше.
Если это просто Англия, то вы можете сами их решить! Вам понадобится надежный алгоритм определения Пасхи, но в противном случае я бы сказал, что вы могли бы сделать это менее чем за час.
Но вы имеете в виду только Англию или Великобританию? Поскольку в Шотландии разные праздники (Рождество, Хогманай и День Святого Андрея), а в Северной Ирландии, Уэльс и, скорее всего, остров Мэн и Нормандские острова также следует торговать по-разному.
Как отмечалось в другом месте, как только ваша область действия становится шире, она становится еще более сложной. Есть местные праздники, полдня, дни, когда банки открыты, а биржи нет, ужасы всякие.
Если вы действительно не можете самостоятельно управлять праздниками и у вас нет пользователей, на которых можно было бы возложить ответственность, то я бы посоветовал вернуться к вашему ограничению «не можете бегать в праздничный день» и поискать способы, которыми это может быть удаленный...
гугл календарь государственные праздники Возможно, вам удастся получить данные о вашей стране / регионе с помощью веб-службы Календаря Google.
Для этого вам понадобится вести праздничный стол. Для правильной интернационализации вам даже нужно указать, какие дни являются выходными для этого, поскольку даже это не универсально. Точно так же вам может потребоваться сохранить праздничные дни в зависимости от региона, чтобы ваша программа знала, что у пользователей в Лондоне выходной день, а у пользователей в Турции - нет.
Это должно быть полностью настраиваемым пользователем. Как известно, день рождения владельца компании может быть «стандартным» выходным днем. Попробуйте найти этот праздник в сети.
Наконец, вы не хотите хранить данные о праздниках за 50 лет. Это будет только неточно и потенциально замедлит весь ваш код.
Нашел еще один сервис для государственных праздников по всему миру, предположительно используемый издателями календарей:
Если это поможет, у меня есть текстовый файл, в котором перечислены правила расчета банковских праздников, определенные для всех крупных и второстепенных финансовых центров. Обычно это определяется по бизнес-центру, например, в Лондоне, Нью-Йорке, Франкфурте и т. д., И т. Д., А не по стране. В качестве примера приведены правила и объяснения для Лондона и некоторых других. Если кто-то захочет получить все, дайте мне знать. Этот участок должен работать не ранее 1990-2030 годов. Очевидно, что никаких новых праздников не будет объявлено после того, как будут собраны флешки (думаю, в 2006 году).
/*
* This file describes holiday calendars in the following way:
* 1. The "n"th "dow" in the month "m", means the 3rd Wednesday in August = "ALWAYS,3,WED,AUG"
* 2. The last etc "dow" in month "m", e.g. the last Monday in June = "LAST,MON,JUN"
* 3. A set date which if on a Sat or Sun is taken on the Monday, eg 13th Aug. = "FWDFROM,13,AUG"
* 4. A set date which if on a Sat is taken on Fri, if Sun on the Mon = "CLOSESTTO,13,AUG"
* 5. A set date which, if on a Sat is unchanged, but if a Sun is taken on the Mon = "FWDFROMSUN,13,AUG"
* 6. A set date which is unchanged if it happens to be on a weekend = "REMAINS,13,AUG"
* 7. The first day on or after day "x" in month "m" e.g. 1st Monday on or after 16th Jan = "FIRSTAFTER,16,MON,JAN"
* 8. A holiday which is a set number of days relative to Easter Sunday, e.g Easter Monday = "EASTER,1"
* 9. A holiday on one specified date only. e.g. 13th Aug 1997 = "ONEOFF,13,AUG,1997"
* 10.A specific date which has been added but is not a holiday and must be removed. = "REMOVE,13,AUG,1997"
* Note REMOVE only works on a date which is already in the calendar: you cannot remove a date which is yet to be added.
* If there is any text after the definition of the holiday it will appear in the date calendar description,
* e.g. you can have "FWDFROM,25,DEC,Christmas Day", if you wish.
*/
LON: HolidayCalendar {
Config: String {
FWDFROM,1,JAN,New Year's Day;
EASTER,-2,Good Friday;
EASTER,1,Easter Monday;
ALWAYS,1,MON,MAY,Early May Bank Holiday;
LAST,MON,MAY,Spring Bank Holiday;
REMOVE,27,MAY,2002,Spring Bank Holiday;
ONEOFF,3,JUN,2002,Spring Bank Holiday;
ONEOFF,4,JUN,2002,Spring Bank Holiday;
LAST,MON,AUG,Summer Bank Holiday;
FWDFROM,25,DEC,Christmas;
FWDFROM,26,DEC,Boxing Day;
ONEOFF,31,DEC,1999,Millenium;
}
EndDate: 31-Dec-2030;
Name: London;
StartDate: 01-Jan-1990;
Weekend: SAT,SUN,;
}
HKG: HolidayCalendar {
Config: String {
FWDFROM,1,JAN,New Year's Day;
ONEOFF,16,FEB,1999,Chinese New Year;
ONEOFF,17,FEB,1999,Chinese New Year;
ONEOFF,18,FEB,1999,Chinese New Year;
FWDFROM,5,FEB,2000,Chinese New Year;
FWDFROM,6,FEB,2000,Chinese New Year;
FWDFROM,7,FEB,2000,Chinese New Year;
CLOSESTTO,5,APR,Ching Ming;
EASTER,-2,Good Friday;
EASTER,1,Easter Monday;
FWDFROM,1,MAY,Labour Day;
ONEOFF,18,JUN,1999,Dragon Boat Festival;
FWDFROM,1,JUL,SAR Establishment Day;
FWDFROM,1,OCT,National Day;
FWDFROM,2,OCT,National Day;
ONEOFF,25,SEP,1999,Mid Autumn Festival;
ONEOFF,17,OCT,1999,Chung Yeung;
FWDFROM,25,DEC,Christmas;
FWDFROM,26,DEC,Boxing Day;
ONEOFF,4,MAY,1998,May bank holiday;
ONEOFF,25,MAY,1998,May bank holiday;
ONEOFF,3,MAY,1999,May bank holiday;
ONEOFF,31,MAY,1999,May bank holiday;
ONEOFF,1,JUL,1997;
ONEOFF,2,JUL,1997;
}
EndDate: 31-Dec-2030;
Name: Hong Kong;
StartDate: 01-Jan-1990;
Weekend: SAT,SUN,;
}
MIL: HolidayCalendar {
Config: String {
FWDFROM,1,JAN,New Year's Day;
REMAINS,6,JAN,Epiphany;
REMAINS,25,APR,Liberation Day;
REMAINS,1,MAY,May Day;
REMAINS,15,AUG,Assumption;
REMAINS,1,NOV,All Saint's;
REMAINS,8,DEC,Immaculate Conception;
EASTER,1,Easter Monday;
FWDFROM,25,DEC,Christmas;
FWDFROM,26,DEC,Boxing Day;
}
EndDate: 31-Dec-2030;
Name: Milan;
StartDate: 01-Jan-1990;
Weekend: SAT,SUN,;
}
FFT: HolidayCalendar {
Config: String {
REMAINS,1,JAN,New Year's Day;
EASTER,-2,Good Friday;
EASTER,1,Easter Monday;
REMAINS,1,MAY,Labour Day;
EASTER,39,Ascension Day;
EASTER,50,Whit Monday;
EASTER,60,Corpus Christi;
REMAINS,3,OCT,Day of German Unity;
REMAINS,24,DEC,Christmas Eve;
REMAINS,25,DEC,Christmas Day;
REMAINS,26,DEC,Boxing Day;
}
EndDate: 31-Dec-2030;
Name: Frankfurt;
StartDate: 01-Jan-1990;
Weekend: SAT,SUN,;
}
ZUR: HolidayCalendar {
Config: String {
REMAINS,1,JAN,New Year's Day;
REMAINS,2,JAN,New Year's Holiday;
EASTER,-2,Good Friday;
EASTER,1,Easter Monday;
EASTER,39,Ascension Day;
EASTER,50,Whit Monday;
REMAINS,1,AUG,August Bank Holiday;
REMAINS,1,MAY, LABOUR DAY;
REMAINS,25,DEC,Christmas;
REMAINS,26,DEC,Boxing Day;
}
EndDate: 31-Dec-2030;
Name: Zurich;
StartDate: 01-Jan-1990;
Weekend: SAT,SUN,;
}
NYK: HolidayCalendar {
Config: String {
REMAINS,1,JAN,New Year's Day;
ALWAYS,3,MON,JAN,Martin Luther King;
ALWAYS,3,MON,FEB,President's Day;
LAST,MON,MAY,Memorial Day;
CLOSESTTO,4,JUL,Independence Day;
ALWAYS,1,MON,SEP,Labor Day;
ALWAYS,2,MON,OCT,Columbus Day;
REMAINS,11,NOV,Veteran's Day;
ALWAYS,4,THU,NOV,Thanksgiving;
FWDFROMSUN,25,DEC,Christmas Day;
ONEOFF,12,NOV,2001,Veteran's Day;
}
EndDate: 31-Dec-2030;
Name: New York;
StartDate: 01-Jan-1990;
Weekend: SAT,SUN,;
}
Этот алгоритм может уменьшить количество ручной настройки в странах, где отмечаются христианские праздники. Преобразование в C# должно быть тривиальным:
http://en.wikipedia.org/wiki/Computus#Anonymous_Gregorian_algorithm
Я просто собираю информацию через Интернет, и у меня есть простой способ рассчитать праздничные дни в США.
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]
Мне нравится ваш подход @Vonpato, однако есть ошибка ... см. День Благодарения 2014, который рассчитывается как 20 ноября. Я тоже попробовал это сделать, см. Мой ответ ниже.
Финансовые учреждения будут подписываться на услуги, которые предоставляют периодические обновления банковских календарей для различных регионов.
Обратите внимание, что между банковскими праздниками и обычными праздниками часто бывает разница. Примером этого в Соединенных Штатах является прошедший День независимости, когда федеральное правительство признало праздник 3 июля, но Федеральный резервный банк Нью-Йорка был открыт.
Для многих из нас в США существует стандартный список деловых праздников, которые можно рассчитать детерминированно.
Вдохновленный кодом Vonpato, я собрал один оператор SQL, который использует функции окна (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
Давайте упростим это:
case
-- New Year's Day
when DATEPART(MM, @DATE) = 1
and DATEPART(DD, @DATE) = 1
and DATEPART(DW, @DATE) in (2,3,4,5,6) then 'Y'
when DATEPART(MM, @DATE) = 12
and DATEPART(DD, @DATE) = 31
and DATEPART(DW, @DATE) = 6 then 'Y'
when DATEPART(MM, @DATE) = 1
and DATEPART(DD, @DATE) = 2
and DATEPART(DW, @DATE) = 2 then 'Y'
-- Memorial Day (last Monday in May)
when DATEPART(MM, @DATE) = 5
and DATEPART(DD, @DATE) between 25 and 31
and DATEPART(DW, @DATE) = 2 then 'Y'
-- Independence Day
when DATEPART(MM, @DATE) = 7
and DATEPART(DD, @DATE) = 4
and DATEPART(DW, @DATE) in (2,3,4,5,6) then 'Y'
when DATEPART(MM, @DATE) = 7
and DATEPART(DD, @DATE) = 3
and DATEPART(DW, @DATE) = 6 then 'Y'
when DATEPART(MM, @DATE) = 7
and DATEPART(DD, @DATE) = 5
and DATEPART(DW, @DATE) = 2 then 'Y'
-- Labor Day (first Monday in September)
when DATEPART(MM, @DATE) = 9
and DATEPART(DD, @DATE) between 1 and 7
and DATEPART(DW, @DATE) = 2 then 'Y'
-- Thanksgiving Day (fourth Thursday in November)
when DATEPART(MM, @DATE) = 11
and DATEPART(DD, @DATE) between 22 and 28
and DATEPART(DW, @DATE) = 5 then 'Y'
-- Black Friday (day after Thanksgiving)
when DATEPART(MM, @DATE) = 11
and DATEPART(DD, @DATE) between 23 and 29
and DATEPART(DW, @DATE) = 6 then 'Y'
-- Christmas Day
when DATEPART(MM, @DATE) = 12
and DATEPART(DD, @DATE) = 25
and DATEPART(DW, @DATE) in (2,3,4,5,6) then 'Y'
when DATEPART(MM, @DATE) = 12
and DATEPART(DD, @DATE) = 24
and DATEPART(DW, @DATE) = 6 then 'Y'
when DATEPART(MM, @DATE) = 12
and DATEPART(DD, @DATE) = 26
and DATEPART(DW, @DATE) = 2 then 'Y'
else 'N' end
В некоторых странах (например, в Польше) количество праздников на Пасху увеличивается.
В конце этого поста вы можете найти код для расчета даты еды и нескольких праздников, которые от нее зависят.
Неподвижные праздники, то есть 1 января, рождественские праздники, день независимости и т. д., Могут быть сохранены где-нибудь в таблице.
Имейте в виду, что в некоторых странах у вас есть регионы / штаты, в которых могут быть дополнительные праздничные дни, но расчет всех праздников для вашей страны или региона должен быть возможным.
В Великобритании, т.е. у вас есть праздничные дни, по которым вы можете использовать некоторые правила в своем коде. - Первый понедельник мая - Последний понедельник мая - Последний понедельник августа и т. д.
Пожалуйста, проверьте эту ссылку для получения более подробной информации http://en.wikipedia.org/wiki/Public_holidays_in_the_United_Kingdom
Как рассчитать дату Пасхи в SQL:
http://www.smart.net/~mmontes/nature1876.html
http://ghiorzi.org/easterda.htm
declare @a int
declare @b int
declare @c int
declare @d int
declare @e int
declare @f int
declare @g int
declare @h int
declare @i int
declare @j int
declare @k int
declare @l int
declare @m int
declare @n int
declare @Year int
declare @Month int
declare @Day int
declare @EasterSunday datetime
declare @EasterMonday datetime
declare @Pentecost datetime
declare @CorpusChristi datetime
SET @Year = 2014
SET @a = @Year%19;
SET @b = @Year/100;
SET @c = @Year%100;
SET @d = @b/4;
SET @e = @b%4;
SET @f = @c/4;
SET @g = @c%4;
SET @h = (@b + 8)/25;
SET @i = (@b - @h + 1)/3;
SET @j = (19*@a + @b - @d - @i + 15) % 30;
SET @k = (32 + 2*@e + 2*@f - @j - @g) % 7;
SET @m = (@a + 11*@j + 22*@k) / 451;
SET @n = @j + @k - 7*@m + 114;
SET @Month = @n/31;
SET @Day = (@n % 31) + 1;
--PRINT @Year
--PRINT @Month
--PRINT @Day
SET @EasterSunday = dateadd(month,((@Year-1900)*12)+@Month-1,@Day-1)
SET @EasterMonday = dateadd(day,1,@EasterSunday)
SET @Pentecost = dateadd(day,49,@EasterSunday)
SET @CorpusChristi = dateadd(day,60,@EasterSunday)
PRINT 'Easter Sunday: ' + CONVERT(VARCHAR, @EasterSunday,120) + ' [' + DATENAME(dw, @EasterSunday) + ']'
PRINT ''
PRINT 'Easter Monday: ' + CONVERT(VARCHAR, @EasterMonday,120) + ' [' + DATENAME(dw, @EasterMonday) + ']'
PRINT ''
PRINT 'Pentecost: ' + CONVERT(VARCHAR, @Pentecost,120) + ' [' + DATENAME(dw, @Pentecost) + ']'
PRINT ''
PRINT 'CorpusChristi: ' + CONVERT(VARCHAR, @CorpusChristi,120) + ' [' + DATENAME(dw, @CorpusChristi) + ']'
PRINT ''
Для тех, у кого возникли проблемы с поиском последнего четверга ноября на День Благодарения, я начинаю с поиска последнего дня месяца, затем использую цикл WHILE (), чтобы вычесть день и проверять имя даты, пока имя даты не станет четвергом:
DECLARE @LastThursday DateTime = DATEADD(s,-1,DATEADD(mm,DATEDIFF(m,0,CONVERT(datetime,CONVERT(varchar,YEAR(GETDATE()))+'-11-01'))+1,0))
WHILE DATENAME(weekday,@LastThursday) <> 'Thursday'
BEGIN
SET @LastThursday = DATEADD(day,DATEDIFF(day,0,@LastThursday)-1,0)
END
SELECT @LastThursday
Банковские праздники в Великобритании в основном вычислимы, но определенно не все.
Правительство Великобритании предоставляет API (https://www.gov.uk/bank-holidays.json), который предоставляет вам эту информацию.
Я считаю эту тему странной. После попытки найти и написать сложные функции на MS, PHP или, в данном случае, языке SQL, я пришел к выводу, что это бессмысленное занятие. Код, который я получил, содержит более 2000 символов, и на его исправление и отладку уходит несколько часов. Если вы думаете об этом, все, что вам нужно сделать, это написать 7 цифр, обозначающих день 1-365 для каждого праздника и строку для каждого года в течение следующих 100 лет. Вам нужно только один раз загрузить эти годы или каникулы следующих лет. Так что держите таблицу с 7 столбцами и 100 строками и заполняйте их правильными днями. Вам нужно делать это только раз в 100 лет, это займет меньше часа, и это портативное устройство.
Вы можете использовать библиотеку Nager.Date для расчета государственных праздников. https://github.com/nager/Nager.Date
Nuget
PM> install-package Nager.Date
Пример:
var publicHolidays = DateSystem.GetPublicHoliday(CountryCode.GB, 2017);
foreach (var publicHoliday in publicHolidays)
{
var name = publicHoliday.LocalName;
}
Я попробовал "ответить" и потратил время на то, чтобы сильно изменить его, чтобы сделать его более читабельным. На самом деле эти параметры "-DATEPART" не нужны, поскольку мы устанавливаем дату прямо перед этим. Он работал довольно хорошо, но были проблемы с MLK Day 2020, поэтому мое доверие к нему было шатким.
Кроме того, мне не понравилось то, что это было очень трудно читать. Я нашел это, и с ним намного легче справиться. Он работает очень похоже на таблицу размеров даты и точно протестирован в течение 3 лет, которые я пробовал.
https://www.codeproject.com/Tips/1168430/US-Federal-Holidays-SQL
Боковое примечание, я бы предпочел просто использовать таблицу измерений даты, но этого не было в текущем проекте.
Это одна из черных дыр программирования. Вы можете тратить бесконечное количество времени (из-за капризов календарей, исключений, необходимости в выходных, разных праздников (официальных и банковских)), и у большинства организаций есть таблица, которую они обновляют каждый ноябрь с приближением праздников. Спасите себя и просто возьмите стол, который обслуживается вручную. Как показывает эта серия ответов, всегда будет что-то, что не рассчитано должным образом.