在 Java 中解析 XML 日期时间的最佳方法是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/909022/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 20:58:12  来源:igfitidea点击:

What's the best way to parse an XML dateTime in Java?

javaxml

提问by

What's the best way to parse an XML dateTime in Java? Legal dateTime values include 2002-10-10T12:00:00-05:00 AND 2002-10-10T17:00:00Z

在 Java 中解析 XML 日期时间的最佳方法是什么?合法的 dateTime 值包括 2002-10-10T12:00:00-05:00 AND 2002-10-10T17:00:00Z

Is there a good open source library I can use, or should I roll my own using SimpleDateFormat or similar?

是否有一个很好的开源库可以使用,还是应该使用 SimpleDateFormat 或类似的方式推出自己的库?

回答by Jon Skeet

I think you want ISODateTimeFormat.dateTimeNoMillis()from Joda Time. In general I would stronglyurge you to stay away from the built-in Date/Calendar classes in Java. Joda Time is much better designed, favours immutability (in particular the formatters are immutable and thread-safe) and is the basis for the new date/time API in Java 7.

我想你想要ISODateTimeFormat.dateTimeNoMillis()Joda Time。一般来说,我强烈建议您远离 Java 中的内置日期/日历类。Joda Time 设计得更好,支持不变性(特别是格式化程序是不可变的和线程安全的),并且是 Java 7 中新日期/时间 API 的基础。

Sample code:

示例代码:

import org.joda.time.*;
import org.joda.time.format.*;

class Test
{   
    public static void main(String[] args)
    {
        parse("2002-10-10T12:00:00-05:00");
        parse("2002-10-10T17:00:00Z");
    }

    private static final DateTimeFormatter XML_DATE_TIME_FORMAT =
        ISODateTimeFormat.dateTimeNoMillis();

    private static final DateTimeFormatter CHECKING_FORMAT =
        ISODateTimeFormat.dateTime().withZone(DateTimeZone.UTC);

    static void parse(String text)
    {
        System.out.println("Parsing: " + text);
        DateTime dt = XML_DATE_TIME_FORMAT.parseDateTime(text);
        System.out.println("Parsed to: " + CHECKING_FORMAT.print(dt));
    }
}

Output:

输出:

Parsing: 2002-10-10T12:00:00-05:00
Parsed to: 2002-10-10T17:00:00.000Z
Parsing: 2002-10-10T17:00:00Z
Parsed to: 2002-10-10T17:00:00.000Z

(Note that in the output both end up as the same UTC time. The output formatted uses UTC because we asked it to with the withZonecall.)

(请注意,在输出中,两者都以相同的 UTC 时间结束。格式化的输出使用 UTC,因为我们在withZone调用时要求它使用。)

回答by StaxMan

