• Java日期时间API系列31-----Jdk8中java.time包中的新的日期时间API类,时间戳的获取方式对比、转换和使用。


      时间戳是指格林威治时间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 > DateInstant > 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

  • 相关阅读:
    神经网络和Deep Learning
    SQL 优化tips 及误区
    特殊字符的八进制含义
    精通Web Analytics 2.0 (4) 第二章:选择你的网络分析灵魂伴侣的最佳策略
    前端学HTTP之客户端识别和cookie
    前端学HTTP之基本认证
    前端学HTTP之安全HTTP
    前端学HTTP之摘要认证
    前端学HTTP之字符集
    前端学HTTP之实体和编码
  • 原文地址:https://www.cnblogs.com/xkzhangsanx/p/12781987.html
Copyright © 2020-2023  润新知