2010-02-03 26 views
24

Vì vậy, đây là một thử thách lập trình ít buồn cười. Tôi đã viết một phương pháp nhanh chóng để xác định tất cả các kỳ nghỉ của thị trường trong một năm cụ thể, và sau đó tôi bắt đầu reading about Easter và phát hiện ra cách điên rồ * logic là để xác định ngày của nó - ngày chủ nhật đầu tiên sau Paschal Full Moon theo sau phân tích mùa xuân! Có ai biết một chức năng hiện có để tính toán ngày lễ Phục sinh cho một năm nhất định không?Chức năng trả về ngày lễ Phục sinh cho năm nhất định

Đã cấp, có thể không phải tất cả rằng khó làm; Tôi chỉ nghĩ rằng tôi sẽ hỏi trong trường hợp ai đó đã làm điều này. (Và điều đó dường như rất có khả năng.)

CẬP NHẬT: Thực ra, tôi đang thực sự tìm kiếm các ngày Thứ Sáu Tuần Thánh (thứ Sáu trước Phục Sinh) ... Tôi chỉ tìm Phục Sinh sẽ làm cho tôi có . Và kể từ khi tôi ở Mỹ, tôi cho rằng tôi đang tìm kiếm lễ Phục sinh Công giáo? Nhưng có lẽ ai đó có thể sửa tôi nếu tôi sai.

* Bằng "điên", tôi muốn nói, như, liên quan đến. Không phải bất cứ điều gì xúc phạm ...

+7

Mà Phục Sinh? Công giáo, Chính Thống, hay Coptic? –

+0

Năm đầu tiên hoạt động chính xác là gì? –

+0

Một bài viết hay khác về "tính toán phục sinh": http://www.simple-talk.com/community/blogs/philfactor/archive/2009/01/18/71701.aspx. Và trong T-SQL, của tất cả mọi thứ. –

Trả lời

11

trong SQL Server Chủ Nhật Phục Sinh sẽ trông như thế này, cuộn xuống cho Thứ Sáu Tốt