Ideally, XML processing packages that are schema-aware (or to be used as basis for things that are) should provide accessors for typed content. I know of one (http://woodstox.codehaus.org/), but it does not (yet) offer access to date/time, just simpler types (numeric, arrays, QNames etc). There is a request to support javax.xml.datatype.XMLGregorianCalendar.

理想情况下,模式感知(或用作事物的基础)的 XML 处理包应该为类型化内容提供访问器。我知道一个(http://woodstox.codehaus.org/),但它(还)不提供对日期/时间的访问,只是提供更简单的类型(数字、数组、QNames 等)。有一个请求支持 javax.xml.datatype.XMLGregorianCalendar。

Alas, not many do. However, it you are using specific package (like XOM or JDOM etc), it might not be a bad idea to ask this question on their user list.

唉,没有多少人这样做。但是,如果您正在使用特定的包(如 XOM 或 JDOM 等),在他们的用户列表中询问这个问题可能不是一个坏主意。

回答by DavidValeri

StaxMan is absolutely correct. In order to use SimpleDateFormat, you need to turn off lax parsing in each SimpleDateFormat and iterate over several SimpleDateFormat formats until you find the one that parses the date without throwing an exception. If you leave lax parsing on, you are prone to get a match when you didn't really want one, and the lexical space of XSD:DateTimeleaves some flexibility in format that SimpleDateFormat can't handle in a single expression.

StaxMan 是绝对正确的。为了使用SimpleDateFormat,您需要关闭每个SimpleDateFormat 中的松散解析并迭代几种SimpleDateFormat 格式,直到找到解析日期而不抛出异常的格式。如果您保留松散的解析,您很容易在您并不真正想要一个匹配项时获得匹配项,并且XSD:DateTime词法空间在格式上留下了一些灵活性,SimpleDateFormat 无法在单个表达式中处理。

XML Schema 1.0 does indeed use ISO 8601, which Joda Time, as suggested by Jon Skeet, implements so that is a valid option.

XML Schema 1.0 确实使用了 ISO 8601,Joda Time 按照 Jon Skeet 的建议实现了 ISO 8601,因此这是一个有效的选择。

If you want to keep it all in the native Java packages, you can also use XMLGregorianCalendarin conjunction with DatatypeFactoryto parse and create XSD:Datetime strings.

如果您想将其全部保留在本机 Java 包中,您还可以将XMLGregorianCalendarDatatypeFactory结合使用来解析和创建 XSD:Datetime 字符串。

See DatatypeFactory.newXMLGregorianCalendar and XMLGregorianCalendar.toXMLFormat

请参阅 DatatypeFactory.newXMLGregorianCalendar 和 XMLGregorianCalendar.toXMLFormat

回答by Zaur_M

http://xmlbeans.apache.org/samples/DateTime.html

http://xmlbeans.apache.org/samples/DateTime.html

There is XmlDateTime class. Just do XMLDateTime.stringToDate(xmlDateTime).

有 XmlDateTime 类。只需执行 XMLDateTime.stringToDate(xmlDateTime)。

回答by MB.

回答by Clement Pellerin

In XML Beans v2 it would be XmlDateTime.Factory.parse(dateTimeString), but this is awkward because it expects an element with start and end tags like <mytime>2011-10-20T15:07:14.112-07:00</mytime>

在 XML Beans v2 中它会是XmlDateTime.Factory.parse(dateTimeString),但这很尴尬,因为它需要一个带有开始和结束标记的元素,例如<mytime>2011-10-20T15:07:14.112-07:00</mytime>

An easier approach is to call (new org.apache.xmlbeans.GDate(dateTimeString)).getDate().

更简单的方法是调用(new org.apache.xmlbeans.GDate(dateTimeString)).getDate().

回答by Javier Cámara

See Parse and format dateTime values, although: -It takes "GMT" as the default timezone -It does not complain if there are trailing non-parseable parts -Does not take into account that TimeZone defaults to "GMT" on wrong "GMT+xxxx"

请参阅解析和格式化 dateTime 值,尽管: - 将“GMT”作为默认时区 - 如果有不可解析的尾随部分,它不会抱怨 - 不考虑 TimeZone 在错误的“GMT+”上默认为“GMT” xxx"

回答by Rich

You can also use newXMLGregorianCalendarin javax.xml.datatype.DatatypeFactory, which gives you detailed control, including detecting whether the timezone was specified or not.

您还可以在 中使用newXMLGregorianCalendarjavax.xml.datatype.DatatypeFactory,它为您提供详细控制,包括检测是否指定了时区。

回答by Basil Bourque

tl;dr

tl;博士

Instant instant = Instant.parse( "2002-10-10T17:00:00Z" );
OffsetDateTime odt = OffsetDateTime.parse( "2002-10-10T12:00:00-05:00" );

Details

细节

The other Answers are correct but now outdated. They use troublesome old classes now supplanted by the java.time framework.

其他答案是正确的,但现在已经过时了。他们使用麻烦的旧类,现在已被 java.time 框架取代。

No such thing as an “XML dateTime”. XMLdoes not define any data type beyond text.

没有“XML 日期时间”这样的东西。XML没有定义文本以外的任何数据类型。

Using java.time

使用 java.time

The input string happens to comply with ISO 8601standard formatting. So no need to specify a formatting pattern as the java.time classes use ISO 8601 by default when parsing/generating strings.

输入字符串恰好符合ISO 8601标准格式。因此无需指定格式模式,因为 java.time 类在解析/生成字符串时默认使用 ISO 8601。

Instant

Instant

The second input string ends in a Z, short for Zulu, and means UTC.

第二个输入字符串以 a 结尾,是Z, 的缩写Zulu,表示UTC

The Instantclass represents a moment on the timeline in UTCwith a resolution of nanoseconds.

Instant级表示时间轴上的时刻UTC,分辨率为纳秒

String input = "2002-10-10T17:00:00Z":
Instant instant = Instant.parse( input );

OffsetDateTime

OffsetDateTime

The first input string includes an offset-from-UTC, so we parse as an OffsetDateTime.

第一个输入字符串包含一个来自 UTC 的偏移量,因此我们将其解析为OffsetDateTime.

String input = "2002-10-10T12:00:00-05:00" ;
OffsetDateTime odt = OffsetDateTime.parse( input );

ZonedDateTime

ZonedDateTime

If you have a specific time zone in mind, rather than a mere offset-from-UTC, apply that.

如果您有一个特定的时区,而不仅仅是与 UTC 的偏移量,请应用它。

Use a proper time zone namein format of continent/region. Never use the 3-4 letter abbreviations that are not true time zones, not standardized, and not even unique(!).

使用正确的时区名称,格式为continent/region. 永远不要使用 3-4 个字母的缩写,这些缩写不是真正的时区,不是标准化的,甚至不是唯一的(!)。

ZoneId zoneId = ZoneId.of( "America/Cancun" );
ZonedDateTime zdt = odt.atZone( zoneId );

enter image description here

在此处输入图片说明

About java.time

关于 java.time

The java.timeframework is built into Java 8 and later. These classes supplant the old troublesome date-time classes such as java.util.Date, .Calendar, & java.text.SimpleDateFormat.

java.time框架是建立在Java 8和更高版本。这些类取代了旧的麻烦的日期时间类,例如java.util.Date, .Calendar, & java.text.SimpleDateFormat

The Joda-Timeproject, now in maintenance mode, advises migration to java.time.

现在处于维护模式Joda-Time项目建议迁移到 java.time。

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations.

要了解更多信息,请参阅Oracle 教程。并在 Stack Overflow 上搜索许多示例和解释。

Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backportand further adapted to Androidin ThreeTenABP.

多的java.time功能后移植到Java 6和7在ThreeTen-反向移植并且还适于的AndroidThreeTenABP

The ThreeTen-Extraproject extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

ThreeTen-额外项目与其他类扩展java.time。该项目是未来可能添加到 java.time 的试验场。你可能在这里找到一些有用的类,如IntervalYearWeekYearQuarter,等。