Spring Boot Sping Boot 将表单数据解析为ZonedDateTime(日/月/年时:分)

vatpfxk5  于 2022-12-23  发布在  Spring
关注(0)|答案(2)|浏览(232)

我有一个具有java.time.ZonedDateTime属性的实体。我想将从表单提交的dd/MM/yyyy HH:mm的字符串解析为java.time.ZonedDateTime
我试过@DateTimeFormat(pattern = "dd/MM/yyyy HH:mm")。但是它只适用于@DateTimeFormat(pattern = "dd/MM/yyyy")LocalDate
我还创建了一个Converter,如下所示

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()));
    }
}

我不知道什么是正确的方法来让它工作.使用Sping Boot 1.5.6. Thymeleaf 3.0.7

woobm2wo

woobm2wo1#

DateTimeFormatter的模式只有日期(dd/MM/yyyy)和时间(HH:mm),但是ZonedDateTime还需要一个时区才能直接解析。
由于输入没有它,一种替代方法是首先将输入解析为java.time.LocalDateTime,然后使用已有的zoneId将其转换为ZoneDateTime

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(格式总是Continent/City,如Asia/KolkataEurope/Berlin),然后使用of方法创建时区,如ZoneId.of("Asia/Kolkata")
避免使用3个字母的缩写(如ISTPST),因为它们不明确且不标准。其中一些可能工作(通常是由于向后兼容的原因),但不能保证。
您可以使用ZoneId.getAvailableZoneIds()获得所有可用时区的列表(并选择最适合您的时区)。

tcbh2hod

tcbh2hod2#

您可以创建一个将自动从String转换为ZonedDateTime字段的配置,如下所示:

package com.example.config;

import org.jetbrains.annotations.NotNull;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.format.datetime.standard.DateTimeFormatterRegistrar;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * Configure the converters to use the ISO format for dates by default.
 */
@Configuration
public class DateTimeFormatConfiguration implements WebMvcConfigurer {
    @Override
    public void addFormatters(@NotNull FormatterRegistry registry) {
        DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
        registrar.setUseIsoFormat(true);
        registrar.registerFormatters(registry);
    }
}

相关问题