从字符串返回d-1值的SOAP Web Service解析日期 [英] SOAP Web Service parsing Date from String returning d-1 value
问题描述
我正在使用 org.apache.cxf.xjc.runtime.DataTypeAdapter.parseDate(StringDate)
将输入的字符串日期从XML解析为JAVA日期.但是我有一个Date对象的第1天的值.
I'm using org.apache.cxf.xjc.runtime.DataTypeAdapter.parseDate(StringDate)
to parse the input string date from XML to JAVA date. But i got a Date objects with day-1 value.
例如
<birth>1939-11-19+01:00</birth>
我想忽略偏移量.我只想要日期,所以无论偏移量是多少,我都应该得到
I want to ignore the offset. I want only the date, so no matter what the offset is, I should get
Sun Nov 19 00:00:00 CET 1939
但是我得到了:
Sat Nov 18 23:00:00 CET 1939
问题出在日期的时间偏移级别.我试图通过忽略时间偏移来修复它,但这没有用.我正在使用Java 6(约束项目).有什么想法吗?
The issue is at the level of date's time offset. I tried to fix it with ignoring the time offset but that didn't work. I'm using java 6 (constraint project). Any ideas?
我以最小,完整和可验证的示例为例:
My best attempt at a minimal, complete and verifiable example:
public static Date parse(final String str) {
Calendar c = DatatypeConverter.parseDateTime(str);
System.out.println(str + "\t" + c.getTime().getTime() / 1000);
return c.getTime();
}
推荐答案
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,要好用得多.所以我的第一个建议是你在这里停止.
A java.time.LocalDate
is a date without time-of-day, so this matches your requirements exactly. At the same time java.util.Date
and friends are long outdated and have proven poorly designed. java.time
, the modern Java date and time API, is so much nicer to work with. So my first recommendation is you stop here.
例如,如果确实需要 Date
,例如对于旧版API,请首先意识到,尽管名称不代表日期.它代表一个时间点,在那个时间点,日期在任何地方都不会相同.如您所知,这可能引起了您的问题: parseDate
和 parseDateTime
将字符串解析为相关日期的UTC指定偏移量的00:00.此时,日期可能与您所在的时区不同,因此,当您打印 Date
时,您会得到,从而调用其 toString
方法,您可能会得到一个不同的日期.我们了解到,您希望改为在自己的时区中将时间设为0:00(CET,可能是中欧时间,反过来又是几个不同时区的名称,这些时区在1939年的那个日期可能会偏移0或+01;您观察到的结果在欧洲/巴黎,非洲/休达,欧洲/安道尔,欧洲/马德里和欧洲/摩纳哥等时区都是有意义的,所有时区均为偏移量0).转换:
If you do need a Date
, for example for a legacy API, first realize that despite the name it does not represent a date. It represents a point in time, and at that point in time the date will not be the same everywhere. This probably caused your problem, as you are aware: parseDate
and parseDateTime
parse your string into 00:00 at the specified offset from UTC on the date in question. At this point in time, the date may not be the same in your time zone, so when you print the Date
you get, thereby invoking its toString
method, you may get a different date. I understand that you want the time at 0:00 in your own time zone instead (CET, probably Central European Time, in turn a name of several different time zones that may be at offsets 0 or +01 on that date in 1939; the result you observed would make sense in time zones Europe/Paris, Africa/Ceuta, Europe/Andorra, Europe/Madrid and Europe/Monaco, all of which were at offset 0). To convert:
Date oldfashionedDateObject
= Date.from(date.atStartOfDay(ZoneId.systemDefault()).toInstant());
System.out.println(oldfashionedDateObject);
已打印
Sun Nov 19 00:00:00 CET 1939
我将时区设置为America/New_York和Europe/Moscow进行了测试,并且总是得到 Sun Nov 19 00:00:00
,仅在不同时区 EST
和 MSK
.
I tested with my time zone set to America/New_York and to Europe/Moscow, and always got Sun Nov 19 00:00:00
, only in different time zones, EST
and MSK
.
我知道您必须使用Java6. java.time
在ThreeTen Backport中已经被反向移植到Java 6和7.因此,请从底部的链接中获取此代码并将其添加到您的项目中,上面的代码将起作用,只是转换发生了一些不同:
I understand that you have to use Java 6. java.time
has been backported to Java 6 and 7 in the ThreeTen Backport. So get this from the link at the bottom and add it to your project, and the above code will work except the conversion happens a little differently:
Date oldfashionedDateObject
= DateTimeUtils.toDate(date.atStartOfDay(ZoneId.systemDefault()).toInstant());
您无需使用ThreeTen Backport来重写所有代码,尤其是当某些地方您不信任现代API来实现所需的行为时,尤其如此.上面的代码片段可以与您已有的代码很好地共存.
You don’t need to rewrite all of your code to use the ThreeTen Backport, and especially not if there are parts where you don’t trust the modern API to behave the way you want. The above snippet can coexist nicely with the code you already have.
如果您真的坚持,那么我可以使用 DatatypeConverter
和 Calendar
来获取所需的 Date
的方式:
If you really insist, the way I could find to get the Date
you want using DatatypeConverter
and 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的方式进行了测试.
We can’t just change the offset or time zone of the Calendar
we got from parsing since this will not change its point in time and therefore not the Date
object we get. Instead we need to set a different Calendar
object to the year, month and day-of-month of the first Calendar
. The call to clear()
sets hours, minutes, seconds and milliseconds to 0. This snippet too has been tested with my JVM’s time zone set to America/New_York and to Europe/Moscow.
- Oracle教程:日期时间解释了如何使用
java.时间
. - Java规范请求(JSR)310 ,其中
java首先描述了.time
. - ThreeTen Backport项目,即
java.time
的反向端口Java 6和7(JSR-310的ThreeTen). - ThreeTenABP ,ThreeTen Backport的Android版本
- 问题:如何在Android Project中使用ThreeTenABP ,非常详尽的解释.
- Oracle tutorial: Date Time explaining how to use
java.time
. - Java Specification Request (JSR) 310, where
java.time
was first described. - ThreeTen Backport project, the backport of
java.time
to Java 6 and 7 (ThreeTen for JSR-310). - ThreeTenABP, Android edition of ThreeTen Backport
- Question: How to use ThreeTenABP in Android Project, with a very thorough explanation.
这篇关于从字符串返回d-1值的SOAP Web Service解析日期的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!