1 为什么需要新的日期和时间库?
Java开发人员的一个长期烦恼是对普通开发人员的日期和时间用例的支持不足。
例如,现有的类(例如java.util.Date和SimpleDateFormatter)是非线程安全的,从而导致用户潜在的并发问题,这不是一般开发人员在编写日期处理代码时会期望处理的问题。
一些日期和时间类还表现出相当差的API设计。例如,年份java.util.Date从1900开始,月份从1开始,天从0开始,这不是很直观。
这些问题以及其他一些问题导致第三方日期和时间库(例如Joda-Time)的欣欣向荣。
为了解决这些问题并在JDK内核中提供更好的支持,针对Java SE 8设计了一个新的没有这些问题的日期和时间API。该项目由Joda-Time(Stephen Colebourne)和Oracle的作者在JSR 310下共同领导,出现在Java SE 8软件包中java.time。
2 核心思想
不可变值类
Java现有格式化程序的严重缺陷之一是它们不是线程安全的。这给开发人员带来了负担,使其需要以线程安全的方式使用它们并在其日常处理日期处理代码的过程中考虑并发问题。新的API通过确保其所有核心类都是不可变的并表示定义明确的值来避免此问题。
域驱动
新的API模型与代表不同的用例类域非常精确Date和Time严密。这与以前的Java库不同,后者在这方面很差。例如,java.util.Date在时间轴上表示一个时刻(一个自UNIX纪元以来的毫秒数的包装器),但如果调用toString(),结果表明它具有时区,从而引起开发人员之间的困惑。
这种对域驱动设计的重视在清晰度和易理解性方面提供了长期利益,但是当从以前的API移植到Java SE 8时,您可能需要考虑应用程序的域日期模型。
按时间顺序分隔
新的API使人们可以使用不同的日历系统来满足世界某些地区(例如日本或泰国)用户的需求,而这些用户不一定遵循ISO-8601。这样做不会给大多数开发人员带来额外负担,他们只需要使用标准的时间顺序即可。
3 LocalDate、LocalTime、LocalDateTime
3.1 相比 Date 的优势
Date 和 SimpleDateFormatter 非线程安全,而 LocalDate 和 LocalTime 和 String 一样,是final类型 - 线程安全且不能被修改。
Date 月份从0开始,一月是0,十二月是11。LocalDate 月份和星期都改成了 enum ,不会再用错。
Date是一个“万能接口”,它包含日期、时间,还有毫秒数。如果你只需要日期或时间那么有一些数据就没啥用。在新的Java 8中,日期和时间被明确划分为 LocalDate 和 LocalTime,LocalDate无法包含时间,LocalTime无法包含日期。当然,LocalDateTime才能同时包含日期和时间。
Date 推算时间(比如往前推几天/ 往后推几天/ 计算某年是否闰年/ 推算某年某月的第一天、最后一天、第一个星期一等等)要结合Calendar要写好多代码,十分恶心!
LocalDate today = LocalDate.now(); //本月的第一天 LocalDate firstday = LocalDate.of(today.getYear(),today.getMonth(),1); //本月的最后一天 LocalDate lastDay =today.with(TemporalAdjusters.lastDayOfMonth());
两个都是本地的,因为它们从观察者的角度表示日期和时间,例如桌子上的日历或墙上的时钟。
还有一种称为复合类LocalDateTime
,这是一个LocalDate和LocalTime的配对。
时区将不同观察者的上下文区分开来,在这里放在一边;不需要上下文时,应使用这些本地类。这些类甚至可以用于表示具有一致时区的分布式系统上的时间。
常用 API
now()
获取在默认的时区系统时钟内的当前日期。该方法将查询默认时区内的系统时钟,以获取当前日期。
使用该方法将防止使用测试用的备用时钟,因为时钟是硬编码的。
方便的加减年月日,而不必亲自计算!