本文共 3980 字,大约阅读时间需要 13 分钟。
之所以以1900年为出发点,是因为当年的一月一日为星期一(如果这天还是农历正月初一那就相当厉害,可惜是腊月初一),可以很方便的计算出从1900年1月1日到所输入日期的总天数,这也是万年历编写的核心算法。
从 1900.1.1 到 输 入 月 份 的 前 一 个 月 月 底 的 总 天 数 + 1 7 = = 0 ? { {从1900.1.1到输入月份的前一个月月底的总天数 + 1}\over {7}}==0? 7从1900.1.1到输入月份的前一个月月底的总天数+1==0? 如果等于0,说明所输入的月份的第一天为星期日,然后可以循环遍历第一天之前的空格位置以及后面的天数部分。/*主方法没有列出,这里仅仅列出了几个封装函数方法,主方法为public,方便用户端输入* 这些封装方法都是内部调用,所以使用了private修饰*//*** 判断是否为闰年* @param year int类型,年份* @return boolean类型,闰年返回true,平年返回false,也用于后面的月份判断*/private static boolean DaysOfleapYear(int year) { if ((0 == year % 4 && 0 != year % 100) || 0 == year % 400) { return true; } else { return false; }}/*** 计算从1900年到去年12月31日的总天数* @param year int类型,当前年份* @return int类型,返回总天数*/private static int DaysFrom1900ToLastYear(int year) { int sumDays = 0; for (int i = 1900; i < year; i++) { sumDays += DaysOfleapYear(i) ? 366 : 365; } return sumDays;}/*** 根据输入月份返回当月的天数* @param month int类型,当月月份* @param year int类型,年份* @return int类型,返回当月的天数*/private static int DaysOfMonth(int month, int year) { switch (month) { case 2: return DaysOfleapYear(year) ? 29 : 28; case 4: case 6: case 9: case 11: return 30; default: return 31; }}/*** 计算今年从1月1日到上个月的月末的总天数* @param month int类型,这个月月份* @param year int类型,年份* @return int类型,返回总天数*/private static int DaysFromJanuaryToLastMonth(int month, int year) { int sumDays = 0; for (int i = 1; i < month; i++) { sumDays += DaysOfMonth(i, year); } return sumDays;}/*** 万年历核心算法,计算当月第一天是星期几,如果 week == 0,表示星期日* 也是循环判断条件,日历从星期日计数,控制空格数* @param year int类型,当年年份* @param month int类型,当月月份* @return int类型,返回week值,判断第一天是周几*/private static int week(int year, int month) { return (DaysFrom1900ToLastYear(year) + DaysFromJanuaryToLastMonth(month, year) + 1) % 7;}/*** 格式化输出万年历* @param week int类型,表示了当月第一天是星期几,如果 week == 0,表示星期一,* 也是循环判断条件,日历从星期日计数,控制空格数* @param year int类型,今年的年份* @param month int类型,当月的月份,配合今年年份计算当月总天数*/private static void printByFormat(int week, int year, int month) { //外观 System.out.println("-----" + year + "年" + month + "月" + "万年历-------"); System.out.println("星期日\t星期一\t星期二\t星期三\t星期四\t星期五\t星期六"); int count = 0; //控制输出的空格数 for (int i = 1; i <= week; i++, count++) { System.out.print("\t\t"); } //输出日期 for (int i = 1; i <= DaysOfMonth(month, year); i++, count++) { if (0 == count % 7) { System.out.println(); } System.out.print(i + "\t\t"); }}//打印结果----------------2019年8月万年历-----------------星期日 星期一 星期二 星期三 星期四 星期五 星期六 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
/***主方法没有列出,依旧列出的是核心代码,从键盘输入的year和month可以直接替换掉下面的year和month*///设置为当前年份和月份,月份必须-1,因为是从0开始计数的calendar.set(Calendar.YEAR, year);calendar.set(Calendar.MONTH, month -1);//获取本月最大天数,这这里注意必须是DATE参数int maxOfMonth = calendar.getActualMaximum(Calendar.DATE);//将本月第一天作为当前时间,以方便后面计算第一天是星期几calendar.set(Calendar.DAY_OF_MONTH, 1);//获取第一天是星期几,java默认i=1表示星期日,这里-1使星期一作为值1返回,0表示周日int i = calendar.get(Calendar.DAY_OF_WEEK) - 1;//计数器,满七换行int count = 0;//打印第一天之前的空格if (0 == i) { //i == 0表示是周日,打印6个空格,特殊处理 for (int j = 1; j < 7; j++, count++) { System.out.print("\t\t "); }} else { for (int j = 1; j < i; j++, count++) { System.out.print("\t\t "); }}//格式化输出空格后面的日期for (int j = 1; j <= maxOfMonth; j++, count++) { if (0 == count % 7) { System.out.println(); } System.out.print(j + "\t\t ");}//打印结果----------------------- 2019年8月 ---------------------星期一 星期二 星期三 星期四 星期五 星期六 星期日 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
转载地址:http://qtgzi.baihongyu.com/