工作这么久了,对于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 获取当前时间

LocalDateTimelocalDateTime=LocalDateTime.now();

// 打印结果: 2019-12-02T22:09:20.503

1.2 获取指定时间

// 获取 2019年12月02号 23 : 59 : 59

LocalDateTimelocalDateTime2=LocalDateTime.of(2019,12,2,23,59,59);

// 打印结果:2019-12-02T13:20:20

1.3 日期/时间加减操作

// localDateTime2的基础上加1天零1s

LocalDateTimelocalDateTime3=localDateTime2.plusDays(1).plusSeconds(1);

// 打印结果:2019-12-04T00:00

1.4 获取指定的字段(年月日时分秒,纳秒,不支持毫秒)

System.out.println("现在是: "+localDateTime.getYear()+" 年中的第 "+localDateTime.getDayOfYear()+" 天");

// 打印结果:现在是: 2019 年中的第 336 天

// 画外音:快过年了呀,感觉这一年又没啥收获

二,给计算机读的(Instant)

小知识:地球上不同地区经度不同会划分时区,以零度经线上为准(格林尼治天文台旧址,UTC时区)为准,将地球上各个部分分为了24个时区。向西走,每过一个时区,就要把表拨慢1个小时;同理每向东走一个时区,就要把表拨快1个小时。最后,中国处于东8区。

2.1 获取UTC时间(格林尼治时间)

Instantinstant=Instant.now();

// 打印结果:2019-12-02T14:31:41.661Z

2.2 获取北京时间(东8区)

// OffsetTime表示有时差的时间,除了UTC时间,都是OffsetTime

OffsetDateTimeoffsetDateTime=instant.atOffset(ZoneOffset.ofHours(8));

// 打印结果:2019-12-02T22:31:41.661+08:00

2.3 获取毫秒数(1970-01-01T00:00:00Z开始计算)

longepochMilli=instant.toEpochMilli()

// 打印结果:1575297101661

2.4 定义时间戳

Instantinstant1=Instant.ofEpochSecond(59);

// 打印结果:1970-01-01T00:00:59Z

instant2=instant1.plusSeconds(99)

// 打印结果:2019-12-02T14:43:00.402Z

三, 时间间隔(Duration)

3.1 计算日期间隔(参数位置影响结果哦)

Instantinstant1=Instant.now();

Instantinstant2=instant1.plusSeconds(99);

Durationduration1=Duration.between(instant1,instant2);

Durationduration2=Duration.between(instant2,instant1);

// 打印结果 duration1:PT1M39S

// 打印结果 duration2:PT-1M-39S

longduration1Seconds=duration1.getSeconds();

longduration2Seconds=duration1.getSeconds();

// 打印结果 duration1Seconds:90

// 打印结果 duration2Seconds:-90

3.2 操作时间间隔

Durationduration3=duration1.plusDays(1);

// 打印结果:PT24H1M39S

注意 : 仅支持时间操作(Instant, LocalTime,LocalDateTime),不支持日期(LocalDate)

四,日期间隔(Period)

LocalDatelocalDate1=LocalDate.now();

LocalDatelocalDate2=localDate1.plusDays(1);

Periodperiod=Period.between(localDate1,localDate2);

longdays=period.getDays();

// 打印结果 peroid:P1D

// 打印结果 days:1

五,日期/时间校正器(TemporalAdjuster)

5.1 获取指定日期或时间

LocalDateTimelocalDateTime1=LocalDateTime.now();

LocalDateTimelocalDateTime2=localDateTime.withDayOfMonth(20);

// 打印结果 localDateTime1:2019-12-02T22:57:47.674

// 打印结果 localDateTime2:2019-12-20T22:57:47.674

5.2 获取下一个固定日期(下一个星期天)

LocalDateTimelocalDateTime3=localDateTime.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));

// 打印结果 localDateTime33:2019-12-08T23:00:43.101

5.3 自定义矫正器

