日历程序的编写:
编写一个程序,程序提供两种功能:
- 根据用户输入的年份输出该年日历。
- 根据用户输入的日期,输出该天星期。
不使用Calendar类,只用Scanner类
程序应具有良好的人机交互性能,即:程序应向用户提示功能说明,并可根据用户的功能选择,执行对应的功能,并给出带详细描述信息的最终执行结果。
刚开始学习Java,记录一下学习过程
相对来说,自我感觉功能二相对于功能一简单一点,我先从功能二开始写,根据用户输入的日期,输出该天的星期,开始的思路是确定一个基准年月日,假设基准为2000年1月1日,查询可得该天为星期六,然后根据要查询的日期来计算与基准日期相差的天数,然后除以七取余数,若查询日期在基准日期之前,可用6减去余数,得到的即为查询日期的星期,差为0即为星期天,若查询日期在基准日期之后同理。但这个算起来较为麻烦,然后我百度后查的了基姆拉尔森公式
可以直接来根据公式来算的某年某月某日是星期几。
基姆拉尔森计算公式
W= (d+2m+3(m+1)/5+y+y/4-y/100+y/400) mod 7
在公式中d表示日期中的日数,m表示月份数,y表示年数。
注意:在公式中有个与其他公式不同的地方:
把一月和二月看成是上一年的十三月和十四月,例:如果是2004-1-10则换算成:2003-13-10来代入公式计算。
有了这个公式就很方便了,首先我们用Scanner类直接从键盘输入一个日期,年月日都是整数,所以用了nextInt()来接收输入的整数,
因为基姆拉尔森计算公式中一月和二月堪称是上一年的十三月和十四月,所以我使用if 语句当输入的月份是1或2时,将参与公式运算的month加上个12,year减一,然后再参与运算,最后的结果中如果为0,那么再给加上个7再输出。两中想法的思路都不难,但明显第二种写起来更简单,最后我使用了第二种方法。
功能一的实现就比较复杂,首先判断该年是否为闰年,使用isLeap()返回值为Boolean类型的函数来判断,是闰年返回true,不是返回false。
定义一个Date类,类的成员有year、month、day,将Date实例化,接收键盘输入的年份
然后用功能二中的公式来计算该年份一月一日的星期,
使用for循环来按照月份来输出,通过计算了该年一月一日的星期,可知道该年的是从星期几开始,然后一月一号这之前的全部输出空白。
二月、三月……之后同理,计算月份第一天的星期,然后之前的都空白输出。
就像图中这样,一月一日是星期四,之前的那都是空白的,然后我发现加入每月第一天的星期为w,当日期加上(w-1)如果除以七余数为0的话该天正好为星期天,然后以此可以控制换行。
再有一个比较难的就是如何对齐,将星期与日期对齐,在网上查询后我使用了整型数的输出printf(“%4d”,iday),这个就是表示输出一个整型数值,输出宽度为4,且右对齐,不够的空格补齐,%3d,%5d应该同理。然后再星期前加一个空格,加以来正好是四个字节,这样就实现了对齐。
最后我们希望日历程序由我们自己设定退出,所以又外加了一个永真while循环,当我们输入3时,break。程序退出。
最后我们再加一个不按照要求输入时,系统会提示按照要求输入。
代码还有一些问题,但可以正常运行使用,以后更深入的学习后再来修改
import java.util.Scanner;
public class Calendar
{
public static void main(String[] args)
{
class Date{
int year;
int month=1;
int day=1;
boolean leap=true;
public boolean isLeap()//判断闰年
{
if(year%4==0&&year%100!=0||year%400==0) leap = true;
else leap = false;
return leap; //判断是否为闰年
}
}
loop:while(true) {
Scanner scan=new Scanner(System.in);//从键盘获得输入
Date n=new Date(); //n为Date的一个实例
System.out.println("^_^请输入1或2或3来选择功能 1:输入年份输出该年日历 2:输入的日期,输出该天星期 3:退出功能");
//从键盘输入选择功能
int x=scan.nextInt();
if (x==1) { //实现功能1
System.out.println("请输入年份:");
n.year=scan.nextInt();
n.month=1;
n.day=1;
for(int imonth=1;imonth<13;imonth++)
{
int W=0;
System.out.printf(" %d月\n",imonth);//每个月顶行输出这是第几月
System.out.println(" Mon Tue Wed Tur Fri Sat Sun");//日期上方的星期
if(imonth==1||imonth==2) {//姆拉尔森计算公式一月二月的情况
int iimonth=imonth+12;
int iiyear=n.year-1;
W= (1+2*iimonth+3*(iimonth+1)/5+iiyear+iiyear/4-iiyear/100+iiyear/400+1)%7;
if(W==0)W=7;
}
else {
W= (1+2*imonth+3*(imonth+1)/5+n.year+n.year/4-n.year/100+n.year/400+1)%7;
if(W==0)W=7;//计算每个月的第一天的星期
}
for(int i = 1;i<W;i++)
System.out.print(" ");//每个月的一号之前空白输出
for(int iday=1;iday<=31;iday++)
{
if(imonth==2&&n.isLeap()&&iday==30) break;//闰年二月29天
if(imonth==2&&!n.isLeap()&&iday==29) break;//平年二月28天
if((imonth==4||imonth==6||imonth==9||imonth==11)&&iday==31) break;//小月30天
System.out.printf("%4d",iday);//实现对齐四个字节的数字,向右靠齐,不够的空格补齐
if((iday+W-1)%7==0)
{
System.out.printf("\n");//星期天后换行
}
}
System.out.printf("\n");//一个月完后换行
}
}
else if(x==2) { //实现功能2
System.out.println("请输入年份:");
int y=scan.nextInt();
System.out.println("请输入月份:");
int m=scan.nextInt();
System.out.println("请输入日期:");
int d=scan.nextInt();
if(m==1){ //姆拉尔森计算公式一月二月的情况
m=13;
y=y-1;
}
if(m==2) {
m=14;
y=y-1;
}
int M= (d+2*m+3*(m+1)/5+y+y/4-y/100+y/400+1)%7;//使用基姆拉尔森计算公式来根据年月日来计算星期
if(M==0) {
M=7;
}
System.out.println("^_^该天星期为:"+M);
}
else if (x==3) { //退出系统
System.out.println("欢迎下次使用!^_^");
scan.close();
break loop;
}
else if(x!=1||x!=2||x!=3){
System.out.println("请按照提示信息输入^_^");
}
}
}
}