【问题标题】:How to compare XMLGregorianCalendar with only the Date portion (day, month, year)?如何仅将 XMLGregorianCalendar 与日期部分(日、月、年)进行比较?
【发布时间】:2013-02-20 11:07:30
【问题描述】:

我正在开发一个与spring-struts web应用程序集成的webservice,在XSD中有一个XMLGregorianCalendar类型的属性,假设属性名称是trxDate

在 SOAPUI 测试应用程序中,如果我将 trxDate 的值插入为:2013-02-21,然后我发送了soap xml 请求数据,并在服务方法中打印了该值:System. out.println(trxDate) 方法,打印结果与输入的相同:2013-02-21。

现在,我正在尝试创建一个函数来将 trxDate 与当前日期进行比较。我知道我们可以使用 trxDate.compare(currentDate) 方法进行比较。问题是我不如何创建 XMLGregorianCalendar 对象集,当前日期只有日期部分(日、月和年)用于比较。

我尝试使用此代码:

    GregorianCalendar gc = new GregorianCalendar();
    gc.set(GregorianCalendar.HOUR_OF_DAY, 0);
    gc.set(GregorianCalendar.MINUTE, 0);
    gc.set(GregorianCalendar.SECOND, 0);
    gc.set(GregorianCalendar.MILLISECOND, 0);

    XMLGregorianCalendar xgc = DatatypeFactory.newInstance().newXMLGregorianCalendar(gc);
    System.out.println(xgc);

结果是:
2013-02-20T00:00:00.000+07:00

但我期待:
2013-02-20

如果使用日期 (xgc) 与 trxDate 进行比较:

int result = trxDate.compare(xgc);

结果为 2,表示:INDETERMINATE(来自 DatatypeConstants 类)。正确的结果应该是 -1、0 或 1。

那么我的代码有什么问题?

【问题讨论】:

    标签: java web-services xsd jaxb gregorian-calendar


    【解决方案1】:

    与其尝试从GregorianCalendar 中清除不需要的字段,不如创建一个未初始化的XMLGregorianCalendar 然后只复制您确实想要的字段: p>

    XMLGregorianCalendar xgc = DatatypeFactory.newInstance().newXMLGregorianCalendar();
    GregorianCalendar now = new GregorianCalendar();
    xgc.setYear(now.get(Calendar.YEAR));
    xgc.setMonth(now.get(Calendar.MONTH) + 1);
    xgc.setDay(now.get(Calendar.DAY_OF_MONTH));
    System.out.println(xgc);
    

    如果您要使用newXMLGregorianCalendar(lexicalRepresentation),这避免了往返字符串和再次返回是必要的

    【讨论】:

    • 哇,我很困惑,有很多方法,你的方法和 Blaise 的方法哪个更好?
    • 我刚试了你的代码,有一点错误,你需要在xgc.setMonth()上加1,所以代码应该变成:xgc.setMonth(now.get(Calendar.MONTH)+1);。似乎 XMLGregorianCalendar 使用基于一个月的索引。
    【解决方案2】:

    javadoc for XMLGregorianCalendar.compare 解释说它使用rules from the XML Schema specification 进行比较,javadoc 链接到该比较。

    第 B.1 节。比较算法声明两个 dateTimes 必须具有完全相同的(子)集定义的 {年、月、日、小时、分钟、秒}字段。如果他们不这样做,结果是不确定的。 (XML Schema 规范在算法描述中使用<> 来表示不确定的结果。)

    因此,如果您有一个只定义了年、月和日的 XMLGregorianCalendar,那么您必须将它与另一个只定义了年、月和日的 XMLGregorianCalendar 进行比较。要么您必须按照 Blaise 的建议从字符串中解析它,要么您必须实例化一个 XMLGregorianCalendar 并自己调用 setYearsetMonthsetDay

    【讨论】:

    • 这是一个很好的答案,在我的书中。我遇到了这个问题,因为我正在比较 2 个 XMLGregorianCalendar 实例,但其中一个设置了时区。将它们转换为 GregorianCalendar 对象并使用 compareTo() 方法为我提供了我正在寻找的比较逻辑。否则,使用 XMLGregorianCalendar 的 compare() 方法将始终返回 DatatypeConstants.INDETERMINATE。
    【解决方案3】:

    更新

    您也可以通过这种方式创建您的XMLGregorianCalendar

        XMLGregorianCalendar xgc = df.newXMLGregorianCalendar(
                2012, 
                DatatypeConstants.FEBRUARY, 
                21, 
                DatatypeConstants.FIELD_UNDEFINED, 
                DatatypeConstants.FIELD_UNDEFINED, 
                DatatypeConstants.FIELD_UNDEFINED, 
                DatatypeConstants.FIELD_UNDEFINED, 
                DatatypeConstants.FIELD_UNDEFINED);
        System.out.println(xgc);
    

    您可以使用以下方法:

    • newXMLGregorianCalendar(String lexicalRepresentation)

    演示

    import javax.xml.datatype.*;
    
    public class Demo {
    
        public static void main(String[] args) throws Exception {
            DatatypeFactory df = DatatypeFactory.newInstance();
    
            XMLGregorianCalendar xgc = df.newXMLGregorianCalendar("2013-02-12");
            System.out.println(xgc);
        }
    
    }
    

    输出

    2013-02-12
    

    【讨论】:

    • 哇,我不知道有这样的方法,非常快速和简单。非常感谢。但我想知道如果使用我上面的代码方式,是否有可能达到相同的结果?
    • 哇,我很困惑,有很多方法,你的方法和伊恩的方法哪个更好?
    【解决方案4】:

    试试

        String str = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        XMLGregorianCalendar xgc = DatatypeFactory.newInstance().newXMLGregorianCalendar(str);
        System.out.println(xgc);
    

    这是对 XMLGregorianCalendar 使用 xsd:date 类型的提示(顺序),其中时间未定义

    【讨论】:

      【解决方案5】:

      如果有人仍在寻找替代方案。这符合我的要求。

          ...
      
          date.setTimezone(DatatypeConstants.FIELD_UNDEFINED);
          date.setTime(DatatypeConstants.FIELD_UNDEFINED,
                  DatatypeConstants.FIELD_UNDEFINED,
                  DatatypeConstants.FIELD_UNDEFINED,
                  DatatypeConstants.FIELD_UNDEFINED);
          ...
      

      这将删除时区和时间戳。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-09-11
        • 1970-01-01
        • 2013-05-10
        • 1970-01-01
        • 2013-09-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多