Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

micronaut convert request param to Instant or ZonedDateTime

Tags:

micronaut

I am using Micronaut 1.3.4 and I am trying to convert an input to an Instant. I tried in many ways until now but without success. The following code shows just two cases I tried and neither worked.

I would like to convert the input date to either Instant or OffsetDateTime

    @Get("/...")
    public List<Obj> method(
//            @Format("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
//                    Instant startDateTime,
            @Format("yyyy-MM-dd")
                    LocalDate endDateTime
    ) {

I would like to use ISO 8601 if possible.

inputs I tried with:

2013-02-04
2013-02-04T22:44:30.652Z
...

The output I get is:

"message": "Required argument [LocalDate endDateTime] not specified",

My fallback is:

        String startDateTime

        Instant parse = Instant.parse(startDateTime);
        OffsetDateTime parse = OffsetDateTime.parse(startDateTime);

But I would still like to know how to do it with Micronaut.

like image 446
tzortzik Avatar asked Oct 17 '25 19:10

tzortzik


2 Answers

Here is an example of how you can pass LocalDateTime as a query parameter in Micronaut:

@Get("/local")
public String local(@Format("yyyy-MM-dd'T'HH:mm:ss") @QueryValue LocalDateTime time) {
    return "Time " + DateTimeFormatter.ISO_DATE_TIME.format(time);
}

Example curl call with the result:

$ curl http://localhost:8080/example/local?time=2020-04-13T21:13:59
Time 2020-04-13T21:13:59

You can use LocalDateTime when the time zone is always the same. And you can convert it into Instant like this time.atZone(ZoneId.systemDefault()).toInstant().

When the time zone can be different and must be part of the input time, then you can use ZonedDateTime parameter like this:

@Get("/zoned")
public String method(@Format("yyyy-MM-dd'T'HH:mm:ss.SSSZ") @QueryValue ZonedDateTime time) {
    return "Time " + DateTimeFormatter.ISO_DATE_TIME.format(time);
}

Where conversion into Instant is simle: time.toInstant()

Example curl call with the result:

$ curl http://localhost:8080/example/zoned?time=2020-04-13T21:13:59.123-0100
Time 2020-04-13T21:13:59.123-01:00

When you enter the time query parameter in a bad format (missing fraction of seconds and zone offset here) then it behaves like this:

$ curl http://localhost:8080/example/zoned?time=2020-04-13T21:13:59
{"message":"Required QueryValue [time] not specified","path":"/time","_links":{"self":{"href":"/example/zoned?time=2020-04-13T21:13:59","templated":false}}}

You can also use time as a part of the request path:

@Get("/local/{time}")
public String local(@Format("yyyy-MM-dd'T'HH:mm:ss") LocalDateTime time) {
    return "Time from request path " + DateTimeFormatter.ISO_DATE_TIME.format(time);
}

Then the example curl call will be:

$ curl http://localhost:8080/example/local/2020-04-13T21:13:59
Time from request path 2020-04-13T21:13:59

When you enter the time in path in a bad format (unwanted fraction of seconds here) then it behaves like this:

$ curl http://localhost:8080/example/local/2020-04-13T21:13:59.111
{"message":"Failed to convert argument [time] for value [2020-04-13T21:13:59.111] due to: Text '2020-04-13T21:13:59.111' could not be parsed, unparsed text found at index 19","path":"/time","_links":{"self":{"href":"/example/local/2020-04-13T21:13:59.111","templated":false}}}
like image 182
cgrim Avatar answered Oct 20 '25 15:10

cgrim


There is also another way of doing this. The @Formatannotation is problematic because it can't support all of the formats that the java classes such as OffsetDateTime and ZonedDateTime support.

If you have for example this method:

@Get("/local")
public String local(@QueryValue OffsetDateTime time) {
    return "Time " + time.toString();
}

To make it support ISO8601, modify your Application.java (or create a new class) containing:

@Context
public class Application {

    public static void main(String[] args) {
        // starts micronaut
    }

    @PostConstruct
    public void addPathConverter(ConversionService<DefaultConversionService> conversionService) {
        conversionService.addConverter(String.class, OffsetDateTime.class, (in) ->
                OffsetDateTime.parse(in));
    }
}
like image 33
pbthorste Avatar answered Oct 20 '25 15:10

pbthorste