您的位置:首页 > 编程语言 > Java开发

Java: 日期相关的类 XMLGregorianCalendar 和 GregorianCalendar

2013-11-23 19:00 906 查看
在 Web 开发中经常需要操纵 Web Service 的响应的信息,其中可能包含日期信息。如果开发是基于 Java 的,通常可以通过返回 XMLGregorianCalendar 类的一个对象来表示一个时间,该对象封装了一个具体时间的年、月、日、时、分、秒及时区(Time Zone)信息。我们假设通过以下语句获取了一个 XMLGregorianCalendar 对象:

// 假设函数 func() 返回一个 XMLGregorianCalendar 对象
XMLGregorianCalendar xcStartTime = func ();


如果在业务上需要将该时间和系统当前时间做比较,由于 XMLGregorianCalendar 类同 GregorianCalendar 类有方便的接口进行转换,我们通常可以创建一个 GregorianCalendar 的对象以捕捉当前系统时间。如下:

// 创建一个 GregorianCalendar 对象表示系统当前时间
GregorianCalendar gcCurrTime = new GregorianCalendar ();

现在的问题是:如何比较这两个时间对象(xcStartTime 和 gcCurrTime)的先后关系呢?

方法一、 

熟悉接口的程序员可以先调用 XMLGregorianCalendar 类的 toGregorianCalendar 方法,将 XMLGregorianCalendar 类的对象转化为 GregorianCalendar 的对象;

// 将 XMLGregoriancalendar 类的对象转为 GregorianCalendar 类的对象。
GregorianCalendar gcStartTime = xcStartTime.toGregorianCalendar ();

然后基于 GregorianCalendar 类的接口来比较两个 GregorianCalendar  对象:

最简单的方式:

// 使用 before 或 after 接口
if (gcStartTime.before (gcCurrTime)){
// TODO:
}
else{
// TODO:
}

方法二、

可以转为整数表示的毫秒,然后比较;

//先获取时间对象的毫秒值(从1970年1月1日00:00起始的 UTC 时间开始计数的毫秒数)
long lnStartTime = gcStartTime.getTimeInMillis ();
long lnCurrtTime = gcStartTime.getTimeInMillis ();
//然后比较这两个整数
if (lnStartTime > lnCurrtTime){
// TODO:
}
else{
// TODO:
}

方法三、

上面的方法可以直接通过一个函数 compareTo 来实现:该函数比较两个 GregorianCalendar 对象的从1970年1月1日UTC时间00:00起始的毫秒数,如果相等,返回 0;否则,返回负数或正数。

int ret = gcCurrTime.compareTo (gcStartTime);
if (ret == 0){
// TODO:
}
if (ret < 0){
// TODO:
}
if (ret > 0){
// TODO:
}

方法四、

人工转换需要注意的问题。有如下代码:

import java.util.Date;
import java.util.GregorianCalendar;

import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;

public class A {
public static void main(String[] args) throws Exception {
// 创建一个 XMLGregorianCalendar 对象表示 1999年1月31日18时30分59秒999毫秒,时区信息为0的时间
XMLGregorianCalendar xt = DatatypeFactory.newInstance().newXMLGregorianCalendar(1999, 1, 31, 18, 30, 59, 999, 0);

// 创建一个 GregorianCalendar 对象,依次取出上述对象的信息填入其中
GregorianCalendar gt = new GregorianCalendar(xt.getYear(),
xt.getMonth(),
xt.getDay(),
xt.getHour(),
xt.getMinute(),
xt.getSecond());
// 返回 GregorianCalendar 类对象 gt 的一个 Date 对象,以方便打印
Date date = gt.getTime();
System.out.println(xt);
System.out.println(date);
}
}

编译运行结果如下:

1999-01-31T18:30:59.999Z
Wed Mar 03 18:30:59 CST 1999

上述结果分别是1月31日和3月3日,注意到月份信息和日期信息均是不正确的。

考察了一下这两个类,首先是 XMLGregorianCalendar:



然后 GregorianCalendar

public GregorianCalendar(int year,
int month,
int dayOfMonth,
int hourOfDay,
int minute,
int second)

为具有默认语言环境的默认时区构造一个具有给定日期和时间设置的 GregorianCalendar。

参数:
year
- 用来在日历中设置
YEAR
日历字段的值。
month
- 用来在日历中设置
MONTH
日历字段的值。Month 值是基于 0 的,例如,0 表示 1 月。
dayOfMonth
- 用来在日历中设置
DAY_OF_MONTH
日历字段的值。
hourOfDay
- 用来在日历中设置
HOUR_OF_DAY
日历字段的值。
minute
- 用来在日历中设置
MINUTE
日历字段的值。
second
- 用来在日历中设置
SECOND
日历字段的值。从上面的文档可以看出。这两个类对月份信息的处理是不一样的:XMLGregorianCalendar 使用1~12表示月份,而 GregorianCalendar 使用0~11表示月份,所以从 XMLGregorianCalendar 到 GregorianCalendar 的转换,需要将月份数值减去1。

有如下的程序:

import java.util.Date;
import java.util.GregorianCalendar;

import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;

public class A {
public static void main(String[] args) throws Exception {
// 创建一个 XMLGregorianCalendar 对象表示 1999年1月31日18时30分59秒999毫秒,时区信息为0的时间
XMLGregorianCalendar xt = DatatypeFactory.newInstance().newXMLGregorianCalendar(1999, 1, 31, 18, 30, 59, 999, 0);

// 创建一个 GregorianCalendar 对象,依次取出上述对象的信息填入其中
GregorianCalendar gt = new GregorianCalendar(xt.getYear(),
xt.getMonth() - 1,
xt.getDay(),
xt.getHour(),
xt.getMinute(),
xt.getSecond());
// 返回 GregorianCalendar 类对象 gt 的一个 Date 对象,以方便打印
Date date = gt.getTime();
System.out.println(xt);
System.out.println(date);
}
}


编译运行结果为:

1999-01-31T18:30:59.999Z
Sun Jan 31 18:30:59 CST 1999

可以看出,结果已经是正确的。

延伸:

GregorianCalendar 类可以通过 getTime () 返回一个 Date 对象, Date 类也提供了诸如 boolean before ()、boolean after ()、 int compareTo ()、long getTime() 等方法用于比较时间。

注意:

Date 类的月份信息也是由 0~11 表示的。以下来自JavaSE6的中文API:



最后:

JDK的日期和时间信息尽量使用 Calendar 类,该类提供了更丰富的接口,GregorianCalendar 类的上述方法都是继承该类的(当然其中的月份也是使用0表示每年的一月)。使用该类可以方便地比较时间。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: