SOAP Web服务从String返回d-1值解析Date

时间:2018-02-07 10:03:16

标签: xml date timezone cxf java-6

我正在使用org.apache.cxf.xjc.runtime.DataTypeAdapter.parseDate(StringDate)来解析从XML到JAVA日期的输入字符串日期。但是我得到了具有第1天值的Date对象。

例如

<birth>1939-11-19+01:00</birth>

我想忽略偏移量。我只想要日期,所以不管偏移是什么,我都应该

Sun Nov 19 00:00:00 CET 1939

但我确实得到了:

Sat Nov 18 23:00:00 CET 1939

问题出在日期时间偏移的水平上。我试图通过忽略时间偏移来修复它,但这不起作用。我正在使用java 6(约束项目)。有什么想法吗?

我最好尝试一个最小,完整和可验证的例子:

public static Date parse(final String str) {
    Calendar c = DatatypeConverter.parseDateTime(str);
    System.out.println(str + "\t" + c.getTime().getTime() / 1000);
    return c.getTime();
}

1 个答案:

答案 0 :(得分:1)

java.time

    String birth = "1939-11-19+01:00";
    LocalDate date = LocalDate.parse(birth, DateTimeFormatter.ISO_OFFSET_DATE);
    System.out.println(date);

打印

1939-11-19

java.time.LocalDate是没有时间的日期,因此这完全符合您的要求。与此同时java.util.Date和朋友们已经过时了,而且设计得很差。 java.time,现代Java日期和时间API,使用起来非常好。所以我的第一个建议是你到此为止。

如果确实需要Date,例如遗留API,请首先意识到尽管名称不代表日期。它代表一个时间点,在那个时间点,日期在各地都不一样。正如您所知,这可能会导致您的问题:parseDateparseDateTime将您的字符串解析为00:00,在指定的日期与UTC相关的偏移量。此时,您的时区中的日期可能不同,因此当您打印所获得的Date,从而调用其toString方法时,您可能会得到不同的日期。我知道你想要在你自己的时区0:00的时间(CET,可能是中欧时间,反过来是1939年那个日期可能在0或+01偏移的几个不同时区的名称;你所观察到的结果在时区欧洲/巴黎,非洲/休达,欧洲/安道尔,欧洲/马德里和欧洲/摩纳哥都有意义,所有这些都是0。转换:

    Date oldfashionedDateObject 
            = Date.from(date.atStartOfDay(ZoneId.systemDefault()).toInstant());
    System.out.println(oldfashionedDateObject);

此印刷

Sun Nov 19 00:00:00 CET 1939

我测试了我的时区设置为America / New_York和欧洲/莫斯科,并且总是得到Sun Nov 19 00:00:00,仅在不同的时区,ESTMSK

Java 6和ThreeTen Backport

我知道您必须使用Java 6. java.time已被移植到ThreeTen Backport中的Java 6和7。所以从底部的链接获取并将其添加到您的项目中,上述代码将起作用,但转换的发生方式略有不同:

    Date oldfashionedDateObject
            = DateTimeUtils.toDate(date.atStartOfDay(ZoneId.systemDefault()).toInstant());

您无需重写所有代码即可使用ThreeTen Backport,特别是如果有些部分您不相信现代API可以按照您的方式运行。上面的代码段可以很好地与您已有的代码共存。

非常老式的方式

如果您真的坚持,我可以找到使用DateDatatypeConverter获取Calendar的方式:

    Calendar calWithParsedOffset = DatatypeConverter.parseDate(birth);
    Calendar calWithMyTimeZone = Calendar.getInstance(TimeZone.getDefault());
    calWithMyTimeZone.clear();
    calWithMyTimeZone.set(calWithParsedOffset.get(Calendar.YEAR),
            calWithParsedOffset.get(Calendar.MONTH),
            calWithParsedOffset.get(Calendar.DAY_OF_MONTH));
    Date oldfashionedDateObject = calWithMyTimeZone.getTime();
    System.out.println(oldfashionedDateObject);

我们不能只改变我们从解析中得到的Calendar的偏移量或时区,因为这不会改变它的时间点,因此不会改变我们得到的Date对象。相反,我们需要将不同的Calendar对象设置为第一个Calendar的年,月和日。对clear()的调用将小时,分钟,秒和毫秒设置为0.此片段也已经过测试,我的JVM时区设置为America / New_York和Europe / Moscow。

链接