Set Nocount On; Set STATISTICS time On; Declare @startYear bigint = 0001 , @endYear bigint = 9999; With t(n) As ( Select t.n From ( Values (0), (0), (0), (0), (0), (0), (0), (0), (0), (0)) As t(n) ) , inputYears (y) As ( Select Top (@endYear - @startYear + 1) (@startYear - 1) + row_number() over(Order By @@spid) As rn From t t1, t t2, t t3, t t4 ) Select * From inputYears dd /* Gauss' Easter algorithm a y % 19 year's position in the 19-year lunar phase cycle b,c,k y % 4, y % 7, y / 100 corrections for century years p (13 + 8*k) / 25 correct for the lunar orbit not being fully describable in integer terms q k / 4 leap-year exceptions in century years M (15 - p + k - q) % 30 correct starting point at the start of each century N (4 + k - q) % 7 starting point for each century d (19*a + M) % 30 number of days between 21 March and the coincident or next following full moon e (2*b + 4*c + 6*d + N) % 7) offset days that must be added to make d arrive on a Sunday o iif(e = 6 And (d = 29 Or (d = 28 And a > 10)), 7, 0) subtract days for 26 April OR 25 April AND a > 10 Add d + e - o to March 22 Easter Sunday (Gregorian calendar) */ Cross Apply ( Select * --e7.EasterDay From (Values (y % 19, y % 4, y % 7, y / 100)) As e1(a, b, c, k) Cross Apply (Values ((13 + 8*k) / 25, k / 4)) As e2(p, q) Cross Apply (Values ((15 - p + k - q) % 30, (4 + k - q) % 7)) As e3(M, N) Cross Apply (Values ((19*a + M) % 30)) As e4(d) Cross Apply (Values ((2*b + 4*c + 6*d + N) % 7)) As e5(e) Cross Apply (Values (iif(e = 6 And (d = 29 Or (d = 28 And a > 10)), 7, 0))) As e6(o) Cross Apply (Values (dateadd(day, d + e - o, datefromparts(y, 3, 22)))) As e7(EasterDay) ) As ge /* Gauss' Julian algorithm (Orthodox "Eastern" Easter Day) a y % 19 year's position in the 19-year lunar phase cycle b, c y % 4, y % 7 leap-year dates d (19*a + 15) % 30 Paschal Full Moon for this year e (2*a + 4*b + 6*d + 6) % 7 the Sunday following the Paschal Full Moon j (y / 100 - y / 400) - 2 the number of days to add to Julian date for Gregorian Calendar Add d + e to March 22 Julian Easter Date Add o to Julian Date Orthodox Easter Sunday (Gregorian Calendar) */ Cross Apply ( Select *, EasterDay = iif(y < 1783, JulianDate, GregorianDate) From (Values (y % 19, y % 4, y % 7)) As e1(a, b, c) Cross Apply (Values ((19*a + 15) % 30)) As e2(d) Cross Apply (Values ((2*b + 4*c + 6*d + 6) % 7, (y / 100 - y / 400) - 2)) As e3(e, o) Cross Apply (Values (dateadd(day, d + e, datefromparts(y, 3, 22)))) As e4(JulianDate) Cross Apply (Values (dateadd(day, o, JulianDate))) As e5(GregorianDate) ) As oge /* Anonymous Gregorian 'Meeus/Jones/Butcher' algorithm (Western Easter Day) a y % 19 year's position in the 19-year lunar phase cycle b, c y / 100, y % 100 corrections for century years d, e b / 4, b % 4 leap-year exceptions in century years f, g (b + 8) / 25, (b - f + 1) / 3 century-year auxiliary corrections to the new-moon and full-moon dates h (19*a + b - d - g + 15) % 30 number of days between 21 March and the coincident or next following full moon i, k c / 4, c % 4 position of the year in the ordinary leap-year cycle l (32 + 2*e + 2*i - h - k) % 7 number between 0 and 6 which is one less than the number of days before the next Sunday which is definitely after the full moon m (a + 11*h + 22*l) / 451 correction for transfer of full moon from a Sunday to a Saturday m = 1 for the required correction else 0 x h + l - 7*m + 114 h + l - 7*m = number of days between 21 March and Easter x / 31, (x % 31) + 1 the month and day on the Gregorian calendar */ Cross Apply ( Select * --e8.EasterDay From (Values (y % 19, y / 100, y % 100)) As e1(a, b, c) Cross Apply (Values (b / 4, b % 4, (b + 8) / 25)) As e2(d, e, f) Cross Apply (Values ((b - f + 1) / 3)) As e3(g) Cross Apply (Values ((19*a + b - d - g + 15) % 30, c / 4, c % 4)) As e4(h, i, k) Cross Apply (Values ((32 + 2*e + 2*i - h - k) % 7)) As e5(l) Cross Apply (Values ((a + 11*h + 22*l) / 451)) As e6(m) Cross Apply (Values (h + l - 7*m + 114)) As e7(x) Cross Apply (Values (datefromparts(y, x / 31, (x % 31) + 1))) As e8(EasterDay) ) As me /* Meeus's Julian algorithm (Orthodox "Eastern" Easter Day) a, b y % 4, y % 7 leap-year dates c y % 19 year's position in the 19-year lunar phase cycle d (19*c + 15) % 30 Paschal Full Moon for this year e (2*a + 4*b - d + 34) % 7 the Sunday following the Paschal Full Moon o (y / 100 - y / 400) - 2 the number of days to add to Julian date for Gregorian Calendar n (d + e + 114) / 31 the month on the Julian Calendar p (d + e + 114) % 31) + 1 the day of the month on the Julian Calendar Add o to Julian Date Orthodox Easter Sunday (Gregorian Calendar) */ Cross Apply ( Select *, EasterDay = iif(y < 1783, JulianDate, GregorianDate) From (Values (y % 4, y % 7, y % 19)) As e1(a, b, c) Cross Apply (Values ((19*c + 15) % 30)) As e2(d) Cross Apply (Values ((2*a + 4*b - d + 34) % 7, (y / 100 - y / 400) - 2)) As e3(e, o) Cross Apply (Values ((d + e + 114) / 31, ((d + e + 114) % 31) + 1)) As e4(n, p) Cross Apply (Values (datefromparts(y, n, p))) As e5(JulianDate) Cross Apply (Values (dateadd(day, o, JulianDate))) As e6(GregorianDate) ) As ome /* Oudin's Easter algorithm g y % 19 year's position in the 19-year lunar phase cycle c y / 100 leap-year corrections for centuries h (c - (c / 4) - ((13 + 8*c) / 25) + 19*g + 15) % 30 the number of days short to the full moon i h - (h / 28) * (1 - (29 / (h + 1)) * ((21 - g) / 11)) number of days from 21 March to the Paschal full moon j (y + (y / 4 + i + 2 - (c - (c / 4)))) % 7 the weekday for the Paschal full moon (0 = Sunday, 1 = Monday, etc.) m 3 + (((i - j) + 40) / 44) the month on the Gregorian calendar n (i - j) + 28 - 31 * (m / 4) the day of the month on the Gregorian calendar */ Cross Apply ( Select * --e7.EasterDay From (Values (y % 19, y / 100)) As e1(g, c) Cross Apply (Values ((c - (c / 4) - ((13 + 8*c) / 25) + 19*g + 15) % 30)) As e2(h) Cross Apply (Values (h - (h / 28) * (1 - (29 / (h + 1)) * ((21 - g) / 11)))) As e3(i) Cross Apply (Values ((y + (y / 4 + i + 2 - (c - (c / 4)))) % 7)) As e4(j) Cross Apply (Values (3 + (((i - j) + 40) / 44))) As e5(m) Cross Apply (Values ((i - j) + 28 - 31 * (m / 4))) As e6(n) Cross Apply (Values (datefromparts(y, m, n))) As e7(EasterDay) ) As oe /* Oudin's Julian algorithm (Orthodox 'Eastern' Easter) g y % 19 year's position in the 19-year lunar phase cycle c y / 100 leap-year corrections for centuries i (19*g + 15) % 30) number of days from 21 March to the Paschal full moon j (y + (y / 4) + i) % 7 the weekday for the Paschal full moon (0 = Sunday, 1 = Monday, etc.) m 3 + (((i - j) + 40) / 44) the month on the Julian Calendar n (i - j) + 28 - 31 * (m / 4) the day of the month on the Julian Calendar o (y / 100 - y / 400) - 2 the number of days to add to Julian date for Gregorian Calendar Add o to Julian Date Orthodox Easter Sunday (Gregorian Calendar) */ Cross Apply ( Select *, EasterDay = iif(y < 1783, JulianDate, GregorianDate) From (Values (y % 19, y / 100)) As e1(g, c) Cross Apply (Values ((19*g + 15) % 30)) As e2(i) Cross Apply (Values ((y + (y / 4) + i) % 7)) As e3(j) Cross Apply (Values (3 + (((i - j) + 40) / 44))) As e4(m) Cross Apply (Values ((i - j) + 28 - 31 * (m / 4), (y / 100 - y / 400) - 2)) As e5(n, o) Cross Apply (Values (datefromparts(y, m, n))) As e6(JulianDate) Cross Apply (Values (dateadd(day, o, JulianDate))) As e7(GregorianDate) ) As ooe /* New Scientist (30 March 1961) - Modification of the Anonymous Gregorian algorithm a y % 19 year's position in the 19-year lunar phase cycle b, c y / 100, y % 100 corrections for century years d, e b / 4, b % 4 leap-year exceptions in century years g 8 * b + 13 / 25 century-year auxiliary corrections to the new-moon and full-moon dates h (19*a + b - d - g + 15) % 30 number of days between 21 March and the coincident or next following full moon i, k c / 4, c % 4 position of the year in the ordinary leap-year cycle l (32 + 2*e + 2*i - h - k) % 7 number between 0 and 6 which is one less than the number of days before the next Sunday which is definitely after the full moon m (a + 11*h + 19*l) / 433 correction for transfer of full moon from a Sunday to a Saturday m = 1 for the required correction else 0 n (h + l - 7*m + 90) / 25 the month on the Gregorian Calendar h + l - 7*m = number of days between 21 March and Easter p (h + l - 7*m + 33*n + 19) % 32) the day of the month on the Gregorian calendar */ Cross Apply ( Select * --e9.EasterDay From (Values (y % 19, y / 100, y % 100)) As e1(a, b, c) Cross Apply (Values (b / 4, b % 4)) As e2(d, e) Cross Apply (Values ((8*b + 13) / 25)) As e3(g) Cross Apply (Values ((19*a + b - d - g + 15) % 30, c / 4, c % 4)) As e4(h, i, k) Cross Apply (Values ((32 + 2*e + 2*i - h - k) % 7)) As e5(l) Cross Apply (Values ((a + 11*h + 19*l) / 433)) As e6(m) Cross Apply (Values ((h + l - 7*m + 90) / 25)) As e7(n) Cross Apply (Values ((h + l - 7*m + 33*n + 19) % 32)) As e8(p) Cross Apply (Values (datefromparts(y, n, p))) As e9(EasterDay) ) As ne --==== Related Easter Holidays (using Gauss' Western algorithm) --Cross Apply ( -- Select h.IsHoliday -- , h.HolidayDate -- , h.HolidayName -- From (Values (ge.EasterDay)) As e(EasterDate) -- Cross Apply (Values (0, dateadd(day,-46, e.EasterDate), 'Ash Wednesday') -- , (0, dateadd(day, -7, e.EasterDate), 'Palm Sunday') -- , (0, dateadd(day, -3, e.EasterDate), 'Maundy Thursday') -- , (1, dateadd(day, -2, e.EasterDate), 'Good Friday') -- , (0, dateadd(day, -1, e.EasterDate), 'Holy Saturday') -- , (1, dateadd(day, 0, e.EasterDate), 'Easter Sunday') -- , (0, dateadd(day, 39, e.EasterDate), 'Ascension Day') -- , (0, dateadd(day, 49, e.EasterDate), 'Pentecost') -- ) As h(IsHoliday, HolidayDate, HolidayName) -- ) As hd; Set STATISTICS time Off; |