如何仅使用@DateTimeFormat 将日期@ConfigurationProperties 与时间绑定?

How to bind date @ConfigurationProperties with time only using @DateTimeFormat?

新 spring-引导。

我正在尝试从带有注释@ConfigurationProperties 的文件中解析属性。我能够解析日期字段以外的字段。

问题是我的 属性 文件只有时间没有日期。即日期=09:30:00.

我可以用@DateTimeFormat(pattern = "HH:mm:ss") 解析它。但问题是,它给出的日期为 date=Thu Jan 01 09:30:00 GST 1970.

我想得到今天的日期 09:30:00。可能吗?

@ConfigurationProperties
public class Config {

    private int id;
    
    private int version;
        
    @DateTimeFormat(pattern = "HH:mm:ss")
    private Date date;
    
}

属性

id=12
version=2
date=09:30:00

为什么不使用只表示时间的类型?

    @DateTimeFormat(pattern = "HH:mm:ss")
    private LocalTime time;

    public LocalDateTime getDate() {
        return LocalDateTime.of(LocalDate.now(), time);
    } 

您得到的输出符合预期,因为使用 SimpleDateFormat 将字符串解析为 java.util.Date,默认日期时间为 January 1, 1970, 00:00:00 GMT

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Main {
    public static void main(String[] args) throws ParseException {
        String text = "09:30:00";
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
        Date date = sdf.parse(text);
        System.out.println(date);
    }
}

我的时区(Europe/London)的输出:

Thu Jan 01 09:30:00 GMT 1970

请注意 java.util.Date 对象不是像 modern date-time types; rather, it represents the number of milliseconds since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT (or UTC). When you print an object of java.util.Date, its toString method returns the date-time in the JVM's timezone, calculated from this milliseconds value. If you need to print the date-time in a different timezone, you will need to set the timezone to SimpleDateFormat and obtain the formatted string from it. The java.util date-time API and their formatting API, SimpleDateFormat are not only outdated but also error-prone because of many such things. It is recommended to stop using them completely and switch to the modern date-time API1.

那样的真正的日期时间对象

下面给出了几个选项:

  1. 推荐:使用真正代表时间的LocalTime
    @DateTimeFormat(pattern = "HH:mm:ss")
    private LocalTime time;
  1. 肮脏的方式: 将您的字段声明为 String 并在您的业务逻辑中解析它,使其容易出错且肮脏。
    private String time;

我强烈建议不要选择第二个选项。

使用LocalTime的快速演示:

import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        String text = "9:30:00";

        // The optional part can be put inside square bracket
        DateTimeFormatter dtfInput = DateTimeFormatter.ofPattern("H:m[:s]", Locale.ENGLISH);
        LocalTime time = LocalTime.parse(text, dtfInput);

        // Default implementation of LocalTime#toString omits the seconds part if it is zero
        System.out.println(time);

        // Custom output
        DateTimeFormatter dtfOutput = DateTimeFormatter.ofPattern("HH:mm:ss", Locale.ENGLISH);
        String formatted = dtfOutput.format(time);
        System.out.println(formatted);
    }
}

输出:

09:30
09:30:00

Trail: Date Time.

了解有关现代日期时间 API 的更多信息

1.无论出于何种原因,如果您必须坚持使用 Java 6 或 Java 7,则可以使用 ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and

不要使用旧的和过时的 class 日期。查看包 java.time and in particular in your case - class LocalTime.

将您的代码更改为: @配置属性 public class 配置 {

private int id;

private int version;
    
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "HH:mm:ss")
private LocalTime date;

}

这应该有效。您可能需要添加以下依赖项:

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
    <version>2.6.0</version>
</dependency>

这是这个问题的修改答案:Spring Data JPA - json 序列化的 ZonedDateTime 格式