Java日期时间API系列31

Wesley13
• 阅读 1104

  时间戳是指格林威治时间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
3年前
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
3年前
一篇文章带你了解JavaScript日期
日期对象允许您使用日期(年、月、日、小时、分钟、秒和毫秒)。一、JavaScript的日期格式一个JavaScript日期可以写为一个字符串:ThuFeb02201909:59:51GMT0800(中国标准时间)或者是一个数字:1486000791164写数字的日期,指定的毫秒数自1970年1月1日00:00:00到现在。1\.显示日期使用
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Wesley13 Wesley13
3年前
java常用类(2)
三、时间处理相关类Date类:计算机世界把1970年1月1号定为基准时间,每个度量单位是毫秒(1秒的千分之一),用long类型的变量表示时间。Date分配Date对象并初始化对象,以表示自从标准基准时间(称为“历元”(epoch),即1970年1月1日08:00:00GMT)以来的指定毫秒数。示例:packagecn.tanjian
Souleigh ✨ Souleigh ✨
4年前
python时间模块的使用 white_study
前言:在开发中经常会与时间打交道,如:获取事件戳,时间戳的格式化等,这里简要记录一下python操作时间的方法。python中常见的处理时间的模块:time:处理时间的模块,如获取时间戳,格式化日期等datetime:date和time的结合体,处理日期和时间calendar:日历相关的模块,如:处理年历/月历tim
Karen110 Karen110
3年前
​一篇文章总结一下Python库中关于时间的常见操作
前言本次来总结一下关于Python时间的相关操作,有一个有趣的问题。如果你的业务用不到时间相关的操作,你的业务基本上会一直用不到。但是如果你的业务一旦用到了时间操作,你就会发现,淦,到处都是时间操作。。。所以思来想去,还是总结一下吧,本次会采用类型注解方式。time包importtime时间戳从1970年1月1日00:00:00标准时区诞生到现在
Wesley13 Wesley13
3年前
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
3年前
Python之time模块的时间戳、时间字符串格式化与转换
Python处理时间和时间戳的内置模块就有time,和datetime两个,本文先说time模块。关于时间戳的几个概念时间戳,根据1970年1月1日00:00:00开始按秒计算的偏移量。时间元组(struct_time),包含9个元素。 time.struct_time(tm_y
Stella981 Stella981
3年前
HIVE 时间操作函数
日期函数UNIX时间戳转日期函数: from\_unixtime语法:   from\_unixtime(bigint unixtime\, string format\)返回值: string说明: 转化UNIX时间戳(从19700101 00:00:00 UTC到指定时间的秒数)到当前时区的时间格式举例:hive   selec
Wesley13 Wesley13
3年前
Java日期时间API系列23
  有时候,往往需要统计某个时间区间的销量等问题,这就需要准确的起始时间,获取准确开始时间00:00:00,获取准确结束时间23:59:59。下面增加了一一些方法,获取当天起始时间,昨天起始时间,当前月第一天开始时间,当前月最后一天结束时间,上个月第一天开始时间,上个月最后一天结束时间,某个指定月的起始结束时间等等。其中月份最后一天往往因为月份不同和