【问题标题】:@DateTimeFormat with daylight saving error when converting@DateTimeFormat 转换时出现夏令时错误
【发布时间】:2018-03-28 10:42:48
【问题描述】:

我在使用 @DateTimeFormat 注释转换实际不存在的日期时遇到问题。

例如,当我设置日期 15/10/2017 时,我的实体中的注释如下:

@Column(nullable = false)
@NotNull
@DateTimeFormat(pattern = "dd/MM/yyyy")
private Date dataVisita;

我收到错误:

Failed To Convert Property Value Of Type Java.Lang.String To Required Type Java.Util.Date For Property DataVisita; 
Nested Exception Is Org.Springframework.Core.Convert.ConversionFailedException: 
    Failed To Convert From Type Java.Lang.String To Type @Javax.Persistence.Column @Javax.Validation.Constraints.NotNull @Org.Springframework.Format.Annotation.DateTimeFormat Java.Util.Date For Value 15/10/2017; 
Nested Exception Is Java.Lang.IllegalArgumentException: 
    Cannot Parse "15/10/2017": Illegal Instant Due To Time Zone Offset Transition (America/Sao_Paulo)

我了解错误告诉我日期15/10/2017 00:00:00实际上并不存在,但我想转换为15/10/2017 01:00:00,这样就忽略了问题并找到了对应的日期。

有没有办法让我覆盖 @DateTimeFormat 注释或让格式化程序变得宽松?

【问题讨论】:

  • '言出必行,言出必行' 您当前正在尝试将日期放入表示日期和时间的对象中。你可以使用 LocalDate 还是你被 Date 卡住了?
  • 您可以创建自定义反序列化器。 AFAIR 它在引擎盖下使用杰克逊。 JsonDeserialize 注释应该会有所帮助。 Jackson-Deserialization example.
  • 尝试使用@DateTimeFormat(iso=ISO.DATE_TIME),它不会忽略字符串中的时间

标签: java spring date formatter


【解决方案1】:

试试这个:

@Column(nullable = false)

@NotNull

@DateTimeFormat(pattern = "dd/MM/yyyy HH:mm:ss")

私人日期数据访问;

它似乎做你想做的(调整0:00到1:00),你需要实现一个validator如下:

public class PersonValidator implements Validator {

    /**
     * This Validator validates *just* Person instances
     */
    public boolean supports(Class clazz) {
        return Date.class.equals(clazz);
    }

    public void validate(Object obj, Errors e) {
        String dateString = (String) obj;
        DateTimeFormatter fmt = DateTimeFormat.forPattern("dd/MM/yyyy HH:mm:ss");
        DateTime ourDate = null;
        try {
            fmt.parseDateTime(dateString);
        } catch (IllegalArgumentException e) {
            // massage your hour here
        } finally {
            ourDate = fmt.parseDateTime(dateString);
        }
    }
}

【讨论】:

  • 很好,@OleV.V.
【解决方案2】:

如果你想使用DateTimeFormat,它是 Java 8 类和新的(自 java 8 起)“java.time”框架的一部分,你可能需要使用 Java 8 Date 类:

日期:
java.time.LocalDate

时间:
java.time.LocalTime, java.time.OffsetTime

时间戳:
java.time.Instant、java.time.LocalDateTime、java.time.OffsetDateTime 和 java.time.ZonedDateTime

另外,您在 Spring 框架中使用的是哪个 ORM? Spring数据,休眠还是其他?如果您使用 Hibernate,请查阅 Hibernate 用户指南:Mapping Date/Time Values

【讨论】:

    【解决方案3】:

    取决于您在数据库中存储日期的方式以及您的服务器时区, 解决方案是在 Spring 初始化时将默认时区设置为 UTC,使用以下代码:

    TimeZone.setDefault(TimeZone.getTimeZone("UTC"));

    【讨论】:

      【解决方案4】:

      对我来说,你不应该直接搞乱系统的语言环境。那是你真正的问题。

      我的意思是您没有提供时区,所以您使用的是服务器之一。在具有其配置的此服务器上,它将是这一天/日期。在另一台服务器上,它将是另一天/日期。

      请确保您使用 UTC(因此没有夏令时和所有)或客户端在输入中提供的明确语言环境,使用本地日期来存储...要么保持这种状态,并且在需要时比较日期,将其转换为 UTC。这样问题就会消失。

      快速解决方法是确保您的服务器使用 UTC,但从长远来看,您应该始终控制您使用的区域设置,因此提供的日期必须是 UTC,或者它是本地日期,另一个字段提供时区。

      【讨论】:

      • 我为应用程序“pt_BR”设置了一个默认的区域设置,所以它会一直使用它作为日期
      【解决方案5】:

      这应该很简单。

      这里的问题是,您正在为日期对象传递一个字符串值。这是相关注释的文档:

      https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/format/annotation/DateTimeFormat.html

      这里简单说一下所需的类型:java.util.Date、java.util.Calendar、java.lang.Long、Joda-Time 值类型

      一种很幼稚的方式:

      SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
      Date destnationDateToBeSaved = sdf.parse("15/10/2017");
      

      推荐方式:

      使用:

      @DateTimeFormat(iso = ISO.DATE_TIME)
      private ZonedDateTime zonedDateTime;
      

      // 'yyyy-MMM-dd HH:mm:ss' pattern or if preferred ISO
      ZonedDateTime  destnationDateToBeSaved= ZonedDateTime.parse("2017-Oct-15 23:35:05", DateTimeFormatter.ofPattern("yyyy-MMM-dd HH:mm:ss").withZone(ZoneId.of("UTC"))); 
      

      希望有帮助!

      【讨论】:

        猜你喜欢
        • 2011-12-22
        • 2013-12-27
        • 2012-08-30
        • 1970-01-01
        • 2018-10-04
        • 1970-01-01
        • 2012-10-31
        • 2021-09-10
        • 2012-11-25
        相关资源
        最近更新 更多