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

我有一个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 ,但当原始日期错误时似乎没有引发异常。

有什么办法可以做到吗? 我的猜测是告诉JAXB在global.jaxb文件中以正确的方式做到这global.jaxb ,这里是我现在使用的一个:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jaxb:bindings version="2.0" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
               xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" xmlns:xs="http://www.w3.org/2001/XMLSchema"
               jaxb:extensionBindingPrefixes="xjc">
    <jaxb:globalBindings>
        <xjc:simple/>
        <xjc:serializable uid="-1"/>
        <jaxb:javaType name="java.util.Calendar" xmlType="xs:dateTime"
                       parseMethod="javax.xml.bind.DatatypeConverter.parseDateTime"
                       printMethod="javax.xml.bind.DatatypeConverter.printDateTime"/>
    </jaxb:globalBindings>
</jaxb:bindings>

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


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

要确定无效的日期时间字符串,请尝试解析并捕获异常。 鉴于你的输入有一个从UTC的偏移量,但不是时区,解析为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教程。 并搜索堆栈溢出了很多例子和解释。 规范是JSR 310。

何处获取java.time类?

  • Java SE 8Java SE 9和更高版本
  • 内置。
  • 带有捆绑实现的标准Java API的一部分。
  • Java 9增加了一些次要功能和修复。
  • Java SE 6Java SE 7
  • 大部分java.time功能都在ThreeTen-Backport中移植到Java 6和7。
  • Android的
  • 后续版本的java.time类的Android捆绑实现。
  • 对于早期的Android, ThreeTenABP项目采用ThreeTen-Backport(上文提到)。 请参阅如何使用ThreeTenABP ...。
  • ThreeTen-Extra项目将java.time扩展到其他类。 这个项目是未来可能增加java.time的一个试验场。 您可以在这里找到一些有用的课程,例如IntervalYearWeekYearQuarter等。


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

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

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

    package com.app.adapter;
    public class MyDatetimeAdapter extends XmlAdapter<String, DateTime> {
        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绑定文件。

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema"
                   xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" jaxb:extensionBindingPrefixes="xjc" jaxb:version="2.1">
        <jaxb:globalBindings>
            <xjc:javaType adapter="com.app.adapter.MyDatetimeAdapter"
                          name="com.app.types.CustomDateTime" xmlType="xs:dateTime"/>
        </jaxb:globalBindings>
    </jaxb:bindings>
    
    链接地址: http://www.djcxy.com/p/3099.html

    上一篇: How to check if a Calendar instance was originally a wrong date

    下一篇: add days to date string using date.tocalender function