1、简介
Calendar是专注于日期处理的抽象类,在Java.util.Calendar包中,Calendar在开发中是经常使用的类。
2、方法API
-
实例化对象
使用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小时。
-
获取值
//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开始的,所以需要加一。
-
设置值
//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开始,所以也需要加一。
-
运算值
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);//周
-
如何判断时间相等
//法一:分别比较年、月、日 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对象,不过这样是判断两个对象是否相等,实际意义不大。
-
判断时间前后
Calendar now = Calendar.getInstance(); Calendar after = Calendar.getInstance(); System.out.println(now.after(after)); System.out.println(now.before(after)); ------------------------------------------ 结果为:false true
-
其余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()方法中就调了这个方法 -
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、运用
- 计算两个日期间相差的月数
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;
}
这里的clone返回的对象,其实还是now引用指向的对象,所以我们自己新建引用nowClone,然后将now引用的地址赋值给nowClone也能达到一样的效果。经测试
clone.equals(now)
返回true。 ↩︎System.out.println(now.getActualMaximum(Calendar.DATE));因为当前Calendar是2020-02-25,它就会返回二月最大的日,也就是29号。 ↩︎
System.out.println(now.getMaximum(Calendar.DATE));当前时间是2020-02-25,虽然今年二月份最大是29,但它返回了31,所以它返回的是月份能够达到的最大日期。 ↩︎
看底层它也是得到当前时间的毫秒数,然后new了一个Date:new Date(getTimeInMillis()) ↩︎