时区处理完全指南:Java、JavaScript、数据库最佳实践

全面介绍时区处理的方法和最佳实践,涵盖 Java、JavaScript、数据库的时区处理方案。

时间与日期 2026-06-03 10 分钟

时区处理完全指南:Java、JavaScript、数据库最佳实践

时区处理是开发中最容易出错的环节之一。本文介绍各平台的时区处理方法和最佳实践。

时区基础

UTC(协调世界时)

UTC 是全球统一的时间标准,所有时区都相对于 UTC。

时区表示

UTC+8: 东八区(中国标准时间)
UTC-5: 西五区(美国东部时间)

IANA 时区数据库

Asia/Shanghai    — 中国
America/New_York — 美国东部
Europe/London    — 英国

Java 时区处理

Java 8+ API

import java.time.*;

// 获取当前时间(带时区)
ZonedDateTime now = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));

// 时区转换
ZonedDateTime tokyoTime = now.withZoneSameInstant(ZoneId.of("Asia/Tokyo"));

// 格式化
String formatted = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z"));

常用操作

// 获取系统默认时区
ZoneId defaultZone = ZoneId.systemDefault();

// 获取所有可用时区
Set<String> zones = ZoneId.getAvailableZoneIds();

// 时间戳转带时区时间
Instant instant = Instant.ofEpochSecond(1704067200);
ZonedDateTime zdt = instant.atZone(ZoneId.of("Asia/Shanghai"));

JavaScript 时区处理

原生 API

// 获取当前时间
const now = new Date();

// 获取时区偏移(分钟)
const offset = now.getTimezoneOffset(); // -480(UTC+8)

// 转为 UTC 字符串
now.toISOString(); // '2024-01-01T00:00:00.000Z'

// 转为本地字符串
now.toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' });

使用 Intl API

// 指定时区显示
new Intl.DateTimeFormat('zh-CN', {
  timeZone: 'Asia/Shanghai',
  year: 'numeric',
  month: '2-digit',
  day: '2-digit',
  hour: '2-digit',
  minute: '2-digit',
  second: '2-digit'
}).format(new Date());

使用 Moment.js / Day.js

// Day.js(推荐,轻量)
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import timezone from 'dayjs/plugin/timezone';

dayjs.extend(utc);
dayjs.extend(timezone);

dayjs().tz('Asia/Shanghai').format('YYYY-MM-DD HH:mm:ss');

数据库时区处理

MySQL

-- 查看当前时区
SELECT @@global.time_zone, @@session.time_zone;

-- 设置时区
SET GLOBAL time_zone = '+08:00';
SET SESSION time_zone = '+08:00';

-- TIMESTAMP 类型:存储时转换为 UTC
-- DATETIME 类型:存储原始值,不转换

PostgreSQL

-- 查看当前时区
SHOW timezone;

-- 设置时区
SET timezone = 'Asia/Shanghai';

-- TIMESTAMP WITH TIME ZONE:存储时转换为 UTC
-- TIMESTAMP WITHOUT TIME ZONE:存储原始值

最佳实践

1. 存储使用 UTC

// 数据库存储 UTC 时间
ZonedDateTime utcTime = ZonedDateTime.now(ZoneOffset.UTC);

2. 传输使用 ISO 8601

// API 响应
String iso8601 = now.format(DateTimeFormatter.ISO_ZONED_DATE_TIME);
// "2024-01-01T00:00:00+08:00[Asia/Shanghai]"

3. 显示转换时区

// 前端根据用户时区显示
const userTime = utcTime.toLocaleString('zh-CN', {
  timeZone: getUserTimezone()
});

4. 使用 IANA 时区标识

// ✅ 推荐
ZoneId.of("Asia/Shanghai")

// ❌ 不推荐
ZoneId.of("GMT+8")

常见问题

1. 时间显示不一致

原因: 前后端时区不一致

解决: 统一使用 UTC 存储和传输

2. 夏令时问题

原因: 某些地区有夏令时

解决: 使用 IANA 时区数据库,自动处理夏令时

3. 数据库时间错误

原因: 数据库时区配置错误

解决: 统一数据库时区为 UTC

总结

时区处理的最佳实践:存储 UTC,传输 ISO 8601,显示转换本地时区。使用 IANA 时区标识,避免手动计算时区偏移。

📚 相关文章