将 Java 日期转换为 XML 日期格式(反之亦然)

Posted

技术标签:

【中文标题】将 Java 日期转换为 XML 日期格式(反之亦然)【英文标题】:Convert Java Date into XML Date Format (and vice versa) 【发布时间】:2011-05-05 05:35:04 【问题描述】:

有没有一种简便的方法可以将 Java 日期转换为 XML 日期字符串格式,反之亦然?

干杯,

安德斯

【问题讨论】:

“XML 日期字符串格式”到底是什么意思?你能发布例子吗? 【参考方案1】:

原答案

我在这里猜测“XML 日期格式”的意思是“2010-11-04T19:14Z”。其实是ISO 8601格式。

您可以使用 SimpleDateFormat 转换它,正如其他人建议的那样,FastDateFormat 或使用 Joda Time 我相信这是专门为 this purpose 创建的。

编辑:代码示例等

正如 earnshae 在评论中所述,可以通过示例改进此答案。

首先,我们必须明确原始答案已经过时了。这是因为 Java 8 引入了用于操作日期和时间的类 - java.time 包应该很有趣。如果您有幸使用 Java 8,您应该使用其中之一。然而,这些事情很难做到。

LocalDate(Time) 不是

考虑这个例子:

LocalDateTime dateTime = LocalDateTime.parse("2016-03-23T18:21");
System.out.println(dateTime); // 2016-03-23T18:21

起初,我们在这里使用的似乎是本地的(对于用户日期和时间)。但是,如果你敢问,你会得到不同的结果:

System.out.println(dateTime.getChronology()); // ISO

这实际上是 ISO 时间。我相信它应该读作“UTC”,但它没有本地时区的概念。所以我们应该认为它是通用的。 请注意,我们正在解析的字符串末尾没有“Z”。如果您添加日期和时间以外的任何内容,您将收到java.time.format.DateTimeParseException。所以如果我们要解析ISO8601字符串,这个类似乎没有用。

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

这里唯一的问题是,您实际上需要使用时区指定。尝试解析原始日期时间(即“2016-03-23T18:21”)将导致已经提到的RuntimeException。根据具体情况,您必须在 LocalDateTimeZonedDateTime 之间进行选择。 当然你可以很容易地在这两者之间进行转换,所以这应该不是问题:

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]

我现在推荐使用这个类。但是,如果您的工作描述包括考古学(这意味着您没有足够的运气使用超过 2 年的 Java 8...),您可能需要使用其他内容。

SimpleDateFormat 的乐趣

我不是 https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html 的忠实粉丝,但有时您别无选择。问题是,它不是线程安全的,如果它不喜欢某些东西,它会在你的脸上抛出一个选中的Exception(即ParseException)。所以sn-p的代码比较难看:

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 是同步的,因此您至少可以摆脱同步块。但是,它是外部依赖项。但是因为它是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);

乔达时间

使用 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

不幸的是,无论您在最后一个位置(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

现在一切都会好的。请注意,与其他答案之一不同,我使用了 dateTimeParser()not dateTime()。我注意到它们之间的行为存在细微但重要的差异(Joda-Time 2.9.2)。但是,我把它留给读者测试和确认。

【讨论】:

+1 用于 Joda Time 参考,这是一个比 SimpleDateFormat 更好的解决方案,SimpleDateFormat 充满危险 是的,这就是我要找的。干杯安德斯。 @Gary Rowe - 为什么它充满了?去年我一直在使用它,并且非常讨厌 Java 日期和时间的所有内容。我们公司有自己的 GregorianCalendar 包装器,每次实例化时总是调用 TimeZone.setDefault("...") 。我从来没有写过它,只需要使用它或围绕它工作:-( 这个答案如果附上代码会更好。【参考方案2】:

如前所述,使用 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);

我的猜测是您要查找的格式/模式是 yyyy-MM-dd'T'HH:mm:ss 也可以看看http://www.w3schools.com/schema/schema_dtypes_date.asp

【讨论】:

【参考方案3】:

使用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

线程安全、不可变且简单。

【讨论】:

【参考方案4】:

Perfect 方法,使用 XMLGregorianCalendar:

GregorianCalendar calendar = new GregorianCalendar();
calendar.setTime(v);
DatatypeFactory df = DatatypeFactory.newInstance();
XMLGregorianCalendar dateTime = df.newXMLGregorianCalendar(calendar);
return dateTime.toString();

【讨论】:

【参考方案5】:

只需在 java 中使用 SimpleDateFormat,我们就可以做到这一点......

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
Date date = sdf.parse("2011-12-31T15:05:50+1000");

【讨论】:

【参考方案6】:

我建议使用 java 内置类 javax.xml.bind.DatatypeConverter。它可以处理与大多数 xml 简单类型之间的转换。对于必须通过 Calendar 对象的日期来说,这有点麻烦,但另一方面,它处理可能出现在 xml datetime 字段中的所有区域信息变体。

来自 xml:

    Calendar c = DatatypeConverter.parseDateTime("2015-10-21T13:25");
    Date d = c.getTime();

到xml:

    Date yourDate = new Date()
    Calendar c = Calendar.getInstance();
    c.setTime(yourDate);
    String xmlDateTime = DatatypeConverter.printDateTime(c);

编辑

DatatypeConverter 类在 Java 9 及更高版本中不再公开可见,因为它属于 javax.xml.bind 包。有关更多信息和可能的解决方案,请参阅this question。 loic vaugeois 提出的使用 XmlGregorianCalendar 的解决方案在这种情况下要好得多。

【讨论】:

【参考方案7】:

您可以使用 SimpleDateFormat 解析和格式化任何格式的日期

【讨论】:

【参考方案8】:

要符合 ISO8601,时区必须采用 +HH:MM 或 - HH:MM 格式

对于 Simpledateformat,您必须使用 XXX 而不是 Z(请参阅 NovelGuy 答案)

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");

【讨论】:

【参考方案9】:

在不确切知道您需要什么格式的情况下,一般的回答是:您将需要 DateFormat 或 SimpleDateFormat。 here 都有很好的教程。

【讨论】:

以上是关于将 Java 日期转换为 XML 日期格式(反之亦然)的主要内容,如果未能解决你的问题,请参考以下文章

如何将 df 中的列转换为具有日期时间格式的纪元,反之亦然?

如何将日期格式QQ-YYYY转换为日期时间对象[重复]

将日期从 xml 转换为可读格式

在格鲁吉亚(基督教)日期转换为波斯日期,反之亦然

将日期转换为字符串,反之亦然返回错误消息

java中如何将字符串转换成日期型