2

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

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

我还创建了一个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()));
    }
}

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

4

1 回答 1

2

DateTimeFormatter的模式只有日期(dd/MM/yyyy)和时间(HH:mm),但aZonedDateTime也需要一个时区来直接解析。

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

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 的默认时区,但请记住,即使在运行时也可以更改它,恕不另行通知,因此最好始终指定要使用的时区。

API 使用IANA 时区名称(始终采用格式Continent/City,例如Asia/KolkataEurope/Berlin)。然后您使用of方法创建时区,例如ZoneId.of("Asia/Kolkata").

避免使用 3 个字母的缩写(如ISTor PST),因为它们模棱两可且不标准。其中一些可能有效(通常是由于复古兼容性原因),但不能保证。

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

于 2017-09-02T21:19:06.980 回答