简体   繁体   中英

from XMLGregorianCalendar to Date/Calendar adds extra time/unwanted

I'm developing a client to a web service which exposes (.wsdl) contract, which requires yyyy-MM-dd format for 1 on the request parameters , however auto generated POJOS based on the .wsdl create the date attribute as Type XMLGregorianCalendar.


My issue is NOT converting to or from XMLGregorianCalendar see my utility below:

public static XMLGregorianCalendar toXMLGregorianCalendar(Calendar c){
 GregorianCalendar gc = new GregorianCalendar();
 gc.setTimeInMillis(c.getTimeInMillis());
 XMLGregorianCalendar xc= null;
try {
    xc = DatatypeFactory.newInstance().newXMLGregorianCalendar(gc);
} catch (DatatypeConfigurationException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}
 return xc;
}

My issue is going from XMLGregorianCalendar to Date/Calendar adds extra time/unwanted data to my yyyy-MM-dd when calling calendar.getTime();

In a particular code segment I need to go from XMLGregorianCalendar to Date

if (repairOrderType.getCloseDate() != null) {

                LOG.debug("ServiceHistoryMapper, processRepairOrders() , repairOrderType.getCloseDate() BEFORE:"
                        + repairOrderType.getCloseDate());
                String date = repairOrderType.getCloseDate().getYear() + "-"
                        + repairOrderType.getCloseDate().getMonth() + "-"
                        + repairOrderType.getCloseDate().getDay();

                //Approach #1, trying to remove hour,minute,sec values by calendar.clear() method , not successful 
                Calendar calendar = Calendar.getInstance();
                calendar.set(repairOrderType.getCloseDate().getYear(),
                        repairOrderType.getCloseDate().getMonth(),
                        repairOrderType.getCloseDate().getDay());
                calendar.clear(Calendar.HOUR);
                calendar.clear(Calendar.MINUTE);
                calendar.clear(Calendar.SECOND);
                calendar.clear(Calendar.MILLISECOND);



                /*Approach#2 , trying to remove hour,minute,sec values using SimpleDateFormat ,
                 * also not successful. SimpleDateFormat or DateFormat are use to format String output NOT remove internal data
                 *
                DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
                Calendar calendar = formatter.getCalendar();
                calendar.set(repairOrderType.getCloseDate().getYear(),
                repairOrderType.getCloseDate().getMonth(),
                repairOrderType.getCloseDate().getDay());
                */

                LOG.debug("ServiceHistoryMapper, processRepairOrders() , repairOrderType.getCloseDate() AFTER:"
                        + calendar.getTime());
                repairOrder.setCloseDate(calendar.getTime());

            }

Output:

27-Nov-2012 18:10:39.743 DEBUG com.tms.owners.integration.nsh.mapping.ServiceHistoryMapper - ServiceHistoryMapper, processRepairOrders() , repairOrderType.getCloseDate() BEFORE:2012-04-30

27-Nov-2012 18:10:51.413 DEBUG com.tms.owners.integration.nsh.mapping.ServiceHistoryMapper - ServiceHistoryMapper, processRepairOrders() , repairOrderType.getCloseDate() AFTER:Wed May 30 18:00:00 PDT 2012

As you can see above BEFORE date is BEFORE:2012-04-30 and AFTER date is May 30 18:00:00 PDT 2012 with unwanted hours "18:00:00 PDT".


Below is my actual request XML sent to the service:

<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
    <S:Body>
        <ns4:VehicleServiceHistoryDetails
            xmlns="urn:tms.toyota.com/Components" xmlns:ns2="urn://esb.ari.xxxxxx.com/2008/12/10/schemas/common/Customer"
            xmlns:ns3="urn:incentives.ari.xxxxxx.com/StandardHeader"
            xmlns:ns4="urn://esb.ari.xxxxxx.com/2008/12/10/schemas/History"
            xmlns:ns5="http://ice.ari.xxxxxx.com/EMF" xmlns:ns6="urn:ari.xxxxxx.com/rtmheader">
            <ns5:ApplicationArea>
                <ns5:CreationDateTime>2012-11-27T18:11:23.071-08:00
                </ns5:CreationDateTime>
                <ns5:Sender />
                <ns5:UserArea />
            </ns5:ApplicationArea>
            <ns4:VehicleServiceHistoryDataArea>
                <ns4:VehicleServiceHistoryHeader>
                    <ns3:TimeStamp>2012-11-27T18:11:23.071-08:00</ns3:TimeStamp>
                    <ns3:SourceSystem>TOO</ns3:SourceSystem>
                    <ns4:SourceKey>TOY1TWXE</ns4:SourceKey>
                </ns4:VehicleServiceHistoryHeader>
                <ns4:VehicleServiceHistory>
                    <ns4:VIN>XXXXXXXXXXXXXXXX</ns4:VIN>
                    <ns4:RepairOrder>
                        <ns2:RepairOrderDealer>
                            <DealerNumber>29059</DealerNumber>
                        </ns2:RepairOrderDealer>
                        <ns2:RepairOrderNumber>0088745</ns2:RepairOrderNumber>
                        <ns2:CloseDate>2012-05-30-07:00</ns2:CloseDate>
                    </ns4:RepairOrder>
                </ns4:VehicleServiceHistory>
            </ns4:VehicleServiceHistoryDataArea>
        </ns4:VehicleServiceHistoryDetails>
    </S:Body>
