java自学教程|www.konglongmei.com

作者: 馥琳
查看: 90|回复: 0

more +社区更新Forums

more +随机图赏Gallery

疯狂Java讲义(第4版) PDF 电子书 百度云 网盘下载疯狂Java讲义(第4版) PDF 电子书 百度云 网盘下载
价值825元 牛客算法通关课程视频教程 第六期 百度云 网盘下载价值825元 牛客算法通关课程视频教程 第六期 百度云 网盘下载
Spring 5核心原理与30个类手写实战 PDF 电子书 百度云 网盘下载Spring 5核心原理与30个类手写实战 PDF 电子书 百度云 网盘下载
Spring 5核心原理与30个类手写实战+Spring Boot编程思想核心篇pdfSpring 5核心原理与30个类手写实战+Spring Boot编程思想核心篇pdf
Spring Boot编程思想核心篇+Spring 5核心原理与30个类手写实战pdfSpring Boot编程思想核心篇+Spring 5核心原理与30个类手写实战pdf
java电子书]微服务架构设计模式 PDF 电子书 百度云 网盘下载java电子书]微服务架构设计模式 PDF 电子书 百度云 网盘下载

[技术知识] 都9012了,Java8中的日期时间API你还没有掌握?

[技术知识] 都9012了,Java8中的日期时间API你还没有掌握?

[复制链接]
馥琳 | 显示全部楼层 发表于: 7 天前
馥琳 发表于: 7 天前 | 显示全部楼层 |阅读模式
查看: 90|回复: 0
工作这么久了,对于Java中时间日期的操作一直很蛋疼,一会用Date,一会用Calendar一会用LocalDateTime,始终没有认真总结过它们的联系与区别。迷迷糊糊用了好几年了,今天终于搞清楚了!
一,Java8日期时间API产生的前因后果

1.1 为什么要重新定义一套日期时间API

  • 操作不方便:java中最初的Date不能直接对指定字段进行加减操作也不支持国际化,后来新增了Calendar,但是Calendar又不支持格式化操作,需要转换成Date再进行格式化,总之一直在填坑,使用起来一点都不够优雅。
  • 线程不安全:Date,Caleandar,SimpleDateFormat都是可变的,线程不安全的,所以你需要编写额外的代码处理线程安全问题。
1.2 Java8重新定义

  • 对时间日期相关操作进行细分:时间,日期,日期&时间,时间戳,时间段,日期段,格式化等
  • 所有类都是不可变的,线程安全
  • 兼容旧的日期时间

1.3Java8兼容就版本的Date,同时也规范了日期时间的转换流程。

一,给人读的( LocalDateTime & LocalDate & LocalTime)

java8中将时间和日期进行的区分,用LocalDateTime表示日期和时间,LocalDate用来表示日期而LocalTime表示时间。内部实现也非常好理解,LocalDateTime = LocalDate + LocalTime,并且他们的内部api也一致,所以笔者就结合工作中的经验,介绍他们最常见的用法。
1.1 获取当前时间
  1. LocalDateTime localDateTime = LocalDateTime.now();// 打印结果: 2019-12-02T22:09:20.503
复制代码
1.2 获取指定时间
  1. // 获取 2019年12月02号 23 : 59 : 59 LocalDateTime localDateTime2 = LocalDateTime.of(2019, 12, 2, 23, 59, 59);// 打印结果: 2019-12-02T13:20:20
复制代码
1.3 日期/时间加减操作
  1. // localDateTime2的基础上加1天零1sLocalDateTime localDateTime3 = localDateTime2.plusDays(1).plusSeconds(1);// 打印结果:2019-12-04T00:00
复制代码
1.4 获取指定的字段(年月日时分秒,纳秒,不支持毫秒)
  1. System.out.println("现在是: " + localDateTime.getYear() + " 年中的第 " + localDateTime.getDayOfYear() +" 天");// 打印结果:现在是: 2019 年中的第 336 天 // 画外音: 快过年了呀,感觉这一年又没啥收获
复制代码
二,给计算机读的(Instant)

小知识:地球上不同地区经度不同会划分时区,以零度经线上为准(格林尼治天文台旧址,UTC时区)为准,将地球上各个部分分为了24个时区。向西走,每过一个时区,就要把表拨慢1个小时;同理每向东走一个时区,就要把表拨快1个小时。最后,中国处于东8区。
2.1 获取UTC时间(格林尼治时间)
  1. Instant instant = Instant.now();// 打印结果: 2019-12-02T14:31:41.661Z
复制代码
2.2 获取北京时间(东8区)
  1. // OffsetTime表示有时差的时间,除了UTC时间,都是OffsetTimeOffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8));// 打印结果: 2019-12-02T22:31:41.661+08:00
复制代码
2.3 获取毫秒数(1970-01-01T00:00:00Z开始计算)
  1. long epochMilli = instant.toEpochMilli()// 打印结果:1575297101661
复制代码
2.4 定义时间戳
  1. Instant instant1 = Instant.ofEpochSecond(59);// 打印结果: 1970-01-01T00:00:59Zinstant2 = instant1.plusSeconds(99)// 打印结果:2019-12-02T14:43:00.402Z
复制代码
三, 时间间隔(Duration)

3.1 计算日期间隔(参数位置影响结果哦)
  1. Instant instant1 = Instant.now();Instant instant2 = instant1.plusSeconds(99);Duration duration1 = Duration.between(instant1, instant2);Duration duration2 = Duration.between(instant2, instant1);// 打印结果 duration1:PT1M39S// 打印结果 duration2:PT-1M-39Slong duration1Seconds = duration1.getSeconds();long duration2Seconds = duration1.getSeconds();// 打印结果 duration1Seconds: 90// 打印结果 duration2Seconds: -90
