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

时间:2015-07-30 07:30:26

标签: java xml web-services parsing jaxb

我有一个Calendar实例,由JAX日期时间通过JAXB的javax.xml.bind.DatatypeConverter.parseDateTime方法解析。

在运行时,我在网络服务中,我想知道原始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文件中以正确的方式执行此操作,这是我现在使用的文件:

<?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>

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

2 个答案:

答案 0 :(得分:2)

TL;博士

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

java.time

麻烦的旧日期时间类,例如java.util.Datejava.util.Calendarjava.text.SimpleDateFormat现在是legacy,取而代之的是Java内置的java.time类8&amp; Java 9.

同样,Joda-Time项目现在位于maintenance mode,团队建议迁移到java.time类。

OffsetDateTime&amp; DateTimeParseException

要确定无效的日期时间字符串,请尝试解析并捕获异常。假设您的输入具有从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 ) ;
}

请参阅code run live at 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及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendar和&amp; SimpleDateFormat

现在位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310

从哪里获取java.time类?

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

答案 1 :(得分:1)

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

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

这是我制作的代码示例(它也回答了我的另一个问题:Check if xsd datetime had a defined timezone before conversion to Java object

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的日期时间和错误代码的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>