学科分类
目录
Java基础

Calendar类

Calendar类用于完成日期和时间字段的操作,它可以通过特定的方法设置和读取日期的特定部分,比如年、月、日、时、分和秒等。Calendar类是一个抽象类,不可以被实例化,在程序中需要调用其静态方法getInstance()来得到一个Calendar对象,然后才能调用其相应的方法,具体示例如下:

Calendar calendar = Calendar.getInstance();

Calendar类为操作日期和时间提供了大量的方法,下面列举一些常用的方法,如表1所示。

表1 Calendar的常用方法

方法声明 功能描述
int get(int field) 返回指定日历字段的值
void add(int field,int amount) 根据日历规则,为指定的日历字段增加或减去指定的时间量
void set(int field,int value) 为指定日历字段设置指定值
void set(int year,int month,int date) 设置Calendar对象的年、月、日三个字段的值
void set(int year.int month,int date,int hourOfDay,int minute,int second) 设置Calendar对象的年、月、日、时、分、秒六个字段的值

表1中,大多数方法都用到了int类型的参数field,该参数需要接收Calendar类中定义的常量值,这些常量值分别表示不同的字段,如Calendar.YEAR用于表示年份,Calendar.MONTH用于表示月份,Calendar.SECOND用于表示秒等。尤其要注意的是,在使用Calendar.MONTH字段时,月份的起始值是从0开始的,而不是从1开始,因此要获取当前的月份需要在Calendar.MONTH的基础上加1。

接下来通过一个案例来学习下Calender类如何获取当前计算机的日期和时间,如文件1所示。

文件1 Example20.java

 1    import java.util.*;
 2    public class Example20 {
 3        public static void main(String[] args) {
 4             // 获取表示当前时间的Calendar对象
 5            Calendar calendar = Calendar.getInstance();
 6            int year = calendar.get(Calendar.YEAR);        // 获取当前年份
 7            int month = calendar.get(Calendar.MONTH) + 1; // 获取当前月份
 8            int date = calendar.get(Calendar.DATE);        // 获取当前日
 9            int hour = calendar.get(Calendar.HOUR);        // 获取时
 10            int minute = calendar.get(Calendar.MINUTE);   // 获取分
 11            int second = calendar.get(Calendar.SECOND);   // 获取秒
 12            System.out.println("当前时间为:" + year + "年 " + month + "月 " 
 13                + date + "日 "+ hour + "时 " + minute + "分 " + second + "秒");
 14        }
 15    }

运行结果如图1所示。

图1 运行结果

在文件1中,调用Calendar的getInstance()方法创建了一个代表默认时区内当前时间的Calendar对象,然后调用该对象的get(int field)方法,通过传入不同的常量字段值来分别得到日期、时间各个字段的值。

在程序中除了要获得当前计算机的时间外,还会经常设置或修改某个时间,比如一项工程的开始时间为2018年的1月1日,假设要100天后竣工,此时要想知道竣工日期是哪天就需要先将日期设定在开始的那天,然后对日期的天数进行增加,如果没有按照预期完成,可能还需要对日期进行修改。其中添加和修改时间的功能就可以通过Calendar类中的add()和set()方法来实现。

接下来就通过案例来实现上述例子,如文件2所示。

文件2 Example21.java

 1    import java.util.*;
 2    public class Example21 {
 3        public static void main(String[] args) {
 4            // 获取表示当前时间的Calendar对象
 5            Calendar calendar = Calendar.getInstance();
 6            // 设置指定日期
 7            calendar.set(2018, 1, 1);
 8            // 为指定日期增加时间
 9            calendar.add(Calendar.DATE, 100);
 10            // 返回指定日期的年
 11            int year = calendar.get(Calendar.YEAR);
 12            // 返回指定日期的月
 13            int month = calendar.get(Calendar.MONTH) + 1;
 14            // 返回指定日期的日
 15            int date = calendar.get(Calendar.DATE);
 16            System.out.println("计划竣工日期为:" + year + "年" 
 17                                   + month + "月" + date + "日");
 18        }
 19    }

运行结果如图2所示。

图2 运行结果

文件2的代码中调用Calendar的set()方法将日期设置为2018年1月1号,然后调用add()方法在Calendar.Date字段上增加100,从图5-21可以看出,增加100天的日期为2018年5月12日。

需要注意的是,Calendar.Date表示的是天数,当天数累加到当月的最大值时,如果继续再累加一次,就会从1开始计数,同时月份值会加1,这和算术运算中的进位有点类似。

多学一招:Calendar日历容错模式与非容错模式

Calendar有两种解释日历字段的模式——lenient模式(容错模式)和non-lenient模式(非容错模式)。当Calendar处于lenient模式时,它的字段可以接收超过允许范围的值,当调用get(int field)方法获取某个字段值时,Calendar会重新计算所有字段的值,将字段的值标准化。换句话说,就是在lenient模式下,允许出现一些数值上的错误,例如月份只有12个月,取值为0到11,但在这种模式下,月份值指定为13也是可以的。当Calendar处于non-lenient模式时,如果某个字段的值超出了它允许的范围,程序将会抛出异常。接下来通过一个案例来演示这种异常情况,如文件3所示。

文件3 Example22.java

 1    import java.util.*;
 2    public class Example22 {
 3        public static void main(String[] args) {
 4            // 获取表示当前时间的Calendar对象
 5            Calendar calendar = Calendar.getInstance();
 6            // 设置指定日期,将MONTH设为13
 7            calendar.set(Calendar.MONTH, 13);
 8            System.out.println(calendar.getTime());
 9            // 开启non-lenient模式
 10            calendar.setLenient(false);
 11            calendar.set(Calendar.MONTH, 13);
 12            System.out.println(calendar.getTime());
 13        }
 14    }

运行结果如图3所示。

图3 运行结果

从图3可以看出,文件3中的第一个输出语句可以正常地输出时间值,而第二个输出语句在输出时间值时报错。出现这样现象的原因在于,Calendar类默认使用lenient模式,当调用Calendar的set()方法将MONTH字段设置为13时,会发生进位,YEAR字段加1,然后MONTH字段变为1,第一个输出语句打印出的结果是“Feb 27”(2月27日)。当代码调用Calendar的setLenient(false)方法开启non-lenient模式后,同样地设置MONTH字段为13,会因为超出了MONTH字段0~11的范围而抛出异常。

本例中用到了Calendar的getTime()方法,getTime()方法会返回一个表示Calendar时间值的Date对象,同时Calendar有一个setTime(Date date)方法,setTime()方法接收一个Date对象,将Date对象表示的时间值设置给Calendar对象,通过这两个方法就可以完成Date和Calendar对象之间的转换。

点击此处
隐藏目录