How to display ZonedDateTime on HTML5 datetime-local input with Thymeleaf? The ExampleModel.datetime is able to convert from HTML datetime-local input with ZonedDateTimeConverter, but unable to display on the HTML datetime-local input, it is always empty.
html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Zoned Date Time</title>
</head>
<body>
<form action="#" th:action="@{/example/}" th:object="${exampleModel}"
method="post">
<p>
Text: <input type="text" th:field="*{text}" />
</p>
<p>
Date Time: <input type="datetime-local" th:field="*{datetime}" />
</p>
<p>
<input type="submit" value="Save" />
</p>
</form>
</body>
</html>
Model
package com.example.springboot.model;
import java.time.ZonedDateTime;
import lombok.Data;
@Data
public class ExampleModel {
private String text;
private ZonedDateTime datetime;
public ExampleModel() {
}
public ExampleModel(String text, ZonedDateTime datetime) {
this.text = text;
this.datetime = datetime;
}
}
Controller
package com.example.springboot.ctrl;
import java.time.ZonedDateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import com.example.springboot.model.ExampleModel;
@Controller
@RequestMapping("/example/")
public class ExampleCtrl {
private static final Logger log = LoggerFactory.getLogger(ExampleCtrl.class);
@GetMapping()
public String doGet(Model model) {
model.addAttribute("exampleModel", new ExampleModel("Hello", ZonedDateTime.now()));
log.debug("model: {}", model);
return "example";
}
@PostMapping()
public String doPost(@ModelAttribute ExampleModel exampleModel, Model model) {
log.info("exampleModel: {}", exampleModel);
return "example";
}
}
ZonedDateTimeConverter
package com.example.springboot;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.convert.converter.Converter;
final class ZonedDateTimeConverter implements Converter<String, ZonedDateTime> {
private static final Logger log = LoggerFactory.getLogger(ZonedDateTimeConverter.class);
private final DateTimeFormatter dtf;
public ZonedDateTimeConverter(ZoneId zoneId) {
// set the zone in the formatter
this.dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm").withZone(zoneId);
}
@Override
public ZonedDateTime convert(String source) {
return ZonedDateTime.parse(source, this.dtf);
}
}
WebConfig
package com.example.springboot;
import java.time.ZoneId;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new ZonedDateTimeConverter(ZoneId.systemDefault()));
}
}