zoukankan      html  css  js  c++  java
  • Java8 时间API

    Java8中,java.time主要包含下面几个类

    Instant:时间戳
    Duration:持续时间,时间差
    LocalDate:只包含日期,比如:2016-10-20
    LocalTime:只包含时间,比如:23:12:10
    LocalDateTime:包含日期和时间,比如:2016-10-20 23:14:21
    Period:时间段
    ZoneOffset:时区偏移量,比如:+8:00
    ZonedDateTime:带时区的时间
    Clock:时钟,比如获取目前美国纽约的时间
    

    以及java.time.format中的时间格式化类

    DateTimeFormatter:时间格式化
    
    1. 时间格式化
    # 时间 -> 字符串
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");
    String datetime = LocalDateTime.now(ZoneOffset.of("+8")).format(formatter);
    
    
    # 字符串 -> 时间
    String dateTimeStr = "2019-07-23 11:38:15";
    DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    LocalDateTime dateTime = LocalDateTime.parse(dateTimeStr, df);
    
    1. Date和LocalDateTime
    //将java.util.Date 转换为java8 的java.time.LocalDateTime,默认时区为东8区
        public static LocalDateTime dateConvertToLocalDateTime(Date date) {
            return date.toInstant().atOffset(ZoneOffset.of("+8")).toLocalDateTime();
        }
     
       
        //将java8 的 java.time.LocalDateTime 转换为 java.util.Date,默认时区为东8区
        public static Date localDateTimeConvertToDate(LocalDateTime localDateTime) {
            return Date.from(localDateTime.toInstant(ZoneOffset.of("+8")));
        }
     
     
        /**
         * 测试转换是否正确
         */
        @Test
        public void testDateConvertToLocalDateTime() {
            Date date = DateUtils.parseDate("2019-07-23 11:38:15", DateUtils.DATE_YMDHMS);
            LocalDateTime localDateTime = DateUtils.dateConvertToLocalDateTime(date);
            Long localDateTimeSecond = localDateTime.toEpochSecond(ZoneOffset.of("+8"));
            Long dateSecond = date.toInstant().atOffset(ZoneOffset.of("+8")).toEpochSecond();
            Assert.assertTrue(dateSecond.equals(localDateTimeSecond));
        }
    

    1、获取今天的日期

    LocalDate todayDate = LocalDate.now();
    System.out.println("今天的日期:"+todayDate);
    //结果
    今天的日期:2016-10-20
    

    2、指定日期,进行相应操作

    //取2016年10月的第1天
    LocalDate firstDay = oneday.with(TemporalAdjusters.firstDayOfMonth());
    System.out.println(firstDay);
            
    //取2016年10月的第1天,另外一种写法
    LocalDate firstDay2 = oneday.withDayOfMonth(1);
    System.out.println(firstDay2);
            
    //取2016年10月的最后1天,不用考虑大月,小月,平年,闰年
    LocalDate lastDay = oneday.with(TemporalAdjusters.lastDayOfMonth());
    System.out.println(lastDay);
            
    //当前日期+1天
    LocalDate tomorrow = oneday.plusDays(1);
    System.out.println(tomorrow);
    
    //判断是否为闰年
    boolean isLeapYear = tomorrow.isLeapYear();
    System.out.println(isLeapYear);
    
    //运行结果
    2016-10-20
    2016-10-01
    2016-10-01
    2016-10-31
    2016-10-21
    true
    

    3、生日检查或者账单日检查

    开发过程中,经常需要为过生日的用户送上一些祝福,例如,用户的生日为1990-10-12,如果今天是2016-10-12,那么今天就是用户的生日(按公历/身份证日期来算),那么通过java8新的日期库,我们该如何来进行判断?

    在java8中,可以使用MonthDay,该类不包含年份信息,当然还有一个类是YearMonth

    LocalDate birthday = LocalDate.of(1990, 10, 12);
    MonthDay birthdayMd = MonthDay.of(birthday.getMonth(), birthday.getDayOfMonth());
    MonthDay today = MonthDay.from(LocalDate.of(2016, 10, 12)); 
            System.out.println(today.equals(birthdayMd));
    //结果
    true
    

    4、获取当前的时间

    日期主要是使用LocalTime,该类不包含日期,只有时间信息

    //获取当前的时间
    LocalTime nowTime = LocalTime.now(); //结果14:29:40.558
            
    //如果不想显示毫秒
    LocalTime nowTime2 = LocalTime.now().withNano(0); //14:43:14
            
    //指定时间
    LocalTime time = LocalTime.of(14, 10, 21); //14:10:21
    LocalTime time2 = LocalTime.parse("12:00:01"); // 12:00:01
            
    //当前时间增加2小时
    LocalTime nowTimePlus2Hour = nowTime.plusHours(2); //16:47:23.144
    //或者
    LocalTime nowTimePlus2Hour2 = nowTime.plus(2, ChronoUnit.HOURS);
    

    5、日期前后比较

    比较2个日期哪个在前,哪个在后,java8 LocalDate提供了2个方法,isAfter(),isBefore

    LocalDate today = LocalDate.now();
    LocalDate specifyDate = LocalDate.of(2015, 10, 20);
    System.out.println(today.isAfter(specifyDate)); //true
    

    6、处理不同时区的时间

    Java8中,将日期,时间,时区都很好的进行了分离。

    //查看当前的时区
    ZoneId defaultZone = ZoneId.systemDefault();
    System.out.println(defaultZone); //Asia/Shanghai
            
    //查看美国纽约当前的时间
    ZoneId america = ZoneId.of("America/New_York");
    LocalDateTime shanghaiTime = LocalDateTime.now();
    LocalDateTime americaDateTime = LocalDateTime.now(america);
    System.out.println(shanghaiTime); //2016-11-06T15:20:27.996
    System.out.println(americaDateTime); //2016-11-06T02:20:27.996 ,可以看到美国与北京时间差了13小时
        
    //带有时区的时间
    ZonedDateTime americaZoneDateTime = ZonedDateTime.now(america);
    System.out.println(americaZoneDateTime); //2016-11-06T02:23:44.863-05:00[America/New_York]
    

    7、比较两个日期之前时间差

    在项目中,经常需要比较两个日期之间相差几天,或者相隔几个月,我们可以使用java8的Period来进行处理。

    LocalDate today = LocalDate.now();
    LocalDate specifyDate = LocalDate.of(2015, 10, 2);
    Period period = Period.between(specifyDate, today);
    
    System.out.println(period.getDays());  //4
    System.out.println(period.getMonths()); //1
    System.out.println(specifyDate.until(today, ChronoUnit.DAYS)); //401
    //输出结果
    4
    1
    401
    

    我们可以看到,我们使用Period类比较天数,比较奇怪,他返回的值,并不是2个日期之间总共的天数差,而是一个相对天数差,比如,5月1日,和10月2日,他比较的是仅仅2个天之间的差,那1号和2号,相差1天,而实际上,因为中间相差了好几个月,所以真正的天数差肯定不是1天,所以我们可以使用until,并指明精度单位是days,就可以计算真正的天数差了。

    8、日期时间格式解析、格式化

    在java8之前,我们进行时间格式化主要是使用SimpleDateFormat,而在java8中,主要是使用DateTimeFormatter,java8中,预定义了一些标准的时间格式,我们可以直接将时间转换为标准的时间格式:

    String specifyDate = "20151011";
    DateTimeFormatter formatter = DateTimeFormatter.BASIC_ISO_DATE;
    LocalDate formatted = LocalDate.parse(specifyDate,formatter); 
    System.out.println(formatted); 
    //输出
    2015-10-11
    

    当然,很多时间标准的时间格式可能也不满足我们的要求,我们需要转为自定义的时间格式

    DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("YYYY MM dd");
    System.out.println(formatter2.format(LocalDate.now()));
    //结果
    2015 10 11
    

    9、java8 时间类与Date类的相互转化

    在转换中,我们需要注意,因为java8之前Date是包含日期和时间的,而LocalDate只包含日期,LocalTime只包含时间,所以与Date在互转中,势必会丢失日期或者时间,或者会使用起始时间。如果转LocalDateTime,那么就不存在信息误差。

    //Date与Instant的相互转化
    Instant instant  = Instant.now();
    Date date = Date.from(instant);
    Instant instant2 = date.toInstant();
            
    //Date转为LocalDateTime
    Date date2 = new Date();
    LocalDateTime localDateTime2 = LocalDateTime.ofInstant(date2.toInstant(), ZoneId.systemDefault());
            
    //LocalDateTime转Date
    LocalDateTime localDateTime3 = LocalDateTime.now();
    Instant instant3 = localDateTime3.atZone(ZoneId.systemDefault()).toInstant();
    Date date3 = Date.from(instant);
    
    //LocalDate转Date
    //因为LocalDate不包含时间,所以转Date时,会默认转为当天的起始时间,00:00:00
    LocalDate localDate4 = LocalDate.now();
    Instant instant4 = localDate4.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant();
    Date date4 = Date.from(instant);
    

    10. Instant 转 LocalDateTime

    Instant.ofEpochSecond(1564589028).atOffset(ZoneOffset.of("+8")).toLocalDateTime();
    

    为什么之前的时间操作类不建议使用了

    • 不支持时区,而且存在线程缺陷
    • 在格式化时间和解析时间时用的不是原子操作,如果多线程使用同一个sdf则可能会造成格式化异常。
  • 相关阅读:
    Nginx 重定向 伪静态 rewrite index.php
    centos安装lnmp
    spring @RequestBody 和 @RequestParams 同时使用
    idea 设置加载多个资源文件,显示本地图片
    阿里云栖社区dubbo 资源整理
    idea npm 调试报错解决办法
    git 设置了ssh key 还是需要输入账户和密码
    zookeeper系列 (第一章 :ubuntu 下安装zookeeper)
    linux 下node升级
    解决spring http输入流和输出流只能读取一次
  • 原文地址:https://www.cnblogs.com/iFanLiwei/p/12791235.html
Copyright © 2011-2022 走看看