Java日期时间处理御用类——Calendar

1、简介

Calendar是专注于日期处理的抽象类,在Java.util.Calendar包中,Calendar在开发中是经常使用的类。

2、方法API
  1. 实例化对象

    使用Calendar.getInstance();可实例化出Calendar的对象,其返回的是当前时间。所以如果有初始化的需求,我们需要set一下对象的值,

    Calendar now = Calendar.getInstance();
    now.setTimeInMillis(0);
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    System.out.println(sdf.format(now.getTime()));
    ----------------------------------------------------------------
    //输出为:1970-01-01,这是格林威治标准时间,也就是1970 年 1 月 1 日的 00:00:00.000,所以Calander中其实是这个标准时间的偏移量。
    

    ps:格林威治标准时间比北京时间慢8小时。

  2. 获取值
    //Calendar使用filed的方式获取和设置时间
    now.get(Calendar.YEAR);//年 
    now.get(Calendar.MONTH) + 1;//月(必须要+1) 
    now.get(Calendar.DATE);//日 
    now.get(Calendar.HOUR_OF_DAY);//时 
    now.get(Calendar.MINUTE);//分 
    now.get(Calendar.SECOND);//秒 
    now.get(Calendar.DAY_OF_WEEK);//星期(Locale.ENGLISH情况下,周日是1,剩下自己推算)
    --------------------------------------------------------------------
    //注意:以上方法返回的都是int值,该int值在Calendar中是一个静态常量,如:
        /**
         * Value of the {@link #DAY_OF_WEEK} field indicating
         * Tuesday.
         */
        public final static int TUESDAY = 3;
    //而Calander的月份是从0开始的,所以需要加一。
    
  3. 设置值
    //Calendar可一次性直接set年、月、日、时、分、秒,十分方便
    now.set(2013, 5, 4, 13, 44, 51);//年月日时分秒(月份0代表1月) 
    now.set(Calendar.YEAR, 2014);//年 
    now.set(Calendar.MONTH, 7);//月(月份0代表1月) 
    now.set(Calendar.DATE, 11);//日 
    now.set(Calendar.HOUR_OF_DAY, 15);//时 
    now.set(Calendar.MINUTE, 33);//分 
    now.set(Calendar.SECOND, 32);//秒
    now.get(Calendar.DAY_OF_WEEK); //星期
    

    ps:Calendar的周是从周日开始,和中国的习惯不一样,所以要加一。其月份下标是从0开始,所以也需要加一。

  4. 运算值
    now.add(Calendar.YEAR, 1);//年 
    now.add(Calendar.MONTH, 1);//月 
    now.add(Calendar.DATE, 1);//日 
    now.add(Calendar.HOUR_OF_DAY, -1);//时 
    now.add(Calendar.MINUTE, 1);//分 
    now.add(Calendar.SECOND, 1);//秒 
    now.add(Calendar.DATE, 7);//周
    
  5. 如何判断时间相等

    //法一:分别比较年、月、日
    Calendar now = Calendar.getInstance();
    Calendar after = Calendar.getInstance();
    System.out.println(now.get(Calendar.YEAR) == after.get(Calendar.YEAR));
    System.out
                .println(now.get(Calendar.MONTH) == after.get(Calendar.MONTH));
    System.out.println(
        now.get(Calendar.DAY_OF_MONTH) == after.get(Calendar.DAY_OF_MONTH));
    //法二:将时间转换为String类型,使用equals判断
    Calendar now = Calendar.getInstance();
    Calendar after = Calendar.getInstance();
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    String nowTime = sdf.format(now.getTime());
    String afterTime = sdf.format(after.getTime());
    System.out.println(nowTime.equals(afterTime));
    

    ps:其实也可以直接使用equals判断Calendar对象,不过这样是判断两个对象是否相等,实际意义不大。

  6. 判断时间前后
    Calendar now = Calendar.getInstance();
    Calendar after = Calendar.getInstance();
    System.out.println(now.after(after));
    System.out.println(now.before(after));
    ------------------------------------------
    结果为:false	true
    
  7. 其余API
    方法作用
    public final void clear()清空当前时间值,当然也可使用setTimeInMillis(0)方法主动清零,效果一样。
    Object clone()创建当前对象的副本,返回的是object,需要强转。1
    int getActualMaximum(int field)返回field域实际包含的最大值2
    int getActualMinimum(int field)返回field域实际包含的最小值
    int getMaximum(int field)返回field域可以包含的最大值3
    int getMinimum(int field)返回field域可以包含的最小值
    Date getTime()返回当前calendar的Date类型值4
    long getTimeInMillis()返回当前calendar的毫秒数,getTime()方法中就调了这个方法
  8. Roll和Add的区别

    add方法:

    //当前时间是2020-02-25
    Calendar now = Calendar.getInstance();
    //将月份设置为12月(Calendar的月份从0开始)
    now.set(Calendar.MONTH,11);
    now.add(Calendar.MONTH,2);
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    System.out.println(sdf.format(now.getTime()));
    -------------------------------------------------
    //输出为:2021-02-25
    

    roll方法:

    //当前时间是2020-02-25
    Calendar now = Calendar.getInstance();
    //将月份设置为12月(Calendar的月份从0开始)
    now.set(Calendar.MONTH,11);
    now.roll(Calendar.MONTH,2);
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    System.out.println(sdf.format(now.getTime()));
    -------------------------------------------------
    //输出为:2020-02-25
    

    总结:Calendar的add会产生日期的影响(所有域联动),而roll仅影响当前的filed,并不影响其它域。

    重点:经测试发现roll是对当前域进行反复加减操作,如当前日期是2020-02-25,这一年为闰年,所以二月有29天,如执行now.roll(Calendar.DATE,34);效果为2020-02-01。下面分步讲解:

    1、2020-02-25加上4天为29号

    2、2020-02-29加上1为1号

    3、2020-02-01加上29还是1号,因为今年(闰年)二月周期为29天

    所以roll是对当前所在域进行循环操作,可以想象成钟表的循环。

    而add则是对当前日期直接加减,如:执行now.add(Calendar.DATE,34);输出为2020-03-30。

    now的日期为:2020-02-25

