一、万年历
这个程序很好地说明了分治策略,因为在一开始过多地关注细节往往会阻碍解决问题的进程。所以最好是通过对一个大问题的逐步求解,得到最终的结果。
实现结果:
源代码如下:
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的值是当前日之前的天数,所以当前日期的值要加一。