zoukankan      html  css  js  c++  java
  • 使用Calendar类和它的子类GregorianCalendar类实现构建动态日历

    大家好, 我是安心君,这是我在博客园的第一篇博客. 这里主要和大家分享我使用Calendar类和它的子类GregorianCalendar类实现构建动态日历项目的收获和心得. 

    以前我们在没有学习到这两个类之前,用的是当前月的头一天到1900年1月1日(因为在这天正好是星期一)的时间除以7(一周的时间) 所得的余数 确定当前月份的第一天是星期几. 这个算法虽然容易理解,但是实现起来比较繁琐.而当我们学会了Calendar类的使用,会发现制作动态日历的过程变得非常轻松

    这里先把代码奉上(在敲这个代码的时候,本人对Calendar类的使用也不熟悉,所以代码很多地方都可以优化,我也会逐一解析)

    import java.util.Calendar;
    import java.util.GregorianCalendar;

    public class DynaCalendar {
    //创建一个日历对象
    Calendar c = Calendar.getInstance();
    //创建一个公历类对象
    GregorianCalendar gc = new GregorianCalendar();
    public static void main(String[] args) {
    //这里选择直接定义 如果你们想在控制台输入 写个Scanner就行了 也不麻烦
    //咱们这就主讲算法了
    int year = 2020;
    int month = 7;
    //创建一个对象调用日历方法(如果创建对象只需要调用一个方法,则可以直接new 不需要再定义一个引用去接受它)
    //建议大家看方法一定要从主方法开始看起 所有程序都是由主方法开始执行的
    new DynaCalendar().dynaCalendar(year,month);
    }

    public void dynaCalendar(int year,int month) {
    //先输出日历格式
    System.out.println("星期一"+" "+"星期二"+" "+"星期三"+" "+"星期四"+" "+"星期五"+" "+"星期六"+" "+"星期日"+" ");
    //通过GregorianCalendar类的isLeapYear判断是否为闰年
    if(gc.isLeapYear(year)){
    switch(month){
    case 1:
    case 3:
    case 5:
    case 7:
    case 8:
    case 10:
    case 12: evenMonth(month - 1,year);//大月排序方法
    break;
    case 2: leapFebMonth(month - 1,year);//闰年2月排序方法
    break;
    case 4:
    case 6:
    case 9:
    case 11: oddMonth(month - 1,year);//小月排序方法
    }
    }else{
    switch(month){
    case 1:
    case 3:
    case 5:
    case 7:
    case 8:
    case 10:
    case 12: evenMonth(month - 1,year);
    break;
    case 2: febMonth(month - 1,year);//普通年份2月排序方法
    break;
    case 4:
    case 6:
    case 9:
    case 11: oddMonth(month - 1,year);
    }

    }
    }
    public void evenMonth(int month,int year){//大月
    int t = 0;
    c.set(Calendar.YEAR, year);
    c.set(Calendar.MONTH, month);
    c.set(Calendar.DAY_OF_MONTH, 1);
    int day = c.get(Calendar.DAY_OF_WEEK);
    // System.out.println(day);
    if(day == 1){
    t = 6;
    }else{
    //打印的空格数
    t = day - 2;
    }
    for(int i = 0;i < t;i++){
    System.out.print(" ");
    }
    for(int i = 1;i < 32;i++){
    System.out.print(i+" ");
    if((i + t) % 7==0){
    System.out.println();
    }
    }
    }

    public void febMonth(int month,int year){//普通2月
    int t = 0;
    c.set(Calendar.YEAR, year);
    c.set(Calendar.MONTH, month);
    c.set(Calendar.DAY_OF_MONTH, 1);
    int day = c.get(Calendar.DAY_OF_WEEK);
    // System.out.println(day);
    if(day == 1){
    t = 6;
    }else{
    t = day - 2;
    }
    for(int i = 0;i < t;i++){
    System.out.print(" ");
    }
    for(int i = 1;i < 29;i++){
    System.out.print(i+" ");
    if((i + t) % 7==0){
    System.out.println();
    }
    }
    }

    public void oddMonth(int month,int year){//小月
    int t = 0;
    c.set(Calendar.YEAR, year);
    c.set(Calendar.MONTH, month);
    c.set(Calendar.DAY_OF_MONTH, 1);
    int day = c.get(Calendar.DAY_OF_WEEK);
    // System.out.println(day);
    if(day == 1){
    t = 6;
    }else{
    t = day - 2;
    }
    for(int i = 0;i < t;i++){
    System.out.print(" ");
    }
    for(int i = 1;i < 31;i++){
    System.out.print(i+" ");
    if((i + t) % 7==0){
    System.out.println();
    }
    }
    }

    public void leapFebMonth(int month,int year){//闰年2月
    int t = 0;
    c.set(Calendar.YEAR, year);
    c.set(Calendar.MONTH, month);
    c.set(Calendar.DAY_OF_MONTH, 1);
    int day = c.get(Calendar.DAY_OF_WEEK);
    // System.out.println(day);
    if(day == 1){
    t = 6;
    }else{
    t = day - 2;
    }
    for(int i = 0;i < t;i++){
    System.out.print(" ");
    }
    for(int i = 1;i < 30;i++){
    System.out.print(i+" ");
    if((i + t) % 7==0){
    System.out.println();
    }
    }
    }
    }

    可能这个时候有些读者已经看出来了 那个时候我还不会使用Calendar类中的getActualMaximum 方法 所以冤枉的写了很多switch-case语句和确定不同月份的日历排序的方法(很烦~~~).

    Calendar类中的getActualMaximum(int field)方法中的参数可以把当前月份-1的值传进来,确定当前月份的天数,这样就不用像我一样创建很多这种方法去计算.而且这两个switch其实也能合并成一个 在二月份那里加上确认闰年的判断就行了

    虽然代码的冗余度高了,但是从某种角度说,读者看这样的代码思路应该会更清晰,也是好事.    现在开始分析代码 :

    1.首先定义创建Calendar类和GregorianCalendar类的对象,这里主要会用到GregorianCalendar类中的isLeapYear方法,即判断闰年的方法.

    2.首先我们就能想到,拿到一个年份,首先判断他是否为闰年,因为只有是或不是两种情况,所以我在选择了闰年一个switch-case语句 非闰年一个switch-case语句 

    3.根据不同月份确定如何排序  其实也没啥改变,只是修改下天数罢了 排序的方式都是相同的  (重点:这里传入方法的月份应该是你输入月份-1的值,因为在Calendar类内部12个月份是按数组排列的 ,下标为0-11,要比实际值少个1,当然用户不知道我们方法的内部实现,不可能自己手动-1,因此我们要将传入的月份-1达到用户的期望)

    4.当设置的年份和月份传入方法后 , 我们利用Calendar类中的set(int field, int value)方法,将时间设定到我们所设置的时间,重点来了:接着我们把天数通过c.set(Calendar.DAY_OF_MONTH, 1);方法设定到当前月份的第一天,然后通过c.get(Calendar.DAY_OF_WEEK);方法得到当前月份的第一天在这周是第几天  这里通过Calendar类中的这些方法就可以实现定位当前月份第一天的想法 较之以前省下了很多代码的编写 

    5.定位了当前月份第一天后,我们就可以确定日历前的空格是多少,这里推荐用" "制表符进行分割. 接下来还是重点:我们要知道,以前的日历是以星期日为一周的第一天,Calendar类也是一样,所以正常情况下,我们是用day-1作为空格数,而现在应该用day-2作为空格数了. 重重重点!   这里还有个意外 就是当当前月份的第一天就是星期日的时候,day -1 是0 而空格数变成了负数,这当然是不合乎常理的 所以我们只需要把这个单独情况列出来即可.

    6.我们输出空格的算法已经完成 最后一步就是把当前月份的日历打印出来,这就很简单了 从当前月份的第一天循环输出到最后一天 (将得到的天数+空格数)%7,得到的余数如果是0 就换行

    7.这样动态日历就制作完成了!!!!!!!!!

    这里附上上面代码的运行结果:

  • 相关阅读:
    Laravel入坑指南(5)——请求与响应
    Laravel入坑指南(4)——数据库(Mysql)
    CentOS7 开机网卡加载失败
    个人CKeditor的config.js配置
    取消ie浏览器edge浏览器输入框右边的叉和眼睛
    angularjs中ckeditor的destroy问题
    angular js ckeditor directive示例代码
    建立没有文件名的文件
    设置ckeditor文本框的宽度为百分比自适应
    js中遍历删除数组中的项(项目中遇到的问题解决)
  • 原文地址:https://www.cnblogs.com/j-1-z-2-s-3/p/13237833.html
Copyright © 2011-2022 走看看