3、运用
  1. 计算两个日期间相差的月数
public static int getMonthDiff(Date startDate, Date endDate) {
    Calendar c1 = Calendar.getInstance();
    Calendar c2 = Calendar.getInstance();
    c1.setTime(endDate);
    c2.setTime(startDate);
    if (c1.getTimeInMillis() < c2.getTimeInMillis())
        return 0;
    int year1 = c1.get(Calendar.YEAR);
    int year2 = c2.get(Calendar.YEAR);
    int month1 = c1.get(Calendar.MONTH);
    int month2 = c2.get(Calendar.MONTH);
    int day1 = c1.get(Calendar.DAY_OF_MONTH);
    int day2 = c2.get(Calendar.DAY_OF_MONTH);
    // 获取年的差值 假设 d1 = 2015-8-16 d2 = 2011-9-30
    int yearInterval = year1 - year2;
    // 如果 d1的 月-日 小于 d2的 月-日 那么 yearInterval-- 这样就得到了相差的年数
    if (month1 < month2 || month1 == month2 && day1 < day2)
        yearInterval--;
    // 获取月数差值
    int monthInterval = (month1 + 12) - month2;
    if (day1 < day2)
        monthInterval--;
    monthInterval %= 12;
    return yearInterval * 12 + monthInterval;
}

  1. 这里的clone返回的对象,其实还是now引用指向的对象,所以我们自己新建引用nowClone,然后将now引用的地址赋值给nowClone也能达到一样的效果。经测试clone.equals(now)返回true。 ↩︎

  2. System.out.println(now.getActualMaximum(Calendar.DATE));因为当前Calendar是2020-02-25,它就会返回二月最大的日,也就是29号。 ↩︎

  3. System.out.println(now.getMaximum(Calendar.DATE));当前时间是2020-02-25,虽然今年二月份最大是29,但它返回了31,所以它返回的是月份能够达到的最大日期。 ↩︎

  4. 看底层它也是得到当前时间的毫秒数,然后new了一个Date:new Date(getTimeInMillis()) ↩︎

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值