// 获取下一个工作日

LocalDateTimelocalDateTime4=localDateTime.with((tempDateTime)->{

LocalDateTimelocalDateTime5=(LocalDateTime)tempDateTime;

DayOfWeekdayOfWeek=localDateTime5.getDayOfWeek();

if(dayOfWeek.equals(DayOfWeek.FRIDAY)){

returnlocalDateTime5.plusDays(3);

}elseif(dayOfWeek.equals(DayOfWeek.SATURDAY)){

returnlocalDateTime5.plusDays(2);

}else{

returnlocalDateTime5.plusDays(1);

}

});

// 打印结果 localDateTime4:2019-12-03T23:00:43.101

六,日期时间格式化

DateTimeFormatterdateTimeFormatter=DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

LocalDateTimelocalDateTime=LocalDateTime.now();

StringdateStr=dateTimeFormatter.format(localDateTime);

// 打印结果: 2019-12-02 23:08:55

LocalDateTimelocalDateTime2=LocalDateTime.parse(dateStr,dateTimeFormatter);

// 打印结果: 2019-12-02T23:08:55

LocalDatelocalDate=LocalDate.parse(dateStr,dateTimeFormatter);

// 打印结果: 2019-12-02

七,基于Instant进行转换

java8api对于时间戳,日期时间以及老版本的Date对象之间的转换也进行了兼容和适配,所有的转换操作都可以基于Instant对象进行。由于LocalDate,LocalTime和LocalDateTime三个类的操作完全一样,所以下文仍使用LocalDateTime演示。

7.1 时间戳转LocalDate,LocalDate,LocalDateTime

longtimestamp=Instant.now().toEpochMilli();

LocalDateTimelocalDateTime=Instant.ofEpochMilli(timestamp).atOffset(ZoneOffset.ofHours(8)).toLocalDateTime();

// 打印结果:2019-12-02T23:20:25.791

7.2 LocalDate,LocalDate,LocalDateTime转时间戳

LocalDateTimelocalDateTime=LocalDateTime.now();

longtimestamp=localDateTime.toInstant(ZoneOffset.ofHours(8)).toEpochMilli();

// 打印结果:1575300368099

7.3 兼容就版本Date

LocalDateTimelocalDateTime3=LocalDateTime.now();Datedate=

Date.from(localDateTime.atZone(ZoneOffset.ofHours(8)).toInstant());LocalDateTimelocalDateTime4=

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中的无锁并发策略可以分为三种:

Copy On Write:写时复制是指:在并发访问的情景下,当需要修改JAVA中Containers的元素时,不直接修改该容器,而是先复制一份副本,在副本上进行修改。修改完成之后,将指向原来容器的引用指向新的容器(副本容器)

ThreadLocal:线程本地存储,就是为每一个线程创建一个变量,只有本线程可以在该变量中查看和修改值。

8.2 Question

这是一道送分题:正如上文提到的,Java8之前的日期时间以及格式化类是线程不安全的,你知道怎么编写测试代码吗?

