java.util.Date 到 XMLGregorianCalendar
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/835889/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
java.util.Date to XMLGregorianCalendar
提问by mac
Isn't there a convenient way of getting from a java.util.Date to a XMLGregorianCalendar?
没有从 java.util.Date 到 XMLGregorianCalendar 的便捷方法吗?
采纳答案by Ole V.V.
I should like to take a step back and a modern look at this 10 years old question. The classes mentioned, Date
and XMLGregorianCalendar
, are old now. I challenge the use of them and offer alternatives.
我想退后一步,用现代的眼光看待这个 10 年前的问题。提到的类Date
和XMLGregorianCalendar
,现在已经过时了。我挑战它们的使用并提供替代方案。
Date
was always poorly designed and is more than 20 years old. This is simple: don't use it.XMLGregorianCalendar
is old too and has an old-fashioned design. As I understand it, it was used for producing dates and times in XML format for XML documents. Like2009-05-07T19:05:45.678+02:00
or2009-05-07T17:05:45.678Z
. These formats agree well enough with ISO 8601 that the classes of java.time, the modern Java date and time API, can produce them, which we prefer.
Date
设计总是很糟糕,已经有 20 多年的历史了。这很简单:不要使用它。XMLGregorianCalendar
也很旧,有一个老式的设计。据我了解,它用于为 XML 文档生成 XML 格式的日期和时间。喜欢2009-05-07T19:05:45.678+02:00
或2009-05-07T17:05:45.678Z
。这些格式与 ISO 8601 非常吻合,现代 Java 日期和时间 API 的 java.time 类可以生成它们,这是我们更喜欢的。
No conversion necessary
无需转换
For many (most?) purposes the modern replacement for a Date
will be an Instant
. An Instant
is a point in time (just as a Date
is).
对于许多(大多数?)用途, a 的现代替代品Date
将是Instant
. AnInstant
是一个时间点(就像 a 一样Date
)。
Instant yourInstant = // ...
System.out.println(yourInstant);
An example output from this snippet:
此代码段的示例输出:
2009-05-07T17:05:45.678Z
2009-05-07T17:05:45.678Z
It's the same as the latter of my example XMLGregorianCalendar
strings above. As most of you know, it comes from Instant.toString
being implicitly called by System.out.println
. With java.time, in many cases we don't need the conversions that in the old days we made between Date
, Calendar
, XMLGregorianCalendar
and other classes (in some cases we do need conversions, though, I am showing you a couple in the next section).
它与我XMLGregorianCalendar
上面的示例字符串中的后者相同。正如你们大多数人所知,它来自于Instant.toString
被隐式调用System.out.println
。随着java.time,在许多情况下,我们并不需要,在过去的日子,我们之间进行的转换Date
,Calendar
,XMLGregorianCalendar
和其他类(在某些情况下,我们确实需要转换,但是,我向您展示一对情侣在下一节) .
Controlling the offset
控制偏移
Neither a Date
nor in Instant
has got a time zone nor a UTC offset. The previously accepted and still highest voted answer by Ben Noland uses the JVMs current default time zone for selecting the offset of the XMLGregorianCalendar
. To include an offset in a modern object we use an OffsetDateTime
. For example:
aDate
和 in都没Instant
有时区或 UTC 偏移量。Ben Noland 先前接受且仍然投票最高的答案使用 JVM 当前默认时区来选择XMLGregorianCalendar
. 要在现代对象中包含偏移量,我们使用OffsetDateTime
. 例如:
ZoneId zone = ZoneId.of("America/Asuncion");
OffsetDateTime dateTime = yourInstant.atZone(zone).toOffsetDateTime();
System.out.println(dateTime);
2009-05-07T13:05:45.678-04:00
2009-05-07T13:05:45.678-04:00
Again this conforms with XML format. If you want to use the current JVM time zone setting again, set zone
to ZoneId.systemDefault()
.
这再次符合 XML 格式。如果要再次使用当前 JVM 时区设置,请设置zone
为ZoneId.systemDefault()
。
What if I absolutely need an XMLGregorianCalendar?
如果我绝对需要一个 XMLGregorianCalendar 怎么办?
There are more ways to convert Instant
to XMLGregorianCalendar
. I will present a couple, each with its pros and cons. First, just as an XMLGregorianCalendar
produces a string like 2009-05-07T17:05:45.678Z
, it can also be built from such a string:
有更多方法可以转换Instant
为XMLGregorianCalendar
. 我将介绍一对夫妇,每个都有其优点和缺点。首先,就像 anXMLGregorianCalendar
产生一个字符串一样2009-05-07T17:05:45.678Z
,它也可以从这样的字符串构建:
String dateTimeString = yourInstant.toString();
XMLGregorianCalendar date2
= DatatypeFactory.newInstance().newXMLGregorianCalendar(dateTimeString);
System.out.println(date2);
2009-05-07T17:05:45.678Z
2009-05-07T17:05:45.678Z
Pro: it's short and I don't think it gives any surprises. Con: To me it feels like a waste formatting the instant into a string and parsing it back.
优点:它很短,我认为它不会带来任何惊喜。缺点:对我来说,将瞬间格式化为字符串并将其解析回来感觉就像是浪费。
ZonedDateTime dateTime = yourInstant.atZone(zone);
GregorianCalendar c = GregorianCalendar.from(dateTime);
XMLGregorianCalendar date2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(c);
System.out.println(date2);
2009-05-07T13:05:45.678-04:00
2009-05-07T13:05:45.678-04:00
Pro: It's the official conversion. Controlling the offset comes naturally. Con: It goes through more steps and is therefore longer.
亲:这是官方转换。控制偏移是很自然的。缺点:它经过更多步骤,因此时间更长。
What if we got a Date?
如果我们有约会怎么办?
If you got an old-fashioned Date
object from a legacy API that you cannot afford to change just now, convert it to Instant
:
如果您Date
从遗留 API获得了一个您现在无法更改的老式对象,请将其转换为Instant
:
Instant i = yourDate.toInstant();
System.out.println(i);
Output is the same as before:
输出与之前相同:
2009-05-07T17:05:45.678Z
2009-05-07T17:05:45.678Z
If you want to control the offset, convert further to an OffsetDateTime
in the same way as above.
如果要控制偏移量,请OffsetDateTime
按照与上述相同的方式进一步转换为 an 。
If you've got an old-fashioned Date
and absolutely need an old-fashioned XMLGregorianCalendar
, just use the answer by Ben Noland.
如果您有一个老式的Date
并且绝对需要一个老式的XMLGregorianCalendar
,请使用 Ben Noland 的答案。
Links
链接
- Oracle tutorial: Date Timeexplaining how to use java.time.
- XSD Date and Time Data Typeson W3Schools.
- Wikipedia article: ISO 8601
- Oracle 教程:解释如何使用 java.time 的日期时间。
- W3Schools 上的XSD 日期和时间数据类型。
- 维基百科文章:ISO 8601
回答by Ben Noland
GregorianCalendar c = new GregorianCalendar();
c.setTime(yourDate);
XMLGregorianCalendar date2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(c);
回答by sasuke
Here is a method for converting from a GregorianCalendar to XMLGregorianCalendar; I'll leave the part of converting from a java.util.Date to GregorianCalendar as an exercise for you:
这是一种从 GregorianCalendar 转换为 XMLGregorianCalendar 的方法;我将把从 java.util.Date 转换为 GregorianCalendar 的部分留给您作为练习:
import java.util.GregorianCalendar;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
public class DateTest {
public static void main(final String[] args) throws Exception {
GregorianCalendar gcal = new GregorianCalendar();
XMLGregorianCalendar xgcal = DatatypeFactory.newInstance()
.newXMLGregorianCalendar(gcal);
System.out.println(xgcal);
}
}
EDIT: Slooow :-)
编辑:Slooow :-)
回答by Daniel K.
I hope my encoding here is right ;D To make it faster just use the ugly getInstance() call of GregorianCalendar instead of constructor call:
我希望我在这里的编码是正确的;D 为了让它更快,只需使用 GregorianCalendar 的丑陋 getInstance() 调用而不是构造函数调用:
import java.util.GregorianCalendar;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
public class DateTest {
public static void main(final String[] args) throws Exception {
// do not forget the type cast :/
GregorianCalendar gcal = (GregorianCalendar) GregorianCalendar.getInstance();
XMLGregorianCalendar xgcal = DatatypeFactory.newInstance()
.newXMLGregorianCalendar(gcal);
System.out.println(xgcal);
}
}
回答by Nuno Furtado
For those that might end up here looking for the opposite conversion (from XMLGregorianCalendar
to Date
):
对于那些可能最终在这里寻找相反转换(从XMLGregorianCalendar
到Date
)的人:
XMLGregorianCalendar xcal = <assume this is initialized>;
java.util.Date dt = xcal.toGregorianCalendar().getTime();
回答by khylo
Just thought I'd add my solution below, since the answers above did not meet my exact needs. My Xml schema required seperate Date and Time elements, not a singe DateTime field. The standard XMLGregorianCalendar constructor used above will generate a DateTime field
只是想我会在下面添加我的解决方案,因为上面的答案没有满足我的确切需求。我的 Xml 架构需要单独的日期和时间元素,而不是单个日期时间字段。上面使用的标准 XMLGregorianCalendar 构造函数将生成一个 DateTime 字段
Note there a couple of gothca's, such as having to add one to the month (since java counts months from 0).
请注意有几个 gothca,例如必须在月份中添加一个(因为 java 从 0 开始计算月份)。
GregorianCalendar cal = new GregorianCalendar();
cal.setTime(yourDate);
XMLGregorianCalendar xmlDate = DatatypeFactory.newInstance().newXMLGregorianCalendarDate(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH)+1, cal.get(Calendar.DAY_OF_MONTH), 0);
XMLGregorianCalendar xmlTime = DatatypeFactory.newInstance().newXMLGregorianCalendarTime(cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND), 0);
回答by KarlP
Assuming you are decoding or encoding xml and using JAXB
, then it's possible to replace the dateTime binding entirely and use something else than `XMLGregorianCalendar' for every date in the schema.
假设您正在解码或编码 xml 并使用JAXB
,那么可以完全替换 dateTime 绑定并为架构中的每个日期使用除“XMLGregorianCalendar”之外的其他内容。
In that way you can have JAXB
do the repetitive stuff while you can spend the time on writing awesome code that delivers value.
这样你就可以JAXB
做重复的事情,同时你可以花时间编写可交付价值的精彩代码。
Example for a jodatime DateTime
: (Doing this with java.util.Date would also work - but with certain limitations. I prefer jodatime and it's copied from my code so I know it works...)
jodatime 示例DateTime
:(使用 java.util.Date 执行此操作也可以 - 但有某些限制。我更喜欢 jodatime,它是从我的代码中复制的,所以我知道它可以工作......)
<jxb:globalBindings>
<jxb:javaType name="org.joda.time.LocalDateTime" xmlType="xs:dateTime"
parseMethod="test.util.JaxbConverter.parseDateTime"
printMethod="se.seb.bis.test.util.JaxbConverter.printDateTime" />
<jxb:javaType name="org.joda.time.LocalDate" xmlType="xs:date"
parseMethod="test.util.JaxbConverter.parseDate"
printMethod="test.util.JaxbConverter.printDate" />
<jxb:javaType name="org.joda.time.LocalTime" xmlType="xs:time"
parseMethod="test.util.JaxbConverter.parseTime"
printMethod="test.util.JaxbConverter.printTime" />
<jxb:serializable uid="2" />
</jxb:globalBindings>
And the converter:
和转换器:
public class JaxbConverter {
static final DateTimeFormatter dtf = ISODateTimeFormat.dateTimeNoMillis();
static final DateTimeFormatter df = ISODateTimeFormat.date();
static final DateTimeFormatter tf = ISODateTimeFormat.time();
public static LocalDateTime parseDateTime(String s) {
try {
if (StringUtils.trimToEmpty(s).isEmpty())
return null;
LocalDateTime r = dtf.parseLocalDateTime(s);
return r;
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
}
public static String printDateTime(LocalDateTime d) {
try {
if (d == null)
return null;
return dtf.print(d);
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
}
public static LocalDate parseDate(String s) {
try {
if (StringUtils.trimToEmpty(s).isEmpty())
return null;
return df.parseLocalDate(s);
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
}
public static String printDate(LocalDate d) {
try {
if (d == null)
return null;
return df.print(d);
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
}
public static String printTime(LocalTime d) {
try {
if (d == null)
return null;
return tf.print(d);
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
}
public static LocalTime parseTime(String s) {
try {
if (StringUtils.trimToEmpty(s).isEmpty())
return null;
return df.parseLocalTime(s);
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
}
See here: how replace XmlGregorianCalendar by Date?
请参阅此处: 如何按日期替换 XmlGregorianCalendar?
If you are happy to just map to an instant based on the timezone+timestamp, and the original timezone is not really relevant, then java.util.Date
is probably fine too.
如果您乐于根据时区+时间戳映射到一个瞬间,并且原始时区并不真正相关,那么java.util.Date
也可能没问题。
回答by Chris Knight
A one line example using Joda-Timelibrary:
使用Joda-Time库的单行示例:
XMLGregorianCalendar xgc = DatatypeFactory.newInstance().newXMLGregorianCalendar(new DateTime().toGregorianCalendar());
Credit to Nicolas Mommaertsfrom his comment in the accepted answer.
感谢尼古拉酒店距离Mommaerts从他的评论接受的答案。
回答by Akash
Check out this code :-
看看这个代码:-
/* Create Date Object */
Date date = new Date();
XMLGregorianCalendar xmlDate = null;
GregorianCalendar gc = new GregorianCalendar();
gc.setTime(date);
try{
xmlDate = DatatypeFactory.newInstance().newXMLGregorianCalendar(gc);
}
catch(Exception e){
e.printStackTrace();
}
System.out.println("XMLGregorianCalendar :- " + xmlDate);
You can see complete example here
您可以在此处查看完整示例