在Java中解析XML dateTime的最佳方法是什么?法定日期时间值包括2002-10-10T12:00:00-05:00和2002-10-10T17:00:00Z
我可以使用一个好的开源库,还是应该使用SimpleDateFormat或类似的?
答案 0 :(得分:72)
答案 1 :(得分:39)
我想你想要来自ISODateTimeFormat.dateTimeNoMillis()
的Joda Time。一般来说
我强烈敦促你远离Java中的内置Date / Calendar类。 Joda Time的设计要好得多,有利于不变性(特别是格式化程序是不可变的和线程安全的),并且是Java 7中新的日期/时间API的基础。
示例代码:
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));
}
}
输出:
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
(请注意,在输出中两者都以相同的UTC时间结束。格式化的输出使用UTC,因为我们通过withZone
调用询问它。)
答案 2 :(得分:6)
StaxMan绝对正确。为了使用SimpleDateFormat,您需要在每个SimpleDateFormat中关闭松散解析并迭代几个SimpleDateFormat格式,直到找到解析日期而不抛出异常的格式。如果你打开松散解析,你很容易得到匹配,当你真的不想要一个,而lexical space of XSD:DateTime在SimpleDateFormat无法在单个表达式中处理的格式留下一些灵活性。
XML Schema 1.0确实使用了ISO 8601,正如Jon Skeet所建议的那样,Joda Time实现了这是一个有效的选项。
如果要将其全部保存在本机Java包中,还可以将XMLGregorianCalendar与DatatypeFactory结合使用来解析和创建XSD:Datetime字符串。
请参阅DatatypeFactory.newXMLGregorianCalendar和XMLGregorianCalendar.toXMLFormat
答案 3 :(得分:2)
见Parse and format dateTime values,但是: - 它将“GMT”作为默认时区 - 如果有不可解析的部分,则不会抱怨 - 没有考虑到TimeZone在错误的“GMT + xxxx”上默认为“GMT”
答案 4 :(得分:2)
Instant instant = Instant.parse( "2002-10-10T17:00:00Z" );
OffsetDateTime odt = OffsetDateTime.parse( "2002-10-10T12:00:00-05:00" );
其他答案是正确的,但现在已经过时了。他们使用现在由java.time框架取代的麻烦的旧类。
没有“XML dateTime”这样的东西。 XML未定义文本之外的任何数据类型。
输入字符串恰好符合ISO 8601标准格式。所以不需要指定格式化模式,因为java.time类在解析/生成字符串时默认使用ISO 8601。
Instant
第二个输入字符串以Z
结尾,Zulu
的缩写,表示UTC。
Instant
类代表UTC中时间轴上的一个时刻,分辨率为nanoseconds。
String input = "2002-10-10T17:00:00Z":
Instant instant = Instant.parse( input );
OffsetDateTime
第一个输入字符串包含UTC的偏移量,因此我们将其解析为OffsetDateTime
。
String input = "2002-10-10T12:00:00-05:00" ;
OffsetDateTime odt = OffsetDateTime.parse( input );
ZonedDateTime
如果你有一个特定的时区,而不是仅仅偏离UTC,请应用它。
以continent/region
的格式使用proper time zone name。切勿使用不是真正时区的3-4字母缩写,不是标准化的,甚至不是唯一的(!)。
ZoneId zoneId = ZoneId.of( "America/Cancun" );
ZonedDateTime zdt = odt.atZone( zoneId );
java.time框架内置于Java 8及更高版本中。这些类取代了旧的麻烦日期时间类,例如java.util.Date
,.Calendar
和& java.text.SimpleDateFormat
。
现在位于Joda-Time的maintenance mode项目建议迁移到java.time。
要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。
大部分java.time功能都被反向移植到Java 6& ThreeTen-Backport中的7,并进一步适应Android中的ThreeTenABP。
ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如Interval
,YearWeek
,YearQuarter
等。
答案 5 :(得分:1)
http://xmlbeans.apache.org/samples/DateTime.html
有XmlDateTime类。只需执行XMLDateTime.stringToDate(xmlDateTime)。
答案 6 :(得分:1)
在XML Beans v2中它将是XmlDateTime.Factory.parse(dateTimeString)
,但这很尴尬,因为它需要一个带有开始和结束标记的元素,如<mytime>2011-10-20T15:07:14.112-07:00</mytime>
更简单的方法是致电(new org.apache.xmlbeans.GDate(dateTimeString)).getDate()
。
答案 7 :(得分:1)
您还可以在javax.xml.datatype.DatatypeFactory
中使用newXMLGregorianCalendar,它可以为您提供详细的控制,包括检测是否指定了时区。
答案 8 :(得分:0)
理想情况下,支持模式(或用作事物基础)的XML处理包应该为类型化内容提供访问器。我知道一个(http://woodstox.codehaus.org/),但它(尚未)提供对日期/时间的访问,只是更简单的类型(数字,数组,QNames等)。请求支持javax.xml.datatype.XMLGregorianCalendar。
唉,没有多少人这样做。但是,如果您使用的是特定包(如XOM或JDOM等),在用户列表中提出此问题可能不是一个坏主意。