IS there an easy way to add 5 days delay to XMLGregorianCalendar date?

71 Views Asked by At

I want to add 5 days delay to XMLGregorianCalendar date (date is coming from json request). I tried converting it first to LocalDateTime as follows, this works

LocalDateTime date = request.getDate().toGregorianCalendar().toZonedDateTime().toLocalDateTime().plusDays(5);
Timestamp ts = Timestamp.valueOf(date);

Another approach I tried was as follows, which is throwing below error

Timestamp date = DateUtil.convertToTimestamp(request.getDate().
                                           add(DatatypeFactory.newInstance().newDuration("P14D"));

Error:

Required type: XMLGregorianCalendar
Provided: void

Although, the LocalDateTime one does not give any errors, I am just wondering if there's an easy way to do this. Any help would be appreciated. Thanks in advance!

2

There are 2 best solutions below

0
On

Don’t use the Timestamp class. It doesn’t do what you think it does. In fact, it doesn’t even do what it was originally intended to do all that well (represent a particular SQL type).

Just use the add method of GregorianCalendar:

XMLGregoriantCalendar xcal = request.getDate();

GregorianCalendar gcal = xcal.toGregorianCalendar();
gcal.add(Calendar.DATE, 5);

xcal = DatatypeFactory.newInstance().newXMLGregorianCalendar(gcal);
0
On

tl;dr

XMLGregorianCalendar ➡️ GregorianCalendar ➡️ ZonedDateTime ➡️ OffsetDateTime

myPreparedStatement
.setObject( 
    … , 
    myXMLGregorianCalendar
    .toGregorianCalendar()
    .toZonedDateTime() 
    .plusDays( 5 )
    .toOffsetDateTime()
)

Avoid legacy date-time classes

When handed a legacy date-time object like XMLGregorianCalendar, immediately convert to the modern java.time classes. In java.time, the replacement class is ZonedDateTime.

To get to ZonedDateTime, go though another legacy class, GregorianCalendar.

ZonedDateTime zdt = myXMLGregorianCalendar.toGregorianCalendar().toZonedDateTime() ;

Add days

Add five days. Adjustments are automatically made for anomalies such as Daylight Saving Time (DST).

ZonedDateTime fiveDaysLater = zdt.plusDays( 5 ) ;

LocalDateTime is not a moment

Do not use LocalDateTime at all in this situation. That class lacks the context of an offset or time zone, so it cannot be used to represent a moment, a specific point on the timeline.

Database

If you are trying to write this value to a database, do not use the legacy Timestamp class. Use only java.time classes. To communicate a moment to a database, use java.time.OffsetDateTime.

OffsetDateTime odt = fiveDaysLater.toOffsetDateTime() ;
myPreparedStatement.setObject( … , odt ) ;

Retrieval.

OffsetDateTime odt = myResultSet.getObject ( … , OffsetDateTime.class ) ;
ZoneId zoneId = ZoneId.of( "Asia/Tokyo"" ) ;
ZonedDateTime zdt = odt.atZoneSameInstant( zoneId ) ;