Java中Calendar类的使用

Calendar类是一个抽象类,所以不能使用构造器来创建Calendar对象。但它提供了几个静态getInstance()方法来获取Calendar对象,这些方法根据TimeZone,Locale类来获取特定的Calendar,如果不指定TimeZone,Locale,刚使用默认的TimeZone,Locale来创建Calendar。

public class CalendarTest
{
	public static void main(String[] args)
	{
		Calendar c = Calendar.getInstance();
		// 取出年
		System.out.println(c.get(YEAR));
		// 取出月份
		System.out.println(c.get(MONTH));
		// 取出日
		System.out.println(c.get(DATE));
		// 分别设置年、月、日、小时、分钟、秒
		c.set(2003 , 10 , 23 , 12, 32, 23); //2003-11-23 12:32:23
		System.out.println(c.getTime());
		// 将Calendar的年前推1年
		c.add(YEAR , -1); //2002-11-23 12:32:23
		System.out.println(c.getTime());
		// 将Calendar的月前推8个月
		c.roll(MONTH , -8); //2002-03-23 12:32:23
		System.out.println(c.getTime());


		Calendar cal1 = Calendar.getInstance();
		cal1.set(2003, 7, 23, 0, 0 , 0); // 2003-8-23
		cal1.add(MONTH, 6); //2003-8-23 => 2004-2-23
		System.out.println(cal1.getTime());


		Calendar cal2 = Calendar.getInstance();
		cal2.set(2003, 7, 31, 0, 0 , 0); // 2003-8-31
		// 因为进位到后月份改为2月,2月没有31日,自动变成29日
		cal2.add(MONTH, 6); // 2003-8-31 => 2004-2-29
		System.out.println(cal2.getTime());


		Calendar cal3 = Calendar.getInstance();
		cal3.set(2003, 7, 23, 0, 0 , 0); //2003-8-23
		// MONTH字段“进位”,但YEAR字段并不增加
		cal3.roll(MONTH, 6); //2003-8-23 => 2003-2-23
		System.out.println(cal3.getTime());


		Calendar cal4 = Calendar.getInstance();
		cal4.set(2003, 7, 31, 0, 0 , 0); //2003-8-31
		// MONTH字段“进位”后变成2,2月没有31日,
		// YEAR字段不会改变,2003年2月只有28天
		cal4.roll(MONTH, 6); //2003-8-31 => 2003-2-28
		System.out.println(cal4.getTime());
	}
}

Calendar类中add()与roll()的区别:
add(int field, int amount)主要用于改变Calendar的特定字段的值。如果需要增加某字段的值,则让amout为正数;如果需要减少某字段的值,则让amount为负数即可。
add(int field, int amount)有如下两条规则,当被修改的字段超出它允许的范围时,会发生进位,即上一级字段也会增大。

		Calendar cal1 = Calendar.getInstance();
		cal1.set(2003, 7, 23, 0, 0 , 0); // 2003-8-23
		cal1.add(MONTH, 6); //2003-8-23 => 2004-2-23
如果下一级字段也需要改变,那么该字段会修正到变化最小的值。

		Calendar cal2 = Calendar.getInstance();
		cal2.set(2003, 7, 31, 0, 0 , 0); // 2003-8-31
		// 因为进位到后月份改为2月,2月没有31日,自动变成29日
		cal2.add(MONTH, 6); // 2003-8-31 => 2004-2-29
roll()的规则与add()的处理规则不同:当被修改的字段超出它允许的范围时,上一级字段不会增大。

		Calendar cal3 = Calendar.getInstance();
		cal3.set(2003, 7, 23, 0, 0 , 0); //2003-8-23
		// MONTH字段“进位”,但YEAR字段并不增加
		cal3.roll(MONTH, 6); //2003-8-23 => 2003-2-23
下一级字段的处理规则与add()相似。

		Calendar cal4 = Calendar.getInstance();
		cal4.set(2003, 7, 31, 0, 0 , 0); //2003-8-31
		// MONTH字段“进位”后变成2,2月没有31日,
		// YEAR字段不会改变,2003年2月只有28天
		cal4.roll(MONTH, 6); //2003-8-31 => 2003-2-28

设置Calendar的容错性:

public class LenientTest
{
	public static void main(String[] args)
	{
		Calendar cal = Calendar.getInstance();
		// 结果是YEAR字段加1,MONTH字段为1(二月)
		cal.set(MONTH , 13);   //①
		System.out.println(cal.getTime());
		// 关闭容错性
		cal.setLenient(false);
		// 导致运行时异常
		cal.set(MONTH , 13);   //②
		System.out.println(cal.getTime());
	}
}
set()方法延迟修改。采用延迟修改的优势是多次调用set()不会触发多次不必要的计算。

public class LazyTest
{
	public static void main(String[] args)
	{
		Calendar cal = Calendar.getInstance();
		cal.set(2003 , 7 , 31);  //2003-8-31
		// 将月份设为9,但9月31日不存在。
		// 如果立即修改,系统将会把cal自动调整到10月1日。
		cal.set(MONTH , 8);
		// 下面代码输出10月1日
		//System.out.println(cal.getTime());    //①
		// 设置DATE字段为5
		cal.set(DATE , 5);    //②
		System.out.println(cal.getTime());    //③
	}
}