1. java.time API 背景
新日期时间 java.time.LocalDate 出现的背景:
java.util.Date、java.util.Calendar 面临的问题:
1.可变性:像日期、时间这样的类应该是不可变的
2.偏移性:Date 中的年份是从 1900 年开始的;月份是从 0 开始的
3.格式化:格式化只对 Date 有用,而对 Calendar 则不行
4.线程安全:它们都不是线程安全
Java 8 吸收了 Joda-Time 的精华,引入了 java.time API,已经纠正了上述的缺陷。
java.time 中包含了:
- LocalDate:本地日期。yyyy-MM-dd 格式的日期。可以存储生日、纪念日等
- LocalTime:本地时间。代表的是时间,不是日期
- LocalDateTime:本地日期时间
- ZonedDateTime:时区
- Duration:持续时间
大大地简化了对日期、时间的操作
2. java.time 常用 API
java.time API 中常用的 API:
- now():获取当前时间、日期
- of():获取指定的日期、时间
- getXxx():获取值
- withXxx():设置值
- plusXxx():加
- minusXxx():减
now()
public class LocalDateTest {
public static void main(String[] args) {
LocalDate localDate = LocalDate.now();
LocalTime localTime = LocalTime.now();
LocalDateTime localDateTime = LocalDateTime.now();
// 日期:2021-07-19
System.out.println(localDate);
// 时间:21:41:18.064
System.out.println(localTime);
// 日期时间:2021-07-19T21:41:18.064
System.out.println(localDateTime);
}
}
localDate
:表示当前的日期
localTime
:表示当前的时间
localDateTime
:表示当前的日期时间
of()
public static void main(String[] args) {
LocalDateTime dateTime = LocalDateTime.of(2021, 7, 19, 21, 50, 0);
// 2021-07-19T21:50
System.out.println(dateTime);
}
指定一个特定的日期
getXxx()
public static void main(String[] args) {
// 2021-07-19T21:47:41.734
LocalDateTime localDateTime = LocalDateTime.now();
// 19
System.out.println(localDateTime.getDayOfMonth());
// JULY
System.out.println(localDateTime.getMonth());
}
withXxx()
public static void main(String[] args) {
// 2021-07-19T21:47:41.734
LocalDateTime localDateTime = LocalDateTime.now();
// 设置为当月的 25 号
LocalDateTime dayOfMonth = localDateTime.withDayOfMonth(25);
// 2021-07-19T21:50:31.580
System.out.println(localDateTime);
// 2021-07-25T21:50:31.580
System.out.println(dayOfMonth);
}
不知你们有没有发现:localDateTime
与 dayOfMonth
不相等。localDateTime 是当前日期,然后设置日期为当月的 25 号,并返回了 dayOfMonth(新日期哈),这就是日期的不可变性!!与 String 类一样,每次修改,返回的是一个新对象。
plusXxx()
public static void main(String[] args) {
// 2021-07-19T21:47:41.734
LocalDateTime localDateTime = LocalDateTime.now();
LocalDateTime months = localDateTime.plusMonths(5);
// 2021-12-19T22:00:40.859
System.out.println(months);
}
在当前日期上,加了 5 个月
3. java.time.format.DateTimeFormatter
java.time.format.DateTimeFormatter:格式化、解析日期或时间(类似于:SimpleDateFormat)
此类提供了三种格式化方法:
- 预定义的标准格式:ISO_LOCAL_DATE_TIME…
- 本地化相关的格式:
- 自定义格式:ofPattern(“yyyy-MM-dd HH:mm:ss”)
public static void main(String[] args) {
LocalDateTime localDateTime = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// 2021-07-19 22:24:11
System.out.println(formatter.format(localDateTime));
}
4. 常用小案例
- 在 Java 8 中获取今天的日期
public static void main(String[] args) {
LocalDateTime dateTime = LocalDateTime.now();
// 2021-07-19T22:44:42.198
System.out.println(dateTime);
}
- 在 Java 8 中获取年、月、日信息
public static void main(String[] args) {
LocalDateTime dateTime = LocalDateTime.now();
// 2021-07-19T22:44:42.198
System.out.println(dateTime);
int year = dateTime.getYear();
int month = dateTime.getMonthValue();
int day = dateTime.getDayOfMonth();
// 2021-7-19
System.out.println(year + "-" + month + "-" + day);
}
- 在 Java 8 中处理特定日期
public static void main(String[] args) {
LocalDateTime dateTime = LocalDateTime.of(2021, 7, 19, 21, 50, 0);
// 2021-07-19T21:50
System.out.println(dateTime);
}
- 在 Java 8 中判断两个日期是否相等
public static void main(String[] args) {
LocalDate nowDate = LocalDate.now();
LocalDate localDate = LocalDate.of(2021, 6, 18);
// false
System.out.println(nowDate.equals(localDate));
}
- 在 Java 8 中检查像生日这种周期性事件
public static void main(String[] args) {
LocalDate now = LocalDate.now();
LocalDate dateOfBirth = LocalDate.of(2018, 07, 19);
MonthDay birthday = MonthDay.of(dateOfBirth.getMonth(), dateOfBirth.getDayOfMonth());
MonthDay currentMonthDay = MonthDay.from(now);
if (currentMonthDay.equals(birthday)) {
System.out.println("Happy Birthday");
} else {
System.out.println("Sorry, today is not your birthday");
}
}
- 如何计算一周后的日期
LocalDate
日期不包含时间信息,它的plus()
方法用来增加天、周、月,ChronoUnit
类声明了这些时间单位。由于LocalDate
也是不变类型,返回后一定要用变量赋值。minus()
方法用来减去天、周、月等
public static void main(String[] args) {
LocalDate nowDate = LocalDate.now();
LocalDate plusDate = nowDate.plus(1, ChronoUnit.WEEKS);
System.out.println(plusDate);
}
- 如何用 Java 判断日期是早于还是晚于另一个日期
在 Java 8 中,LocalDate 类有两类方法 isBefore() 和 isAfter() 用于比较日期。调用 isBefore() 方法时,如果给定日期小于当前日期则返回 true
public static void main(String[] args) {
LocalDate now = LocalDate.now();
LocalDate tomorrow = LocalDate.of(2021,7,19);
if(tomorrow.isAfter(now)){
System.out.println("Tomorrow comes after today");
}
LocalDate yesterday = now.minus(1, ChronoUnit.DAYS);
if(yesterday.isBefore(now)){
System.out.println("Yesterday is day before today");
}
}
- 如何表示信用卡到期这类固定日期,答案就在 YearMonth
与 MonthDay 检查重复事件的例子相似,YearMonth 是另一个组合类,用于表示信用卡到期日、FD 到期日、期货期权到期日等。还可以用这个类得到 当月共有多少天,YearMonth 实例的 lengthOfMonth() 方法可以返回当月的天数,在判断 2 月有 28 天还是 29 天时非常有用
public static void main(String[] args) {
YearMonth currentYearMonth = YearMonth.now();
System.out.printf("Days in month year %s: %d%n", currentYearMonth, currentYearMonth.lengthOfMonth());
YearMonth creditCardExpiry = YearMonth.of(2018, Month.FEBRUARY);
System.out.printf("Your credit card expires on %s %n", creditCardExpiry)
}
- 计算两个日期之间的天数和月数
有一个常见日期操作是计算两个日期之间的天数、周数或月数。在 Java 8 中可以用 java.time.Period 类来做计算
public static void main(String[] args) {
LocalDate now = LocalDate.now();
LocalDate date = LocalDate.of(2019, Month.MARCH, 20);
Period period = Period.between(now, date);
System.out.println("离下个时间还有" + period.getMonths() + " 个月");
}