java.util.Date 到 XMLGregorianCalendar [英] java.util.Date to XMLGregorianCalendar
问题描述
难道没有一种从 java.util.Date 到 XMLGregorianCalendar 的便捷方法吗?
我想退后一步,以现代的眼光看待这个 10 年前的问题.提到的类 Date
和 XMLGregorianCalendar
现在已经过时了.我挑战使用它们并提供替代方案.
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 类可以生成它们,这是我们更喜欢的.
无需转换
对于许多(大多数?)用途,Date
的现代替代品将是 Instant
.Instant
是一个时间点(就像 Date
一样).
Instant yourInstant =//...System.out.println(yourInstant);
此代码段的示例输出:
<块引用>2009-05-07T17:05:45.678Z
它与我上面的示例 XMLGregorianCalendar
字符串的后者相同.正如大多数人所知,它来自 Instant.toString
被 System.out.println
隐式调用.使用 java.time,在很多情况下,我们不需要过去在 Date
、Calendar
、XMLGregorianCalendar
和其他类(在某些情况下,我们确实需要转换,但我将在下一节中向您展示一些).
控制偏移
Date
和 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
这再次符合 XML 格式.如果要再次使用当前 JVM 时区设置,请将 zone
设置为 ZoneId.systemDefault()
.
如果我绝对需要一个 XMLGregorianCalendar 怎么办?
有更多方法可以将 Instant
转换为 XMLGregorianCalendar
.我将介绍一对夫妇,每一个都有其优点和缺点.首先,就像 XMLGregorianCalendar
产生一个类似 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
Pro:它很短,我认为它不会带来任何惊喜.缺点:对我来说,将瞬间格式化为字符串并解析回来是一种浪费.
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
Pro:这是官方转换.控制偏移是很自然的.缺点:步骤较多,因此时间较长.
如果我们有约会怎么办?
如果您从遗留 API 获得了一个老式的 Date
对象,而您现在无法对其进行更改,请将其转换为 Instant
:
Instant i = yourDate.toInstant();System.out.println(i);
输出和之前一样:
<块引用>2009-05-07T17:05:45.678Z
如果你想控制偏移量,按照上面同样的方式进一步转换为OffsetDateTime
.
如果您有一个老式的 Date
并且绝对需要一个老式的 XMLGregorianCalendar
,请使用 Ben Noland 的答案.
链接
- Oracle 教程:日期时间解释如何使用 java.time.莉>W3Schools 上的
- XSD 日期和时间数据类型.
- 维基百科文章:ISO 8601
Isn't there a convenient way of getting from a java.util.Date to a XMLGregorianCalendar?
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.
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.
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).
Instant yourInstant = // ...
System.out.println(yourInstant);
An example output from this snippet:
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).
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:
ZoneId zone = ZoneId.of("America/Asuncion");
OffsetDateTime dateTime = yourInstant.atZone(zone).toOffsetDateTime();
System.out.println(dateTime);
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()
.
What if I absolutely need an 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:
String dateTimeString = yourInstant.toString();
XMLGregorianCalendar date2
= DatatypeFactory.newInstance().newXMLGregorianCalendar(dateTimeString);
System.out.println(date2);
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
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
:
Instant i = yourDate.toInstant();
System.out.println(i);
Output is the same as before:
2009-05-07T17:05:45.678Z
If you want to control the offset, convert further to an OffsetDateTime
in the same way as above.
If you’ve got an old-fashioned Date
and absolutely need an old-fashioned XMLGregorianCalendar
, just use the answer by Ben Noland.
Links
- Oracle tutorial: Date Time explaining how to use java.time.
- XSD Date and Time Data Types on W3Schools.
- Wikipedia article: ISO 8601
这篇关于java.util.Date 到 XMLGregorianCalendar的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!