How to Work with Dates in Thymeleaf – 如何在Thymeleaf中处理日期问题

最后修改: 2017年 1月 10日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.介绍

Thymeleaf is a Java template engine able to work directly with Spring. For an intro to Thymeleaf and Spring, have a look at this write-up.

Thymeleaf是一个Java模板引擎,能够直接与Spring一起工作。关于Thymeleaf和Spring的介绍,请看这个文章

Besides these basic functions, Thymeleaf offers us a set of utility objects that will help us perform common tasks in our application.

除了这些基本功能,Thymeleaf还为我们提供了一组实用对象,它们将帮助我们在应用程序中执行常见的任务。

In this tutorial, we’ll discuss the processing and formatting of the new and old Java Date classes with a handful of features of Thymeleaf 3.0.

在本教程中,我们将讨论新旧JavaDate类的处理和格式化问题,以及Thymeleaf 3.0的一些特性。

2. Maven Dependencies

2.Maven的依赖性

First, let’s create the configuration to integrate Thymeleaf with Spring into our pom.xml:

首先,让我们在pom.xml中创建配置,将Thymeleaf与Spring集成起来。

<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>

The latest versions of thymeleaf and thymeleaf-spring5 can be found on Maven Central. Note that, for a Spring 4 project, the thymeleaf-spring4 library must be used instead of thymeleaf-spring5.

thymeleafthymeleaf-spring5的最新版本可以在Maven中心找到。请注意,对于Spring 4项目,必须使用thymeleaf-spring4库而不是thymeleaf-spring5

Moreover, in order to work with new Java 8 Date classes, we’ll need to add another dependency to our pom.xml:

此外,为了与新的Java 8 Date 类一起工作,我们需要在pom.xml中添加另一个依赖项。

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

The thymeleaf extras is an optional module, fully supported by the official Thymeleaf team, that was created for compatibility with the Java 8 Time API. It adds a #temporals object to the Context as a utility object processor during expression evaluations. This means that it can be used to evaluate expressions in Object-Graph Navigation Language (OGNL) and Spring Expression Language (SpringEL).

thymeleaf extras是一个可选的模块,由Thymeleaf官方团队完全支持,它是为了与Java 8 Time API兼容而创建。它向Context添加了一个#temporals对象,作为表达式评估期间的实用对象处理器。这意味着它可以用来评估对象-图形导航语言(OGNL)和Spring表达式语言(SpringEL)中的表达式。

3. Old and New: java.util and java.time

3.新与旧 java.utiljava.time

The Time package is a new date, time, and calendar API for the Java SE platform. The main difference between this new API and the old legacy Date API is that the new API distinguishes between machine and human views of a timeline. The machine view reveals a sequence of integral values relative to the epoch, whereas the human view reveals a set of fields (for example, year, month, and day).

Time包是Java SE平台的一个新的日期、时间和日历API。这个新的API与旧的传统Date API之间的主要区别是,新的API区分了时间线的机器视图和人类视图。机器视图显示了相对于epoch的积分值序列,而人类视图显示了一组字段(例如,年、月、日)。

To work with the new Time package, we need to configure our template engine to use the new Java8TimeDialect:

为了使用新的Time包,我们需要配置我们的模板引擎以使用新的Java8TimeDialect

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

This will add the #temporals object similar to the ones in the Standard Dialect, allowing the formatting and creation of Temporal objects from Thymeleaf templates.

这将增加类似于标准方言中的#temporals对象,允许从Thymeleaf模板中格式化和创建Temporal对象。

In order to test the processing of new and old classes, we’ll create the following variables and add them as model objects to our controller class:

为了测试新旧类的处理,我们将创建以下变量,并将它们作为模型对象添加到我们的控制器类中。

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

Now, we’re ready to use Thymeleaf’s Expression and Temporals utility objects.

现在,我们准备使用Thymeleaf的ExpressionTemporals实用对象。

3.1. Format Dates

3.1.格式化的日期

The first function that we want to cover is the formatting of a Date object (which is added to the Spring model parameters). We’ll use the ISO8601 format:

我们要介绍的第一个功能是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>

