星期几算法错误?
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;
}
你好我做了一个生成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;
}