如何检查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.Date
, java.util.Calendar
和java.text.SimpleDateFormat
现在已成为遗留问题 ,取而代之的是Java 8和Java 9中内置的java.time类。
同样, Joda-Time项目现在处于维护模式 ,团队建议迁移到java.time类。
OffsetDateTime
和DateTimeParseException
要确定无效的日期时间字符串,请尝试解析并捕获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.Date
, Calendar
和SimpleDateFormat
。
现在处于维护模式的Joda-Time项目建议迁移到java.time类。
要了解更多信息,请参阅Oracle教程 。 并搜索Stack Overflow以获取许多示例和解释。 规范是JSR 310 。
从哪里获取java.time类?
- Java SE 8 , Java SE 9及更高版本
- 内置。
- 带有捆绑实现的标准Java API的一部分。
- Java 9增加了一些小function和修复。
- Java SE 6和Java SE 7
- 许多java.timefunction都被反向移植到ThreeTen-Backport中的 Java 6和7。
- Android的
- 更高版本的Android捆绑java.time类的实现。
- 对于早期的Android, ThreeTenABP项目采用ThreeTen-Backport (如上所述)。 请参见如何使用ThreeTenABP ….
ThreeTen-Extra项目使用其他类扩展了java.time。 该项目是未来可能添加到java.time的试验场。 您可以在这里找到一些有用的课程,如Interval
, YearWeek
, YearQuarter
等。
我通过在自定义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绑定文件。