将 Java 日期转换为 XML 日期格式(反之亦然)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4099862/
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
Convert Java Date into XML Date Format (and vice versa)
提问by Andez
Is there a nice and easy way to convert a Java Date into XML date string format and vice versa?
是否有一种很好且简单的方法可以将 Java 日期转换为 XML 日期字符串格式,反之亦然?
Cheers,
干杯,
Andez
安德斯
采纳答案by Pawe? Dyda
Original answer
原答案
I am guessing here that by "XML Date Format" you mean something like "2010-11-04T19:14Z". It is actually ISO 8601format.
我在这里猜测“XML 日期格式”的意思是“2010-11-04T19:14Z”。它实际上是ISO 8601格式。
You can convert it using SimpleDateFormat, as others suggested, FastDateFormat or using Joda Timewhich was I believe especially created for this purpose.
您可以使用 SimpleDateFormat 转换它,正如其他人建议的那样,FastDateFormat 或使用Joda Time,我相信这是专门为此目的创建的。
Edit: code samples and more
编辑:代码示例等
As earnshaestated in a comment, this answer could be improved with examples.
正如earnshae在评论中所说,这个答案可以通过例子来改进。
First, we have to make clear that the original answer is pretty outdated. It's because Java 8 introduced the classes to manipulate date and time - java.time
package should be of interest. If you are lucky enough to be using Java 8, you should use one of them. However, these things are surprisingly difficult to get right.
首先,我们必须明确原始答案已经过时了。这是因为 Java 8 引入了操作日期和时间的类 -java.time
应该对包感兴趣。如果您有幸使用 Java 8,则应该使用其中之一。然而,这些事情出人意料地难以做到。
LocalDate(Time) that isn't
LocalDate(Time) 不是
Consider this example:
考虑这个例子:
LocalDateTime dateTime = LocalDateTime.parse("2016-03-23T18:21");
System.out.println(dateTime); // 2016-03-23T18:21
At first it may seem that what we're using here is a local (to the user date and time). However, if you dare to ask, you'll get different result:
起初,我们在这里使用的似乎是本地的(用户日期和时间)。但是,如果你敢问,你会得到不同的结果:
System.out.println(dateTime.getChronology()); // ISO
This actually, the ISO time. I believe it should read 'UTC' but nonetheless this has no notion of local time zone. So we should consider it universal.
Please notice, that there is no "Z" at the end of the string we are parsing. Should you add anything apart of date and time, you'll be greeted with java.time.format.DateTimeParseException
. So it seems that this class is of no use if we want to parse ISO8601 string.
这实际上是 ISO 时间。我相信它应该读为“UTC”,但它没有本地时区的概念。所以我们应该认为它是通用的。
请注意,我们正在解析的字符串末尾没有“Z”。如果您添加日期和时间之外的任何内容,您将收到java.time.format.DateTimeParseException
. 所以如果我们要解析 ISO8601 字符串,这个类似乎没有用。
ZonedDateTime to the rescue
ZonedDateTime 来救援
Fortunately, there is a class that allows for parsing ISO8601 strings - it's a java.time.ZonedDateTime.
幸运的是,有一个类允许解析 ISO8601 字符串——它是一个java.time.ZonedDateTime。
ZonedDateTime zonedDateTime = ZonedDateTime.parse("2016-03-23T18:21+01:00");
System.out.println(zonedDateTime); // 2016-03-23T18:21+01:00
ZonedDateTime zonedDateTimeZulu = ZonedDateTime.parse("2016-03-23T18:21Z");
System.out.println(zonedDateTimeZulu); // 2016-03-23T18:21Z
The only problem here is, you actually need to use time zone designation. Trying to parse raw date time (i.e. "2016-03-23T18:21") will result in already mentioned RuntimeException
. Depending on the situation you'd have to choose between LocalDateTime
and ZonedDateTime
.
Of course you can easily convert between those two, so it should not be a problem:
这里唯一的问题是,您实际上需要使用时区指定。尝试解析原始日期时间(即“2016-03-23T18:21”)将导致已经提到的RuntimeException
. 根据情况,您必须在LocalDateTime
和之间进行选择ZonedDateTime
。
当然,您可以轻松地在这两者之间进行转换,因此应该不成问题:
System.out.println(zonedDateTimeZulu.toLocalDateTime()); // 2016-03-23T18:21
// Zone conversion
ZonedDateTime cetDateTime = zonedDateTimeZulu.toLocalDateTime()
.atZone(ZoneId.of("CET"));
System.out.println(cetDateTime); // 2016-03-23T18:21+01:00[CET]
I recommend using this classes nowadays. However, if your job description includes archeology (meaning you are not lucky enough to be working with more than 2 year old Java 8...), you may need to use something else.
我建议现在使用这个类。但是,如果您的工作描述包括考古学(意味着您没有幸运地使用超过 2 年的 Java 8...),您可能需要使用其他东西。
The joy of SimpleDateFormat
SimpleDateFormat 的乐趣
I am not a very big fan of https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html, but sometimes you just have no other choice. Problem is, it is not thread-safe and it will throw a checked Exception
(namely ParseException
) in your face if it dislikes something. Therefore the code snippet is rather ugly:
我不是 https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html 的忠实粉丝,但有时您别无选择。问题是,它不是线程安全的,如果它不喜欢某些东西,它会在你的脸上抛出一个检查Exception
(即ParseException
)。因此代码片段相当丑陋:
private Object lock = new Object();
// ...
try {
synchronized (lock) {
// Either "2016-03-23T18:21+01:00" or "2016-03-23T18:21Z"
// will be correctly parsed (mind the different meaning though)
Date date = dateFormat.parse("2016-03-23T18:21Z");
System.out.println(date); // Wed Mar 23 19:21:00 CET 2016
}
} catch (ParseException e) {
LOG.error("Date time parsing exception", e);
}
FastDateFormat
快速日期格式
FastDateFormat
is synchronized, therefore you can at least get rid of the synchronized block. However, it is an external dependency. But since it's the Apache Commons Langand it is thoroughly used, I guess it is acceptable. It is actually very similar in usage to SimpleDateFormat
:
FastDateFormat
是同步的,因此您至少可以摆脱同步块。然而,它是一个外部依赖。但是因为它是Apache Commons Lang并且它被彻底使用,我想它是可以接受的。它的用法实际上非常类似于SimpleDateFormat
:
FastDateFormat fastDateFormat = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mmX");
try {
Date fastDate = fastDateFormat.parse("2016-03-23T18:21+01:00");
System.out.println(fastDate);
} catch (ParseException e) {
LOG.error("Date time parsing exception", e);
}
JodaTime
乔达时间
With Joda-Time you may think that following works:
使用 Joda-Time,您可能认为以下有效:
DateTimeFormatter parser = ISODateTimeFormat.dateTimeParser();
LocalDateTime dateTime = LocalDateTime.parse("2016-03-23T20:48+01:00", parser);
System.out.println(dateTime); // 2016-03-23T20:48:00.000
Unfortunately, no matter what you put at last position (Z, +03:00, ...) the result will be the same. Clearly, it isn't working.
Well, you really should be parsing it directly:
不幸的是,无论您在最后一个位置 (Z, +03:00, ...) 放什么,结果都是一样的。显然,它不起作用。
好吧,你真的应该直接解析它:
DateTimeFormatter parser = ISODateTimeFormat.dateTimeParser();
DateTime dateTime = parser.parseDateTime("2016-03-23T21:12:23+04:00");
System.out.println(dateTime); // 2016-03-23T18:12:23.000+01:00
Now it will be OK. Please note, that unlike one of other answers, I used dateTimeParser()
and notdateTime()
. I noticed subtle, but important difference in behavior between them (Joda-Time 2.9.2). But, I leave it to the reader to test it and confirm.
现在就OK了。请注意,与其他答案之一不同,我使用了dateTimeParser()
而不是dateTime()
. 我注意到它们之间微妙但重要的行为差异(Joda-Time 2.9.2)。但是,我把它留给读者来测试和确认。
回答by Eugene Kuleshov
You can parse and format dates to and from any format using SimpleDateFormat
您可以使用SimpleDateFormat从任何格式解析和格式化日期
回答by javamonkey79
回答by Kennet
As already suggested use SimpleDateFormat.
正如已经建议使用 SimpleDateFormat。
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
String date = sdf.format(new Date());
System.out.println(date);
Date d = sdf.parse(date);
My guess is that the format/pattern that your looking for is yyyy-MM-dd'T'HH:mm:ss
Also have a look at http://www.w3schools.com/schema/schema_dtypes_date.asp
我的猜测是您正在寻找的格式/模式yyyy-MM-dd'T'HH:mm:ss
也看看http://www.w3schools.com/schema/schema_dtypes_date.asp
回答by Gary Rowe
Using Joda Timeyou would do the following:
使用Joda Time,您将执行以下操作:
DateTimeFormatter fmt = ISODateTimeFormat.dateTime(); // ISO8601 (XML) Date/time
DateTime dt = fmt.parseDateTime("2000-01-01T12:00:00+100"); // +1hr time zone
System.out.println(fmt.print(dt)); // Prints in ISO8601 format
Thread safe, immutable and simple.
线程安全、不可变且简单。
回答by Sridhar Nalam
Just by using SimpleDateFormat in java we can do this...
只需在 java 中使用 SimpleDateFormat 我们就可以做到这一点......
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
Date date = sdf.parse("2011-12-31T15:05:50+1000");
回答by Belz
The Perfect method, use XMLGregorianCalendar:
Perfect 方法,使用 XMLGregorianCalendar:
GregorianCalendar calendar = new GregorianCalendar();
calendar.setTime(v);
DatatypeFactory df = DatatypeFactory.newInstance();
XMLGregorianCalendar dateTime = df.newXMLGregorianCalendar(calendar);
return dateTime.toString();
回答by arkhos
To comply with ISO8601, the timezone must be in the format +HH:MM or - HH:MM
要符合 ISO8601,时区必须采用 +HH:MM 或 - HH:MM 格式
With Simpledateformat you must use XXX instead of Z (see NovelGuy answer)
使用 Simpledateformat 您必须使用 XXX 而不是 Z(请参阅 NovelGuy 答案)
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
回答by stenix
I would recommend to use the java built in class javax.xml.bind.DatatypeConverter. It can handle conversion to and from most of the xml simple types. It is a little bit cumbersome for dates that you have to go through a Calendar
object but on the other hand it handles all variants of zone information that can occur in a xml datetime
field.
我建议使用javax.xml.bind.DatatypeConverter内置的 java 。它可以处理与大多数 xml 简单类型之间的转换。对于必须通过Calendar
对象的日期来说有点麻烦,但另一方面,它处理可能出现在 xmldatetime
字段中的区域信息的所有变体。
From xml:
来自 xml:
Calendar c = DatatypeConverter.parseDateTime("2015-10-21T13:25");
Date d = c.getTime();
To xml:
到 xml:
Date yourDate = new Date()
Calendar c = Calendar.getInstance();
c.setTime(yourDate);
String xmlDateTime = DatatypeConverter.printDateTime(c);
EDIT
编辑
The DatatypeConverter class is no longer publicly visible in Java 9 and above since it belongs to the javax.xml.bind package. See this questionfor more information and possible solutions. The solution proposed by loic vaugeoisto use XmlGregorianCalendar is much better in this case.
DatatypeConverter 类在 Java 9 及更高版本中不再公开可见,因为它属于 javax.xml.bind 包。有关更多信息和可能的解决方案,请参阅此问题。在这种情况下,loic vaugeois提出的使用 XmlGregorianCalendar的解决方案要好得多。