Wrong timezone in XMLGregorian calendar

I am using the below code to set a XMLGregorianCalendar field in webservice

SimpleDateFormat format = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss");
Date dateOfBirth = null;
try {
    dateOfBirth = format.parse(adult.getDob_day() + "-" + adult.getDob_month() + "-"
                               + adult.getDob_year() + " 00:00:00");
} catch (Exception e) {
    log.error("Error while parsing dateOfBirth. Cause " + e.getMessage());
              e.printStackTrace();
}
passenger.setDateOfBirthField(convertToXMLCalendar(dateOfBirth));

The method convertToXMLCalendar is as below

private XMLGregorianCalendar convertToXMLCalendar(Date date) {

    XMLGregorianCalendar xmlCalendar = null;
    GregorianCalendar calendar = new GregorianCalendar();

    if (date != null) {
        try {
            calendar.setTime(date);
            xmlCalendar = DatatypeFactory.newInstance().newXMLGregorianCalendar(calendar);
        } catch (Exception e) {
            log.error("Error while converting to XMLGregorianCalendar. Cause " + e.getMessage());
    //      e.printStackTrace();
        }
    }
    return xmlCalendar;
}

My server location timezone is +03:00. But in few random scenarios the timezone is being send as +04:00 in SOAP request.

<ns7:dateOfBirthField>1955-08-27T00:00:00.000+04:00</ns7:dateOfBirthField>

Due to this the service is receiving the date as one day lesser than actual date. If I send 03-06-2014 00:00:00 its reaching the service as 02-06-2014 11:00:00.

If I set the time as 12:00:00 instead of 00:00:00 will it fix the issue. But whats the reason for this timezone change?

Jon Skeet
people
quotationmark

Your SimpleDateFormat doesn't specify a time zone, so it's using your local time zone. I would suggest:

  • Not parsing a value at all. You've got the individual day, month and year - so use that directly with a calendar!
  • Pass a Calendar to convertToXMLCalendar instead of a date... if you need to at all (see below)
  • Specify the time zone of the calendar as UTC if you really want to... although fundamentally I'd expect a dateOfBirth value to be just a date, to be honest, e.g. 1955-08-27. That way you're not specifying a time zone at all.

In fact, given that you've got the year/month/day, I'd just create an XMLGregorianCalendar directly from those values:

XMLGregorianCalendar calendar = DatatypeFactory.newInstance()
    .newXMLGregorianCalendar(adult.getDob_year(),
                             adult.getDob_month(),
                             adult.getDob_day(),
                             DatatypeConstants.FIELD_UNDEFINED); // No time zone

Then you're representing a date rather than a dateTime, which is what fits your data.

people

See more on this question at Stackoverflow