Java中几个关于时间的程序:万年历、Zeller公式、显示当前时间

一、万年历

这个程序很好地说明了分治策略,因为在一开始过多地关注细节往往会阻碍解决问题的进程。所以最好是通过对一个大问题的逐步求解,得到最终的结果。


实现结果:




源代码如下:

import java.util.Scanner; 
public class Text {
	public static boolean isLeapYear(int year) {//判断闰年
        if((year%4 == 0 && year%100 != 0) || (year%400 == 0))
            return true;
        else 
            return false;
    }

    public static int daysOfMonthOfYear(int year, int month) {//每个月的天数
        int day = 0;
        switch (month) {
            case 1: 
            case 3:
            case 5:
            case 7:
            case 8:
            case 10:
            case 12:
                day = 31;
                break;
            case 4: 
            case 6:
            case 9:
            case 11:
                day = 30;
                break;
            case 2: 
                if(isLeapYear(year)) {
                    day = 29;
                } else {
                    day = 28;
                }
                break;
            }
        return day;
    }

    public static int whatDayOfMonth(int year, int month) {
        int firstDay;//日历月份开始的星期
        int totalDays = 0;//计算和日历月份的第一天相差的总天数 
        for(int i=1900; i<year; i++) {//以1900年1月1日(星期一)为时间基点
            if(isLeapYear(i)) 
            	totalDays = totalDays + 366;
            else 
            	totalDays = totalDays + 365;
        }
        for(int j=1; j<month; j++)
        	totalDays = totalDays + daysOfMonthOfYear(year, j);
        firstDay = (totalDays + 1) % 7;
        return firstDay;
    }

    public static void main(String[] args) {
    	Scanner input=new Scanner(System.in);
		System.out.print("Enter full year(e.g.,2001):");
		int year=input.nextInt();
		System.out.print("Enter month in number between 1 and 12:");
		int month=input.nextInt();
		switch(month){
			case 1:System.out.println("\t\t\tJanuary "+year);break;
			case 2:System.out.println("\t\t\tFebruary "+year);break;
			case 3:System.out.println("\t\t\tMarch "+year);break;
			case 4:System.out.println("\t\t\tApril "+year);break;
			case 5:System.out.println("\t\t\tMay "+year);break;
			case 6:System.out.println("\t\t\tJune "+year);break;
			case 7:System.out.println("\t\t\tJuly "+year);break;
			case 8:System.out.println("\t\t\tAugust "+year);break;
			case 9:System.out.println("\t\t\tSeptember "+year);break;
			case 10:System.out.println("\t\t\tOctober "+year);break;
			case 11:System.out.println("\t\t\tNovember "+year);break;
			case 12:System.out.println("\t\t\tDecember "+year);
		}
		System.out.println("----------------------------------------------------");
		System.out.println("Sun\tMon\tTue\tWed\tThu\tFri\tSat\t");
        int times = 0;
        for(int i=0; i<whatDayOfMonth(year, month)&&whatDayOfMonth(year, month)!=6; i++) {
            System.out.print("\t");
            times++;
        }
        for(int j=1; j<=daysOfMonthOfYear(year, month); j++) {
            System.out.print(j + "\t");
            times++;
            if(times % 7 == 0) {
                System.out.println();
            }
        }       
    }
}

其中, firstDay = (totalDays + 1) % 7;  这个语句值得去思考。

记得要补充输出空格的条件 whatDayOfMonth(year, month)!=6 ,否则若第一天就是星期日将会输出7个空格再开始打印第一天。


二、Zeller公式

由于在万年历中理解求第一天的星期花了较长时间,且在做习题的时候看到了Zeller公式,于是也写了如何用Zeller公式求第一天的星期。

 W=Y+[Y/4]+[C/4]-2C+[26×(M+1)/10]+D-1

实现结果:


源代码如下:

