Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring @RequestParam DateTime format as ISO 8601 Date Optional Time

I'm using Spring Framework for my services API and org.joda.time.DateTime for datetime parsing. Specifically, I'm using the ISOFormatter.dateOptionalTimeParser(), which allows users the flexibility to use just the date, or both date and time, which is a requirement.

Believe me, I've seen all these related questions that I can already tell people are going to point me towards, e.g. this and this, etc.

Previously, I was taking the date as String and then processing it using the joda formatter mentioned above in the service layer, but now I want to add request validation in the controller, which means that if the request is syntactically incorrect, the request shouldn't even go to the service layer.

I've tried using multiple variations of @DateTimeFormat(iso = ISO.DATE_TIME), as well as specifying the pattern String in format thing with no luck, whatsoever.

@RequestMapping(value = URIConstants.TEST_URL, method = RequestMethod.GET)
public @ResponseBody String getData(@RequestParam(required = false) DateTime from,
                                    @RequestParam(required = false)  DateTime to)  {
    return dataService.fetchDataFromDB(from, to);
}

What should I do to ensure that the date I get from user complies with the ISO 8601 dateOptionalTime format? Can I maybe apply multiple patterns to implement this?

like image 769
ystark Avatar asked Apr 19 '16 06:04

ystark


People also ask

How do I format a date in ISO 8601?

ISO 8601 represents date and time by starting with the year, followed by the month, the day, the hour, the minutes, seconds and milliseconds. For example, 2020-07-10 15:00:00.000, represents the 10th of July 2020 at 3 p.m. (in local time as there is no time zone offset specified—more on that below).


2 Answers

You can also create a converter and that will take care of it. I have used OffsetDateTime in the example below, but that can be easily replaced with LocalDateTime. For a detailed article, refer this url - http://www.baeldung.com/spring-mvc-custom-data-binder

Even I was struggling with this for sometime and it wasn't working. The trick is to use the @Component annotation and did it for me.

import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;

import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;

@Component
public class OffsetDateTimeConverter implements Converter<String, OffsetDateTime> {

    @Override
    public OffsetDateTime convert(final String source) {

        if (source == null || source.isEmpty()) {
            return null;
        }

        return OffsetDateTime.parse(source, DateTimeFormatter.ISO_OFFSET_DATE_TIME);
    }
}
like image 170
divinedragon Avatar answered Oct 22 '22 09:10

divinedragon


I ended up creating a POJO for this, where I parse the time from String using the ISODateTimeFormat.dateOptionalTimeParser():

public class DateOptionalTime {

    private DateTime date;

    private DateTimeFormatter formatter = ISODateTimeFormat.dateOptionalTimeParser();

    public DateOptionalTime() {
    }

    public DateOptionalTime(String date) {
        if (date != null) {
            this.setDate(formatter.parseDateTime(date));
        }
    }

    public DateTime getDate() {
        return date;
    }

    public void setDate(DateTime date) {
        this.date = date;
    }

    public LocalDateTime getLocalDateTime() {
        return date.toLocalDateTime();
    }


}

And in the controller, I used it like this:

@RequestMapping(value = URIConstants.TEST_URL, method = RequestMethod.GET)
public @ResponseBody String getData(@RequestParam(required = false) DateOptionalTime from,
                                    @RequestParam(required = false)  DateOptionalTime to)  {
    return dataService.fetchDataFromDB(from, to);
}

It validates the date format according to the ISO standard, and returns BAD_REQUEST status if the format is incorrect.

like image 3
ystark Avatar answered Oct 22 '22 08:10

ystark