几年前在看动漫电影《夏日大作战》时,一个场景是宅男主人公在车上心算妹子的出生日期是星期几,当时对这一技能十分好奇。不过人家是全国奥数队员,数字功底深厚,心算某一天是星期几根本就不算个事儿,我也就只能望而兴叹了。今天看到《Java语言程序设计》第3章的课后习题时,给出了一个计算某天是星期几的公式,这个公式被叫做“泽勒一致性”,由克里斯汀·泽勒发明。公式长这样:
公式中各个字母的含义是:
h: 是我们要计算的星期几
q: 是要计数某天的日期数,比如要计算2014年4月17日,q 就是17
m: 是某天所在的月份数
k: 是某天所在世纪的后两位年份,如:2014年4月17日,k就是14
j: 是某天所在世纪的世纪数,如:2014年4月17日,j就是20
下面我们来套下公式,看是不是能求出某天是星期几。
h = (17 + (26*(4+1)/10) + 14 + 14/4 + 20/4 + 5*20) % 7
h = 5
发现余数是5,但2014年4月17日是星期四。而这个算法余数结果与星期的对应关系是:0为星期六,1为星期天,2为星期一,3为星期二,4为星期三,5为星期四,6为星期五,6为星期六。所以,余数是5为星期四,看来算法是对。不过,我们还没对特殊的2月份做过测试呢。我们接着再做几组数据的测试:
2014年2月1日 --> 星期三,实际是星期六
2014年2月28日 --> 星期二,实际是星期五
2014年10月2日 --> 星期四,实际是星期四
2014年12月8日 --> 星期一,实际是星期一
1989年5月10日 --> 星期三,实际是星期三
1990年1月5日 --> 星期三,实际是星期五
上面6个日期计算的星期数,三个错误,三个正确。但只要日期是在2月份的全部歇菜,连1月份的也不对。原来泽勒一致性还有个规定:如果月份是1月或2月,月份数字要用13和14来代替,同时年份数字要改为去年的年份数字。如:2014年1月29日,实际被计算的年、月、日数字是:2013, 13, 29。根据这些规则,我们的Java代码如下:
import java.util.Scanner;
class calculateDate
{
public static void main(String[] args)
{
Scanner s = new Scanner(System.in);
System.out.print("Enter year: (e.g., 2008): ");
int year = s.nextInt();
System.out.print("Enter month: 1-12: ");
int month = s.nextInt();
System.out.print("Enter the day of the month: 1-31: ");
int day = s.nextInt();
int k = year % 100;
int j = year / 100;
// 处理1月、2月的日期
if(month == 1)
{
month = 13;
year = year - 1;
}
else if (month == 2)
{
month = 14;
year = year
}
int h = (day + (26*(month+1)/10) + k + k/4 + j/4 + 5*j) % 7; // 泽勒一致性公式
// 对余数做日期判断
switch(h)
{
case 0:
System.out.println("Day of the week is Sunday.");
break;
case 1:
System.out.println("Day of the week is Saturday.");
break;
case 2:
System.out.println("Day of the week is Monday.");
break;
case 3:
System.out.println("Day of the week is Tuesday.");
break;
case 4:
System.out.println("Day of the week is Wednesday.");
break;
case 5:
System.out.println("Day of the week is Thursday.");
break;
case 6:
System.out.println("Day of the week is Friday.");
break;
}
}
}