Перейти к основному содержимому

Как работать с датами в Thymeleaf

· 5 мин. чтения

1. Введение

Thymeleaf — это механизм шаблонов Java, способный напрямую работать с Spring. Чтобы познакомиться с Thymeleaf и Spring, ознакомьтесь с этой статьей .

Помимо этих основных функций, Thymeleaf предлагает нам набор служебных объектов, которые помогут нам выполнять общие задачи в нашем приложении.

В этом руководстве мы обсудим обработку и форматирование новых и старых классов Java Date с несколькими функциями Thymeleaf 3.0.

2. Зависимости Maven

Во-первых, давайте создадим конфигурацию для интеграции Thymeleaf с Spring в наш pom.xml :

<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.0.11.RELEASE</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>3.0.11.RELEASE</version>
</dependency>

Последние версии thymeleaf и thymeleaf-spring5 можно найти на Maven Central. Обратите внимание, что для проекта Spring 4 вместо тимелеаф-спринг5 необходимо использовать библиотеку тимелеаф-спринг4 .

Более того, чтобы работать с новыми классами Date Java 8 , нам нужно добавить еще одну зависимость в наш pom.xml :

<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-java8time</artifactId>
<version>3.0.4.RELEASE</version>
</dependency>

Дополнительные функции thymeleaf — это дополнительный модуль, полностью поддерживаемый официальной командой Thymeleaf, который был создан для совместимости с Java 8 Time API. Он добавляет # временной объект в контекст в качестве обработчика служебных объектов во время оценки выражений. Это означает, что его можно использовать для оценки выражений на языке навигации по графам объектов (OGNL) и языке выражений Spring (SpringEL).

3. Старое и новое: java.util и java.time

Пакет Time — это новый API даты, времени и календаря для платформы Java SE. Основное различие между этим новым API и старым устаревшим API Date заключается в том, что новый API различает машинное и человеческое представление временной шкалы. Машинное представление показывает последовательность целочисленных значений относительно эпохи , тогда как человеческое представление показывает набор полей (например, год, месяц и день).

Для работы с новым пакетом Time нам нужно настроить наш механизм шаблонов для использования нового Java8TimeDialect :

private ISpringTemplateEngine templateEngine(ITemplateResolver templateResolver) {
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.addDialect(new Java8TimeDialect());
engine.setTemplateResolver(templateResolver);
return engine;
}

Это добавит объект #temporal , аналогичный объектам в стандартном диалекте, что позволит форматировать и создавать временные объекты из шаблонов Thymeleaf.

Чтобы протестировать обработку новых и старых классов, мы создадим следующие переменные и добавим их как объекты модели в наш класс контроллера:

model.addAttribute("standardDate", new Date());
model.addAttribute("localDateTime", LocalDateTime.now());
model.addAttribute("localDate", LocalDate.now());
model.addAttribute("timestamp", Instant.now());

Теперь мы готовы использовать служебные объекты Thymeleaf Expression и Temporals .

3.1. Формат даты

Первая функция, которую мы хотим охватить, — это форматирование объекта Date (который добавляется к параметрам модели Spring). Мы будем использовать формат ISO8601 :

<h1>Format ISO</h1>
<p th:text="${#dates.formatISO(standardDate)}"></p>
<p th:text="${#temporals.formatISO(localDateTime)}"></p>
<p th:text="${#temporals.formatISO(localDate)}"></p>
<p th:text="${#temporals.formatISO(timestamp)}"></p>

Независимо от того, как наша дата была установлена на стороне сервера, она будет отображаться в Thymeleaf в соответствии с выбранным стандартом. StandardDate будет обрабатываться утилитой # date . Новые классы LocalDateTime , LocalDate и Instant будут обрабатываться утилитой #temporals . ``

Более того, если мы хотим установить формат вручную, мы можем сделать это с помощью:

<h1>Format manually</h1>
<p th:text="${#dates.format(standardDate, 'dd-MM-yyyy HH:mm')}"></p>
<p th:text="${#temporals.format(localDateTime, 'dd-MM-yyyy HH:mm')}"></p>
<p th:text="${#temporals.format(localDate, 'MM-yyyy')}"></p>

Как мы видим, мы не можем обработать класс Instant с помощью # temporals.format(…) — это приведет к UnsupportedTemporalTypeException . Кроме того, форматирование LocalDate возможно только в том случае, если мы указываем только определенные поля даты, пропуская поля времени.