import java.util.Scanner; 
public class Text {
	public static void main(String[] args) {
		Scanner input=new Scanner(System.in);
		int week,century,year,month,day,number;
		number=input.nextInt();
		century=number/100;//年份前两位
		year=number%100;//年份后两位
		month=input.nextInt();
		day=input.nextInt();
		if(month==1) {//1月2月分别看作上一年的13月14月
			month=13;
			if(year==0) {
				year=99;
				century-=1;
			}
			else
				year--;
		}
		else if(month==2) {
			month=14;
			if(year==0) {
				year=99;
				century-=1;
			}
			else
				year--;
		}
		week=(year+(int)(year/4)+(int)(century/4)-2*century+(int)(26*(month+1)/10)+day-1)%7;
		week=(week+7)%7;//注意负数的取模运算
		System.out.println(week);
	}
}
这个方法相对较好理解一些,在第一遍运行时代入几个日期都得到正确结果就以为是对的,但当代入2006年4月4日发现结果竟然是负数。这是因为没有对可能出现的负数进行取模运算(即结果加MOD再取余),导致有可能得到一个负的星期数。

修改后就得到正确的结果。


三、显示当前时间(用System.currentTimeMillis()

用了两种不同的方法来获得不同的当前时间:1、GMT:用了复杂的System.currentTimeMillis()2、CST:用了简单的java.util.Date()

实现结果:


源代码如下:

import java.util.Scanner; 
public class Text {
	public static void main(String[] args) {
		long totalSeconds=System.currentTimeMillis()/1000;
		long currentSeconds=totalSeconds%60;
		long totalMinutes=totalSeconds/60;
		long currentMinutes=totalMinutes%60;
		long totalHours=totalMinutes/60;
		long currentHours=totalHours%24;
		long totalDays=totalHours/24;		
		long days=0;
		int year=1970;//Unix时间戳为1970年1月1日(星期四)
		for(;;year++) {//求得当前年份
			if(isLeapYear(year))
				if(366+days>=totalDays)
					break;
				else
					days+=366;
			else
				if(365+days>=totalDays)
					break;
				else
					days+=365;
		}
		days=totalDays-days;//在当前年份,当前日期以前的天数
		String month;
		if(isLeapYear(year)) {
			if(days<=60&&days>=32) {
				month="February ";
				days-=31;
			}
			else if(days<=31)
				month="January ";
			else if(days<=91) {
				month="March ";
				days-=60;
			}
			else if(days<=121) {
				month="April ";
				days-=91;
			}
			else if(days<=152) {
				month="May ";
				days-=121;
			}
			else if(days<=182) {
				month="June ";
				days-=152;
			}
			else if(days<=213) {
				month="July ";
				days-=182;
			}
			else if(days<=244) {
				month="August ";
				days-=213;
			}
			else if(days<=274) {
				month="September ";
				days-=244;
			}
			else if(days<=305) {
				month="October ";
				days-=274;
			}
			else if(days<=335) {
				month="November ";
				days-=305;
			}
			else {
				month="December ";	
				days-=335;
			}
		}
		else {
			if(days<=59&&days>=32) {
				month="February ";
				days-=31;
			}
			else if(days<=31)
				month="January ";
			else if(days<=90) {
				month="March ";
				days-=59;
			}
			else if(days<=120) {
				month="April ";
				days-=90;
			}
			else if(days<=151) {
				month="May ";
				days-=120;
			}
			else if(days<=181) {
				month="June ";
				days-=151;
			}
			else if(days<=212) {
				month="July ";
				days-=181;
			}
			else if(days<=243) {
				month="August ";
				days-=212;
			}
			else if(days<=273) {
				month="September ";
				days-=243;
			}
			else if(days<=304) {
				month="October ";
				days-=273;
			}
			else if(days<=334) {
				month="November ";
				days-=304;
			}
			else {
				month="December ";	
				days-=334;
			}
		}
		System.out.println("Method1(GMT):Current date and time is "+month+(days+1)+","+year+" "+currentHours+":"
		+currentMinutes+":"+currentSeconds);
		java.util.Date currentDate=new java.util.Date();
	    System.out.println("Method2(CST):Current date: "+currentDate.toString());
	}
	
	public static boolean isLeapYear(int year) {//判断闰年
        if((year%4 == 0 && year%100 != 0) || (year%400 == 0))
            return true;
        else 
            return false;
    }

}
代码看似很长,其实思想很简单,主要是求月份的那里占了很大一部分。第一次运行的时候日期不对,少了一天,是因为最后days的值是当前日之前的天数,所以当前日期的值要加一。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值