</S:Envelope>

You can see in the request xml in the 2012-05-30-07:00 that extra "-07:00" data is added i just want 2012-05-30.

Thanks

The in context of XML datatypes the XMLGregorianCalendar is created via factory methods in javax.xml.datatype.DatatypeFactory which seems to have a method called newXMLGregorianCalendarDate(int year, int month, int day, int timezone);


So I created a utility method :

public static XMLGregorianCalendar toXMLGregorianCalendarDateOnly(Calendar c){
     GregorianCalendar gc = new GregorianCalendar();
     gc.setTimeInMillis(c.getTimeInMillis());
     XMLGregorianCalendar xc= null;
    try {
        xc = DatatypeFactory.newInstance().newXMLGregorianCalendarDate(gc.get(Calendar.YEAR),Calendar.MONTH,Calendar.DAY_OF_MONTH,DatatypeConstants.FIELD_UNDEFINED);
    } catch (DatatypeConfigurationException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
     return xc;
    }

The issue is resolved now, we are getting the desired yyyy-MM-ddd.

You can also write it in a following manner which is more readable:

GregorianCalendar gc = new GregorianCalendar();
gc.setTimeInMillis(c.getTimeInMillis());

XMLGregorianCalendar calendar = DatatypeFactory.newInstance().newXMLGregorianCalendar(gc);
calendar.setMillisecond(DatatypeConstants.FIELD_UNDEFINED);
calendar.setTimezone(DatatypeConstants.FIELD_UNDEFINED);

I used the below code to resolve the same problem.

public  static XMLGregorianCalendar toXMLGregorianCalendarWithoutTimeStamp(String date) {
        Date mDate = null;
        GregorianCalendar cal = new GregorianCalendar();
        XMLGregorianCalendar xmlGregorianCalendar;
        DateFormat df = new SimpleDateFormat("dd-MM-yyyy");
        try {
            mDate = df.parse(date);
            cal.setTime(mDate);
            xmlGregorianCalendar = DatatypeFactory.newInstance()
                    .newXMLGregorianCalendarDate(cal.get(Calendar.YEAR),
                            cal.get(Calendar.MONTH) + 1,
                            cal.get(Calendar.DAY_OF_MONTH),
                            DatatypeConstants.FIELD_UNDEFINED);
            return xmlGregorianCalendar;

        } catch (DatatypeConfigurationException e) {
            LOGGER.error("Error in getCustomerCDRResponse Date Formate Type Configuartion :: " + e);
        } catch (ParseException e) {
            LOGGER.error("Error in getCustomerCDRResponse Date Parsing :: " + e);
        }
        return null;
    }

try this.

Date dob=null;
    DateFormat df=new SimpleDateFormat("dd/MM/yyyy");
    dob=df.parse( "10/02/2014 11:15:00" );
    GregorianCalendar cal = new GregorianCalendar();

    cal.setTime(dob);
XMLGregorianCalendar xmlDate3 = DatatypeFactory.newInstance().newXMLGregorianCalendarDate(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH)+1, cal.get(Calendar.DAY_OF_MONTH),DatatypeConstants.FIELD_UNDEFINED);
System.out.println(xmlDate3);

If you are using javax.xml.bind.Marshaller to prepare SOAP body then the root of the unwanted bahavior is in yours xlmns:ns2. The field ns2:CloseDate is of type (or some other type wichich include date and time):

{http://www.w3.org/2001/XMLSchema}dateTime

change it to (or other date type without hour and minute):

{http://www.w3.org/2001/XMLSchema}date

If you don't manage this xlmns, just accept that yours CloseDate must have time defined. Without it called web service would have unapropiate time declaration (I don't know exactly value, but I'm bet on 0:00)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM