Search code examples
javadatetimetimezone-offsetdatetimeoffsetxmlgregoriancalendar

My xmlGregorianCalendar coming with offset value ..how to adjust it? in java


My xmlGregorianCalendar value coming as 2020-10-02T13:07:38-06:00 .. I want to pass thisxmlGregorianCalendar value and get the output like 2020-10-02T07:07:38(which reduces 6 hours from the time) any suggestion on this please?

I have used this below method.

return new Timestamp(xmlGregorianCalendar.toGregorianCalendar(TimeZone.getTimeZone("GMT"),null,null).getTimeInMillis())..

But it removing the off set value but not adjusting the time. the output i am getting is 2020-10-02T13:07:38..But i am expecting the 2020-10-02T07:07:38 like this.


Solution

  • First of all, I recommend you switch from the outdated and error-prone java.util date-time API to the modern java.time date-time API. Learn more about the modern date-time API from Trail: Date Time.

    Your understanding of Zone-Offset is not correct

    The date-time string, 2020-10-02T13:07:38-06:00 tells us that the given date and time has been adjusted with an offset of -06:00 hours from UTC i.e. the corresponding date-time at UTC would be 2020-10-02T19:07:38Z where Z specifies a Zone-Offset of 00:00 hours.

    It means that if you are expecting a date-time of 2020-10-02T07:07:38, you need to offset the given date-time further by -06:00 hours i.e. it will be at a total of -12:00 hours offset from UTC.

    The following example illustrates this concept:

    import java.time.OffsetDateTime;
    import java.time.ZoneOffset;
    import java.time.format.DateTimeFormatter;
    
    public class Main {
        public static void main(String[] args) {
            OffsetDateTime odtGiven = OffsetDateTime.parse("2020-10-02T13:07:38-06:00");
            System.out.println(odtGiven);
    
            // Date and time at Zone-Offset of 00:00 hours
            OffsetDateTime odtUTC = odtGiven.withOffsetSameInstant(ZoneOffset.UTC);
            System.out.println(odtUTC);
    
            // Date and time at Zone-Offset of -12:00 hours
            OffsetDateTime odtDerived = odtGiven.withOffsetSameInstant(ZoneOffset.of("-12:00"));
            System.out.println(odtDerived);
    
            // Get the date-time string in the format with Zone-Offset dropped
            String strDateTimeZoneOffsetDropped = odtDerived.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
            System.out.println(strDateTimeZoneOffsetDropped);
        }
    }
    

    Output:

    2020-10-02T13:07:38-06:00
    2020-10-02T19:07:38Z
    2020-10-02T07:07:38-12:00
    2020-10-02T07:07:38
    

    Using the legacy API:

    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.TimeZone;
    
    import javax.xml.datatype.DatatypeConfigurationException;
    import javax.xml.datatype.DatatypeFactory;
    import javax.xml.datatype.XMLGregorianCalendar;
    
    public class Main {
        public static void main(String[] args) throws DatatypeConfigurationException, ParseException {
            String givenDateTimeString = "2020-10-02T13:07:38-06:00";
            XMLGregorianCalendar xmlGregorianCalendar = DatatypeFactory.newInstance()
                    .newXMLGregorianCalendar(givenDateTimeString);
            System.out.println(xmlGregorianCalendar);
    
            // Derive the date-time string at Zone-Offset of UTC-12:00 hours
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
            sdf.setTimeZone(TimeZone.getTimeZone("GMT-12:00"));
            Date date = xmlGregorianCalendar.toGregorianCalendar().getTime();
            String derivedDateTimeString = sdf.format(date);
            System.out.println(derivedDateTimeString);
        }
    }
    

    Output:

    2020-10-02T13:07:38-06:00
    2020-10-02T07:07:38