Посмотрим конечный результат:

./4b7652d9fc984fa7c784b2ff0c459208.png

3.2. Получить определенные поля даты

Чтобы получить определенные поля класса java.util.Date , мы должны использовать следующие служебные объекты:

${#dates.day(date)}
${#dates.month(date)}
${#dates.monthName(date)}
${#dates.monthNameShort(date)}
${#dates.year(date)}
${#dates.dayOfWeek(date)}
${#dates.dayOfWeekName(date)}
${#dates.dayOfWeekNameShort(date)}
${#dates.hour(date)}
${#dates.minute(date)}
${#dates.second(date)}
${#dates.millisecond(date)}

Для нового пакета java.time мы должны использовать # временные утилиты:

${#temporals.day(date)}
${#temporals.month(date)}
${#temporals.monthName(date)}
${#temporals.monthNameShort(date)}
${#temporals.year(date)}
${#temporals.dayOfWeek(date)}
${#temporals.dayOfWeekName(date)}
${#temporals.dayOfWeekNameShort(date)}
${#temporals.hour(date)}
${#temporals.minute(date)}
${#temporals.second(date)}
${#temporals.millisecond(date)}

Давайте рассмотрим несколько примеров. Во-первых, давайте покажем сегодняшний день недели:

<h1>Show only which day of a week</h1>
<p th:text="${#dates.day(standardDate)}"></p>
<p th:text="${#temporals.day(localDateTime)}"></p>
<p th:text="${#temporals.day(localDate)}"></p>

Далее покажем название дня недели:

<h1>Show the name of the week day</h1>
<p th:text="${#dates.dayOfWeekName(standardDate)}"></p>
<p th:text="${#temporals.dayOfWeekName(localDateTime)}"></p>
<p th:text="${#temporals.dayOfWeekName(localDate)}"></p>

Наконец, давайте покажем текущую секунду дня:

<h1>Show the second of the day</h1>
<p th:text="${#dates.second(standardDate)}"></p>
<p th:text="${#temporals.second(localDateTime)}"></p>

Обратите внимание, что для работы с частями времени нам нужно будет использовать LocalDateTime , так как LocalDate выдаст ошибку.

4. Как использовать средство выбора даты в форме

Давайте посмотрим, как использовать средство выбора даты для отправки значения Date из формы Thymeleaf .

Во-первых, давайте создадим класс Student с атрибутом Date :

public class Student implements Serializable {
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birthDate;
}

Аннотация @DateTimeFormat объявляет , что поле BirthdayDate должно быть отформатировано как Date .

Далее мы создадим форму Thymeleaf для ввода даты :

<form th:action="@{/saveStudent}" method="post" th:object="${student}">
<div>
<label for="student-birth-date">Date of birth:</label>
<input type="date" th:field="${student.birthDate}" id="student-birth-date"/>
</div>
<div>
<button type="submit" class="button">Submit</button>
</div>
</form>

Когда мы отправляем форму, контроллер перехватывает объект Student , отображенный в форме с атрибутом th:object . Кроме того, атрибут th:field связывает входное значение с полемbirthDate .

Теперь давайте создадим контроллер для перехвата POST - запроса:

@RequestMapping(value = "/saveStudent", method = RequestMethod.POST)
public String saveStudent(Model model, @ModelAttribute("student") Student student) {
model.addAttribute("student", student);
return "datePicker/displayDate.html";
}

После того, как мы отправим форму, мы отобразим значение BirthdayDate на другой странице с шаблоном dd/MM/yyyy :

<h1>Student birth date</h1>
<p th:text="${#dates.format(student.birthDate, 'dd/MM/yyyy')}"></p>

Результат показывает нашу форму с выбором даты:

./d11b4dd68f190e6eb289b8c870879f25.png

После отправки формы мы увидим выбранную дату:

./91794af4aced6328b0b11173d137eebe.png

5. Вывод

В этом кратком руководстве мы обсудили функции обработки даты Java , реализованные в платформе Thymeleaf версии 3.0.

Как проверить? Мы предлагаем сначала поиграть с кодом в браузере, а затем также проверить наши существующие тесты JUnit.

Обратите внимание, что наши примеры не охватывают все доступные параметры в Thymeleaf. Если вы хотите узнать обо всех типах утилит, взгляните на нашу статью о Spring и Thymeleaf Expressions .

Полную реализацию этого руководства можно найти на GitHub .