星期几算法错误?

Day of week algorithm bug?

你好我做了一个生成HTML日历的软件。我按照 wiki http://www.wikihow.com/Calculate-the-Day-of-the-Week 中的方法 1 算法来获取一年中当天的确切星期几。但问题是当它从 2099 年到 2100 年时出现错误,然后在 2100 年大约落后一天。

我的问题是...该算法是否正确?应该回到 2100 年的一天吗?我没有时间等 85 年才弄明白:( 我还尝试了复活节星期天算法,它还会在应该是星期日的那一天生成星期日算法,所以我不确定谁有权利,如果我或两个正确生成算法。

以下是我认为未来几年有问题的地方: 测试年份 0 到 2200
年复一年不正确的日子:99/100
每年不正确的日期:199/200
年复一年不正确的日子:299/300
每年不正确的日期:499/500
年复一年不正确的日子:599/600
每年不正确的日期:699/700
每年不正确的日期:899/900
每年不正确的日期:999/1000
每年不正确的日期:1099/1100
每年不正确的日期:1299/1300
每年不正确的日期:1399/1400
每年不正确的日期:1499/1500
每年不正确的日期:1699/1700
每年不正确的日期:1799/1800
年复一年的日期不正确:1899/1900
每年不正确的日期:2099/2100

*编辑
这是获得复活节星期天的算法:

int c = year/100;
int n = year - 19*(int)(year/19);
int k = (c - 17)/25;
int i = c - (int)(c/4) - (int)((c - k)/3) + 19*n + 15;
i -= 30*(int)(i/30);
i -= (int)(i/28)*(1 - (int)(i/28)*(int)(29/(i + 1))*(int)((21 - n)/11));
int j = year + (int)(year/4) + i + 2 - c + (int)(c/4);
j -= 7*(int)(j/7);
int l = i - j;
int m = 3 + (int)((l + 40)/44); //Your month when is Easter Sunday
int d = l + 28 - 31*(int)(m/4); //Your day when is Easter Sunday

这是获取年月日中星期几的算法

int [] CENTURY_TABLE = {0, 5, 3, 1};
int [] MONTH_TABLE = {0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5};
boolean leap = false;
int t1 = (day + MONTH_TABLE[month - 1]) % 7;
int m1 = year % 100;
int t2 = (m1 % 7) + (m1/4) + CENTURY_TABLE[((int)(year/100)) % CENTURY_TABLE.length] - (leap  &&  (month == 1  || month == 2) ? 1 : 0);
if(t2 == -1){
    t2 = 6;
}
int d = (t1 + t2) % 7;  //0 - Saturday, 1 - Sunday, 2 - Monday... 6 - Friday

*修复
将星期几算法中的 "leap" 摘要更改为

leap = year % 4 == 0  &&  (year % 100 == 0 ? year % 400 == 0 : true) //This fixed my problem <3

我认为你的程序受闰年影响:https://en.wikipedia.org/wiki/Leap_year

您对所有可整除 100 但不是 400 的年份都有疑问。

在 select 之后编辑为解决方案:

代码运行没有问题。我稍微更改了一下进行测试,没有出现错误:

@Test
public void dayTest()
{
    for (int y = 2099; y <=2100; y++)
    {
        int day = easterSundayDay(y);
        int month = easterSundayMonth(y);

        assertTrue("Wrong year: " + day + "."+ month + "."+ y + " is day: " + dayOfWeek(day, month, y), 1 ==dayOfWeek(day, month, y));
    }
}

public int easterSundayDay(int year)
{
    int c = year/100;
    int n = year - 19*(int)(year/19);
    int k = (c - 17)/25;
    int i = c - (int)(c/4) - (int)((c - k)/3) + 19*n + 15;
    i -= 30*(int)(i/30);
    i -= (int)(i/28)*(1 - (int)(i/28)*(int)(29/(i + 1))*(int)((21 - n)/11));
    int j = year + (int)(year/4) + i + 2 - c + (int)(c/4);
    j -= 7*(int)(j/7);
    int l = i - j;
    int m = 3 + (int)((l + 40)/44); //Your month when is Easter Sunday
    int d = l + 28 - 31*(int)(m/4);

    return d;
}

public int easterSundayMonth(int year)
{
    int c = year/100;
    int n = year - 19*(int)(year/19);
    int k = (c - 17)/25;
    int i = c - (int)(c/4) - (int)((c - k)/3) + 19*n + 15;
    i -= 30*(int)(i/30);
    i -= (int)(i/28)*(1 - (int)(i/28)*(int)(29/(i + 1))*(int)((21 - n)/11));
    int j = year + (int)(year/4) + i + 2 - c + (int)(c/4);
    j -= 7*(int)(j/7);
    int l = i - j;
    int m = 3 + (int)((l + 40)/44); //Your month when is Easter Sunday
    int d = l + 28 - 31*(int)(m/4);

    return m;
}
public int dayOfWeek(int day, int month, int year)
{
    int [] CENTURY_TABLE = {0, 5, 3, 1};
    int [] MONTH_TABLE = {0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5};
    boolean leap = false;
    int t1 = (day + MONTH_TABLE[month - 1]) % 7;
    int m1 = year % 100;
    int t2 = (m1 % 7) + (m1/4) + CENTURY_TABLE[((int)(year/100)) % CENTURY_TABLE.length] - (leap  &&  (month == 1  || month == 2) ? 1 : 0);
    if(t2 == -1){
        t2 = 6;
    }
    int d = (t1 + t2) % 7;

    return d;
}