将 XMLGregorianCalendar 转换为 GregorianCalendar 的正确方法

发布于 2024-12-16 23:13:49 字数 2245 浏览 0 评论 0原文

我有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 日上午 9:00 GMT+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。

I have 2 classes. First contains Calendar field and Integer field (tz offset). Second contains XmlGregorianCalendar field. I want to compare date from firs class to date from second.

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()) + "]");
}

I've set equal dates (Nov 19, 9:00 AM GMT+1) in that classes.

Depending on the system TZ it shows different results (in GMT TZ):

Debian Lenny, TZ is CET:

Second  [Nov 19, 2011 7:00:00 AM] - wrong!
First [Nov 19, 2011 8:00:00 AM] -right!

Win7, TZ is GMT+3:

Second  [Nov 19, 2011 8:30:00 AM] - wrong!
First [Nov 19, 2011 8:00:00 AM] -right!

What I'm doing wrong?

Thanks.

UPDATE

1st and 2nd classes:

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 is an org.apache.commons.lang.SerializationUtils from Apache commons-lang lib.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

谢绝鈎搭 2024-12-23 23:13:49

当我们调用(日历)SerializationUtils.clone(firstClass.getDepartureDatetime())时,时区出现问题。时区设置为服务器 TZ,我们在比较过程中损失了一些小时。

It was a problem with Timezone when we call (Calendar) SerializationUtils.clone(firstClass.getDepartureDatetime()). Timezone was set to the server TZ and we lost some hours during comparing.

倚栏听风 2024-12-23 23:13:49

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

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

The first question you should ask yourself: What am i trying to do? Converting GregorianCalendar and XMLGregorianCalendar is easy:

GregorianCalendar gc;
XMLGregorianCalendar xc;
gc = xc.toGregorianCalendar();
xc = DatatypeFactory.newInstance().newXMLGregorianCalendar(gc);

But that doesn't seem to be the core of your problem. Are you trying to perform time zone conversions? IMHO thes can be done more easily if you shift the conversion to the display time (since it's really a formatting issue), make use of the fact that both GregorianCalendar and XMLGregorianCalendar carry their time zone information with them and get rid of the two helper classes.

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);
}

Or maybe your problem is really an issue of sanitizing the input. I see you have a departureTime variable, presumably for flights from airports around the world, and you probably get them from some data source that has no explicit time zone information, and instead assumes "local time at the airport". That would explain the helper classes, but in that case, you should sanitize your input where it happens. Determining "local time at the airport" can be tricky at times (a country might choose to switch from daylight saving time to standard a week later next year, or abolish DST altogether, and an airport might even switch timezones in the US, for example, counties moving from eastern to central and back happens more frequently than you'd think). You should use your computer's Locale database to resolve that, and avoid trying to roll your own timezone arithmetic.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文