本文目录导读:

在Java中进行日期处理时,要统一调用流程,核心目标是解决以下痛点:
- 线程安全:旧API (
java.util.Date,SimpleDateFormat) 非线程安全。 - 代码混乱:混用
Date、Calendar、SimpleDateFormat和java.time包。 - 时区混乱:不同环境(服务器、用户)时区不一致。
- 格式不一致:到处硬编码
yyyy-MM-dd HH:mm:ss。
以下是推荐的统一标准化流程,基于 Java 8+ 的 java.time 包。
核心原则:统一使用 java.time
- 存储/交互:使用
Instant(时间戳) 或String(ISO 8601标准格式)。 - 业务逻辑/计算:使用
LocalDate、LocalDateTime、ZonedDateTime。 - 显示/输入:使用
DateTimeFormatter。 - 数据库交互:通过
PreparedStatement.setObject()/ResultSet.getObject()直接读写java.time对象。
统一调用流程(三层架构)
接收外部输入(Controller层 / 前端)
- 原则:统一接收 ISO 8601 字符串 或 毫秒时间戳。
// 1.1 接收 ISO 8601 字符串
public void receiveDate(String dateStr) {
// 统一解析为 Instant(UTC时间)
Instant instant = Instant.parse(dateStr); // "2023-10-27T10:30:00Z"
// 或者解析为特定时区的 ZonedDateTime
ZonedDateTime zdt = ZonedDateTime.parse(dateStr);
}
// 1.2 接收时间戳 (Long)
public void receiveTimestamp(Long timestamp) {
Instant instant = Instant.ofEpochMilli(timestamp);
}
业务处理(Service层)
- 原则:内部统一用
LocalDateTime(业务无关时区)或ZonedDateTime(有时区需求)。
@Service
public class OrderService {
public void processOrder(Instant createInstant) {
// 转换为系统默认时区进行业务计算
ZonedDateTime beijingTime = createInstant.atZone(ZoneId.of("Asia/Shanghai"));
LocalDateTime ldt = beijingTime.toLocalDateTime();
// 业务逻辑:计算 +3天
LocalDateTime dueDate = ldt.plusDays(3);
// 如果需要返回,转换为 Instant 或标准字符串
Instant dueInstant = dueDate.atZone(ZoneId.of("Asia/Shanghai")).toInstant();
}
}
持久化(DAO层 / 数据库)
- 原则:使用
PreparedStatement.setObject()/ResultSet.getObject(),无需手动转换。
// 3.1 写入数据库
PreparedStatement ps = conn.prepareStatement("INSERT INTO orders (create_time) VALUES (?)");
ps.setObject(1, LocalDateTime.now()); // 数据库字段类型 TIMESTAMP/TIMESTAMP WITHOUT TIME ZONE
// 3.2 读取数据库
ResultSet rs = stmt.executeQuery("SELECT create_time FROM orders");
LocalDateTime ldt = rs.getObject("create_time", LocalDateTime.class);
// 3.3 如果需要UTC存储,使用 Instant
ps.setObject(1, Instant.now()); // 数据库字段类型 TIMESTAMP WITH TIME ZONE
输出到外部(Response / 展示层)
- 原则:统一输出为 ISO 8601 字符串(推荐)或 时间戳。
// 4.1 输出为 ISO 8601 标准字符串(推荐)
Instant now = Instant.now();
String isoString = now.toString(); // 输出: "2023-10-27T02:30:00Z"
// 4.2 输出为特定格式的字符串
LocalDateTime ldt = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formatted = ldt.format(formatter);
// 4.3 使用 Jackson 自动序列化(配置全局格式)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private LocalDateTime createTime;
关键工具封装:统一转换器
为了避免业务代码中到处写 DateTimeFormatter 和 ZoneId,建议创建工具类:
import java.time.*;
import java.time.format.DateTimeFormatter;
public final class DateUtils {
private static final ZoneId DEFAULT_ZONE = ZoneId.of("Asia/Shanghai");
private static final DateTimeFormatter DEFAULT_FORMATTER
= DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// 1. LocalDateTime -> 格式化的字符串
public static String format(LocalDateTime ldt) {
return ldt.format(DEFAULT_FORMATTER);
}
// 2. 字符串 -> LocalDateTime (按指定格式)
public static LocalDateTime parse(String dateStr, String pattern) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
return LocalDateTime.parse(dateStr, formatter);
}
// 3. LocalDateTime <-> Instant (指定时区)
public static Instant toInstant(LocalDateTime ldt) {
return ldt.atZone(DEFAULT_ZONE).toInstant();
}
public static LocalDateTime fromInstant(Instant instant) {
return LocalDateTime.ofInstant(instant, DEFAULT_ZONE);
}
// 4. Date (遗留系统) <-> LocalDateTime (桥接)
public static LocalDateTime fromDate(Date date) {
return date.toInstant().atZone(DEFAULT_ZONE).toLocalDateTime();
}
public static Date toDate(LocalDateTime ldt) {
return Date.from(ldt.atZone(DEFAULT_ZONE).toInstant());
}
}
| 场景 | 推荐类型 | 为什么? |
|---|---|---|
| 系统内部计算 | LocalDateTime |
无时区干扰,简洁高效 |
| 跨时区系统 | Instant 或 ZonedDateTime |
保证时间唯一性,避免时区错误 |
| 数据库存储 | TIMESTAMP + LocalDateTime |
与 java.time 对应,无需转换 |
| 前端交互 | String (ISO 8601格式) |
通用性强,前端友好 |
| 遗留系统对接 | Date + SimpleDateFormat |
桥接旧API,但需注意线程安全 |
特别避坑提醒
- 禁止在代码中混用
Date和LocalDateTime,如果必须使用(如第三方库返回Date),立即转换为LocalDateTime再使用。 - 禁止使用
SimpleDateFormat,如果必须使用(如旧框架),请创建局部变量或使用ThreadLocal。 - 统一时区配置:在应用启动时设置默认时区,避免依赖服务器环境变量。
@PostConstruct public void init() { TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai")); }
遵循这个流程,你的日期处理将变得可预测、线程安全、易于维护。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播