java 月份适配计算_Java8中的时间日期API这么好用,你居然还没有掌握?相关推荐

  1. java 月份适配计算_js+rem动态计算font-size的大小适配各种手机设备

    需求:在不同的移动终端设备中实现,UI设计稿的等比例适配. 方案:使用js动态改变html的字体大小font-size+rem的特性,来保证最初的设计图中每个元素的尺寸比例不变,以适用于不同尺寸的设备 ...

  2. Java 8中的时间日期库DateTime API及示例

    点击蓝色"程序猿DD"关注我 回复"资源"获取独家整理的学习资料! Java8新特性的功能已经更新了不少篇幅了,今天重点讲解时间日期库中DateTime相关处理 ...

  3. java instant获取微秒转成日期格式_Java8新特性时间日期库DateTime API及示例

    点击上方蓝字关注「程序新视界」 Java8新特性的功能已经更新了不少篇幅了,今天重点讲解时间日期库中DateTime相关处理.同样的,如果你现在依旧在项目中使用传统Date.Calendar和Simp ...

  4. Spring Boot和Feign中使用Java 8时间日期API(LocalDate等)的序列化问题

    LocalDate. LocalTime. LocalDateTime是Java 8开始提供的时间日期API,主要用来优化Java 8以前对于时间日期的处理操作.然而,我们在使用Spring Clou ...

  5. feign 序列化_Spring Boot和Feign中使用Java 8时间日期API(LocalDate等)的序列化问题...

    LocalDate.LocalTime.LocalDateTime是Java 8开始提供的时间日期API,主要用来优化Java 8以前对于时间日期的处理操作.然而,我们在使用Spring Boot或使 ...

  6. sqlserver获取前一天的日期_Java8新特性时间日期库DateTime API及示例

    点击上方蓝字关注「程序新视界」 Java8新特性的功能已经更新了不少篇幅了,今天重点讲解时间日期库中DateTime相关处理.同样的,如果你现在依旧在项目中使用传统Date.Calendar和Simp ...

  7. java8 时间加一秒_java8 时间加一秒_java8新的时间日期库及使用示例

    来自:Java译站 链接:http://it.deepinmind.com/java/2015/03/17/20-examples-of-date-and-time-api-from-Java8.ht ...

  8. java记事本获取当前时间_calendar 用Java写的日历,有查询时间日期,还有记事本以及到点提醒功能。 Develop 238万源代码下载- www.pudn.com...

    文件名称: calendar下载 收藏√  [ 5  4  3  2  1 ] 开发工具: Java 文件大小: 4465 KB 上传时间: 2013-06-30 下载次数: 3 提 供 者: 陈园园 ...

  9. c语言编程时间,C语言中读取时间日期的基本方法

    C语言time()函数:获取当前时间(以秒数表示)头文件: #include 定义函数: time_t time(time_t *t); 函数说明:此函数会返回从公元 1970 年1 月1 日的UTC ...

最新文章

  1. 智能驾驶时代已经到来
  2. Quick-cocos2d-x3.3 Study (十五)--------- 为小鸟添加一个物理加速度
  3. 记一次windows的安装
  4. 保镖机器人作文_我的保镖作文500字
  5. python opencv ImportError: libGL.so.1: cannot open shared object file: No such file or directory
  6. .NET语言的编译过程:中间语言(IL)和即时编译器(JIT)
  7. 抛开vue-cli 利用requireJS搭建一个vue项目
  8. qt 16进制字符串和十六进制数_Python字符串类型及其操作
  9. Flex builder3与eclipse整合 转载
  10. CentOS7.7安装MySQL5.6并配置环境变量(详细版)
  11. 三分钟小课堂-----------------docker(三)增删改查命令
  12. rsync + inotify数据同步
  13. strategy dynamic参数的使用
  14. python 随机种子 时间_python课堂整理24----时间和随机数模块
  15. 项目管理十大知识领域运用流程
  16. 嵌入式系统课程大作业设计报告
  17. 计算机信息系统集成高级工程师,软考信息系统项目管理师(高级资格/高级工程师)简介...
  18. 经典的面板数据集(R语言包plm)
  19. Python报错:PermissionError: [Errno 13] Permission denied解决方案详解
  20. 关于C++ non-aggregate cannot be initialized错误的解决

热门文章

  1. HDMI 1.4和HDMI 2.0区别
  2. 怎样在Mac上的Safari中观看YouTube画中画?
  3. 在日签证更新手续 网址
  4. Go语言开发工具 LiteIDE X27 发布
  5. 纽约大学历年本科生录取数据分析
  6. 如何让您的CEO沉迷于客户反馈
  7. Ubuntu防火墙状态整理
  8. idea2020无限重置
  9. 100本最棒的web前端图书推荐
  10. 5 款最棒的 Vue 移动端 UI 组件库 - 特别针对国内使用场景推荐