1

我有一個具有java.time.ZonedDateTime屬性的實體。我想解析從dd/MM/yyyy HH:mm格式的表單提交的字符串到java.time.ZonedDateTime。我試過@DateTimeFormat(pattern = "dd/MM/yyyy HH:mm")。但它只適用於格式的LocalDateSpring Boot解析表單數據到ZonedDateTime(dd/MM/yyyy HH:mm)

我還創建了一個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。 Thymeleaf 3.0.7

回答

2

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(始終格式爲Continent/City,如Asia/KolkataEurope/Berlin)。然後使用of方法創建時區,例如ZoneId.of("Asia/Kolkata")

避免使用3個字母的縮寫(如IST或),因爲它們是ambiguous and not standard。其中一些可能工作(通常由於兼容性原因),但不能保證。

您可以使用ZoneId.getAvailableZoneIds()獲得所有可用時區的列表(並選擇最適合您的情況)。