Java日期时间API系列31

Wesley13
• 阅读 800

  时间戳是指格林威治时间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() 获取时间戳 单位为秒。

5.总结

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

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

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Karen110 Karen110
2年前
一篇文章带你了解JavaScript日期
日期对象允许您使用日期(年、月、日、小时、分钟、秒和毫秒)。一、JavaScript的日期格式一个JavaScript日期可以写为一个字符串:ThuFeb02201909:59:51GMT0800(中国标准时间)或者是一个数字:1486000791164写数字的日期,指定的毫秒数自1970年1月1日00:00:00到现在。1\.显示日期使用
Wesley13 Wesley13
2年前
java常用类(2)
三、时间处理相关类Date类:计算机世界把1970年1月1号定为基准时间,每个度量单位是毫秒(1秒的千分之一),用long类型的变量表示时间。Date分配Date对象并初始化对象,以表示自从标准基准时间(称为“历元”(epoch),即1970年1月1日08:00:00GMT)以来的指定毫秒数。示例:packagecn.tanjian
Souleigh ✨ Souleigh ✨
3年前
python时间模块的使用 white_study
前言:在开发中经常会与时间打交道,如:获取事件戳,时间戳的格式化等,这里简要记录一下python操作时间的方法。python中常见的处理时间的模块:time:处理时间的模块,如获取时间戳,格式化日期等datetime:date和time的结合体,处理日期和时间calendar:日历相关的模块,如:处理年历/月历tim
捉虫大师 捉虫大师
3年前
低开销获取时间戳
前言在前面文章中提了一句关于时间戳获取性能的问题获取操作系统时间,在Java中直接调用System.currentTimeMillis();就可以,但在Cobar中如果这么获取时间,就会导致性能损耗非常严重(怎么解决?去Cobar的github仓库上看看代码吧)。这个话题展开具体说说,我们在Java中获取时间戳的方法是System.currentTim
Karen110 Karen110
2年前
​一篇文章总结一下Python库中关于时间的常见操作
前言本次来总结一下关于Python时间的相关操作,有一个有趣的问题。如果你的业务用不到时间相关的操作,你的业务基本上会一直用不到。但是如果你的业务一旦用到了时间操作,你就会发现,淦,到处都是时间操作。。。所以思来想去,还是总结一下吧,本次会采用类型注解方式。time包importtime时间戳从1970年1月1日00:00:00标准时区诞生到现在
Wesley13 Wesley13
2年前
mysql简单常用语句汇总
1\.常用函数uuid和时间戳SELECTUUID(),UNIX_TIMESTAMP();将时间戳转为日期格式FROM_UNIXTIME(mw.created_at,'%Y%m%d%H:%i:%s')设置参数select@m_no:max(m_no)fromvc_m;set@m
Stella981 Stella981
2年前
Python之time模块的时间戳、时间字符串格式化与转换
Python处理时间和时间戳的内置模块就有time,和datetime两个,本文先说time模块。关于时间戳的几个概念时间戳,根据1970年1月1日00:00:00开始按秒计算的偏移量。时间元组(struct_time),包含9个元素。 time.struct_time(tm_y
Stella981 Stella981
2年前
HIVE 时间操作函数
日期函数UNIX时间戳转日期函数: from\_unixtime语法:   from\_unixtime(bigint unixtime\, string format\)返回值: string说明: 转化UNIX时间戳(从19700101 00:00:00 UTC到指定时间的秒数)到当前时区的时间格式举例:hive   selec
Wesley13 Wesley13
2年前
Java日期时间API系列23
  有时候,往往需要统计某个时间区间的销量等问题,这就需要准确的起始时间,获取准确开始时间00:00:00,获取准确结束时间23:59:59。下面增加了一一些方法,获取当天起始时间,昨天起始时间,当前月第一天开始时间,当前月最后一天结束时间,上个月第一天开始时间,上个月最后一天结束时间,某个指定月的起始结束时间等等。其中月份最后一天往往因为月份不同和