Coder
Coder

Reputation: 33

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

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!

Upvotes: 0

Views: 91

Answers (2)

Basil Bourque
Basil Bourque

Reputation: 338181

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 ) ;

Upvotes: 1

VGR
VGR

Reputation: 44292

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);

Upvotes: 0

Related Questions