MapStruct Date 转 LocalDate 偏差一天问题
当使用 MapStruct 将 java.util.Date
转换为 java.time.LocalDate
时出现日期偏差一天的问题,通常是由时区处理引起的。
问题原因
- 时区差异:
Date
对象内部存储的是 UTC 时间戳,而LocalDate
是无时区概念的本地日期 - 隐式转换:MapStruct 在转换时会使用系统默认时区
- 时间点问题:UTC 时间与本地时区时间可能存在日期差异(例如 UTC 时间 00:00 在某些时区可能是前一天的晚上)
解决方案
1. 明确指定时区
@Mapper
public interface MyMapper {default LocalDate dateToLocalDate(Date date) {return date.toInstant().atZone(ZoneId.systemDefault()) // 或指定特定时区 ZoneId.of("Asia/Shanghai").toLocalDate();}
}
2. 使用自定义映射方法
@Mapper
public interface MyMapper {@Mapping(target = "localDateProperty", source = "dateProperty", dateFormat = "yyyy-MM-dd")Target map(Source source);default LocalDate map(Date date) {if (date == null) {return null;}return date.toInstant().atZone(ZoneId.of("UTC")).toLocalDate();}
}
3. 全局配置(MapStruct 1.5+)
@MapperConfig
public interface CentralConfig {default LocalDate map(Date date) {return date == null ? null : date.toInstant().atZone(ZoneOffset.UTC).toLocalDate();}
}@Mapper(config = CentralConfig.class)
public interface MyMapper {// 自动使用中央配置的转换方法
}
验证建议
- 打印原始
Date
对象的toString()
和getTime()
- 检查系统默认时区
ZoneId.systemDefault()
- 确保数据库连接和应用程序使用相同的时区配置
通过明确控制时区转换,可以避免 Date 到 LocalDate 转换时的日期偏差问题。