Java 将XMLGregorianCalendar转换为GregorianCalendar的正确方法
我有两门课。第一个包含日历字段和整数字段(tz偏移量)。第二个包含XmlGregorianCalendar字段。我想比较从第一节课到第二节课的日期Java 将XMLGregorianCalendar转换为GregorianCalendar的正确方法,java,calendar,timezone,timezone-offset,Java,Calendar,Timezone,Timezone Offset,我有两门课。第一个包含日历字段和整数字段(tz偏移量)。第二个包含XmlGregorianCalendar字段。我想比较从第一节课到第二节课的日期 Calendar cal1 = (Calendar) SerializationUtils.clone(firstClass.getDepartureDatetime()); cal1.add(Calendar.MINUTE, -firstClass.getDepartureTzOffset()); GregorianCalendar cal2 =
Calendar cal1 = (Calendar) SerializationUtils.clone(firstClass.getDepartureDatetime());
cal1.add(Calendar.MINUTE, -firstClass.getDepartureTzOffset());
GregorianCalendar cal2 = secondClass.getDepartureDateTime().toGregorianCalendar();
cal2.add(Calendar.MINUTE, -secondClass.getDepartureDateTime().getTimezone());
if (LOGGER.isDebugEnabled()) {
LOGGER.debug(" - Second [" + DateFormat.getDateTimeInstance().format(cal2.getTime()) + "]");
LOGGER.debug(" - First [" + DateFormat.getDateTimeInstance().format(cal1.getTime()) + "]");
}
我在这门课上设定了相同的日期(11月19日,格林尼治标准时间上午9:00+1)
根据系统TZ显示不同的结果(以GMT TZ为单位):
Debian Lenny,TZ是CET:
Second [Nov 19, 2011 7:00:00 AM] - wrong!
First [Nov 19, 2011 8:00:00 AM] -right!
Win7,TZ是GMT+3:
Second [Nov 19, 2011 8:30:00 AM] - wrong!
First [Nov 19, 2011 8:00:00 AM] -right!
我做错了什么
谢谢
更新
一等和二等:
public class FirstClass implements Serializable {
private static final long serialVersionUID = -1150341618306402800L;
private Calendar departureDatetime;
private Integer departureTzOffset;
public Calendar getDepartureDatetime() {
return departureDatetime;
}
public void setDepartureDatetime(Calendar departureDatetime) {
this.departureDatetime = departureDatetime;
}
public Integer getDepartureTzOffset() {
return departureTzOffset;
}
public void setDepartureTzOffset(Integer departureTzOffset) {
this.departureTzOffset = departureTzOffset;
}
}
public class SecondClass implements Serializable
{
private final static long serialVersionUID = 12345L;
protected XMLGregorianCalendar departureDateTime;
public XMLGregorianCalendar getDepartureDateTime() {
return departureDateTime;
}
public void setDepartureDateTime(XMLGregorianCalendar value) {
this.departureDateTime = value;
}
}
SerializationUtils是来自apache commons lang lib的org.apache.commons.lang.SerializationUtils。您应该问自己的第一个问题:我想做什么?转换GregorianCalendar和XMLGregorianCalendar很容易:
GregorianCalendar gc;
XMLGregorianCalendar xc;
gc = xc.toGregorianCalendar();
xc = DatatypeFactory.newInstance().newXMLGregorianCalendar(gc);
但这似乎不是你问题的核心。您正在尝试执行时区转换吗?如果将转换转换转换为显示时间(因为这实际上是一个格式问题),那么可以更轻松地完成这些操作,利用GregorianCalendar和XMLGregorianCalendar都携带时区信息的事实,并去掉这两个帮助器类
TimeZone cet = TimeZone.getTimeZone("CET");
TimeZone utc = TimeZone.getTimeZone("UTC");
GregorianCalendar gc = new GregorianCalendar();
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
@Test
public void testNow() throws DatatypeConfigurationException {
df.setTimeZone(gc.getTimeZone());
log.info(" - Gregorian LOCAL [" + df.format(gc.getTime()) + "]");
df.setTimeZone(cet);
log.info(" - Gregorian CET [" + df.format(gc.getTime()) + "]");
df.setTimeZone(utc);
String gcs = df.format(gc.getTime());
log.info(" - Gregorian UTC [" + df.format(gc.getTime()) + "]");
XMLGregorianCalendar xc = DatatypeFactory.newInstance().newXMLGregorianCalendar(gc);
df.setTimeZone(xc.getTimeZone(0));
log.info(" - XML RAW [" + df.format(xc.toGregorianCalendar().getTime()) + "]");
df.setTimeZone(cet);
log.info(" - XML CET [" + df.format(xc.toGregorianCalendar().getTime()) + "]");
df.setTimeZone(utc);
String xcs = df.format(xc.toGregorianCalendar().getTime());
log.info(" - XML UTC [" + df.format(xc.toGregorianCalendar().getTime()) + "]");
assertEquals(gcs, xcs);
}
或者,您的问题实际上是对输入进行消毒的问题。我看到你有一个出发时间变量,大概是来自世界各地机场的航班,你可能从一些没有明确时区信息的数据源获得它们,而是假设“机场的本地时间”。这可以解释helper类,但是在这种情况下,您应该清理发生输入的地方。确定“机场的当地时间”有时会很棘手(一个国家可能会选择在明年晚些时候从夏令时改为标准时间,或者干脆取消夏令时,一个机场甚至可能在美国切换时区,例如,从东部到中部和从中部到后部的县比你想象的要频繁)。您应该使用计算机的区域设置数据库来解决此问题,并避免尝试滚动您自己的时区算法。当我们调用(日历)SerializationUtils.clone(firstClass.getDepartureDatetime())时,时区有问题。时区设置为服务器TZ,我们在比较过程中损失了几个小时。您能稍微简化一下测试用例吗?取出第一类、第二类和SerializationUtils.clone