Java时间戳转换完整教程
掌握Java中处理Unix时间戳的所有技巧,包含传统API和Java 8+新API的详细代码示例。
获取当前时间戳
使用不同方法获取当前Unix时间戳
Java
// 传统方式 - 毫秒级时间戳
long timestampMs = System.currentTimeMillis();
System.out.println(timestampMs); // 1735660800000L
// 秒级时间戳
long timestampSec = System.currentTimeMillis() / 1000;
System.out.println(timestampSec); // 1735660800
// Java 8+ 方式
import java.time.Instant;
Instant now = Instant.now();
long epochSec = now.getEpochSecond(); // 秒级
long epochMilli = now.toEpochMilli(); // 毫秒级
System.out.println("秒级: " + epochSec);
System.out.println("毫秒: " + epochMilli);时间戳转日期时间
将Unix时间戳转换为日期时间对象
Java
// Java 8+ 方式(推荐)
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
long timestamp = 1735660800L;
// 转为Instant
Instant instant = Instant.ofEpochSecond(timestamp);
// 转为本地时间
LocalDateTime localDateTime = LocalDateTime.ofInstant(
instant,
ZoneId.systemDefault()
);
// 格式化输出
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
System.out.println(localDateTime.format(formatter)); // 2025-01-01 00:00:00
// 转为指定时区时间
ZonedDateTime zonedDateTime = instant.atZone(ZoneId.of("Asia/Shanghai"));
System.out.println(zonedDateTime.format(formatter));
// 传统方式(Java 8之前)
import java.util.Date;
import java.text.SimpleDateFormat;
Date date = new Date(timestamp * 1000L);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(sdf.format(date));日期时间转时间戳
将日期时间对象或字符串转换为Unix时间戳
Java
// LocalDateTime转时间戳
import java.time.LocalDateTime;
import java.time.ZoneId;
LocalDateTime dateTime = LocalDateTime.of(2025, 1, 1, 0, 0, 0);
long timestamp = dateTime.atZone(ZoneId.systemDefault()).toEpochSecond();
System.out.println(timestamp); // 1735660800
// 解析日期字符串
import java.time.format.DateTimeFormatter;
String dateStr = "2025-01-01 00:00:00";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime parsed = LocalDateTime.parse(dateStr, formatter);
long ts = parsed.atZone(ZoneId.systemDefault()).toEpochSecond();
// ISO格式直接解析
import java.time.Instant;
Instant instant = Instant.parse("2025-01-01T00:00:00+08:00");
long ts2 = instant.getEpochSecond();
// 传统方式
import java.util.Date;
Date date = new Date();
long legacyTs = date.getTime() / 1000;日期格式化
将日期时间格式化为各种显示格式
Java
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
LocalDateTime dateTime = LocalDateTime.of(2025, 1, 1, 0, 0, 0);
// 预定义格式
System.out.println(dateTime.format(DateTimeFormatter.ISO_LOCAL_DATE)); // 2025-01-01
System.out.println(dateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)); // 2025-01-01T00:00:00
// 自定义格式
DateTimeFormatter[] formatters = {
DateTimeFormatter.ofPattern("yyyy-MM-dd"),
DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"),
DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH时mm分ss秒"),
DateTimeFormatter.ofPattern("EEE, MMM dd, yyyy"),
};
for (DateTimeFormatter fmt : formatters) {
System.out.println(dateTime.format(fmt));
}
// 线程安全的格式化
// DateTimeFormatter是不可变的,可以安全地在多线程中使用
private static final DateTimeFormatter DATE_FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");时区处理
处理不同时区的时间戳转换
Java
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
// 获取当前时间在不同时区的表示
Instant now = Instant.now();
// 转换为不同时区
ZoneId shanghai = ZoneId.of("Asia/Shanghai");
ZoneId newYork = ZoneId.of("America/New_York");
ZoneId london = ZoneId.of("Europe/London");
ZoneId utc = ZoneId.of("UTC");
ZonedDateTime shanghaiTime = now.atZone(shanghai);
ZonedDateTime newYorkTime = now.atZone(newYork);
ZonedDateTime londonTime = now.atZone(london);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z");
System.out.println("上海: " + shanghaiTime.format(formatter));
System.out.println("纽约: " + newYorkTime.format(formatter));
System.out.println("伦敦: " + londonTime.format(formatter));
// 时区转换
ZonedDateTime converted = shanghaiTime.withZoneSameInstant(newYork);
System.out.println("上海转纽约: " + converted.format(formatter));常用时间操作
时间计算、比较等常用操作
Java
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.time.Duration;
import java.time.Period;
LocalDateTime now = LocalDateTime.now();
LocalDateTime future = now.plusDays(7).plusHours(3).plusMinutes(30);
// 时间差计算
long daysBetween = ChronoUnit.DAYS.between(now, future);
long hoursBetween = ChronoUnit.HOURS.between(now, future);
long minutesBetween = ChronoUnit.MINUTES.between(now, future);
// 使用Duration
Duration duration = Duration.between(now, future);
System.out.println("相差分钟: " + duration.toMinutes());
// 使用Period
LocalDateTime date1 = LocalDateTime.of(2025, 1, 1, 0, 0);
LocalDateTime date2 = LocalDateTime.of(2025, 2, 15, 12, 30);
Period period = Period.between(date1.toLocalDate(), date2.toLocalDate());
System.out.println("相差: " + period.getMonths() + "月" + period.getDays() + "天");
// 时间比较
boolean isAfter = now.isAfter(future); // false
boolean isBefore = now.isBefore(future); // true
boolean isEqual = now.isEqual(future); // false最佳实践
- •推荐使用Java 8+的java.time包,比传统Date/Calendar更好用
- •DateTimeFormatter是不可变的,可以定义为静态常量
- •存储时间戳时使用long类型,避免2038年问题
- •数据库存储使用TIMESTAMP类型或BIGINT存储毫秒时间戳
常见问题
Java时间戳是秒还是毫秒?
System.currentTimeMillis()返回毫秒级时间戳。Instant的toEpochMilli()也是毫秒,getEpochSecond()是秒级。注意与Unix时间戳转换时的单位。
Date和LocalDateTime有什么区别?
Date是旧API,可变且非线程安全。LocalDateTime是Java 8+新API,不可变、线程安全,且区分了时区相关的ZonedDateTime和不带时区的LocalDateTime。
SimpleDateFormat为什么线程不安全?
SimpleDateFormat在格式化过程中会修改内部状态,多线程共享会导致数据错乱。建议使用DateTimeFormatter(不可变,线程安全)或每次创建新的SimpleDateFormat实例。
如何解决2038年问题?
使用long类型存储时间戳(而非int)。Java的long是64位,可以表示非常大的时间范围,不存在2038年问题。