复制代码
3.2 操作时间间隔
  1. Duration duration3 = duration1.plusDays(1);// 打印结果:PT24H1M39S
复制代码
注意 : 仅支持时间操作(Instant, LocalTime,LocalDateTime),不支持日期(LocalDate)
四,日期间隔(Period)
  1. LocalDate localDate1 = LocalDate.now();LocalDate localDate2 = localDate1.plusDays(1);Period period = Period.between(localDate1, localDate2);long days =  period.getDays();// 打印结果 peroid: P1D// 打印结果 days: 1
复制代码
五,日期/时间校正器(TemporalAdjuster)

5.1 获取指定日期或时间
  1. LocalDateTime localDateTime1 = LocalDateTime.now();LocalDateTime localDateTime2 = localDateTime.withDayOfMonth(20);// 打印结果 localDateTime1:2019-12-02T22:57:47.674// 打印结果 localDateTime2:2019-12-20T22:57:47.674
复制代码
5.2 获取下一个固定日期(下一个星期天)
  1. LocalDateTime localDateTime3 = localDateTime.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));// 打印结果 localDateTime33:2019-12-08T23:00:43.101
复制代码
5.3 自定义矫正器
  1. // 获取下一个工作日    LocalDateTime localDateTime4 = localDateTime.with((tempDateTime) -> {            LocalDateTime localDateTime5 = (LocalDateTime) tempDateTime;            DayOfWeek dayOfWeek = localDateTime5.getDayOfWeek();            if (dayOfWeek.equals(DayOfWeek.FRIDAY)) {                    return localDateTime5.plusDays(3);            } else if (dayOfWeek.equals(DayOfWeek.SATURDAY)) {                    return localDateTime5.plusDays(2);            } else {                    return localDateTime5.plusDays(1);            }    });// 打印结果 localDateTime4:2019-12-03T23:00:43.101
复制代码
六,日期时间格式化
  1. DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");LocalDateTime localDateTime = LocalDateTime.now();String dateStr =dateTimeFormatter.format(localDateTime);// 打印结果: 2019-12-02 23:08:55LocalDateTime localDateTime2 = LocalDateTime.parse(dateStr, dateTimeFormatter);// 打印结果: 2019-12-02T23:08:55LocalDate localDate = LocalDate.parse(dateStr, dateTimeFormatter);// 打印结果: 2019-12-02
复制代码
七,基于Instant进行转换

java8api对于时间戳,日期时间以及老版本的Date对象之间的转换也进行了兼容和适配,所有的转换操作都可以基于Instant对象进行。由于LocalDate,LocalTime和LocalDateTime三个类的操作完全一样,所以下文仍使用LocalDateTime演示。
7.1 时间戳转LocalDate,LocalDate,LocalDateTime
  1. long timestamp = Instant.now().toEpochMilli();LocalDateTime localDateTime = Instant.ofEpochMilli(timestamp).atOffset(ZoneOffset.ofHours(8)).toLocalDateTime();// 打印结果:2019-12-02T23:20:25.791
复制代码
7.2 LocalDate,LocalDate,LocalDateTime转时间戳
  1. LocalDateTime localDateTime = LocalDateTime.now();long timestamp = localDateTime.toInstant(ZoneOffset.ofHours(8)).toEpochMilli();// 打印结果:1575300368099
复制代码
7.3 兼容就版本Date
  1. LocalDateTime localDateTime3 = LocalDateTime.now();Date date = Date.from(localDateTime.atZone(ZoneOffset.ofHours(8)).toInstant());LocalDateTime localDateTime4  = localDateTime3.atZone(ZoneOffset.ofHours(8)).toLocalDateTime();// 打印结果 date:Mon Dec 02 23:32:53 CST 2019// 打印结果 lcoalDateTime4:2019-12-02T23:32:53.188
复制代码
八, Q&A

上一篇问题:在java中通常使用synchronized来实现方法同步,AQS中通过CAS保证了修改同步状态的一致性问题,那么对比synchronized,cas有什么优势不同与优势呢?你还知道其他无锁并发的策略吗?
8.1 Answer
Java中的无锁并发策略可以分为三种:

  • 基于乐观锁的CAS操作
  • Copy On Write:写时复制是指:在并发访问的情景下,当需要修改JAVA中Containers的元素时,不直接修改该容器,而是先复制一份副本,在副本上进行修改。修改完成之后,将指向原来容器的引用指向新的容器(副本容器)
  • ThreadLocal:线程本地存储,就是为每一个线程创建一个变量,只有本线程可以在该变量中查看和修改值。
8.2 Question

  • 这是一道送分题:正如上文提到的,Java8之前的日期时间以及格式化类是线程不安全的,你知道怎么编写测试代码吗?
  • 如果优雅得获取昨天0点整的毫秒值?
学习Java过程中可能遇到问题和困惑,关注我vx公众号 “cruder” ,后台留言,笔者帮你一起解决!(需要学习资料的请关注后后台留言,主要都是java相关,java基础,并发,mysql,redis,es,mq等都都有!)


鲁班 Java架构师VIP课程一期共89G视频教程 luban it教程下载:http://www.77cxw.com/download/78
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|网站地图|java自学教程|www.konglongmei.com

GMT+8, 2019-12-10 10:19 , Processed in 0.143647 second(s), 47 queries .

快速回复 返回顶部 返回列表