zoukankan      html  css  js  c++  java
  • java8 Date/Time API 新的日期处理工具

    接上篇文章 java8 新特性 由于上篇过于庞大,使得重点不够清晰,本篇单独拿出 java8 的 Date/Time api 进行说明,新的日期时间工具全部都在 java.time 及其子包中。

    新 Date/Time API 设计原则

    Java 8日期/时间API是 JSR-310 规范的实现,它的目标是克服旧的日期/时间API实现中所有的缺陷,新的日期/时间API的一些设计原则如下:

    • 不变性:新的日期/时间API中,所有的类都是不可变的,这种设计有利于并发编程。
    • 关注点分离:新的API将人可读的日期时间和机器时间(unix timestamp)明确分离,它为日期(Date)、时间(Time)、日期时间(DateTime)、时间戳(unix timestamp)以及时区定义了不同的类。
    • 清晰:在所有的类中,方法都被明确定义用以完成相同的行为。举个例子,要拿到当前实例我们可以使用now()方法,在所有的类中都定义了format()和parse()方法,而不是像以前那样专门有一个独立的类。为了更好的处理问题,所有的类都使用了工厂模式和策略模式,一旦你使用了其中某个类的方法,与其他类协同工作并不困难。
    • 实用操作:所有新的日期/时间API类都实现了一系列方法用以完成通用的任务,如:加、减、格式化、解析、从日期/时间中提取单独部分等操作。
    • 可扩展性:新的日期/时间API是工作在ISO-8601日历系统上的,但我们也可以将其应用在非IOS的日历上。

    常用类及其使用

    时间大致可以分为三个部分:日期、时间、时区;其中日期又细分为年、月、日;时间又细分为时、分、秒

    一般机器时间用从 1970-01-01T00:00 到现在的秒数来表示时间; 这里纠正大部分人犯的一个错误概念,时间戳指的是秒数,而不是毫秒数。

    几乎所有的时间对象都实现了 Temporal 接口,所以接口参数一般都是 Temporal

    • Instant: 表示时间线上的一个点,参考点是标准的Java纪元(epoch),即1970-01-01T00:00:00Z(1970年1月1日00:00 GMT)

    • LocalDate: 日期值对象如 2019-09-22

    • LocalTime:时间值对象如 21:25:36

    • LocalDateTime:日期+时间值对象

    • ZoneId:时区

    • ZonedDateTime:日期+时间+时区值对象

    • DateTimeFormatter:用于日期时间的格式化

    • Period:用于计算日期间隔

    • Duration:用于计算时间间隔

    Instant 表示时间线上的一个点(瞬时)

    // 测试执行一个 new 操作使用的时间(纳秒值)
    Instant begin = Instant.now();
    StreamMain streamMain = new StreamMain();
    Instant end = Instant.now();
    System.out.println(Duration.between(begin,end).toNanos());
    

    LocalDateLocalTimeLocalDateTimeZonedDateTime 可以规为一组,用于表示时间的

    // 可以使用 of 方法构建它们的实例,如下面创建了一个 2019-9-22 21:42:59 东八区 的时间对象 
    LocalDate localDate = LocalDate.of(2019, Month.SEPTEMBER, 22);
    LocalTime localTime = LocalTime.of(21, 42, 59);
    LocalDateTime localDateTime = LocalDateTime.of(localDate, localTime);
    ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, ZoneId.systemDefault());
    
    // 获取现在的时间,这是一个静态方法
    LocalDate now = LocalDate.now();
    
    // 每个实例可以获取它们的 part 信息,如获取年 
    int year = localDate.getYear();
    
    // 可以修改 part 信息,这将返回一个新对象,如增加一年
    LocalDate localDatePlus = localDate.plusYears(1);
    
    // 设置 part 信息,也会返回新的对象,如设置为 2017 年 
    LocalDate localDateWithYear = localDate.withYear(2017);
    
    // 比较两个日期 isAfter,isBefore
    boolean after = localDate.isAfter(LocalDate.now());
    
    // 格式化日期时间
    // yyyy-MM-dd
    System.out.println(now.format(DateTimeFormatter.ISO_DATE));
    // yyyy-MM-ddTHH:mm:ss
    System.out.println(now.format(DateTimeFormatter.ISO_DATE_TIME));
    // yyyy-MM-dd HH:mm:ss
    System.out.println(now.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)));
    
    // 日期解析 
    System.out.println(LocalDate.parse("2019-09-22"));
    System.out.println(LocalDateTime.parse("2019-09-22T21:05:22"));
    System.out.println(LocalDateTime.parse("2019-09-22 21:05:22",DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)));
    

    ZoneId 用来操作时区,它提供了获取所有时区和本地时区的方法

    ZoneId zoneId = ZoneId.systemDefault();
    Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();
    

    PeriodDuration 可以视为一组,用于计算时间间隔

    // 创建一个两周的间隔
    Period periodWeeks = Period.ofWeeks(2);
    
    // 一年三个月零二天的间隔
    Period custom = Period.of(1, 3, 2);
    
    // 一天的时长
    Duration duration = Duration.ofDays(1);
    
    // 计算2015/6/16 号到现在 2019/09/22 过了多久,它这个把间隔分到每个 part 了
    LocalDate now = LocalDate.now();
    LocalDate customDate = LocalDate.of(2015, 6, 16);
    Period between = Period.between(customDate, now);
    // 结果为 4:3:6 即过去了 4年3个月6天了
    System.out.println(between.getYears()+":"+between.getMonths()+":"+between.getDays());
    
    // 比较两个瞬时的时间间隔 
    Instant begin = Instant.now();
    Instant end = Instant.now();
    Duration.between(begin,end);
    
    // 同样可以修改 part 信息和设置 part 信息,都是返回新的对象来表示设置过的值,原来的对象不变
    Period plusDays = between.plusDays(1);
    Period withDays = between.withDays(4);
    
    

    与 Date,Calendar 的转换

    虽然说,这个新的时间工具很好用,但如果不能与以前的旧的 api 兼容的话,一样是没有用的;还好新的工具类能很好的与以前的工具类进行相互转换。

    通过 Instant做中间转换实现DateCalendarLocalDateTimeZonedDateTimeLocalDate 的互相转换

    // LocalDateTime 转 Date
    Date localDateTimeDate = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    // LocalDateTime 转 Calendar
    Calendar localDateTimeCalendar = GregorianCalendar.from(ZonedDateTime.of(localDateTime, ZoneId.systemDefault()));
    
    // Date 转 LocalDateTime
    LocalDateTime dateLocalDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
    // Calendar 转 LocalDateTime
    LocalDateTime calendarLocalDateTime = LocalDateTime.ofInstant(calendar.toInstant(), ZoneOffset.systemDefault());
    

    相关源码位置

    https://gitee.com/sanri/example/tree/master/testjava8

    一点小推广

    创作不易,希望可以支持下我的开源软件,及我的小工具,欢迎来 gitee 点星,fork ,提 bug 。

    Excel 通用导入导出,支持 Excel 公式
    博客地址:https://blog.csdn.net/sanri1993/article/details/100601578
    gitee:https://gitee.com/sanri/sanri-excel-poi

    使用模板代码 ,从数据库生成代码 ,及一些项目中经常可以用到的小工具
    博客地址:https://blog.csdn.net/sanri1993/article/details/98664034
    gitee:https://gitee.com/sanri/sanri-tools-maven

  • 相关阅读:
    安卓学习第12课——SimpleAdapter
    用栈结构实现多项式计算器
    用B-树实现虚拟图书管理系统
    HDU4791【杂】
    HDU4801【DFS】
    萌新学习图的强连通(Tarjan算法)笔记
    Lightoj 1021【状压DP(未搞)】
    Lightoj 1008【规律】
    CodeForces Canada Cup 2016【A,B,C,D】
    51nod 1068【简单博弈】
  • 原文地址:https://www.cnblogs.com/sanri1993/p/11580511.html
Copyright © 2011-2022 走看看