如何检查Calendar实例最初是否是错误的日期

我有一个Calendar实例,通过JAXB的javax.xml.bind.DatatypeConverter.parseDateTime方法从XSD datetime解析。

在运行时,我在一个Web服务,我想知道原始xsd日期时间是否有效(月<12,日期<31,30,29,28,根据月…等)。 示例:这是有效日期: 2015-07-30T09:32:05.543+02:00 ,这不是: 2015-07-35T09:32:05.543+02:00

我试图在Web服务的实例上使用setLenient ,但是当原始日期错误时它似乎没有引发exception。

有什么办法吗? 我的猜测是告诉JAXB在global.jaxb文件中以正确的方式执行它,这是我现在使用的那个:

         

任何帮助,将不胜感激。 谢谢。

TL;博士

 OffsetDateTime.parse( "2015-07-35T09:32:05.543+02:00" ) … catch ( DateTimeParseException e ) 

java.time

麻烦的旧日期时间类(如java.util.Datejava.util.Calendarjava.text.SimpleDateFormat现在已成为遗留问题 ,取而代之的是Java 8和Java 9中内置的java.time类。

同样, Joda-Time项目现在处于维护模式 ,团队建议迁移到java.time类。

OffsetDateTimeDateTimeParseException

要确定无效的日期时间字符串,请尝试解析并捕获exception。 假设您的输入具有从UTC而不是时区的偏移量, OffsetDateTime解析为OffsetDateTime对象。 无效的输入抛出DateTimeParseException

 String inputGood = "2015-07-30T09:32:05.543+02:00" ; String inputBad = "2015-07-35T09:32:05.543+02:00" ; try{ // Good OffsetDateTime odtGood = OffsetDateTime.parse( inputGood ) ; System.out.println( "odtGood.toString(): " + odtGood ) ; // Bad OffsetDateTime odtBad = OffsetDateTime.parse( inputBad ) ; System.out.println( "odtBad.toString(): " + odtBad ) ; } catch ( DateTimeParseException e ) { System.out.println( e ) ; } 

请参阅IdeOne.com上的现场代码 。

odtGood.toString():2015-07-30T09:32:05.543 + 02:00

java.time.format.DateTimeParseException:无法解析文本’2015-07-35T09:32:05.543 + 02:00’:DayOfMonth的值无效(有效值1 – 28/31):35


关于java.time

java.time框架内置于Java 8及更高版本中。 这些类取代了麻烦的旧遗留日期时间类,如java.util.DateCalendarSimpleDateFormat

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

要了解更多信息,请参阅Oracle教程 。 并搜索Stack Overflow以获取许多示例和解释。 规范是JSR 310 。

从哪里获取java.time类?

  • Java SE 8Java SE 9及更高版本
    • 内置。
    • 带有捆绑实现的标准Java API的一部分。
    • Java 9增加了一些小function和修复。
  • Java SE 6Java SE 7
    • 许多java.timefunction都被反向移植到ThreeTen-Backport中的 Java 6和7。
  • Android的
    • 更高版本的Android捆绑java.time类的实现。
    • 对于早期的Android, ThreeTenABP项目采用ThreeTen-Backport (如上所述)。 请参见如何使用ThreeTenABP ….

ThreeTen-Extra项目使用其他类扩展了java.time。 该项目是未来可能添加到java.time的试验场。 您可以在这里找到一些有用的课程,如IntervalYearWeekYearQuarter等。

我通过在自定义JAXB绑定文件中使用JodaTime的ISODateTimeFormat#dateTimeParser()和自定义适配器解决了我的问题。 JodaTime是比Calendar标准Java API好得多的API,默认情况下它不宽松。

我可以为Calendar做同样的事情,但我应该自己定义所有格式,JodaTime已经定义了它们。

这里是我做的代码示例(它也回答了我的另一个问题: 检查xsd datetime在转换为Java对象之前是否有定义的时区 )

 package com.app.adapter; public class MyDatetimeAdapter extends XmlAdapter { private final static DateTimeFormatter DATETIME_FORMATTER = ISODateTimeFormat.dateTime(); private final static Pattern TIMEZONE_PATTERN = Pattern.compile("(\\+|\\-)[0-9]{2}:[0-9]{2}$"); @Override public DateTime unmarshal(String string) throws Exception { string = string.trim(); try { DateTime tmp = ISODateTimeFormat.dateTimeParser().parseDateTime(string); if (string.charAt(string.length()-1) == 'Z' || TIMEZONE_PATTERN.matcher(string).find()) { return new CustomDateTime(tmp); } return new CustomDateTime(tmp, CustomDateTime.Error.NO_TIMEZONE); } catch (IllegalArgumentException e) { return new CustomDateTime(null, CustomDateTime.Error.INVALID); } } @Override public String marshal(CustomDateTime date) throws Exception { return DATETIME_FORMATTER.print(date.getDateTime()); } } 

这里是CustomDateTime(包装JodaTime的DateTime和错误代码的POJO)

 package com.app.types; public final class CustomDateTime { private DateTime dateTime; private Error error; // getter .. setters .. constructor public static CustomDateTime getInstance(Error error) { return new CustomDateTime(DateTime.now(), error); } public static CustomDateTime getInstance() { return getInstance(Error.NONE); } public enum Error { NONE, NO_TIMEZONE INVALID; } } 

最后,JAXB绑定文件。