CREATE FUNCTION dbo.GetEasterSunday 
(@Y INT) 
RETURNS SMALLDATETIME 
AS 
BEGIN 
    DECLARE  @EpactCalc INT, 
     @PaschalDaysCalc INT, 
     @NumOfDaysToSunday INT, 
     @EasterMonth INT, 
     @EasterDay INT 

    SET @EpactCalc = (24 + 19 * (@Y % 19)) % 30 
    SET @PaschalDaysCalc = @EpactCalc - (@EpactCalc/28) 
    SET @NumOfDaysToSunday = @PaschalDaysCalc - ( 
     (@Y + @Y/4 + @PaschalDaysCalc - 13) % 7 
    ) 

    SET @EasterMonth = 3 + (@NumOfDaysToSunday + 40)/44 

    SET @EasterDay = @NumOfDaysToSunday + 28 - ( 
     31 * (@EasterMonth/4) 
    ) 

    RETURN 
    ( 
     SELECT CONVERT 
     ( SMALLDATETIME, 
       RTRIM(@Y) 
      + RIGHT('0'+RTRIM(@EasterMonth), 2) 
      + RIGHT('0'+RTRIM(@EasterDay), 2) 
    ) 
END 
GO 

Good Friday là như thế này và nó sử dụng các chức năng Phục Sinh trên

CREATE FUNCTION dbo.GetGoodFriday 
( 
    @Y INT 
) 
RETURNS SMALLDATETIME 
AS 
BEGIN 
    RETURN (SELECT dbo.GetEasterSunday(@Y) - 2) 
END 
GO 

Từ đây: http://sqlserver2000.databases.aspfaq.com/why-should-i-consider-using-an-auxiliary-calendar-table.html

+0

Tôi * nghĩ * bạn là người đầu tiên thực sự đăng mã thực hiện điều này. Kudos, bạn của tôi ... và cảm ơn. –

+0

Điều này chỉ hoạt động trong những năm 1900 - 2199. Trước năm 1900 và sau năm 2199, nó lệch khỏi kịch bản tính toán Phục Sinh của NOAA. Lợi ích của tập lệnh này là nó ngắn và ngọt ngào. Đây là [kịch bản của NOAA] (http://aa.usno.navy.mil/faq/docs/easter.php) Cảm ơn bạn đã đăng bài này. – LDawggie

+0

@LDawggie Độ lệch giữa phiên bản đơn giản trong câu trả lời này và phiên bản NOAA thực sự bắt đầu từ năm 1899 (ngày 3 tháng 4 năm 1899 (đơn giản) so với ngày 2 tháng 4 năm 1899 (NOAA)). Nhưng chúng khác nhau ngay từ năm 2100 (ngày 27 tháng 3 năm 2100 (Đơn giản) so với ngày 28 tháng 3 năm 2100 (NOAA)) Tôi sẽ đăng câu trả lời bằng thuật toán NOAA vào cuối ngày hôm nay. – buckley

27

Python: sử dụng dateutil's easter() function.

>>> from dateutil.easter import * 
>>> print easter(2010) 
2010-04-04 
>>> print easter(2011) 
2011-04-24 

Các chức năng được, như một cuộc tranh cãi, các loại tính bạn thích:

EASTER_JULIAN = 1 
EASTER_ORTHODOX = 2 
EASTER_WESTERN = 3 

Bạn có thể chọn một trong những liên quan đến Mỹ.

Giảm hai ngày kể từ kết quả sẽ cung cấp cho bạn Thứ Sáu Tuần Thánh:

>>> from datetime import timedelta 
>>> d = timedelta(days=-2) 
>>> easter(2011) 
datetime.date(2011, 4, 24) 
>>> easter(2011)+d 
datetime.date(2011, 4, 22) 

Lạ lùng thay, có ai đó đang lặp lại này, và công bố các kết quả trong Wikipedia's article about the algorithm:

alt text

4

Khi nó đến cho tôi để viết những dòng này (dự đoán lưu lượng dựa trên ngày trong tuần và ngày lễ), Tôi đã từ bỏ việc tự mình viết nó. Tôi tìm thấy nó ở đâu đó trên mạng. Mã này là phạm vi công cộng, nhưng ...

phào nhẹ

xem cho chính mình.

void dateOfEaster(struct tm* p) 
{ 
    int Y = p->tm_year; 
    int a = Y % 19; 
    int b = Y/100; 
    int c = Y % 100; 
    int d = b/4; 
    int e = b % 4; 
    int f = (b + 8)/25; 
    int g = (b - f + 1)/3; 
    int h = (19 * a + b - d - g + 15) % 30; 
    int i = c/4; 
    int k = c % 4; 
    int L = (32 + 2 * e + 2 * i - h - k) % 7; 
    int m = (a + 11 * h + 22 * L)/451; 
    p->tm_mon = ((h + L - 7 * m + 114)/31) - 1; 
    p->tm_mday = ((h + L - 7 * m + 114) % 31) + 1; 
    p->tm_hour = 12; 
    const time_t tmp = mktime(p); 
    *p = *localtime(&tmp); //recover yday from mon+mday 
} 

Một số câu hỏi không được để trống.

Tôi cảm thấy may mắn là tất cả các ngày lễ di chuyển ở nước tôi đều là khoản bù đắp cố định kể từ ngày lễ Phục Sinh.

+0

+1 Rất đẹp. Hãy thử tìm ra DST ở đất nước của tôi, nó có một số giai thoại hay. http://en.wikipedia.org/wiki/Israel_Summer_Time –

+1

Dường như nhà phát triển đã viết điều này cho j trục. –

+1

Tôi nghĩ rằng đây thực sự là thuật toán của Donald Knuth: http://www.linuxtopia.org/online_books/programming_books/python_programming/python_ch38.html –

1

Chức năng SQL Server dưới đây là tổng quát hơn là câu trả lời chấp nhận

Câu trả lời được chấp nhận là chỉ đúng trong phạm vi (bao gồm): 1900/04/15 đến 2099-04-12

Nó sử dụng các thuật toán cung cấp bởi The Observatory hải Hoa Kỳ (USNO)

http://aa.usno.navy.mil/faq/docs/easter.php

CREATE FUNCTION dbo.GetEasterSunday (@Y INT) 
RETURNS DATETIME 
AS 
    BEGIN 

     -- Source of algorithm : http://aa.usno.navy.mil/faq/docs/easter.php 

     DECLARE @c INT = @Y/100 
     DECLARE @n INT = @Y - 19 * (@Y/19) 
     DECLARE @k INT = (@c - 17)/25 
     DECLARE @i INT = @c - @c/4 - (@c - @k)/3 + 19 * @n + 15 
     SET @i = @i - 30 * (@i/30) 
     SET @i = @i - (@i/28) * (1 - (@i/28) * (29/(@i + 1)) * ((21 - @n)/11)) 
     DECLARE @j INT = @Y + @Y/4 + @i + 2 - @c + @c/4 
     SET @j = @j - 7 * (@j/7) 
     DECLARE @l INT = @i - @j 
     DECLARE @m INT = 3 + (@l + 40)/44 
     DECLARE @d INT = @l + 28 - 31 * (@m/4) 

     RETURN 
    ( 
     SELECT CONVERT 
     ( DATETIME, 
       RTRIM(@Y) 
      + RIGHT('0'+RTRIM(@m), 2) 
      + RIGHT('0'+RTRIM(@d), 2) 
    ) 
    ) 
    END 


GO 
Các vấn đề liên quan