micronaut 将请求参数转换为 Instant 或 ZonedDateTime
micronaut convert request param to Instant or ZonedDateTime
我正在使用 Micronaut 1.3.4,我正在尝试将输入转换为 Instant。到目前为止,我尝试了很多方法但没有成功。以下代码仅显示了我尝试过但均无效的两种情况。
我想将输入日期转换为 Instant
或 OffsetDateTime
@Get("/...")
public List<Obj> method(
// @Format("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
// Instant startDateTime,
@Format("yyyy-MM-dd")
LocalDate endDateTime
) {
如果可能,我想使用 ISO 8601。
我试过的输入:
2013-02-04
2013-02-04T22:44:30.652Z
...
我得到的输出是:
"message": "Required argument [LocalDate endDateTime] not specified",
我的后备方案是:
String startDateTime
Instant parse = Instant.parse(startDateTime);
OffsetDateTime parse = OffsetDateTime.parse(startDateTime);
但我还是想知道如何用 Micronaut 来做。
下面是一个示例,说明如何在 Micronaut 中将 LocalDateTime
作为查询参数传递:
@Get("/local")
public String local(@Format("yyyy-MM-dd'T'HH:mm:ss") @QueryValue LocalDateTime time) {
return "Time " + DateTimeFormatter.ISO_DATE_TIME.format(time);
}
示例 curl 调用结果:
$ curl http://localhost:8080/example/local?time=2020-04-13T21:13:59
Time 2020-04-13T21:13:59
当时区始终相同时,您可以使用 LocalDateTime
。你可以把它转换成 Instant
像这样 time.atZone(ZoneId.systemDefault()).toInstant()
.
当时区可以不同并且必须是输入时间的一部分时,那么你可以像这样使用ZonedDateTime
参数:
@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);
}
转换成 Instant
很简单:time.toInstant()
示例 curl 调用结果:
$ curl http://localhost:8080/example/zoned?time=2020-04-13T21:13:59.123-0100
Time 2020-04-13T21:13:59.123-01:00
当您以错误的格式输入时间查询参数(此处缺少秒数和时区偏移)时,它的行为如下:
$ 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}}}
您也可以使用时间作为请求路径的一部分:
@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);
}
那么示例 curl 调用将是:
$ curl http://localhost:8080/example/local/2020-04-13T21:13:59
Time from request path 2020-04-13T21:13:59
当您以错误的格式在路径中输入时间(此处不需要几分之一秒)时,它的行为如下:
$ 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}}}
还有另一种方法可以做到这一点。 @Format
注释有问题,因为它不能支持 java class 等 OffsetDateTime 和 ZonedDateTime 支持的所有格式。
如果你有例如这个方法:
@Get("/local")
public String local(@QueryValue OffsetDateTime time) {
return "Time " + time.toString();
}
要使其支持 ISO8601,请修改您的 Application.java
(或创建一个新的 class),其中包含:
@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));
}
}
在 Micronaut 3 中推荐的解决这个问题的方法,具有以下灵活性
多种格式,通过添加自定义类型转换器。
OffsetDateTime
的示例实现可以是:
@Singleton
public class OffsetDateTimeConverter implements TypeConverter<String, OffsetDateTime> {
@Override
public Optional<OffsetDateTime> convert(String inputDateTime, Class<OffsetDateTime> targetType, ConversionContext context) {
if (inputDateTime != null) {
try {
var offsetDateTime = OffsetDateTime.parse(inputDateTime);
return Optional.of(offsetDateTime);
} catch (DateTimeParseException e) {
context.reject(inputDateTime, e);
}
}
return Optional.empty();
}
}
这可以在 3.2.7 documentation(和其他)中查看。
我正在使用 Micronaut 1.3.4,我正在尝试将输入转换为 Instant。到目前为止,我尝试了很多方法但没有成功。以下代码仅显示了我尝试过但均无效的两种情况。
我想将输入日期转换为 Instant
或 OffsetDateTime
@Get("/...")
public List<Obj> method(
// @Format("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
// Instant startDateTime,
@Format("yyyy-MM-dd")
LocalDate endDateTime
) {
如果可能,我想使用 ISO 8601。
我试过的输入:
2013-02-04
2013-02-04T22:44:30.652Z
...
我得到的输出是:
"message": "Required argument [LocalDate endDateTime] not specified",
我的后备方案是:
String startDateTime
Instant parse = Instant.parse(startDateTime);
OffsetDateTime parse = OffsetDateTime.parse(startDateTime);
但我还是想知道如何用 Micronaut 来做。
下面是一个示例,说明如何在 Micronaut 中将 LocalDateTime
作为查询参数传递:
@Get("/local")
public String local(@Format("yyyy-MM-dd'T'HH:mm:ss") @QueryValue LocalDateTime time) {
return "Time " + DateTimeFormatter.ISO_DATE_TIME.format(time);
}
示例 curl 调用结果:
$ curl http://localhost:8080/example/local?time=2020-04-13T21:13:59
Time 2020-04-13T21:13:59
当时区始终相同时,您可以使用 LocalDateTime
。你可以把它转换成 Instant
像这样 time.atZone(ZoneId.systemDefault()).toInstant()
.
当时区可以不同并且必须是输入时间的一部分时,那么你可以像这样使用ZonedDateTime
参数:
@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);
}
转换成 Instant
很简单:time.toInstant()
示例 curl 调用结果:
$ curl http://localhost:8080/example/zoned?time=2020-04-13T21:13:59.123-0100
Time 2020-04-13T21:13:59.123-01:00
当您以错误的格式输入时间查询参数(此处缺少秒数和时区偏移)时,它的行为如下:
$ 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}}}
您也可以使用时间作为请求路径的一部分:
@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);
}
那么示例 curl 调用将是:
$ curl http://localhost:8080/example/local/2020-04-13T21:13:59
Time from request path 2020-04-13T21:13:59
当您以错误的格式在路径中输入时间(此处不需要几分之一秒)时,它的行为如下:
$ 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}}}
还有另一种方法可以做到这一点。 @Format
注释有问题,因为它不能支持 java class 等 OffsetDateTime 和 ZonedDateTime 支持的所有格式。
如果你有例如这个方法:
@Get("/local")
public String local(@QueryValue OffsetDateTime time) {
return "Time " + time.toString();
}
要使其支持 ISO8601,请修改您的 Application.java
(或创建一个新的 class),其中包含:
@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));
}
}
在 Micronaut 3 中推荐的解决这个问题的方法,具有以下灵活性 多种格式,通过添加自定义类型转换器。
OffsetDateTime
的示例实现可以是:
@Singleton
public class OffsetDateTimeConverter implements TypeConverter<String, OffsetDateTime> {
@Override
public Optional<OffsetDateTime> convert(String inputDateTime, Class<OffsetDateTime> targetType, ConversionContext context) {
if (inputDateTime != null) {
try {
var offsetDateTime = OffsetDateTime.parse(inputDateTime);
return Optional.of(offsetDateTime);
} catch (DateTimeParseException e) {
context.reject(inputDateTime, e);
}
}
return Optional.empty();
}
}
这可以在 3.2.7 documentation(和其他)中查看。