3

我有2节课。首先包含日历字段和整数字段(tz 偏移)。第二个包含 XmlGregorianCalendar 字段。我想比较第一堂课的日期和第二堂课的日期。

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 日,格林威治标准时间 +1 上午 9:00)。

根据系统 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!

我做错了什么?

谢谢。

更新

1级和2级:

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。

4

2 回答 2

1

当我们调用 (Calendar) SerializationUtils.clone(firstClass.getDepartureDatetime()) 时,时区有问题。时区设置为服务器 TZ,我们在比较过程中损失了几个小时。

于 2011-11-18T15:56:28.117 回答
0

你应该问自己的第一个问题:我想做什么?转换 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);
}

或者,也许您的问题实际上是清理输入的问题。我看到你有一个离开时间变量,大概是来自世界各地机场的航班,你可能从一些没有明确时区信息的数据源中获取它们,而是假设“机场当地时间”。这将解释帮助程序类,但在这种情况下,您应该在发生输入的地方清理输入。确定“机场当地时间”有时可能很棘手(例如,一个国家可能会选择在明年一周后从夏令时切换到标准时间,或者完全取消 DST,机场甚至可能会切换美国的时区,从东部到中部并返回的县发生的频率比你想象的要频繁)。您应该使用计算机的区域设置数据库来解决这个问题,

于 2011-11-17T15:07:11.743 回答