时间戳是指格林威治时间1970年01月01日00时00分00秒起至现在的总毫秒数,是所有时间的基础,其他时间可以通过时间戳转换得到。Java中本来已经有相关获取时间戳的方法,Java8后增加新的类Instant等专用于处理时间戳问题。

1 获取时间戳的方法和性能对比

1.1 获取时间戳方法

Java8以前可以使用System.currentTimeMillis() 、new Date().getTime() 、和Calendar.getInstance().getTimeInMillis()获取。Java8以后可以另外通过Instant.now().toEpochMilli()和Clock.systemUTC().millis()获取。

比较简单,下面直接看代码:

* 使用System获取时间戳 @Test public void getEpochMilliWithSystem(){ long s = System.currentTimeMillis(); for ( int i = 0; i < 1000000; i++ ) { System.currentTimeMillis(); System.out.println( "getEpochMilliWithSystem cost:"+(System.currentTimeMillis()- s)); * 使用Date获取时间戳 @Test public void getEpochMilliWithDate(){ long s = System.currentTimeMillis(); for ( int i = 0; i < 1000000; i++ ) { new Date().getTime(); System.out.println( "getEpochMilliWithDate cost:"+(System.currentTimeMillis()- s)); * 使用Calendar获取时间戳 @Test public void getEpochMilliWithCalendar(){ long s = System.currentTimeMillis(); for ( int i = 0; i < 1000000; i++ ) { Calendar.getInstance().getTimeInMillis(); System.out.println( "getEpochMilliWithCalendar cost:"+(System.currentTimeMillis()- s)); * 使用Instant获取时间戳 @Test public void getEpochMilliWithInstant(){ long s = System.currentTimeMillis(); for ( int i = 0; i < 1000000; i++ ) { Instant.now().toEpochMilli(); System.out.println( "getEpochMilliWithInstant cost:"+(System.currentTimeMillis()- s)); * 使用Clock获取时间戳 @Test public void getEpochMilliWithClock(){ long s = System.currentTimeMillis(); for ( int i = 0; i < 1000000; i++ ) { Clock.systemUTC().millis(); System.out.println( "getEpochMilliWithClock cost:"+(System.currentTimeMillis()- s));

查看过上面相关源码,基本都是通过System.currentTimeMillis() 来创建对象的。比如 new Date:

public Date() {
        this(System.currentTimeMillis());

1.2 性能对比

上面代码执行输出:

getEpochMilliWithSystem cost:5
getEpochMilliWithDate cost:38
getEpochMilliWithCalendar cost:1094
getEpochMilliWithInstant cost:106
getEpochMilliWithClock cost:17

通过1.1 中的分析得知基本都是通过System.currentTimeMillis() 来创建对象的System.currentTimeMillis()最快,性能最好。

所以,性能排序:System > Clock > Date Instant > Calendar 

2.时间戳转换为其他类

 2.1 时间戳和其他类型的转换

* 时间戳epochMilli毫秒转Date *
@param epochMilli * @return public static Date toDate(long epochMilli){ Objects.requireNonNull(epochMilli, "epochMilli"); return new Date(epochMilli); * 时间戳epochMilli毫秒转LocalDateTime * @param epochMilli * @return public static LocalDateTime toLocalDateTime(long epochMilli) { Objects.requireNonNull(epochMilli, "epochMilli"); return LocalDateTime.ofInstant(Instant.ofEpochMilli(epochMilli), ZoneId.systemDefault()); * 时间戳epochMilli毫秒转LocalDate * @param epochMilli * @return public static LocalDate toLocalDate(long epochMilli) { Objects.requireNonNull(epochMilli, "epochMilli"); return toLocalDateTime(epochMilli).toLocalDate(); * 时间戳epochMilli毫秒转Instant * @param epochMilli * @return public static Instant toInstant(long epochMilli) { Objects.requireNonNull(epochMilli, "epochMilli"); return Instant.ofEpochMilli(epochMilli); * 时间戳epochMilli毫秒转ZonedDateTime,时区为系统默认时区 * @param epochMilli * @return public static ZonedDateTime toZonedDateTime(long epochMilli) { Objects.requireNonNull(epochMilli, "epochMilli"); return LocalDateTime.ofInstant(Instant.ofEpochMilli(epochMilli), ZoneId.systemDefault()) .atZone(ZoneId.systemDefault()); * 时间戳epochMilli转Timestamp * @param epochMilli * @return public static Timestamp toTimestamp(long epochMilli){ return new Timestamp(epochMilli); * Date转时间戳 * 从1970-01-01T00:00:00Z开始的毫秒值 * @param date * @return public static long toEpochMilli(Date date){ Objects.requireNonNull(date, "date"); return date.getTime(); * LocalDateTime转时间戳 * 从1970-01-01T00:00:00Z开始的毫秒值 * @param localDateTime * @return public static long toEpochMilli(LocalDateTime localDateTime){ return toInstant(localDateTime).toEpochMilli(); * LocalDate转时间戳 * 从1970-01-01T00:00:00Z开始的毫秒值 * @param localDate * @return public static long toEpochMilli(LocalDate localDate){ return toInstant(localDate).toEpochMilli(); * Instant转时间戳 * 从1970-01-01T00:00:00Z开始的毫秒值 * @param instant * @return public static long toEpochMilli(Instant instant){ Objects.requireNonNull(instant, "instant"); return instant.toEpochMilli(); * ZonedDateTime转时间戳,注意,zonedDateTime时区必须和当前系统时区一致,不然会出现问题 * 从1970-01-01T00:00:00Z开始的毫秒值 * @param zonedDateTime * @return public static long toEpochMilli(ZonedDateTime zonedDateTime) { Objects.requireNonNull(zonedDateTime, "zonedDateTime"); return zonedDateTime.toInstant().toEpochMilli(); * Timestamp转时间戳 * 从1970-01-01T00:00:00Z开始的毫秒值 * @param timestamp * @return public static long toEpochMilli(Timestamp timestamp){ Objects.requireNonNull(timestamp, "timestamp"); return timestamp.getTime();

测试代码:

* 时间戳转换测试 @Test
public void epochMilliConverterTest(){ System.out.println("===================epochMilliConverterTest====================="); Date date = new Date(); long epochMilli = date.getTime(); System.out.println("epochMilli:"+epochMilli); System.out.println("===================ToOther====================="); System.out.println(DateTimeConverterUtil.toDate(epochMilli)); System.out.println(DateTimeConverterUtil.toLocalDateTime(epochMilli)); System.out.println(DateTimeConverterUtil.toLocalDate(epochMilli)); System.out.println(DateTimeConverterUtil.toInstant(epochMilli)); System.out.println(DateTimeConverterUtil.toZonedDateTime(epochMilli)); System.out.println(DateTimeConverterUtil.toTimestamp(epochMilli)); System.out.println("===================toEpochMilli====================="); System.out.println(DateTimeConverterUtil.toEpochMilli(new Date())); System.out.println(DateTimeConverterUtil.toEpochMilli(LocalDateTime.now())); // 另一种方式: +8 时区 System.out.println(LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli()); System.out.println(DateTimeConverterUtil.toEpochMilli(LocalDate.now())); System.out.println(DateTimeConverterUtil.toEpochMilli(Instant.now())); System.out.println(DateTimeConverterUtil.toEpochMilli(ZonedDateTime.now())); System.out.println(DateTimeConverterUtil.toEpochMilli(new Timestamp(System.currentTimeMillis())));
===================epochMilliConverterTest=====================
epochMilli:1587950768191
===================ToOther=====================
Mon Apr 27 09:26:08 CST 2020
2020-04-27T09:26:08.191
2020-04-27
2020-04-27T01:26:08.191Z
2020-04-27T09:26:08.191+08:00[Asia/Shanghai]
2020-04-27 09:26:08.191
===================toEpochMilli=====================
1587950768304
1587950768304
1587950768304
1587916800000
1587950768305
1587950768305
1587950768305

 3 Timestamp

Timestamp是Java8以前处理时间戳的类。Timestamp和其他类型的转换

* Timestamp转LocalDateTime *
@param timestamp * @return public static LocalDateTime toLocalDateTime(Timestamp timestamp) { Objects.requireNonNull(timestamp, "timestamp"); return timestamp.toLocalDateTime(); * Timestamp转Instant * @param timestamp * @return public static Instant toInstant(Timestamp timestamp) { Objects.requireNonNull(timestamp, "timestamp"); return timestamp.toInstant(); * Timestamp转时间戳 * 从1970-01-01T00:00:00Z开始的毫秒值 * @param timestamp * @return public static long toEpochMilli(Timestamp timestamp){ Objects.requireNonNull(timestamp, "timestamp"); return timestamp.getTime(); * Date转Timestamp * @param date * @return public static Timestamp toTimestamp(Date date){ Objects.requireNonNull(date, "date"); return new Timestamp(date.getTime()); * LocalDateTime转Timestamp * @param localDateTime * @return public static Timestamp toTimestamp(LocalDateTime localDateTime){ Objects.requireNonNull(localDateTime, "localDateTime"); return Timestamp.valueOf(localDateTime); * Instant转Timestamp * @param instant * @return public static Timestamp toTimestamp(Instant instant){ Objects.requireNonNull(instant, "instant"); return Timestamp.from(instant); * 时间戳epochMilli转Timestamp * @param epochMilli * @return public static Timestamp toTimestamp(long epochMilli){ return new Timestamp(epochMilli);

测试代码:

* Timestamp转换测试 @Test
public void timestampConverterTest(){ System.out.println("===================timestampConverterTest====================="); Timestamp timestamp = new Timestamp(System.currentTimeMillis()); long epochMilli = timestamp.getTime(); System.out.println("epochMilli:"+epochMilli); System.out.println("===================ToOther====================="); System.out.println(DateTimeConverterUtil.toLocalDateTime(timestamp)); System.out.println(DateTimeConverterUtil.toInstant(timestamp)); System.out.println(DateTimeConverterUtil.toEpochMilli(timestamp)); System.out.println("===================toEpochMilli====================="); System.out.println(DateTimeConverterUtil.toTimestamp(new Date())); System.out.println(DateTimeConverterUtil.toTimestamp(LocalDateTime.now())); System.out.println(DateTimeConverterUtil.toTimestamp(Instant.now())); System.out.println(DateTimeConverterUtil.toTimestamp(epochMilli));
===================timestampConverterTest=====================
epochMilli:1587950937677
===================ToOther=====================
2020-04-27T09:28:57.677
2020-04-27T01:28:57.677Z
1587950937677
===================toEpochMilli=====================
2020-04-27 09:28:57.774
2020-04-27 09:28:57.781
2020-04-27 09:28:57.782
2020-04-27 09:28:57.677

4 Instant

Java8可以使用Instant方便的获取时间戳相关的信息。

4.1 创建方式

public static Instant now() {
        return Clock.systemUTC().instant();
Instant now方法默认使用的是UTC,协调世界时。now(Clock clock)方法 clock参数可以设置时区信息,就可以获取不同时区的Instant,比如 Clock systemDefaultZone()
或指定时区 Clock system(ZoneId zone)等。

4.2 获取时间戳

public long toEpochMilli() 获取时间戳 单位为毫秒。
public long getEpochSecond() 获取时间戳 单位为秒。

   通过上面可以看出,时间戳是所有时间创建和转换的基础,通过简单的System.currentTimeMillis()获取到,但时间戳只是一个简单的数字,不转换为其他时间类没有意义,比如 年、月、日、时、分、秒、星期、闰年、时区、夏令时等,更多相关的比如各种节假日,星座等附加意义的信息。

源代码地址:https://github.com/xkzhangsan/xk-time