spring-mvc - Spring Boot 将表单数据解析为 ZonedDateTime (dd/MM/yyyy HH :mm)

标签 spring-mvc spring-boot java-time datetime-parsing zoneddatetime

我有一个具有 java.time.ZonedDateTime 属性的实体。我想将以 dd/MM/yyyy HH:mm 格式从表单提交的字符串解析为 java.time.ZonedDateTime

我尝试了@DateTimeFormat(pattern = "dd/MM/yyyy HH:mm")。但它仅适用于 LocalDate@DateTimeFormat(pattern = "dd/MM/yyyy") 格式。

我还创建了一个转换器,如下所示

public class ZonedDateTimeConverter implements Converter<String, ZonedDateTime> {

    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm");

    private final ZoneId zoneId;

    public ZonedDateTimeConverter(ZoneId zoneId) {
        this.zoneId = zoneId;
    }

    @Override
    public ZonedDateTime convert(String source) {
        LOG.info("Parsing string {} to ZonedDateTime: {}", source, ZonedDateTime.parse(source, DATE_TIME_FORMATTER));
        return ZonedDateTime.parse(source, DATE_TIME_FORMATTER);
    }
}

并覆盖 webMvcConfiguration 如下

@Configuration
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {
    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverter(new ZonedDateTimeConverter(ZoneId.systemDefault()));
    }
}

我不确定什么是让它发挥作用的正确方法。 使用 Spring Boot 1.5.6。百里香叶3.0.7

最佳答案

您的 DateTimeFormatter 的模式只有日期 (dd/MM/yyyy) 和时间 (HH:mm),但是ZonedDateTime 也需要时区才能直接解析。

由于输入没有它,一种替代方法是首先将输入解析为 java.time.LocalDateTime,然后将其转换为 ZoneDateTime,使用您已有的 zoneId:

public ZonedDateTime convert(String source) {
    // parse to LocalDateTime
    LocalDateTime dt = LocalDateTime.parse(source, DATE_TIME_FORMATTER);
    // convert to ZonedDateTime
    return dt.atZone(this.zoneId);
}

另一种选择是在格式化程序中设置时区,这样您就可以直接解析为 ZonedDateTime。但在这种情况下,我还建议您进行重构:使格式化程序成为转换器类的字段(而不是 static 字段),因为它将依赖于 ZoneId 你传入构造函数。

public class ZonedDateTimeConverter implements Converter<String, ZonedDateTime> {

    private final DateTimeFormatter formatter;

    public ZonedDateTimeConverter(ZoneId zoneId) {
        // set the zone in the formatter
        this.formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm").withZone(zoneId);
    }

    @Override
    public ZonedDateTime convert(String source) {
        // now the formatter has a zone set, so I can parse directly to ZonedDateTime
        return ZonedDateTime.parse(source, this.formatter);
    }
}

关于使用 ZoneId.systemDefault() 的说明。此方法获取 JVM 的默认时区,但请记住 it can be changed without notice, even at runtime ,因此最好始终指定您要使用的时区。

API 使用 IANA timezones names (始终采用大陆/城市格式,例如亚洲/加尔各答欧洲/柏林)。然后使用 of 方法创建时区,例如 ZoneId.of("Asia/Kolkata")

避免使用 3 个字母的缩写(例如 ISTPST),因为它们是 ambiguous and not standard 。其中一些可能有效(通常是由于向后兼容的原因),但不能保证。

您可以使用 ZoneId.getAvailableZoneIds() 获取所有可用时区的列表(并选择最适合您情况的时区)。

关于spring-mvc - Spring Boot 将表单数据解析为 ZonedDateTime (dd/MM/yyyy HH :mm),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46017003/

相关文章:

java - 如何在 Spring 输入标签中隐藏默认绑定(bind)值?

java - Spring 在 xml 配置文件中重复了 bean 定义,一个在 !stage 中,另一个在 dev 中

spring - 如何在 spring Restapi 的 json 请求中的未知字段上抛出错误

spring-boot - 我们是否应该使用 springboot 为生产级应用程序提供的嵌入式 tomcat 容器?

java - LocalDateTime , ZonedDateTime 和时间戳

java - 如何以 Spring 形式包含多个模型元素?

java - 在 Spring MVC 中获取对静态资源文件中项目的基本 url 的引用

java - 使用 JAAS 登录模块注销

java - DateTime.now() 和 new DateTime(System.currentTimeMillis()) 方法在 Java 中是否相等?

java - LocalDateTime.format(DateTimeFormatter) 和 DateTimeFormatter.format(TemporalAccessor) 有什么区别?