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.
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}}}
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));
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With