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对象之间的转换。