No matter how our Date was set on the back-end side, it will be displayed in Thymeleaf according to the selected standard. The standardDate is going to be processed by the #dates utility. The new LocalDateTime, LocalDate, and Instant classes are going to be processed by the #temporals utility.

无论我们的Date在后端是如何设置的,它都将根据选定的标准在Thymeleaf中显示。standardDate将被#dates工具处理。新的LocalDateTimeLocalDateInstant类将由#temporals工具处理。

Moreover, if we want to set the format manually, we can do it by using:

此外,如果我们想手动设置格式,我们可以通过使用来实现。

<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>

As we can observe, we cannot process the Instant class with #temporals.format(…) — it will result in UnsupportedTemporalTypeException. Moreover, formatting the LocalDate is only possible if we specify only the particular date fields, skipping the time fields.

我们可以观察到,我们不能用#temporals.format(…)来处理Instant类–它将导致UnsupportedTemporalTypeException。此外,只有当我们只指定特定的日期字段,跳过时间字段时,格式化LocalDate才有可能。

Let’s see the final result:

让我们看看最后的结果。

Zrzut-ekranu

3.2. Obtain Specific Date Fields

3.2.获得特定的日期字段

In order to obtain the specific fields of the java.util.Date class, we should use the following utility objects:

为了获得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)}

For the new java.time package, we should stick with #temporals utilities:

对于新的java.time包,我们应该坚持使用#temporals工具。

${#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)}

Let’s look at a few examples. First, let’s show today’s day of the week:

让我们看几个例子。首先,让我们显示今天是星期几。

<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>

Next, let’s show the name of the weekday:

接下来,让我们展示一下工作日的名称。

<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>

Finally, let’s show the current second of the day:

最后,让我们展示一下当前的秒数。

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

Please note that in order to work with time parts, we would need to use LocalDateTime, as LocalDate will throw an error.

请注意,为了处理时间部分,我们需要使用LocalDateTime,因为LocalDate会出现错误。

4. How to Use a Date-Picker in a Form

4.如何在表单中使用日期选择器

Let’s look at how to use a date-picker to submit a Date value from a Thymeleaf form.

让我们看看如何使用日期选择器从Thymeleaf表单中提交一个Date

First, let’s create a Student class with a Date attribute:

首先,让我们创建一个带有Date属性的Student类。

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

The @DateTimeFormat annotation declares that the birthDate field should be formatted as a Date.

@DateTimeFormat注解声明birthDate字段应被格式化为a Date

Next, we’ll create a Thymeleaf form to submit a Date input:

接下来,我们将创建一个Thymeleaf表单来提交一个Date输入。

<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>

When we submit the form, a controller will intercept the Student object mapped in the form with th:object attribute. Also, the th:field attribute binds the input value with the birthDate field.

当我们提交表单时,控制器将拦截表单中用th:object属性映射的Student对象。同时,th:field属性将输入值与birthDate字段绑定。

Now, let’s create a controller to intercept the POST request:

现在,让我们创建一个控制器来拦截POST请求。

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

After we submit the form, we’ll display the birthDate value on another page with the pattern dd/MM/yyyy:

在我们提交表单后,我们将在另一个页面上显示birthDate值,模式为dd/MM/yyyy

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

The result shows our form with a date-picker:

结果显示我们的表单有一个日期选择器。

datePicker

After submitting the form, we’ll see the selected date:

提交表格后,我们会看到选定的日期。

display date

5. Conclusion

5.结论

In this quick tutorial, we discussed Java Date processing features implemented in the Thymeleaf framework, version 3.0.

在这个快速教程中,我们讨论了在Thymeleaf框架3.0版本中实现的JavaDate处理功能。

How to test? Our suggestion is to play with the code in a browser first, then check our existing JUnit tests as well.

如何测试?我们的建议是先在浏览器中玩玩代码,然后也检查一下我们现有的JUnit测试。

Please note that our examples do not cover all available options in Thymeleaf. If you want to learn about all types of utilities, then take a look at our article covering Spring and Thymeleaf Expressions.

请注意,我们的例子并没有涵盖Thymeleaf的所有可用选项。如果您想了解所有类型的实用程序,那么请看我们的文章,内容包括Spring和Thymeleaf Expressions

The full implementation of this tutorial can be found over on GitHub.

本教程的完整实现可以在GitHub上找到